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:
parent
5bcaecdc7d
commit
06e5909d05
|
@ -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()
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue