Change in vdsm[master]: Signed-off-by: Dan Yasny <dyasny at gmail.com>
dyasny at gmail.com
dyasny at gmail.com
Tue Aug 28 15:29:58 UTC 2012
Dan Yasny has uploaded a new change for review.
Change subject: Signed-off-by: Dan Yasny <dyasny at gmail.com>
......................................................................
Signed-off-by: Dan Yasny <dyasny at gmail.com>
Cisco VM-FEX support vdsm hooks
Change-Id: I45a7fa46919bb39a648dff190c40618395990e91
Signed-off-by: Dan Yasny <dyasny at dy-lappie.usersys.redhat.com>
---
A vdsm_hooks/vmfex/Makefile.am
A vdsm_hooks/vmfex/README
A vdsm_hooks/vmfex/before_vm_migrate_destination.py
A vdsm_hooks/vmfex/before_vm_start.py
4 files changed, 394 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/47/7547/1
diff --git a/vdsm_hooks/vmfex/Makefile.am b/vdsm_hooks/vmfex/Makefile.am
new file mode 100644
index 0000000..b921275
--- /dev/null
+++ b/vdsm_hooks/vmfex/Makefile.am
@@ -0,0 +1,36 @@
+#
+# Copyright 2011 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# Refer to the README and COPYING files for full details of the license
+#
+
+EXTRA_DIST = \
+ before_vm_migrate_destination.py \
+ before_vm_start.py \
+
+install-data-local:
+ $(MKDIR_P) $(DESTDIR)$(vdsmhooksdir)/before_vm_start
+ $(INSTALL_SCRIPT) $(srcdir)/before_vm_start.py \
+ $(DESTDIR)$(vdsmhooksdir)/before_vm_start/50_vmfex
+ $(MKDIR_P) $(DESTDIR)$(vdsmhooksdir)/before_vm_migrate_destination
+ $(INSTALL_SCRIPT) $(srcdir)/before_vm_migrate_destination.py \
+ $(DESTDIR)$(vdsmhooksdir)/before_vm_migrate_destination/50_vmfex
+
+uninstall-local: uninstall-data-sudoers
+ $(RM) $(DESTDIR)$(vdsmhooksdir)/before_vm_start/50_vmfex
+ $(RM) $(DESTDIR)$(vdsmhooksdir)/before_vm_migrate_destination/50_vmfex
+
diff --git a/vdsm_hooks/vmfex/README b/vdsm_hooks/vmfex/README
new file mode 100644
index 0000000..1eb7629
--- /dev/null
+++ b/vdsm_hooks/vmfex/README
@@ -0,0 +1,61 @@
+vmfex vdsm hook
+===================
+
+Add Cisco VM-FEX Port Profile to Virtual Machine
+Sample:
+ vmfex=NIC1:profile1,NIC2:profile2...
+
+ Will add 2 virtual nics attached to profile1 and profile2 using the vnic
+ MAC addresses specified, replacing the actual NICs assigned to the VM.
+ The mapping is by order of NIC<number> in the parameters, mapped to the
+ order of the "interface" elements in the devices of the VM xml, as well
+ as the NICs defined for a VM in the RHEV-M admin GUI.
+
+Libvirt internals:
+Replace the existing interface xml:
+ <interface type="bridge">
+ <mac address="<mac>"/>
+ <model type="virtio"/>
+ <source bridge="<logical network>"/>
+ </interface>
+
+with the following interface xml:
+ <interface type='network'>
+ <mac address='<mac>'/>
+ <source network='direct-pool'/>
+ <virtualport type='802.1Qbh'>
+ <parameters profileid='<Port Profile>'/>
+ </virtualport>
+ <model type='virtio'/>
+ </interface>
+
+Dynamic network with libvirt (define a NIC pool, so libvirt can assign VMs to NICs dynamically):
+
+ <network>
+ <name>direct-pool</name>
+ <forward mode="passthrough">
+ <interface dev="eth3"/>
+ <interface dev="eth4"/>
+ <interface dev="eth5"/>
+ <interface dev="eth6"/>
+ <interface dev="eth7"/>
+ <interface dev="eth8"/>
+ <interface dev="eth9"/>
+ <interface dev="eth10"/>
+ <interface dev="eth11"/>
+ </forward>
+ </network>
+
+Using libvirt, the network is defined like this:
+
+ virsh net-define /tmp/direct-pool.xml
+ virsh net-start direct-pool
+ virsh net-autostart direct-pool
+
+(where /tmp/direct-pool.xml contains the xml above)
+
+(everything else is autogenerated, and shouldn't be specified
+when defining a guest (but whatever is there after definition
+should be left in place, e.g. the PCI address)). Note that these
+interface definitions are completely static - you never need to modify
+them due to migration, or starting up/shutting down the guest.
diff --git a/vdsm_hooks/vmfex/before_vm_migrate_destination.py b/vdsm_hooks/vmfex/before_vm_migrate_destination.py
new file mode 100755
index 0000000..a80df7f
--- /dev/null
+++ b/vdsm_hooks/vmfex/before_vm_migrate_destination.py
@@ -0,0 +1,109 @@
+#!/usr/bin/python
+
+import os
+import subprocess
+import sys
+import hooking
+import traceback
+import libvirtconnection
+
+'''
+Placed in before_vm_migrate_destination
+
+vmfex hook on migration destination:
+
+Set up a dynamic NIC pool for incoming migrations to use
+
+ <network>
+ <name>direct-pool</name>
+ <forward mode="passthrough">
+ <interface dev="eth3"/>
+ <interface dev="eth4"/>
+ <interface dev="eth5"/>
+ <interface dev="eth6"/>
+ <interface dev="eth7"/>
+ <interface dev="eth8"/>
+ <interface dev="eth9"/>
+ <interface dev="eth10"/>
+ <interface dev="eth11"/>
+ </forward>
+ </network>
+
+Using libvirt, the network is defined like this:
+
+ virsh net-define /tmp/direct-pool.xml
+ virsh net-start direct-pool
+ virsh net-autostart direct-pool
+
+(where /tmp/direct-pool.xml contains the xml above)
+
+(everything else is autogenerated, and shouldn't be specified
+when defining a guest (but whatever is there after definition
+should be left in place, e.g. the PCI address)). Note that these
+interface definitions are completely static - you never need to modify
+them due to migration, or starting up/shutting down the guest.
+
+'''
+
+def getUsableNics():
+ # Scan localhost for physical NICs and return list of physical nics
+ # that have all zeroes MAC
+ # Example ['eth0','eth1']
+ nics = []
+ cmd = "find /sys/devices/pci* | grep '/net/' |grep address"
+ p = subprocess.Popen(cmd,stdout=subprocess.PIPE,shell=True)
+ s = p.stdout.read().split()
+ for i in s:
+ mac = open(i).read().strip()
+ if mac == '00:00:00:00:00:00':
+ nics.append(i.split('/')[-2])
+ return nics
+
+def createDirectPool(conn):
+ xmlstr = """<network> \n <name>direct-pool</name> \n <forward mode="passthrough"> \n """
+ for i in getUsableNics():
+ s = '<interface dev="' + str(i) + '"/> \n'
+ xmlstr += s
+
+ xmlstr += """ </forward> \n </network> """
+ conn.networkDefineXML(xmlstr)
+ dpool = conn.networkLookupByName('direct-pool')
+ dpool.setAutostart(1)
+ dpool.create()
+
+
+
+if os.environ.has_key('vmfex'):
+ try:
+ #connect to libvirtd
+ conn = libvirtconnection.get('qemu:///system')
+
+ #check for running VMs. If there are VMs running, skip creating a dNIC pool
+ if len(conn.listDomainsID()) == 0:
+ #check if direct-pool is created
+ if 'direct-pool' not in conn.listNetworks():
+ createDirectPool(conn)
+ else:
+ if conn.networkLookupByName('direct-pool').isActive() == 0:
+ conn.networkLookupByName('direct-pool').create()
+ conn.networkLookupByName('direct-pool').setAutostart(1)
+
+ #check if the defined dNIC pool didn't change
+ dpool = conn.networkLookupByName('direct-pool')
+ definedNics = []
+ for i in dpool.split():
+ if 'dev=' in i:
+ definedNics.append(str(i.split('=')[1].split('/')[0].strip("'")))
+ #if the defined NIC pool doesn't match the usable NIC list, recreate the network
+ if set(definedNics) != set(getUsableNics()):
+ conn.networkLookupByName('direct-pool').destroy()
+ conn.networkLookupByName('direct-pool').undefine()
+ createDirectPool(conn)
+
+ if 'direct-pool' not in conn.listNetworks():
+ createDirectPool(conn)
+
+ except:
+ sys.stderr.write('vmfex: [unexpected error]: %s\n' % traceback.format_exc())
+ sys.exit(2)
+
diff --git a/vdsm_hooks/vmfex/before_vm_start.py b/vdsm_hooks/vmfex/before_vm_start.py
new file mode 100755
index 0000000..9002e3f
--- /dev/null
+++ b/vdsm_hooks/vmfex/before_vm_start.py
@@ -0,0 +1,188 @@
+#!/usr/bin/python
+
+import os
+import subprocess
+import sys
+import xml
+import hooking
+import traceback
+from xml.dom import minidom
+import libvirtconnection
+
+'''
+Placed in before_vm_start
+
+vmfex hook:
+Add Cisco VM-FEX Port Profile to Virtual Machine
+Sample:
+ vmfex=NIC1:profile1,NIC2:profile2...
+
+ Will add 2 virtual nics attached to profile1 and profile2 using the vnic
+ MAC addresses specified, replacing the actual NICs assigned to the VM.
+ The mapping is by order of NIC<number> in the parameters, mapped to the
+ order of the "interface" elements in the devices of the VM xml, as well
+ as the NICs defined for a VM in the RHEV-M admin GUI.
+
+Libvirt internals:
+Replace the existing interface xml:
+ <interface type="bridge">
+ <mac address="<mac>"/>
+ <model type="virtio"/>
+ <source bridge="<logical network>"/>
+ </interface>
+
+with the following interface xml:
+ <interface type='network'>
+ <mac address='<mac>'/>
+ <source network='direct-pool'/>
+ <virtualport type='802.1Qbh'>
+ <parameters profileid='<Port Profile>'/>
+ </virtualport>
+ <model type='virtio'/>
+ </interface>
+
+Dynamic network with libvirt (define a NIC pool, so libvirt can assign VMs to NICs dynamically):
+
+ <network>
+ <name>direct-pool</name>
+ <forward mode="passthrough">
+ <interface dev="eth3"/>
+ <interface dev="eth4"/>
+ <interface dev="eth5"/>
+ <interface dev="eth6"/>
+ <interface dev="eth7"/>
+ <interface dev="eth8"/>
+ <interface dev="eth9"/>
+ <interface dev="eth10"/>
+ <interface dev="eth11"/>
+ </forward>
+ </network>
+
+Using libvirt, the network is defined like this:
+
+ virsh net-define /tmp/direct-pool.xml
+ virsh net-start direct-pool
+ virsh net-autostart direct-pool
+
+(where /tmp/direct-pool.xml contains the xml above)
+
+(everything else is autogenerated, and shouldn't be specified
+when defining a guest (but whatever is there after definition
+should be left in place, e.g. the PCI address)). Note that these
+interface definitions are completely static - you never need to modify
+them due to migration, or starting up/shutting down the guest.
+
+'''
+
+def getUsableNics():
+ # Scan localhost for physical NICs and return list of physical nics
+ # that have all zeroes MAC
+ # Example ['eth0','eth1']
+ nics = []
+ cmd = "find /sys/devices/pci* | grep '/net/' |grep address"
+ p = subprocess.Popen(cmd,stdout=subprocess.PIPE,shell=True)
+ s = p.stdout.read().split()
+ for i in s:
+ mac = open(i).read().strip()
+ if mac == '00:00:00:00:00:00':
+ nics.append(i.split('/')[-2])
+ return nics
+
+def enumNics(devices):
+ # Given the domxml of VM devices, return the NIC elements numbered 1 through len()+1
+ vnicmap = {}
+ i = 1
+ for interface in devices.getElementsByTagName('interface'):
+ vnicmap[i] = interface
+ i += 1
+ return vnicmap
+
+def createDirectPool(conn):
+ xmlstr = """<network> \n <name>direct-pool</name> \n <forward mode="passthrough"> \n """
+ for i in getUsableNics():
+ s = '<interface dev="' + str(i) + '"/> \n'
+ xmlstr += s
+
+ xmlstr += """ </forward> \n </network> """
+ conn.networkDefineXML(xmlstr)
+ dpool = conn.networkLookupByName('direct-pool')
+ dpool.setAutostart(1)
+ dpool.create()
+
+
+
+if os.environ.has_key('vmfex'):
+ try:
+ #connect to libvirtd
+ conn = libvirtconnection.get('qemu:///system')
+
+ #check for running VMs. If there are VMs running, skip creating a dNIC pool
+ if len(conn.listDomainsID()) == 0:
+ #check if direct-pool is created
+ if 'direct-pool' not in conn.listNetworks():
+ createDirectPool(conn)
+ else:
+ if conn.networkLookupByName('direct-pool').isActive() == 0:
+ conn.networkLookupByName('direct-pool').create()
+ conn.networkLookupByName('direct-pool').setAutostart(1)
+
+ #check if the defined dNIC pool didn't change
+ dpool = conn.networkLookupByName('direct-pool')
+ definedNics = []
+ for i in dpool.split():
+ if 'dev=' in i:
+ definedNics.append(str(i.split('=')[1].split('/')[0].strip("'")))
+ #if the defined NIC pool doesn't match the usable NIC list, recreate the network
+ if set(definedNics) != set(getUsableNics()):
+ conn.networkLookupByName('direct-pool').destroy()
+ conn.networkLookupByName('direct-pool').undefine()
+ createDirectPool(conn)
+
+ if 'direct-pool' not in conn.listNetworks():
+ createDirectPool(conn)
+
+ except:
+ pass
+
+
+ try:
+ #Get the vmfex line
+ vmfex = os.environ['vmfex']
+
+ #Get the VM's xml definition
+ domxml = hooking.read_domxml()
+ devices = domxml.getElementsByTagName('devices')[0]
+ vnicmap = enumNics(devices)
+
+ counter = 0
+
+ for entry in vmfex.split(','):
+ sys.stderr.write('vmfex: adding interface to profile: %s\n' % entry)
+ try:
+ nicnum = int(entry.split(':')[0][3:])
+ profile = entry.split(':')[1]
+ mynic = vnicmap[nicnum]
+ #replace type="bridge" with "network"
+ mynic.setAttribute('type','network')
+
+ source = mynic.getElementsByTagName('source')[0]
+ source.removeAttribute('bridge')
+ source.setAttribute('network', 'direct-pool')
+
+ virtualport = domxml.createElement('virtualport')
+ virtualport.setAttribute('type', '802.1Qbh')
+ mynic.appendChild(virtualport)
+
+ parameters = domxml.createElement('parameters')
+ parameters.setAttribute('profileid', profile)
+ virtualport.appendChild(parameters)
+
+ except:
+ sys.stderr.write('vmfex: Error in vmfex custom property line: %s\n' % entry)
+ sys.exit(2)
+
+ hooking.write_domxml(domxml)
+ except:
+ sys.stderr.write('vmfex: [unexpected error]: %s\n' % traceback.format_exc())
+ sys.exit(2)
+
--
To view, visit http://gerrit.ovirt.org/7547
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I45a7fa46919bb39a648dff190c40618395990e91
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Dan Yasny <dyasny at gmail.com>
More information about the vdsm-patches
mailing list