Refactor Xen Vif drivers. Fixes LP907850

* Allows Vif subclasses to have an __init__ for setting up state
* Allows Vif subclasses to pass arbitrary kwargs to plug/unplug should
  they require more than what the interface specifies

Change-Id: I816aa1537d21005d4332af3477d9fd12f177f326
This commit is contained in:
Jason Kölker 2011-12-22 14:26:51 -06:00
parent 5bcaecdc7d
commit 06e5909d05
3 changed files with 56 additions and 36 deletions

View File

@ -20,11 +20,15 @@
class VIFDriver(object):
"""Abstract class that defines generic interfaces for all VIF drivers."""
def __init__(self, **kwargs):
# NOTE(jkoelker) __init__ is here so subclasses *could* take
# advantage of any kwargs should they need to
pass
def plug(self, instance, network, mapping):
def plug(self, instance, network, mapping, **kwargs):
"""Plug VIF into network."""
raise NotImplementedError()
def unplug(self, instance, network, mapping):
def unplug(self, instance, network, mapping, **kwargs):
"""Unplug VIF from network."""
raise NotImplementedError()

View File

@ -23,6 +23,7 @@ from nova import flags
from nova import log as logging
from nova.virt.vif import VIFDriver
from nova.virt.xenapi.network_utils import NetworkHelper
from nova.virt.xenapi.vm_utils import VMHelper
FLAGS = flags.FLAGS
flags.DEFINE_string('xenapi_ovs_integration_bridge', 'xapi1',
@ -31,33 +32,42 @@ flags.DEFINE_string('xenapi_ovs_integration_bridge', 'xapi1',
LOG = logging.getLogger("nova.virt.xenapi.vif")
class XenAPIBridgeDriver(VIFDriver):
class XenVIFDriver(VIFDriver):
def __init__(self, xenapi_session):
self._session = xenapi_session
class XenAPIBridgeDriver(XenVIFDriver):
"""VIF Driver for XenAPI that uses XenAPI to create Networks."""
def plug(self, xenapi_session, vm_ref, instance, device, network,
network_mapping):
if network_mapping.get('should_create_vlan'):
network_ref = self.ensure_vlan_bridge(xenapi_session, network)
def plug(self, instance, network, mapping, vm_ref=None, device=None):
if not vm_ref:
vm_ref = VMHelper.lookup(self._session, instance.name)
if not device:
device = 0
if mapping.get('should_create_vlan'):
network_ref = self._ensure_vlan_bridge(network)
else:
network_ref = NetworkHelper.find_network_with_bridge(
xenapi_session, network['bridge'])
self._session, network['bridge'])
vif_rec = {}
vif_rec['device'] = str(device)
vif_rec['network'] = network_ref
vif_rec['VM'] = vm_ref
vif_rec['MAC'] = network_mapping['mac']
vif_rec['MAC'] = mapping['mac']
vif_rec['MTU'] = '1500'
vif_rec['other_config'] = {}
if "rxtx_cap" in network_mapping:
if "rxtx_cap" in mapping:
vif_rec['qos_algorithm_type'] = "ratelimit"
vif_rec['qos_algorithm_params'] = \
{"kbps": str(network_mapping['rxtx_cap'] * 1024)}
{"kbps": str(mapping['rxtx_cap'] * 1024)}
else:
vif_rec['qos_algorithm_type'] = ""
vif_rec['qos_algorithm_params'] = {}
return vif_rec
def ensure_vlan_bridge(self, xenapi_session, network):
def _ensure_vlan_bridge(self, network):
"""Ensure that a VLAN bridge exists"""
vlan_num = network['vlan']
@ -66,7 +76,7 @@ class XenAPIBridgeDriver(VIFDriver):
# Check whether bridge already exists
# Retrieve network whose name_label is "bridge"
network_ref = NetworkHelper.find_network_with_name_label(
xenapi_session, bridge)
self._session, bridge)
if network_ref is None:
# If bridge does not exists
# 1 - create network
@ -74,34 +84,34 @@ class XenAPIBridgeDriver(VIFDriver):
network_rec = {'name_label': bridge,
'name_description': description,
'other_config': {}}
network_ref = xenapi_session.call_xenapi('network.create',
network_rec)
network_ref = self._session.call_xenapi('network.create',
network_rec)
# 2 - find PIF for VLAN NOTE(salvatore-orlando): using double
# quotes inside single quotes as xapi filter only support
# tokens in double quotes
expr = 'field "device" = "%s" and \
field "VLAN" = "-1"' % bridge_interface
pifs = xenapi_session.call_xenapi('PIF.get_all_records_where',
expr)
pifs = self._session.call_xenapi('PIF.get_all_records_where',
expr)
pif_ref = None
# Multiple PIF are ok: we are dealing with a pool
if len(pifs) == 0:
raise Exception(_('Found no PIF for device %s') % \
bridge_interface)
for pif_ref in pifs.keys():
xenapi_session.call_xenapi('VLAN.create',
pif_ref,
str(vlan_num),
network_ref)
self._session.call_xenapi('VLAN.create',
pif_ref,
str(vlan_num),
network_ref)
else:
# Check VLAN tag is appropriate
network_rec = xenapi_session.call_xenapi('network.get_record',
network_ref)
network_rec = self._session.call_xenapi('network.get_record',
network_ref)
# Retrieve PIFs from network
for pif_ref in network_rec['PIFs']:
# Retrieve VLAN from PIF
pif_rec = xenapi_session.call_xenapi('PIF.get_record',
pif_ref)
pif_rec = self._session.call_xenapi('PIF.get_record',
pif_ref)
pif_vlan = int(pif_rec['VLAN'])
# Raise an exception if VLAN != vlan_num
if pif_vlan != vlan_num:
@ -116,27 +126,32 @@ class XenAPIBridgeDriver(VIFDriver):
pass
class XenAPIOpenVswitchDriver(VIFDriver):
class XenAPIOpenVswitchDriver(XenVIFDriver):
"""VIF driver for Open vSwitch with XenAPI."""
def plug(self, xenapi_session, vm_ref, instance, device, network,
network_mapping):
def plug(self, instance, network, mapping, vm_ref=None, device=None):
if not vm_ref:
vm_ref = VMHelper.lookup(self._session, instance.name)
if not device:
device = 0
# with OVS model, always plug into an OVS integration bridge
# that is already created
network_ref = NetworkHelper.find_network_with_bridge(xenapi_session,
network_ref = NetworkHelper.find_network_with_bridge(self._session,
FLAGS.xenapi_ovs_integration_bridge)
vif_rec = {}
vif_rec['device'] = str(device)
vif_rec['network'] = network_ref
vif_rec['VM'] = vm_ref
vif_rec['MAC'] = network_mapping['mac']
vif_rec['MAC'] = mapping['mac']
vif_rec['MTU'] = '1500'
vif_rec['qos_algorithm_type'] = ""
vif_rec['qos_algorithm_params'] = {}
# OVS on the hypervisor monitors this key and uses it to
# set the iface-id attribute
vif_rec['other_config'] = \
{"nicira-iface-id": network_mapping['vif_uuid']}
{"nicira-iface-id": mapping['vif_uuid']}
return vif_rec
def unplug(self, instance, network, mapping):

View File

@ -94,7 +94,8 @@ class VMOps(object):
self._session = session
self.poll_rescue_last_ran = None
VMHelper.XenAPI = self.XenAPI
self.vif_driver = utils.import_object(FLAGS.xenapi_vif_driver)
vif_impl = utils.import_class(FLAGS.xenapi_vif_driver)
self.vif_driver = vif_impl(xenapi_session=self._session)
self._product_version = product_version
def list_instances(self):
@ -1429,8 +1430,8 @@ class VMOps(object):
self._session.call_xenapi("VM.get_record", vm_ref)
for device, (network, info) in enumerate(network_info):
vif_rec = self.vif_driver.plug(self._session,
vm_ref, instance, device, network, info)
vif_rec = self.vif_driver.plug(instance, network, info,
vm_ref=vm_ref, device=device)
network_ref = vif_rec['network']
LOG.debug(_('Creating VIF for VM %(vm_ref)s,' \
' network %(network_ref)s.') % locals())
@ -1440,8 +1441,8 @@ class VMOps(object):
def plug_vifs(self, instance, network_info):
"""Set up VIF networking on the host."""
for (network, mapping) in network_info:
self.vif_driver.plug(self._session, instance, network, mapping)
for device, (network, mapping) in enumerate(network_info):
self.vif_driver.plug(instance, network, mapping, device=device)
def unplug_vifs(self, instance, network_info):
if network_info: