예제 #1
0
 def test_set_vnic_back_devs_max_capacity_invoked(self, mock_vioget):
     mock_sys = sys_wrapper(self.fake_sriovs)
     mock_vioget.return_value = [mock.Mock(uuid='vios_uuid1')]
     self.adpt.build_href.side_effect = lambda *a, **k: '%s' % a[1]
     vnic = card.VNIC.bld(self.adpt, pvid=5)
     self.assertEqual(0, len(vnic.back_devs))
     tsriov.set_vnic_back_devs(vnic, ['pport_loc%d' % x for x in range(60)],
                               sys_w=mock_sys, capacity=0.02, redundancy=1,
                               max_capacity=0.75)
     # Ensure that the max and min capacities attached to back_devices as
     # expected
     self.assertEqual(0.02, vnic.back_devs[0].capacity)
     self.assertEqual(0.75, vnic.back_devs[0].max_capacity)
예제 #2
0
    def plug(self, vif, slot_num, new_vif=True):
        if not new_vif:
            return None

        physnet = vif.get_physical_network()
        if not physnet:
            # Get physnet from neutron network if not present in vif
            # TODO(svenkat): This section of code will be eliminated in
            # pike release. Design will be in place to fix any vif
            # that has physical_network missing. The fix will be in
            # compute startup code.
            net_id = vif['network']['id']
            admin_context = ctx.get_admin_context()
            napi = net_api.API()
            network = napi.get(admin_context, net_id)
            physnet = network.physical_network

        LOG.debug("Plugging vNIC SR-IOV vif for physical network %(physnet)s.",
                  {'physnet': physnet},
                  instance=self.instance)

        # Get the msys
        msys = pvm_ms.System.get(self.adapter)[0]
        # Physical ports for the given port label
        pports_w = sriovtask.find_pports_for_portlabel(physnet, self.adapter,
                                                       msys)
        pports = [pport.loc_code for pport in pports_w]

        if not pports:
            raise exception.VirtualInterfacePlugException(
                _("Unable to find acceptable Ethernet ports on physical "
                  "network '%(physnet)s' for instance %(inst)s for SRIOV "
                  "based VIF with MAC address %(vif_mac)s.") % {
                      'physnet': physnet,
                      'inst': self.instance.name,
                      'vif_mac': vif['address']
                  })

        # MAC
        mac_address = pvm_util.sanitize_mac_for_api(vif['address'])

        # vlan id
        vlan_id = int(vif['details']['vlan'])

        # Redundancy: plugin sets from binding:profile, then conf, then default
        redundancy = int(vif['details']['redundancy'])

        # Capacity: plugin sets from binding:profile, then conf, then default
        capacity = vif['details']['capacity']

        vnic = pvm_card.VNIC.bld(self.adapter,
                                 vlan_id,
                                 slot_num=slot_num,
                                 mac_addr=mac_address,
                                 allowed_vlans=pvm_util.VLANList.NONE,
                                 allowed_macs=pvm_util.MACList.NONE)

        sriovtask.set_vnic_back_devs(vnic,
                                     pports,
                                     sys_w=msys,
                                     redundancy=redundancy,
                                     capacity=capacity,
                                     check_port_status=True)

        return vnic.create(parent_type=pvm_lpar.LPAR,
                           parent_uuid=vm.get_pvm_uuid(self.instance))
예제 #3
0
    def test_set_vnic_back_devs(self, mock_shuffle, mock_vioget):
        """Test set_vnic_back_devs."""
        mock_sys = sys_wrapper(self.fake_sriovs)
        mock_vioget.return_value = [
            mock.Mock(uuid='vios_uuid1'),
            mock.Mock(uuid='vios_uuid2'),
            mock.Mock(uuid='vios_uuid3')
        ]
        self.adpt.build_href.side_effect = lambda *a, **k: '%s' % a[1]
        vnic = card.VNIC.bld(self.adpt, pvid=5)
        self.assertEqual(0, len(vnic.back_devs))
        # Silly case: redundancy of zero
        tsriov.set_vnic_back_devs(vnic, [], sys_w=mock_sys, redundancy=0)
        self.assertEqual(0, len(vnic.back_devs))
        mock_vioget.assert_called_once_with(self.adpt, None, 0)

        cap = 0.019
        # Things to note about the following:
        # - VIOSes rotate.  1, 2, 3, repeat.  If we hadn't mocked shuffle, the
        #   base order would be random, but they would still rotate in whatever
        #   that shuffled order was.
        # - The least-used (emptiest) physical ports come first...
        # - ...except (e.g. 21) we force distribution across cards, so...
        # - ...cards alternate until exhausted; hence 5 repeated at the end.
        # - Capacity set across the board according to the parameter.
        all_back_devs = [
            ('vios_uuid1', 1, 12, cap), ('vios_uuid2', 5, 52, cap),
            ('vios_uuid3', 4, 42, cap), ('vios_uuid1', 2, 21, cap),
            ('vios_uuid2', 5, 54, cap), ('vios_uuid3', 4, 41, cap),
            ('vios_uuid1', 1, 13, cap), ('vios_uuid2', 5, 56, cap),
            ('vios_uuid3', 1, 11, cap), ('vios_uuid1', 5, 57, cap),
            ('vios_uuid2', 5, 55, cap), ('vios_uuid3', 5, 51, cap)
        ]
        # 5/55 is link-down.  When it drops off, the last one moves to VIOS 2.
        live_back_devs = all_back_devs[:10] + [('vios_uuid2', 5, 51, cap)]

        # Use 'em all
        tsriov.set_vnic_back_devs(vnic, ['pport_loc%d' % x for x in range(60)],
                                  sys_w=mock_sys,
                                  capacity=cap,
                                  redundancy=12)
        self.assertEqual(
            all_back_devs,
            [(bd.vios_href, bd.sriov_adap_id, bd.pport_id, bd.capacity)
             for bd in vnic.back_devs])

        # Check port status - 55 drops off
        tsriov.set_vnic_back_devs(vnic, ['pport_loc%d' % x for x in range(60)],
                                  sys_w=mock_sys,
                                  capacity=cap,
                                  redundancy=11,
                                  check_port_status=True)
        self.assertEqual(
            live_back_devs,
            [(bd.vios_href, bd.sriov_adap_id, bd.pport_id, bd.capacity)
             for bd in vnic.back_devs])

        # Fail if we can't satisfy redundancy
        self.assertRaises(ex.InsufficientSRIOVCapacity,
                          tsriov.set_vnic_back_devs,
                          vnic, ['pport_loc%d' % x for x in range(60)],
                          sys_w=mock_sys,
                          capacity=cap,
                          redundancy=13)

        # The passed-in wrapper isn't modified if the method raises.
        self.assertEqual(
            live_back_devs,
            [(bd.vios_href, bd.sriov_adap_id, bd.pport_id, bd.capacity)
             for bd in vnic.back_devs])

        # Make sure redundancy caps it.
        # By reusing vnic without resetting its back_devs, we're proving the
        # documented behavior that the method clears first.
        tsriov.set_vnic_back_devs(vnic, ['pport_loc%d' % x for x in range(60)],
                                  sys_w=mock_sys,
                                  capacity=cap,
                                  redundancy=5)
        self.assertEqual(
            all_back_devs[:5],
            [(bd.vios_href, bd.sriov_adap_id, bd.pport_id, bd.capacity)
             for bd in vnic.back_devs])

        self.assertEqual(5, mock_shuffle.call_count)