diff options
Diffstat (limited to 'nova/virt/ironic/driver.py')
-rw-r--r-- | nova/virt/ironic/driver.py | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/nova/virt/ironic/driver.py b/nova/virt/ironic/driver.py index 7496db5a7c..77fefb81ea 100644 --- a/nova/virt/ironic/driver.py +++ b/nova/virt/ironic/driver.py @@ -397,6 +397,18 @@ class IronicDriver(virt_driver.ComputeDriver): _("Ironic node uuid not supplied to " "driver for instance %s.") % instance.uuid) node = self._get_node(node_uuid) + + # Its possible this node has just moved from deleting + # to cleaning. Placement will update the inventory + # as all reserved, but this instance might have got here + # before that happened, but after the previous allocation + # got deleted. We trigger a re-schedule to another node. + if (self._node_resources_used(node) or + self._node_resources_unavailable(node)): + msg = "Chosen ironic node %s is not available" % node_uuid + LOG.info(msg, instance=instance) + raise exception.ComputeResourcesUnavailable(reason=msg) + self._set_instance_id(node, instance) def failed_spawn_cleanup(self, instance): @@ -827,6 +839,13 @@ class IronicDriver(virt_driver.ComputeDriver): return node_uuids + def get_nodenames_by_uuid(self, refresh=False): + nodes = self.get_available_nodes(refresh=refresh) + # We use the uuid for compute_node.uuid and + # compute_node.hypervisor_hostname, so the dict keys and values are + # the same. + return dict(zip(nodes, nodes)) + def update_provider_tree(self, provider_tree, nodename, allocations=None): """Update a ProviderTree object with current resource provider and inventory information. @@ -874,15 +893,25 @@ class IronicDriver(virt_driver.ComputeDriver): """ # nodename is the ironic node's UUID. node = self._node_from_cache(nodename) + reserved = False - if (not self._node_resources_used(node) and - self._node_resources_unavailable(node)): - LOG.debug('Node %(node)s is not ready for a deployment, ' - 'reporting resources as reserved for it. Node\'s ' - 'provision state is %(prov)s, power state is ' - '%(power)s and maintenance is %(maint)s.', - {'node': node.uuid, 'prov': node.provision_state, - 'power': node.power_state, 'maint': node.maintenance}) + if self._node_resources_unavailable(node): + # Operators might mark a node as in maintainance, + # even when an instance is on the node, + # either way lets mark this as reserved + reserved = True + + if (self._node_resources_used(node) and + not CONF.workarounds.skip_reserve_in_use_ironic_nodes): + # Make resources as reserved once we have + # and instance here. + # When the allocation is deleted, most likely + # automatic clean will start, so we keep the node + # reserved until it becomes available again. + # In the case without automatic clean, once + # the allocation is removed in placement it + # also stays as reserved until we notice on + # the next periodic its actually available. reserved = True info = self._node_resource(node) |