Exemple #1
0
    def set_maintenance(self, node_id, state, maint_reason=None):
        """Set the maintenance mode for the node.

        :param node_id: The UUID of the node.
        :param state: the maintenance mode; either a Boolean or a string
                      representation of a Boolean (eg, 'true', 'on', 'false',
                      'off'). True to put the node in maintenance mode; False
                      to take the node out of maintenance mode.
        :param maint_reason: Optional string. Reason for putting node
                             into maintenance mode.
        :raises: InvalidAttribute if state is an invalid string (that doesn't
                 represent a Boolean).

        """
        if isinstance(state, bool):
            maintenance_mode = state
        else:
            try:
                maintenance_mode = strutils.bool_from_string(state, True)
            except ValueError as e:
                raise exc.InvalidAttribute(
                    _("Argument 'state': %(err)s") % {'err': e})
        path = "%s/maintenance" % node_id
        if maintenance_mode:
            reason = {'reason': maint_reason}
            return self.update(path, reason, http_method='PUT')
        else:
            return self.delete(path)
Exemple #2
0
    def vif_attach(self,
                   node_ident,
                   vif_id,
                   os_ironic_api_version=None,
                   global_request_id=None,
                   **kwargs):
        """Attach VIF to a given node.

        :param node_ident: The UUID or Name of the node.
        :param vif_id: The UUID or Name of the VIF to attach.
        :param os_ironic_api_version: String version (e.g. "1.35") to use for
            the request.  If not specified, the client's default is used.
        :param global_request_id: String containing global request ID header
            value (in form "req-<UUID>") to use for the request.
        :param kwargs: A dictionary containing the attributes of the resource
                       that will be created.
        """
        path = "%s/vifs" % node_ident
        data = {"id": vif_id}
        if 'id' in kwargs:
            raise exc.InvalidAttribute("The attribute 'id' can't be "
                                       "specified in vif-info")
        data.update(kwargs)
        # TODO(vdrok): cleanup places doing custom path and http_method
        self.update(path,
                    data,
                    http_method="POST",
                    os_ironic_api_version=os_ironic_api_version,
                    global_request_id=global_request_id)
    def vendor_passthru(self, node_id, method, args=None, http_method=None):
        """Issue requests for vendor-specific actions on a given node.

        :param node_id: The UUID of the node.
        :param method: Name of the vendor method.
        :param args: Optional. The arguments to be passed to the method.
        :param http_method: The HTTP method to use on the request.
                            Defaults to POST.
        """
        if args is None:
            args = {}

        if http_method is None:
            http_method = 'POST'

        http_method = http_method.upper()

        path = "%s/vendor_passthru/%s" % (node_id, method)
        if http_method in ('POST', 'PUT', 'PATCH'):
            return self.update(path, args, http_method=http_method)
        elif http_method == 'DELETE':
            return self.delete(path)
        elif http_method == 'GET':
            return self.get(path)
        else:
            raise exc.InvalidAttribute(
                _('Unknown HTTP method: %s') % http_method)
    def list(self, marker=None, limit=None, sort_key=None,
             sort_dir=None, detail=False, fields=None,
             os_ironic_api_version=None, global_request_id=None):
        """Retrieve a list of chassis.

        :param marker: Optional, the UUID of a chassis, eg the last
                       chassis from a previous result set. Return
                       the next result set.
        :param limit: The maximum number of results to return per
                      request, if:

            1) limit > 0, the maximum number of chassis to return.
            2) limit == 0, return the entire list of chassis.
            3) limit param is NOT specified (None), the number of items
               returned respect the maximum imposed by the Ironic API
               (see Ironic's api.max_limit option).

        :param sort_key: Optional, field used for sorting.

        :param sort_dir: Optional, direction of sorting, either 'asc' (the
                         default) or 'desc'.

        :param detail: Optional, boolean whether to return detailed information
                       about chassis.

        :param fields: Optional, a list with a specified set of fields
                       of the resource to be returned. Can not be used
                       when 'detail' is set.

        :param os_ironic_api_version: String version (e.g. "1.35") to use for
            the request.  If not specified, the client's default is used.

        :param global_request_id: String containing global request ID header
            value (in form "req-<UUID>") to use for the request.

        :returns: A list of chassis.

        """
        if limit is not None:
            limit = int(limit)

        if detail and fields:
            raise exc.InvalidAttribute(_("Can't fetch a subset of fields "
                                         "with 'detail' set"))

        filters = utils.common_filters(marker, limit, sort_key, sort_dir,
                                       fields)

        path = ''
        if detail:
            path += 'detail'
        if filters:
            path += '?' + '&'.join(filters)
        header_values = {"os_ironic_api_version": os_ironic_api_version,
                         "global_request_id": global_request_id}
        if limit is None:
            return self._list(self._path(path), "chassis", **header_values)
        else:
            return self._list_pagination(self._path(path), "chassis",
                                         limit=limit, **header_values)
