1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-01-24 02:03:52 +03:00

feature #3208: Implement VXLAN support. Moved common bridge functions from 802.1Q to VLANDriver class. Rename vlan_driver to vlan_tag_driver for 802.1Q.

This commit is contained in:
Ruben S. Montero 2015-01-05 02:31:03 +01:00
parent e061f11f69
commit 5d44f6e758
11 changed files with 256 additions and 97 deletions

View File

@ -262,6 +262,7 @@ VAR_DIRS="$VAR_LOCATION/remotes \
$VAR_LOCATION/remotes/vmm/az \
$VAR_LOCATION/remotes/vnm \
$VAR_LOCATION/remotes/vnm/802.1Q \
$VAR_LOCATION/remotes/vnm/vxlan \
$VAR_LOCATION/remotes/vnm/dummy \
$VAR_LOCATION/remotes/vnm/ebtables \
$VAR_LOCATION/remotes/vnm/fw \
@ -449,6 +450,7 @@ INSTALL_FILES=(
DATASTORE_DRIVER_DEV_SCRIPTS:$VAR_LOCATION/remotes/datastore/dev
NETWORK_FILES:$VAR_LOCATION/remotes/vnm
NETWORK_8021Q_FILES:$VAR_LOCATION/remotes/vnm/802.1Q
NETWORK_VXLAN_FILES:$VAR_LOCATION/remotes/vnm/vxlan
NETWORK_DUMMY_FILES:$VAR_LOCATION/remotes/vnm/dummy
NETWORK_EBTABLES_FILES:$VAR_LOCATION/remotes/vnm/ebtables
NETWORK_FW_FILES:$VAR_LOCATION/remotes/vnm/fw
@ -940,6 +942,7 @@ NETWORK_FILES="src/vnm_mad/remotes/lib/vnm_driver.rb \
src/vnm_mad/remotes/lib/address.rb \
src/vnm_mad/remotes/lib/command.rb \
src/vnm_mad/remotes/lib/vm.rb \
src/vnm_mad/remotes/lib/vlan.rb \
src/vnm_mad/remotes/lib/security_groups.rb \
src/vnm_mad/remotes/lib/security_groups_iptables.rb \
src/vnm_mad/remotes/lib/nic.rb"
@ -947,7 +950,13 @@ NETWORK_FILES="src/vnm_mad/remotes/lib/vnm_driver.rb \
NETWORK_8021Q_FILES="src/vnm_mad/remotes/802.1Q/clean \
src/vnm_mad/remotes/802.1Q/post \
src/vnm_mad/remotes/802.1Q/pre \
src/vnm_mad/remotes/802.1Q/vlan_driver.rb"
src/vnm_mad/remotes/802.1Q/vlan_tag_driver.rb"
NETWORK_VXLAN_FILES="src/vnm_mad/remotes/vxlan/clean \
src/vnm_mad/remotes/vxlan/post \
src/vnm_mad/remotes/vxlan/pre \
src/vnm_mad/remotes/vxlan/vxlan_driver.rb"
NETWORK_DUMMY_FILES="src/vnm_mad/remotes/dummy/clean \
src/vnm_mad/remotes/dummy/post \

View File

@ -19,7 +19,7 @@
$: << File.dirname(__FILE__)
$: << File.join(File.dirname(__FILE__), "..")
require 'vlan_driver'
require 'vlan_tag_driver'
hm = VLANDriver.from_base64(ARGV[0])
hm = VLANTagDriver.from_base64(ARGV[0])
exit hm.activate

View File

