def test_numa_topology_with_pci_fail(self, mock_get_by_instance):
        dev_dict = {
            'compute_node_id': 1,
            'address': 'a',
            'product_id': 'p',
            'vendor_id': 'v',
            'numa_node': 1,
            'dev_type': 'type-PCI',
            'parent_addr': 'a1',
            'status': 'available'
        }
        dev_dict2 = {
            'compute_node_id': 1,
            'address': 'a',
            'product_id': 'p',
            'vendor_id': 'v',
            'numa_node': 2,
            'dev_type': 'type-PCI',
            'parent_addr': 'a1',
            'status': 'available'
        }
        self.tracker.new_pci_tracker()
        self.tracker.pci_tracker._set_hvdevs([dev_dict, dev_dict2])

        request = objects.InstancePCIRequest(count=2,
                                             spec=[{
                                                 'vendor_id': 'v',
                                                 'product_id': 'p'
                                             }])
        requests = objects.InstancePCIRequests(requests=[request])
        mock_get_by_instance.return_value = requests

        huge_instance = objects.InstanceNUMATopology(cells=[
            objects.InstanceNUMACell(id=1, cpuset=set([1, 2]), memory=512)
        ])

        self.assertRaises(exception.ComputeResourcesUnavailable,
                          self._claim,
                          requests=requests,
                          numa_topology=huge_instance)
    def test_obj_make_compatible(self):
        topo_obj = objects.InstanceNUMACell(
            cpuset=set(),
            pcpuset=set([0, 1]),
            cpuset_reserved=set([1, 2]),
            cpu_policy=fields.CPUAllocationPolicy.MIXED,
        )
        versions = ovo_base.obj_tree_get_versions('InstanceNUMACell')
        data = lambda x: x['nova_object.data']

        primitive = data(
            topo_obj.obj_to_primitive(target_version='1.6',
                                      version_manifest=versions))
        self.assertEqual(fields.CPUAllocationPolicy.MIXED,
                         primitive['cpu_policy'])

        self.assertRaises(exception.ObjectActionError,
                          topo_obj.obj_to_primitive,
                          target_version='1.5',
                          version_manifest=versions)

        # set this to something compatible with <  1.6 so we can keep testing
        topo_obj.cpu_policy = fields.CPUAllocationPolicy.DEDICATED
        primitive = data(
            topo_obj.obj_to_primitive(target_version='1.5',
                                      version_manifest=versions))
        self.assertIn('pcpuset', primitive)

        primitive = data(
            topo_obj.obj_to_primitive(target_version='1.4',
                                      version_manifest=versions))
        self.assertNotIn('pcpuset', primitive)
        self.assertEqual(set([0, 1]), set(primitive['cpuset']))
        self.assertIn('cpuset_reserved', primitive)

        primitive = data(
            topo_obj.obj_to_primitive(target_version='1.3',
                                      version_manifest=versions))
        self.assertNotIn('cpuset_reserved', primitive)
 def test_claim_fails_page_size_not_called(self):
     instance_type = self._fake_instance_type()
     instance = self._fake_instance()
     # This topology cannot fit in self.compute_node
     # (see _fake_compute_node())
     numa_topology = objects.InstanceNUMATopology(cells=[
         objects.InstanceNUMACell(
             id=1, cpuset=set([1, 2, 3]), pcpuset=set(), memory=1024)
     ])
     with test.nested(
             mock.patch('nova.virt.hardware.numa_get_constraints',
                        return_value=numa_topology),
             mock.patch(
                 'nova.compute.claims.MoveClaim._test_live_migration_page_size'
             )) as (mock_test_numa, mock_test_page_size):
         self.assertRaisesRegex(
             exception.ComputeResourcesUnavailable,
             'Requested instance NUMA topology', claims.MoveClaim,
             self.context, instance, _NODENAME, instance_type, {},
             self.tracker, self.compute_node, self.empty_requests,
             objects.Migration(migration_type='live-migration'), None)
         mock_test_page_size.assert_not_called()