Exemple #5
0
    def list(self,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None,
             detail=False,
             fields=None):
        """Retrieve a list of deploy templates.

        :param marker: Optional, the UUID of a deploy template, eg the last
                       template from a previous result set. Return the next
                       result set.
        :param limit: The maximum number of results to return per
                      request, if:

            1) limit > 0, the maximum number of deploy templates to return.
            2) limit == 0, return the entire list of deploy templates.
            3) limit param is NOT specified (None), the number of items
               returned respect the maximum imposed by the Ironic API
               (see Ironic's api.max_limit option).

        :param sort_key: Optional, field used for sorting.

        :param sort_dir: Optional, direction of sorting, either 'asc' (the
                         default) or 'desc'.

        :param detail: Optional, boolean whether to return detailed information
                       about deploy templates.

        :param fields: Optional, a list with a specified set of fields
                       of the resource to be returned. Can not be used
                       when 'detail' is set.

        :returns: A list of deploy templates.

        """
        if limit is not None:
            limit = int(limit)

        if detail and fields:
            raise exc.InvalidAttribute(
                _("Can't fetch a subset of fields "
                  "with 'detail' set"))

        filters = utils.common_filters(marker,
                                       limit,
                                       sort_key,
                                       sort_dir,
                                       fields,
                                       detail=detail)
        path = ''
        if filters:
            path += '?' + '&'.join(filters)

        if limit is None:
            return self._list(self._path(path), "deploy_templates")
        else:
            return self._list_pagination(self._path(path),
                                         "deploy_templates",
                                         limit=limit)
Exemple #6
0
    def create(self, **kwargs):
        """Create a resource based on a kwargs dictionary of attributes.

        :param kwargs: A dictionary containing the attributes of the resource
                       that will be created.
        :raises exc.InvalidAttribute: For invalid attributes that are not
                                      needed to create the resource.
        """

        new = {}
        invalid = []
        for (key, value) in kwargs.items():
            if key in self._creation_attributes:
                new[key] = value
            else:
                invalid.append(key)
        if invalid:
            raise exc.InvalidAttribute(
                'The attribute(s) "%(attrs)s" are invalid; they are not '
                'needed to create %(resource)s.' %
                {'resource': self._resource_name,
                 'attrs': '","'.join(invalid)})
        url = self._path()
        resp, body = self.api.json_request('POST', url, body=new)
        if body:
            return self.resource_class(self, body)
    def list_volume_connectors(self,
                               node_id,
                               marker=None,
                               limit=None,
                               sort_key=None,
                               sort_dir=None,
                               detail=False,
                               fields=None):
        """List all the volume connectors for a given node.
        :param node_id: Name or UUID of the node.
        :param marker: Optional, the UUID of a volume connector, eg the last
                       volume connector from a previous result set. Return
                       the next result set.
        :param limit: The maximum number of results to return per
                      request, if:
            1) limit > 0, the maximum number of volume connectors to return.
            2) limit == 0, return the entire list of volume connectors.
            3) limit param is NOT specified (None), the number of items
               returned respect the maximum imposed by the Ironic API
               (see Ironic's api.max_limit option).
        :param sort_key: Optional, field used for sorting.
        :param sort_dir: Optional, direction of sorting, either 'asc' (the
                         default) or 'desc'.
        :param detail: Optional, boolean whether to return detailed information
                       about volume connectors.
        :param fields: Optional, a list with a specified set of fields
                       of the resource to be returned. Can not be used
                       when 'detail' is set.
        :returns: A list of volume connectors.
        """
        if limit is not None:
            limit = int(limit)

        if detail and fields:
            raise exc.InvalidAttribute(
                _("Can't fetch a subset of fields "
                  "with 'detail' set"))

        filters = utils.common_filters(marker=marker,
                                       limit=limit,
                                       sort_key=sort_key,
                                       sort_dir=sort_dir,
                                       fields=fields,
                                       detail=detail)

        path = "%s/volume/connectors" % node_id
        if filters:
            path += '?' + '&'.join(filters)

        if limit is None:
            return self._list(self._path(path),
                              response_key="connectors",
                              obj_class=volume_connector.VolumeConnector)
        else:
            return self._list_pagination(
                self._path(path),
                response_key="connectors",
                limit=limit,
                obj_class=volume_connector.VolumeConnector)
