mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-20 10:50:08 +03:00
feature #3175: Moved Nic and VM to new modules
This commit is contained in:
parent
0e49cf00bb
commit
fba4deec6e
@ -16,8 +16,7 @@
|
||||
|
||||
module VNMMAD
|
||||
|
||||
# The address module provides basic functions to manage IP addresses
|
||||
module Address
|
||||
module VNMNetwork
|
||||
|
||||
# This methods translates an address range to a set of IPv4 networks
|
||||
# in CIDR notation
|
||||
|
@ -16,8 +16,7 @@
|
||||
|
||||
module VNMMAD
|
||||
|
||||
# This module includes functions to execute and manage Network commands.
|
||||
module Command
|
||||
module VNMNetwork
|
||||
|
||||
# Command configuration for common network commands. This CAN be adjust
|
||||
# to local installations. Any modification requires to sync the hosts with
|
||||
|
154
src/vnm_mad/remotes/lib/nic.rb
Normal file
154
src/vnm_mad/remotes/lib/nic.rb
Normal file
@ -0,0 +1,154 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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 VNMNetwork
|
||||
|
||||
# This class represents the NICS of a VM, it provides a factory method
|
||||
# to create VMs of the given hyprtvisor
|
||||
class Nics < Array
|
||||
def initialize(hypervisor)
|
||||
case hypervisor
|
||||
when "kvm"
|
||||
@nicClass = NicKVM
|
||||
when "xen"
|
||||
@nicClass = NicXen
|
||||
when "vmware"
|
||||
@nicClass = NicVMware
|
||||
end
|
||||
end
|
||||
|
||||
def new_nic
|
||||
@nicClass.new
|
||||
end
|
||||
end
|
||||
|
||||
############################################################################
|
||||
# Hypervisor specific implementation of network interfaces. Each class
|
||||
# implements the following interface:
|
||||
# - get_info to populste the VM.vm_info Hash
|
||||
# - get_tap to set the [:tap] attribute with the associated NIC
|
||||
############################################################################
|
||||
|
||||
# A NIC using KVM. This class implements functions to get the physical
|
||||
# interface that the NIC is using, based on the MAC address
|
||||
class NicKVM < Hash
|
||||
def initialize
|
||||
super(nil)
|
||||
end
|
||||
|
||||
# Get the VM information with virsh dumpxml
|
||||
def get_info(vm)
|
||||
if vm.deploy_id
|
||||
deploy_id = vm.deploy_id
|
||||
else
|
||||
deploy_id = vm['DEPLOY_ID']
|
||||
end
|
||||
|
||||
if deploy_id and vm.vm_info[:dumpxml].nil?
|
||||
vm.vm_info[:dumpxml] = `#{VNMNetwork::COMMANDS[:virsh]} dumpxml #{deploy_id} 2>/dev/null`
|
||||
|
||||
vm.vm_info.each_key do |k|
|
||||
vm.vm_info[k] = nil if vm.vm_info[k].to_s.strip.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Look for the tap in
|
||||
# devices/interface[@type='bridge']/mac[@address='<mac>']/../target"
|
||||
def get_tap(vm)
|
||||
dumpxml = vm.vm_info[:dumpxml]
|
||||
|
||||
if dumpxml
|
||||
dumpxml_root = REXML::Document.new(dumpxml).root
|
||||
|
||||
xpath = "devices/interface[@type='bridge']/" \
|
||||
"mac[@address='#{self[:mac]}']/../target"
|
||||
|
||||
tap = dumpxml_root.elements[xpath]
|
||||
|
||||
self[:tap] = tap.attributes['dev'] if tap
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# A NIC using Xen. This class implements functions to get the physical interface
|
||||
# that the NIC is using
|
||||
class NicXen < Hash
|
||||
def initialize
|
||||
super(nil)
|
||||
end
|
||||
|
||||
def get_info(vm)
|
||||
if vm.deploy_id
|
||||
deploy_id = vm.deploy_id
|
||||
else
|
||||
deploy_id = vm['DEPLOY_ID']
|
||||
end
|
||||
|
||||
if deploy_id and (vm.vm_info[:domid].nil? or vm.vm_info[:networks].nil?)
|
||||
vm.vm_info[:domid] =`#{VNMNetwork::COMMANDS[:xm]} domid #{deploy_id}`.strip
|
||||
vm.vm_info[:networks] =`#{VNMNetwork::COMMANDS[:xm]} network-list #{deploy_id}`
|
||||
|
||||
vm.vm_info.each_key do |k|
|
||||
vm.vm_info[k] = nil if vm.vm_info[k].to_s.strip.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_tap(vm)
|
||||
domid = vm.vm_info[:domid]
|
||||
|
||||
if domid
|
||||
networks = vm.vm_info[:networks].split("\n")[1..-1]
|
||||
networks.each do |net|
|
||||
n = net.split
|
||||
|
||||
iface_id = n[0]
|
||||
iface_mac = n[2]
|
||||
|
||||
if iface_mac == self[:mac]
|
||||
self[:tap] = "vif#{domid}.#{iface_id}"
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
# A NIC using VMware. This class implements functions to get the physical interface
|
||||
# that the NIC is using
|
||||
class NicVMware < Hash
|
||||
def initialize
|
||||
super(nil)
|
||||
end
|
||||
|
||||
def get_info(vm)
|
||||
end
|
||||
|
||||
def get_tap(vm)
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
179
src/vnm_mad/remotes/lib/opennebula_network.rb
Normal file
179
src/vnm_mad/remotes/lib/opennebula_network.rb
Normal file
@ -0,0 +1,179 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
# 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 'rexml/document'
|
||||
require 'base64'
|
||||
require 'yaml'
|
||||
|
||||
require 'one_firewall'
|
||||
require 'one_sg'
|
||||
require 'lib/vm'
|
||||
require 'lib/nic'
|
||||
require 'lib/address'
|
||||
require 'lib/security_groups'
|
||||
require 'lib/security_groups_iptables'
|
||||
|
||||
require 'scripts_common'
|
||||
|
||||
include OpenNebula
|
||||
|
||||
begin
|
||||
CONF = YAML.load_file(
|
||||
File.join(File.dirname(__FILE__), "OpenNebulaNetwork.conf")
|
||||
)
|
||||
rescue
|
||||
CONF = {
|
||||
:start_vlan => 2
|
||||
}
|
||||
end
|
||||
|
||||
# Set PATH
|
||||
ENV['PATH'] = "#{ENV['PATH']}:/bin:/sbin:/usr/bin"
|
||||
|
||||
|
||||
################################################################################
|
||||
# The VNMMAD module provides the basic abstraction to implement custom
|
||||
# virtual network drivers. The VNMAD module includes:
|
||||
# - VNMNetwork with base classes and main functionality
|
||||
# - SGIPTables a module with a SG implementation based in iptables/ipset
|
||||
################################################################################
|
||||
module VNMMAD
|
||||
|
||||
############################################################################
|
||||
# Base driver class to implement a Network driver. It relays on two filter
|
||||
# drivers OpenNebulaFirewall and OpenNebulaSG.
|
||||
############################################################################
|
||||
class OpenNebulaNetwork
|
||||
attr_reader :hypervisor, :vm
|
||||
|
||||
# Creates new OpenNebulaNetwork using:
|
||||
# @param vm_tpl [String] XML String from oned
|
||||
# @param xpath_filter [String] to get relevant NICs for the driver
|
||||
# @param deploy_id [String]
|
||||
# @param hypervisor [String]
|
||||
def initialize(vm_tpl, xpath_filter, deploy_id = nil, hypervisor = nil)
|
||||
@locking = false
|
||||
|
||||
if !hypervisor
|
||||
@hypervisor = detect_hypervisor
|
||||
else
|
||||
@hypervisor = hypervisor
|
||||
end
|
||||
|
||||
@vm = VM.new(REXML::Document.new(vm_tpl).root, xpath_filter,
|
||||
deploy_id, @hypervisor)
|
||||
end
|
||||
|
||||
# Creates a new OpenNebulaNetwork using:
|
||||
# @param vm_64 [String] Base64 encoded XML String from oned
|
||||
# @param deploy_id [String]
|
||||
# @param hypervisor [String]
|
||||
def self.from_base64(vm_64, deploy_id = nil, hypervisor = nil)
|
||||
vm_xml = Base64::decode64(vm_64)
|
||||
self.new(vm_xml, deploy_id, hypervisor)
|
||||
end
|
||||
|
||||
# Locking function to serialized driver operations if needed. Similar
|
||||
# to flock. File is created as /tmp/onevnm-<driver>-lock
|
||||
def lock
|
||||
if @locking
|
||||
driver_name = self.class.name.downcase
|
||||
@locking_file = File.open("/tmp/onevnm-#{driver_name}-lock","w")
|
||||
@locking_file.flock(File::LOCK_EX)
|
||||
end
|
||||
end
|
||||
|
||||
# Unlock driver execution mutex
|
||||
def unlock
|
||||
if @locking
|
||||
@locking_file.close
|
||||
end
|
||||
end
|
||||
|
||||
# Executes the given block on each NIC
|
||||
def process(&block)
|
||||
@vm.each_nic(block)
|
||||
end
|
||||
|
||||
# Return a string for the hypervisor
|
||||
# @return [String] "kvm", "xen" or nil
|
||||
def detect_hypervisor
|
||||
lsmod = `#{VNMNetwork::COMMANDS[:lsmod]}`
|
||||
xen_file = "/proc/xen/capabilities"
|
||||
|
||||
if File.exists?(xen_file)
|
||||
"xen"
|
||||
elsif lsmod.match(/kvm/)
|
||||
"kvm"
|
||||
else
|
||||
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
|
||||
# - WHITE_PORTS_TCP
|
||||
# - WHITE_PORTS_UDP
|
||||
# - BLACK_PORTS_TCP
|
||||
# - BLACK_PORTS_UDP
|
||||
#
|
||||
# @return Boolean
|
||||
def self.has_fw_attrs?(vm_xml)
|
||||
vm_root = REXML::Document.new(vm_xml).root
|
||||
!vm_root.elements[OpenNebulaFirewall::XPATH_FILTER].nil?
|
||||
end
|
||||
|
||||
# Returns a filter object based on the contents of the template
|
||||
#
|
||||
# @return OpenNebulaFirewall or OpenNebulaSG object
|
||||
def self.filter_driver(vm_64, deploy_id = nil, hypervisor = nil)
|
||||
vm_xml = Base64::decode64(vm_64)
|
||||
|
||||
if self.has_fw_attrs?(vm_xml)
|
||||
OpenNebulaFirewall.new(vm_xml, deploy_id, hypervisor)
|
||||
else
|
||||
OpenNebulaSG.new(vm_xml, deploy_id, hypervisor)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -17,7 +17,7 @@
|
||||
module VNMMAD
|
||||
|
||||
# This module includes provides the abstractions to implement SecurityGroups
|
||||
module SGBase
|
||||
module VNMNetwork
|
||||
|
||||
############################################################################
|
||||
# Rule supports these (final and relevant) attributes:
|
||||
@ -101,7 +101,7 @@ module SGBase
|
||||
def net
|
||||
return [] if @ip.nil? || @size.nil?
|
||||
|
||||
Address::to_nets(@ip, @size)
|
||||
VNMNetwork::to_nets(@ip, @size)
|
||||
end
|
||||
|
||||
# Expand the ICMP type with associated codes if any
|
||||
@ -190,7 +190,7 @@ module SGBase
|
||||
@rules = []
|
||||
@vars = {}
|
||||
|
||||
@commands = Commands.new
|
||||
@commands = VNMNetwork::Commands.new
|
||||
|
||||
rules.each do |rule|
|
||||
@rules << new_rule(rule)
|
||||
|
@ -22,7 +22,7 @@ module SGIPTables
|
||||
############################################################################
|
||||
# A Rule implemented with the iptables/ipset Linux kernel facilities
|
||||
############################################################################
|
||||
class RuleIPTables < Rule
|
||||
class RuleIPTables < VNMNetwork::Rule
|
||||
########################################################################
|
||||
# Implementation of each rule type
|
||||
########################################################################
|
||||
@ -136,7 +136,7 @@ module SGIPTables
|
||||
# This class represents a SecurityGroup implemented with iptables/ipset
|
||||
# Kernel facilities.
|
||||
############################################################################
|
||||
class SecurityGroupIPTables < SecurityGroup
|
||||
class SecurityGroupIPTables < VNMNetwork::SecurityGroup
|
||||
def initialize(vm, nic, sg_id, rules)
|
||||
super
|
||||
|
||||
@ -157,7 +157,7 @@ module SGIPTables
|
||||
# - :iptables_s
|
||||
# - :ipset_list
|
||||
def self.info
|
||||
commands = Commands.new
|
||||
commands = VNMNetwork::Commands.new
|
||||
|
||||
commands << :iptables "-S"
|
||||
iptables_s = commands.run!
|
||||
@ -188,7 +188,7 @@ module SGIPTables
|
||||
|
||||
return if info[:iptables_s].split("\n").include? "-N #{GLOBAL_CHAIN}"
|
||||
|
||||
commands = Commands.new
|
||||
commands = VNMNetwork::Commands.new
|
||||
|
||||
commands.iptables "-N #{GLOBAL_CHAIN}"
|
||||
commands.iptables "-A FORWARD -m physdev --physdev-is-bridged -j #{GLOBAL_CHAIN}"
|
||||
@ -244,7 +244,7 @@ module SGIPTables
|
||||
# IP spoofing
|
||||
# iptables -A one-3-0-o ! --source 10.0.0.1 -j DROP
|
||||
def self.nic_pre(vm, nic)
|
||||
commands = Commands.new
|
||||
commands = VNMNetwork::Commands.new
|
||||
|
||||
vars = SGIPTables.vars(vm, nic)
|
||||
|
||||
@ -285,7 +285,7 @@ module SGIPTables
|
||||
chain_in = vars[:chain_in]
|
||||
chain_out = vars[:chain_out]
|
||||
|
||||
commands = Commands.new
|
||||
commands = VNMNetwork::Commands.new
|
||||
commands << :iptables "-A #{chain_in} -j DROP"
|
||||
commands << :iptables "-A #{chain_out} -j DROP"
|
||||
|
||||
@ -304,7 +304,7 @@ module SGIPTables
|
||||
iptables_s = info[:iptables_s]
|
||||
ipset_list = info[:ipset_list]
|
||||
|
||||
commands = Commands.new
|
||||
commands = VNMNetwork::Commands.new
|
||||
|
||||
iptables_forwards.lines.reverse_each do |line|
|
||||
fields = line.split
|
||||
|
110
src/vnm_mad/remotes/lib/vm.rb
Normal file
110
src/vnm_mad/remotes/lib/vm.rb
Normal 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 VNMNetwork
|
||||
|
||||
############################################################################
|
||||
# This class represents the VM abstraction. It provides basic methods
|
||||
# to interact with its network interfaces.
|
||||
############################################################################
|
||||
class VM
|
||||
attr_accessor :nics, :vm_info, :deploy_id, :vm_root
|
||||
|
||||
|
||||
# Creates a new VM object, and bootstrap the NICs array
|
||||
# @param vm_root [REXML] XML document representing the VM
|
||||
# @param xpath_filer [String] to get the VM NICs
|
||||
# @param deploy_id [String] refers to the VM in the hypervisor
|
||||
# @param hypervisor [String]
|
||||
def initialize(vm_root, xpath_filter, deploy_id, hypervisor)
|
||||
@vm_root = vm_root
|
||||
@xpath_filter = xpath_filter
|
||||
@deploy_id = deploy_id
|
||||
@hypervisor = hypervisor
|
||||
@vm_info = Hash.new
|
||||
|
||||
@deploy_id = nil if deploy_id == "-"
|
||||
|
||||
nics = VNMNetwork::Nics.new(@hypervisor)
|
||||
|
||||
@vm_root.elements.each(@xpath_filter) do |nic_element|
|
||||
nic = nics.new_nic
|
||||
|
||||
nic_build_hash(nic_element,nic)
|
||||
|
||||
nic.get_info(self)
|
||||
nic.get_tap(self)
|
||||
|
||||
nics << nic
|
||||
end
|
||||
|
||||
@nics = nics
|
||||
end
|
||||
|
||||
# Iterator on each NIC of the VM
|
||||
def each_nic(block)
|
||||
if @nics != nil
|
||||
@nics.each do |the_nic|
|
||||
block.call(the_nic)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Access an XML Element of the VM
|
||||
# @param element [String] element name
|
||||
# @return [String] valule of the element or nil if not found
|
||||
def [](element)
|
||||
if @vm_root
|
||||
val = @vm_root.elements[element]
|
||||
return val.text if !val.nil? && val.text
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
private:
|
||||
|
||||
# Method to build the associated Hash from a NIC
|
||||
# @param nic_element [REXML] for the NIC
|
||||
# @param nic [Nic] class representation
|
||||
def nic_build_hash(nic_element,nic)
|
||||
nic_element.elements.each('*') do |nic_attribute|
|
||||
key = nic_attribute.name.downcase.to_sym
|
||||
|
||||
if nic_attribute.has_elements?
|
||||
data = {}
|
||||
nic_build_hash(nic_attribute,data)
|
||||
else
|
||||
data = nic_attribute.text
|
||||
end
|
||||
|
||||
if nic[key]
|
||||
if nic[key].instance_of?(Array)
|
||||
nic[key] << data
|
||||
else
|
||||
nic[key] = [nic[key], data]
|
||||
end
|
||||
else
|
||||
nic[key] = data
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user