Fix the resource request handling with wrong resourcepoolId
[pti/o2.git] / o2ims / views / ocloud_route.py
1 # Copyright (C) 2021 Wind River Systems, Inc.
2 #
3 #  Licensed under the Apache License, Version 2.0 (the "License");
4 #  you may not use this file except in compliance with the License.
5 #  You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 #  Unless required by applicable law or agreed to in writing, software
10 #  distributed under the License is distributed on an "AS IS" BASIS,
11 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 #  See the License for the specific language governing permissions and
13 #  limitations under the License.
14
15 from flask import request
16 from flask_restx import Resource, reqparse
17
18 from o2common.service.messagebus import MessageBus
19 from o2common.views.pagination_route import link_header, PAGE_PARAM
20 from o2common.views.route_exception import NotFoundException, \
21     BadRequestException
22 from o2ims.domain import ocloud
23 from o2ims.views import ocloud_view
24 from o2ims.views.api_ns import api_ims_inventory as api_ims_inventory_v1
25 from o2ims.views.ocloud_dto import OcloudDTO, ResourceTypeDTO,\
26     ResourcePoolDTO, ResourceDTO, DeploymentManagerDTO, SubscriptionDTO
27
28 from o2common.helper import o2logging
29 logger = o2logging.get_logger(__name__)
30
31
32 def configure_api_route():
33     # Set global bus for resource
34     global bus
35     bus = MessageBus.get_instance()
36
37
38 # ----------  API versions ---------- #
39 @api_ims_inventory_v1.route("/v1/api_versions")
40 class VersionRouter(Resource):
41     def get(self):
42         return {
43             'uriPrefix': request.base_url.rsplit('/', 1)[0],
44             'apiVersions': [{
45                 'version': '1.0.0',
46                 # 'isDeprecated': 'False',
47                 # 'retirementDate': ''
48             }]
49         }
50
51
52 # ----------  OClouds ---------- #
53 @api_ims_inventory_v1.route(*["/v1", "/v1/"])
54 @api_ims_inventory_v1.response(404, 'oCloud not found')
55 @api_ims_inventory_v1.param(
56     'all_fields',
57     'Set any value for show all fields. This value will cover "fields" ' +
58     'and "all_fields".',
59     _in='query')
60 @api_ims_inventory_v1.param(
61     'fields',
62     'Set fields to show, split by comma, "/" for parent and children.' +
63     ' Like "name,parent/children". This value will cover "exculde_fields".',
64     _in='query')
65 @api_ims_inventory_v1.param(
66     'exclude_fields',
67     'Set fields to exclude showing, split by comma, "/" for parent and ' +
68     'children. Like "name,parent/children". This value will cover ' +
69     '"exclude_default".',
70     _in='query')
71 @api_ims_inventory_v1.param(
72     'exclude_default',
73     'Exclude showing all default fields, Set "true" to enable.',
74     _in='query')
75 class OcloudsListRouter(Resource):
76     """Ocloud get endpoint
77     O2 interface ocloud endpoint
78     """
79
80     ocloud_get = OcloudDTO.ocloud
81
82     @api_ims_inventory_v1.marshal_with(ocloud_get)
83     def get(self):
84         res = ocloud_view.oclouds(bus.uow)
85         if len(res) > 0:
86             return res[0]
87         raise NotFoundException("oCloud doesn't exist")
88
89
90 # ----------  ResourceTypes ---------- #
91 @api_ims_inventory_v1.route("/v1/resourceTypes")
92 @api_ims_inventory_v1.param(PAGE_PARAM,
93                             'Page number of the results to fetch.' +
94                             ' Default: 1',
95                             _in='query', default=1)
96 @api_ims_inventory_v1.param(
97     'all_fields',
98     'Set any value for show all fields. This value will cover "fields" ' +
99     'and "all_fields".',
100     _in='query')
101 @api_ims_inventory_v1.param(
102     'fields',
103     'Set fields to show, split by comma, "/" for parent and children.' +
104     ' Like "name,parent/children". This value will cover "exculde_fields".',
105     _in='query')
106 @api_ims_inventory_v1.param(
107     'exclude_fields',
108     'Set fields to exclude showing, split by comma, "/" for parent and ' +
109     'children. Like "name,parent/children". This value will cover ' +
110     '"exclude_default".',
111     _in='query')
112 @api_ims_inventory_v1.param(
113     'exclude_default',
114     'Exclude showing all default fields, Set "true" to enable.',
115     _in='query')
116 @api_ims_inventory_v1.param(
117     'filter',
118     'Filter of the query.',
119     _in='query')
120 class ResourceTypesListRouter(Resource):
121
122     model = ResourceTypeDTO.resource_type_get
123
124     @api_ims_inventory_v1.marshal_list_with(model)
125     def get(self):
126         parser = reqparse.RequestParser()
127         parser.add_argument(PAGE_PARAM, location='args')
128         parser.add_argument('filter', location='args')
129         args = parser.parse_args()
130         kwargs = {}
131         if args.nextpage_opaque_marker is not None:
132             kwargs['page'] = args.nextpage_opaque_marker
133         kwargs['filter'] = args.filter if args.filter is not None else ''
134
135         ret = ocloud_view.resource_types(bus.uow, **kwargs)
136         return link_header(request.full_path, ret)
137
138
139 @api_ims_inventory_v1.route("/v1/resourceTypes/<resourceTypeID>")
140 @api_ims_inventory_v1.param('resourceTypeID', 'ID of the resource type')
141 @api_ims_inventory_v1.response(404, 'Resource type not found')
142 @api_ims_inventory_v1.param(
143     'all_fields',
144     'Set any value for show all fields. This value will cover "fields" ' +
145     'and "all_fields".',
146     _in='query')
147 @api_ims_inventory_v1.param(
148     'fields',
149     'Set fields to show, split by comma, "/" for parent and children.' +
150     ' Like "name,parent/children". This value will cover "exculde_fields".',
151     _in='query')
152 @api_ims_inventory_v1.param(
153     'exclude_fields',
154     'Set fields to exclude showing, split by comma, "/" for parent and ' +
155     'children. Like "name,parent/children". This value will cover ' +
156     '"exclude_default".',
157     _in='query')
158 @api_ims_inventory_v1.param(
159     'exclude_default',
160     'Exclude showing all default fields, Set "true" to enable.',
161     _in='query')
162 class ResourceTypeGetRouter(Resource):
163
164     model = ResourceTypeDTO.resource_type_get
165
166     @api_ims_inventory_v1.doc('Get resource type')
167     @api_ims_inventory_v1.marshal_with(model)
168     def get(self, resourceTypeID):
169         result = ocloud_view.resource_type_one(resourceTypeID, bus.uow)
170         if result is not None:
171             return result
172         raise NotFoundException("Resource type {} doesn't exist".format(
173             resourceTypeID))
174
175
176 # ----------  ResourcePools ---------- #
177 @api_ims_inventory_v1.route("/v1/resourcePools")
178 @api_ims_inventory_v1.param(PAGE_PARAM,
179                             'Page number of the results to fetch.' +
180                             ' Default: 1',
181                             _in='query', default=1)
182 @api_ims_inventory_v1.param(
183     'all_fields',
184     'Set any value for show all fields. This value will cover "fields" ' +
185     'and "all_fields".',
186     _in='query')
187 @api_ims_inventory_v1.param(
188     'fields',
189     'Set fields to show, split by comma, "/" for parent and children.' +
190     ' Like "name,parent/children". This value will cover "exculde_fields".',
191     _in='query')
192 @api_ims_inventory_v1.param(
193     'exclude_fields',
194     'Set fields to exclude showing, split by comma, "/" for parent and ' +
195     'children. Like "name,parent/children". This value will cover ' +
196     '"exclude_default".',
197     _in='query')
198 @api_ims_inventory_v1.param(
199     'exclude_default',
200     'Exclude showing all default fields, Set "true" to enable.',
201     _in='query')
202 @api_ims_inventory_v1.param(
203     'filter',
204     'Filter of the query.',
205     _in='query')
206 class ResourcePoolsListRouter(Resource):
207
208     model = ResourcePoolDTO.resource_pool_get
209
210     @api_ims_inventory_v1.marshal_list_with(model)
211     def get(self):
212         parser = reqparse.RequestParser()
213         parser.add_argument(PAGE_PARAM, location='args')
214         parser.add_argument('filter', location='args')
215         args = parser.parse_args()
216         kwargs = {}
217         if args.nextpage_opaque_marker is not None:
218             kwargs['page'] = args.nextpage_opaque_marker
219         kwargs['filter'] = args.filter if args.filter is not None else ''
220
221         ret = ocloud_view.resource_pools(bus.uow, **kwargs)
222         return link_header(request.full_path, ret)
223
224
225 @api_ims_inventory_v1.route("/v1/resourcePools/<resourcePoolID>")
226 @api_ims_inventory_v1.param('resourcePoolID', 'ID of the resource pool')
227 @api_ims_inventory_v1.response(404, 'Resource pool not found')
228 @api_ims_inventory_v1.param(
229     'all_fields',
230     'Set any value for show all fields. This value will cover "fields" ' +
231     'and "all_fields".',
232     _in='query')
233 @api_ims_inventory_v1.param(
234     'fields',
235     'Set fields to show, split by comma, "/" for parent and children.' +
236     ' Like "name,parent/children". This value will cover "exculde_fields".',
237     _in='query')
238 @api_ims_inventory_v1.param(
239     'exclude_fields',
240     'Set fields to exclude showing, split by comma, "/" for parent and ' +
241     'children. Like "name,parent/children". This value will cover ' +
242     '"exclude_default".',
243     _in='query')
244 @api_ims_inventory_v1.param(
245     'exclude_default',
246     'Exclude showing all default fields, Set "true" to enable.',
247     _in='query')
248 class ResourcePoolGetRouter(Resource):
249
250     model = ResourcePoolDTO.resource_pool_get
251
252     @api_ims_inventory_v1.doc('Get resource pool')
253     @api_ims_inventory_v1.marshal_with(model)
254     def get(self, resourcePoolID):
255         result = ocloud_view.resource_pool_one(resourcePoolID, bus.uow)
256         if result is not None:
257             return result
258         raise NotFoundException("Resource pool {} doesn't exist".format(
259             resourcePoolID))
260
261
262 # ----------  Resources ---------- #
263 @api_ims_inventory_v1.route("/v1/resourcePools/<resourcePoolID>/resources")
264 @api_ims_inventory_v1.param('resourcePoolID', 'ID of the resource pool')
265 @api_ims_inventory_v1.response(404, 'Resource pool not found')
266 # @api_ims_inventory_v1.param('sort', 'sort by column name',
267 #                             _in='query')
268 # @api_ims_inventory_v1.param('per_page', 'The number of results per page ' +
269 #                             '(max 100). Default: 30',
270 #                             _in='query', default=30)
271 @api_ims_inventory_v1.param(PAGE_PARAM,
272                             'Page number of the results to fetch.' +
273                             ' Default: 1',
274                             _in='query', default=1)
275 @api_ims_inventory_v1.param(
276     'all_fields',
277     'Set any value for show all fields. This value will cover "fields" ' +
278     'and "all_fields".',
279     _in='query')
280 @api_ims_inventory_v1.param(
281     'fields',
282     'Set fields to show, split by comma, "/" for parent and children.' +
283     ' Like "name,parent/children". This value will cover "exculde_fields".',
284     _in='query')
285 @api_ims_inventory_v1.param(
286     'exclude_fields',
287     'Set fields to exclude showing, split by comma, "/" for parent and ' +
288     'children. Like "name,parent/children". This value will cover ' +
289     '"exclude_default".',
290     _in='query')
291 @api_ims_inventory_v1.param(
292     'exclude_default',
293     'Exclude showing all default fields, Set "true" to enable.',
294     _in='query')
295 @api_ims_inventory_v1.param(
296     'filter',
297     'Filter of the query.',
298     _in='query')
299 class ResourcesListRouter(Resource):
300
301     model = ResourceDTO.resource_list
302
303     @api_ims_inventory_v1.marshal_list_with(model)
304     def get(self, resourcePoolID):
305         parser = reqparse.RequestParser()
306         parser.add_argument(PAGE_PARAM, location='args')
307         parser.add_argument('filter', location='args')
308         args = parser.parse_args()
309         kwargs = {}
310         # if args.per_page is not None:
311         #     kwargs['per_page'] = args.per_page
312         #     base_url = base_url + 'per_page=' + args.per_page + '&'
313         if args.nextpage_opaque_marker is not None:
314             kwargs['page'] = args.nextpage_opaque_marker
315         kwargs['filter'] = args.filter if args.filter is not None else ''
316         ret = ocloud_view.resources(resourcePoolID, bus.uow, **kwargs)
317         if ret is None:
318             raise NotFoundException("Resources under {} doesn't exist".format(
319                 resourcePoolID))
320         return link_header(request.full_path, ret)
321
322
323 @api_ims_inventory_v1.route(
324     "/v1/resourcePools/<resourcePoolID>/resources/<resourceID>")
325 @api_ims_inventory_v1.param('resourcePoolID', 'ID of the resource pool')
326 @api_ims_inventory_v1.param('resourceID', 'ID of the resource')
327 @api_ims_inventory_v1.response(404, 'Resource not found')
328 @api_ims_inventory_v1.param(
329     'all_fields',
330     'Set any value for show all fields. This value will cover "fields" ' +
331     'and "all_fields".',
332     _in='query')
333 @api_ims_inventory_v1.param(
334     'fields',
335     'Set fields to show, split by comma, "/" for parent and children.' +
336     ' Like "name,parent/children". This value will cover "exculde_fields".',
337     _in='query')
338 @api_ims_inventory_v1.param(
339     'exclude_fields',
340     'Set fields to exclude showing, split by comma, "/" for parent and ' +
341     'children. Like "name,parent/children". This value will cover ' +
342     '"exclude_default".',
343     _in='query')
344 @api_ims_inventory_v1.param(
345     'exclude_default',
346     'Exclude showing all default fields, Set "true" to enable.',
347     _in='query')
348 class ResourceGetRouter(Resource):
349
350     # dto = ResourceDTO()
351     # model = dto.get_resource_get()
352     model = ResourceDTO.recursive_resource_mapping()
353
354     @api_ims_inventory_v1.doc('Get resource')
355     @api_ims_inventory_v1.marshal_with(model)
356     def get(self, resourcePoolID, resourceID):
357         result = ocloud_view.resource_one(resourceID, bus.uow, resourcePoolID)
358         if result is None:
359             raise NotFoundException("Resource {} doesn't exist".format(
360                 resourceID))
361         return result
362
363
364 # ----------  DeploymentManagers ---------- #
365 @api_ims_inventory_v1.route("/v1/deploymentManagers")
366 @api_ims_inventory_v1.param(PAGE_PARAM,
367                             'Page number of the results to fetch.' +
368                             ' Default: 1',
369                             _in='query', default=1)
370 @api_ims_inventory_v1.param(
371     'all_fields',
372     'Set any value for show all fields. This value will cover "fields" ' +
373     'and "all_fields".',
374     _in='query')
375 @api_ims_inventory_v1.param(
376     'fields',
377     'Set fields to show, split by comma, "/" for parent and children.' +
378     ' Like "name,parent/children". This value will cover "exculde_fields".',
379     _in='query')
380 @api_ims_inventory_v1.param(
381     'exclude_fields',
382     'Set fields to exclude showing, split by comma, "/" for parent and ' +
383     'children. Like "name,parent/children". This value will cover ' +
384     '"exclude_default".',
385     _in='query')
386 @api_ims_inventory_v1.param(
387     'exclude_default',
388     'Exclude showing all default fields, Set "true" to enable.',
389     _in='query')
390 @api_ims_inventory_v1.param(
391     'filter',
392     'Filter of the query.',
393     _in='query')
394 class DeploymentManagersListRouter(Resource):
395
396     model = DeploymentManagerDTO.deployment_manager_list
397
398     @api_ims_inventory_v1.marshal_list_with(model)
399     def get(self):
400         parser = reqparse.RequestParser()
401         parser.add_argument(PAGE_PARAM, location='args')
402         parser.add_argument('filter', location='args')
403         args = parser.parse_args()
404         kwargs = {}
405         if args.nextpage_opaque_marker is not None:
406             kwargs['page'] = args.nextpage_opaque_marker
407         kwargs['filter'] = args.filter if args.filter is not None else ''
408
409         ret = ocloud_view.deployment_managers(bus.uow, **kwargs)
410         return link_header(request.full_path, ret)
411
412
413 @api_ims_inventory_v1.route("/v1/deploymentManagers/<deploymentManagerID>")
414 @api_ims_inventory_v1.param('deploymentManagerID',
415                             'ID of the deployment manager')
416 @api_ims_inventory_v1.param(
417     'profile', 'DMS profile: value supports "native_k8sapi"',
418     _in='query')
419 @api_ims_inventory_v1.response(404, 'Deployment manager not found')
420 @api_ims_inventory_v1.param(
421     'all_fields',
422     'Set any value for show all fields. This value will cover "fields" ' +
423     'and "all_fields".',
424     _in='query')
425 @api_ims_inventory_v1.param(
426     'fields',
427     'Set fields to show, split by comma, "/" for parent and children.' +
428     ' Like "name,parent/children". This value will cover "exculde_fields".',
429     _in='query')
430 @api_ims_inventory_v1.param(
431     'exclude_fields',
432     'Set fields to exclude showing, split by comma, "/" for parent and ' +
433     'children. Like "name,parent/children". This value will cover ' +
434     '"exclude_default".',
435     _in='query')
436 @api_ims_inventory_v1.param(
437     'exclude_default',
438     'Exclude showing all default fields, Set "true" to enable.',
439     _in='query')
440 class DeploymentManagerGetRouter(Resource):
441
442     model = DeploymentManagerDTO.deployment_manager_get
443
444     @api_ims_inventory_v1.doc('Get deployment manager')
445     @api_ims_inventory_v1.marshal_with(model)
446     def get(self, deploymentManagerID):
447         parser = reqparse.RequestParser()
448         parser.add_argument('profile', location='args')
449         args = parser.parse_args()
450         profile = (
451             args.profile if args.profile is not None and args.profile != ''
452             else ocloud.DeploymentManagerProfileDefault)
453         result = ocloud_view.deployment_manager_one(
454             deploymentManagerID, bus.uow, profile)
455         if result is not None and result != "":
456             return result
457         elif result == "":
458             raise NotFoundException(
459                 "Profile {} doesn't support".format(
460                     args.profile))
461
462         raise NotFoundException("Deployment manager {} doesn't exist".format(
463             deploymentManagerID))
464
465
466 # ----------  Subscriptions ---------- #
467 @api_ims_inventory_v1.route("/v1/subscriptions")
468 class SubscriptionsListRouter(Resource):
469
470     model = SubscriptionDTO.subscription_get
471     expect = SubscriptionDTO.subscription_create
472
473     @api_ims_inventory_v1.doc('List subscriptions')
474     @api_ims_inventory_v1.marshal_list_with(model)
475     @api_ims_inventory_v1.param(
476         PAGE_PARAM,
477         'Page number of the results to fetch. Default: 1',
478         _in='query', default=1)
479     @api_ims_inventory_v1.param(
480         'all_fields',
481         'Set any value for show all fields. This value will cover "fields" ' +
482         'and "all_fields".',
483         _in='query')
484     @api_ims_inventory_v1.param(
485         'fields',
486         'Set fields to show, split by comma, "/" for parent and children.' +
487         ' Like "name,parent/children". This value will cover' +
488         ' "exculde_fields".',
489         _in='query')
490     @api_ims_inventory_v1.param(
491         'exclude_fields',
492         'Set fields to exclude showing, split by comma, "/" for parent and ' +
493         'children. Like "name,parent/children". This value will cover ' +
494         '"exclude_default".',
495         _in='query')
496     @api_ims_inventory_v1.param(
497         'exclude_default',
498         'Exclude showing all default fields, Set "true" to enable.',
499         _in='query')
500     @api_ims_inventory_v1.param(
501         'filter',
502         'Filter of the query.',
503         _in='query')
504     def get(self):
505         parser = reqparse.RequestParser()
506         parser.add_argument(PAGE_PARAM, location='args')
507         parser.add_argument('filter', location='args')
508         args = parser.parse_args()
509         kwargs = {}
510         if args.nextpage_opaque_marker is not None:
511             kwargs['page'] = args.nextpage_opaque_marker
512         kwargs['filter'] = args.filter if args.filter is not None else ''
513
514         ret = ocloud_view.subscriptions(bus.uow, **kwargs)
515         return link_header(request.full_path, ret)
516
517     @api_ims_inventory_v1.doc('Create a subscription')
518     @api_ims_inventory_v1.expect(expect)
519     @api_ims_inventory_v1.marshal_with(
520         model, code=201,
521         mask='{subscriptionId,callback,consumerSubscriptionId,filter}')
522     def post(self):
523         data = api_ims_inventory_v1.payload
524         callback = data.get('callback', None)
525         if not callback:
526             raise BadRequestException('The callback parameter is required')
527
528         result = ocloud_view.subscription_create(data, bus.uow)
529         return result, 201
530
531
532 @api_ims_inventory_v1.route("/v1/subscriptions/<subscriptionID>")
533 @api_ims_inventory_v1.param('subscriptionID', 'ID of the subscription')
534 @api_ims_inventory_v1.response(404, 'Subscription not found')
535 class SubscriptionGetDelRouter(Resource):
536
537     model = SubscriptionDTO.subscription_get
538
539     @api_ims_inventory_v1.doc('Get subscription by ID')
540     @api_ims_inventory_v1.marshal_with(model)
541     @api_ims_inventory_v1.param(
542         'all_fields',
543         'Set any value for show all fields. This value will cover "fields" ' +
544         'and "all_fields".',
545         _in='query')
546     @api_ims_inventory_v1.param(
547         'fields',
548         'Set fields to show, split by comma, "/" for parent and children.' +
549         ' Like "name,parent/children". This value will cover' +
550         ' "exculde_fields".',
551         _in='query')
552     @api_ims_inventory_v1.param(
553         'exclude_fields',
554         'Set fields to exclude showing, split by comma, "/" for parent and ' +
555         'children. Like "name,parent/children". This value will cover ' +
556         '"exclude_default".',
557         _in='query')
558     @api_ims_inventory_v1.param(
559         'exclude_default',
560         'Exclude showing all default fields, Set "true" to enable.',
561         _in='query')
562     def get(self, subscriptionID):
563         result = ocloud_view.subscription_one(
564             subscriptionID, bus.uow)
565         if result is not None:
566             return result
567         raise NotFoundException("Subscription {} doesn't exist".format(
568             subscriptionID))
569
570     @api_ims_inventory_v1.doc('Delete subscription by ID')
571     @api_ims_inventory_v1.response(200, 'Subscription deleted')
572     def delete(self, subscriptionID):
573         result = ocloud_view.subscription_delete(subscriptionID, bus.uow)
574         return result, 200