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 import exceptions
14from openstack import resource
15
16
17class AcceleratorRequest(resource.Resource):
18    resource_key = 'arq'
19    resources_key = 'arqs'
20    base_path = '/accelerator_requests'
21
22    # capabilities
23    allow_create = True
24    allow_fetch = True
25    allow_delete = True
26    allow_list = True
27    #: Allow patch operation for binding.
28    allow_patch = True
29
30    #: The device address associated with this ARQ (if any)
31    attach_handle_info = resource.Body('attach_handle_info')
32    #: The type of attach handle (e.g. PCI, mdev...)
33    attach_handle_type = resource.Body('attach_handle_type')
34    #: The name of the device profile
35    device_profile_name = resource.Body('device_profile_name')
36    #: The id of the device profile group
37    device_profile_group_id = resource.Body('device_profile_group_id')
38    #: The UUID of the bound device RP (if any)
39    device_rp_uuid = resource.Body('device_rp_uuid')
40    #: The host name to which ARQ is bound. (if any)
41    hostname = resource.Body('hostname')
42    #: The UUID of the instance associated with this ARQ (if any)
43    instance_uuid = resource.Body('instance_uuid')
44    #: The state of the ARQ
45    state = resource.Body('state')
46    #: The UUID of the ARQ
47    uuid = resource.Body('uuid', alternate_id=True)
48
49    def _convert_patch(self, patch):
50        # This overrides the default behavior of _convert_patch because
51        # the PATCH method consumes JSON, its key is the ARQ uuid
52        # and its value is an ordinary JSON patch. spec:
53        # https://specs.openstack.org/openstack/cyborg-specs/specs/train/implemented/cyborg-api
54
55        converted = super(AcceleratorRequest, self)._convert_patch(patch)
56        converted = {self.id: converted}
57        return converted
58
59    def patch(self, session, patch=None, prepend_key=True, has_body=True,
60              retry_on_conflict=None, base_path=None):
61        # This overrides the default behavior of patch because
62        # the PATCH method consumes a dict rather than a list. spec:
63        # https://specs.openstack.org/openstack/cyborg-specs/specs/train/implemented/cyborg-api
64
65        # The id cannot be dirty for an commit
66        self._body._dirty.discard("id")
67
68        # Only try to update if we actually have anything to commit.
69        if not patch and not self.requires_commit:
70            return self
71
72        if not self.allow_patch:
73            raise exceptions.MethodNotSupported(self, "patch")
74
75        request = self._prepare_request(prepend_key=prepend_key,
76                                        base_path=base_path, patch=True)
77        microversion = self._get_microversion_for(session, 'patch')
78        if patch:
79            request.body = self._convert_patch(patch)
80
81        return self._commit(session, request, 'PATCH', microversion,
82                            has_body=has_body,
83                            retry_on_conflict=retry_on_conflict)
84
85    def _consume_attrs(self, mapping, attrs):
86        # This overrides the default behavior of _consume_attrs because
87        # cyborg api returns an ARQ as list. spec:
88        # https://specs.openstack.org/openstack/cyborg-specs/specs/train/implemented/cyborg-api
89        if isinstance(self, AcceleratorRequest):
90            if self.resources_key in attrs:
91                attrs = attrs[self.resources_key][0]
92        return super(AcceleratorRequest, self)._consume_attrs(mapping, attrs)
93
94    def create(self, session, base_path=None):
95        # This overrides the default behavior of resource creation because
96        # cyborg doesn't accept resource_key in its request.
97        return super(AcceleratorRequest, self).create(
98            session, prepend_key=False, base_path=base_path)
99