1# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5#      http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13from openstack.baremetal.v1 import _common
14from openstack.baremetal.v1 import allocation as _allocation
15from openstack.baremetal.v1 import chassis as _chassis
16from openstack.baremetal.v1 import conductor as _conductor
17from openstack.baremetal.v1 import deploy_templates as _deploytemplates
18from openstack.baremetal.v1 import driver as _driver
19from openstack.baremetal.v1 import node as _node
20from openstack.baremetal.v1 import port as _port
21from openstack.baremetal.v1 import port_group as _portgroup
22from openstack.baremetal.v1 import volume_connector as _volumeconnector
23from openstack.baremetal.v1 import volume_target as _volumetarget
24from openstack import exceptions
25from openstack import proxy
26from openstack import utils
27
28
29class Proxy(proxy.Proxy):
30
31    retriable_status_codes = _common.RETRIABLE_STATUS_CODES
32
33    def _get_with_fields(self, resource_type, value, fields=None):
34        """Fetch a bare metal resource.
35
36        :param resource_type: The type of resource to get.
37        :type resource_type: :class:`~openstack.resource.Resource`
38        :param value: The value to get. Can be either the ID of a
39                      resource or a :class:`~openstack.resource.Resource`
40                      subclass.
41        :param fields: Limit the resource fields to fetch.
42
43        :returns: The result of the ``fetch``
44        :rtype: :class:`~openstack.resource.Resource`
45        """
46        res = self._get_resource(resource_type, value)
47        kwargs = {}
48        if fields:
49            kwargs['fields'] = _common.fields_type(fields, resource_type)
50        return res.fetch(
51            self,
52            error_message="No {resource_type} found for {value}".format(
53                resource_type=resource_type.__name__, value=value),
54            **kwargs)
55
56    def chassis(self, details=False, **query):
57        """Retrieve a generator of chassis.
58
59        :param details: A boolean indicating whether the detailed information
60                        for every chassis should be returned.
61        :param dict query: Optional query parameters to be sent to
62            restrict the chassis to be returned. Available parameters include:
63
64            * ``fields``: A list containing one or more fields to be returned
65              in the response. This may lead to some performance gain
66              because other fields of the resource are not refreshed.
67            * ``limit``: Requests at most the specified number of items be
68              returned from the query.
69            * ``marker``: Specifies the ID of the last-seen chassis. Use the
70              ``limit`` parameter to make an initial limited request and
71              use the ID of the last-seen chassis from the response as
72              the ``marker`` value in a subsequent limited request.
73            * ``sort_dir``: Sorts the response by the requested sort direction.
74              A valid value is ``asc`` (ascending) or ``desc``
75              (descending). Default is ``asc``. You can specify multiple
76              pairs of sort key and sort direction query parameters. If
77              you omit the sort direction in a pair, the API uses the
78              natural sorting direction of the server attribute that is
79              provided as the ``sort_key``.
80            * ``sort_key``: Sorts the response by the this attribute value.
81              Default is ``id``. You can specify multiple pairs of sort
82              key and sort direction query parameters. If you omit the
83              sort direction in a pair, the API uses the natural sorting
84              direction of the server attribute that is provided as the
85              ``sort_key``.
86
87        :returns: A generator of chassis instances.
88        """
89        return _chassis.Chassis.list(self, details=details, **query)
90
91    def create_chassis(self, **attrs):
92        """Create a new chassis from attributes.
93
94        :param dict attrs: Keyword arguments that will be used to create a
95             :class:`~openstack.baremetal.v1.chassis.Chassis`.
96
97        :returns: The results of chassis creation.
98        :rtype: :class:`~openstack.baremetal.v1.chassis.Chassis`.
99        """
100        return self._create(_chassis.Chassis, **attrs)
101
102    def find_chassis(self, name_or_id, ignore_missing=True):
103        """Find a single chassis.
104
105        :param str name_or_id: The ID of a chassis.
106        :param bool ignore_missing: When set to ``False``, an exception of
107            :class:`~openstack.exceptions.ResourceNotFound` will be raised
108            when the chassis does not exist.  When set to `True``, None will
109            be returned when attempting to find a nonexistent chassis.
110        :returns: One :class:`~openstack.baremetal.v1.chassis.Chassis` object
111            or None.
112        """
113        return self._find(_chassis.Chassis, name_or_id,
114                          ignore_missing=ignore_missing)
115
116    def get_chassis(self, chassis, fields=None):
117        """Get a specific chassis.
118
119        :param chassis: The value can be the ID of a chassis or a
120            :class:`~openstack.baremetal.v1.chassis.Chassis` instance.
121        :param fields: Limit the resource fields to fetch.
122
123        :returns: One :class:`~openstack.baremetal.v1.chassis.Chassis`
124        :raises: :class:`~openstack.exceptions.ResourceNotFound` when no
125            chassis matching the name or ID could be found.
126        """
127        return self._get_with_fields(_chassis.Chassis, chassis, fields=fields)
128
129    def update_chassis(self, chassis, **attrs):
130        """Update a chassis.
131
132        :param chassis: Either the ID of a chassis, or an instance
133            of :class:`~openstack.baremetal.v1.chassis.Chassis`.
134        :param dict attrs: The attributes to update on the chassis represented
135            by the ``chassis`` parameter.
136
137        :returns: The updated chassis.
138        :rtype: :class:`~openstack.baremetal.v1.chassis.Chassis`
139        """
140        return self._update(_chassis.Chassis, chassis, **attrs)
141
142    def patch_chassis(self, chassis, patch):
143        """Apply a JSON patch to the chassis.
144
145        :param chassis: The value can be the ID of a chassis or a
146            :class:`~openstack.baremetal.v1.chassis.Chassis` instance.
147        :param patch: JSON patch to apply.
148
149        :returns: The updated chassis.
150        :rtype: :class:`~openstack.baremetal.v1.chassis.Chassis`
151        """
152        return self._get_resource(_chassis.Chassis, chassis).patch(self, patch)
153
154    def delete_chassis(self, chassis, ignore_missing=True):
155        """Delete a chassis.
156
157        :param chassis: The value can be either the ID of a chassis or
158            a :class:`~openstack.baremetal.v1.chassis.Chassis` instance.
159        :param bool ignore_missing: When set to ``False``, an exception
160            :class:`~openstack.exceptions.ResourceNotFound` will be raised
161            when the chassis could not be found. When set to ``True``, no
162            exception will be raised when attempting to delete a non-existent
163            chassis.
164
165        :returns: The instance of the chassis which was deleted.
166        :rtype: :class:`~openstack.baremetal.v1.chassis.Chassis`.
167        """
168        return self._delete(_chassis.Chassis, chassis,
169                            ignore_missing=ignore_missing)
170
171    def drivers(self, details=False, **query):
172        """Retrieve a generator of drivers.
173
174        :param bool details: A boolean indicating whether the detailed
175            information for every driver should be returned.
176        :param kwargs query: Optional query parameters to be sent to limit
177            the resources being returned.
178        :returns: A generator of driver instances.
179        """
180        # NOTE(dtantsur): details are available starting with API microversion
181        # 1.30. Thus we do not send any value if not needed.
182        if details:
183            query['details'] = True
184        return self._list(_driver.Driver, **query)
185
186    def get_driver(self, driver):
187        """Get a specific driver.
188
189        :param driver: The value can be the name of a driver or a
190            :class:`~openstack.baremetal.v1.driver.Driver` instance.
191
192        :returns: One :class:`~openstack.baremetal.v1.driver.Driver`
193        :raises: :class:`~openstack.exceptions.ResourceNotFound` when no
194            driver matching the name could be found.
195        """
196        return self._get(_driver.Driver, driver)
197
198    def list_driver_vendor_passthru(self, driver):
199        """Get driver's vendor_passthru methods.
200
201        :param driver: The value can be the name of a driver or a
202            :class:`~openstack.baremetal.v1.driver.Driver` instance.
203
204        :returns: One :dict: of vendor methods with corresponding usages
205        :raises: :class:`~openstack.exceptions.ResourceNotFound` when no
206            driver matching the name could be found.
207        """
208        driver = self.get_driver(driver)
209        return driver.list_vendor_passthru(self)
210
211    def call_driver_vendor_passthru(self, driver,
212                                    verb: str, method: str, body=None):
213        """Call driver's vendor_passthru method.
214
215        :param driver: The value can be the name of a driver or a
216            :class:`~openstack.baremetal.v1.driver.Driver` instance.
217        :param verb: One of GET, POST, PUT, DELETE,
218            depending on the driver and method.
219        :param method: Name of vendor method.
220        :param body: passed to the vendor function as json body.
221
222        :returns: Server response
223        """
224        driver = self.get_driver(driver)
225        return driver.call_vendor_passthru(self, verb, method, body)
226
227    def nodes(self, details=False, **query):
228        """Retrieve a generator of nodes.
229
230        :param details: A boolean indicating whether the detailed information
231                        for every node should be returned.
232        :param dict query: Optional query parameters to be sent to restrict
233            the nodes returned. Available parameters include:
234
235            * ``associated``: Only return those which are, or are not,
236              associated with an ``instance_id``.
237            * ``conductor_group``: Only return those in the specified
238              ``conductor_group``.
239            * ``driver``: Only return those with the specified ``driver``.
240            * ``fault``: Only return those with the specified fault type.
241            * ``fields``: A list containing one or more fields to be returned
242              in the response. This may lead to some performance gain
243              because other fields of the resource are not refreshed.
244            * ``instance_id``: Only return the node with this specific instance
245              UUID or an empty set if not found.
246            * ``is_maintenance``: Only return those with ``maintenance`` set to
247              ``True`` or ``False``.
248            * ``limit``: Requests at most the specified number of nodes be
249              returned from the query.
250            * ``marker``: Specifies the ID of the last-seen node. Use the
251              ``limit`` parameter to make an initial limited request and
252              use the ID of the last-seen node from the response as
253              the ``marker`` value in a subsequent limited request.
254            * ``provision_state``: Only return those nodes with the specified
255              ``provision_state``.
256            * ``resource_class``: Only return those with the specified
257              ``resource_class``.
258            * ``sort_dir``: Sorts the response by the requested sort direction.
259              A valid value is ``asc`` (ascending) or ``desc``
260              (descending). Default is ``asc``. You can specify multiple
261              pairs of sort key and sort direction query parameters. If
262              you omit the sort direction in a pair, the API uses the
263              natural sorting direction of the server attribute that is
264              provided as the ``sort_key``.
265            * ``sort_key``: Sorts the response by the this attribute value.
266              Default is ``id``. You can specify multiple pairs of sort
267              key and sort direction query pa rameters. If you omit the
268              sort direction in a pair, the API uses the natural sorting
269              direction of the server attribute that is provided as the
270              ``sort_key``.
271
272        :returns: A generator of :class:`~openstack.baremetal.v1.node.Node`
273        """
274        return _node.Node.list(self, details=details, **query)
275
276    def create_node(self, **attrs):
277        """Create a new node from attributes.
278
279        :param dict attrs: Keyword arguments that will be used to create a
280             :class:`~openstack.baremetal.v1.node.Node`.
281
282        :returns: The results of node creation.
283        :rtype: :class:`~openstack.baremetal.v1.node.Node`.
284        """
285        return self._create(_node.Node, **attrs)
286
287    def find_node(self, name_or_id, ignore_missing=True):
288        """Find a single node.
289
290        :param str name_or_id: The name or ID of a node.
291        :param bool ignore_missing: When set to ``False``, an exception of
292            :class:`~openstack.exceptions.ResourceNotFound` will be raised
293            when the node does not exist.  When set to `True``, None will
294            be returned when attempting to find a nonexistent node.
295        :returns: One :class:`~openstack.baremetal.v1.node.Node` object
296            or None.
297        """
298        return self._find(_node.Node, name_or_id,
299                          ignore_missing=ignore_missing)
300
301    def get_node(self, node, fields=None):
302        """Get a specific node.
303
304        :param node: The value can be the name or ID of a node or a
305            :class:`~openstack.baremetal.v1.node.Node` instance.
306        :param fields: Limit the resource fields to fetch.
307
308        :returns: One :class:`~openstack.baremetal.v1.node.Node`
309        :raises: :class:`~openstack.exceptions.ResourceNotFound` when no
310            node matching the name or ID could be found.
311        """
312        return self._get_with_fields(_node.Node, node, fields=fields)
313
314    def update_node(self, node, retry_on_conflict=True, **attrs):
315        """Update a node.
316
317        :param node: The value can be the name or ID of a node or a
318            :class:`~openstack.baremetal.v1.node.Node` instance.
319        :param bool retry_on_conflict: Whether to retry HTTP CONFLICT error.
320            Most of the time it can be retried, since it is caused by the node
321            being locked. However, when setting ``instance_id``, this is
322            a normal code and should not be retried.
323        :param dict attrs: The attributes to update on the node represented
324            by the ``node`` parameter.
325
326        :returns: The updated node.
327        :rtype: :class:`~openstack.baremetal.v1.node.Node`
328        """
329        res = self._get_resource(_node.Node, node, **attrs)
330        return res.commit(self, retry_on_conflict=retry_on_conflict)
331
332    def patch_node(self, node, patch, reset_interfaces=None,
333                   retry_on_conflict=True):
334        """Apply a JSON patch to the node.
335
336        :param node: The value can be the name or ID of a node or a
337            :class:`~openstack.baremetal.v1.node.Node` instance.
338        :param patch: JSON patch to apply.
339        :param bool reset_interfaces: whether to reset the node hardware
340            interfaces to their defaults. This works only when changing
341            drivers. Added in API microversion 1.45.
342        :param bool retry_on_conflict: Whether to retry HTTP CONFLICT error.
343            Most of the time it can be retried, since it is caused by the node
344            being locked. However, when setting ``instance_id``, this is
345            a normal code and should not be retried.
346
347        See `Update Node
348        <https://docs.openstack.org/api-ref/baremetal/?expanded=update-node-detail#update-node>`_
349        for details.
350
351        :returns: The updated node.
352        :rtype: :class:`~openstack.baremetal.v1.node.Node`
353        """
354        res = self._get_resource(_node.Node, node)
355        return res.patch(self, patch, retry_on_conflict=retry_on_conflict,
356                         reset_interfaces=reset_interfaces)
357
358    def set_node_provision_state(self, node, target, config_drive=None,
359                                 clean_steps=None, rescue_password=None,
360                                 wait=False, timeout=None, deploy_steps=None):
361        """Run an action modifying node's provision state.
362
363        This call is asynchronous, it will return success as soon as the Bare
364        Metal service acknowledges the request.
365
366        :param node: The value can be the name or ID of a node or a
367            :class:`~openstack.baremetal.v1.node.Node` instance.
368        :param target: Provisioning action, e.g. ``active``, ``provide``.
369            See the Bare Metal service documentation for available actions.
370        :param config_drive: Config drive to pass to the node, only valid
371            for ``active` and ``rebuild`` targets. You can use functions from
372            :mod:`openstack.baremetal.configdrive` to build it.
373        :param clean_steps: Clean steps to execute, only valid for ``clean``
374            target.
375        :param rescue_password: Password for the rescue operation, only valid
376            for ``rescue`` target.
377        :param wait: Whether to wait for the node to get into the expected
378            state. The expected state is determined from a combination of
379            the current provision state and ``target``.
380        :param timeout: If ``wait`` is set to ``True``, specifies how much (in
381            seconds) to wait for the expected state to be reached. The value of
382            ``None`` (the default) means no client-side timeout.
383        :param deploy_steps: Deploy steps to execute, only valid for ``active``
384            and ``rebuild`` target.
385
386        :returns: The updated :class:`~openstack.baremetal.v1.node.Node`
387        :raises: ValueError if ``config_drive``, ``clean_steps``,
388            ``deploy_steps`` or ``rescue_password`` are provided with an
389            invalid ``target``.
390        """
391        res = self._get_resource(_node.Node, node)
392        return res.set_provision_state(self, target, config_drive=config_drive,
393                                       clean_steps=clean_steps,
394                                       rescue_password=rescue_password,
395                                       wait=wait, timeout=timeout,
396                                       deploy_steps=deploy_steps)
397
398    def set_node_boot_device(self, node, boot_device, persistent=False):
399        """Set node boot device
400
401        :param node: The value can be the name or ID of a node or a
402            :class:`~openstack.baremetal.v1.node.Node` instance.
403        :param boot_device: Boot device to assign to the node.
404        :param persistent: If the boot device change is maintained after node
405            reboot
406        :return: The updated :class:`~openstack.baremetal.v1.node.Node`
407        """
408        res = self._get_resource(_node.Node, node)
409        return res.set_boot_device(self, boot_device, persistent=persistent)
410
411    def set_node_boot_mode(self, node, target):
412        """Make a request to change node's boot mode
413
414        :param node: The value can be the name or ID of a node or a
415            :class:`~openstack.baremetal.v1.node.Node` instance.
416        :param target: Boot mode to set for node, one of either 'uefi'/'bios'.
417        """
418        res = self._get_resource(_node.Node, node)
419        return res.set_boot_mode(self, target)
420
421    def set_node_secure_boot(self, node, target):
422        """Make a request to change node's secure boot state
423
424        :param node: The value can be the name or ID of a node or a
425            :class:`~openstack.baremetal.v1.node.Node` instance.
426        :param target: Boolean indicating secure boot state to set.
427            True/False corresponding to 'on'/'off' respectively.
428        """
429        res = self._get_resource(_node.Node, node)
430        return res.set_secure_boot(self, target)
431
432    def wait_for_nodes_provision_state(self, nodes, expected_state,
433                                       timeout=None,
434                                       abort_on_failed_state=True,
435                                       fail=True):
436        """Wait for the nodes to reach the expected state.
437
438        :param nodes: List of nodes - name, ID or
439            :class:`~openstack.baremetal.v1.node.Node` instance.
440        :param expected_state: The expected provisioning state to reach.
441        :param timeout: If ``wait`` is set to ``True``, specifies how much (in
442            seconds) to wait for the expected state to be reached. The value of
443            ``None`` (the default) means no client-side timeout.
444        :param abort_on_failed_state: If ``True`` (the default), abort waiting
445            if any node reaches a failure state which does not match the
446            expected one. Note that the failure state for ``enroll`` ->
447            ``manageable`` transition is ``enroll`` again.
448        :param fail: If set to ``False`` this call will not raise on timeouts
449            and provisioning failures.
450
451        :return: If `fail` is ``True`` (the default), the list of
452            :class:`~openstack.baremetal.v1.node.Node` instances that reached
453            the requested state. If `fail` is ``False``, a
454            :class:`~openstack.baremetal.v1.node.WaitResult` named tuple.
455        :raises: :class:`~openstack.exceptions.ResourceFailure` if a node
456            reaches an error state and ``abort_on_failed_state`` is ``True``.
457        :raises: :class:`~openstack.exceptions.ResourceTimeout` on timeout.
458        """
459        log_nodes = ', '.join(n.id if isinstance(n, _node.Node) else n
460                              for n in nodes)
461
462        finished = []
463        failed = []
464        remaining = nodes
465        try:
466            for count in utils.iterate_timeout(
467                    timeout,
468                    "Timeout waiting for nodes %(nodes)s to reach "
469                    "target state '%(state)s'" % {'nodes': log_nodes,
470                                                  'state': expected_state}):
471                nodes = [self.get_node(n) for n in remaining]
472                remaining = []
473                for n in nodes:
474                    try:
475                        if n._check_state_reached(self, expected_state,
476                                                  abort_on_failed_state):
477                            finished.append(n)
478                        else:
479                            remaining.append(n)
480                    except exceptions.ResourceFailure:
481                        if fail:
482                            raise
483                        else:
484                            failed.append(n)
485
486                if not remaining:
487                    if fail:
488                        return finished
489                    else:
490                        return _node.WaitResult(finished, failed, [])
491
492                self.log.debug(
493                    'Still waiting for nodes %(nodes)s to reach state '
494                    '"%(target)s"',
495                    {'nodes': ', '.join(n.id for n in remaining),
496                     'target': expected_state})
497        except exceptions.ResourceTimeout:
498            if fail:
499                raise
500            else:
501                return _node.WaitResult(finished, failed, remaining)
502
503    def set_node_power_state(self, node, target, wait=False, timeout=None):
504        """Run an action modifying node's power state.
505
506        This call is asynchronous, it will return success as soon as the Bare
507        Metal service acknowledges the request.
508
509        :param node: The value can be the name or ID of a node or a
510            :class:`~openstack.baremetal.v1.node.Node` instance.
511        :param target: Target power state, one of
512            :class:`~openstack.baremetal.v1.node.PowerAction` or a string.
513        :param wait: Whether to wait for the node to get into the expected
514            state.
515        :param timeout: If ``wait`` is set to ``True``, specifies how much (in
516            seconds) to wait for the expected state to be reached. The value of
517            ``None`` (the default) means no client-side timeout.
518        """
519        self._get_resource(_node.Node, node).set_power_state(
520            self, target, wait=wait, timeout=timeout)
521
522    def wait_for_node_power_state(self, node, expected_state, timeout=None):
523        """Wait for the node to reach the power state.
524
525        :param node: The value can be the name or ID of a node or a
526            :class:`~openstack.baremetal.v1.node.Node` instance.
527        :param timeout: How much (in seconds) to wait for the target state
528            to be reached. The value of ``None`` (the default) means
529            no timeout.
530
531        :returns: The updated :class:`~openstack.baremetal.v1.node.Node`
532        """
533        res = self._get_resource(_node.Node, node)
534        return res.wait_for_power_state(self, expected_state, timeout=timeout)
535
536    def wait_for_node_reservation(self, node, timeout=None):
537        """Wait for a lock on the node to be released.
538
539        Bare metal nodes in ironic have a reservation lock that
540        is used to represent that a conductor has locked the node
541        while performing some sort of action, such as changing
542        configuration as a result of a machine state change.
543
544        This lock can occur during power syncronization, and prevents
545        updates to objects attached to the node, such as ports.
546
547        Note that nothing prevents a conductor from acquiring the lock again
548        after this call returns, so it should be treated as best effort.
549
550        Returns immediately if there is no reservation on the node.
551
552        :param node: The value can be the name or ID of a node or a
553            :class:`~openstack.baremetal.v1.node.Node` instance.
554        :param timeout: How much (in seconds) to wait for the lock to be
555            released. The value of ``None`` (the default) means no timeout.
556
557        :returns: The updated :class:`~openstack.baremetal.v1.node.Node`
558        """
559        res = self._get_resource(_node.Node, node)
560        return res.wait_for_reservation(self, timeout=timeout)
561
562    def validate_node(self, node, required=('boot', 'deploy', 'power')):
563        """Validate required information on a node.
564
565        :param node: The value can be either the name or ID of a node or
566            a :class:`~openstack.baremetal.v1.node.Node` instance.
567        :param required: List of interfaces that are required to pass
568            validation. The default value is the list of minimum required
569            interfaces for provisioning.
570
571        :return: dict mapping interface names to
572            :class:`~openstack.baremetal.v1.node.ValidationResult` objects.
573        :raises: :exc:`~openstack.exceptions.ValidationException` if validation
574            fails for a required interface.
575        """
576        res = self._get_resource(_node.Node, node)
577        return res.validate(self, required=required)
578
579    def set_node_maintenance(self, node, reason=None):
580        """Enable maintenance mode on the node.
581
582        :param node: The value can be either the name or ID of a node or
583            a :class:`~openstack.baremetal.v1.node.Node` instance.
584        :param reason: Optional reason for maintenance.
585        :return: This :class:`Node` instance.
586        """
587        res = self._get_resource(_node.Node, node)
588        return res.set_maintenance(self, reason)
589
590    def unset_node_maintenance(self, node):
591        """Disable maintenance mode on the node.
592
593        :param node: The value can be either the name or ID of a node or
594            a :class:`~openstack.baremetal.v1.node.Node` instance.
595        :return: This :class:`Node` instance.
596        """
597        res = self._get_resource(_node.Node, node)
598        return res.unset_maintenance(self)
599
600    def delete_node(self, node, ignore_missing=True):
601        """Delete a node.
602
603        :param node: The value can be either the name or ID of a node or
604            a :class:`~openstack.baremetal.v1.node.Node` instance.
605        :param bool ignore_missing: When set to ``False``, an exception
606            :class:`~openstack.exceptions.ResourceNotFound` will be raised
607            when the node could not be found. When set to ``True``, no
608            exception will be raised when attempting to delete a non-existent
609            node.
610
611        :returns: The instance of the node which was deleted.
612        :rtype: :class:`~openstack.baremetal.v1.node.Node`.
613        """
614        return self._delete(_node.Node, node, ignore_missing=ignore_missing)
615
616    def ports(self, details=False, **query):
617        """Retrieve a generator of ports.
618
619        :param details: A boolean indicating whether the detailed information
620                        for every port should be returned.
621        :param dict query: Optional query parameters to be sent to restrict
622            the ports returned. Available parameters include:
623
624            * ``address``: Only return ports with the specified physical
625              hardware address, typically a MAC address.
626            * ``driver``: Only return those with the specified ``driver``.
627            * ``fields``: A list containing one or more fields to be returned
628              in the response. This may lead to some performance gain
629              because other fields of the resource are not refreshed.
630            * ``limit``: Requests at most the specified number of ports be
631              returned from the query.
632            * ``marker``: Specifies the ID of the last-seen port. Use the
633              ``limit`` parameter to make an initial limited request and
634              use the ID of the last-seen port from the response as
635              the ``marker`` value in a subsequent limited request.
636            * ``node``:only return the ones associated with this specific node
637              (name or UUID), or an empty set if not found.
638            * ``node_id``:only return the ones associated with this specific
639              node UUID, or an empty set if not found.
640            * ``portgroup``: only return the ports associated with this
641              specific Portgroup (name or UUID), or an empty set if not
642              found.  Added in API microversion 1.24.
643            * ``sort_dir``: Sorts the response by the requested sort direction.
644              A valid value is ``asc`` (ascending) or ``desc``
645              (descending). Default is ``asc``. You can specify multiple
646              pairs of sort key and sort direction query parameters. If
647              you omit the sort direction in a pair, the API uses the
648              natural sorting direction of the server attribute that is
649              provided as the ``sort_key``.
650            * ``sort_key``: Sorts the response by the this attribute value.
651              Default is ``id``. You can specify multiple pairs of sort
652              key and sort direction query parameters. If you omit the
653              sort direction in a pair, the API uses the natural sorting
654              direction of the server attribute that is provided as the
655              ``sort_key``.
656
657        :returns: A generator of port instances.
658        """
659        return _port.Port.list(self, details=details, **query)
660
661    def create_port(self, **attrs):
662        """Create a new port from attributes.
663
664        :param dict attrs: Keyword arguments that will be used to create a
665             :class:`~openstack.baremetal.v1.port.Port`.
666
667        :returns: The results of port creation.
668        :rtype: :class:`~openstack.baremetal.v1.port.Port`.
669        """
670        return self._create(_port.Port, **attrs)
671
672    def find_port(self, name_or_id, ignore_missing=True):
673        """Find a single port.
674
675        :param str name_or_id: The ID of a port.
676        :param bool ignore_missing: When set to ``False``, an exception of
677            :class:`~openstack.exceptions.ResourceNotFound` will be raised
678            when the port does not exist.  When set to `True``, None will
679            be returned when attempting to find a nonexistent port.
680        :returns: One :class:`~openstack.baremetal.v1.port.Port` object
681            or None.
682        """
683        return self._find(_port.Port, name_or_id,
684                          ignore_missing=ignore_missing)
685
686    def get_port(self, port, fields=None):
687        """Get a specific port.
688
689        :param port: The value can be the ID of a port or a
690            :class:`~openstack.baremetal.v1.port.Port` instance.
691        :param fields: Limit the resource fields to fetch.
692
693        :returns: One :class:`~openstack.baremetal.v1.port.Port`
694        :raises: :class:`~openstack.exceptions.ResourceNotFound` when no
695            port matching the name or ID could be found.
696        """
697        return self._get_with_fields(_port.Port, port, fields=fields)
698
699    def update_port(self, port, **attrs):
700        """Update a port.
701
702        :param port: Either the ID of a port or an instance
703            of :class:`~openstack.baremetal.v1.port.Port`.
704        :param dict attrs: The attributes to update on the port represented
705            by the ``port`` parameter.
706
707        :returns: The updated port.
708        :rtype: :class:`~openstack.baremetal.v1.port.Port`
709        """
710        return self._update(_port.Port, port, **attrs)
711
712    def patch_port(self, port, patch):
713        """Apply a JSON patch to the port.
714
715        :param port: The value can be the ID of a port or a
716            :class:`~openstack.baremetal.v1.port.Port` instance.
717        :param patch: JSON patch to apply.
718
719        :returns: The updated port.
720        :rtype: :class:`~openstack.baremetal.v1.port.Port`
721        """
722        return self._get_resource(_port.Port, port).patch(self, patch)
723
724    def delete_port(self, port, ignore_missing=True):
725        """Delete a port.
726
727        :param port: The value can be either the ID of a port or
728            a :class:`~openstack.baremetal.v1.port.Port` instance.
729        :param bool ignore_missing: When set to ``False``, an exception
730            :class:`~openstack.exceptions.ResourceNotFound` will be raised
731            when the port could not be found. When set to ``True``, no
732            exception will be raised when attempting to delete a non-existent
733            port.
734
735        :returns: The instance of the port which was deleted.
736        :rtype: :class:`~openstack.baremetal.v1.port.Port`.
737        """
738        return self._delete(_port.Port, port, ignore_missing=ignore_missing)
739
740    def port_groups(self, details=False, **query):
741        """Retrieve a generator of port groups.
742
743        :param details: A boolean indicating whether the detailed information
744                        for every port group should be returned.
745        :param dict query: Optional query parameters to be sent to restrict
746            the port groups returned. Available parameters include:
747
748            * ``address``: Only return portgroups with the specified physical
749              hardware address, typically a MAC address.
750            * ``fields``: A list containing one or more fields to be returned
751              in the response. This may lead to some performance gain
752              because other fields of the resource are not refreshed.
753            * ``limit``: Requests at most the specified number of portgroups
754              returned from the query.
755            * ``marker``: Specifies the ID of the last-seen portgroup. Use the
756              ``limit`` parameter to make an initial limited request and
757              use the ID of the last-seen portgroup from the response as
758              the ``marker`` value in a subsequent limited request.
759            * ``node``:only return the ones associated with this specific node
760              (name or UUID), or an empty set if not found.
761            * ``sort_dir``: Sorts the response by the requested sort direction.
762              A valid value is ``asc`` (ascending) or ``desc``
763              (descending). Default is ``asc``. You can specify multiple
764              pairs of sort key and sort direction query parameters. If
765              you omit the sort direction in a pair, the API uses the
766              natural sorting direction of the server attribute that is
767              provided as the ``sort_key``.
768            * ``sort_key``: Sorts the response by the this attribute value.
769              Default is ``id``. You can specify multiple pairs of sort
770              key and sort direction query parameters. If you omit the
771              sort direction in a pair, the API uses the natural sorting
772              direction of the server attribute that is provided as the
773              ``sort_key``.
774
775        :returns: A generator of port group instances.
776        """
777        return _portgroup.PortGroup.list(self, details=details, **query)
778
779    def create_port_group(self, **attrs):
780        """Create a new portgroup from attributes.
781
782        :param dict attrs: Keyword arguments that will be used to create a
783             :class:`~openstack.baremetal.v1.port_group.PortGroup`.
784
785        :returns: The results of portgroup creation.
786        :rtype: :class:`~openstack.baremetal.v1.port_group.PortGroup`.
787        """
788        return self._create(_portgroup.PortGroup, **attrs)
789
790    def find_port_group(self, name_or_id, ignore_missing=True):
791        """Find a single port group.
792
793        :param str name_or_id: The name or ID of a portgroup.
794        :param bool ignore_missing: When set to ``False``, an exception of
795            :class:`~openstack.exceptions.ResourceNotFound` will be raised
796            when the port group does not exist.  When set to `True``, None will
797            be returned when attempting to find a nonexistent port group.
798        :returns: One :class:`~openstack.baremetal.v1.port_group.PortGroup`
799            object or None.
800        """
801        return self._find(_portgroup.PortGroup, name_or_id,
802                          ignore_missing=ignore_missing)
803
804    def get_port_group(self, port_group, fields=None):
805        """Get a specific port group.
806
807        :param port_group: The value can be the name or ID of a chassis or a
808            :class:`~openstack.baremetal.v1.port_group.PortGroup` instance.
809        :param fields: Limit the resource fields to fetch.
810
811        :returns: One :class:`~openstack.baremetal.v1.port_group.PortGroup`
812        :raises: :class:`~openstack.exceptions.ResourceNotFound` when no
813            port group matching the name or ID could be found.
814        """
815        return self._get_with_fields(_portgroup.PortGroup, port_group,
816                                     fields=fields)
817
818    def update_port_group(self, port_group, **attrs):
819        """Update a port group.
820
821        :param port_group: Either the name or the ID of a port group or
822            an instance of
823            :class:`~openstack.baremetal.v1.port_group.PortGroup`.
824        :param dict attrs: The attributes to update on the port group
825            represented by the ``port_group`` parameter.
826
827        :returns: The updated port group.
828        :rtype: :class:`~openstack.baremetal.v1.port_group.PortGroup`
829        """
830        return self._update(_portgroup.PortGroup, port_group, **attrs)
831
832    def patch_port_group(self, port_group, patch):
833        """Apply a JSON patch to the port_group.
834
835        :param port_group: The value can be the ID of a port group or a
836            :class:`~openstack.baremetal.v1.port_group.PortGroup` instance.
837        :param patch: JSON patch to apply.
838
839        :returns: The updated port group.
840        :rtype: :class:`~openstack.baremetal.v1.port_group.PortGroup`
841        """
842        res = self._get_resource(_portgroup.PortGroup, port_group)
843        return res.patch(self, patch)
844
845    def delete_port_group(self, port_group, ignore_missing=True):
846        """Delete a port group.
847
848        :param port_group: The value can be either the name or ID of
849            a port group or a
850            :class:`~openstack.baremetal.v1.port_group.PortGroup`
851            instance.
852        :param bool ignore_missing: When set to ``False``, an exception
853            :class:`~openstack.exceptions.ResourceNotFound` will be raised
854            when the port group could not be found. When set to ``True``, no
855            exception will be raised when attempting to delete a non-existent
856            port group.
857
858        :returns: The instance of the port group which was deleted.
859        :rtype: :class:`~openstack.baremetal.v1.port_group.PortGroup`.
860        """
861        return self._delete(_portgroup.PortGroup, port_group,
862                            ignore_missing=ignore_missing)
863
864    def attach_vif_to_node(self, node, vif_id, retry_on_conflict=True):
865        """Attach a VIF to the node.
866
867        The exact form of the VIF ID depends on the network interface used by
868        the node. In the most common case it is a Network service port
869        (NOT a Bare Metal port) ID. A VIF can only be attached to one node
870        at a time.
871
872        :param node: The value can be either the name or ID of a node or
873            a :class:`~openstack.baremetal.v1.node.Node` instance.
874        :param string vif_id: Backend-specific VIF ID.
875        :param retry_on_conflict: Whether to retry HTTP CONFLICT errors.
876            This can happen when either the VIF is already used on a node or
877            the node is locked. Since the latter happens more often, the
878            default value is True.
879        :return: ``None``
880        :raises: :exc:`~openstack.exceptions.NotSupported` if the server
881            does not support the VIF API.
882        """
883        res = self._get_resource(_node.Node, node)
884        res.attach_vif(self, vif_id, retry_on_conflict=retry_on_conflict)
885
886    def detach_vif_from_node(self, node, vif_id, ignore_missing=True):
887        """Detach a VIF from the node.
888
889        The exact form of the VIF ID depends on the network interface used by
890        the node. In the most common case it is a Network service port
891        (NOT a Bare Metal port) ID.
892
893        :param node: The value can be either the name or ID of a node or
894            a :class:`~openstack.baremetal.v1.node.Node` instance.
895        :param string vif_id: Backend-specific VIF ID.
896        :param bool ignore_missing: When set to ``False``
897                    :class:`~openstack.exceptions.ResourceNotFound` will be
898                    raised when the VIF does not exist. Otherwise, ``False``
899                    is returned.
900        :return: ``True`` if the VIF was detached, otherwise ``False``.
901        :raises: :exc:`~openstack.exceptions.NotSupported` if the server
902            does not support the VIF API.
903        """
904        res = self._get_resource(_node.Node, node)
905        return res.detach_vif(self, vif_id, ignore_missing=ignore_missing)
906
907    def list_node_vifs(self, node):
908        """List IDs of VIFs attached to the node.
909
910        The exact form of the VIF ID depends on the network interface used by
911        the node. In the most common case it is a Network service port
912        (NOT a Bare Metal port) ID.
913
914        :param node: The value can be either the name or ID of a node or
915            a :class:`~openstack.baremetal.v1.node.Node` instance.
916        :return: List of VIF IDs as strings.
917        :raises: :exc:`~openstack.exceptions.NotSupported` if the server
918            does not support the VIF API.
919        """
920        res = self._get_resource(_node.Node, node)
921        return res.list_vifs(self)
922
923    def allocations(self, **query):
924        """Retrieve a generator of allocations.
925
926        :param dict query: Optional query parameters to be sent to restrict
927            the allocation to be returned. Available parameters include:
928
929            * ``fields``: A list containing one or more fields to be returned
930              in the response. This may lead to some performance gain
931              because other fields of the resource are not refreshed.
932            * ``limit``: Requests at most the specified number of items be
933              returned from the query.
934            * ``marker``: Specifies the ID of the last-seen allocation. Use the
935              ``limit`` parameter to make an initial limited request and
936              use the ID of the last-seen allocation from the response as
937              the ``marker`` value in a subsequent limited request.
938            * ``sort_dir``: Sorts the response by the requested sort direction.
939              A valid value is ``asc`` (ascending) or ``desc``
940              (descending). Default is ``asc``. You can specify multiple
941              pairs of sort key and sort direction query parameters. If
942              you omit the sort direction in a pair, the API uses the
943              natural sorting direction of the server attribute that is
944              provided as the ``sort_key``.
945            * ``sort_key``: Sorts the response by the this attribute value.
946              Default is ``id``. You can specify multiple pairs of sort
947              key and sort direction query parameters. If you omit the
948              sort direction in a pair, the API uses the natural sorting
949              direction of the server attribute that is provided as the
950              ``sort_key``.
951
952        :returns: A generator of allocation instances.
953        """
954        return _allocation.Allocation.list(self, **query)
955
956    def create_allocation(self, **attrs):
957        """Create a new allocation from attributes.
958
959        :param dict attrs: Keyword arguments that will be used to create a
960             :class:`~openstack.baremetal.v1.allocation.Allocation`.
961
962        :returns: The results of allocation creation.
963        :rtype: :class:`~openstack.baremetal.v1.allocation.Allocation`.
964        """
965        return self._create(_allocation.Allocation, **attrs)
966
967    def get_allocation(self, allocation, fields=None):
968        """Get a specific allocation.
969
970        :param allocation: The value can be the name or ID of an allocation or
971            a :class:`~openstack.baremetal.v1.allocation.Allocation` instance.
972        :param fields: Limit the resource fields to fetch.
973
974        :returns: One :class:`~openstack.baremetal.v1.allocation.Allocation`
975        :raises: :class:`~openstack.exceptions.ResourceNotFound` when no
976            allocation matching the name or ID could be found.
977        """
978        return self._get_with_fields(_allocation.Allocation, allocation,
979                                     fields=fields)
980
981    def update_allocation(self, allocation, **attrs):
982        """Update an allocation.
983
984        :param allocation: The value can be the name or ID of an allocation or
985            a :class:`~openstack.baremetal.v1.allocation.Allocation` instance.
986        :param dict attrs: The attributes to update on the allocation
987            represented by the ``allocation`` parameter.
988
989        :returns: The updated allocation.
990        :rtype: :class:`~openstack.baremetal.v1.allocation.Allocation`
991        """
992        return self._update(_allocation.Allocation, allocation, **attrs)
993
994    def patch_allocation(self, allocation, patch):
995        """Apply a JSON patch to the allocation.
996
997        :param allocation: The value can be the name or ID of an allocation or
998            a :class:`~openstack.baremetal.v1.allocation.Allocation` instance.
999        :param patch: JSON patch to apply.
1000
1001        :returns: The updated allocation.
1002        :rtype: :class:`~openstack.baremetal.v1.allocation.Allocation`
1003        """
1004        return self._get_resource(_allocation.Allocation,
1005                                  allocation).patch(self, patch)
1006
1007    def delete_allocation(self, allocation, ignore_missing=True):
1008        """Delete an allocation.
1009
1010        :param allocation: The value can be the name or ID of an allocation or
1011            a :class:`~openstack.baremetal.v1.allocation.Allocation` instance.
1012        :param bool ignore_missing: When set to ``False``, an exception
1013            :class:`~openstack.exceptions.ResourceNotFound` will be raised
1014            when the allocation could not be found. When set to ``True``, no
1015            exception will be raised when attempting to delete a non-existent
1016            allocation.
1017
1018        :returns: The instance of the allocation which was deleted.
1019        :rtype: :class:`~openstack.baremetal.v1.allocation.Allocation`.
1020        """
1021        return self._delete(_allocation.Allocation, allocation,
1022                            ignore_missing=ignore_missing)
1023
1024    def wait_for_allocation(self, allocation, timeout=None,
1025                            ignore_error=False):
1026        """Wait for the allocation to become active.
1027
1028        :param allocation: The value can be the name or ID of an allocation or
1029            a :class:`~openstack.baremetal.v1.allocation.Allocation` instance.
1030        :param timeout: How much (in seconds) to wait for the allocation.
1031            The value of ``None`` (the default) means no client-side timeout.
1032        :param ignore_error: If ``True``, this call will raise an exception
1033            if the allocation reaches the ``error`` state. Otherwise the error
1034            state is considered successful and the call returns.
1035
1036        :returns: The instance of the allocation.
1037        :rtype: :class:`~openstack.baremetal.v1.allocation.Allocation`.
1038        :raises: :class:`~openstack.exceptions.ResourceFailure` if allocation
1039            fails and ``ignore_error`` is ``False``.
1040        :raises: :class:`~openstack.exceptions.ResourceTimeout` on timeout.
1041        """
1042        res = self._get_resource(_allocation.Allocation, allocation)
1043        return res.wait(self, timeout=timeout, ignore_error=ignore_error)
1044
1045    def add_node_trait(self, node, trait):
1046        """Add a trait to a node.
1047
1048        :param node: The value can be the name or ID of a node or a
1049            :class:`~openstack.baremetal.v1.node.Node` instance.
1050        :param trait: trait to remove from the node.
1051        :returns: The updated node
1052        """
1053        res = self._get_resource(_node.Node, node)
1054        return res.add_trait(self, trait)
1055
1056    def remove_node_trait(self, node, trait, ignore_missing=True):
1057        """Remove a trait from a node.
1058
1059        :param node: The value can be the name or ID of a node or a
1060            :class:`~openstack.baremetal.v1.node.Node` instance.
1061        :param trait: trait to remove from the node.
1062        :param bool ignore_missing: When set to ``False``, an exception
1063            :class:`~openstack.exceptions.ResourceNotFound` will be raised
1064            when the trait could not be found. When set to ``True``, no
1065            exception will be raised when attempting to delete a non-existent
1066            trait.
1067        :returns: The updated :class:`~openstack.baremetal.v1.node.Node`
1068        """
1069        res = self._get_resource(_node.Node, node)
1070        return res.remove_trait(self, trait, ignore_missing=ignore_missing)
1071
1072    def call_node_vendor_passthru(self, node, verb, method, body=None):
1073        """Calls vendor_passthru for a node.
1074
1075        :param session: The session to use for making this request.
1076        :param verb: The HTTP verb, one of GET, SET, POST, DELETE.
1077        :param method: The method to call using vendor_passthru.
1078        :param body: The JSON body in the HTTP call.
1079        """
1080        res = self._get_resource(_node.Node, node)
1081        return res.call_vendor_passthru(self, verb, method, body)
1082
1083    def list_node_vendor_passthru(self, node):
1084        """Lists vendor_passthru for a node.
1085
1086        :param session: The session to use for making this request.
1087        """
1088        res = self._get_resource(_node.Node, node)
1089        return res.list_vendor_passthru(self)
1090
1091    def set_node_traits(self, node, traits):
1092        """Set traits for a node.
1093
1094        Removes any existing traits and adds the traits passed in to this
1095        method.
1096
1097        :param node: The value can be the name or ID of a node or a
1098            :class:`~openstack.baremetal.v1.node.Node` instance.
1099        :param traits: list of traits to add to the node.
1100        :returns: The updated :class:`~openstack.baremetal.v1.node.Node`
1101        """
1102        res = self._get_resource(_node.Node, node)
1103        return res.set_traits(self, traits)
1104
1105    def volume_connectors(self, details=False, **query):
1106        """Retrieve a generator of volume_connector.
1107
1108        :param details: A boolean indicating whether the detailed information
1109                        for every volume_connector should be returned.
1110        :param dict query: Optional query parameters to be sent to restrict
1111            the volume_connectors returned. Available parameters include:
1112
1113            * ``fields``: A list containing one or more fields to be returned
1114              in the response. This may lead to some performance gain
1115              because other fields of the resource are not refreshed.
1116            * ``limit``: Requests at most the specified number of
1117              volume_connector be returned from the query.
1118            * ``marker``: Specifies the ID of the last-seen volume_connector.
1119              Use the ``limit`` parameter to make an initial limited request
1120              and use the ID of the last-seen volume_connector from the
1121              response as the ``marker`` value in subsequent limited request.
1122            * ``node``:only return the ones associated with this specific node
1123              (name or UUID), or an empty set if not found.
1124            * ``sort_dir``:Sorts the response by the requested sort direction.
1125              A valid value is ``asc`` (ascending) or ``desc``
1126              (descending). Default is ``asc``. You can specify multiple
1127              pairs of sort key and sort direction query parameters. If
1128              you omit the sort direction in a pair, the API uses the
1129              natural sorting direction of the server attribute that is
1130              provided as the ``sort_key``.
1131            * ``sort_key``: Sorts the response by the this attribute value.
1132              Default is ``id``. You can specify multiple pairs of sort
1133              key and sort direction query parameters. If you omit the
1134              sort direction in a pair, the API uses the natural sorting
1135              direction of the server attribute that is provided as the
1136              ``sort_key``.
1137
1138        :returns: A generator of volume_connector instances.
1139        """
1140        if details:
1141            query['detail'] = True
1142        return _volumeconnector.VolumeConnector.list(self, **query)
1143
1144    def create_volume_connector(self, **attrs):
1145        """Create a new volume_connector from attributes.
1146
1147        :param dict attrs: Keyword arguments that will be used to create a
1148            :class:
1149            `~openstack.baremetal.v1.volume_connector.VolumeConnector`.
1150
1151        :returns: The results of volume_connector creation.
1152        :rtype::class:
1153            `~openstack.baremetal.v1.volume_connector.VolumeConnector`.
1154        """
1155        return self._create(_volumeconnector.VolumeConnector, **attrs)
1156
1157    def find_volume_connector(self, vc_id, ignore_missing=True):
1158        """Find a single volume connector.
1159
1160        :param str vc_id: The ID of a volume connector.
1161
1162        :param bool ignore_missing: When set to ``False``, an exception of
1163            :class:`~openstack.exceptions.ResourceNotFound` will be raised
1164            when the volume connector does not exist.  When set to `True``,
1165            None will be returned when attempting to find a nonexistent
1166            volume connector.
1167        :returns: One :class:
1168            `~openstack.baremetal.v1.volumeconnector.VolumeConnector`
1169            object or None.
1170        """
1171        return self._find(_volumeconnector.VolumeConnector, vc_id,
1172                          ignore_missing=ignore_missing)
1173
1174    def get_volume_connector(self, volume_connector, fields=None):
1175        """Get a specific volume_connector.
1176
1177        :param volume_connector: The value can be the ID of a
1178            volume_connector or a :class:
1179            `~openstack.baremetal.v1.volume_connector.VolumeConnector
1180            instance.`
1181        :param fields: Limit the resource fields to fetch.`
1182
1183        :returns: One
1184            :class:
1185            `~openstack.baremetal.v1.volume_connector.VolumeConnector`
1186        :raises: :class:`~openstack.exceptions.ResourceNotFound` when no
1187            volume_connector matching the name or ID could be found.`
1188        """
1189        return self._get_with_fields(_volumeconnector.VolumeConnector,
1190                                     volume_connector,
1191                                     fields=fields)
1192
1193    def update_volume_connector(self, volume_connector, **attrs):
1194        """Update a volume_connector.
1195
1196        :param volume_connector:Either the ID of a volume_connector
1197        or an instance of
1198        :class:`~openstack.baremetal.v1.volume_connector.VolumeConnector.`
1199        :param dict attrs: The attributes to update on the
1200        volume_connector represented by the ``volume_connector`` parameter.`
1201
1202        :returns: The updated volume_connector.
1203        :rtype::class:
1204            `~openstack.baremetal.v1.volume_connector.VolumeConnector.`
1205        """
1206        return self._update(_volumeconnector.VolumeConnector,
1207                            volume_connector, **attrs)
1208
1209    def patch_volume_connector(self, volume_connector, patch):
1210        """Apply a JSON patch to the volume_connector.
1211
1212        :param volume_connector: The value can be the ID of a
1213            volume_connector or a :class:
1214            `~openstack.baremetal.v1.volume_connector.VolumeConnector`
1215            instance.
1216        :param patch: JSON patch to apply.
1217
1218        :returns: The updated volume_connector.
1219        :rtype::class:
1220            `~openstack.baremetal.v1.volume_connector.VolumeConnector.`
1221        """
1222        return self._get_resource(_volumeconnector.VolumeConnector,
1223                                  volume_connector).patch(self, patch)
1224
1225    def delete_volume_connector(self, volume_connector,
1226                                ignore_missing=True):
1227        """Delete an volume_connector.
1228
1229        :param volume_connector: The value can be either the ID of a
1230            volume_connector.VolumeConnector or a
1231            :class:
1232            `~openstack.baremetal.v1.volume_connector.VolumeConnector`
1233            instance.
1234        :param bool ignore_missing: When set to ``False``, an exception
1235            :class:`~openstack.exceptions.ResourceNotFound` will be raised
1236            when the volume_connector could not be found.
1237            When set to ``True``, no exception will be raised when
1238            attempting to delete a non-existent volume_connector.
1239
1240        :returns: The instance of the volume_connector which was deleted.
1241        :rtype::class:
1242            `~openstack.baremetal.v1.volume_connector.VolumeConnector`.
1243        """
1244        return self._delete(_volumeconnector.VolumeConnector,
1245                            volume_connector, ignore_missing=ignore_missing)
1246
1247    def volume_targets(self, details=False, **query):
1248        """Retrieve a generator of volume_target.
1249
1250        :param details: A boolean indicating whether the detailed information
1251                        for every volume_target should be returned.
1252        :param dict query: Optional query parameters to be sent to restrict
1253            the volume_targets returned. Available parameters include:
1254
1255            * ``fields``: A list containing one or more fields to be returned
1256              in the response. This may lead to some performance gain
1257              because other fields of the resource are not refreshed.
1258            * ``limit``: Requests at most the specified number of
1259              volume_connector be returned from the query.
1260            * ``marker``: Specifies the ID of the last-seen volume_target.
1261              Use the ``limit`` parameter to make an initial limited request
1262              and use the ID of the last-seen volume_target from the
1263              response as the ``marker`` value in subsequent limited request.
1264            * ``node``:only return the ones associated with this specific node
1265              (name or UUID), or an empty set if not found.
1266            * ``sort_dir``:Sorts the response by the requested sort direction.
1267              A valid value is ``asc`` (ascending) or ``desc``
1268              (descending). Default is ``asc``. You can specify multiple
1269              pairs of sort key and sort direction query parameters. If
1270              you omit the sort direction in a pair, the API uses the
1271              natural sorting direction of the server attribute that is
1272              provided as the ``sort_key``.
1273            * ``sort_key``: Sorts the response by the this attribute value.
1274              Default is ``id``. You can specify multiple pairs of sort
1275              key and sort direction query parameters. If you omit the
1276              sort direction in a pair, the API uses the natural sorting
1277              direction of the server attribute that is provided as the
1278              ``sort_key``.
1279
1280        :returns: A generator of volume_target instances.
1281        """
1282        if details:
1283            query['detail'] = True
1284        return _volumetarget.VolumeTarget.list(self, **query)
1285
1286    def create_volume_target(self, **attrs):
1287        """Create a new volume_target from attributes.
1288
1289        :param dict attrs: Keyword arguments that will be used to create a
1290            :class:
1291            `~openstack.baremetal.v1.volume_target.VolumeTarget`.
1292
1293        :returns: The results of volume_target creation.
1294        :rtype::class:
1295            `~openstack.baremetal.v1.volume_target.VolumeTarget`.
1296        """
1297        return self._create(_volumetarget.VolumeTarget, **attrs)
1298
1299    def find_volume_target(self, vt_id, ignore_missing=True):
1300        """Find a single volume target.
1301
1302        :param str vt_id: The ID of a volume target.
1303
1304        :param bool ignore_missing: When set to ``False``, an exception of
1305            :class:`~openstack.exceptions.ResourceNotFound` will be raised
1306            when the volume connector does not exist.  When set to `True``,
1307            None will be returned when attempting to find a nonexistent
1308            volume target.
1309        :returns: One :class:
1310            `~openstack.baremetal.v1.volumetarget.VolumeTarget`
1311            object or None.
1312        """
1313        return self._find(_volumetarget.VolumeTarget, vt_id,
1314                          ignore_missing=ignore_missing)
1315
1316    def get_volume_target(self, volume_target, fields=None):
1317        """Get a specific volume_target.
1318
1319        :param volume_target: The value can be the ID of a
1320            volume_target or a :class:
1321            `~openstack.baremetal.v1.volume_target.VolumeTarget
1322            instance.`
1323        :param fields: Limit the resource fields to fetch.`
1324
1325        :returns: One
1326            :class:
1327            `~openstack.baremetal.v1.volume_target.VolumeTarget`
1328        :raises: :class:`~openstack.exceptions.ResourceNotFound` when no
1329            volume_target matching the name or ID could be found.`
1330        """
1331        return self._get_with_fields(_volumetarget.VolumeTarget,
1332                                     volume_target,
1333                                     fields=fields)
1334
1335    def update_volume_target(self, volume_target, **attrs):
1336        """Update a volume_target.
1337
1338        :param volume_target:Either the ID of a volume_target
1339        or an instance of
1340        :class:`~openstack.baremetal.v1.volume_target.VolumeTarget.`
1341        :param dict attrs: The attributes to update on the
1342        volume_target represented by the ``volume_target`` parameter.`
1343
1344        :returns: The updated volume_target.
1345        :rtype::class:
1346            `~openstack.baremetal.v1.volume_target.VolumeTarget.`
1347        """
1348        return self._update(_volumetarget.VolumeTarget,
1349                            volume_target, **attrs)
1350
1351    def patch_volume_target(self, volume_target, patch):
1352        """Apply a JSON patch to the volume_target.
1353
1354        :param volume_target: The value can be the ID of a
1355            volume_target or a :class:
1356            `~openstack.baremetal.v1.volume_target.VolumeTarget`
1357            instance.
1358        :param patch: JSON patch to apply.
1359
1360        :returns: The updated volume_target.
1361        :rtype::class:
1362            `~openstack.baremetal.v1.volume_target.VolumeTarget.`
1363        """
1364        return self._get_resource(_volumetarget.VolumeTarget,
1365                                  volume_target).patch(self, patch)
1366
1367    def delete_volume_target(self, volume_target,
1368                             ignore_missing=True):
1369        """Delete an volume_target.
1370
1371        :param volume_target: The value can be either the ID of a
1372            volume_target.VolumeTarget or a
1373            :class:
1374            `~openstack.baremetal.v1.volume_target.VolumeTarget`
1375            instance.
1376        :param bool ignore_missing: When set to ``False``, an exception
1377            :class:`~openstack.exceptions.ResourceNotFound` will be raised
1378            when the volume_target could not be found.
1379            When set to ``True``, no exception will be raised when
1380            attempting to delete a non-existent volume_target.
1381
1382        :returns: The instance of the volume_target which was deleted.
1383        :rtype::class:
1384            `~openstack.baremetal.v1.volume_target.VolumeTarget`.
1385        """
1386        return self._delete(_volumetarget.VolumeTarget,
1387                            volume_target, ignore_missing=ignore_missing)
1388
1389    def deploy_templates(self, details=False, **query):
1390        """Retrieve a generator of deploy_templates.
1391
1392        :param details: A boolean indicating whether the detailed information
1393                        for every deploy_templates should be returned.
1394        :param dict query: Optional query parameters to be sent to
1395                           restrict the deploy_templates to be returned.
1396
1397        :returns: A generator of Deploy templates instances.
1398        """
1399        if details:
1400            query['detail'] = True
1401        return _deploytemplates.DeployTemplate.list(self, **query)
1402
1403    def create_deploy_template(self, **attrs):
1404        """Create a new deploy_template from attributes.
1405
1406        :param dict attrs: Keyword arguments that will be used to create a
1407                :class:`~openstack.baremetal.v1.deploy_templates.DeployTemplate`.
1408
1409        :returns: The results of deploy_template creation.
1410        :rtype:
1411                :class:`~openstack.baremetal.v1.deploy_templates.DeployTemplate`.
1412        """
1413        return self._create(_deploytemplates.DeployTemplate, **attrs)
1414
1415    def update_deploy_template(self, deploy_template, **attrs):
1416        """Update a deploy_template.
1417
1418        :param deploy_template: Either the ID of a deploy_template,
1419                                or an instance of
1420                                :class:`~openstack.baremetal.v1.deploy_templates.DeployTemplate`.
1421        :param dict attrs: The attributes to update on
1422                           the deploy_template represented
1423                           by the ``deploy_template`` parameter.
1424
1425        :returns: The updated deploy_template.
1426        :rtype::class:
1427                       `~openstack.baremetal.v1.deploy_templates.DeployTemplate`
1428        """
1429        return self._update(_deploytemplates.DeployTemplate,
1430                            deploy_template, **attrs)
1431
1432    def delete_deploy_template(self, deploy_template,
1433                               ignore_missing=True):
1434        """Delete a deploy_template.
1435
1436        :param deploy_template:The value can be
1437                               either the ID of a deploy_template or a
1438        :class:`~openstack.baremetal.v1.deploy_templates.DeployTemplate`
1439                instance.
1440
1441        :param bool ignore_missing: When set to ``False``,
1442            an exception:class:`~openstack.exceptions.ResourceNotFound`
1443            will be raised when the deploy_template
1444            could not be found.
1445            When set to ``True``, no
1446            exception will be raised when attempting
1447            to delete a non-existent
1448            deploy_template.
1449
1450        :returns: The instance of the deploy_template which was deleted.
1451        :rtype::class:
1452                        `~openstack.baremetal.v1.deploy_templates.DeployTemplate`.
1453        """
1454
1455        return self._delete(_deploytemplates.DeployTemplate,
1456                            deploy_template, ignore_missing=ignore_missing)
1457
1458    def get_deploy_template(self, deploy_template, fields=None):
1459        """Get a specific deployment template.
1460
1461        :param deploy_template: The value can be the name or ID
1462            of a deployment template
1463            :class:`~openstack.baremetal.v1.deploy_templates.DeployTemplate`
1464            instance.
1465
1466        :param fields: Limit the resource fields to fetch.
1467
1468        :returns: One
1469                  :class:`~openstack.baremetal.v1.deploy_templates.DeployTemplate`
1470        :raises: :class:`~openstack.exceptions.ResourceNotFound`
1471                        when no deployment template matching the name or
1472                        ID could be found.
1473        """
1474        return self._get_with_fields(_deploytemplates.DeployTemplate,
1475                                     deploy_template, fields=fields)
1476
1477    def patch_deploy_template(self, deploy_template, patch):
1478        """Apply a JSON patch to the deploy_templates.
1479
1480        :param deploy_templates: The value can be the ID of a
1481            deploy_template or a
1482            :class:`~openstack.baremetal.v1.deploy_templates.DeployTemplate`
1483            instance.
1484
1485        :param patch: JSON patch to apply.
1486
1487        :returns: The updated deploy_template.
1488        :rtype::class:
1489                        `~openstack.baremetal.v1.deploy_templates.DeployTemplate`
1490        """
1491        return self._get_resource(_deploytemplates.DeployTemplate,
1492                                  deploy_template).patch(self, patch)
1493
1494    def conductors(self, details=False, **query):
1495        """Retrieve a generator of conductors.
1496
1497        :param bool details: A boolean indicating whether the detailed
1498            information for every conductor should be returned.
1499
1500        :returns: A generator of conductor instances.
1501        """
1502
1503        if details:
1504            query['details'] = True
1505        return _conductor.Conductor.list(self, **query)
1506
1507    def get_conductor(self, conductor, fields=None):
1508        """Get a specific conductor.
1509
1510        :param conductor: The value can be the name of a conductor or a
1511            :class:`~openstack.baremetal.v1.conductor.Conductor` instance.
1512
1513        :returns: One :class:`~openstack.baremetal.v1.conductor.Conductor`
1514
1515        :raises: :class:`~openstack.exceptions.ResourceNotFound` when no
1516            conductor matching the name could be found.
1517        """
1518        return self._get_with_fields(_conductor.Conductor,
1519                                     conductor, fields=fields)
1520