Merge "Refactor Xen Vif drivers. Fixes LP907850"
This commit is contained in:
@@ -20,11 +20,15 @@
|
|||||||
|
|
||||||
class VIFDriver(object):
|
class VIFDriver(object):
|
||||||
"""Abstract class that defines generic interfaces for all VIF drivers."""
|
"""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."""
|
"""Plug VIF into network."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def unplug(self, instance, network, mapping):
|
def unplug(self, instance, network, mapping, **kwargs):
|
||||||
"""Unplug VIF from network."""
|
"""Unplug VIF from network."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
@@ -23,6 +23,7 @@ from nova import flags
|
|||||||
from nova import log as logging
|
from nova import log as logging
|
||||||
from nova.virt.vif import VIFDriver
|
from nova.virt.vif import VIFDriver
|
||||||
from nova.virt.xenapi.network_utils import NetworkHelper
|
from nova.virt.xenapi.network_utils import NetworkHelper
|
||||||
|
from nova.virt.xenapi.vm_utils import VMHelper
|
||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
flags.DEFINE_string('xenapi_ovs_integration_bridge', 'xapi1',
|
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")
|
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."""
|
"""VIF Driver for XenAPI that uses XenAPI to create Networks."""
|
||||||
|
|
||||||
def plug(self, xenapi_session, vm_ref, instance, device, network,
|
def plug(self, instance, network, mapping, vm_ref=None, device=None):
|
||||||
network_mapping):
|
if not vm_ref:
|
||||||
if network_mapping.get('should_create_vlan'):
|
vm_ref = VMHelper.lookup(self._session, instance.name)
|
||||||
network_ref = self.ensure_vlan_bridge(xenapi_session, network)
|
if not device:
|
||||||
|
device = 0
|
||||||
|
|
||||||
|
if mapping.get('should_create_vlan'):
|
||||||
|
network_ref = self._ensure_vlan_bridge(network)
|
||||||
else:
|
else:
|
||||||
network_ref = NetworkHelper.find_network_with_bridge(
|
network_ref = NetworkHelper.find_network_with_bridge(
|
||||||
xenapi_session, network['bridge'])
|
self._session, network['bridge'])
|
||||||
vif_rec = {}
|
vif_rec = {}
|
||||||
vif_rec['device'] = str(device)
|
vif_rec['device'] = str(device)
|
||||||
vif_rec['network'] = network_ref
|
vif_rec['network'] = network_ref
|
||||||
vif_rec['VM'] = vm_ref
|
vif_rec['VM'] = vm_ref
|
||||||
vif_rec['MAC'] = network_mapping['mac']
|
vif_rec['MAC'] = mapping['mac']
|
||||||
vif_rec['MTU'] = '1500'
|
vif_rec['MTU'] = '1500'
|
||||||
vif_rec['other_config'] = {}
|
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_type'] = "ratelimit"
|
||||||
vif_rec['qos_algorithm_params'] = \
|
vif_rec['qos_algorithm_params'] = \
|
||||||
{"kbps": str(network_mapping['rxtx_cap'] * 1024)}
|
{"kbps": str(mapping['rxtx_cap'] * 1024)}
|
||||||
else:
|
else:
|
||||||
vif_rec['qos_algorithm_type'] = ""
|
vif_rec['qos_algorithm_type'] = ""
|
||||||
vif_rec['qos_algorithm_params'] = {}
|
vif_rec['qos_algorithm_params'] = {}
|
||||||
return vif_rec
|
return vif_rec
|
||||||
|
|
||||||
def ensure_vlan_bridge(self, xenapi_session, network):
|
def _ensure_vlan_bridge(self, network):
|
||||||
"""Ensure that a VLAN bridge exists"""
|
"""Ensure that a VLAN bridge exists"""
|
||||||
|
|
||||||
vlan_num = network['vlan']
|
vlan_num = network['vlan']
|
||||||
@@ -66,7 +76,7 @@ class XenAPIBridgeDriver(VIFDriver):
|
|||||||
# Check whether bridge already exists
|
# Check whether bridge already exists
|
||||||
# Retrieve network whose name_label is "bridge"
|
# Retrieve network whose name_label is "bridge"
|
||||||
network_ref = NetworkHelper.find_network_with_name_label(
|
network_ref = NetworkHelper.find_network_with_name_label(
|
||||||
xenapi_session, bridge)
|
self._session, bridge)
|
||||||
if network_ref is None:
|
if network_ref is None:
|
||||||
# If bridge does not exists
|
# If bridge does not exists
|
||||||
# 1 - create network
|
# 1 - create network
|
||||||
@@ -74,34 +84,34 @@ class XenAPIBridgeDriver(VIFDriver):
|
|||||||
network_rec = {'name_label': bridge,
|
network_rec = {'name_label': bridge,
|
||||||
'name_description': description,
|
'name_description': description,
|
||||||
'other_config': {}}
|
'other_config': {}}
|
||||||
network_ref = xenapi_session.call_xenapi('network.create',
|
network_ref = self._session.call_xenapi('network.create',
|
||||||
network_rec)
|
network_rec)
|
||||||
# 2 - find PIF for VLAN NOTE(salvatore-orlando): using double
|
# 2 - find PIF for VLAN NOTE(salvatore-orlando): using double
|
||||||
# quotes inside single quotes as xapi filter only support
|
# quotes inside single quotes as xapi filter only support
|
||||||
# tokens in double quotes
|
# tokens in double quotes
|
||||||
expr = 'field "device" = "%s" and \
|
expr = 'field "device" = "%s" and \
|
||||||
field "VLAN" = "-1"' % bridge_interface
|
field "VLAN" = "-1"' % bridge_interface
|
||||||
pifs = xenapi_session.call_xenapi('PIF.get_all_records_where',
|
pifs = self._session.call_xenapi('PIF.get_all_records_where',
|
||||||
expr)
|
expr)
|
||||||
pif_ref = None
|
pif_ref = None
|
||||||
# Multiple PIF are ok: we are dealing with a pool
|
# Multiple PIF are ok: we are dealing with a pool
|
||||||
if len(pifs) == 0:
|
if len(pifs) == 0:
|
||||||
raise Exception(_('Found no PIF for device %s') % \
|
raise Exception(_('Found no PIF for device %s') % \
|
||||||
bridge_interface)
|
bridge_interface)
|
||||||
for pif_ref in pifs.keys():
|
for pif_ref in pifs.keys():
|
||||||
xenapi_session.call_xenapi('VLAN.create',
|
self._session.call_xenapi('VLAN.create',
|
||||||
pif_ref,
|
pif_ref,
|
||||||
str(vlan_num),
|
str(vlan_num),
|
||||||
network_ref)
|
network_ref)
|
||||||
else:
|
else:
|
||||||
# Check VLAN tag is appropriate
|
# Check VLAN tag is appropriate
|
||||||
network_rec = xenapi_session.call_xenapi('network.get_record',
|
network_rec = self._session.call_xenapi('network.get_record',
|
||||||
network_ref)
|
network_ref)
|
||||||
# Retrieve PIFs from network
|
# Retrieve PIFs from network
|
||||||
for pif_ref in network_rec['PIFs']:
|
for pif_ref in network_rec['PIFs']:
|
||||||
# Retrieve VLAN from PIF
|
# Retrieve VLAN from PIF
|
||||||
pif_rec = xenapi_session.call_xenapi('PIF.get_record',
|
pif_rec = self._session.call_xenapi('PIF.get_record',
|
||||||
pif_ref)
|
pif_ref)
|
||||||
pif_vlan = int(pif_rec['VLAN'])
|
pif_vlan = int(pif_rec['VLAN'])
|
||||||
# Raise an exception if VLAN != vlan_num
|
# Raise an exception if VLAN != vlan_num
|
||||||
if pif_vlan != vlan_num:
|
if pif_vlan != vlan_num:
|
||||||
@@ -116,27 +126,32 @@ class XenAPIBridgeDriver(VIFDriver):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class XenAPIOpenVswitchDriver(VIFDriver):
|
class XenAPIOpenVswitchDriver(XenVIFDriver):
|
||||||
"""VIF driver for Open vSwitch with XenAPI."""
|
"""VIF driver for Open vSwitch with XenAPI."""
|
||||||
|
|
||||||
def plug(self, xenapi_session, vm_ref, instance, device, network,
|
def plug(self, instance, network, mapping, vm_ref=None, device=None):
|
||||||
network_mapping):
|
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
|
# with OVS model, always plug into an OVS integration bridge
|
||||||
# that is already created
|
# 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)
|
FLAGS.xenapi_ovs_integration_bridge)
|
||||||
vif_rec = {}
|
vif_rec = {}
|
||||||
vif_rec['device'] = str(device)
|
vif_rec['device'] = str(device)
|
||||||
vif_rec['network'] = network_ref
|
vif_rec['network'] = network_ref
|
||||||
vif_rec['VM'] = vm_ref
|
vif_rec['VM'] = vm_ref
|
||||||
vif_rec['MAC'] = network_mapping['mac']
|
vif_rec['MAC'] = mapping['mac']
|
||||||
vif_rec['MTU'] = '1500'
|
vif_rec['MTU'] = '1500'
|
||||||
vif_rec['qos_algorithm_type'] = ""
|
vif_rec['qos_algorithm_type'] = ""
|
||||||
vif_rec['qos_algorithm_params'] = {}
|
vif_rec['qos_algorithm_params'] = {}
|
||||||
# OVS on the hypervisor monitors this key and uses it to
|
# OVS on the hypervisor monitors this key and uses it to
|
||||||
# set the iface-id attribute
|
# set the iface-id attribute
|
||||||
vif_rec['other_config'] = \
|
vif_rec['other_config'] = \
|
||||||
{"nicira-iface-id": network_mapping['vif_uuid']}
|
{"nicira-iface-id": mapping['vif_uuid']}
|
||||||
return vif_rec
|
return vif_rec
|
||||||
|
|
||||||
def unplug(self, instance, network, mapping):
|
def unplug(self, instance, network, mapping):
|
||||||
|
@@ -94,7 +94,8 @@ class VMOps(object):
|
|||||||
self._session = session
|
self._session = session
|
||||||
self.poll_rescue_last_ran = None
|
self.poll_rescue_last_ran = None
|
||||||
VMHelper.XenAPI = self.XenAPI
|
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
|
self._product_version = product_version
|
||||||
|
|
||||||
def list_instances(self):
|
def list_instances(self):
|
||||||
@@ -1429,8 +1430,8 @@ class VMOps(object):
|
|||||||
self._session.call_xenapi("VM.get_record", vm_ref)
|
self._session.call_xenapi("VM.get_record", vm_ref)
|
||||||
|
|
||||||
for device, (network, info) in enumerate(network_info):
|
for device, (network, info) in enumerate(network_info):
|
||||||
vif_rec = self.vif_driver.plug(self._session,
|
vif_rec = self.vif_driver.plug(instance, network, info,
|
||||||
vm_ref, instance, device, network, info)
|
vm_ref=vm_ref, device=device)
|
||||||
network_ref = vif_rec['network']
|
network_ref = vif_rec['network']
|
||||||
LOG.debug(_('Creating VIF for VM %(vm_ref)s,' \
|
LOG.debug(_('Creating VIF for VM %(vm_ref)s,' \
|
||||||
' network %(network_ref)s.') % locals())
|
' network %(network_ref)s.') % locals())
|
||||||
@@ -1440,8 +1441,8 @@ class VMOps(object):
|
|||||||
|
|
||||||
def plug_vifs(self, instance, network_info):
|
def plug_vifs(self, instance, network_info):
|
||||||
"""Set up VIF networking on the host."""
|
"""Set up VIF networking on the host."""
|
||||||
for (network, mapping) in network_info:
|
for device, (network, mapping) in enumerate(network_info):
|
||||||
self.vif_driver.plug(self._session, instance, network, mapping)
|
self.vif_driver.plug(instance, network, mapping, device=device)
|
||||||
|
|
||||||
def unplug_vifs(self, instance, network_info):
|
def unplug_vifs(self, instance, network_info):
|
||||||
if network_info:
|
if network_info:
|
||||||
|
Reference in New Issue
Block a user