Fixing the placement of instance on spawn
- Fixed the placement of nova instances on correct composed nodes - Tracks the resources of correct provider in placement - Updated unit tests Change-Id: If27e1c4b45680a0011dfed0a0ca611d7636c8eb1 Signed-off-by: Helena McGough <helena.mcgough@intel.com>
This commit is contained in:
parent
31d08ff0d4
commit
97ab8e835e
|
@ -60,13 +60,14 @@ CONF = cfg.CONF
|
|||
class FakeInstance(object):
|
||||
"""A class to fake out nova instances."""
|
||||
|
||||
def __init__(self, name, state, uuid, new_flavor):
|
||||
def __init__(self, name, state, uuid, new_flavor, node):
|
||||
"""Initialize the variables for fake instances."""
|
||||
self.name = name
|
||||
self.power_state = state
|
||||
self.uuid = uuid
|
||||
self.display_description = None
|
||||
self.flavor = new_flavor
|
||||
self.node = node
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Method to retrieve fake instance variables."""
|
||||
|
@ -110,7 +111,8 @@ class TestRSDDriver(base.BaseTestCase):
|
|||
mock_connector.return_value = self.root_conn
|
||||
|
||||
# Create sample collections and instances of Chassis/System/Nodes
|
||||
with open('rsd_virt_for_nova/tests/json_samples/root.json', 'r') as f:
|
||||
with open('rsd_virt_for_nova/tests/json_samples/root.json',
|
||||
'r') as f:
|
||||
self.root_conn.get.return_value.json.return_value = json.loads(
|
||||
f.read())
|
||||
self.rsd = rsd_lib.main.RSDLib('http://foo.bar:8442', username='foo',
|
||||
|
@ -188,10 +190,11 @@ class TestRSDDriver(base.BaseTestCase):
|
|||
self.system_inst.identity,
|
||||
spec)
|
||||
self.inst1 = FakeInstance('inst1', power_state.RUNNING,
|
||||
'inst1id', self.flavor)
|
||||
'inst1id', self.flavor,
|
||||
"/redfish/v1/Chassis/Chassis1")
|
||||
self.invalid_inst = FakeInstance(
|
||||
'inv_inst', power_state.RUNNING, 'inv_inst_id',
|
||||
self.flavor)
|
||||
self.flavor, "/redfish/v1/Chassis/Chassis1")
|
||||
self.RSD.instances = {self.inst1.uuid: self.inst1}
|
||||
|
||||
# A provider tree for testing on the placement API
|
||||
|
@ -320,9 +323,15 @@ class TestRSDDriver(base.BaseTestCase):
|
|||
node_col.members_identities = ['/redfish/v1/Nodes/Node1']
|
||||
self.RSD.driver.PODM.get_node.return_value = self.node_ass_inst
|
||||
mock_context = context.get_admin_context()
|
||||
self.RSD.rsd_flavors = {self.flavor.flavorid: {
|
||||
'id': 'flav_id',
|
||||
'rsd_systems': [self.system_inst.identity]}}
|
||||
self.RSD.rsd_flavors = {
|
||||
self.flavor.flavorid: {
|
||||
'id': 'flav_id',
|
||||
'rsd_systems': {
|
||||
'/redfish/v1/Chassis/Chassis1':
|
||||
self.system_inst.identity
|
||||
}
|
||||
}
|
||||
}
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
# Run spawning test
|
||||
self.RSD.spawn(mock_context, self.inst1, image_meta,
|
||||
|
@ -695,18 +704,23 @@ class TestRSDDriver(base.BaseTestCase):
|
|||
'/redfish/v1/Systems/System3',
|
||||
'/redfish/v1/Systems/System4'])
|
||||
|
||||
@mock.patch.object(driver.RSDDriver, 'check_chassis_systems')
|
||||
@mock.patch.object(context, 'get_admin_context')
|
||||
@mock.patch.object(flavor.Flavor, '_flavor_get_by_flavor_id_from_db')
|
||||
@mock.patch.object(flavor, '_flavor_create')
|
||||
@mock.patch.object(fields.ResourceClass, 'normalize_name')
|
||||
@mock.patch.object(driver.RSDDriver, 'conv_GiB_to_MiB')
|
||||
def test_create_flavors_success(self, conv_mem, norm_name, flav_create,
|
||||
get_flav, admin_context):
|
||||
get_flav, admin_context, check_chas):
|
||||
"""Test creation of new flavors for a System, success."""
|
||||
# Set up the mock objects for a sucessful creation test
|
||||
sys_col = self.RSD.driver.PODM.get_system_collection.return_value
|
||||
chas_col = self.RSD.driver.PODM.get_chassis_collection.return_value
|
||||
chas_col.members_identities = ['/redfish/v1/Chassis/Chassis1']
|
||||
sys_col.members_identities = ['/redfish/v1/Systems/System1']
|
||||
sys_col.get_member.return_value = self.system_inst
|
||||
chas_col.get_member.return_value = self.chassis_inst
|
||||
check_chas.return_value = ['/redfish/v1/Systems/System1']
|
||||
spec = 'resources:' + norm_name.return_value
|
||||
mem = conv_mem.return_value - 512
|
||||
proc = self.system_inst.processors.summary.count
|
||||
|
@ -716,6 +730,9 @@ class TestRSDDriver(base.BaseTestCase):
|
|||
|
||||
# Check the function calls for the test
|
||||
self.RSD.driver.PODM.get_system_collection.assert_called_once()
|
||||
self.RSD.driver.PODM.get_chassis_collection.assert_called()
|
||||
chas_col.get_member.assert_called_with('/redfish/v1/Chassis/Chassis1')
|
||||
check_chas.assert_called()
|
||||
sys_col.get_member.assert_called_with('/redfish/v1/Systems/System1')
|
||||
conv_mem.assert_called_with(self.system_inst.memory_summary.size_gib)
|
||||
norm_name.assert_called_with(flav_id)
|
||||
|
@ -732,49 +749,6 @@ class TestRSDDriver(base.BaseTestCase):
|
|||
'extra_specs': {spec: '1'}})
|
||||
get_flav.assert_not_called()
|
||||
|
||||
@mock.patch.object(context, 'get_admin_context')
|
||||
@mock.patch.object(flavor.Flavor, '_flavor_get_by_flavor_id_from_db')
|
||||
@mock.patch.object(flavor, '_flavor_create')
|
||||
@mock.patch.object(fields.ResourceClass, 'normalize_name')
|
||||
@mock.patch.object(driver.RSDDriver, 'conv_GiB_to_MiB')
|
||||
def test_create_flavors_exists(self, conv_mem, norm_name, flav_create,
|
||||
get_flav, admin_context):
|
||||
"""Test failing to create a flavor that already exists."""
|
||||
# Set up mocks to ensure flavors fail to be created
|
||||
sys_col = self.RSD.driver.PODM.get_system_collection.return_value
|
||||
sys_col.members_identities = ['/redfish/v1/Systems/System1']
|
||||
sys_col.get_member.return_value = self.system_inst
|
||||
spec = 'resources:' + norm_name.return_value
|
||||
mem = conv_mem.return_value - 512
|
||||
proc = self.system_inst.processors.summary.count
|
||||
flav_id = str(mem) + 'MB-' + str(proc) + 'vcpus'
|
||||
self.RSD.rsd_flavors = {flav_id: {
|
||||
'id': flav_create.return_value['id'],
|
||||
'rsd_systems': [self.system_inst.identity]
|
||||
}}
|
||||
flav_create.return_value = Exception
|
||||
# Run test to try and create new flavors based on available systems
|
||||
self.RSD._create_flavors()
|
||||
|
||||
# Confirm no new flavors have been created
|
||||
self.RSD.driver.PODM.get_system_collection.assert_called_once()
|
||||
sys_col.get_member.assert_called_with('/redfish/v1/Systems/System1')
|
||||
conv_mem.assert_called_with(self.system_inst.memory_summary.size_gib)
|
||||
norm_name.assert_called_with(flav_id)
|
||||
admin_context.assert_called()
|
||||
|
||||
# Flavor creation call check
|
||||
flav_create.assert_called_once_with(
|
||||
admin_context.return_value,
|
||||
{'name': 'RSD-' + flav_id,
|
||||
'flavorid': flav_id,
|
||||
'memory_mb': mem,
|
||||
'vcpus': self.system_inst.processors.summary.count,
|
||||
'root_gb': 0,
|
||||
'extra_specs': {spec: '1'}})
|
||||
# Confirm that the flavor already exists
|
||||
get_flav.assert_called_once_with(admin_context.return_value, flav_id)
|
||||
|
||||
@mock.patch.object(flavor.Flavor, '_flavor_get_by_flavor_id_from_db')
|
||||
@mock.patch.object(flavor, '_flavor_create')
|
||||
@mock.patch.object(fields.ResourceClass, 'normalize_name')
|
||||
|
@ -818,8 +792,14 @@ class TestRSDDriver(base.BaseTestCase):
|
|||
sys_col = self.RSD.driver.PODM.get_system_collection.return_value
|
||||
sys_col.get_member.return_value = self.system_inst
|
||||
self.RSD.rsd_flavors = {
|
||||
'mock_flav_id': {'id': 'flav_id',
|
||||
'rsd_systems': [self.system_inst.identity]}}
|
||||
'mock_flav_id': {
|
||||
'id': 'flav_id',
|
||||
'rsd_systems': {
|
||||
'/redfish/v1/Chassis/Chassis1':
|
||||
self.system_inst.identity
|
||||
}
|
||||
}
|
||||
}
|
||||
self.RSD.check_flavors(sys_col, ['/redfish/v1/Systems/System1'])
|
||||
|
||||
# Confirm the list of available flavors
|
||||
|
@ -827,4 +807,4 @@ class TestRSDDriver(base.BaseTestCase):
|
|||
get_context.assert_called()
|
||||
flav_list.assert_called_with(get_context.return_value)
|
||||
sys_col.get_member.assert_called_with('/redfish/v1/Systems/System1')
|
||||
flav_destroy.assert_not_called()
|
||||
flav_destroy.assert_called()
|
||||
|
|
|
@ -75,6 +75,7 @@ class RSDDriver(driver.ComputeDriver):
|
|||
self.driver = rsd.PODM_connection()
|
||||
self.instances = OrderedDict()
|
||||
self.rsd_flavors = OrderedDict()
|
||||
self.chas_systems = OrderedDict()
|
||||
self._nodes = []
|
||||
self._composed_nodes = OrderedDict()
|
||||
self.instance_node = None
|
||||
|
@ -136,7 +137,7 @@ class RSDDriver(driver.ComputeDriver):
|
|||
COMPOSED_NODE_COL = self.driver.PODM.get_node_collection()
|
||||
node_inst = None
|
||||
flav_id = instance.flavor.flavorid
|
||||
sys_list = self.rsd_flavors[flav_id]['rsd_systems']
|
||||
sys_list = self.rsd_flavors[flav_id]['rsd_systems'][instance.node]
|
||||
for n in COMPOSED_NODE_COL.members_identities:
|
||||
try:
|
||||
node_inst = self.driver.PODM.get_node(n)
|
||||
|
@ -194,6 +195,7 @@ class RSDDriver(driver.ComputeDriver):
|
|||
def get_available_resource(self, nodename):
|
||||
"""Update compute manager resource info on ComputeNode table."""
|
||||
cpu_info = ''
|
||||
cha_sys = []
|
||||
|
||||
SYSTEM_COL = self.driver.PODM.get_system_collection()
|
||||
members = SYSTEM_COL.members_identities
|
||||
|
@ -434,46 +436,66 @@ class RSDDriver(driver.ComputeDriver):
|
|||
def _create_flavors(self):
|
||||
"""Auto-generate the flavors for the compute systems available."""
|
||||
SYSTEM_COL = self.driver.PODM.get_system_collection()
|
||||
for s in SYSTEM_COL.members_identities:
|
||||
sys = SYSTEM_COL.get_member(s)
|
||||
mem = self.conv_GiB_to_MiB(sys.memory_summary.size_gib) - 512
|
||||
proc = sys.processors.summary.count
|
||||
flav_id = str(mem) + 'MB-' + str(proc) + 'vcpus'
|
||||
res = fields.ResourceClass.normalize_name(flav_id)
|
||||
spec = 'resources:' + res
|
||||
values = {
|
||||
'name': 'RSD-' + flav_id,
|
||||
'flavorid': flav_id,
|
||||
'memory_mb': mem,
|
||||
'vcpus': proc,
|
||||
'root_gb': 0,
|
||||
'extra_specs': {
|
||||
spec: '1'}
|
||||
}
|
||||
if sys.identity not in self.rsd_flavors:
|
||||
try:
|
||||
LOG.debug("New flavor for system: %s", sys.identity)
|
||||
rsd_flav = flavor._flavor_create(
|
||||
context.get_admin_context(), values)
|
||||
self.rsd_flavors[flav_id] = {
|
||||
'id': rsd_flav['id'],
|
||||
'rsd_systems': [sys.identity]
|
||||
}
|
||||
self._nodes = self._init_nodes()
|
||||
except Exception as ex:
|
||||
LOG.debug(
|
||||
"A flavor already exists for this rsd system: %s", ex)
|
||||
ex_flav = flavor.Flavor._flavor_get_by_flavor_id_from_db(
|
||||
context.get_admin_context(), flav_id)
|
||||
if flav_id not in self.rsd_flavors.keys():
|
||||
CHASSIS_COL = self.driver.PODM.get_chassis_collection()
|
||||
for c in CHASSIS_COL.members_identities:
|
||||
chas = CHASSIS_COL.get_member(c)
|
||||
cha_sys = self.check_chassis_systems(chas)
|
||||
|
||||
for s in cha_sys:
|
||||
sys = SYSTEM_COL.get_member(s)
|
||||
mem = self.conv_GiB_to_MiB(sys.memory_summary.size_gib) - 512
|
||||
proc = sys.processors.summary.count
|
||||
flav_id = str(mem) + 'MB-' + str(proc) + 'vcpus'
|
||||
res = fields.ResourceClass.normalize_name(flav_id)
|
||||
spec = 'resources:' + res
|
||||
values = {
|
||||
'name': 'RSD-' + flav_id,
|
||||
'flavorid': flav_id,
|
||||
'memory_mb': mem,
|
||||
'vcpus': proc,
|
||||
'root_gb': 0,
|
||||
'extra_specs': {
|
||||
spec: '1'}
|
||||
}
|
||||
if sys.identity not in self.rsd_flavors:
|
||||
try:
|
||||
LOG.debug("New flavor for system: %s", sys.identity)
|
||||
flavor._flavor_create(
|
||||
context.get_admin_context(), values)
|
||||
self.chas_systems[str(chas.path)] = [str(sys.identity)]
|
||||
self.rsd_flavors[flav_id] = {
|
||||
'id': ex_flav['id'],
|
||||
'rsd_systems': [sys.identity]
|
||||
'rsd_systems': self.chas_systems
|
||||
}
|
||||
else:
|
||||
sys_list = self.rsd_flavors[flav_id]['rsd_systems']
|
||||
sys_list.append(sys.identity)
|
||||
self.rsd_flavors[flav_id]['rsd_systems'] = sys_list
|
||||
self._nodes = self._init_nodes()
|
||||
except Exception as ex:
|
||||
LOG.debug(
|
||||
"A flavor already exists for this system: %s", ex)
|
||||
flavor.Flavor._flavor_get_by_flavor_id_from_db(
|
||||
context.get_admin_context(), flav_id)
|
||||
if flav_id not in self.rsd_flavors.keys():
|
||||
self.chas_systems[str(chas.path)] = [
|
||||
str(sys.identity)]
|
||||
self.rsd_flavors[flav_id] = {
|
||||
'rsd_systems': self.chas_systems
|
||||
}
|
||||
|
||||
else:
|
||||
chassis_ = self.rsd_flavors[flav_id]['rsd_systems']
|
||||
if str(chas.path) not in chassis_.keys():
|
||||
self.chas_systems[str(chas.path)] = [
|
||||
str(sys.identity)]
|
||||
self.rsd_flavors[flav_id] = {
|
||||
'rsd_systems': self.chas_systems
|
||||
}
|
||||
else:
|
||||
systems = self.rsd_flavors[
|
||||
flav_id]['rsd_systems'][str(chas.path)]
|
||||
if str(sys.identity) not in systems:
|
||||
systems.append(str(sys.identity))
|
||||
self.chas_systems[str(chas.path)] = systems
|
||||
self.rsd_flavors[flav_id] = {
|
||||
'rsd_systems': self.chas_systems
|
||||
}
|
||||
|
||||
def check_flavors(self, collection, systems):
|
||||
"""Check if flavors should be deleted based on system removal."""
|
||||
|
@ -500,15 +522,18 @@ class RSDDriver(driver.ComputeDriver):
|
|||
LOG.warn("Flavor not found exception: %s", ex)
|
||||
|
||||
for k in list(self.rsd_flavors):
|
||||
sys_list = self.rsd_flavors[k]['rsd_systems']
|
||||
for s in sys_list:
|
||||
if s not in sys_ids:
|
||||
try:
|
||||
rsd_id = self.rsd_flavors[k]['id']
|
||||
flavor._flavor_destroy(
|
||||
context.get_admin_context(), rsd_id)
|
||||
LOG.debug("Deleting flavor for removed systems: %s", k)
|
||||
del self.rsd_flavors[k]
|
||||
except KeyError as k_ex:
|
||||
LOG.warn("Flavor has already been deleted:%s", k_ex)
|
||||
if k in self.rsd_flavors.keys():
|
||||
chas_list = self.rsd_flavors[k]['rsd_systems'].keys()
|
||||
for c in chas_list:
|
||||
sys_list = self.rsd_flavors[k]['rsd_systems'][c]
|
||||
for s in sys_list:
|
||||
if s not in sys_ids:
|
||||
try:
|
||||
rsd_id = self.rsd_flavors[k]['id']
|
||||
flavor._flavor_destroy(
|
||||
context.get_admin_context(), rsd_id)
|
||||
LOG.debug("Deleting flavor: %s", k)
|
||||
del self.rsd_flavors[k]
|
||||
except KeyError as k_ex:
|
||||
LOG.warn("Flavor doesn't exist:%s", k_ex)
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue