module Havox::Merlin

Constants

BASENAME_REGEX
ERROR_REGEX
RULES_BLOCK_REGEX
SEPARATOR_REGEX

Public Class Methods

compile(topology_file, policy_file, opts = {}) click to toggle source
# File lib/havox/modules/merlin.rb, line 65
def self.compile(topology_file, policy_file, opts = {})
  rules = []
  result = run(cmd.compile(topology_file, policy_file))                     # Runs Merlin in the remote VM and retrieves its output.
  result = parse(result)                                                    # Parses the output into raw rules.
  result = Havox::RuleSanitizer.new(result).sanitized_rules                 # Removes unwanted rule snippets.
  result = Havox::RuleExpander.new(result).expanded_rules if opts[:expand]  # Expands each raw rule in the parsed result.
  result.each { |raw_rule| rules << Havox::Rule.new(raw_rule, opts) }       # Creates Rule instances for each raw rule.
  rules
end
compile!(topology_file, policy_file, opts = {}) click to toggle source
# File lib/havox/modules/merlin.rb, line 75
def self.compile!(topology_file, policy_file, opts = {})
  check_options(opts)
  policy_file = Havox::ModifiedPolicy.new(topology_file, policy_file).path if opts[:basic]
  if upload!(topology_file, opts[:dst]) && upload!(policy_file, opts[:dst])
    topology_file = "#{opts[:dst]}#{basename(topology_file)}"
    policy_file = "#{opts[:dst]}#{basename(policy_file)}"
    compile(topology_file, policy_file, opts)
  end
end
run(command) click to toggle source
# File lib/havox/modules/merlin.rb, line 53
def self.run(command)
  output = nil
  ssh_connection { |ssh| output = ssh.exec!(command) }
  output
end
upload!(file, dst = nil) click to toggle source
# File lib/havox/modules/merlin.rb, line 59
def self.upload!(file, dst = nil)
  dst ||= "#{config.merlin_path}/examples/"
  ssh_connection { |ssh| ssh.scp.upload!(file, dst) }
  true
end

Private Class Methods

basename(path) click to toggle source
# File lib/havox/modules/merlin.rb, line 39
def basename(path)
  path.match(BASENAME_REGEX)[:name]
end
check_for_errors(result) click to toggle source
# File lib/havox/modules/merlin.rb, line 34
def check_for_errors(result)
  error_msg = result.scan(ERROR_REGEX).flatten.first
  raise Havox::Merlin::ParsingError, error_msg unless error_msg.nil?
end
check_options(opts) click to toggle source
# File lib/havox/modules/merlin.rb, line 43
def check_options(opts)
  opts[:dst]    ||= "#{config.merlin_path}/examples/"                     # Sets the upload path in Merlin VM.
  opts[:force]  ||= false                                                 # Forces Havox to ignore field conflicts.
  opts[:basic]  ||= false                                                 # Instructs to append basic policies.
  opts[:expand] ||= false                                                 # Expands raw rules from VLAN-based to full predicates.
  opts[:output] ||= false                                                 # Switches Enqueue action for Output action.
  opts[:syntax] ||= :trema                                                # Sets the output syntax for generated rules.
end
cmd() click to toggle source
# File lib/havox/modules/merlin.rb, line 15
def cmd
  Havox::Command
end
config() click to toggle source
# File lib/havox/modules/merlin.rb, line 11
def config
  Havox.configuration
end
parse(result) click to toggle source
# File lib/havox/modules/merlin.rb, line 25
def parse(result)
  result = result.tr("\n", '').tr("\t", ' ')                              # Removes line break and tab characters.
  check_for_errors(result)                                                # Raises an error if Merlin has errored.
  result = result.scan(RULES_BLOCK_REGEX).flatten.first                   # Matches OpenFlow rules block.
  return [] if result.nil?                                                # Returns an empty array if no rules were created.
  result = result.split(SEPARATOR_REGEX)                                  # Splits the block into separated rules.
  result.map(&:to_s)                                                      # Converts NetSSH special string to string.
end
ssh_connection() { |ssh| ... } click to toggle source
# File lib/havox/modules/merlin.rb, line 19
def ssh_connection
  Net::SSH.start(config.merlin_host, config.merlin_user, password: config.merlin_password) do |ssh|
    yield(ssh)
  end
end