From 112052c8e21fd1b8b862824e96bce17411c3ce19 Mon Sep 17 00:00:00 2001 From: goberle Date: Wed, 10 Jun 2015 10:20:14 +0200 Subject: [PATCH 1/2] Feature #3666: Clean VXLAN devices when no VM is left in the hypervisor --- src/vnm_mad/remotes/802.1Q/clean | 37 +++++- src/vnm_mad/remotes/802.1Q/vlan_tag_driver.rb | 14 +-- src/vnm_mad/remotes/lib/vlan.rb | 106 +++++++++++------- src/vnm_mad/remotes/vxlan/clean | 37 +++++- src/vnm_mad/remotes/vxlan/vxlan_driver.rb | 18 +-- 5 files changed, 151 insertions(+), 61 deletions(-) mode change 120000 => 100755 src/vnm_mad/remotes/802.1Q/clean mode change 120000 => 100755 src/vnm_mad/remotes/vxlan/clean diff --git a/src/vnm_mad/remotes/802.1Q/clean b/src/vnm_mad/remotes/802.1Q/clean deleted file mode 120000 index 940540d063f..00000000000 --- a/src/vnm_mad/remotes/802.1Q/clean +++ /dev/null @@ -1 +0,0 @@ -../fw/clean \ No newline at end of file diff --git a/src/vnm_mad/remotes/802.1Q/clean b/src/vnm_mad/remotes/802.1Q/clean new file mode 100755 index 00000000000..667e4528856 --- /dev/null +++ b/src/vnm_mad/remotes/802.1Q/clean @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +$: << File.dirname(__FILE__) +$: << File.join(File.dirname(__FILE__), "..") + +require 'vnmmad' +require 'vlan_tag_driver' + +template64 = ARGV[0] + +begin + hm = VLANTagDriver.from_base64(template64) + hm.deactivate + filter_driver = VNMMAD::VNMDriver.filter_driver(template64) + filter_driver.deactivate +rescue Exception => e + OpenNebula.log_error(e.message) + OpenNebula.log_error(e.backtrace) + exit 1 +end diff --git a/src/vnm_mad/remotes/802.1Q/vlan_tag_driver.rb b/src/vnm_mad/remotes/802.1Q/vlan_tag_driver.rb index edc8365f2ee..b5c74c2d573 100644 --- a/src/vnm_mad/remotes/802.1Q/vlan_tag_driver.rb +++ b/src/vnm_mad/remotes/802.1Q/vlan_tag_driver.rb @@ -30,10 +30,10 @@ class VLANTagDriver < VNMMAD::VLANDriver XPATH_FILTER = "TEMPLATE/NIC[VLAN='YES']" ############################################################################ - # Creatges the driver device operations are not locked + # Create driver device operations are locked ############################################################################ def initialize(vm, deploy_id = nil, hypervisor = nil) - @locking = false + @locking = true super(vm, XPATH_FILTER, deploy_id, hypervisor) end @@ -41,13 +41,13 @@ def initialize(vm, deploy_id = nil, hypervisor = nil) ############################################################################ # This function creates and activate a VLAN device ############################################################################ - def create_vlan_dev(options) - mtu = options[:mtu] ? "mtu #{options[:mtu]}" : "" + def create_vlan_dev + mtu = @nic[:mtu] ? "mtu #{@nic[:mtu]}" : "" OpenNebula.exec_and_log("#{command(:ip)} link add link"\ - " #{options[:phydev]} name #{options[:vlan_dev]} #{mtu} type vlan id"\ - " #{options[:vlan_id]}") + " #{@nic[:phydev]} name #{@nic[:vlan_dev]} #{mtu} type vlan id"\ + " #{@nic[:vlan_id]}") - OpenNebula.exec_and_log("#{command(:ip)} link set #{options[:vlan_dev]} up") + OpenNebula.exec_and_log("#{command(:ip)} link set #{@nic[:vlan_dev]} up") end end diff --git a/src/vnm_mad/remotes/lib/vlan.rb b/src/vnm_mad/remotes/lib/vlan.rb index 469aa207e89..04b7231fde5 100644 --- a/src/vnm_mad/remotes/lib/vlan.rb +++ b/src/vnm_mad/remotes/lib/vlan.rb @@ -24,6 +24,8 @@ module VNMMAD class VLANDriver < VNMMAD::VNMDriver def initialize(vm_tpl, xpath_filter, deploy_id = nil, hypervisor = nil) + @locking = true + super(vm_tpl, xpath_filter, deploy_id, hypervisor) lock @@ -35,21 +37,28 @@ def initialize(vm_tpl, xpath_filter, deploy_id = nil, hypervisor = nil) def activate lock - options = Hash.new - process do |nic| + @nic = nic + + next if @nic[:phydev].nil? + + # Get the name of the vlan device. + get_vlan_dev_name - options.clear + # Create the bridge. + create_bridge - options[:bridge] = nic[:bridge] - options[:phydev] = nic[:phydev] - options[:vlan_id] = nic[:vlan_id] - options[:network_id] = nic[:network_id] - options[:mtu] = nic[:mtu] + # Return if vlan device is already in the bridge. + next if @bridges[@nic[:bridge]].include? @nic[:vlan_dev] - return if options[:phydev].nil? + # Create vlan device. + create_vlan_dev - set_up_vlan(options) + # Add vlan device to the bridge. + OpenNebula.exec_and_log("#{command(:brctl)} addif"\ + " #{@nic[:bridge]} #{@nic[:vlan_dev]}") + + @bridges[@nic[:bridge]] << @nic[:vlan_dev] end unlock @@ -57,56 +66,67 @@ def activate return 0 end - # Set ups the VLAN for the VMs. - # @param options [Hash] including - # - :phydev Physical Device to bind the VLAN traffic to - # - :bridge Name of the bridge to attach the VMs and VLAN dev to - # - :network_id - def set_up_vlan(options) + # This function needs to be implemented by any VLAN driver to + # create the VLAN device. The device MUST be set up by this function + def create_vlan_dev + OpenNebula.log_error("create_vlan_dev function not implemented.") - if options[:vlan_id].nil? - options[:vlan_id] = CONF[:start_vlan] + options[:network_id].to_i - end + exit -1 + end + + # Deactivate the driver and delete bridges and tags devices as needed. + def deactivate + lock - options[:vlan_dev] = "#{options[:phydev]}.#{options[:vlan_id]}" + attach_nic_id = @vm['TEMPLATE/NIC[ATTACH="YES"]/NIC_ID'] - create_bridge(options[:bridge]) + process do |nic| + next if attach_nic_id && attach_nic_id != nic[:nic_id] - return if @bridges[options[:bridge]].include? options[:vlan_dev] + @nic = nic - create_vlan_dev(options) + next if @nic[:phydev].nil? - OpenNebula.exec_and_log("#{command(:brctl)} addif"\ - " #{options[:bridge]} #{options[:vlan_dev]}") + # Get the name of the vlan device. + get_vlan_dev_name - @bridges[options[:bridge]] << options[:vlan_dev] - end + # Return if the vlan device is not the only left device in the bridge. + next if @bridges[@nic[:bridge]].length > 1 or !@bridges[@nic[:bridge]].include? @nic[:vlan_dev] - # This function needs to be implemented by any VLAN driver to - # create the VLAN device. The device MUST be set up by this function - # Options is a driver specific hash. It includes - # :vlan_dev the name for the VLAN device - # :phydev Physical Device to bind the VLAN traffic to - # :vlan_id the VLAN ID - # : additional driver specific parameters - def create_vlan_dev(options) - OpenNebula.log_error("create_vlan_dev function not implemented.") + # Delete the vlan device. + OpenNebula.exec_and_log("#{command(:ip)} link delete"\ + " #{@nic[:vlan_dev]}") + @bridges[@nic[:bridge]].delete(@nic[:vlan_dev]) - exit -1 + # Delete the bridge. + OpenNebula.exec_and_log("#{command(:ip)} link delete"\ + " #{@nic[:bridge]}") + @bridges.delete(@nic[:bridge]) + end + + unlock end private + # Generate the name of the vlan device which will be added to the bridge. + def get_vlan_dev_name + if @nic[:vlan_id].nil? + @nic[:vlan_id] = CONF[:start_vlan] + @nic[:network_id].to_i + end + + @nic[:vlan_dev] = "#{@nic[:phydev]}.#{@nic[:vlan_id]}" + end + # Creates a bridge if it does not exists, and brings it up. # This function IS FINAL, exits if action cannot be completed - # @param bridge [String] the bridge name - def create_bridge(bridge) - return if @bridges.keys.include? bridge + def create_bridge + return if @bridges.keys.include? @nic[:bridge] - OpenNebula.exec_and_log("#{command(:brctl)} addbr #{bridge}") + OpenNebula.exec_and_log("#{command(:brctl)} addbr #{@nic[:bridge]}") - @bridges[bridge] = Array.new + @bridges[@nic[:bridge]] = Array.new - OpenNebula.exec_and_log("#{command(:ip)} link set #{bridge} up") + OpenNebula.exec_and_log("#{command(:ip)} link set #{@nic[:bridge]} up") end # Get hypervisor bridges diff --git a/src/vnm_mad/remotes/vxlan/clean b/src/vnm_mad/remotes/vxlan/clean deleted file mode 120000 index 940540d063f..00000000000 --- a/src/vnm_mad/remotes/vxlan/clean +++ /dev/null @@ -1 +0,0 @@ -../fw/clean \ No newline at end of file diff --git a/src/vnm_mad/remotes/vxlan/clean b/src/vnm_mad/remotes/vxlan/clean new file mode 100755 index 00000000000..7b9bc76bb19 --- /dev/null +++ b/src/vnm_mad/remotes/vxlan/clean @@ -0,0 +1,36 @@ +#!/usr/bin/env ruby + +# -------------------------------------------------------------------------- # +# Copyright 2002-2015, OpenNebula Project (OpenNebula.org), C12G Labs # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); you may # +# not use this file except in compliance with the License. You may obtain # +# a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +#--------------------------------------------------------------------------- # + +$: << File.dirname(__FILE__) +$: << File.join(File.dirname(__FILE__), "..") + +require 'vnmmad' +require 'vxlan_driver' + +template64 = ARGV[0] + +begin + hm = VXLANDriver.from_base64(template64) + hm.deactivate + filter_driver = VNMMAD::VNMDriver.filter_driver(template64) + filter_driver.deactivate +rescue Exception => e + OpenNebula.log_error(e.message) + OpenNebula.log_error(e.backtrace) + exit 1 +end diff --git a/src/vnm_mad/remotes/vxlan/vxlan_driver.rb b/src/vnm_mad/remotes/vxlan/vxlan_driver.rb index b5d26f63feb..35e06af0119 100644 --- a/src/vnm_mad/remotes/vxlan/vxlan_driver.rb +++ b/src/vnm_mad/remotes/vxlan/vxlan_driver.rb @@ -30,10 +30,10 @@ class VXLANDriver < VNMMAD::VLANDriver XPATH_FILTER = "TEMPLATE/NIC[VLAN='YES']" ############################################################################ - # Creatges the driver device operations are not locked + # Create driver device operations are locked ############################################################################ def initialize(vm, deploy_id = nil, hypervisor = nil) - @locking = false + @locking = true super(vm, XPATH_FILTER, deploy_id, hypervisor) end @@ -41,15 +41,15 @@ def initialize(vm, deploy_id = nil, hypervisor = nil) ############################################################################ # This function creates and activate a VLAN device ############################################################################ - def create_vlan_dev(options) - mc = VNMMAD::VNMNetwork::IPv4.to_i(CONF[:vxlan_mc]) + options[:vlan_id].to_i + def create_vlan_dev + mc = VNMMAD::VNMNetwork::IPv4.to_i(CONF[:vxlan_mc]) + @nic[:vlan_id].to_i mcs = VNMMAD::VNMNetwork::IPv4.to_s(mc) - mtu = options[:mtu] ? "mtu #{options[:mtu]}" : "" + mtu = @nic[:mtu] ? "mtu #{@nic[:mtu]}" : "" - OpenNebula.exec_and_log("#{command(:ip)} link add #{options[:vlan_dev]}"\ - " #{mtu} type vxlan id #{options[:vlan_id]} group #{mcs}"\ - " dev #{options[:phydev]}") + OpenNebula.exec_and_log("#{command(:ip)} link add #{@nic[:vlan_dev]}"\ + " #{mtu} type vxlan id #{@nic[:vlan_id]} group #{mcs}"\ + " dev #{@nic[:phydev]}") - OpenNebula.exec_and_log("#{command(:ip)} link set #{options[:vlan_dev]} up") + OpenNebula.exec_and_log("#{command(:ip)} link set #{@nic[:vlan_dev]} up") end end From e35f04c33a0679cc55018caf1360a00bd9bfdb10 Mon Sep 17 00:00:00 2001 From: goberle Date: Fri, 12 Jun 2015 14:54:04 +0200 Subject: [PATCH 2/2] Feature #3666: move get_bridges to activate/deactivate method. --- src/vnm_mad/remotes/lib/vlan.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vnm_mad/remotes/lib/vlan.rb b/src/vnm_mad/remotes/lib/vlan.rb index 04b7231fde5..c6cf1e35c3f 100644 --- a/src/vnm_mad/remotes/lib/vlan.rb +++ b/src/vnm_mad/remotes/lib/vlan.rb @@ -27,15 +27,13 @@ def initialize(vm_tpl, xpath_filter, deploy_id = nil, hypervisor = nil) @locking = true super(vm_tpl, xpath_filter, deploy_id, hypervisor) - - lock - @bridges = get_bridges - unlock end # Activate the driver and creates bridges and tags devices as needed. def activate lock + + @bridges = get_bridges process do |nic| @nic = nic @@ -77,6 +75,8 @@ def create_vlan_dev # Deactivate the driver and delete bridges and tags devices as needed. def deactivate lock + + @bridges = get_bridges attach_nic_id = @vm['TEMPLATE/NIC[ATTACH="YES"]/NIC_ID']