Exemple #8
0
 def create(self, **kwargs):
     new = {}
     for (key, value) in kwargs.items():
         if key in CREATION_ATTRIBUTES:
             new[key] = value
         else:
             raise exc.InvalidAttribute()
     return self._create(self._path(), new)
 def test_create_single_node_raises_invalid_exception(self):
     params = {'driver': 'fake'}
     e = exc.InvalidAttribute('foo')
     self.client.node.create.side_effect = e
     res, err = create_resources.create_single_node(self.client, **params)
     self.assertIsNone(res)
     self.assertIsInstance(err, exc.InvalidAttribute)
     self.assertIn('Cannot create the node with attributes', str(err))
     self.client.node.create.assert_called_once_with(driver='fake')
Exemple #10
0
    def test_set_target_raid_config_stdin_exception(self, stdin_read_mock):
        client_mock = mock.MagicMock()
        stdin_read_mock.side_effect = exc.InvalidAttribute('bad')
        args_mock = mock.MagicMock(node='node', target_raid_config='-')

        self.assertRaises(exc.InvalidAttribute,
                          n_shell.do_node_set_target_raid_config, client_mock,
                          args_mock)

        stdin_read_mock.assert_called_once_with('target_raid_config')
        self.assertFalse(client_mock.set_target_raid_config.called)
def do_node_set_target_raid_config(cc, args):
    """Set target RAID config on a node."""
    target_raid_config = args.target_raid_config
    if not target_raid_config:
        raise exc.InvalidAttribute(_("target RAID configuration not provided"))

    if target_raid_config == '-':
        target_raid_config = _get_from_stdin('target_raid_config')
    target_raid_config = _handle_json_or_file_arg(target_raid_config)

    cc.node.set_target_raid_config(args.node, target_raid_config)
Exemple #12
0
def get_from_stdin(info_desc):
    """Read information from stdin.

    :param info_desc: A string description of the desired information
    :raises: InvalidAttribute if there was a problem reading from stdin
    :returns: the string that was read from stdin
    """
    try:
        info = sys.stdin.read().strip()
    except Exception as e:
        err = _("Cannot get %(desc)s from standard input. Error: %(err)s")
        raise exc.InvalidAttribute(err % {'desc': info_desc, 'err': e})
    return info
Exemple #13
0
    def test_do_node_set_provision_state_clean_stdin_fails(self, mock_stdin):
        mock_stdin.side_effect = exc.InvalidAttribute('bad')
        client_mock = mock.MagicMock()
        args = mock.MagicMock()
        args.node = 'node_uuid'
        args.provision_state = 'clean'
        args.config_drive = None
        args.clean_steps = '-'

        self.assertRaises(exc.InvalidAttribute,
                          n_shell.do_node_set_provision_state, client_mock,
                          args)
        mock_stdin.assert_called_once_with('clean steps')
        self.assertFalse(client_mock.node.set_provision_state.called)
    def vif_attach(self, node_ident, vif_id, **kwargs):
        """Attach VIF to a given node.

        :param node_ident: The UUID or Name of the node.
        :param vif_id: The UUID or Name of the VIF to attach.
        :param kwargs: A dictionary containing the attributes of the resource
                       that will be created.
        """
        path = "%s/vifs" % node_ident
        data = {"id": vif_id}
        if 'id' in kwargs:
            raise exc.InvalidAttribute("The attribute 'id' can't be "
                                       "specified in vif-info")
        data.update(kwargs)
        # TODO(vdrok): cleanup places doing custom path and http_method
        self.update(path, data, http_method="POST")