@ -23,7 +23,7 @@ require 'vnmmad'
#
# Once activated the VM will be attached to this bridge
################################################################################
class VLANDriver < VNMMAD::VNMDriver
class VLANTagDriver < VNMMAD::VLANDriver
# DRIVER name and XPATH for relevant NICs
DRIVER = "802.1Q"
@ -33,12 +33,9 @@ class VLANDriver < VNMMAD::VNMDriver
# Creatges the driver device operations are not locked
############################################################################
def initialize(vm, deploy_id = nil, hypervisor = nil)
super(vm, XPATH_FILTER, deploy_id, hypervisor)
@locking = false
lock
@bridges = get_interfaces
unlock
super(vm, XPATH_FILTER, deploy_id, hypervisor)
end
############################################################################
@ -47,33 +44,21 @@ class VLANDriver < VNMMAD::VNMDriver
def activate
lock
vm_id = @vm['ID']
vm_id = @vm['ID']
options = Hash.new
process do |nic|
bridge = nic[:bridge]
dev = nic[:phydev]
if dev
if nic[:vlan_id]
vlan = nic[:vlan_id]
else
vlan = CONF[:start_vlan] + nic[:network_id].to_i
end
options.clear
if !bridge_exists? bridge
create_bridge bridge
ifup bridge
end
options[:bridge] = nic[:bridge]
options[:phydev] = nic[:phydev]
options[:vlan_id] = nic[:vlan_id]
options[:network_id] = nic[:network_id]
if !device_exists?(dev, vlan)
create_dev_vlan(dev, vlan)
ifup(dev, vlan)
end
return if options[:phydev].nil?
if !attached_bridge_dev?(bridge, dev, vlan)
attach_brigde_dev(bridge, dev, vlan)
end
end
set_up_vlan(options)
end
unlock
@ -82,49 +67,13 @@ class VLANDriver < VNMMAD::VNMDriver
end
############################################################################
# Private interface, methods to manage bridges and VLAN tags through the
# brctl and ip commands
# This function creates and activate a VLAN device
############################################################################
private
def create_vlan_dev(options)
OpenNebula.exec_and_log("#{command(:ip)} link add link"\
" #{options[:phydev]} name #{options[:vlan_dev]} type vlan id"\
" #{options[:vlan_id]}")
def bridge_exists?(bridge)
@bridges.keys.include? bridge
end
def create_bridge(bridge)
OpenNebula.exec_and_log("#{command(:brctl)} addbr #{bridge}")
@bridges[bridge] = Array.new
end
def device_exists?(dev, vlan=nil)
dev = "#{dev}.#{vlan}" if vlan
`#{command(:ip)} link show #{dev}`
$?.exitstatus == 0
end
def create_dev_vlan(dev, vlan)
cmd = "#{command(:ip)} link add link #{dev}"
cmd << " name #{dev}.#{vlan} type vlan id #{vlan}"
OpenNebula.exec_and_log(cmd)
end
def attached_bridge_dev?(bridge, dev, vlan=nil)
return false if !bridge_exists? bridge
dev = "#{dev}.#{vlan}" if vlan
@bridges[bridge].include? dev
end
def attach_brigde_dev(bridge, dev, vlan=nil)
dev = "#{dev}.#{vlan}" if vlan
OpenNebula.exec_and_log("#{command(:brctl)} addif #{bridge} #{dev}")
@bridges[bridge] << dev
end
def ifup(dev, vlan=nil)
dev = "#{dev}.#{vlan}" if vlan
OpenNebula.exec_and_log("#{command(:ip)} link set #{dev} up")
OpenNebula.exec_and_log("#{command(:ip)} link set #{options[:vlan_dev]} up")
end
end

View File

@ -27,3 +27,10 @@
# Enable ARP Cache Poisoning Prevention Rules
:arp_cache_poisoning: true
################################################################################
# VXLAN Options
################################################################################
# Base multicast address for each VLAN. The mc address is :vxlan_mc + :vlan_id
:vxlan_mc: 239.0.0.0

View File