Example #4
0
    def _test_core_bind(self, context, instance, resource_tracker):
        LOG.debug("get instance cpu bind info in _test_core_bind")
        filter_properties = {}
        inst_extra = objects.HuaweiInstanceExtra.get_by_instance_uuid(
            context, instance.uuid)
        if inst_extra:
            scheduler_hints = jsonutils.loads(inst_extra.scheduler_hints
                                              or '{}')
            stats = jsonutils.loads(inst_extra.stats or '{}')
        else:
            scheduler_hints = {}
            stats = {}
        filter_properties['scheduler_hints'] = scheduler_hints
        filter_properties['stats'] = stats
        pci_requests = objects.InstancePCIRequests.get_by_instance_uuid(
            context, instance['uuid'])
        if pci_requests:
            filter_properties['pci_requests'] = pci_requests

        bind_info, instance_numa, enable_ht = sched_utils.get_inst_cpu_bind_info(
            instance,
            resource_tracker.host,
            filter_properties=filter_properties)

        sched_utils.update_cpu_bind_info_to_db(bind_info, instance.uuid,
                                               instance_numa)

        if instance_numa and instance_numa['cells'][0].get('is_huawei'):
            cells = []
            for cell in instance_numa['cells']:
                cells.append(
                    objects.InstanceNUMACell(id=cell['id'],
                                             cpuset=set(cell['cpuset']),
                                             memory=cell['mem']['total'],
                                             pagesize=cell.get('pagesize')))

            format_inst_numa = objects.InstanceNUMATopology(cells=cells)
            self.claimed_numa_topology = format_inst_numa
            self.instance['numa_topology'] = format_inst_numa
Example #5
0
    def test_stat_consumption_from_instance_pci(self):

        inst_topology = objects.InstanceNUMATopology(
                            cells = [objects.InstanceNUMACell(
                                                      cpuset=set([0]),
                                                      memory=512, id=0)])

        fake_requests = [{'request_id': 'fake_request1', 'count': 1,
                          'spec': [{'vendor_id': '8086'}]}]
        fake_requests_obj = objects.InstancePCIRequests(
                                requests=[objects.InstancePCIRequest(**r)
                                          for r in fake_requests],
                                instance_uuid='fake-uuid')
        req_spec = objects.RequestSpec(
            instance_uuid='fake-uuid',
            project_id='12345',
            numa_topology=inst_topology,
            pci_requests=fake_requests_obj,
            flavor=objects.Flavor(root_gb=0,
                                  ephemeral_gb=0,
                                  memory_mb=512,
                                  vcpus=1))
        host = host_manager.HostState("fakehost", "fakenode")
        self.assertIsNone(host.updated)
        host.pci_stats = pci_stats.PciDeviceStats(
                                      [objects.PciDevicePool(vendor_id='8086',
                                                             product_id='15ed',
                                                             numa_node=1,
                                                             count=1)])
        host.numa_topology = fakes.NUMA_TOPOLOGY
        host.consume_from_request(req_spec)
        self.assertIsInstance(req_spec.numa_topology,
                              objects.InstanceNUMATopology)

        self.assertEqual(512, host.numa_topology.cells[1].memory_usage)
        self.assertEqual(1, host.numa_topology.cells[1].cpu_usage)
        self.assertEqual(0, len(host.pci_stats.pools))
        self.assertIsNotNone(host.updated)
Example #6
0
    def test_create_migration_context(self):
        numa_topology = objects.InstanceNUMATopology(
                cells=[objects.InstanceNUMACell(
                    id=1, cpuset=set([1, 2]), memory=512)])
        claim = self._claim(numa_topology=numa_topology)
        migration = objects.Migration(context=self.context, id=42)
        claim.migration = migration
        fake_mig_context = mock.Mock(spec=objects.MigrationContext)

        @mock.patch('nova.db.instance_extra_get_by_instance_uuid',
                    return_value=None)
        @mock.patch('nova.objects.MigrationContext',
                    return_value=fake_mig_context)
        def _test(ctxt_mock, mock_get_extra):
            claim.create_migration_context()
            ctxt_mock.assert_called_once_with(
                context=self.context, instance_uuid=self.instance.uuid,
                migration_id=42, old_numa_topology=None,
                new_numa_topology=mock.ANY)
            self.assertIsInstance(ctxt_mock.call_args[1]['new_numa_topology'],
                                  objects.InstanceNUMATopology)
            self.assertEqual(migration, claim.migration)
        _test()
    def test_numa_topology_with_pci(self, mock_get):
        dev_dict = {
            'compute_node_id': 1,
            'address': 'a',
            'product_id': 'p',
            'vendor_id': 'v',
            'numa_node': 1,
            'status': 'available'
        }
        self.tracker.new_pci_tracker()
        self.tracker.pci_tracker.set_hvdevs([dev_dict])
        request = objects.InstancePCIRequest(count=1,
                                             spec=[{
                                                 'vendor_id': 'v',
                                                 'product_id': 'p'
                                             }])
        mock_get.return_value = objects.InstancePCIRequests(requests=[request])

        huge_instance = objects.InstanceNUMATopology(cells=[
            objects.InstanceNUMACell(id=1, cpuset=set([1, 2]), memory=512)
        ])

        self._claim(numa_topology=huge_instance)