Exemple #15
0
 def wrapper(client, **params):
     uuid = None
     error = None
     try:
         uuid = create_method(client, **params)
     except exc.InvalidAttribute as e:
         error = exc.InvalidAttribute(
             'Cannot create the %(resource)s with attributes '
             '%(params)s. One or more attributes are invalid: %(err)s' %
             {'params': params, 'resource': resource_type, 'err': e}
         )
     except Exception as e:
         error = exc.ClientException(
             'Unable to create the %(resource)s with the specified '
             'attributes: %(params)s. The error is: %(error)s' %
             {'error': e, 'resource': resource_type, 'params': params})
     return uuid, error
Exemple #16
0
    def vendor_passthru(self,
                        driver_name,
                        method,
                        args=None,
                        http_method=None,
                        os_ironic_api_version=None,
                        global_request_id=None):
        """Issue requests for vendor-specific actions on a given driver.

        :param driver_name: The name of the driver.
        :param method: Name of the vendor method.
        :param args: Optional. The arguments to be passed to the method.
        :param http_method: The HTTP method to use on the request.
                            Defaults to POST.
        :param os_ironic_api_version: String version (e.g. "1.35") to use for
            the request.  If not specified, the client's default is used.
        :param global_request_id: String containing global request ID header
            value (in form "req-<UUID>") to use for the request.
        """
        if args is None:
            args = {}

        if http_method is None:
            http_method = 'POST'

        http_method = http_method.upper()

        header_values = {
            "os_ironic_api_version": os_ironic_api_version,
            "global_request_id": global_request_id
        }

        path = "%s/vendor_passthru/%s" % (driver_name, method)
        if http_method in ('POST', 'PUT', 'PATCH'):
            return self.update(path,
                               args,
                               http_method=http_method,
                               **header_values)
        elif http_method == 'DELETE':
            return self.delete(path, **header_values)
        elif http_method == 'GET':
            return self.get(path, **header_values)
        else:
            raise exc.InvalidAttribute(
                _('Unknown HTTP method: %s') % http_method)
Exemple #17
0
    def set_maintenance(self,
                        node_id,
                        state,
                        maint_reason=None,
                        os_ironic_api_version=None,
                        global_request_id=None):
        """Set the maintenance mode for the node.

        :param node_id: The UUID of the node.
        :param state: the maintenance mode; either a Boolean or a string
                      representation of a Boolean (eg, 'true', 'on', 'false',
                      'off'). True to put the node in maintenance mode; False
                      to take the node out of maintenance mode.
        :param maint_reason: Optional string. Reason for putting node
                             into maintenance mode.
        :param os_ironic_api_version: String version (e.g. "1.35") to use for
            the request.  If not specified, the client's default is used.
        :param global_request_id: String containing global request ID header
            value (in form "req-<UUID>") to use for the request.

        :raises: InvalidAttribute if state is an invalid string (that doesn't
                 represent a Boolean).
        """
        if isinstance(state, bool):
            maintenance_mode = state
        else:
            try:
                maintenance_mode = strutils.bool_from_string(state, True)
            except ValueError as e:
                raise exc.InvalidAttribute(
                    _("Argument 'state': %(err)s") % {'err': e})
        path = "%s/maintenance" % node_id
        header_values = {
            "os_ironic_api_version": os_ironic_api_version,
            "global_request_id": global_request_id
        }
        if maintenance_mode:
            reason = {'reason': maint_reason}
            return self.update(path,
                               reason,
                               http_method='PUT',
                               **header_values)
        else:
            return self.delete(path, **header_values)
Exemple #18
0
    def create(self, **kwargs):
        """Create a resource based on a kwargs dictionary of attributes.

        :param kwargs: A dictionary containing the attributes of the resource
                       that will be created.
        :raises exc.InvalidAttribute: For invalid attributes that are not
                                      needed to create the resource.
        """

        new = {}
        for (key, value) in kwargs.items():
            if key in self._creation_attributes:
                new[key] = value
            else:
                raise exc.InvalidAttribute()
        url = self._path()
        resp, body = self.api.json_request('POST', url, body=new)
        if body:
            return self.resource_class(self, body)
