'Check that when going from an Ocata installation with Ironic having
node\'s resource class attributes set, that we properly "auto-heal" the
inventory and allocation records in the placement API to account for
both the old-style VCPU/MEMORY_MB/DISK_GB resources as well as the new
custom resource class from Ironic\'s node.resource_class attribute.'

@mock.patch('nova.compute.utils.is_volume_backed_instance', return_value=False)
@mock.patch('nova.objects.compute_node.ComputeNode.save')
@mock.patch('keystoneauth1.session.Session.get_auth_headers', return_value={'x-auth-token': 'admin'})
@mock.patch('keystoneauth1.session.Session.get_endpoint', return_value='http://localhost/placement')
def test_ironic_ocata_to_pike(self, mock_vbi, mock_endpoint, mock_auth, mock_cn):

    with interceptor.RequestsInterceptor(app=self.app, url=self.url):
        self.assertEqual(0, len(self.rt.compute_nodes))
        for cn in self.COMPUTE_NODE_FIXTURES.values():
            self.assertEqual(404, self.placement_get_inventory(cn.uuid))
        for inst in self.INSTANCE_FIXTURES.keys():
            self.assertEqual({}, self.placement_get_allocations(inst))
        self.assertEqual(0, len(self.placement_get_custom_rcs()))
        for cn in self.COMPUTE_NODE_FIXTURES.values():
            nodename = cn.hypervisor_hostname
            self.driver_mock.get_available_resource.return_value = {'hypervisor_hostname': nodename, 'hypervisor_type': 'ironic', 'hypervisor_version': 0, 'vcpus': cn.vcpus, 'vcpus_used': cn.vcpus_used, 'memory_mb': cn.memory_mb, 'memory_mb_used': cn.memory_mb_used, 'local_gb': cn.local_gb, 'local_gb_used': cn.local_gb_used, 'numa_topology': None, 'resource_class': None}
            self.driver_mock.get_inventory.return_value = {VCPU: {'total': cn.vcpus, 'reserved': 0, 'min_unit': 1, 'max_unit': cn.vcpus, 'step_size': 1, 'allocation_ratio': 1.0}, MEMORY_MB: {'total': cn.memory_mb, 'reserved': 0, 'min_unit': 1, 'max_unit': cn.memory_mb, 'step_size': 1, 'allocation_ratio': 1.0}, DISK_GB: {'total': cn.local_gb, 'reserved': 0, 'min_unit': 1, 'max_unit': cn.local_gb, 'step_size': 1, 'allocation_ratio': 1.0}}
            self.rt.update_available_resource(self.ctx, nodename)
        self.assertEqual(3, len(self.rt.compute_nodes))
        crcs = self.placement_get_custom_rcs()
        self.assertNotIn('CUSTOM_SMALL_IRON', crcs)
        for cn in self.COMPUTE_NODE_FIXTURES.values():
            inv = self.placement_get_inventory(cn.uuid)
            self.assertEqual(3, len(inv))
        cn1_obj = self.COMPUTE_NODE_FIXTURES[uuids.cn1]
        cn1_nodename = cn1_obj.hypervisor_hostname
        inst = self.INSTANCE_FIXTURES[uuids.instance1]
        with self.rt.instance_claim(self.ctx, inst, cn1_nodename):
            pass
        allocs = self.placement_get_allocations(inst.uuid)
        self.assertEqual(1, len(allocs))
        self.assertIn(uuids.cn1, allocs)
        resources = allocs[uuids.cn1]['resources']
        self.assertEqual(3, len(resources))
        for rc in (VCPU, MEMORY_MB, DISK_GB):
            self.assertIn(rc, resources)
        self.driver_mock.get_available_resource.return_value = {'hypervisor_hostname': cn1_obj.hypervisor_hostname, 'hypervisor_type': 'ironic', 'hypervisor_version': 0, 'vcpus': cn1_obj.vcpus, 'vcpus_used': cn1_obj.vcpus_used, 'memory_mb': cn1_obj.memory_mb, 'memory_mb_used': cn1_obj.memory_mb_used, 'local_gb': cn1_obj.local_gb, 'local_gb_used': cn1_obj.local_gb_used, 'numa_topology': None, 'resource_class': 'small-iron'}
        self.driver_mock.get_inventory.return_value = {VCPU: {'total': cn1_obj.vcpus, 'reserved': 0, 'min_unit': 1, 'max_unit': cn1_obj.vcpus, 'step_size': 1, 'allocation_ratio': 1.0}, MEMORY_MB: {'total': cn1_obj.memory_mb, 'reserved': 0, 'min_unit': 1, 'max_unit': cn1_obj.memory_mb, 'step_size': 1, 'allocation_ratio': 1.0}, DISK_GB: {'total': cn1_obj.local_gb, 'reserved': 0, 'min_unit': 1, 'max_unit': cn1_obj.local_gb, 'step_size': 1, 'allocation_ratio': 1.0}, 'CUSTOM_SMALL_IRON': {'total': 1, 'reserved': 0, 'min_unit': 1, 'max_unit': 1, 'step_size': 1, 'allocation_ratio': 1.0}}
        self.rt.update_available_resource(self.ctx, cn1_nodename)
        self.assertIn('CUSTOM_SMALL_IRON', self.placement_get_custom_rcs())
        allocs = self.placement_get_allocations(inst.uuid)
        self.assertEqual(1, len(allocs))
        self.assertIn(uuids.cn1, allocs)
        resources = allocs[uuids.cn1]['resources']
        self.assertEqual(3, len(resources))
        for rc in (VCPU, MEMORY_MB, DISK_GB):
            self.assertIn(rc, resources)
