summaryrefslogtreecommitdiff
path: root/nova/virt/powervm/vif.py
diff options
context:
space:
mode:
Diffstat (limited to 'nova/virt/powervm/vif.py')
-rw-r--r--nova/virt/powervm/vif.py373
1 files changed, 0 insertions, 373 deletions
diff --git a/nova/virt/powervm/vif.py b/nova/virt/powervm/vif.py
deleted file mode 100644
index 8ab591a15d..0000000000
--- a/nova/virt/powervm/vif.py
+++ /dev/null
@@ -1,373 +0,0 @@
-# Copyright 2016, 2017 IBM Corp.
-#
-# All Rights Reserved.
-#
-# 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.
-
-import abc
-
-from oslo_log import log
-from oslo_serialization import jsonutils
-from oslo_utils import excutils
-from oslo_utils import importutils
-from pypowervm import exceptions as pvm_ex
-from pypowervm.tasks import cna as pvm_cna
-from pypowervm.tasks import partition as pvm_par
-from pypowervm.wrappers import event as pvm_evt
-
-from nova import exception
-from nova.network import model as network_model
-from nova.virt.powervm import vm
-
-LOG = log.getLogger(__name__)
-
-NOVALINK_VSWITCH = 'NovaLinkVEABridge'
-
-# Provider tag for custom events from this module
-EVENT_PROVIDER_ID = 'NOVA_PVM_VIF'
-
-VIF_TYPE_PVM_SEA = 'pvm_sea'
-VIF_TYPE_PVM_OVS = 'ovs'
-VIF_MAPPING = {VIF_TYPE_PVM_SEA:
- 'nova.virt.powervm.vif.PvmSeaVifDriver',
- VIF_TYPE_PVM_OVS:
- 'nova.virt.powervm.vif.PvmOvsVifDriver'}
-
-
-def _build_vif_driver(adapter, instance, vif):
- """Returns the appropriate VIF Driver for the given VIF.
-
- :param adapter: The pypowervm adapter API interface.
- :param instance: The nova instance.
- :param vif: The virtual interface.
- :return: The appropriate PvmVifDriver for the VIF.
- """
- if vif.get('type') is None:
- LOG.exception("Failed to build vif driver. Missing vif type.",
- instance=instance)
- raise exception.VirtualInterfacePlugException()
-
- # Check the type to the implementations
- if VIF_MAPPING.get(vif['type']):
- return importutils.import_object(
- VIF_MAPPING.get(vif['type']), adapter, instance)
-
- # No matching implementation, raise error.
- LOG.exception("Failed to build vif driver. Invalid vif type provided.",
- instance=instance)
- raise exception.VirtualInterfacePlugException()
-
-
-def _push_vif_event(adapter, action, vif_w, instance, vif_type):
- """Push a custom event to the REST server for a vif action (plug/unplug).
-
- This event prompts the neutron agent to mark the port up or down. It is
- consumed by custom neutron agents (e.g. Shared Ethernet Adapter)
-
- :param adapter: The pypowervm adapter.
- :param action: The action taken on the vif - either 'plug' or 'unplug'
- :param vif_w: The pypowervm wrapper of the affected vif (CNA, VNIC, etc.)
- :param instance: The nova instance for the event
- :param vif_type: The type of event source (pvm_sea, ovs, bridge,
- pvm_sriov etc)
- """
- data = vif_w.href
- detail = jsonutils.dumps(dict(provider=EVENT_PROVIDER_ID, action=action,
- mac=vif_w.mac, type=vif_type))
- event = pvm_evt.Event.bld(adapter, data, detail)
- try:
- event = event.create()
- LOG.debug('Pushed custom event for consumption by neutron agent: %s',
- str(event), instance=instance)
- except Exception:
- with excutils.save_and_reraise_exception(logger=LOG):
- LOG.exception('Custom VIF event push failed. %s', str(event),
- instance=instance)
-
-
-def plug(adapter, instance, vif, new_vif=True):
- """Plugs a virtual interface (network) into a VM.
-
- :param adapter: The pypowervm adapter.
- :param instance: The nova instance object.
- :param vif: The virtual interface to plug into the instance.
- :param new_vif: (Optional, Default: True) If set, indicates that it is
- a brand new VIF. If False, it indicates that the VIF
- is already on the client but should be treated on the
- bridge.
- :return: The wrapper (CNA) representing the plugged virtual network. None
- if the vnet was not created.
- """
- vif_drv = _build_vif_driver(adapter, instance, vif)
-
- try:
- vnet_w = vif_drv.plug(vif, new_vif=new_vif)
- except pvm_ex.HttpError:
- LOG.exception('VIF plug failed for instance.', instance=instance)
- raise exception.VirtualInterfacePlugException()
- # Other exceptions are (hopefully) custom VirtualInterfacePlugException
- # generated lower in the call stack.
-
- # Push a custom event if we really plugged the vif
- if vnet_w is not None:
- _push_vif_event(adapter, 'plug', vnet_w, instance, vif['type'])
-
- return vnet_w
-
-
-def unplug(adapter, instance, vif, cna_w_list=None):
- """Unplugs a virtual interface (network) from a VM.
-
- :param adapter: The pypowervm adapter.
- :param instance: The nova instance object.
- :param vif: The virtual interface to plug into the instance.
- :param cna_w_list: (Optional, Default: None) The list of Client Network
- Adapters from pypowervm. Providing this input
- allows for an improvement in operation speed.
- """
- vif_drv = _build_vif_driver(adapter, instance, vif)
- try:
- vnet_w = vif_drv.unplug(vif, cna_w_list=cna_w_list)
- except pvm_ex.HttpError as he:
- LOG.exception('VIF unplug failed for instance', instance=instance)
- raise exception.VirtualInterfaceUnplugException(reason=he.args[0])
-
- # Push a custom event if we successfully unplugged the vif.
- if vnet_w:
- _push_vif_event(adapter, 'unplug', vnet_w, instance, vif['type'])
-
-
-class PvmVifDriver(metaclass=abc.ABCMeta):
- """Represents an abstract class for a PowerVM Vif Driver.
-
- A VIF Driver understands a given virtual interface type (network). It
- understands how to plug and unplug a given VIF for a virtual machine.
- """
-
- def __init__(self, adapter, instance):
- """Initializes a VIF Driver.
- :param adapter: The pypowervm adapter API interface.
- :param instance: The nova instance that the vif action will be run
- against.
- """
- self.adapter = adapter
- self.instance = instance
-
- @abc.abstractmethod
- def plug(self, vif, new_vif=True):
- """Plugs a virtual interface (network) into a VM.
-
- :param vif: The virtual interface to plug into the instance.
- :param new_vif: (Optional, Default: True) If set, indicates that it is
- a brand new VIF. If False, it indicates that the VIF
- is already on the client but should be treated on the
- bridge.
- :return: The new vif that was created. Only returned if new_vif is
- set to True. Otherwise None is expected.
- """
- pass
-
- def unplug(self, vif, cna_w_list=None):
- """Unplugs a virtual interface (network) from a VM.
-
- :param vif: The virtual interface to plug into the instance.
- :param cna_w_list: (Optional, Default: None) The list of Client Network
- Adapters from pypowervm. Providing this input
- allows for an improvement in operation speed.
- :return cna_w: The deleted Client Network Adapter or None if the CNA
- is not found.
- """
- # This is a default implementation that most implementations will
- # require.
-
- # Need to find the adapters if they were not provided
- if not cna_w_list:
- cna_w_list = vm.get_cnas(self.adapter, self.instance)
-
- cna_w = self._find_cna_for_vif(cna_w_list, vif)
- if not cna_w:
- LOG.warning('Unable to unplug VIF with mac %(mac)s. The VIF was '
- 'not found on the instance.',
- {'mac': vif['address']}, instance=self.instance)
- return None
-
- LOG.info('Deleting VIF with mac %(mac)s.',
- {'mac': vif['address']}, instance=self.instance)
- try:
- cna_w.delete()
- except Exception as e:
- LOG.exception('Unable to unplug VIF with mac %(mac)s.',
- {'mac': vif['address']}, instance=self.instance)
- raise exception.VirtualInterfaceUnplugException(
- reason=str(e))
- return cna_w
-
- @staticmethod
- def _find_cna_for_vif(cna_w_list, vif):
- """Finds the PowerVM CNA for a given Nova VIF.
-
- :param cna_w_list: The list of Client Network Adapter wrappers from
- pypowervm.
- :param vif: The Nova Virtual Interface (virtual network interface).
- :return: The CNA that corresponds to the VIF. None if one is not
- part of the cna_w_list.
- """
- for cna_w in cna_w_list:
- if vm.norm_mac(cna_w.mac) == vif['address']:
- return cna_w
- return None
-
-
-class PvmOvsVifDriver(PvmVifDriver):
- """The Open vSwitch VIF driver for PowerVM."""
-
- def plug(self, vif, new_vif=True):
- """Plugs a virtual interface (network) into a VM.
-
- Creates a 'peer to peer' connection between the Management partition
- hosting the Linux I/O and the client VM. There will be one trunk
- adapter for a given client adapter.
-
- The device will be 'up' on the mgmt partition.
-
- Will make sure that the trunk device has the appropriate metadata (e.g.
- port id) set on it so that the Open vSwitch agent picks it up properly.
-
- :param vif: The virtual interface to plug into the instance.
- :param new_vif: (Optional, Default: True) If set, indicates that it is
- a brand new VIF. If False, it indicates that the VIF
- is already on the client but should be treated on the
- bridge.
- :return: The new vif that was created. Only returned if new_vif is
- set to True. Otherwise None is expected.
- """
-
- # Create the trunk and client adapter.
- lpar_uuid = vm.get_pvm_uuid(self.instance)
- mgmt_uuid = pvm_par.get_this_partition(self.adapter).uuid
-
- mtu = vif['network'].get_meta('mtu')
- if 'devname' in vif:
- dev_name = vif['devname']
- else:
- dev_name = ("nic" + vif['id'])[:network_model.NIC_NAME_LEN]
-
- meta_attrs = ','.join([
- 'iface-id=%s' % (vif.get('ovs_interfaceid') or vif['id']),
- 'iface-status=active',
- 'attached-mac=%s' % vif['address'],
- 'vm-uuid=%s' % self.instance.uuid])
-
- if new_vif:
- return pvm_cna.crt_p2p_cna(
- self.adapter, None, lpar_uuid, [mgmt_uuid], NOVALINK_VSWITCH,
- crt_vswitch=True, mac_addr=vif['address'], dev_name=dev_name,
- ovs_bridge=vif['network']['bridge'],
- ovs_ext_ids=meta_attrs, configured_mtu=mtu)[0]
- else:
- # Bug : https://bugs.launchpad.net/nova-powervm/+bug/1731548
- # When a host is rebooted, something is discarding tap devices for
- # VMs deployed with OVS vif. To prevent VMs losing network
- # connectivity, this is fixed by recreating the tap devices during
- # init of the nova compute service, which will call vif plug with
- # new_vif==False.
-
- # Find the CNA for this vif.
- # TODO(esberglu) improve performance by caching VIOS wrapper(s) and
- # CNA lists (in case >1 vif per VM).
- cna_w_list = vm.get_cnas(self.adapter, self.instance)
- cna_w = self._find_cna_for_vif(cna_w_list, vif)
- if not cna_w:
- LOG.warning('Unable to plug VIF with mac %s for instance. The '
- 'VIF was not found on the instance.',
- vif['address'], instance=self.instance)
- return None
-
- # Find the corresponding trunk adapter
- trunks = pvm_cna.find_trunks(self.adapter, cna_w)
- for trunk in trunks:
- # Set MTU, OVS external ids, and OVS bridge metadata
- trunk.configured_mtu = mtu
- trunk.ovs_ext_ids = meta_attrs
- trunk.ovs_bridge = vif['network']['bridge']
- # Updating the trunk adapter will cause NovaLink to reassociate
- # the tap device.
- trunk.update()
-
- def unplug(self, vif, cna_w_list=None):
- """Unplugs a virtual interface (network) from a VM.
-
- Extends the base implementation, but before calling it will remove
- the adapter from the Open vSwitch and delete the trunk.
-
- :param vif: The virtual interface to plug into the instance.
- :param cna_w_list: (Optional, Default: None) The list of Client Network
- Adapters from pypowervm. Providing this input
- allows for an improvement in operation speed.
- :return cna_w: The deleted Client Network Adapter or None if the CNA
- is not found.
- """
- # Need to find the adapters if they were not provided
- if not cna_w_list:
- cna_w_list = vm.get_cnas(self.adapter, self.instance)
-
- # Find the CNA for this vif.
- cna_w = self._find_cna_for_vif(cna_w_list, vif)
-
- if not cna_w:
- LOG.warning('Unable to unplug VIF with mac %s for instance. The '
- 'VIF was not found on the instance.', vif['address'],
- instance=self.instance)
- return None
-
- # Find and delete the trunk adapters
- trunks = pvm_cna.find_trunks(self.adapter, cna_w)
- for trunk in trunks:
- trunk.delete()
-
- # Delete the client CNA
- return super(PvmOvsVifDriver, self).unplug(vif, cna_w_list=cna_w_list)
-
-
-class PvmSeaVifDriver(PvmVifDriver):
- """The PowerVM Shared Ethernet Adapter VIF Driver."""
-
- def plug(self, vif, new_vif=True):
- """Plugs a virtual interface (network) into a VM.
-
- This method simply creates the client network adapter into the VM.
-
- :param vif: The virtual interface to plug into the instance.
- :param new_vif: (Optional, Default: True) If set, indicates that it is
- a brand new VIF. If False, it indicates that the VIF
- is already on the client but should be treated on the
- bridge.
- :return: The new vif that was created. Only returned if new_vif is
- set to True. Otherwise None is expected.
- """
- # Do nothing if not a new VIF
- if not new_vif:
- return None
-
- lpar_uuid = vm.get_pvm_uuid(self.instance)
-
- # CNA's require a VLAN. The networking-powervm neutron agent puts this
- # in the vif details.
- vlan = int(vif['details']['vlan'])
-
- LOG.debug("Creating SEA-based VIF with VLAN %s", str(vlan),
- instance=self.instance)
- cna_w = pvm_cna.crt_cna(self.adapter, None, lpar_uuid, vlan,
- mac_addr=vif['address'])
-
- return cna_w