Exemple #19
0
    def list(self,
             address=None,
             limit=None,
             marker=None,
             sort_key=None,
             sort_dir=None,
             detail=False,
             fields=None,
             node=None,
             portgroup=None):
        """Retrieve a list of ports.

        :param address: Optional, MAC address of a port, to get
                       the port which has this MAC address
        :param marker: Optional, the UUID of a port, eg the last
                       port from a previous result set. Return
                       the next result set.
        :param limit: The maximum number of results to return per
                      request, if:

            1) limit > 0, the maximum number of ports to return.
            2) limit == 0, return the entire list of ports.
            3) limit param is NOT specified (None), the number of items
               returned respect the maximum imposed by the Ironic API
               (see Ironic's api.max_limit option).

        :param sort_key: Optional, field used for sorting.

        :param sort_dir: Optional, direction of sorting, either 'asc' (the
                         default) or 'desc'.

        :param detail: Optional, boolean whether to return detailed information
                       about ports.

        :param fields: Optional, a list with a specified set of fields
                       of the resource to be returned. Can not be used
                       when 'detail' is set.

        :param node: Optional, name or UUID of a node. Used to get
                     ports of this node.

        :param portgroup: Optional, name or UUID of a portgroup. Used to get
                          ports of this portgroup.

        :returns: A list of ports.

        """
        if limit is not None:
            limit = int(limit)

        if detail and fields:
            raise exc.InvalidAttribute(
                _("Can't fetch a subset of fields "
                  "with 'detail' set"))

        filters = utils.common_filters(marker, limit, sort_key, sort_dir,
                                       fields)
        if address is not None:
            filters.append('address=%s' % address)
        if node is not None:
            filters.append('node=%s' % node)
        if portgroup is not None:
            filters.append('portgroup=%s' % portgroup)

        path = ''
        if detail:
            path += 'detail'
        if filters:
            path += '?' + '&'.join(filters)

        if limit is None:
            return self._list(self._path(path), "ports")
        else:
            return self._list_pagination(self._path(path),
                                         "ports",
                                         limit=limit)
    def list(self,
             associated=None,
             maintenance=None,
             marker=None,
             limit=None,
             detail=False,
             sort_key=None,
             sort_dir=None,
             fields=None,
             provision_state=None,
             driver=None,
             resource_class=None,
             chassis=None):
        """Retrieve a list of nodes.

        :param associated: Optional. Either a Boolean or a string
                           representation of a Boolean that indicates whether
                           to return a list of associated (True or "True") or
                           unassociated (False or "False") nodes.
        :param maintenance: Optional. Either a Boolean or a string
                            representation of a Boolean that indicates whether
                            to return nodes in maintenance mode (True or
                            "True"), or not in maintenance mode (False or
                            "False").
        :param provision_state: Optional. String value to get only nodes in
                                that provision state.
        :param marker: Optional, the UUID of a node, eg the last
                       node from a previous result set. Return
                       the next result set.
        :param limit: The maximum number of results to return per
                      request, if:

            1) limit > 0, the maximum number of nodes to return.
            2) limit == 0, return the entire list of nodes.
            3) limit param is NOT specified (None), the number of items
               returned respect the maximum imposed by the Ironic API
               (see Ironic's api.max_limit option).

        :param detail: Optional, boolean whether to return detailed information
                       about nodes.

        :param sort_key: Optional, field used for sorting.

        :param sort_dir: Optional, direction of sorting, either 'asc' (the
                         default) or 'desc'.

        :param fields: Optional, a list with a specified set of fields
                       of the resource to be returned. Can not be used
                       when 'detail' is set.

        :param driver: Optional. String value to get only nodes using that
                       driver.

        :param resource_class: Optional. String value to get only nodes
                               with the given resource class set.

        :param chassis: Optional, the UUID of a chassis. Used to get only
                        nodes of this chassis.

        :returns: A list of nodes.

        """
        if limit is not None:
            limit = int(limit)

        if detail and fields:
            raise exc.InvalidAttribute(
                _("Can't fetch a subset of fields "
                  "with 'detail' set"))

        filters = utils.common_filters(marker, limit, sort_key, sort_dir,
                                       fields)
        if associated is not None:
            filters.append('associated=%s' % associated)
        if maintenance is not None:
            filters.append('maintenance=%s' % maintenance)
        if provision_state is not None:
            filters.append('provision_state=%s' % provision_state)
        if driver is not None:
            filters.append('driver=%s' % driver)
        if resource_class is not None:
            filters.append('resource_class=%s' % resource_class)
        if chassis is not None:
            filters.append('chassis_uuid=%s' % chassis)

        path = ''
        if detail:
            path += 'detail'
        if filters:
            path += '?' + '&'.join(filters)

        if limit is None:
            return self._list(self._path(path), "nodes")
        else:
            return self._list_pagination(self._path(path),
                                         "nodes",
                                         limit=limit)
