From 5ad82f634e2f10aaeccf1d2420fafc63e2d0056e Mon Sep 17 00:00:00 2001 From: Bin Yang Date: Tue, 7 Dec 2021 11:32:07 +0800 Subject: [PATCH] Integrate nfdeployment api with event handler Fix O2DMS api load issue Issue-ID: INF-239 Signed-off-by: Bin Yang Change-Id: Idc5a41eb25fab5f23ac23fc5632f6589776e8f7c --- o2app/entrypoints/flask_application.py | 2 +- o2app/entrypoints/redis_eventconsumer.py | 22 +++- o2app/service/handlers.py | 10 +- o2dms/adapter/dms_repository.py | 8 ++ o2dms/adapter/orm.py | 1 + o2dms/api/__init__.py | 33 +++++ o2dms/api/dms_api_ns.py | 5 + o2dms/{views => api}/dms_dto.py | 10 +- o2dms/api/dms_lcm_nfdeployment.py | 112 ++++++++++++++++ o2dms/api/dms_lcm_nfdeployment_vres.py | 36 +++++ o2dms/api/dms_lcm_nfdeploymentdesc.py | 99 ++++++++++++++ o2dms/api/dms_lcm_view.py | 34 +++++ o2dms/{views => api}/dms_route.py | 15 ++- o2dms/{views => api}/nfdeployment_desc_route.py | 33 +++-- o2dms/{views => api}/nfdeployment_route.py | 52 +++++--- o2dms/{views => api}/ocloud_vresource_route.py | 13 +- o2dms/domain/commands.py | 27 ++++ o2dms/domain/dms.py | 4 +- o2dms/domain/dms_repo.py | 14 ++ o2dms/{views/__init__.py => domain/events.py} | 52 ++++---- o2dms/service/nfdeployment_handler.py | 43 ++++++ o2dms/views/dms_lcm_view.py | 168 ------------------------ 22 files changed, 560 insertions(+), 233 deletions(-) create mode 100644 o2dms/api/__init__.py create mode 100644 o2dms/api/dms_api_ns.py rename o2dms/{views => api}/dms_dto.py (93%) create mode 100644 o2dms/api/dms_lcm_nfdeployment.py create mode 100644 o2dms/api/dms_lcm_nfdeployment_vres.py create mode 100644 o2dms/api/dms_lcm_nfdeploymentdesc.py create mode 100644 o2dms/api/dms_lcm_view.py rename o2dms/{views => api}/dms_route.py (81%) rename o2dms/{views => api}/nfdeployment_desc_route.py (80%) rename o2dms/{views => api}/nfdeployment_route.py (69%) rename o2dms/{views => api}/ocloud_vresource_route.py (90%) create mode 100644 o2dms/domain/commands.py rename o2dms/{views/__init__.py => domain/events.py} (66%) create mode 100644 o2dms/service/nfdeployment_handler.py delete mode 100644 o2dms/views/dms_lcm_view.py diff --git a/o2app/entrypoints/flask_application.py b/o2app/entrypoints/flask_application.py index ab8c261..f9d5f85 100644 --- a/o2app/entrypoints/flask_application.py +++ b/o2app/entrypoints/flask_application.py @@ -17,7 +17,7 @@ from flask_restx import Api from o2app import bootstrap from o2ims.views import ocloud_route as ims_route -from o2dms.views import configure_namespace as dms_route_configure_namespace +from o2dms.api import configure_namespace as dms_route_configure_namespace # apibase = config.get_o2ims_api_base() diff --git a/o2app/entrypoints/redis_eventconsumer.py b/o2app/entrypoints/redis_eventconsumer.py index 188eb87..1d38f04 100644 --- a/o2app/entrypoints/redis_eventconsumer.py +++ b/o2app/entrypoints/redis_eventconsumer.py @@ -13,11 +13,14 @@ # limitations under the License. # import json +from logging import log import redis - +import json from o2app import bootstrap from o2common.config import config # from o2common.domain import commands +from o2dms.domain import commands +from o2dms.domain import events from o2common.helper import o2logging logger = o2logging.get_logger(__name__) @@ -29,14 +32,27 @@ def main(): logger.info("Redis pubsub starting") bus = bootstrap.bootstrap() pubsub = r.pubsub(ignore_subscribe_messages=True) - pubsub.subscribe("dms_changed") + pubsub.subscribe("NfDeploymentCreated") for m in pubsub.listen(): - handle_dms_changed(m, bus) + try: + handle_dms_changed(m, bus) + except Exception as ex: + logger.warning("{}".format(str(ex))) + continue def handle_dms_changed(m, bus): logger.info("handling %s", m) + channel = m['channel'].decode("UTF-8") + if channel == "NfDeploymentCreated": + datastr = m['data'] + data = json.loads(datastr) + logger.info('InstallNfDeployment with cmd:{}'.format(data)) + cmd = commands.InstallNfDeployment(NfDeploymentId = data['NfDeploymentId']) + bus.handle(cmd) + else: + logger.info("unhandled:{}".format(channel)) # data = json.loads(m["data"]) # cmd = commands.UpdateDms(ref=data["dmsid"]) # bus.handle(cmd) diff --git a/o2app/service/handlers.py b/o2app/service/handlers.py index f3b3d6d..b551ca6 100644 --- a/o2app/service/handlers.py +++ b/o2app/service/handlers.py @@ -18,9 +18,14 @@ from __future__ import annotations from typing import List, Dict, Callable, Type # TYPE_CHECKING from o2ims.domain import commands, events + +from o2dms.domain import commands as o2dms_cmmands +from o2dms.domain import events as o2dms_events from o2ims.service.auditor import ocloud_handler, dms_handler, \ resourcepool_handler, pserver_handler, pserver_cpu_handler, \ pserver_mem_handler, pserver_port_handler, pserver_if_handler +from o2dms.service.nfdeployment_handler import publish_nfdeployment_created +from o2dms.service.nfdeployment_handler import install_nfdeployment # if TYPE_CHECKING: # from . import unit_of_work @@ -31,7 +36,8 @@ class InvalidResourceType(Exception): EVENT_HANDLERS = { -} # type: Dict[Type[events.Event], List[Callable]] + o2dms_events.NfDeploymentCreated: [publish_nfdeployment_created] +} COMMAND_HANDLERS = { @@ -43,4 +49,6 @@ COMMAND_HANDLERS = { commands.UpdatePserverMem: pserver_mem_handler.update_pserver_mem, commands.UpdatePserverIf: pserver_if_handler.update_pserver_if, commands.UpdatePserverPort: pserver_port_handler.update_pserver_port, + o2dms_cmmands.InstallNfDeployment: install_nfdeployment + } # type: Dict[Type[commands.Command], Callable] diff --git a/o2dms/adapter/dms_repository.py b/o2dms/adapter/dms_repository.py index 2c7c3ca..d0116d0 100644 --- a/o2dms/adapter/dms_repository.py +++ b/o2dms/adapter/dms_repository.py @@ -42,6 +42,10 @@ class NfDeploymentDescSqlAlchemyRepository(dms_repo id=nfdeployment_desc_id ).delete() + def _count(self, **kwargs): + return self.session.query( + dms.NfDeploymentDesc).filter_by(**kwargs).count() + class NfDeploymentSqlAlchemyRepository( dms_repo.NfDeploymentRepository): @@ -69,6 +73,10 @@ class NfDeploymentSqlAlchemyRepository( id=nfdeployment_id ).delete() + def _count(self, **kwargs): + return self.session.query( + dms.NfDeployment).filter_by(**kwargs).count() + class NfOCloudVResourceSqlAlchemyRepository( dms_repo.NfOCloudVResourceRepository): diff --git a/o2dms/adapter/orm.py b/o2dms/adapter/orm.py index 1c2c93a..4226d26 100644 --- a/o2dms/adapter/orm.py +++ b/o2dms/adapter/orm.py @@ -47,6 +47,7 @@ nfDeploymentDesc = Table( Column("description", String(255)), Column("inputParams", String(255)), Column("outputParams", String(255)), + Column("artifactUrl", String(255)), # Column("extensions", String(1024)) ) diff --git a/o2dms/api/__init__.py b/o2dms/api/__init__.py new file mode 100644 index 0000000..10d5562 --- /dev/null +++ b/o2dms/api/__init__.py @@ -0,0 +1,33 @@ +# Copyright (C) 2021 Wind River Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from o2dms.api.dms_api_ns import api_dms_lcm_v1 +from . import dms_route +from . import nfdeployment_desc_route +from . import nfdeployment_route +from o2common.config import config + +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) + + +def configure_namespace(app): + apibase = config.get_o2dms_api_base() + logger.info( + "Expose O2DMS API:{}".format(apibase)) + + dms_route.configure_api_route() + nfdeployment_desc_route.configure_api_route() + nfdeployment_route.configure_api_route() + app.add_namespace(api_dms_lcm_v1, path=apibase) diff --git a/o2dms/api/dms_api_ns.py b/o2dms/api/dms_api_ns.py new file mode 100644 index 0000000..4c8235f --- /dev/null +++ b/o2dms/api/dms_api_ns.py @@ -0,0 +1,5 @@ +from flask_restx import Namespace + + +api_dms_lcm_v1 = Namespace( + "O2DMS_LCM", description='DMS LCM related operations.') diff --git a/o2dms/views/dms_dto.py b/o2dms/api/dms_dto.py similarity index 93% rename from o2dms/views/dms_dto.py rename to o2dms/api/dms_dto.py index e52bc3e..06d4f3c 100644 --- a/o2dms/views/dms_dto.py +++ b/o2dms/api/dms_dto.py @@ -13,7 +13,9 @@ # limitations under the License. from flask_restx import fields -from o2dms.views import api_dms_lcm_v1 +from o2dms.api.dms_api_ns import api_dms_lcm_v1 +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) class DmsDTO: @@ -42,7 +44,8 @@ class DmsLcmNfDeploymentDescriptorDTO: 'name': fields.String, 'description': fields.String, 'inputParams': fields.String, - 'outputParams': fields.String + 'outputParams': fields.String, + 'artifactUrl': fields.String } ) @@ -51,6 +54,7 @@ class DmsLcmNfDeploymentDescriptorDTO: { 'name': fields.String, 'description': fields.String, + 'artifactUrl': fields.String, 'inputParams': fields.String, 'outputParams': fields.String } @@ -69,6 +73,7 @@ class DmsLcmNfDeploymentDescriptorDTO: { 'name': fields.String, 'description': fields.String, + 'artifactUrl': fields.String, 'inputParams': fields.String, 'outputParams': fields.String } @@ -113,7 +118,6 @@ class DmsLcmNfDeploymentDTO: { 'name': fields.String, 'description': fields.String, - 'descriptorId': fields.String, 'parentDeploymentId': fields.String } ) diff --git a/o2dms/api/dms_lcm_nfdeployment.py b/o2dms/api/dms_lcm_nfdeployment.py new file mode 100644 index 0000000..bdf5ea5 --- /dev/null +++ b/o2dms/api/dms_lcm_nfdeployment.py @@ -0,0 +1,112 @@ +# Copyright (C) 2021 Wind River Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from sqlalchemy import select +import uuid +from o2common.service import messagebus +from o2dms.domain import events +from o2common.service import unit_of_work +from o2dms.adapter.orm import nfDeployment +from o2dms.api.dms_dto import DmsLcmNfDeploymentDTO +from o2dms.domain.dms import NfDeployment +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) + + +def lcm_nfdeployment_list( + deploymentManagerID: str, uow: unit_of_work.AbstractUnitOfWork): + with uow: + res = uow.session.execute(select(nfDeployment).where( + nfDeployment.c.deploymentManagerId == deploymentManagerID)) + return [dict(r) for r in res] + + +def lcm_nfdeployment_one( + nfdeploymentid: str, uow: unit_of_work.AbstractUnitOfWork): + with uow: + res = uow.session.execute(select(nfDeployment).where( + nfDeployment.c.id == nfdeploymentid)) + first = res.first() + return None if first is None else dict(first) + + +def lcm_nfdeployment_create( + deploymentManagerId: str, + input: DmsLcmNfDeploymentDTO. + NfDeployment_create, + bus: messagebus.MessageBus): + + uow = bus.uow + with uow: + _check_duplication(input, uow) + _check_dependencies(input, uow) + id = str(uuid.uuid4()) + entity = NfDeployment( + id, input['name'], deploymentManagerId, input['description'], + input['descriptorId'], input['parentDeploymentId']) + uow.nfdeployments.add(entity) + + # publish event + event = events.NfDeploymentCreated(NfDeploymentId=id) + uow.commit() + bus.handle(event) + + return id + + +def lcm_nfdeployment_update( + nfdeploymentid: str, + input: DmsLcmNfDeploymentDTO.NfDeployment_update, + uow: unit_of_work.AbstractUnitOfWork): + + with uow: + entity = uow.nfdeployments.get(nfdeploymentid) + entity.name = input['name'] + entity.description = input['description'] + entity.outputParams = input['parentDeploymentId'] + uow.commit() + return True + + +def lcm_nfdeployment_delete( + nfdeploymentid: str, uow: unit_of_work.AbstractUnitOfWork): + + with uow: + uow.nfdeployments.delete(nfdeploymentid) + uow.commit() + return True + + +def _check_duplication( + input: DmsLcmNfDeploymentDTO, + uow: unit_of_work.AbstractUnitOfWork): + name = input['name'] + descriptorId = input['descriptorId'] + if uow.nfdeployments.count(name=name) > 0: + raise Exception( + "NfDeployment with name {} exists already".format(name)) + if uow.nfdeployments.count(descriptorId=descriptorId) > 0: + raise Exception( + "NfDeployment with descriptorId {} exists already".format( + descriptorId)) + + +def _check_dependencies( + input: DmsLcmNfDeploymentDTO, + uow: unit_of_work.AbstractUnitOfWork): + descriptorId = input['descriptorId'] + if uow.nfdeployment_descs.count(id=descriptorId) == 0: + raise Exception( + "NfDeploymentDescriptor with id {} does not exist".format( + descriptorId)) diff --git a/o2dms/api/dms_lcm_nfdeployment_vres.py b/o2dms/api/dms_lcm_nfdeployment_vres.py new file mode 100644 index 0000000..edd989a --- /dev/null +++ b/o2dms/api/dms_lcm_nfdeployment_vres.py @@ -0,0 +1,36 @@ +# Copyright (C) 2021 Wind River Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from sqlalchemy import select +from o2common.service import unit_of_work +from o2dms.adapter.orm import nfOCloudVResource +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) + + +def lcm_nfocloudvresource_list( + nfDeploymentId: str, uow: unit_of_work.AbstractUnitOfWork): + with uow: + res = uow.session.execute(select(nfOCloudVResource).where( + nfOCloudVResource.c.nfDeploymentId == nfDeploymentId)) + return [dict(r) for r in res] + + +def lcm_nfocloudvresource_one( + ocloudvresourceId: str, uow: unit_of_work.AbstractUnitOfWork): + with uow: + res = uow.session.execute(select(nfOCloudVResource).where( + nfOCloudVResource.c.id == ocloudvresourceId)) + first = res.first() + return None if first is None else dict(first) diff --git a/o2dms/api/dms_lcm_nfdeploymentdesc.py b/o2dms/api/dms_lcm_nfdeploymentdesc.py new file mode 100644 index 0000000..5ed98b7 --- /dev/null +++ b/o2dms/api/dms_lcm_nfdeploymentdesc.py @@ -0,0 +1,99 @@ +# Copyright (C) 2021 Wind River Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from sqlalchemy import select +import uuid +from o2common.service import unit_of_work +from o2dms.adapter.orm import nfDeploymentDesc +from o2dms.api.dms_dto import DmsLcmNfDeploymentDescriptorDTO +from o2dms.domain.dms import NfDeploymentDesc +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) + + +def lcm_nfdeploymentdesc_list(deploymentManagerID: str, + uow: unit_of_work.AbstractUnitOfWork): + with uow: + res = uow.session.execute(select(nfDeploymentDesc).where( + nfDeploymentDesc.c.deploymentManagerId == deploymentManagerID)) + return [dict(r) for r in res] + + +def lcm_nfdeploymentdesc_one(nfdeploymentdescriptorid: str, + uow: unit_of_work.AbstractUnitOfWork): + with uow: + res = uow.session.execute(select(nfDeploymentDesc).where( + nfDeploymentDesc.c.id == nfdeploymentdescriptorid)) + first = res.first() + return None if first is None else dict(first) + + +def _check_duplication(name: str, uow: unit_of_work.AbstractUnitOfWork): + if uow.nfdeployment_descs.count(name=name) > 0: + raise Exception( + "NfDeploymentDescriptor with name {} exists already".format(name)) + + +def lcm_nfdeploymentdesc_create( + deploymentManagerId: str, + input: DmsLcmNfDeploymentDescriptorDTO. + NfDeploymentDescriptor_create, + uow: unit_of_work.AbstractUnitOfWork): + + with uow: + _check_duplication(input['name'], uow) + id = str(uuid.uuid4()) + entity = NfDeploymentDesc( + id, input['name'], deploymentManagerId, input['description'], + input['inputParams'], input['outputParams'], input['artifactUrl']) + uow.nfdeployment_descs.add(entity) + uow.commit() + return id + + +def lcm_nfdeploymentdesc_update( + nfdeploymentdescriptorid: str, + input: DmsLcmNfDeploymentDescriptorDTO.NfDeploymentDescriptor_update, + uow: unit_of_work.AbstractUnitOfWork): + + with uow: + entity = uow.nfdeployment_descs.get(nfdeploymentdescriptorid) + entity.name = input['name'] + entity.description = input['description'] + entity.inputParams = input['inputParams'] + entity.outputParams = input['outputParams'] + entity.artifactUrl = input['artifactUrl'] + uow.commit() + return True + + +def lcm_nfdeploymentdesc_delete( + nfdeploymentdescriptorid: str, uow: unit_of_work.AbstractUnitOfWork): + + with uow: + # check dependency + _check_dependencies(nfdeploymentdescriptorid, uow) + uow.nfdeployment_descs.delete(nfdeploymentdescriptorid) + uow.commit() + return True + + +def _check_dependencies( + descriptorId: str, uow: unit_of_work.AbstractUnitOfWork +): + # check if nfdeployment depends on it + if uow.nfdeployments.count(descriptorId=descriptorId) > 0: + raise Exception( + "NfDeployment with descriptorId {} exists".format( + descriptorId)) diff --git a/o2dms/api/dms_lcm_view.py b/o2dms/api/dms_lcm_view.py new file mode 100644 index 0000000..9995e8e --- /dev/null +++ b/o2dms/api/dms_lcm_view.py @@ -0,0 +1,34 @@ +# Copyright (C) 2021 Wind River Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from sqlalchemy import select +from o2common.service import unit_of_work +from o2ims.adapter.orm import deploymentmanager +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) + + +def deployment_managers(uow: unit_of_work.AbstractUnitOfWork): + with uow: + res = uow.session.execute(select(deploymentmanager)) + return [dict(r) for r in res] + + +def deployment_manager_one(deploymentManagerId: str, + uow: unit_of_work.AbstractUnitOfWork): + with uow: + res = uow.session.execute(select(deploymentmanager).where( + deploymentmanager.c.deploymentManagerId == deploymentManagerId)) + first = res.first() + return None if first is None else dict(first) diff --git a/o2dms/views/dms_route.py b/o2dms/api/dms_route.py similarity index 81% rename from o2dms/views/dms_route.py rename to o2dms/api/dms_route.py index 4541258..480d965 100644 --- a/o2dms/views/dms_route.py +++ b/o2dms/api/dms_route.py @@ -15,9 +15,17 @@ # from flask import jsonify from flask_restx import Resource -from o2dms.views.dms_dto import DmsDTO -from o2dms.views import dms_lcm_view, api_dms_lcm_v1 +from o2dms.api.dms_dto import DmsDTO +from o2dms.api import dms_lcm_view +from o2dms.api.dms_api_ns import api_dms_lcm_v1 + from o2common.service.messagebus import MessageBus +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) + + +def configure_api_route(): + pass # ---------- DeploymentManagers ---------- # @@ -31,6 +39,9 @@ class DmsGetRouter(Resource): @api_dms_lcm_v1.doc('Get deployment manager') @api_dms_lcm_v1.marshal_with(model) def get(self, deploymentManagerID): + logger.debug("get o2dms info:{}".format( + deploymentManagerID + )) bus = MessageBus.get_instance() result = dms_lcm_view.deployment_manager_one( deploymentManagerID, bus.uow) diff --git a/o2dms/views/nfdeployment_desc_route.py b/o2dms/api/nfdeployment_desc_route.py similarity index 80% rename from o2dms/views/nfdeployment_desc_route.py rename to o2dms/api/nfdeployment_desc_route.py index 7bcf3c3..8d6dc91 100644 --- a/o2dms/views/nfdeployment_desc_route.py +++ b/o2dms/api/nfdeployment_desc_route.py @@ -15,12 +15,17 @@ # from flask import jsonify from flask_restx import Resource -from o2common.config import config -from o2dms.views.dms_dto import DmsLcmNfDeploymentDescriptorDTO -from o2dms.views import dms_lcm_view, api_dms_lcm_v1 +from o2dms.api.dms_dto import DmsLcmNfDeploymentDescriptorDTO +from o2dms.api import dms_lcm_nfdeploymentdesc as dms_lcm_view +from o2dms.api.dms_api_ns import api_dms_lcm_v1 + from o2common.service.messagebus import MessageBus +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) + -apibase = config.get_o2dms_api_base() +def configure_api_route(): + pass # LCM services # @@ -49,11 +54,18 @@ class DmsLcmNfDeploymentDescListRouter(Resource): @api_dms_lcm_v1.expect(createdto) @api_dms_lcm_v1.marshal_with(post_resp, code=201) def post(self, deploymentManagerID): - bus = MessageBus.get_instance() - data = api_dms_lcm_v1.payload - id = dms_lcm_view.lcm_nfdeploymentdesc_create( - deploymentManagerID, data, bus.uow) - return {"id": id}, 201 + try: + logger.debug("create deployment desc:{}".format( + api_dms_lcm_v1.payload + )) + bus = MessageBus.get_instance() + data = api_dms_lcm_v1.payload + id = dms_lcm_view.lcm_nfdeploymentdesc_create( + deploymentManagerID, data, bus.uow) + return {"id": id}, 201 + except Exception as ex: + logger.warning("{}".format(str(ex))) + api_dms_lcm_v1.abort(400, str(ex)) @api_dms_lcm_v1\ @@ -85,6 +97,9 @@ class DmsLcmNfDeploymentDescGetRouter(Resource): @api_dms_lcm_v1.doc('Update a NfDeploymentDescriptor') @api_dms_lcm_v1.expect(updatedto) def put(self, nfDeploymentDescriptorId, deploymentManagerID): + logger.debug("update deployment desc:{}".format( + api_dms_lcm_v1.payload + )) bus = MessageBus.get_instance() data = api_dms_lcm_v1.payload dms_lcm_view.lcm_nfdeploymentdesc_update( diff --git a/o2dms/views/nfdeployment_route.py b/o2dms/api/nfdeployment_route.py similarity index 69% rename from o2dms/views/nfdeployment_route.py rename to o2dms/api/nfdeployment_route.py index 962e6f4..bced33d 100644 --- a/o2dms/views/nfdeployment_route.py +++ b/o2dms/api/nfdeployment_route.py @@ -15,12 +15,17 @@ # from flask import jsonify from flask_restx import Resource -from o2common.config import config -from o2dms.views.dms_dto import DmsLcmNfDeploymentDTO -from o2dms.views import dms_lcm_view, api_dms_lcm_v1 +from o2dms.api.dms_dto import DmsLcmNfDeploymentDTO +from o2dms.api import dms_lcm_nfdeployment as dms_lcm_view +from o2dms.api.dms_api_ns import api_dms_lcm_v1 + from o2common.service.messagebus import MessageBus +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) + -apibase = config.get_o2dms_api_base() +def configure_api_route(): + pass # LCM services # @@ -49,11 +54,18 @@ class DmsLcmNfDeploymentListRouter(Resource): @api_dms_lcm_v1.expect(createdto) @api_dms_lcm_v1.marshal_with(post_resp, code=201) def post(self, deploymentManagerID): - bus = MessageBus.get_instance() - data = api_dms_lcm_v1.payload - id = dms_lcm_view.lcm_nfdeployment_create( - deploymentManagerID, data, bus.uow) - return {"id": id}, 201 + try: + logger.debug("create deployment:{}".format( + api_dms_lcm_v1.payload + )) + bus = MessageBus.get_instance() + data = api_dms_lcm_v1.payload + id = dms_lcm_view.lcm_nfdeployment_create( + deploymentManagerID, data, bus) + return {"id": id}, 201 + except Exception as ex: + logger.warning("{}".format(str(ex))) + api_dms_lcm_v1.abort(400, str(ex)) @api_dms_lcm_v1\ @@ -70,7 +82,7 @@ class DmsLcmNfDeploymentGetRouter(Resource): updatedto = DmsLcmNfDeploymentDTO.\ NfDeployment_update - @api_dms_lcm_v1.doc('Get a NfDeploymentDescriptor') + @api_dms_lcm_v1.doc('Get a NfDeployment') @api_dms_lcm_v1.marshal_with(model) def get(self, nfDeploymentId, deploymentManagerID): bus = MessageBus.get_instance() @@ -79,17 +91,25 @@ class DmsLcmNfDeploymentGetRouter(Resource): if result is not None: return result api_dms_lcm_v1.abort( - 404, "NfDeploymentDescriptor {} doesn't exist".format( + 404, "NfDeployment {} doesn't exist".format( nfDeploymentId)) @api_dms_lcm_v1.doc('Update a NfDeployment') @api_dms_lcm_v1.expect(updatedto) def put(self, nfDeploymentId, deploymentManagerID): - bus = MessageBus.get_instance() - data = api_dms_lcm_v1.payload - dms_lcm_view.lcm_nfdeployment_update( - nfDeploymentId, data, bus.uow) - return {}, 201 + try: + logger.debug("update deployment:{},{}".format( + nfDeploymentId, + api_dms_lcm_v1.payload + )) + bus = MessageBus.get_instance() + data = api_dms_lcm_v1.payload + dms_lcm_view.lcm_nfdeployment_update( + nfDeploymentId, data, bus.uow) + return {}, 201 + except Exception as ex: + logger.warning("{}".format(str(ex))) + api_dms_lcm_v1.abort(400, str(ex)) @api_dms_lcm_v1.doc('Delete NfDeployment by ID') @api_dms_lcm_v1.response(204, 'NfDeployment deleted') diff --git a/o2dms/views/ocloud_vresource_route.py b/o2dms/api/ocloud_vresource_route.py similarity index 90% rename from o2dms/views/ocloud_vresource_route.py rename to o2dms/api/ocloud_vresource_route.py index 4f0adfd..8d77650 100644 --- a/o2dms/views/ocloud_vresource_route.py +++ b/o2dms/api/ocloud_vresource_route.py @@ -15,12 +15,17 @@ # from flask import jsonify from flask_restx import Resource -from o2common.config import config -from o2dms.views.dms_dto import DmsLcmNfOCloudVResourceDTO -from o2dms.views import dms_lcm_view, api_dms_lcm_v1 +from o2dms.api.dms_dto import DmsLcmNfOCloudVResourceDTO +from o2dms.api import dms_lcm_nfdeployment_vres as dms_lcm_view +from o2dms.api.dms_api_ns import api_dms_lcm_v1 + from o2common.service.messagebus import MessageBus +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) + -apibase = config.get_o2dms_api_base() +def configure_api_route(): + pass # LCM services # diff --git a/o2dms/domain/commands.py b/o2dms/domain/commands.py new file mode 100644 index 0000000..7c275a2 --- /dev/null +++ b/o2dms/domain/commands.py @@ -0,0 +1,27 @@ +# Copyright (C) 2021 Wind River Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# pylint: disable=too-few-public-methods +# from datetime import date +# from typing import Optional +from dataclasses import dataclass +# from datetime import datetime +# from o2ims.domain.resource_type import ResourceTypeEnum + +from o2common.domain.commands import Command + + +@dataclass +class InstallNfDeployment(Command): + NfDeploymentId: str diff --git a/o2dms/domain/dms.py b/o2dms/domain/dms.py index 28faf3c..783231f 100644 --- a/o2dms/domain/dms.py +++ b/o2dms/domain/dms.py @@ -19,7 +19,8 @@ from o2common.domain.base import AgRoot class NfDeploymentDesc(AgRoot): def __init__(self, id: str, name: str, dmsId: str, description: str = '', - inputParams: str = '', outputParams: str = '',) -> None: + inputParams: str = '', outputParams: str = '', + artifacturl: str = '') -> None: super().__init__() self.id = id self.version_number = 0 @@ -28,6 +29,7 @@ class NfDeploymentDesc(AgRoot): self.description = description self.inputParams = inputParams self.outputParams = outputParams + self.artifactUrl = artifacturl # self.extensions = [] diff --git a/o2dms/domain/dms_repo.py b/o2dms/domain/dms_repo.py index c53d90f..4a63a85 100644 --- a/o2dms/domain/dms_repo.py +++ b/o2dms/domain/dms_repo.py @@ -40,6 +40,9 @@ class NfDeploymentRepository(abc.ABC): def delete(self, nfdeployment_id): self._delete(nfdeployment_id) + def count(self, **kwargs): + return self._count(**kwargs) + @abc.abstractmethod def _add(self, nfdeployment: dms.NfDeployment): raise NotImplementedError @@ -56,6 +59,10 @@ class NfDeploymentRepository(abc.ABC): def _delete(self, nfdeployment_id): raise NotImplementedError + @abc.abstractmethod + def _count(self, **kwargs): + raise NotImplementedError + class NfDeploymentDescRepository(abc.ABC): def __init__(self): @@ -80,6 +87,9 @@ class NfDeploymentDescRepository(abc.ABC): def delete(self, nfdeployment_descriptor_id): self._delete(nfdeployment_descriptor_id) + def count(self, **kwargs): + return self._count(**kwargs) + @abc.abstractmethod def _add(self, nfdeployment_descriptor: dms.NfDeploymentDesc): raise NotImplementedError @@ -96,6 +106,10 @@ class NfDeploymentDescRepository(abc.ABC): def _delete(self, nfdeployment_descriptor_id): raise NotImplementedError + @abc.abstractmethod + def _count(self, **kwargs): + raise NotImplementedError + class NfOCloudVResourceRepository(abc.ABC): def __init__(self): diff --git a/o2dms/views/__init__.py b/o2dms/domain/events.py similarity index 66% rename from o2dms/views/__init__.py rename to o2dms/domain/events.py index 7a888a6..93af574 100644 --- a/o2dms/views/__init__.py +++ b/o2dms/domain/events.py @@ -1,25 +1,27 @@ -# Copyright (C) 2021 Wind River Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from flask_restx import Namespace -from o2common.config import config - - -api_dms_lcm_v1 = Namespace( - "O2DMS_LCM", description='DMS LCM related operations.') -apibase = config.get_o2dms_api_base() - - -def configure_namespace(app): - app.add_namespace(api_dms_lcm_v1, path=apibase) +# Copyright (C) 2021 Wind River Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# pylint: disable=too-few-public-methods +from dataclasses import dataclass +from o2common.domain.events import Event + + +@dataclass +class NfDeploymentCreated(Event): + NfDeploymentId: str + + +@dataclass +class NfDeploymentDeleted(Event): + NfDeploymentId: str diff --git a/o2dms/service/nfdeployment_handler.py b/o2dms/service/nfdeployment_handler.py new file mode 100644 index 0000000..6143f18 --- /dev/null +++ b/o2dms/service/nfdeployment_handler.py @@ -0,0 +1,43 @@ +# Copyright (C) 2021 Wind River Systems, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# pylint: disable=unused-argument +from __future__ import annotations +from o2dms.domain.commands import InstallNfDeployment +from typing import Callable + +from o2dms.domain import events +from o2common.service.unit_of_work import AbstractUnitOfWork +# if TYPE_CHECKING: +# from . import unit_of_work + +from o2common.helper import o2logging +logger = o2logging.get_logger(__name__) + + +def publish_nfdeployment_created( + event: events.NfDeploymentCreated, + publish: Callable, +): + publish("NfDeploymentCreated", event) + logger.debug("published NfDeploymentCreated: {}".format( + event.NfDeploymentId)) + + +def install_nfdeployment( + cmd: InstallNfDeployment, + uow: AbstractUnitOfWork +): + logger.info("install with NfDeploymentId: {}".format( + cmd.NfDeploymentId)) diff --git a/o2dms/views/dms_lcm_view.py b/o2dms/views/dms_lcm_view.py deleted file mode 100644 index 186c9c3..0000000 --- a/o2dms/views/dms_lcm_view.py +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright (C) 2021 Wind River Systems, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from sqlalchemy import select -import uuid -from o2common.service import unit_of_work -from o2ims.adapter.orm import deploymentmanager -from o2dms.adapter.orm import nfDeploymentDesc, nfDeployment, nfOCloudVResource -from o2dms.views.dms_dto import DmsLcmNfDeploymentDescriptorDTO -from o2dms.views.dms_dto import DmsLcmNfDeploymentDTO -from o2dms.domain.dms import NfDeploymentDesc, NfDeployment - - -def deployment_managers(uow: unit_of_work.AbstractUnitOfWork): - with uow: - res = uow.session.execute(select(deploymentmanager)) - return [dict(r) for r in res] - - -def deployment_manager_one(deploymentManagerId: str, - uow: unit_of_work.AbstractUnitOfWork): - with uow: - res = uow.session.execute(select(deploymentmanager).where( - deploymentmanager.c.deploymentManagerId == deploymentManagerId)) - first = res.first() - return None if first is None else dict(first) - - -def lcm_nfdeploymentdesc_list(deploymentManagerID: str, - uow: unit_of_work.AbstractUnitOfWork): - with uow: - res = uow.session.execute(select(nfDeploymentDesc).where( - nfDeploymentDesc.c.deploymentManagerId == deploymentManagerID)) - return [dict(r) for r in res] - - -def lcm_nfdeploymentdesc_one(nfdeploymentdescriptorid: str, - uow: unit_of_work.AbstractUnitOfWork): - with uow: - res = uow.session.execute(select(nfDeploymentDesc).where( - nfDeploymentDesc.c.id == nfdeploymentdescriptorid)) - first = res.first() - return None if first is None else dict(first) - - -def lcm_nfdeploymentdesc_create( - deploymentManagerId: str, - input: DmsLcmNfDeploymentDescriptorDTO. - NfDeploymentDescriptor_create, - uow: unit_of_work.AbstractUnitOfWork): - - id = str(uuid.uuid4()) - entity = NfDeploymentDesc( - id, input['name'], deploymentManagerId, input['description'], - input['inputParams'], input['outputParams']) - with uow: - uow.nfdeployment_descs.add(entity) - uow.commit() - return id - - -def lcm_nfdeploymentdesc_update( - nfdeploymentdescriptorid: str, - input: DmsLcmNfDeploymentDescriptorDTO.NfDeploymentDescriptor_update, - uow: unit_of_work.AbstractUnitOfWork): - - with uow: - entity = uow.nfdeployment_descs.get(nfdeploymentdescriptorid) - entity.name = input['name'] - entity.description = input['description'] - entity.inputParams = input['inputParams'] - entity.outputParams = input['outputParams'] - uow.commit() - return True - - -def lcm_nfdeploymentdesc_delete( - nfdeploymentdescriptorid: str, uow: unit_of_work.AbstractUnitOfWork): - - with uow: - uow.nfdeployment_descs.delete(nfdeploymentdescriptorid) - uow.commit() - return True - - -def lcm_nfdeployment_list( - deploymentManagerID: str, uow: unit_of_work.AbstractUnitOfWork): - with uow: - res = uow.session.execute(select(nfDeployment).where( - nfDeployment.c.deploymentManagerId == deploymentManagerID)) - return [dict(r) for r in res] - - -def lcm_nfdeployment_one( - nfdeploymentid: str, uow: unit_of_work.AbstractUnitOfWork): - with uow: - res = uow.session.execute(select(nfDeployment).where( - nfDeployment.c.id == nfdeploymentid)) - first = res.first() - return None if first is None else dict(first) - - -def lcm_nfdeployment_create( - deploymentManagerId: str, - input: DmsLcmNfDeploymentDTO. - NfDeployment_create, - uow: unit_of_work.AbstractUnitOfWork): - - id = str(uuid.uuid4()) - entity = NfDeployment( - id, input['name'], deploymentManagerId, input['description'], - input['descriptorId'], input['parentDeploymentId']) - with uow: - uow.nfdeployments.add(entity) - uow.commit() - return id - - -def lcm_nfdeployment_update( - nfdeploymentdescriptorid: str, - input: DmsLcmNfDeploymentDTO.NfDeployment_update, - uow: unit_of_work.AbstractUnitOfWork): - - with uow: - entity = uow.nfdeployments.get(nfdeploymentdescriptorid) - entity.name = input['name'] - entity.description = input['description'] - entity.inputParams = input['descriptorId'] - entity.outputParams = input['parentDeploymentId'] - uow.commit() - return True - - -def lcm_nfdeployment_delete( - nfdeploymentdescriptorid: str, uow: unit_of_work.AbstractUnitOfWork): - - with uow: - uow.nfdeployments.delete(nfdeploymentdescriptorid) - uow.commit() - return True - - -def lcm_nfocloudvresource_list( - nfDeploymentId: str, uow: unit_of_work.AbstractUnitOfWork): - with uow: - res = uow.session.execute(select(nfOCloudVResource).where( - nfOCloudVResource.c.nfDeploymentId == nfDeploymentId)) - return [dict(r) for r in res] - - -def lcm_nfocloudvresource_one( - ocloudvresourceId: str, uow: unit_of_work.AbstractUnitOfWork): - with uow: - res = uow.session.execute(select(nfOCloudVResource).where( - nfOCloudVResource.c.id == ocloudvresourceId)) - first = res.first() - return None if first is None else dict(first) -- 2.16.6