Implement list_instances and `metalsmith list`
Change-Id: I51f83fcebf665be8b290774433fbf1da5108ec27 Story: #2003585 Task: #24891
This commit is contained in:
parent
06a19626cd
commit
d20abe3c79
|
@ -85,6 +85,11 @@ def _do_wait(api, args, formatter):
|
|||
formatter.show(instances)
|
||||
|
||||
|
||||
def _do_list(api, args, formatter):
|
||||
instances = api.list_instances()
|
||||
formatter.show(instances)
|
||||
|
||||
|
||||
def _parse_args(args, config):
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Deployment and Scheduling tool for Bare Metal')
|
||||
|
@ -151,6 +156,9 @@ def _parse_args(args, config):
|
|||
show.set_defaults(func=_do_show)
|
||||
show.add_argument('instance', nargs='+', help='instance UUID(s)')
|
||||
|
||||
show = subparsers.add_parser('list')
|
||||
show.set_defaults(func=_do_list)
|
||||
|
||||
wait = subparsers.add_parser('wait')
|
||||
wait.set_defaults(func=_do_wait)
|
||||
wait.add_argument('instance', nargs='+', help='instance UUID(s)')
|
||||
|
|
|
@ -16,14 +16,15 @@
|
|||
from metalsmith import _os_api
|
||||
|
||||
|
||||
_PROGRESS_STATES = frozenset(['deploying', 'wait call-back',
|
||||
'deploy complete'])
|
||||
# NOTE(dtantsur): include available since there is a period of time between
|
||||
# claiming the instance and starting the actual provisioning via ironic.
|
||||
_DEPLOYING_STATES = frozenset(['available', 'deploying', 'wait call-back',
|
||||
'deploy complete'])
|
||||
_DEPLOYING_STATES = _PROGRESS_STATES | {'available'}
|
||||
_ACTIVE_STATES = frozenset(['active'])
|
||||
_ERROR_STATE = frozenset(['error', 'deploy failed'])
|
||||
_ERROR_STATES = frozenset(['error', 'deploy failed'])
|
||||
|
||||
_HEALTHY_STATES = frozenset(['deploying', 'active'])
|
||||
_HEALTHY_STATES = _PROGRESS_STATES | _ACTIVE_STATES
|
||||
|
||||
|
||||
class Instance(object):
|
||||
|
@ -58,6 +59,10 @@ class Instance(object):
|
|||
"""Whether the node is deployed."""
|
||||
return self._node.provision_state in _ACTIVE_STATES
|
||||
|
||||
@property
|
||||
def _is_deployed_by_metalsmith(self):
|
||||
return _os_api.HOSTNAME_FIELD in self._node.instance_info
|
||||
|
||||
@property
|
||||
def is_healthy(self):
|
||||
"""Whether the node is not at fault or maintenance."""
|
||||
|
@ -101,7 +106,7 @@ class Instance(object):
|
|||
prov_state = self._node.provision_state
|
||||
if prov_state in _DEPLOYING_STATES:
|
||||
return 'deploying'
|
||||
elif prov_state in _ERROR_STATE:
|
||||
elif prov_state in _ERROR_STATES:
|
||||
return 'error'
|
||||
elif prov_state in _ACTIVE_STATES:
|
||||
if self._node.maintenance:
|
||||
|
|
|
@ -506,3 +506,14 @@ class Provisioner(object):
|
|||
self._api.get_node(inst, accept_hostname=True))
|
||||
for inst in instances
|
||||
]
|
||||
|
||||
def list_instances(self):
|
||||
"""List instances deployed by metalsmith.
|
||||
|
||||
:return: list of :py:class:`metalsmith.Instance` objects.
|
||||
"""
|
||||
nodes = self._api.list_nodes(provision_state=None, associated=True)
|
||||
instances = [i for i in
|
||||
(_instance.Instance(self._api, node) for node in nodes)
|
||||
if i._is_deployed_by_metalsmith]
|
||||
return instances
|
||||
|
|
|
@ -751,6 +751,18 @@ class TestShowWait(testtools.TestCase):
|
|||
mock_pr.return_value.show_instances.assert_called_once_with(
|
||||
['uuid1', 'hostname2'])
|
||||
|
||||
def test_list(self, mock_os_conf, mock_pr):
|
||||
mock_pr.return_value.list_instances.return_value = self.instances
|
||||
args = ['list']
|
||||
_cmd.main(args)
|
||||
|
||||
self.mock_print.assert_has_calls([
|
||||
mock.call(mock.ANY, node='name-1 (UUID 1)', state='active'),
|
||||
mock.call(mock.ANY, ips='private=1.2.3.4'),
|
||||
mock.call(mock.ANY, node='name-2 (UUID 2)', state='deploying'),
|
||||
])
|
||||
mock_pr.return_value.list_instances.assert_called_once_with()
|
||||
|
||||
def test_wait(self, mock_os_conf, mock_pr):
|
||||
mock_pr.return_value.wait_for_provisioning.return_value = (
|
||||
self.instances)
|
||||
|
@ -790,6 +802,18 @@ class TestShowWait(testtools.TestCase):
|
|||
{'hostname1': {'1': 'name-1'},
|
||||
'hostname2': {'2': 'name-2'}})
|
||||
|
||||
def test_list_json(self, mock_os_conf, mock_pr):
|
||||
mock_pr.return_value.list_instances.return_value = self.instances
|
||||
args = ['--format', 'json', 'list']
|
||||
|
||||
fake_io = six.StringIO()
|
||||
with mock.patch('sys.stdout', fake_io):
|
||||
_cmd.main(args)
|
||||
self.assertEqual(json.loads(fake_io.getvalue()),
|
||||
{'hostname1': {'1': 'name-1'},
|
||||
'hostname2': {'2': 'name-2'}})
|
||||
mock_pr.return_value.list_instances.assert_called_once_with()
|
||||
|
||||
def test_wait_json(self, mock_os_conf, mock_pr):
|
||||
mock_pr.return_value.wait_for_provisioning.return_value = (
|
||||
self.instances)
|
||||
|
|
|
@ -903,3 +903,23 @@ class TestWaitForState(Base):
|
|||
|
||||
mock_sleep.assert_called_with(1)
|
||||
self.assertEqual(3, mock_sleep.call_count)
|
||||
|
||||
|
||||
class TestListInstances(Base):
|
||||
def setUp(self):
|
||||
super(TestListInstances, self).setUp()
|
||||
self.nodes = [
|
||||
mock.Mock(spec=_os_api.NODE_FIELDS, provision_state=state,
|
||||
instance_info={'metalsmith_hostname': '1234'})
|
||||
for state in ('active', 'active', 'deploying', 'wait call-back',
|
||||
'deploy failed', 'available')
|
||||
]
|
||||
del self.nodes[-1].instance_info['metalsmith_hostname']
|
||||
self.api.list_nodes.return_value = self.nodes
|
||||
|
||||
def test_list(self):
|
||||
instances = self.pr.list_instances()
|
||||
self.assertTrue(isinstance(i, _instance.Instance) for i in instances)
|
||||
self.assertEqual(self.nodes[:5], [i.node for i in instances])
|
||||
self.api.list_nodes.assert_called_once_with(provision_state=None,
|
||||
associated=True)
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
- "{{ ssh_key_file }}"
|
||||
user_name: "{{ configure_instance_user | default('') }}"
|
||||
|
||||
- name: Get instance info via CLI
|
||||
- name: Get instance info via CLI show
|
||||
command: metalsmith --format=json show test
|
||||
register: instance_info
|
||||
|
||||
|
@ -38,6 +38,15 @@
|
|||
instance: "{{ (instance_info.stdout | from_json).test }}"
|
||||
failed_when: instance.state != 'active' or instance.node.provision_state != 'active'
|
||||
|
||||
- name: Get instance info via CLI list
|
||||
command: metalsmith --format=json list
|
||||
register: instance_info_via_list
|
||||
|
||||
- name: Verify that instance info via list is also correct
|
||||
set_fact:
|
||||
instance_via_list: "{{ (instance_info_via_list.stdout | from_json).test }}"
|
||||
failed_when: instance_via_list.state != 'active' or instance_via_list.node.provision_state != 'active'
|
||||
|
||||
- name: Show active node information
|
||||
command: openstack baremetal node show {{ instance.node.uuid }}
|
||||
|
||||
|
|
Loading…
Reference in New Issue