Example #8
0
def _numa_fit_instance_cell(host_cell, instance_cell, limit_cell=None):
    """Check if a instance cell can fit and set it's cell id

    :param host_cell: host cell to fit the instance cell onto
    :param instance_cell: instance cell we want to fit
    :param limit_cell: cell with limits of the host_cell if any

    Make sure we can fit the instance cell onto a host cell and if so,
    return a new objects.InstanceNUMACell with the id set to that of
    the host, or None if the cell exceeds the limits of the host

    :returns: a new instance cell or None
    """
    # NOTE (ndipanov): do not allow an instance to overcommit against
    # itself on any NUMA cell
    if (instance_cell.memory > host_cell.memory
            or len(instance_cell.cpuset) > len(host_cell.cpuset)):
        return None

    if limit_cell:
        memory_usage = host_cell.memory_usage + instance_cell.memory
        cpu_usage = host_cell.cpu_usage + len(instance_cell.cpuset)
        if (memory_usage > limit_cell.memory_limit
                or cpu_usage > limit_cell.cpu_limit):
            return None

    pagesize = None
    if instance_cell.pagesize:
        pagesize = _numa_cell_supports_pagesize_request(
            host_cell, instance_cell)
        if not pagesize:
            return

    return objects.InstanceNUMACell(id=host_cell.id,
                                    cpuset=instance_cell.cpuset,
                                    memory=instance_cell.memory,
                                    pagesize=pagesize)
 def test_cpu_pinning_requested_cell(self):
     inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]),
                                          cpu_pinning=None)
     self.assertFalse(inst_cell.cpu_pinning_requested)
     inst_cell.cpu_pinning = {}
     self.assertTrue(inst_cell.cpu_pinning_requested)
