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. """ # 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 %(mac)s for. The VIF ' 'was not found on the instance.', {'mac': vif['address']}, instance=self.instance) return None # Find and delete the trunk adapters trunks = pvm_cna.find_trunks(self.adapter, cna_w) dev = self.get_trunk_dev_name(vif) linux_net.delete_ovs_vif_port(vif['network']['bridge'], dev) for trunk in trunks: trunk.delete() # Now delete the client CNA return super(PvmOvsVifDriver, self).unplug(vif, cna_w_list=cna_w_list)
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. """ # 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(_LW('Unable to unplug VIF with mac %(mac)s for ' 'instance %(inst)s. The VIF was not found on ' 'the instance.'), {'mac': vif['address'], 'inst': self.instance.name}) return None # Find and delete the trunk adapters trunks = pvm_cna.find_trunks(self.adapter, cna_w) dev = self.get_trunk_dev_name(vif) linux_net.delete_ovs_vif_port(vif['network']['bridge'], dev) for trunk in trunks: trunk.delete() # Now delete the client CNA return super(PvmOvsVifDriver, self).unplug(vif, cna_w_list=cna_w_list)
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)
def unplug(self, vif, cna_w_list=None): """Unplugs a virtual interface (network) from a VM. Extends the base implementation, but before invoking it will remove itself from the bridge it is connected to and delete the corresponding trunk device on the mgmt partition. :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. """ # 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(_LW('Unable to unplug VIF with mac %(mac)s for ' 'instance %(inst)s. The VIF was not found on ' 'the instance.'), { 'mac': vif['address'], 'inst': self.instance.name }, instance=self.instance) return None # Find and delete the trunk adapters trunks = pvm_cna.find_trunks(self.adapter, cna_w) dev_name = self.get_trunk_dev_name(vif) utils.execute('ip', 'link', 'set', dev_name, 'down', run_as_root=True) try: utils.execute('brctl', 'delif', vif['network']['bridge'], dev_name, run_as_root=True) except Exception as e: LOG.warning(_LW('Unable to delete device %(dev_name)s from bridge ' '%(bridge)s. Error: %(error)s'), { 'dev_name': dev_name, 'bridge': vif['network']['bridge'], 'error': e.message }, instance=self.instance) for trunk in trunks: trunk.delete() # Now delete the client CNA return super(PvmLBVifDriver, self).unplug(vif, cna_w_list=cna_w_list)
def unplug(self, vif, cna_w_list=None): """Unplugs a virtual interface (network) from a VM. This will remove the adapter from the Open vSwitch and delete the trunk adapters. :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() # Now delete the client CNA LOG.info('Deleting VIF with mac %s for instance.', vif['address'], instance=self.instance) try: cna_w.delete() except Exception as e: LOG.error('Unable to unplug VIF with mac %s for instance.', vif['address'], instance=self.instance) raise exception.VirtualInterfaceUnplugException( reason=six.text_type(e)) return cna_w
def test_find_trunks(self, mock_vios_get, mock_get_mgmt, mock_find_trunk): # Mocked responses can be simple, since they are just fed into the # _find_trunk_on_lpar mock_vios_get.return_value = [mock.MagicMock(), mock.MagicMock()] mock_get_mgmt.return_value = mock.MagicMock() # The responses back from the find trunk. Make it an odd trunk # priority ordering to make sure we sort properly v1 = mock.Mock(trunk_pri=3) c1, c2 = mock.Mock(trunk_pri=1), mock.Mock(trunk_pri=2) mock_find_trunk.side_effect = [v1, c1, c2] # Invoke the method. resp = cna.find_trunks(self.adpt, mock.Mock(pvid=2)) # Make sure four calls to the find trunk self.assertEqual(3, mock_find_trunk.call_count) # Order of the response is important. Should be based off of trunk # priority self.assertEqual([c1, c2, v1], resp)
def pre_live_migrate_at_source(self, vif): """Performs the pre live migrate on the source host. This is executed directly before the migration is started on the source host. :param vif: The virtual interface that will be migrated. This may be called network_info in other portions of the code. :return: The list of TrunkAdapter's on the source that are hosting the VM's vif. Should only return data if those trunks should be deleted after the migration. """ # Right before the migration, we need to find the trunk on the source # host. mac = pvm_util.sanitize_mac_for_api(vif['address']) cna_w = pvm_net.CNA.search(self.adapter, parent_type=pvm_lpar.LPAR.schema_type, parent_uuid=vm.get_pvm_uuid(self.instance), one_result=True, mac=mac) return pvm_cna.find_trunks(self.adapter, cna_w)
def unplug(self, vif, cna_w_list=None): """Unplugs a virtual interface (network) from a VM. Extends the base implementation, but before invoking it will remove itself from the bridge it is connected to and delete the corresponding trunk device on the mgmt partition. :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. """ # 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(_LW('Unable to unplug VIF with mac %(mac)s for ' 'instance %(inst)s. The VIF was not found on ' 'the instance.'), {'mac': vif['address'], 'inst': self.instance.name}) return None # Find and delete the trunk adapters trunks = pvm_cna.find_trunks(self.adapter, cna_w) dev_name = self.get_trunk_dev_name(vif) utils.execute('ip', 'link', 'set', dev_name, 'down', run_as_root=True) utils.execute('brctl', 'delif', vif['network']['bridge'], dev_name, run_as_root=True) for trunk in trunks: trunk.delete() # Now delete the client CNA return super(PvmLBVifDriver, self).unplug(vif, cna_w_list=cna_w_list)
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 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 plug(self, vif, slot_num, new_vif=True): """Plugs a virtual interface (network) into a VM. Extends the Lio implementation. Will make sure that the trunk device has the appropriate metadata (ex. 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 slot_num: Which slot number to plug the VIF into. May be None. :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. """ lpar_uuid = vm.get_pvm_uuid(self.instance) mgmt_uuid = pvm_par.get_mgmt_partition(self.adapter).uuid # There will only be one trunk wrap, as we have created with just # the mgmt lpar. Next step is to connect to the OVS. mtu = vif['network'].get_meta('mtu') dev_name = _get_trunk_dev_name(vif) meta_attrs = PvmMetaAttrs(vif, self.instance) if new_vif: # Create the trunk and client adapter. return pvm_cna.crt_p2p_cna( self.adapter, self.host_uuid, lpar_uuid, [mgmt_uuid], CONF.powervm.pvm_vswitch_for_novalink_io, crt_vswitch=True, mac_addr=vif['address'], dev_name=dev_name, slot_num=slot_num, ovs_bridge=vif['network']['bridge'], ovs_ext_ids=str(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(svenkat) 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) # 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 # TODO(svenkat) set_parm_value calls should be replaced once # pypowervm supports setting these values directly. trunk.set_parm_value('ConfiguredMTU', mtu, attrib=pvm_c.ATTR_KSV160) trunk.set_parm_value('OvsPortExternalIds', meta_attrs, attrib=pvm_c.ATTR_KSV160) trunk.set_parm_value('OvsBridge', vif['network']['bridge'], attrib=pvm_c.ATTR_KSV160) # Updating the trunk adapter will cause NovaLink to reassociate # the tap device. trunk.update()