Beispiel #1
0
    def test_get_me(self, mock_my_id, mock_lp_search, mock_vio_search):
        """Test get_this_partition()."""
        # Good path - one hit on LPAR
        mock_lp_search.return_value = [lpar.LPAR.wrap(self.mgmt_lpar)[0]]
        mock_vio_search.return_value = []
        mock_my_id.return_value = 9
        my_w = tpar.get_this_partition(self.adpt)
        self.assertEqual(9, my_w.id)
        self.assertEqual('089FFB20-5D19-4A8C-BB80-13650627D985', my_w.uuid)
        mock_lp_search.assert_called_with(self.adpt, id=9)
        mock_vio_search.assert_called_with(self.adpt, id=9)

        # Good path - one hit on VIOS
        mock_lp_search.reset_mock()
        mock_lp_search.return_value = []
        mock_vio_search.return_value = [vios.VIOS.wrap(self.mgmt_vio)[0]]
        mock_my_id.return_value = 2
        my_w = tpar.get_this_partition(self.adpt)
        self.assertEqual(2, my_w.id)
        self.assertEqual('1300C76F-9814-4A4D-B1F0-5B69352A7DEA', my_w.uuid)
        mock_lp_search.assert_not_called()
        mock_vio_search.assert_called_with(self.adpt, id=2)

        # Bad path - no hits
        mock_lp_search.return_value = []
        mock_vio_search.return_value = []
        self.assertRaises(ex.ThisPartitionNotFoundException,
                          tpar.get_this_partition, self.adpt)
Beispiel #2
0
    def rollback_live_migration_at_destination(self, vif, vea_vlan_mappings):
        """Rolls back the pre live migrate on the destination host.

        Will delete the TrunkAdapter that pre_live_migrate_at_destination
        created with its unique hypervisor VLAN.  This uses the
        vea_vlan_mappings to provide the information as to what TrunkAdapter
        it should remove.

        :param vif: The virtual interface that was being migrated.  This may be
                    called network_info in other portions of the code.
        :param vea_vlan_mappings: The VEA VLAN mappings.  Key is the vif
                                  mac address, value is the destination's
                                  target hypervisor VLAN.
        """
        LOG.warning("Rolling back the live migrate of VIF with mac %(mac)s.",
                    {'mac': vif['address']},
                    instance=self.instance)

        # We know that we just attached the VIF to the NovaLink VM.  Search
        # for a trunk adapter with the PVID and vSwitch that we specified
        # above.  This is guaranteed to be unique.
        vlan = int(vea_vlan_mappings[vif['address']])
        vswitch_id = pvm_net.VSwitch.search(
            self.adapter,
            parent_type=pvm_ms.System,
            one_result=True,
            name=CONF.powervm.pvm_vswitch_for_novalink_io).switch_id

        # Delete port from OVS
        linux_net.delete_ovs_vif_port(vif['network']['bridge'],
                                      self.get_trunk_dev_name(vif))

        # Find the trunk
        mgmt_wrap = pvm_par.get_this_partition(self.adapter)
        child_adpts = pvm_net.CNA.get(self.adapter, parent=mgmt_wrap)
        trunk = None
        for adpt in child_adpts:
            # We need a trunk adapter (so check trunk_pri).  Then the trunk
            # is unique by PVID and PowerVM vSwitch ID.
            if (adpt.pvid == vlan and adpt.vswitch_id == vswitch_id
                    and adpt.trunk_pri):
                trunk = adpt
                break

        if trunk:
            # Delete the peer'd trunk adapter.
            LOG.warning(
                "Deleting target side trunk adapter %(dev)s for "
                "rollback operation", {'dev': trunk.dev_name},
                instance=self.instance)
            trunk.delete()
