Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit.

  • Loading branch information...
commit 7863a8e00ba945ba598a7c6f9404ffd74df2bda7 0 parents
sathlan authored
1  .gitignore
@@ -0,0 +1 @@
+.vagrant
199 README.org
@@ -0,0 +1,199 @@
+* Cluster Ahealix
+** Description
+The goal is to mimic a eNovance environment in order to improve the
+continuous integration of specific development and puppet recipe.
+
+The setup is based on [[http://www.virtualbox.org/][virtualbox]] driven by [[https://github.com/mitchellh/vagrant][vagrant]] and a specific
+development ([[https://github.com/sathlan/machine-nics][machine-nics]]) which setup the host virtual networking
+environment.
+
+The environment is composed of:
+ - a cluster ahaelix;
+ - a cluster of firewall;
+ - two machines providing mx and dns services
+ - a monitoring machine
+ - a puppet master
+
+
+ | Type | machine | ip | service | done |
+ |------------+-----------+-----------------+--------------+------|
+ | ahealix | b1 | 172.143.115.36 | openvz | |
+ | | | | drbd | |
+ | | b2 | 172.143.115.37 | openvz | |
+ | | | | drbd | |
+ |------------+-----------+-----------------+--------------+------|
+ | fw | fw1 | | gateway | |
+ | | | | iptables | |
+ | | | | heartbeat1.3 | |
+ | | | | pacemaker | |
+ | | fw2 | | gateway | |
+ | | | | iptables | |
+ | | | | heartbeat1.3 | |
+ | | | | pacemaker | |
+ |------------+-----------+-----------------+--------------+------|
+ | monitoring | mon_1 | | centreon | |
+ | | | | nagios | |
+ | | | | graph | |
+ | | mon_2 | | centreon | |
+ | | | | nagios | |
+ | | | | graph | |
+ |------------+-----------+-----------------+--------------+------|
+ | mail/dns | dns_mx_1 | | dns | |
+ | | | | mx | |
+ | | dns_mx_2 | | dns | |
+ | | | | mx | |
+ |------------+-----------+-----------------+--------------+------|
+ | backup | backup_1 | | backuppc | |
+ | | backup_2 | | backuppc | |
+ |------------+-----------+-----------------+--------------+------|
+ | outsider | outside_1 | | no service | |
+
+Eleven machines that create a realist production environment. Network
+bond and vlan are working inside each vm to mimic even more the
+production.
+
+Not all machines need to be started for all need. Only one firewall
+is required for the machine to get network connectivity. After if you
+test a puppet/backup recipe, you need only:
+ - fw1;
+ - backup_1;
+ - backup_2;
+ - puppet;
+
+
+Each machine consume roughly 475M of memory, so make you math.
+
+** Setup
+*** VirtualBox
+A version above 4.0.0 is required.
+
+For mainstream Linux use the packages available [[https://www.virtualbox.org/wiki/Linux_Downloads][here]].
+
+For FreeBSD you can use [[http://redports.org/browser/virtualbox?rev=1481&order=name][redports virtualbox]].
+
+*** Ruby
+**** Requirements
+You need :
+ 1. a version of the [[http://www.ruby-lang.org/en/][ruby]] interpreter above 1.9
+ 2. a version of the [[http://rubygems.org/pages/download][RubyGem]] above 1.8
+ 3. a version of [[http://gembundler.com/][bundler]] above 1.0
+
+It is recommended to use native ruby tool for installation of the
+gem.
+
+Here's a example for Debian.
+
+**** Debian example
+TODO: test http://deb.bearstech.com/squeeze/ruby-1.9.3/
+
+#+begin_src sh
+ wget http://download.virtualbox.org/virtualbox/4.1.8/virtualbox-4.1_4.1.8-75467~Debian~squeeze_amd64.deb
+ dpkg -i virtualbox-4.1_4.1.8-75467~Debian~squeeze_amd64.deb
+
+ sudo apt-get install ruby1.9.1
+ sudo apt-get install ri1.9
+
+ # required to get gem >= 1.8 the 1.3 does not work.
+ sudo env REALLY_GEM_UPDATE_SYSTEM=1 gem update --system
+
+ sudo update-alternatives --install /usr/bin/ruby ruby /usr/bin/ruby1.9.1 500 \
+ --slave /usr/share/man/man1/ruby.1.gz ruby.1.gz /usr/share/man/man1/ruby1.9.1.1.gz \
+ --slave /usr/share/man/man1/ri.1.gz ri.1.gz /usr/share/man/man1/ri1.9.1.1.gz \
+ --slave /usr/share/man/man1/rdoc.1.gz rdoc.1.gz /usr/share/man/man1/rdoc1.9.1.1.gz \
+ --slave /usr/share/man/man1/irb.1.gz irb.1.gz /usr/share/man/man1/irb1.9.1.1.gz \
+ --slave /usr/bin/ri ri /usr/bin/ri1.9.1 \
+ --slave /usr/bin/irb irb /usr/bin/irb1.9.1 \
+ --slave /usr/bin/rdoc rdoc /usr/bin/rdoc1.9.1
+
+ gem install bundler -v '~>1.0'
+
+#+end_src
+
+*** Vagrant
+You need a specific version.
+
+#+srcname: install_vagrant_1
+#+begin_src sh
+ cd /usr/src
+ git clone --ref vendor/sathlan git://github.com/sathlan/vagrant.git
+ cd vagrant
+ bundle install
+ rake build
+ sudo gem install pkg/vagrant*.gem
+#+end_src
+
+*** Machine-nics
+
+#+begin_src sh
+ cd /usr/src
+ git clone git://github.com/sathlan/machine-nics.git
+ cd machine-nics
+ bundle install
+ rake build
+ sudo gem install pkg/machine-nics*.gem
+
+#+end_src
+
+*** cluster_healix
+First we need the vagrant configuration and the associated rakefile (=
+makefile in ruby):
+#+begin_src sh
+ cd ~/vps
+ mkdir ~/cluster_ahealix
+ git clone git://github.com/sathlan/cluster.git
+#+end_src
+
+Then we need some network on the host.
+
+#+begin_src sh
+ # list available network configuration
+ rake -T
+ # make one.
+ rake Add_eNovance_small
+ rake Add_ip
+
+#+end_src
+
+Here you'll have to make sure that everything which goes out is
+SNATed.
+
+Finally we start the virtual machines. The first time is very long as
+it has to download the host (3.2G base PXE ahealix type server) and
+create an vm out of it.
+
+#+begin_src sh
+ vagrant up fw1
+ vagrant up b1
+ vagrant up puppet
+
+#+end_src
+
+Done, now you can enjoy the environment.
+
+#+begin_src sh
+ vagrant help
+ vagrant ssh b1
+#+end_src
+
+*** Snapshots
+We can have virtualbox snapshot at the command line for free with
+[[https://github.com/t9md/vagrant-snap][vagrant-snap]].
+
+#+begin_src sh
+ sudo gem install vagrant-snap
+#+end_src
+
+All vm comes with a initial snapshot so you can always get back to
+this point if everything goes bad.
+
+
+** Basic Puppet integrated.
+Vagrant has puppet provisioning integrated. Here, it's use to setup
+network connectivity. Another use can be to quickly test an puppet
+module. Coupled with snapshot, it enable the user to get test without
+hurting an new module.
+
+The basic setup is found in for each machine in the
+=manifests/<machine>.pp= file.
+
+
91 Rakefile
@@ -0,0 +1,91 @@
+require 'machine-nics'
+require 'yaml'
+NET_CONFIGUATION = 'network.yml'
+
+BRDG = YAML.load_file(NET_CONFIGUATION)
+
+BRDG.each_key do |host|
+ desc "Make nics for #{host}"
+ tree = MachineNics::Tree.create_from_hash({host => BRDG[host]})
+ actions = MachineNics::Actions.new(RbConfig::CONFIG['host_os'])
+ task "nics_#{host}" do |t|
+ tree.traverse_df(tree.root, 0) do |nic, level|
+ next if level <= 0
+ actions.display('create', nic, level, tree.children[nic] )
+ actions.create!(nic, tree.children[nic])
+ end
+ end
+ desc "Destroy nics for #{host}"
+ task "rem_nics_for_#{host}" do |t|
+ tree.traverse_df(tree.root, 0) do |nic, level|
+ next if level <= 0
+ actions.display('destroy', nic, level, tree.children[nic] )
+ actions.destroy!(nic, tree.children[nic])
+ end
+ end
+end
+
+desc "Destroy everything."
+task clobber: [:Rem_ip] do |t|
+ BRDG.each_key do |host|
+ tree = MachineNics::Tree.create_from_hash({host => BRDG[host]})
+ actions = MachineNics::Actions.new(RbConfig::CONFIG['host_os'])
+ tree.traverse_df(tree.root, 0) do |nic, level|
+ next if level <= 0
+ actions.display('destroy', nic, level, tree.children[nic] )
+ actions.destroy!(nic, tree.children[nic])
+ end
+ end
+end
+
+desc "Add cluster ehaelix"
+task Add_blastors: [:nics_b1, :nics_b2]
+
+desc "Remove cluster ehaelix"
+task Rem_blastors: [:clobber_nics_for_b1, :clobber_nics_for_b2]
+
+desc "Add cluster FW"
+task Add_fws: [:nics_fw1, :nics_fw2]
+
+desc "Add ips routers"
+task :Add_ip do |t|
+ if `ifconfig vlan101 2>/dev/null`.split.empty?
+ `sudo ifconfig vlan10100 172.143.112.67/26`
+ else
+ `sudo ifconfig vlan101 172.143.112.67/26`
+ end
+ `sudo sysctl net.inet.ip.forwarding=1`
+ `sudo sysctl net.link.bridge.ipfw=0`
+ `sudo sysctl net.link.bridge.pfil_local_phys=0`
+ `sudo sysctl net.link.bridge.pfil_member=0`
+ `sudo sysctl net.link.bridge.pfil_bridge=0`
+ `sudo sysctl net.link.bridge.ipfw_arp=0`
+ `sudo sysctl net.link.bridge.pfil_onlyip=0`
+ `sudo /etc/rc.d/pf restart`
+ `sudo route add 172.143.115.35/27 172.143.112.71` # router cfg
+ `sudo route add 172.143.114.192/27 172.143.112.71` # router cfg
+end
+
+desc "Remove ips routers"
+task :Rem_ip do |t|
+ `sudo route del 172.143.115.35/27 172.143.112.71` # router cfg
+ `sudo route del 172.143.114.192/27 172.143.112.71` # router cfg
+ `sudo ifconfig vlan10100 -alias 172.143.112.67 2>/dev/null`
+ `sudo ifconfig vlan101 -alias 172.143.112.67 2>/dev/null`
+end
+
+desc "Remove cluster FW"
+task Rem_fws: [:rem_nics_for_fw1, :rem_nics_for_fw2]
+
+desc "Add eNovance"
+task Add_eNovance: [:Add_blastors, :Add_fws, :Add_ip]
+
+desc "Add eNovance Small: fw1, b1, puppet"
+task Add_eNovance_small: [:nics_b1, :nics_fw1, :nics_puppet, :Add_ip ]
+
+desc "Remove eNovance Small: fw1, b1, puppet"
+task Rem_eNovance_small: [:rem_nics_for_b1, :rem_nics_for_fw1, :rem_nics_for_puppet, :Rem_ip ]
+
+desc "Remove eNovance"
+task Rem_eNovance: [:Rem_ip, :Rem_fws, :Rem_blastors ]
+
201 Vagrantfile
@@ -0,0 +1,201 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant::Config.run do |config|
+ # All Vagrant configuration is done here. The most common configuration
+ # options are documented and commented below. For a complete reference,
+ # please see the online documentation at vagrantup.com.
+
+ config.vm.define :b1 do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "b1"
+ config.vm.network :bridged, { nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap101', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap200', nic_type: 'virtio', auto_config: false }
+ config.vm.provision :puppet do |puppet|
+ puppet.manifest_file = "b1.pp"
+ end
+ end
+
+ config.vm.define :b2 do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "b2"
+ config.vm.network :bridged, { bridge: 'tap102', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap103', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap201', nic_type: 'virtio', auto_config: false }
+ config.vm.provision :puppet do |puppet|
+ puppet.manifest_file = "b2.pp"
+ end
+ end
+
+ config.vm.define :fw1 do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "fw1"
+ config.vm.network :bridged, { bridge: 'tap104', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap105', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap106', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap107', nic_type: 'virtio', auto_config: false }
+ end
+
+ config.vm.define :fw2 do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "fw2"
+ config.vm.network :bridged, { bridge: 'tap109', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap110', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap111', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap112', nic_type: 'virtio', auto_config: false }
+ end
+
+ config.vm.define :mon_1 do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "mon_1"
+ config.vm.network :bridged, { bridge: 'tap113', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap114', nic_type: 'virtio', auto_config: false }
+ end
+
+ config.vm.define :mon_2 do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "mon_2"
+ config.vm.network :bridged, { bridge: 'tap115', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap116', nic_type: 'virtio', auto_config: false }
+ end
+
+ config.vm.define :dns_mx_1 do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "dns_mx_1"
+ config.vm.network :bridged, { bridge: 'tap117', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap118', nic_type: 'virtio', auto_config: false }
+ end
+
+ config.vm.define :dns_mx_2 do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "dns_mx_2"
+ config.vm.network :bridged, { bridge: 'tap119', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap120', nic_type: 'virtio', auto_config: false }
+ end
+
+ config.vm.define :backup_1 do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "backup_1"
+ config.vm.network :bridged, { bridge: 'tap121', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap122', nic_type: 'virtio', auto_config: false }
+ end
+
+ config.vm.define :backup_2 do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "backup_2"
+ config.vm.network :bridged, { bridge: 'tap123', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap124', nic_type: 'virtio', auto_config: false }
+ end
+
+ config.vm.define :puppet do |config|
+ config.vm.box = "ehaelix-0.0.2"
+ config.vm.box_url = "http://dev-2.lan.enovance.com/ehaelix-0.0.2.box"
+ config.vm.host_name = "puppet"
+ config.vm.network :bridged, { bridge: 'tap125', nic_type: 'virtio', auto_config: false }
+ config.vm.network :bridged, { bridge: 'tap126', nic_type: 'virtio', auto_config: false }
+ end
+
+ # Every Vagrant virtual environment requires a box to build off of.
+
+ # The url from where the 'config.vm.box' box will be fetched if it
+ # doesn't already exist on the user's system.
+ # config.vm.box_url = "http://domain.com/path/to/above.box"
+
+ # Boot with a GUI so you can see the screen. (Default is headless)
+ # config.vm.boot_mode = :gui
+
+ # Assign this VM to a host-only network IP, allowing you to access it
+ # via the IP. Host-only networks can talk to the host machine as well as
+ # any other machines on the same network, but cannot be accessed (through this
+ # network interface) by any external networks.
+ # config.vm.network :hostonly, "33.33.33.10"
+
+ # Assign this VM to a bridged network, allowing you to connect directly to a
+ # network using the host's network device. This makes the VM appear as another
+ # physical device on your network.
+# config.vm.network :bridged, {bridge: 'tap95'}
+# config.vm.network :bridged, {bridge: 'tap96'}
+# config.vm.network :bridged, {bridge: 'tap97'}
+# config.vm.network :bridged
+# config.vm.network :bridged
+# config.vm.network :bridged
+# config.vm.network :bridged
+
+ # Forward a port from the guest to the host, which allows for outside
+ # computers to access the VM, whereas host only networking does not.
+ # config.vm.forward_port "http", 80, 8080
+
+ # Share an additional folder to the guest VM. The first argument is
+ # an identifier, the second is the path on the guest to mount the
+ # folder, and the third is the path on the host to the actual folder.
+ # config.vm.share_folder "v-data", "/vagrant_data", "../data"
+
+ # Enable provisioning with Puppet stand alone. Puppet manifests
+ # are contained in a directory path relative to this Vagrantfile.
+ # You will need to create the manifests directory and a manifest in
+ # the file luci32_base.pp in the manifests_path directory.
+ #
+ # An example Puppet manifest to provision the message of the day:
+ #
+ # # group { "puppet":
+ # # ensure => "present",
+ # # }
+ # #
+ # # File { owner => 0, group => 0, mode => 0644 }
+ # #
+ # # file { '/etc/motd':
+ # # content => "Welcome to your Vagrant-built virtual machine!
+ # # Managed by Puppet.\n"
+ # # }
+ #
+ # config.vm.provision :puppet do |puppet|
+ # puppet.manifests_path = "manifests"
+ # puppet.manifest_file = "luci32_base.pp"
+ # end
+
+ # Enable provisioning with chef solo, specifying a cookbooks path (relative
+ # to this Vagrantfile), and adding some recipes and/or roles.
+ #
+ # config.vm.provision :chef_solo do |chef|
+ # chef.cookbooks_path = "cookbooks"
+ # chef.add_recipe "mysql"
+ # chef.add_role "web"
+ #
+ # # You may also specify custom JSON attributes:
+ # chef.json = { :mysql_password => "foo" }
+ # end
+
+ # Enable provisioning with chef server, specifying the chef server URL,
+ # and the path to the validation key (relative to this Vagrantfile).
+ #
+ # The Opscode Platform uses HTTPS. Substitute your organization for
+ # ORGNAME in the URL and validation key.
+ #
+ # If you have your own Chef Server, use the appropriate URL, which may be
+ # HTTP instead of HTTPS depending on your configuration. Also change the
+ # validation key to validation.pem.
+ #
+ # config.vm.provision :chef_client do |chef|
+ # chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
+ # chef.validation_key_path = "ORGNAME-validator.pem"
+ # end
+ #
+ # If you're using the Opscode platform, your validator client is
+ # ORGNAME-validator, replacing ORGNAME with your organization name.
+ #
+ # IF you have your own Chef Server, the default validation client name is
+ # chef-validator, unless you changed the configuration.
+ #
+ # chef.validation_client_name = "ORGNAME-validator"
+end
197 lib/MachineNics.rb
@@ -0,0 +1,197 @@
+class MachineNics
+ attr_reader :root
+ attr_reader :parent_of
+ attr_reader :children
+ def initialize(machine_name)
+ @root = machine_name
+ # here, a nic is a hash. This could be a class.
+ @children = Hash.new([])
+ @parent_of = Hash.new([])
+ end
+
+ def add(root,nics)
+ @children[root] = nics
+ nics.each {|nic| parent_of[nic] = root}
+ end
+
+ # parse a hash of hash of any depth with the machine name as unique
+ # root. Some syntaxic sugar is present for leaf. Check the
+ # sanitize function.
+ #
+ # Ex: { bridge0: {tap101: nil, tap102: nil}} can be written:
+ # { bridge0: [ tap101, tap102 ]}
+ # this works too: {brigde0: [{ lagg0: [tap200, tap201] }, tap100]
+ # and is equivaleunt to {bridge0: {lagg0: {tap200: nil, tap201: nil}, tap100: nil}
+
+ def self.create_from_hash(description)
+ machine = MachineNics.new(description.first[0])
+ current_roots = []
+
+ sanitized_values = sanitize(description[machine.root])
+ machine.add(machine.root, sanitized_values.keys)
+ current_roots = [sanitized_values]
+
+ until current_roots.empty?
+ current_roots.each do |current_root|
+ current_roots = []
+ current_root.each_key do |root|
+ unless current_root[root].nil?
+ sanitized_current_root = sanitize(current_root[root])
+ machine.add(root, sanitized_current_root.keys)
+ current_roots.push(sanitized_current_root)
+ end
+ end
+ end
+ end
+
+ machine
+ end
+
+ def length(root)
+ max = 0
+ traverse(root,0) {|n, l| max = l if l > max }
+ max
+ end
+
+ def traverse(node,level,&block)
+ yield node, level if block_given?
+ @children[node].each { |child| traverse(child, level+1, &block) }
+ end
+
+ def traverse_df(node,level,&block)
+ # depth first and deepest first.
+ @children[node].sort_by {|a| length(a) }.reverse.each { |child| traverse_df(child, level+1, &block) }
+ yield node, level if block_given?
+ end
+
+ def display
+ puts @root.to_s + " " + "=" * 10
+ traverse(@root,0) {|n, l| puts " "*l + "node: #{n}"}
+ self
+ end
+ def display_df
+ puts @root.to_s + " df*" + "=" * 10
+ traverse_df(@root,0) {|n, l| puts " "*l + "*node: #{n}"}
+ self
+ end
+ def up
+ traverse_df(@root,0) do |nic, level|
+ `sudo ifconfig #{remove_mtu_from_name(nic)} up 2>/dev/null`
+ end
+ end
+ def create
+ traverse_df(@root,0) do |nic, level|
+ return unless level > 0
+ cmd = dispatch('create', nic)
+ prefix = " "*level
+ puts "#{prefix}* Creating #{nic.upcase} "
+ cmd.flatten.each {|c| puts prefix + " #{c}"}
+ out = cmd.flatten.each {|c| `#{c} 2>/dev/null`}
+ end
+ end
+ def dispatch(cmd, nic)
+ function = nic.to_s.sub(/^(?:\/dev\/)?([^0-9_]+)[\d_]+/,'\1')
+ return send(function + '_' + cmd, nic)
+ end
+ def tap_empty?(name)
+ true
+ end
+ def lagg_empty?(name)
+ composite_empty?(name, 'laggport')
+ end
+ def bridge_empty?(name)
+ composite_empty?(name, 'member')
+ end
+ def vlan_empty?(name)
+ true
+ end
+ def composite_empty?(name, port_name)
+ cmd = %Q{ifconfig #{remove_mtu_from_name(name)} | awk '/#{port_name}:/{print $2}'}
+ `#{cmd}`.split.empty?
+ end
+
+ def destroy
+ traverse_df(@root,0) do |name, level|
+ next if level == 0
+ next unless dispatch('empty?', name)
+ cmd = "sudo ifconfig #{remove_mtu_from_name(name)} destroy 2>/dev/null"
+ puts " "*level + "* #{cmd}"
+ out = `#{cmd}`
+ end
+ end
+
+ def mtu_by_name(name)
+ name.to_s.sub(/.*_(.*)/, '\1')
+ end
+ def remove_mtu_from_name(name)
+ name.to_s.sub(/(.*)_.*/, '\1')
+ end
+ def tap_create(name)
+ mtu = mtu_by_name(name)
+ name_without_mtu = remove_mtu_from_name(name)
+ cmd = ["sudo ifconfig #{name_without_mtu} create mtu #{mtu}"]
+ end
+
+ def lagg_create(name)
+ cmd = "sudo ifconfig #{name} create laggproto loadbalance "
+ children[name].each do |nic|
+ cmd += " laggport #{remove_mtu_from_name(nic)} "
+ end
+ [cmd]
+ end
+ def bridge_create(name)
+ cmd_before = "sudo ifconfig #{name} create 2>/dev/null; "
+ cmd_pre = "sudo ifconfig #{name} "
+ cmds = []
+ children[name].each do |nic|
+ cmds << "#{cmd_pre} addm #{remove_mtu_from_name(nic)} "
+ end
+ cmd = [cmd_before, cmds]
+ end
+ def get_vid_from_name(name)
+ # several vlan with the same vid but not the same name:
+ # vlan10100 vlan10101, ...
+ vid = ""
+ if name.to_s.length > 8
+ l = name.to_s.length - 2 - 4
+ vid = name.to_s[4,l]
+ else
+ vid = name.to_s.gsub(/\D+/,'')
+ end
+ vid
+ end
+ def vlan_create(name)
+ vid = get_vid_from_name(name)
+ cmd = ["sudo ifconfig #{name} create vlan #{vid} vlandev #{remove_mtu_from_name(children[name].first)}"]
+ end
+
+ private
+ # syntaxic sugar. We expect an hash of a hash, but for terminal
+ # node, we can take array or symbol. Transforme the structure here
+ # to make it fit our requirements.
+ def self.sanitize(hash_or_array)
+ hash = {}
+ if hash_or_array.class.name == "Array"
+ hash_or_array.each do |element|
+ # each eleement can be a terminal nic or a composed nic.
+ if element.class.name == "Symbol"
+ hash[element] = nil
+ else
+ element.each_key do |nic|
+ hash[nic] = element[nic]
+ end
+ end
+ end
+ elsif hash_or_array.class.name == "Symbol"
+ hash = {}
+ hash[hash_or_array] = nil
+ else
+ hash = hash_or_array
+ end
+ hash
+ end
+
+end
+
+# -> goal: { bridge0: { vlan101: { lagg0: [:tap200, :tap201] }}}
+
30 manifests/b1.pp
@@ -0,0 +1,30 @@
+augeas { "bond_interface" :
+ context => "/files/etc/network/interfaces",
+ changes => [
+ "set auto[child::1 = 'bond0']/1 bond0",
+ "set iface[. = 'bond0'] bond0",
+ "set iface[. = 'bond0']/family inet",
+ "set iface[. = 'bond0']/method manual",
+ "set iface[. = 'bond0']/bond-slaves 'eth1 eth2'",
+ "set iface[. = 'bond0']/bound-mode balance-xor",
+ "set iface[. = 'bond0']/bond-miimon 100",
+ "set iface[. = 'bond0']/bond-downdelay 200",
+ "set iface[. = 'bond0']/bond-updelay 200",
+ "set iface[. = 'bond0']/bond-xmit_hash_policy layer3+4",
+ "set auto[child::1 = 'vzbr3100']/1 vzbr3100",
+ "set iface[. = 'vzbr3100'] vzbr3100",
+ "set iface[. = 'vzbr3100']/family inet",
+ "set iface[. = 'vzbr3100']/method static",
+ "set iface[. = 'vzbr3100']/bridge_ports bond0.3100",
+ "set iface[. = 'vzbr3100']/bridge_maxwait 0",
+ "set iface[. = 'vzbr3100']/bridge_fd 0",
+ "set iface[. = 'vzbr3100']/address 172.143.115.36",
+ "set iface[. = 'vzbr3100']/netmask 255.255.255.224",
+ "set auto[child::1 = 'eth3']/1 eth3",
+ "set iface[. = 'eth3'] eth3",
+ "set iface[. = 'eth3']/family inet",
+ "set iface[. = 'eth3']/method static",
+ "set iface[. = 'eth3']/address 172.16.0.201",
+ "set iface[. = 'eth3']/netmask 255.255.255.0",
+ ],
+}
30 manifests/b2.pp
@@ -0,0 +1,30 @@
+augeas { "bond_interface" :
+ context => "/files/etc/network/interfaces",
+ changes => [
+ "set auto[child::1 = 'bond0']/1 bond0",
+ "set iface[. = 'bond0'] bond0",
+ "set iface[. = 'bond0']/family inet",
+ "set iface[. = 'bond0']/method manual",
+ "set iface[. = 'bond0']/bond-slaves 'eth3 eth2'",
+ "set iface[. = 'bond0']/bound-mode balance-xor",
+ "set iface[. = 'bond0']/bond-miimon 100",
+ "set iface[. = 'bond0']/bond-downdelay 200",
+ "set iface[. = 'bond0']/bond-updelay 200",
+ "set iface[. = 'bond0']/bond-xmit_hash_policy layer3+4",
+ "set auto[child::1 = 'vzbr3100']/1 vzbr3100",
+ "set iface[. = 'vzbr3100'] vzbr3100",
+ "set iface[. = 'vzbr3100']/family inet",
+ "set iface[. = 'vzbr3100']/method static",
+ "set iface[. = 'vzbr3100']/bridge_ports bond0.3100",
+ "set iface[. = 'vzbr3100']/bridge_maxwait 0",
+ "set iface[. = 'vzbr3100']/bridge_fd 0",
+ "set iface[. = 'vzbr3100']/address 172.143.115.37",
+ "set iface[. = 'vzbr3100']/netmask 255.255.255.224",
+ "set auto[child::1 = 'eth4']/1 eth4",
+ "set iface[. = 'eth4'] eth4",
+ "set iface[. = 'eth4']/family inet",
+ "set iface[. = 'eth4']/method static",
+ "set iface[. = 'eth4']/address 172.16.0.202",
+ "set iface[. = 'eth4']/netmask 255.255.255.0",
+ ],
+}
66 network.yml
@@ -0,0 +1,66 @@
+---
+:b1:
+ :bridge0:
+ :lagg7:
+ - :tap100_1496
+ - :tap101_1496
+ :bridge1: :tap200
+:b2:
+ :bridge0:
+ :lagg1:
+ - :tap102_1496
+ - :tap103_1496
+ :bridge1: :tap201
+:fw1:
+ :bridge0:
+ :vlan101:
+ :lagg2:
+ - :tap104
+ - :tap105
+ :lagg3:
+ - :tap106_1496
+ - :tap107_1496
+:fw2:
+ :bridge0:
+ :vlan10100:
+ :lagg4:
+ - :tap108
+ - :tap109
+ :lagg5:
+ - :tap110_1496
+ - :tap111_1496
+:puppet:
+ :bridge0:
+ :lagg12:
+ - :tap122_1496
+ - :tap123_1496
+:mon_1:
+ :bridge0:
+ :lagg7:
+ - :tap113_1496
+ - :tap114_1496
+:mon_2:
+ :bridge0:
+ :lagg8:
+ - :tap115_1496
+ - :tap116_1496
+:dns_mx_1:
+ :bridge0:
+ :lagg9:
+ - :tap117_1496
+ - :tap118_1496
+:dns_mx_2:
+ :bridge0:
+ :lagg10:
+ - :tap119_1496
+ - :tap120_1496
+:backup_1:
+ :bridge0:
+ :lagg11:
+ - :tap121_1496
+ - :tap122_1496
+:backup_2:
+ :bridge0:
+ :lagg12:
+ - :tap123_1496
+ - :tap124_1496
37 test-nic.rb
@@ -0,0 +1,37 @@
+require './lib/MachineNics'
+require 'pp'
+n0 = MachineNics.create_from_hash({ fw0: {bridge0: {tap104: nil, tap105: nil}, tap200: nil}}).display_df
+n0 = MachineNics.create_from_hash({ fw0: {bridge0: {tap104: nil, tap105: nil}, tap200: nil}}).display
+n0.create
+n0.destroy
+n1 = MachineNics.create_from_hash({ fw1: {bridge0: [:tap104, :tap105], tap200: nil}}).display
+n1.create
+n1.destroy
+
+n1 = MachineNics.create_from_hash({ fw2: {tap201: nil, tap202: nil, bridge0: {lagg2: {tap104: nil, tap105: nil}, lagg3: {tap106: nil, tap107: nil}}}}).display
+n2 = MachineNics.create_from_hash({ fw3: [:tap201, :tap202, bridge0: {lagg2: {tap104: nil, tap105: nil}, lagg3: {tap106: nil, tap107: nil}}]}).display
+n3 = MachineNics.create_from_hash({ fw4: [:tap201, :tap202, bridge0: {lagg2: [:tap104, :tap105], lagg3: {tap106: nil, tap107: nil}}]}).display
+n4 = MachineNics.create_from_hash({ fw5: [:tap201, :tap202, bridge0: {lagg2: [:tap104, :tap105], lagg3: [:tap106, :tap107]}]}).display
+n4.create
+n4.destroy
+
+n5 = MachineNics.create_from_hash({ fw6: [:tap201, :tap202, bridge0: [{lagg2: [:tap104, :tap105, {bridge1: [:tap201, :tap202]}], lagg3: [:tap106, :tap107]}, :tap200]]}).display
+n5 = MachineNics.create_from_hash({ fw6: [:tap201, :tap202, bridge0: [{lagg2: [:tap104, :tap105, {bridge1: [:tap201, :tap202]}], lagg3: [:tap106, :tap107]}, :tap200]]}).display_df
+puts "length fw6: #{n5.length(:fw6)}, tap201 #{n5.length(:tap201)}, bridge0: #{n5.length(:bridge0)}, lagg2: #{n5.length(:lagg2)}, lagg3: #{n5.length(:lagg3)}"
+puts "sorted #{n5.children[:fw6].sort {|a,b| a.length <=> b.length }.reverse}"
+pp n5
+n5.create
+n5.destroy
+
+##
+n6 = MachineNics.create_from_hash({ fw7: [:tap201, :tap202_1496]}).display
+puts n6.parent_of[:tap201]
+p n6
+n7 = MachineNics.create_from_hash({ fw7: {bridge0: [:tap201, :tap202, {lagg0: [:tap101, :tap102]}], vlan101: :tap1}}).display
+n7.create
+n8 = MachineNics.create_from_hash({ fw7: {bridge0: [:tap201_1496, :tap202_1496, {lagg0: [:tap101_1496, :tap102_1496], vlan10100: :tap2}], vlan101: :tap1, lagg1: [:tap150_1496, :tap151_1496], bridge1: { lagg2: [:tap170, :tap171], tap180: nil}}}).display
+n8.create
+puts `ifconfig`
+pp n8
+
+n8.destroy
Please sign in to comment.
Something went wrong with that request. Please try again.