Expose Allocation objects on Instance
Change-Id: If62a6829478c532428aff2f5f51edc35df8ee2e1
This commit is contained in:
parent
ce77bf8e1e
commit
1afa4ac4ed
@ -25,6 +25,9 @@ Installation
|
||||
|
||||
pip install --user metalsmith
|
||||
|
||||
.. note::
|
||||
The current versions of *metalsmith* require Bare Metal API from the Stein
|
||||
release or newer. Use the 0.11 release series for older versions.
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
@ -5,7 +5,7 @@ fixtures==3.0.0
|
||||
flake8-import-order==0.13
|
||||
hacking==1.0.0
|
||||
mock==2.0
|
||||
openstacksdk==0.22.0
|
||||
openstacksdk==0.25.0
|
||||
pbr==2.0.0
|
||||
Pygments==2.2.0
|
||||
requests==2.18.4
|
||||
|
@ -86,10 +86,16 @@ _DEPLOYED_STATES = frozenset([InstanceState.ACTIVE, InstanceState.MAINTENANCE])
|
||||
class Instance(object):
|
||||
"""Instance status in metalsmith."""
|
||||
|
||||
def __init__(self, connection, node):
|
||||
def __init__(self, connection, node, allocation=None):
|
||||
self._connection = connection
|
||||
self._uuid = node.id
|
||||
self._node = node
|
||||
self._allocation = allocation
|
||||
|
||||
@property
|
||||
def allocation(self):
|
||||
"""Allocation object associated with the node (if any)."""
|
||||
return self._allocation
|
||||
|
||||
@property
|
||||
def hostname(self):
|
||||
@ -163,6 +169,8 @@ class Instance(object):
|
||||
def to_dict(self):
|
||||
"""Convert instance to a dict."""
|
||||
return {
|
||||
'allocation': (self._allocation.to_dict()
|
||||
if self._allocation is not None else None),
|
||||
'hostname': self.hostname,
|
||||
'ip_addresses': self.ip_addresses(),
|
||||
'node': self._node.to_dict(),
|
||||
|
@ -332,6 +332,7 @@ class Provisioner(_utils.GetNodeMixin):
|
||||
else:
|
||||
# Update the node to return it's latest state
|
||||
node = self._get_node(node, refresh=True)
|
||||
# We don't create allocations yet, so don't use _get_instance.
|
||||
instance = _instance.Instance(self.connection, node)
|
||||
|
||||
return instance
|
||||
@ -358,7 +359,9 @@ class Provisioner(_utils.GetNodeMixin):
|
||||
nodes = [self._get_node(n, accept_hostname=True) for n in nodes]
|
||||
nodes = self.connection.baremetal.wait_for_nodes_provision_state(
|
||||
nodes, 'active', timeout=timeout)
|
||||
return [_instance.Instance(self.connection, node) for node in nodes]
|
||||
# Using _get_instance in case the deployment started by something
|
||||
# external that uses allocations.
|
||||
return [self._get_instance(node) for node in nodes]
|
||||
|
||||
def _clean_instance_info(self, instance_info):
|
||||
return {key: value
|
||||
@ -426,6 +429,16 @@ class Provisioner(_utils.GetNodeMixin):
|
||||
"""
|
||||
return self.show_instances([instance_id])[0]
|
||||
|
||||
def _get_instance(self, ident):
|
||||
node = self._get_node(ident, accept_hostname=True)
|
||||
if node.allocation_id:
|
||||
allocation = self.connection.baremetal.get_allocation(
|
||||
node.allocation_id)
|
||||
else:
|
||||
allocation = None
|
||||
return _instance.Instance(self.connection, node,
|
||||
allocation=allocation)
|
||||
|
||||
def show_instances(self, instances):
|
||||
"""Show information about instance.
|
||||
|
||||
@ -439,12 +452,7 @@ class Provisioner(_utils.GetNodeMixin):
|
||||
if one of the instances are not valid instances.
|
||||
"""
|
||||
with self._cache_node_list_for_lookup():
|
||||
result = [
|
||||
_instance.Instance(
|
||||
self.connection,
|
||||
self._get_node(inst, accept_hostname=True))
|
||||
for inst in instances
|
||||
]
|
||||
result = [self._get_instance(inst) for inst in instances]
|
||||
# NOTE(dtantsur): do not accept node names as valid instances if they
|
||||
# are not deployed or being deployed.
|
||||
missing = [inst for (res, inst) in zip(result, instances)
|
||||
@ -461,8 +469,6 @@ class Provisioner(_utils.GetNodeMixin):
|
||||
:return: list of :py:class:`metalsmith.Instance` objects.
|
||||
"""
|
||||
nodes = self.connection.baremetal.nodes(associated=True, details=True)
|
||||
instances = [i for i in
|
||||
(_instance.Instance(self.connection, node)
|
||||
for node in nodes)
|
||||
instances = [i for i in map(self._get_instance, nodes)
|
||||
if i.state != _instance.InstanceState.UNKNOWN]
|
||||
return instances
|
||||
|
@ -129,7 +129,28 @@ class TestInstanceStates(test_provisioner.Base):
|
||||
mock_ips.return_value = {'private': ['1.2.3.4']}
|
||||
|
||||
to_dict = self.instance.to_dict()
|
||||
self.assertEqual({'hostname': 'host',
|
||||
self.assertEqual({'allocation': None,
|
||||
'hostname': 'host',
|
||||
'ip_addresses': {'private': ['1.2.3.4']},
|
||||
'node': {'node': 'dict'},
|
||||
'state': 'deploying',
|
||||
'uuid': self.node.id},
|
||||
to_dict)
|
||||
# States are converted to strings
|
||||
self.assertIsInstance(to_dict['state'], six.string_types)
|
||||
|
||||
@mock.patch.object(_instance.Instance, 'ip_addresses', autospec=True)
|
||||
def test_to_dict_with_allocation(self, mock_ips):
|
||||
self.node.provision_state = 'wait call-back'
|
||||
self.node.to_dict.return_value = {'node': 'dict'}
|
||||
self.node.instance_info = {'metalsmith_hostname': 'host'}
|
||||
mock_ips.return_value = {'private': ['1.2.3.4']}
|
||||
self.instance._allocation = mock.Mock()
|
||||
self.instance._allocation.to_dict.return_value = {'alloc': 'dict'}
|
||||
|
||||
to_dict = self.instance.to_dict()
|
||||
self.assertEqual({'allocation': {'alloc': 'dict'},
|
||||
'hostname': 'host',
|
||||
'ip_addresses': {'private': ['1.2.3.4']},
|
||||
'node': {'node': 'dict'},
|
||||
'state': 'deploying',
|
||||
|
@ -29,7 +29,8 @@ from metalsmith import sources
|
||||
|
||||
NODE_FIELDS = ['name', 'id', 'instance_info', 'instance_id', 'is_maintenance',
|
||||
'maintenance_reason', 'properties', 'provision_state', 'extra',
|
||||
'last_error', 'traits', 'resource_class', 'conductor_group']
|
||||
'last_error', 'traits', 'resource_class', 'conductor_group',
|
||||
'allocation_id']
|
||||
|
||||
|
||||
class TestInit(testtools.TestCase):
|
||||
@ -66,7 +67,8 @@ class Base(testtools.TestCase):
|
||||
id='000', instance_id=None,
|
||||
properties={'local_gb': 100},
|
||||
instance_info={},
|
||||
is_maintenance=False, extra={})
|
||||
is_maintenance=False, extra={},
|
||||
allocation_id=None)
|
||||
self.node.name = 'control-0'
|
||||
|
||||
def _reset_api_mock(self):
|
||||
@ -1386,6 +1388,19 @@ class TestShowInstance(Base):
|
||||
self.assertIs(inst.node, self.node)
|
||||
self.assertIs(inst.uuid, self.node.id)
|
||||
|
||||
def test_show_instance_with_allocation(self):
|
||||
self.node.allocation_id = 'id2'
|
||||
self.mock_get_node.side_effect = lambda n, *a, **kw: self.node
|
||||
inst = self.pr.show_instance('id1')
|
||||
self.mock_get_node.assert_called_once_with(self.pr, 'id1',
|
||||
accept_hostname=True)
|
||||
self.api.baremetal.get_allocation.assert_called_once_with('id2')
|
||||
self.assertIsInstance(inst, _instance.Instance)
|
||||
self.assertIs(inst.allocation,
|
||||
self.api.baremetal.get_allocation.return_value)
|
||||
self.assertIs(inst.node, self.node)
|
||||
self.assertIs(inst.uuid, self.node.id)
|
||||
|
||||
def test_show_instances(self):
|
||||
self.mock_get_node.side_effect = [self.node, self.node]
|
||||
result = self.pr.show_instances(['1', '2'])
|
||||
@ -1415,10 +1430,11 @@ class TestListInstances(Base):
|
||||
super(TestListInstances, self).setUp()
|
||||
self.nodes = [
|
||||
mock.Mock(spec=NODE_FIELDS, provision_state=state,
|
||||
instance_id='1234')
|
||||
instance_id='1234', allocation_id=None)
|
||||
for state in ('active', 'active', 'deploying', 'wait call-back',
|
||||
'deploy failed', 'available', 'available', 'enroll')
|
||||
]
|
||||
self.nodes[0].allocation_id = 'id2'
|
||||
self.nodes[6].instance_id = None
|
||||
self.api.baremetal.nodes.return_value = self.nodes
|
||||
|
||||
@ -1426,5 +1442,8 @@ class TestListInstances(Base):
|
||||
instances = self.pr.list_instances()
|
||||
self.assertTrue(isinstance(i, _instance.Instance) for i in instances)
|
||||
self.assertEqual(self.nodes[:6], [i.node for i in instances])
|
||||
self.assertEqual([self.api.baremetal.get_allocation.return_value]
|
||||
+ [None] * 5,
|
||||
[i.allocation for i in instances])
|
||||
self.api.baremetal.nodes.assert_called_once_with(associated=True,
|
||||
details=True)
|
||||
|
@ -2,7 +2,7 @@
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
||||
openstacksdk>=0.22.0 # Apache-2.0
|
||||
openstacksdk>=0.25.0 # Apache-2.0
|
||||
requests>=2.18.4 # Apache-2.0
|
||||
six>=1.10.0 # MIT
|
||||
enum34>=1.0.4;python_version=='2.7' or python_version=='2.6' or python_version=='3.3' # BSD
|
||||
|
Loading…
Reference in New Issue
Block a user