Beispiel #3
0
    def pre_live_migrate_at_destination(self, vif, vea_vlan_mappings):
        """Performs the pre live migrate on the destination host.

        This method will create the trunk adapter on the destination host,
        set its link state up, and attach it to the integration OVS switch.
        It also updates the vea_vlan_mappings to indicate which unique
        hypervisor VLAN should be used for this VIF for the migration operation
        to complete properly.

        :param vif: The virtual interface that will be migrated.  This may be
                    called network_info in other portions of the code.
        :param vea_vlan_mappings: The VEA VLAN mappings.  Key is the vif
                                  mac address, value is the destination's
                                  target hypervisor VLAN.
        """
        self._cleanup_orphan_adapters(vif,
                                      CONF.powervm.pvm_vswitch_for_novalink_io)
        mgmt_wrap = pvm_par.get_this_partition(self.adapter)
        dev = self.get_trunk_dev_name(vif)

        # Find a specific free VLAN and create the Trunk in a single atomic
        # action.
        cna_w = pvm_cna.crt_trunk_with_free_vlan(
            self.adapter,
            self.host_uuid, [mgmt_wrap.uuid],
            CONF.powervm.pvm_vswitch_for_novalink_io,
            dev_name=dev)[0]

        # Bring the vif up.  This signals to neutron that its ready for vif
        # plugging
        utils.execute('ip', 'link', 'set', dev, 'up', run_as_root=True)
        linux_net.create_ovs_vif_port(vif['network']['bridge'], dev,
                                      self.get_ovs_interfaceid(vif),
                                      vif['address'], self.instance.uuid)

        # Save this data for the migration command.
        vea_vlan_mappings[vif['address']] = cna_w.pvid
        LOG.info(
            "VIF with mac %(mac)s is going on trunk %(dev)s with PVID "
            "%(pvid)s", {
                'mac': vif['address'],
                'dev': dev,
                'pvid': cna_w.pvid
            },
            instance=self.instance)
Beispiel #4
0
    def plug(self, vif, slot_num, 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.

        :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.
        """
        dev_name = self.get_trunk_dev_name(vif)

        if new_vif:
            # Create the trunk and client adapter.
            lpar_uuid = vm.get_pvm_uuid(self.instance)
            mgmt_uuid = pvm_par.get_this_partition(self.adapter).uuid
            cna_w = 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)[0]
        else:
            cna_w = None

        # Make sure to just run the up just in case.
        utils.execute('ip', 'link', 'set', dev_name, 'up', run_as_root=True)

        return cna_w
Beispiel #5
0
    def post_live_migrate_at_destination(self, vif):
        """Performs live migrate cleanup on the destination host.

        This is optional, child classes do not need to implement this.

        :param vif: The virtual interface that was migrated.
        """
        # 1) Find a free vlan to use
        # 2) Update the migrated CNA to use the new vlan that was found
        #    and ensure that the CNA is enabled
        # 3) Create a trunk adapter on the destination of the migration
        #    using the same vlan as the CNA

        mgmt_wrap = pvm_par.get_this_partition(self.adapter)
        dev_name = self.get_trunk_dev_name(vif)
        mac = pvm_util.sanitize_mac_for_api(vif['address'])

        # Get vlan
        vswitch_w = pvm_net.VSwitch.search(
            self.adapter, parent_type=pvm_ms.System.schema_type,
            one_result=True, parent_uuid=self.host_uuid,
            name=CONF.powervm.pvm_vswitch_for_novalink_io)
        cna = pvm_net.CNA.search(
            self.adapter, mac=mac, one_result=True, parent_type=pvm_lpar.LPAR,
            parent_uuid=vm.get_pvm_uuid(self.instance))

        # Assigns a free vlan (which is returned) to the cna_list
        # also enable the cna
        cna = pvm_cna.assign_free_vlan(
            self.adapter, self.host_uuid, vswitch_w, cna)
        # Create a trunk with the vlan_id
        trunk_adpt = pvm_net.CNA.bld(
            self.adapter, cna.pvid, vswitch_w.related_href, trunk_pri=1,
            dev_name=dev_name)
        trunk_adpt.create(parent=mgmt_wrap)

        utils.execute('ip', 'link', 'set', dev_name, 'up', run_as_root=True)
        linux_net.create_ovs_vif_port(vif['network']['bridge'], dev_name,
                                      self.get_ovs_interfaceid(vif),
                                      vif['address'], self.instance.uuid)
Beispiel #6
0
    def plug(self, vif, slot_num):
        """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.

        :param vif: The virtual interface to plug into the instance.
        :param slot_num: Which slot number to plug the VIF into.  May be None.
        """
        # Create the trunk and client adapter.
        lpar_uuid = vm.get_pvm_uuid(self.instance)
        mgmt_uuid = pvm_par.get_this_partition(self.adapter).uuid
        dev_name = self.get_trunk_dev_name(vif)
        cna_w, trunk_wraps = 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)

        utils.execute('ip', 'link', 'set', dev_name, 'up', run_as_root=True)

        return cna_w
Beispiel #7
0
    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()
Beispiel #8
0
    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()
Beispiel #9
0
def mgmt_uuid(adapter):
    """Returns the management partitions UUID."""
    global _MP_UUID
    if not _MP_UUID:
        _MP_UUID = pvm_par.get_this_partition(adapter).uuid
    return _MP_UUID
Beispiel #10
0
def mgmt_uuid(adapter):
    """Returns the management partitions UUID."""
    global _MP_UUID
    if not _MP_UUID:
        _MP_UUID = pvm_par.get_this_partition(adapter).uuid
    return _MP_UUID