Example #10
0
    def _schedule(self, context, request_spec, filter_properties):
        """Returns a list of hosts that meet the required specs,
        ordered by their fitness.
        """
        elevated = context.elevated()
        instance_properties = request_spec['instance_properties']
        instance_type = request_spec.get("instance_type", None)
        instance_uuids = request_spec.get("instance_uuids", None)

        LOG.debug("[HINTS] filter_properties=%s" % filter_properties)
        # query scheduler_hints from database, and skip what in the parameters.
        if instance_uuids:
            inst_extra = objects.HuaweiInstanceExtra.get_by_instance_uuid(
                context, instance_uuids[0])
            if inst_extra:
                scheduler_hints = jsonutils.loads(inst_extra.scheduler_hints
                                                  or '{}')
                stats = jsonutils.loads(inst_extra.stats or '{}')
            else:
                scheduler_hints = {}
                stats = {}

            LOG.debug("[HINTS] Got scheduler_hints via db. "
                      "scheduler_hints=%s" % scheduler_hints)
            filter_properties['scheduler_hints'] = scheduler_hints
            filter_properties['stats'] = stats
            instance_properties['stats'] = stats
        try:
            update_group_hosts = self._setup_instance_group(
                context, filter_properties)
        except exception.InstanceGroupNotFound as e:
            # InstanceGroup has already checked in API,
            # might has been deleted when migrate/ha
            LOG.warning("ServerGroup %s doesn't exist" %
                        scheduler_hints.get('group', "None"))
            update_group_hosts = False
        config_options = self._get_configuration_options()

        filter_properties.update({
            'context': context,
            'request_spec': request_spec,
            'config_options': config_options,
            'instance_type': instance_type
        })

        self.populate_filter_properties(request_spec, filter_properties)

        # Find our local list of acceptable hosts by repeatedly
        # filtering and weighing our options. Each time we choose a
        # host, we virtually consume resources on it so subsequent
        # selections can adjust accordingly.

        # Note: remember, we are using an iterator here. So only
        # traverse this list once. This can bite you if the hosts
        # are being scanned in a filter or weighing function.
        hosts = self._get_all_host_states(elevated)

        selected_hosts = []
        if instance_uuids:
            num_instances = len(instance_uuids)
        else:
            num_instances = request_spec.get('num_instances', 1)
        for num in xrange(num_instances):
            #NOTE: add a tracker of filter
            tracker = HuaweiFilterTracker()
            filter_properties['__tracker'] = tracker

            # Filter local hosts based on requirements ...
            hosts = self.host_manager.get_filtered_hosts(hosts,
                                                         filter_properties,
                                                         index=num)
            if not hosts:
                # Can't get any more locally.
                break

            LOG.debug("Filtered %(hosts)s", {'hosts': hosts})

            weighed_hosts = self.host_manager.get_weighed_hosts(
                hosts, filter_properties)

            LOG.debug("Weighed %(hosts)s", {'hosts': weighed_hosts})

            scheduler_host_subset_size = CONF.scheduler_host_subset_size
            if scheduler_host_subset_size > len(weighed_hosts):
                scheduler_host_subset_size = len(weighed_hosts)
            if scheduler_host_subset_size < 1:
                scheduler_host_subset_size = 1

            chosen_host = random.choice(
                weighed_hosts[0:scheduler_host_subset_size])

            host_mapper = dict()
            for host in weighed_hosts:
                host_mapper[host.obj.host] = host

            if 'resize_prefer_to_same_host' in filter_properties:
                origin_host = filter_properties['resize_prefer_to_same_host']
                chosen_host = host_mapper.get(origin_host, chosen_host)

            migrate_host = filter_properties.get('migrate_host')
            if migrate_host:
                if migrate_host in host_mapper:
                    chosen_host = host_mapper.get(migrate_host)
                else:
                    # migrate_host not in filter hosts list
                    # raise NoVaildHost
                    break

            selected_hosts.append(chosen_host)

            # Now consume the resources so the filter/weights
            # will change for the next instance.
            # NOTE () adding and deleting pci_requests is a temporary
            # fix to avoid DB access in consume_from_instance() while getting
            # pci_requests. The change can be removed once pci_requests is
            # part of the instance object that is passed into the scheduler
            # APIs
            pci_requests = filter_properties.get('pci_requests')
            if pci_requests:
                instance_properties['pci_requests'] = pci_requests

            if request_spec.get('instance_type'):
                instance_properties['numa_topology'] = \
                    hardware.numa_get_constraints(instance_type, {})
            self._update_instance_topology(instance_properties, chosen_host)

            try:
                bind_info, instance_numa, __ = utils.get_inst_cpu_bind_info(
                    instance_properties,
                    chosen_host.obj,
                    filter_properties=filter_properties)
            except exception.NovaException as ex:
                msg = ("Get cpu binding info on host %(host)s failed, the"
                       " host_numa_top is %(host_numa_top)s, "
                       "instance_properties is  %(instance_properties)s")
                params = {
                    'host': chosen_host.obj.host,
                    'host_numa_top': chosen_host.obj.numa_topology,
                    'instance_properties': instance_properties
                }
                # set bind_info and instance_numa is None
                bind_info = None
                instance_numa = None
                LOG.debug(_LE(msg), params)
                LOG.debug(_LE(ex.format_message()))

            scheduler_hints = filter_properties.get('scheduler_hints', None)

            if instance_numa and instance_numa['cells'][0].get('is_huawei'):
                cells = []
                for cell in instance_numa['cells']:
                    cells.append(
                        objects.InstanceNUMACell(
                            id=cell['id'],
                            cpuset=set(cell['cpuset']),
                            memory=cell['mem']['total'],
                            pagesize=cell.get('pagesize')))

                format_inst_numa = objects.InstanceNUMATopology(cells=cells)
                instance_properties['numa_topology'] = format_inst_numa

            try:
                if isinstance(chosen_host.obj,
                              ironic_host_manager.IronicNodeState):
                    chosen_host.obj.consume_from_instance(instance_properties)
                else:
                    chosen_host.obj.consume_from_instance(
                        instance_properties, filter_properties)
            except exception.PciDeviceRequestFailed as e:
                # pop the select chosen host in order to rollback resource in
                # memory
                LOG.warning("consume get exception: %s", e.format_message())
                rollback_hosts = [chosen_host]
                self.host_manager.force_update_host_states(
                    context, rollback_hosts)

            if pci_requests:
                del instance_properties['pci_requests']
            if update_group_hosts is True:
                # NOTE(): Group details are serialized into a list now
                # that they are populated by the conductor, we need to
                # deserialize them
                if isinstance(filter_properties['group_hosts'], list):
                    filter_properties['group_hosts'] = set(
                        filter_properties['group_hosts'])

        self._check_fulfill_for_multiple_create(context, num_instances,
                                                selected_hosts)

        return selected_hosts
    def test_siblings(self):
        # default thread number of VirtualCPUTopology is one, one thread means
        # no thread and no sibling
        inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2]),
                                             pcpuset=set())
        self.assertEqual([], inst_cell.siblings)
        inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2]),
                                             pcpuset=set([4, 5, 6]))
        self.assertEqual([], inst_cell.siblings)

        # 'threads=0' means no sibling
        topo = objects.VirtCPUTopology(sockets=1, cores=3, threads=0)
        inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2]),
                                             pcpuset=set(),
                                             cpu_topology=topo)
        self.assertEqual([], inst_cell.siblings)
        inst_cell = objects.InstanceNUMACell(cpuset=set(),
                                             pcpuset=set([0, 1, 2]),
                                             cpu_topology=topo)
        self.assertEqual([], inst_cell.siblings)

        # One thread actually means no threads
        topo = objects.VirtCPUTopology(sockets=1, cores=3, threads=1)
        inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2]),
                                             pcpuset=set(),
                                             cpu_topology=topo)
        self.assertEqual([], inst_cell.siblings)
        inst_cell = objects.InstanceNUMACell(cpuset=set(),
                                             pcpuset=set([0, 1, 2]),
                                             cpu_topology=topo)
        self.assertEqual([], inst_cell.siblings)

        # 2 threads per virtual core, and numa node has only one type CPU
        # pinned and un-pinned.
        topo = objects.VirtCPUTopology(sockets=1, cores=2, threads=2)
        inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]),
                                             pcpuset=set(),
                                             cpu_topology=topo)
        self.assertEqual([set([0, 1]), set([2, 3])], inst_cell.siblings)
        inst_cell = objects.InstanceNUMACell(cpuset=set(),
                                             pcpuset=set([0, 1, 2, 3]),
                                             cpu_topology=topo)
        self.assertEqual([set([0, 1]), set([2, 3])], inst_cell.siblings)

        # 4 threads per virtual core, numa node has only one type CPU
        topo = objects.VirtCPUTopology(sockets=1, cores=1, threads=4)
        inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]),
                                             pcpuset=set(),
                                             cpu_topology=topo)
        self.assertEqual([set([0, 1, 2, 3])], inst_cell.siblings)
        inst_cell = objects.InstanceNUMACell(cpuset=set(),
                                             pcpuset=set([0, 1, 2, 3]),
                                             cpu_topology=topo)
        self.assertEqual([set([0, 1, 2, 3])], inst_cell.siblings)

        # 2 threads per virtual core, numa node with two type CPUs, the pinned
        # and un-pinned
        topo = objects.VirtCPUTopology(sockets=1, cores=2, threads=2)
        inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1]),
                                             pcpuset=set([2, 3]),
                                             cpu_topology=topo)
        self.assertEqual([set([0, 1]), set([2, 3])], inst_cell.siblings)
