def _plug_vifs(self, node, instance, network_info): LOG.debug("plug: instance_uuid=%(uuid)s vif=%(network_info)s" % { 'uuid': instance['uuid'], 'network_info': network_info }) # start by ensuring the ports are clear self._unplug_vifs(node, instance, network_info) icli = client_wrapper.IronicClientWrapper() ports = icli.call("node.list_ports", node.uuid) if len(network_info) > len(ports): raise exception.NovaException( _("Ironic node: %(id)s virtual to physical interface count" " missmatch" " (Vif count: %(vif_count)d, Pif count: %(pif_count)d)") % { 'id': node.uuid, 'vif_count': len(network_info), 'pif_count': len(ports) }) if len(network_info) > 0: # not needed if no vif are defined for vif, pif in zip(network_info, ports): # attach what neutron needs directly to the port port_id = unicode(vif['id']) patch = [{ 'op': 'add', 'path': '/extra/vif_port_id', 'value': port_id }] icli.call("port.update", pif.uuid, patch)
def macs_for_instance(self, instance): icli = client_wrapper.IronicClientWrapper() try: node = icli.call("node.get", instance['node']) except ironic_exception.NotFound: return [] ports = icli.call("node.list_ports", node.uuid) return [p.address for p in ports]
def get_host_stats(self, refresh=False): caps = [] icli = client_wrapper.IronicClientWrapper() node_list = icli.call("node.list") for node in node_list: data = self._node_resource(node) caps.append(data) return caps
def node_is_available(self, nodename): """Confirms a Nova hypervisor node exists in the Ironic inventory.""" icli = client_wrapper.IronicClientWrapper() try: icli.call("node.get", nodename) return True except ironic_exception.NotFound: return False
def list_instance_uuids(self): """Return the UUIDs of all the instances provisioned. :returns: a list of instance UUIDs. """ icli = client_wrapper.IronicClientWrapper() node_list = icli.call("node.list", associated=True) return list(set(n.instance_uuid for n in node_list))
def test__get_client_with_auth_token(self, mock_ir_cli): self.flags(admin_auth_token='fake-token', group='ironic') icli = client_wrapper.IronicClientWrapper() # dummy call to have _get_client() called icli.call("node.list") expected = {'os_auth_token': 'fake-token', 'ironic_url': CONF.ironic.api_endpoint} mock_ir_cli.assert_called_once_with(CONF.ironic.api_version, **expected)
def test_validate_instance_and_node_failed(self, mock_gbiui): icli = cw.IronicClientWrapper() mock_gbiui.side_effect = ironic_exception.NotFound() instance_uuid = uuidutils.generate_uuid(), instance = fake_instance.fake_instance_obj(self.ctx, uuid=instance_uuid) self.assertRaises(exception.InstanceNotFound, ironic_driver.validate_instance_and_node, icli, instance)
def list_instances(self): """Return the names of all the instances provisioned.""" icli = client_wrapper.IronicClientWrapper() node_list = icli.call("node.list", associated=True) context = nova_context.get_admin_context() return [ instance_obj.Instance.get_by_uuid(context, i.instance_uuid).name for i in node_list ]
def unplug_vifs(self, instance, network_info): """Unplug VIFs from networks. :param instance: The instance object. :param network_info: Instance network information. """ icli = client_wrapper.IronicClientWrapper() node = icli.call("node.get", instance['node']) self._unplug_vifs(node, instance, network_info)
def power_on(self, context, instance, network_info, block_device_info=None, node=None): # TODO(nobodycam): check the current power state first. icli = client_wrapper.IronicClientWrapper() node = validate_instance_and_node(icli, instance) icli.call("node.set_power_state", node.uuid, 'on')
def power_off(self, instance): """Power off the specified instance. :param instance: The instance object. """ # TODO(nobodycam): check the current power state first. icli = client_wrapper.IronicClientWrapper() node = validate_instance_and_node(icli, instance) icli.call("node.set_power_state", node.uuid, 'off')
def test_validate_instance_and_node_failed(self): icli = cw.IronicClientWrapper() with mock.patch.object(FAKE_CLIENT.node, 'get_by_instance_uuid') \ as mock_gbiui: mock_gbiui.side_effect = ironic_exception.HTTPNotFound() instance_uuid = uuidutils.generate_uuid(), instance = fake_instance.fake_instance_obj(self.ctx, uuid=instance_uuid) self.assertRaises(exception.InstanceNotFound, ironic_driver.validate_instance_and_node, icli, instance)
def test_validate_instance_and_node(self, mock_gbiui): node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' instance_uuid = uuidutils.generate_uuid() node = ironic_utils.get_test_node(uuid=node_uuid, instance_uuid=instance_uuid) instance = fake_instance.fake_instance_obj(self.ctx, uuid=instance_uuid) icli = cw.IronicClientWrapper() mock_gbiui.return_value = node result = ironic_driver.validate_instance_and_node(icli, instance) self.assertEqual(result.uuid, node_uuid)
def test__get_client_no_auth_token(self, mock_ir_cli): self.flags(admin_auth_token=None, group='ironic') icli = client_wrapper.IronicClientWrapper() # dummy call to have _get_client() called icli.call("node.list") expected = {'os_username': CONF.ironic.admin_username, 'os_password': CONF.ironic.admin_password, 'os_auth_url': CONF.ironic.admin_url, 'os_tenant_name': CONF.ironic.admin_tenant_name, 'os_service_type': 'baremetal', 'os_endpoint_type': 'public'} mock_ir_cli.assert_called_once_with(CONF.ironic.api_version, **expected)
def get_available_resource(self, node): """Retrieve resource information. This method is called when nova-compute launches, and as part of a periodic task that records the results in the DB. :param node: the uuid of the node :returns: dictionary describing resources """ icli = client_wrapper.IronicClientWrapper() node = icli.call("node.get", node) return self._node_resource(node)
def get_available_nodes(self, refresh=False): nodes = [] icli = client_wrapper.IronicClientWrapper() node_list = icli.call("node.list") for n in node_list: # for now we'll use the nodes power state. if power_state is None # we'll assume it is not ready to be presented to Nova. if n.power_state: nodes.append(n.uuid) LOG.debug("Returning Nodes: %s" % nodes) return nodes
def get_available_nodes(self, refresh=False): """Returns the UUIDs of all nodes in the Ironic inventory. :param refresh: Boolean value; If True run update first. Ignored by this driver. :returns: a list of UUIDs """ icli = client_wrapper.IronicClientWrapper() node_list = icli.call("node.list") nodes = [n.uuid for n in node_list] LOG.debug("Returning %(num_nodes)s available node(s): %(nodes)s", dict(num_nodes=len(nodes), nodes=nodes)) return nodes
def test_validate_instance_and_node(self): node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' instance_uuid = uuidutils.generate_uuid() node = ironic_utils.get_test_node(uuid=node_uuid, instance_uuid=instance_uuid) instance = fake_instance.fake_instance_obj(self.ctx, uuid=instance_uuid) icli = cw.IronicClientWrapper() with mock.patch.object(FAKE_CLIENT.node, 'get_by_instance_uuid') \ as mock_gbiui: mock_gbiui.return_value = node result = ironic_driver.validate_instance_and_node(icli, instance) self.assertEqual(result.uuid, node_uuid)
def get_host_stats(self, refresh=False): """Return the currently known stats for all Ironic nodes. :param refresh: Boolean value; If True run update first. Ignored by this driver. :returns: a list of dictionaries; each dictionary contains the stats for a node. """ caps = [] icli = client_wrapper.IronicClientWrapper() node_list = icli.call("node.list") for node in node_list: data = self._node_resource(node) caps.append(data) return caps
def instance_exists(self, instance): """Checks the existence of an instance. Checks the existence of an instance. This is an override of the base method for efficiency. :param instance: The instance object. :returns: True if the instance exists. False if not. """ icli = client_wrapper.IronicClientWrapper() try: validate_instance_and_node(icli, instance) return True except exception.InstanceNotFound: return False
def instance_exists(self, instance): """Checks the existence of an instance. Checks the existence of an instance. This is an override of the base method for efficiency. :param instance: The instance object. :returns: True if the instance exists. False if not. """ icli = client_wrapper.IronicClientWrapper() try: icli.call("node.get_by_instance_uuid", instance['uuid']) return True except ironic_exception.NotFound: return False
def macs_for_instance(self, instance): """List the MAC addresses of an instance. List of MAC addresses for the node which this instance is associated with. :param instance: the instance object. :returns: a list of MAC addresses. """ icli = client_wrapper.IronicClientWrapper() try: node = icli.call("node.get", instance['node']) except ironic_exception.NotFound: return [] ports = icli.call("node.list_ports", node.uuid) return [p.address for p in ports]
def _unplug_vifs(self, node, instance, network_info): LOG.debug("unplug: instance_uuid=%(uuid)s vif=%(network_info)s" % { 'uuid': instance['uuid'], 'network_info': network_info }) if network_info and len(network_info) > 0: icli = client_wrapper.IronicClientWrapper() ports = icli.call("node.list_ports", node.uuid) # not needed if no vif are defined for vif, pif in zip(network_info, ports): # we can not attach a dict directly patch = [{'op': 'remove', 'path': '/extra/vif_port_id'}] try: icli.call("port.update", pif.uuid, patch) except ironic_exception.BadRequest: pass
def test__get_client_with_auth_token(self): self.flags(admin_auth_token='fake-token', group='ironic') # stop _get_client mock self.mock_cli_patcher.stop() self.mock_cli = None with mock.patch.object(nova_context, 'get_admin_context') as mock_ctx: mock_ctx.return_value = self.ctx with mock.patch.object(ironic_client, 'get_client') as mock_ir_cli: icli = cw.IronicClientWrapper() # dummy call to have _get_client() called icli.call("node.list") expected = { 'os_auth_token': 'fake-token', 'ironic_url': CONF.ironic.api_endpoint } mock_ir_cli.assert_called_once_with(CONF.ironic.api_version, **expected)
def power_on(self, context, instance, network_info, block_device_info=None): """Power on the specified instance. :param context: The security context. :param instance: The instance object. :param network_info: Instance network information. Ignored by this driver. :param block_device_info: Instance block device information. Ignored by this driver. """ # TODO(nobodycam): check the current power state first. icli = client_wrapper.IronicClientWrapper() node = validate_instance_and_node(icli, instance) icli.call("node.set_power_state", node.uuid, 'on')
def _cleanup_deploy(self, node, instance, network_info): icli = client_wrapper.IronicClientWrapper() patch = patcher.create(node).get_cleanup_patch(instance, network_info) # Unassociate the node patch.append({'op': 'remove', 'path': '/instance_uuid'}) try: icli.call('node.update', node.uuid, patch) except ironic_exception.BadRequest: msg = (_("Failed clean up the parameters on node %(node)s " "when unprovisioning the instance %(instance)s") % { 'node': node.uuid, 'instance': instance['uuid'] }) LOG.error(msg) reason = _("Fail to clean up node %s parameters") % node.uuid raise exception.InstanceTerminationFailure(reason=reason) self._unplug_vifs(node, instance, network_info) self._stop_firewall(instance, network_info)
def get_info(self, instance): icli = client_wrapper.IronicClientWrapper() try: node = icli.call("node.get_by_instance_uuid", instance['uuid']) except ironic_exception.NotFound: return { 'state': map_power_state(ironic_states.NOSTATE), 'max_mem': 0, 'mem': 0, 'num_cpu': 0, 'cpu_time': 0 } return { 'state': map_power_state(node.power_state), 'max_mem': node.properties.get('memory_mb'), 'mem': node.properties.get('memory_mb'), 'num_cpu': node.properties.get('cpus'), 'cpu_time': 0 }
def destroy(self, context, instance, network_info, block_device_info=None): icli = client_wrapper.IronicClientWrapper() try: node = validate_instance_and_node(icli, instance) except exception.InstanceNotFound: LOG.debug("Destroy called on non-existing instance %s." % instance['uuid']) # NOTE(deva): if nova.compute.ComputeManager._delete_instance() # is called on a non-existing instance, the only way # to delete it is to return from this method # without raising any exceptions. return if node.provision_state in (ironic_states.ACTIVE, ironic_states.DEPLOYFAIL, ironic_states.ERROR, ironic_states.DEPLOYWAIT): self._unprovision(icli, instance, node) self._cleanup_deploy(node, instance, network_info)
def _add_driver_fields(self, node, instance, image_meta, flavor): icli = client_wrapper.IronicClientWrapper() patch = patcher.create(node).get_deploy_patch(instance, image_meta, flavor) # Associate the node with an instance patch.append({ 'path': '/instance_uuid', 'op': 'add', 'value': instance['uuid'] }) try: icli.call('node.update', node.uuid, patch) except ironic_exception.BadRequest: msg = (_("Failed to add deploy parameters on node %(node)s " "when provisioning the instance %(instance)s") % { 'node': node.uuid, 'instance': instance['uuid'] }) LOG.error(msg) raise exception.InstanceDeployFailure(msg)
def test__get_client_no_auth_token(self): self.flags(admin_auth_token=None, group='ironic') # stop _get_client mock self.mock_cli_patcher.stop() self.mock_cli = None with mock.patch.object(nova_context, 'get_admin_context') as mock_ctx: mock_ctx.return_value = self.ctx with mock.patch.object(ironic_client, 'get_client') as mock_ir_cli: icli = cw.IronicClientWrapper() # dummy call to have _get_client() called icli.call("node.list") expected = { 'os_username': CONF.ironic.admin_username, 'os_password': CONF.ironic.admin_password, 'os_auth_url': CONF.ironic.admin_url, 'os_tenant_name': CONF.ironic.admin_tenant_name, 'os_service_type': 'baremetal', 'os_endpoint_type': 'public' } mock_ir_cli.assert_called_once_with(CONF.ironic.api_version, **expected)