Store requested capabilities in instance_info
Also allow overriding them in the provision_node call. Story: #2002171 Task: #20031 Change-Id: I4b3de4db6c3b6371e5a36921e32953ea354784cc
This commit is contained in:
parent
cbf7294be9
commit
2d6ccf26d8
|
@ -80,6 +80,10 @@ class Provisioner(object):
|
|||
capabilities)
|
||||
node = _scheduler.schedule_node(nodes, filters, reserver,
|
||||
dry_run=self._dry_run)
|
||||
if capabilities:
|
||||
node = self._api.update_node(
|
||||
node, {'/instance_info/capabilities': capabilities})
|
||||
|
||||
LOG.debug('Reserved node: %s', node)
|
||||
return node
|
||||
|
||||
|
@ -146,7 +150,8 @@ class Provisioner(object):
|
|||
return hostname
|
||||
|
||||
def provision_node(self, node, image, nics=None, root_disk_size=None,
|
||||
config=None, hostname=None, netboot=False, wait=None):
|
||||
config=None, hostname=None, netboot=False,
|
||||
capabilities=None, wait=None):
|
||||
"""Provision the node with the given image.
|
||||
|
||||
Example::
|
||||
|
@ -172,6 +177,10 @@ class Provisioner(object):
|
|||
:param hostname: Hostname to assign to the instance. Defaults to the
|
||||
node's name or UUID.
|
||||
:param netboot: Whether to use networking boot for final instances.
|
||||
:param capabilities: Requested capabilities of the node. If present,
|
||||
overwrites the capabilities set by :meth:`reserve_node`.
|
||||
Note that the capabilities are not checked against the ones
|
||||
provided by the node - use :meth:`reserve_node` for that.
|
||||
:param wait: How many seconds to wait for the deployment to finish,
|
||||
None to return immediately.
|
||||
:return: :py:class:`metalsmith.Instance` object with the current
|
||||
|
@ -200,6 +209,9 @@ class Provisioner(object):
|
|||
|
||||
nics = self._get_nics(nics or [])
|
||||
|
||||
if capabilities is None:
|
||||
capabilities = node.instance_info.get('capabilities') or {}
|
||||
|
||||
if self._dry_run:
|
||||
LOG.warning('Dry run, not provisioning node %s',
|
||||
_utils.log_node(node))
|
||||
|
@ -208,11 +220,11 @@ class Provisioner(object):
|
|||
self._create_and_attach_ports(node, nics,
|
||||
created_ports, attached_ports)
|
||||
|
||||
target_caps = {'boot_option': 'netboot' if netboot else 'local'}
|
||||
capabilities['boot_option'] = 'netboot' if netboot else 'local'
|
||||
|
||||
updates = {'/instance_info/image_source': image.id,
|
||||
'/instance_info/root_gb': root_disk_size,
|
||||
'/instance_info/capabilities': target_caps,
|
||||
'/instance_info/capabilities': capabilities,
|
||||
'/extra/%s' % _CREATED_PORTS: created_ports,
|
||||
'/extra/%s' % _ATTACHED_PORTS: attached_ports,
|
||||
'/instance_info/%s' % _os_api.HOSTNAME_FIELD: hostname}
|
||||
|
|
|
@ -33,6 +33,7 @@ class Base(testtools.TestCase):
|
|||
self.node = mock.Mock(spec=_os_api.NODE_FIELDS + ['to_dict'],
|
||||
uuid='000', instance_uuid=None,
|
||||
properties={'local_gb': 100},
|
||||
instance_info={},
|
||||
maintenance=False, extra={})
|
||||
self.node.name = 'control-0'
|
||||
|
||||
|
@ -72,6 +73,7 @@ class TestReserveNode(Base):
|
|||
node = self.pr.reserve_node('control')
|
||||
|
||||
self.assertIn(node, nodes)
|
||||
self.assertFalse(self.api.update_node.called)
|
||||
|
||||
def test_with_capabilities(self):
|
||||
nodes = [
|
||||
|
@ -86,6 +88,8 @@ class TestReserveNode(Base):
|
|||
node = self.pr.reserve_node('control', {'answer': '42'})
|
||||
|
||||
self.assertIs(node, expected)
|
||||
self.api.update_node.assert_called_once_with(
|
||||
node, {'/instance_info/capabilities': {'answer': '42'}})
|
||||
|
||||
|
||||
CLEAN_UP = {
|
||||
|
@ -295,6 +299,77 @@ class TestProvisionNode(Base):
|
|||
self.assertFalse(self.api.release_node.called)
|
||||
self.assertFalse(self.api.delete_port.called)
|
||||
|
||||
def test_with_capabilities(self):
|
||||
inst = self.pr.provision_node(self.node, 'image',
|
||||
[{'network': 'network'}],
|
||||
capabilities={'answer': '42'})
|
||||
self.updates['/instance_info/capabilities'] = {'boot_option': 'local',
|
||||
'answer': '42'}
|
||||
|
||||
self.assertEqual(inst.uuid, self.node.uuid)
|
||||
self.assertEqual(inst.node, self.node)
|
||||
|
||||
self.api.create_port.assert_called_once_with(
|
||||
network_id=self.api.get_network.return_value.id)
|
||||
self.api.attach_port_to_node.assert_called_once_with(
|
||||
self.node.uuid, self.api.create_port.return_value.id)
|
||||
self.api.update_node.assert_called_once_with(self.node, self.updates)
|
||||
self.api.validate_node.assert_called_once_with(self.node,
|
||||
validate_deploy=True)
|
||||
self.api.node_action.assert_called_once_with(self.node, 'active',
|
||||
configdrive=mock.ANY)
|
||||
self.assertFalse(self.wait_mock.called)
|
||||
self.assertFalse(self.api.release_node.called)
|
||||
self.assertFalse(self.api.delete_port.called)
|
||||
|
||||
def test_with_existing_capabilities(self):
|
||||
self.node.instance_info['capabilities'] = {'answer': '42'}
|
||||
inst = self.pr.provision_node(self.node, 'image',
|
||||
[{'network': 'network'}])
|
||||
self.updates['/instance_info/capabilities'] = {'boot_option': 'local',
|
||||
'answer': '42'}
|
||||
|
||||
self.assertEqual(inst.uuid, self.node.uuid)
|
||||
self.assertEqual(inst.node, self.node)
|
||||
|
||||
self.api.create_port.assert_called_once_with(
|
||||
network_id=self.api.get_network.return_value.id)
|
||||
self.api.attach_port_to_node.assert_called_once_with(
|
||||
self.node.uuid, self.api.create_port.return_value.id)
|
||||
self.api.update_node.assert_called_once_with(self.node, self.updates)
|
||||
self.api.validate_node.assert_called_once_with(self.node,
|
||||
validate_deploy=True)
|
||||
self.api.node_action.assert_called_once_with(self.node, 'active',
|
||||
configdrive=mock.ANY)
|
||||
self.assertFalse(self.wait_mock.called)
|
||||
self.assertFalse(self.api.release_node.called)
|
||||
self.assertFalse(self.api.delete_port.called)
|
||||
|
||||
def test_override_existing_capabilities(self):
|
||||
self.node.instance_info['capabilities'] = {'answer': '1',
|
||||
'cat': 'meow'}
|
||||
inst = self.pr.provision_node(self.node, 'image',
|
||||
[{'network': 'network'}],
|
||||
capabilities={'answer': '42'})
|
||||
self.updates['/instance_info/capabilities'] = {'boot_option': 'local',
|
||||
'answer': '42'}
|
||||
|
||||
self.assertEqual(inst.uuid, self.node.uuid)
|
||||
self.assertEqual(inst.node, self.node)
|
||||
|
||||
self.api.create_port.assert_called_once_with(
|
||||
network_id=self.api.get_network.return_value.id)
|
||||
self.api.attach_port_to_node.assert_called_once_with(
|
||||
self.node.uuid, self.api.create_port.return_value.id)
|
||||
self.api.update_node.assert_called_once_with(self.node, self.updates)
|
||||
self.api.validate_node.assert_called_once_with(self.node,
|
||||
validate_deploy=True)
|
||||
self.api.node_action.assert_called_once_with(self.node, 'active',
|
||||
configdrive=mock.ANY)
|
||||
self.assertFalse(self.wait_mock.called)
|
||||
self.assertFalse(self.api.release_node.called)
|
||||
self.assertFalse(self.api.delete_port.called)
|
||||
|
||||
def test_with_wait(self):
|
||||
self.api.get_port.return_value = mock.Mock(
|
||||
spec=['fixed_ips'],
|
||||
|
|
Loading…
Reference in New Issue