Example #12
0
 def test_numa_pinning_requested_cell(self):
     inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]),
                                          physnode=None)
     self.assertFalse(inst_cell.numa_pinning_requested)
     inst_cell.physnode = 0
     self.assertTrue(inst_cell.numa_pinning_requested)
Example #13
0
 def test_obj_make_compatible_numa_cell_pre_1_4(self):
     topo_obj = objects.InstanceNUMACell(cpuset_reserved=set([1, 2]))
     versions = ovo_base.obj_tree_get_versions('InstanceNUMACell')
     primitive = topo_obj.obj_to_primitive(target_version='1.3',
                                           version_manifest=versions)
     self.assertNotIn('cpuset_reserved', primitive)
Example #14
0
 def test_cpu_pinning_requested_cell(self):
     inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]),
                                          cpu_pinning=None)
     self.assertFalse(inst_cell.cpu_pinning_requested)
     inst_cell.cpu_policy = fields.CPUAllocationPolicy.DEDICATED
     self.assertTrue(inst_cell.cpu_pinning_requested)
Example #15
0
 def test_pin_vcpus(self):
     inst_cell = objects.InstanceNUMACell(cpuset=set([0, 1, 2, 3]),
                                          cpu_pinning=None)
     inst_cell.pin_vcpus((0, 14), (1, 15), (2, 16), (3, 17))
     self.assertEqual({0: 14, 1: 15, 2: 16, 3: 17}, inst_cell.cpu_pinning)
Example #16
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.

from oslo_serialization import jsonutils
from oslo_utils import uuidutils

from nova import context
from nova import objects
from nova.tests.unit import fake_flavor
from nova.tests import uuidsentinel as uuids

INSTANCE_NUMA_TOPOLOGY = objects.InstanceNUMATopology(cells=[
    objects.InstanceNUMACell(id=0, cpuset=set([1, 2]), memory=512),
    objects.InstanceNUMACell(id=1, cpuset=set([3, 4]), memory=512)
])
INSTANCE_NUMA_TOPOLOGY.obj_reset_changes(recursive=True)