@ -0,0 +1,110 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2014, 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. #
#--------------------------------------------------------------------------- #
module VNMMAD
############################################################################
# Module to use as mixin for implementing VLAN drivers based on special
# link devices though the Linux kernel features and bridges. It provides
# common functionality to handle bridges
############################################################################
class VLANDriver < VNMMAD::VNMDriver
def initialize(vm_tpl, xpath_filter, deploy_id = nil, hypervisor = nil)
super(vm_tpl, xpath_filter, deploy_id, hypervisor)
lock
@bridges = get_bridges
unlock
end
# 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.")
exit -1
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)
if options[:vlan_id].nil?
options[:vlan_id] = CONF[:start_vlan] + options[:network_id].to_i
end
options[:vlan_dev] = "#{options[:phydev]}.#{options[:vlan_id]}"
create_bridge(options[:bridge])
return if @bridges[options[:bridge]].include? options[:vlan_dev]
create_vlan_dev(options)
OpenNebula.exec_and_log("#{command(:brctl)} addif"\
" #{options[:bridge]} #{options[:vlan_dev]}")
@bridges[options[:bridge]] << options[:vlan_dev]
end
private
# 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
OpenNebula.exec_and_log("#{command(:brctl)} addbr #{bridge}")
@bridges[bridge] = Array.new
OpenNebula.exec_and_log("#{command(:ip)} link set #{bridge} up")
end
# Get hypervisor bridges
# @return [Hash<String>] with the bridge names
def get_bridges
bridges = Hash.new
brctl_exit =`#{VNMNetwork::COMMANDS[:brctl]} show`
cur_bridge = ""
brctl_exit.split("\n")[1..-1].each do |l|
l = l.split
if l.length > 1
cur_bridge = l[0]
bridges[cur_bridge] = Array.new
bridges[cur_bridge] << l[3] if l[3]
else
bridges[cur_bridge] << l[0]
end
end
bridges
end
end
end

View File

@ -35,7 +35,7 @@ module VNMMAD
# @param deploy_id [String]
# @param hypervisor [String]
def initialize(vm_tpl, xpath_filter, deploy_id = nil, hypervisor = nil)
@locking = false
@locking ||= false
if !hypervisor
@hypervisor = detect_hypervisor
@ -92,30 +92,6 @@ module VNMMAD
nil
end
end
# Get hypervisor bridges
# @return [Hash<String>] with the bridge names
def get_interfaces
bridges = Hash.new
brctl_exit =`#{VNMNetwork::COMMANDS[:brctl]} show`
cur_bridge = ""
brctl_exit.split("\n")[1..-1].each do |l|
l = l.split
if l.length > 1
cur_bridge = l[0]
bridges[cur_bridge] = Array.new
bridges[cur_bridge] << l[3] if l[3]
else
bridges[cur_bridge] << l[0]
end
end
bridges
end
# Returns true if the template contains the deprecated firewall attributes:
# - ICMP

View File

@ -30,7 +30,7 @@ require 'security_groups_iptables'
require 'vnm_driver'
require 'fw_driver'
require 'sg_driver'
require 'vlan'
require 'scripts_common'
include OpenNebula

View File

@ -0,0 +1 @@
../fw/clean

View File

@ -0,0 +1 @@
../fw/post

25
src/vnm_mad/remotes/vxlan/pre Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2014, 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 'vxlan_driver'
hm = VXLANDriver.from_base64(ARGV[0])
exit hm.activate

View File

@ -0,0 +1,81 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2014, 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. #
#--------------------------------------------------------------------------- #
require 'vnmmad'
################################################################################
# This driver tag VM traffic with a VLAN_ID using VXLAN protocol. Features:
# - Creates a bridge and bind phisycal device if not present
# - Creates a tagged interface for the VM dev.vlan_id
#
# Once activated the VM will be attached to this bridge
################################################################################
class VXLANDriver < VNMMAD::VLANDriver
# DRIVER name and XPATH for relevant NICs
DRIVER = "vxlan"
XPATH_FILTER = "TEMPLATE/NIC[VLAN='YES']"
############################################################################
# Creatges the driver device operations are not locked
############################################################################
def initialize(vm, deploy_id = nil, hypervisor = nil)
@locking = false
super(vm, XPATH_FILTER, deploy_id, hypervisor)
end
############################################################################
# Activate the driver and creates bridges and tags devices as needed.
############################################################################
def activate
lock
options = Hash.new
process do |nic|
options.clear
options[:bridge] = nic[:bridge]
options[:phydev] = nic[:phydev]
options[:vlan_id] = nic[:vlan_id]
options[:network_id] = nic[:network_id]
return if options[:phydev].nil?
set_up_vlan(options)
end
unlock
return 0
end
############################################################################
# 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
mcs = VNMMAD::VNMNetwork::IPv4.to_s(mc)
OpenNebula.exec_and_log("#{command(:ip)} link add #{options[:vlan_dev]}"\
" type vxlan id #{options[:vlan_id]} group #{mcs}"\
" dev #{options[:phydev]}")
OpenNebula.exec_and_log("#{command(:ip)} link set #{options[:vlan_dev]} up")
end
end