Exemple #21
0
    def list(self,
             associated=None,
             maintenance=None,
             marker=None,
             limit=None,
             detail=False,
             sort_key=None,
             sort_dir=None,
             fields=None,
             provision_state=None,
             driver=None,
             resource_class=None,
             chassis=None,
             fault=None,
             os_ironic_api_version=None,
             conductor_group=None,
             conductor=None,
             owner=None,
             retired=None,
             lessee=None,
             global_request_id=None):
        """Retrieve a list of nodes.

        :param associated: Optional. Either a Boolean or a string
                           representation of a Boolean that indicates whether
                           to return a list of associated (True or "True") or
                           unassociated (False or "False") nodes.
        :param maintenance: Optional. Either a Boolean or a string
                            representation of a Boolean that indicates whether
                            to return nodes in maintenance mode (True or
                            "True"), or not in maintenance mode (False or
                            "False").
        :param retired: Optional. Either a Boolean or a string representation
                        of a Boolean that indicates whether to return retired
                        nodes (True or "True").
        :param provision_state: Optional. String value to get only nodes in
                                that provision state.
        :param marker: Optional, the UUID of a node, eg the last
                       node from a previous result set. Return
                       the next result set.
        :param limit: The maximum number of results to return per
                      request, if:

            1) limit > 0, the maximum number of nodes to return.
            2) limit == 0, return the entire list of nodes.
            3) limit param is NOT specified (None), the number of items
               returned respect the maximum imposed by the Ironic API
               (see Ironic's api.max_limit option).

        :param detail: Optional, boolean whether to return detailed information
                       about nodes.

        :param sort_key: Optional, field used for sorting.

        :param sort_dir: Optional, direction of sorting, either 'asc' (the
                         default) or 'desc'.

        :param fields: Optional, a list with a specified set of fields
                       of the resource to be returned. Can not be used
                       when 'detail' is set.

        :param driver: Optional. String value to get only nodes using that
                       driver.

        :param resource_class: Optional. String value to get only nodes
                               with the given resource class set.

        :param chassis: Optional, the UUID of a chassis. Used to get only
                        nodes of this chassis.

        :param fault: Optional. String value to get only nodes with
                      specified fault.

        :param os_ironic_api_version: String version (e.g. "1.35") to use for
            the request.  If not specified, the client's default is used.

        :param global_request_id: String containing global request ID header
            value (in form "req-<UUID>") to use for the request.

        :param conductor_group: Optional. String value to get only nodes
                                with the given conductor group set.
        :param conductor: Optional. String value to get only nodes
                          mapped to the given conductor.
        :param owner: Optional. String value to get only nodes
                          mapped to a specific owner.
        :param lessee: Optional. String value to get only nodes
                          mapped to a specific lessee.

        :returns: A list of nodes.

        """
        if limit is not None:
            limit = int(limit)

        if detail and fields:
            raise exc.InvalidAttribute(
                _("Can't fetch a subset of fields "
                  "with 'detail' set"))

        filters = utils.common_filters(marker, limit, sort_key, sort_dir,
                                       fields)
        if associated is not None:
            filters.append('associated=%s' % associated)
        if maintenance is not None:
            filters.append('maintenance=%s' % maintenance)
        if retired is not None:
            filters.append('retired=%s' % retired)
        if fault is not None:
            filters.append('fault=%s' % fault)
        if provision_state is not None:
            filters.append('provision_state=%s' % provision_state)
        if driver is not None:
            filters.append('driver=%s' % driver)
        if resource_class is not None:
            filters.append('resource_class=%s' % resource_class)
        if chassis is not None:
            filters.append('chassis_uuid=%s' % chassis)
        if conductor_group is not None:
            filters.append('conductor_group=%s' % conductor_group)
        if conductor is not None:
            filters.append('conductor=%s' % conductor)
        if owner is not None:
            filters.append('owner=%s' % owner)
        if lessee is not None:
            filters.append('lessee=%s' % lessee)

        path = ''
        if detail:
            path += 'detail'
        if filters:
            path += '?' + '&'.join(filters)
        header_values = {
            "os_ironic_api_version": os_ironic_api_version,
            "global_request_id": global_request_id
        }
        if limit is None:
            return self._list(self._path(path), "nodes", **header_values)
        else:
            return self._list_pagination(self._path(path),
                                         "nodes",
                                         limit=limit,
                                         **header_values)