IMAGE_META = objects.ImageMeta.from_dict({
    'status':
    'active',
    'container_format':
    'bare',
    'min_ram':
    0,
    'updated_at':
    '2014-12-12T11:16:36.000000',
    'min_disk':
    0,
Example #17
0
 def test_pci_claim_instance_with_numa_fail(self, mock_get):
     self._create_pci_requests_object(mock_get, fake_pci_requests)
     self.inst.numa_topology = objects.InstanceNUMATopology(cells=[
         objects.InstanceNUMACell(id=1, cpuset=set([1, 2]), memory=512)
     ])
     self.assertIsNone(self.tracker.claim_instance(None, self.inst))
class CellsSchedulerTestCase(test.TestCase):
    """Test case for CellsScheduler class."""

    def setUp(self):
        super(CellsSchedulerTestCase, self).setUp()
        self.flags(scheduler_filter_classes=[], scheduler_weight_classes=[],
                   group='cells')
        self._init_cells_scheduler()

    def _init_cells_scheduler(self):
        fakes.init(self)
        self.msg_runner = fakes.get_message_runner('api-cell')
        self.scheduler = self.msg_runner.scheduler
        self.state_manager = self.msg_runner.state_manager
        self.my_cell_state = self.state_manager.get_my_state()
        self.ctxt = context.RequestContext('fake', 'fake')
        instance_uuids = []
        for x in range(3):
            instance_uuids.append(uuidutils.generate_uuid())
        self.instance_uuids = instance_uuids
        self.instances = [objects.Instance(uuid=uuid, id=id)
                          for id, uuid in enumerate(instance_uuids)]
        self.request_spec = {
                'num_instances': len(instance_uuids),
                'instance_properties': self.instances[0],
                'instance_type': 'fake_type',
                'image': 'fake_image'}
        self.build_inst_kwargs = {
                'instances': self.instances,
                'image': 'fake_image',
                'filter_properties': {'instance_type': 'fake_type'},
                'security_groups': 'fake_sec_groups',
                'block_device_mapping': 'fake_bdm'}

    def test_create_instances_here(self):
        # Just grab the first instance type
        inst_type = objects.Flavor.get_by_id(self.ctxt, 1)
        image = {'properties': {}}
        instance_uuids = self.instance_uuids
        instance_props = {'id': 'removed',
                          'security_groups': 'removed',
                          'info_cache': 'removed',
                          'name': 'instance-00000001',
                          'hostname': 'meow',
                          'display_name': 'moo',
                          'image_ref': 'fake_image_ref',
                          'user_id': self.ctxt.user_id,
                          # Test these as lists
                          'metadata': {'moo': 'cow'},
                          'system_metadata': {'meow': 'cat'},
                          'flavor': inst_type,
                          'project_id': self.ctxt.project_id,
                          'numa_topology': None}

        call_info = {'uuids': []}
        block_device_mapping = [
                objects.BlockDeviceMapping(context=self.ctxt,
                    **fake_block_device.FakeDbBlockDeviceDict(
                            block_device.create_image_bdm('fake_image_ref'),
                            anon=True))
               ]

        def _fake_instance_update_at_top(_ctxt, instance):
            call_info['uuids'].append(instance['uuid'])

        self.stubs.Set(self.msg_runner, 'instance_update_at_top',
                       _fake_instance_update_at_top)

        self.scheduler._create_instances_here(self.ctxt, instance_uuids,
                instance_props, inst_type, image,
                ['default'], block_device_mapping)
        self.assertEqual(instance_uuids, call_info['uuids'])

        for count, instance_uuid in enumerate(instance_uuids):
            instance = db.instance_get_by_uuid(self.ctxt, instance_uuid)
            meta = utils.instance_meta(instance)
            self.assertEqual('cow', meta['moo'])
            sys_meta = utils.instance_sys_meta(instance)
            self.assertEqual('cat', sys_meta['meow'])
            self.assertEqual('meow', instance['hostname'])
            self.assertEqual('moo-%d' % (count + 1),
                             instance['display_name'])
            self.assertEqual('fake_image_ref', instance['image_ref'])

    def test_build_instances_selects_child_cell(self):
        # Make sure there's no capacity info so we're sure to
        # select a child cell
        our_cell_info = self.state_manager.get_my_state()
        our_cell_info.capacities = {}

        call_info = {'times': 0}

        orig_fn = self.msg_runner.build_instances

        def msg_runner_build_instances(ctxt, target_cell, build_inst_kwargs):
            # This gets called twice.  Once for our running it
            # in this cell.. and then it'll get called when the
            # child cell is picked.  So, first time.. just run it
            # like normal.
            if not call_info['times']:
                call_info['times'] += 1
                return orig_fn(ctxt, target_cell, build_inst_kwargs)
            call_info['ctxt'] = ctxt
            call_info['target_cell'] = target_cell
            call_info['build_inst_kwargs'] = build_inst_kwargs

        def fake_build_request_spec(ctxt, image, instances):
            request_spec = {
                    'num_instances': len(instances),
                    'image': image}
            return request_spec

        self.stubs.Set(self.msg_runner, 'build_instances',
                msg_runner_build_instances)
        self.stubs.Set(scheduler_utils, 'build_request_spec',
                fake_build_request_spec)

        self.msg_runner.build_instances(self.ctxt, self.my_cell_state,
                self.build_inst_kwargs)

        self.assertEqual(self.ctxt, call_info['ctxt'])
        self.assertEqual(self.build_inst_kwargs,
                call_info['build_inst_kwargs'])
        child_cells = self.state_manager.get_child_cells()
        self.assertIn(call_info['target_cell'], child_cells)

    def test_build_instances_selects_current_cell(self):
        # Make sure there's no child cells so that we will be
        # selected
        self.state_manager.child_cells = {}

        call_info = {}
        build_inst_kwargs = copy.deepcopy(self.build_inst_kwargs)

        def fake_create_instances_here(ctxt, instance_uuids,
                instance_properties, instance_type, image, security_groups,
                block_device_mapping):
            call_info['ctxt'] = ctxt
            call_info['instance_uuids'] = instance_uuids
            call_info['instance_properties'] = instance_properties
            call_info['instance_type'] = instance_type
            call_info['image'] = image
            call_info['security_groups'] = security_groups
            call_info['block_device_mapping'] = block_device_mapping
            return self.instances

        def fake_rpc_build_instances(ctxt, **build_inst_kwargs):
            call_info['build_inst_kwargs'] = build_inst_kwargs

        def fake_build_request_spec(ctxt, image, instances):
            request_spec = {
                    'num_instances': len(instances),
                    'image': image}
            return request_spec

        self.stubs.Set(self.scheduler, '_create_instances_here',
                fake_create_instances_here)
        self.stubs.Set(self.scheduler.compute_task_api,
                       'build_instances', fake_rpc_build_instances)
        self.stubs.Set(scheduler_utils, 'build_request_spec',
                fake_build_request_spec)

        self.msg_runner.build_instances(self.ctxt, self.my_cell_state,
                build_inst_kwargs)

        self.assertEqual(self.ctxt, call_info['ctxt'])
        self.assertEqual(self.instance_uuids, call_info['instance_uuids'])
        self.assertEqual(self.build_inst_kwargs['instances'][0]['id'],
                         call_info['instance_properties']['id'])
        self.assertEqual(
            self.build_inst_kwargs['filter_properties']['instance_type'],
            call_info['instance_type'])
        self.assertEqual(self.build_inst_kwargs['image'], call_info['image'])
        self.assertEqual(self.build_inst_kwargs['security_groups'],
                call_info['security_groups'])
        self.assertEqual(self.build_inst_kwargs['block_device_mapping'],
                call_info['block_device_mapping'])
        self.assertEqual(build_inst_kwargs,
                call_info['build_inst_kwargs'])
        self.assertEqual(self.instance_uuids, call_info['instance_uuids'])

    def test_build_instances_retries_when_no_cells_avail(self):
        self.flags(scheduler_retries=7, group='cells')

        call_info = {'num_tries': 0, 'errored_uuids': []}

        def fake_grab_target_cells(filter_properties):
            call_info['num_tries'] += 1
            raise exception.NoCellsAvailable()

        def fake_sleep(_secs):
            return

        def fake_instance_save(inst):
            self.assertEqual(vm_states.ERROR, inst.vm_state)
            call_info['errored_uuids'].append(inst.uuid)

        def fake_build_request_spec(ctxt, image, instances):
            request_spec = {
                    'num_instances': len(instances),
                    'image': image}
            return request_spec

        self.stubs.Set(self.scheduler, '_grab_target_cells',
                fake_grab_target_cells)
        self.stubs.Set(time, 'sleep', fake_sleep)
        self.stubs.Set(objects.Instance, 'save', fake_instance_save)
        self.stubs.Set(scheduler_utils, 'build_request_spec',
                fake_build_request_spec)

        self.msg_runner.build_instances(self.ctxt, self.my_cell_state,
                self.build_inst_kwargs)

        self.assertEqual(8, call_info['num_tries'])
        self.assertEqual(self.instance_uuids, call_info['errored_uuids'])
                                                                                                                                                      
    def test_build_instances_numa_topology_not_none(self):
        self.build_inst_kwargs['instances'][0].numa_topology = 
            objects.InstanceNUMATopology()
        self.build_inst_kwargs['instances'][0].numa_topology.cells = 
            [objects.InstanceNUMACell(cpu_pinning_raw=None,cpu_topology=None,
            cpuset=set([0]),id=0,memory=64,pagesize=None)]
                fake_build_request_spec)

        self.msg_runner.build_instances(self.ctxt, self.my_cell_state,
                self.build_inst_kwargs)

        self.assertEqual(8, call_info['num_tries'])
        self.assertEqual(self.instance_uuids, call_info['errored_uuids'])
                                                                                                                                                      
    def test_build_instances_numa_topology_not_none(self):
        self.build_inst_kwargs['instances'][0].numa_topology = 
            objects.InstanceNUMATopology()
        self.build_inst_kwargs['instances'][0].numa_topology.cells = 
            [objects.InstanceNUMACell(cpu_pinning_raw=None,cpu_topology=None,
            cpuset=set([0]),id=0,memory=64,pagesize=None)]
        instance_topology = objects.InstanceNUMATopology()
        instance_topology.cells = [objects.InstanceNUMACell(cpu_pinning_raw=None,
            cpu_topology=None,cpuset=set([0]),id=0,memory=64,pagesize=None)] 
      
        self.msg_runner.build_instances(self.ctxt, self.my_cell_state, 
                                        self.build_inst_kwargs)
      
        self.assertEqual(instance_topology.cells[0]['cpu_pinning_raw'], 
                self.build_inst_kwargs['instances'][0].numa_topology.cells[0]['cpu_pinning_raw']) 
        self.assertEqual(instance_topology.cells[0]['cpu_topology'], 
                self.build_inst_kwargs['instances'][0].numa_topology.cells[0]['cpu_topology']) 
        self.assertEqual(instance_topology.cells[0]['cpuset'], 
               self.build_inst_kwargs['instances'][0].numa_topology.cells[0]['cpuset']) 
        self.assertEqual(instance_topology.cells[0]['id'], 
                self.build_inst_kwargs['instances'][0].numa_topology.cells[0]['id']) 
        self.assertEqual(instance_topology.cells[0]['memory'], 
                self.build_inst_kwargs['instances'][0].numa_topology.cells[0]['memory']) 
        self.assertEqual(instance_topology.cells[0]['pagesize'], 
Example #20
0
 def _instance_topology(self, mem):
     mem = mem * 1024
     return objects.InstanceNUMATopology(cells=[
         objects.InstanceNUMACell(id=0, cpuset=set([1]), memory=mem),
         objects.InstanceNUMACell(id=1, cpuset=set([3]), memory=mem)
     ])
Example #21
0
 def test_consume_requests_numa_failed(self):
     cells = [
         objects.InstanceNUMACell(
             id=0, cpuset=set(), pcpuset=set(), memory=0),
     ]
     self.assertIsNone(self.pci_stats.consume_requests(pci_requests, cells))
Example #22
0
import mock
from oslo_serialization import jsonutils

from nova import exception
from nova import objects
from nova.objects import fields
from nova.tests.unit.objects import test_objects

fake_instance_uuid = str(uuid.uuid4())

fake_obj_numa_topology = objects.InstanceNUMATopology(
    instance_uuid=fake_instance_uuid,
    cells=[
        objects.InstanceNUMACell(id=0,
                                 cpuset=set([1, 2]),
                                 memory=512,
                                 pagesize=2048),
        objects.InstanceNUMACell(id=1,
                                 cpuset=set([3, 4]),
                                 memory=512,
                                 pagesize=2048)
    ])

fake_numa_topology = fake_obj_numa_topology._to_dict()

fake_db_topology = {
    'created_at': None,
    'updated_at': None,
    'deleted_at': None,
    'deleted': 0,
    'id': 1,
Example #23
0
    1: flavors.save_flavor_info({}, _INSTANCE_TYPE_FIXTURES[1]),
    2: flavors.save_flavor_info({}, _INSTANCE_TYPE_FIXTURES[2]),
}

_MIGRATION_SYS_META = flavors.save_flavor_info({}, _INSTANCE_TYPE_FIXTURES[1],
                                               'old_')
_MIGRATION_SYS_META = flavors.save_flavor_info(_MIGRATION_SYS_META,
                                               _INSTANCE_TYPE_FIXTURES[2],
                                               'new_')

_2MB = 2 * units.Mi / units.Ki

_INSTANCE_NUMA_TOPOLOGIES = {
    '2mb':
    objects.InstanceNUMATopology(cells=[
        objects.InstanceNUMACell(
            id=0, cpuset=set([1]), memory=_2MB, pagesize=0),
        objects.InstanceNUMACell(
            id=1, cpuset=set([3]), memory=_2MB, pagesize=0)
    ]),
}

_NUMA_LIMIT_TOPOLOGIES = {
    '2mb':
    objects.NUMATopologyLimits(id=0,
                               cpu_allocation_ratio=1.0,
                               ram_allocation_ratio=1.0),
}

_NUMA_PAGE_TOPOLOGIES = {
    '2kb*8': objects.NUMAPagesTopology(size_kb=2, total=8, used=0)
}
Example #24
0
 def test_default_behavior(self):
     inst_cell = objects.InstanceNUMACell()
     self.assertEqual(0, len(inst_cell.obj_get_changes()))
Example #25
0
 def test_support_requests_numa_failed(self):
     cells = [objects.InstanceNUMACell(id=0, cpuset=set(), memory=0)]
     self.assertFalse(self.pci_stats.support_requests(pci_requests, cells))
Example #26
0
 def test_numa_topology_no_limit(self):
     huge_instance = objects.InstanceNUMATopology(cells=[
         objects.InstanceNUMACell(id=1, cpuset=set([1, 2]), memory=512)
     ])
     self._claim(numa_topology=huge_instance)
Example #27
0
 def test_consume_requests_numa_failed(self):
     cells = [objects.InstanceNUMACell(id=0, cpuset=set(), memory=0)]
     self.assertRaises(exception.PciDeviceRequestFailed,
                       self.pci_stats.consume_requests, pci_requests, cells)