From a9840e41848cbbffcedf76f0a53ffc5d9bc87c01 Mon Sep 17 00:00:00 2001 From: "Zhang Rong(Jon)" Date: Fri, 28 Oct 2022 20:18:09 +0800 Subject: [PATCH] Add api_versions support; update model of ocloud, resourcepool, and resource Issue-ID: INF-301 Issue-ID: INF-306 Issue-ID: INF-311 Signed-off-by: Zhang Rong(Jon) Change-Id: I7a2cc626c87fc8c43fcbd1f750948c7f8d7aae52 --- configs/o2app.conf | 2 + o2app/adapter/unit_of_work.py | 5 +- o2common/config/config.py | 4 +- o2ims/__init__.py | 10 ++ o2ims/adapter/clients/alarm_dict_client.py | 24 +++-- o2ims/adapter/orm.py | 31 +++--- o2ims/domain/ocloud.py | 54 +++++++---- o2ims/domain/resource_type.py | 7 ++ o2ims/domain/subscription_obj.py | 3 +- o2ims/service/auditor/pserver_cpu_handler.py | 2 +- o2ims/service/auditor/pserver_eth_handler.py | 2 +- o2ims/service/auditor/pserver_handler.py | 2 +- o2ims/service/auditor/pserver_if_handler.py | 2 +- o2ims/service/auditor/pserver_mem_handler.py | 2 +- o2ims/service/auditor/pserver_port_handler.py | 2 +- o2ims/views/__init__.py | 4 +- o2ims/views/alarm_dto.py | 2 +- o2ims/views/alarm_route.py | 24 ++++- o2ims/views/api_ns.py | 32 +++++- o2ims/views/ocloud_dto.py | 134 ++++++++++++++------------ o2ims/views/ocloud_route.py | 38 +++++--- o2ims/views/ocloud_view.py | 4 +- tests/unit/test_alarm.py | 24 +---- tests/unit/test_ocloud.py | 16 +-- tox.ini | 1 + 25 files changed, 259 insertions(+), 172 deletions(-) diff --git a/configs/o2app.conf b/configs/o2app.conf index 6ee900a..036ad09 100644 --- a/configs/o2app.conf +++ b/configs/o2app.conf @@ -3,6 +3,8 @@ ocloud_global_id = 4e24b97c-8c49-4c4f-b53e-3de5235a4e37 smo_register_url = http://127.0.0.1:8090/register smo_token_data = smo_token_payload + + [API] test = "hello" diff --git a/o2app/adapter/unit_of_work.py b/o2app/adapter/unit_of_work.py index 7e16308..93893e2 100644 --- a/o2app/adapter/unit_of_work.py +++ b/o2app/adapter/unit_of_work.py @@ -21,7 +21,7 @@ from sqlalchemy.orm.session import Session from o2common.config import config from o2common.service.unit_of_work import AbstractUnitOfWork -from o2ims.adapter import ocloud_repository, alarm_repository, alarm_loader +from o2ims.adapter import ocloud_repository, alarm_repository from o2dms.adapter import dms_repository from o2common.helper import o2logging @@ -74,9 +74,6 @@ class SqlAlchemyUnitOfWork(AbstractUnitOfWork): self.alarm_probable_causes = alarm_repository\ .AlarmProbableCauseSqlAlchemyRepository(self.session) - # config file - self.alarm_dictionaries = alarm_loader\ - .AlarmDictionaryConfigFileRepository() return super().__enter__() def __exit__(self, *args): diff --git a/o2common/config/config.py b/o2common/config/config.py index b1d2cae..9756535 100644 --- a/o2common/config/config.py +++ b/o2common/config/config.py @@ -55,11 +55,11 @@ def get_root_api_base(): def get_o2ims_api_base(): - return get_root_api_base() + 'o2ims-infrastructureInventory/v1' + return get_root_api_base() + 'o2ims-infrastructureInventory' def get_o2ims_monitoring_api_base(): - return get_root_api_base() + 'o2ims-infrastructureMonitoring/v1' + return get_root_api_base() + 'o2ims-infrastructureMonitoring' def get_o2dms_api_base(): diff --git a/o2ims/__init__.py b/o2ims/__init__.py index 813897e..a475140 100644 --- a/o2ims/__init__.py +++ b/o2ims/__init__.py @@ -11,3 +11,13 @@ # 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 o2common.config import config, conf +from o2ims.adapter import alarm_loader +from o2ims.adapter.clients.alarm_dict_client import \ + load_alarm_dictionary_from_conf_file + +# config file +conf.alarm_dictionaries = alarm_loader\ + .AlarmDictionaryConfigFileRepository() +load_alarm_dictionary_from_conf_file(config.get_alarm_yaml_filename()) diff --git a/o2ims/adapter/clients/alarm_dict_client.py b/o2ims/adapter/clients/alarm_dict_client.py index e15531a..521453b 100644 --- a/o2ims/adapter/clients/alarm_dict_client.py +++ b/o2ims/adapter/clients/alarm_dict_client.py @@ -20,15 +20,14 @@ import collections import uuid as uuid_gen from o2common.service import unit_of_work -from o2common.config import config +from o2common.config import config, conf from o2ims.domain import alarm_obj as alarm from o2common.helper import o2logging logger = o2logging.get_logger(__name__) -def load_alarm_dictionary_from_conf_file(conf_path: str, - uow: unit_of_work.AbstractUnitOfWork): +def load_alarm_dictionary_from_conf_file(conf_path: str): logger.info("Converting alarm.yaml to dict: ") @@ -48,16 +47,15 @@ def load_alarm_dictionary_from_conf_file(conf_path: str, raise RuntimeError(exp) for dictionary in list(dictionaries.keys()): - with uow: - # res_type = uow.resource_types.get_by_name(dictionary) - # logger.info('res_type: ' + res_type.resourceTypeName) - alarm_dict = alarm.AlarmDictionary(dictionary) - alarm_dict.entityType = dictionary - alarm_dict.alarmDictionaryVersion = \ - dictionaries[dictionary]['version'] - alarm_dict.alarmDefinition = \ - dictionaries[dictionary]['alarmDefinition'] - uow.alarm_dictionaries.add(alarm_dict) + # res_type = uow.resource_types.get_by_name(dictionary) + # logger.info('res_type: ' + res_type.resourceTypeName) + alarm_dict = alarm.AlarmDictionary(dictionary) + alarm_dict.entityType = dictionary + alarm_dict.alarmDictionaryVersion = \ + dictionaries[dictionary]['version'] + alarm_dict.alarmDefinition = \ + dictionaries[dictionary]['alarmDefinition'] + conf.alarm_dictionaries.add(alarm_dict) def prettyDict(dict): diff --git a/o2ims/adapter/orm.py b/o2ims/adapter/orm.py index 4e3e39f..f7ea107 100644 --- a/o2ims/adapter/orm.py +++ b/o2ims/adapter/orm.py @@ -37,7 +37,7 @@ from sqlalchemy.orm import mapper, relationship from o2ims.domain import ocloud as ocloudModel from o2ims.domain import subscription_obj as subModel from o2ims.domain import alarm_obj as alarmModel -from o2ims.domain.resource_type import ResourceTypeEnum +from o2ims.domain.resource_type import ResourceTypeEnum, ResourceKindEnum # from o2ims.domain.alarm_obj import AlarmLastChangeEnum, PerceivedSeverityEnum from o2common.helper import o2logging @@ -54,34 +54,39 @@ ocloud = Table( Column("version_number", Integer), Column("oCloudId", String(255), primary_key=True), - Column("globalcloudId", String(255)), + Column("globalCloudId", String(255)), Column("name", String(255)), Column("description", String(255)), - Column("serviceUri", String(255)) + Column("serviceUri", String(255)), + Column("smoRegistrationService", String(255)) # Column("extensions", String(1024)) ) resourcetype = Table( - "resourcetype", + "resourceType", metadata, Column("updatetime", DateTime), Column("createtime", DateTime), Column("hash", String(255)), + Column("version_number", Integer), Column("resourceTypeId", String(255), primary_key=True), Column("resourceTypeEnum", Enum( ResourceTypeEnum, native_enum=False), nullable=False), - Column("oCloudId", ForeignKey("ocloud.oCloudId")), Column("name", String(255)), + Column("description", String(255)), Column("vendor", String(255)), Column("model", String(255)), Column("version", String(255)), - Column("description", String(255)), + Column("resourceKind", Enum(ResourceKindEnum)), + Column("resourceClass", Enum(ResourceTypeEnum)), # Column("extensions", String(1024)) + + Column("oCloudId", ForeignKey("ocloud.oCloudId")), ) resourcepool = Table( - "resourcepool", + "resourcePool", metadata, Column("updatetime", DateTime), Column("createtime", DateTime), @@ -107,10 +112,10 @@ resource = Table( Column("version_number", Integer), Column("resourceId", String(255), primary_key=True), - Column("resourceTypeId", ForeignKey("resourcetype.resourceTypeId")), - Column("resourcePoolId", ForeignKey("resourcepool.resourcePoolId")), + Column("resourceTypeId", ForeignKey("resourceType.resourceTypeId")), + Column("resourcePoolId", ForeignKey("resourcePool.resourcePoolId")), Column("name", String(255)), - # Column("globalAssetId", String(255)), + Column("globalAssetId", String(255)), Column("parentId", String(255)), Column("description", String(255)), Column("elements", Text()) @@ -118,7 +123,7 @@ resource = Table( ) deploymentmanager = Table( - "deploymentmanager", + "deploymentManager", metadata, Column("updatetime", DateTime), Column("createtime", DateTime), @@ -129,7 +134,7 @@ deploymentmanager = Table( Column("oCloudId", ForeignKey("ocloud.oCloudId")), Column("name", String(255)), Column("description", String(255)), - Column("deploymentManagementServiceEndpoint", String(255)), + Column("serviceUri", String(255)), Column("supportedLocations", String(255)), Column("capabilities", String(255)), Column("capacity", String(255)), @@ -175,7 +180,7 @@ alarm_event_record = Table( Column("hash", String(255)), Column("alarmEventRecordId", String(255), primary_key=True), - Column("resourceTypeId", ForeignKey("resourcetype.resourceTypeId")), + Column("resourceTypeId", ForeignKey("resourceType.resourceTypeId")), Column("resourceId", ForeignKey("resource.resourceId")), Column("alarmDefinitionId", ForeignKey( "alarmDefinition.alarmDefinitionId")), diff --git a/o2ims/domain/ocloud.py b/o2ims/domain/ocloud.py index 047fb8b..a8e7c2f 100644 --- a/o2ims/domain/ocloud.py +++ b/o2ims/domain/ocloud.py @@ -16,10 +16,11 @@ from __future__ import annotations import json from o2common.domain.base import AgRoot, Serializer +from o2common.config import conf as CONF # from dataclasses import dataclass # from datetime import date # from typing import Optional, List, Set -from .resource_type import ResourceTypeEnum +from .resource_type import ResourceKindEnum, ResourceTypeEnum # from uuid import UUID @@ -35,17 +36,18 @@ class DeploymentManager(AgRoot, Serializer): capacity: str = '', profile: str = '') -> None: super().__init__() self.deploymentManagerId = id - self.version_number = 0 - self.oCloudId = ocloudid self.name = name self.description = description - self.deploymentManagementServiceEndpoint = dmsendpoint + self.oCloudId = ocloudid + self.serviceUri = dmsendpoint self.supportedLocations = supportedLocations self.capabilities = capabilities self.capacity = capacity self.profile = profile self.extensions = [] + self.version_number = 0 + def serialize(self): d = Serializer.serialize(self) @@ -66,14 +68,16 @@ class ResourcePool(AgRoot, Serializer): description: str = '') -> None: super().__init__() self.resourcePoolId = id - self.version_number = 0 - self.oCloudId = ocloudid self.globalLocationId = gLocationId self.name = name - self.location = location self.description = description + self.oCloudId = ocloudid + self.location = location + self.resources = '' self.extensions = [] + self.version_number = 0 + class ResourceType(AgRoot, Serializer): def __init__(self, typeid: str, name: str, typeEnum: ResourceTypeEnum, @@ -82,16 +86,26 @@ class ResourceType(AgRoot, Serializer): description: str = '') -> None: super().__init__() self.resourceTypeId = typeid - self.version_number = 0 - self.oCloudId = ocloudid self.resourceTypeEnum = typeEnum self.name = name + self.description = description self.vender = vender self.model = model self.version = version - self.description = description + self.alarmDictionary = {} + self.resourceKind = ResourceKindEnum.UNDEFINED + self.resourceClass = ResourceTypeEnum.UNDEFINED self.extensions = [] + self.version_number = 0 + + def serialize(self): + d = Serializer.serialize(self) + + d["alarmDictionary"] = CONF.alarm_dictionaries.get( + d['name']).serialize() + return d + class Resource(AgRoot, Serializer): def __init__(self, resourceId: str, resourceTypeId: str, @@ -100,16 +114,18 @@ class Resource(AgRoot, Serializer): description: str = '') -> None: super().__init__() self.resourceId = resourceId - self.version_number = 0 + self.description = description self.resourceTypeId = resourceTypeId + self.globalAssetId = gAssetId self.resourcePoolId = resourcePoolId + self.elements = elements + self.extensions = [] + self.name = name - self.globalAssetId = gAssetId self.parentId = parentId - self.elements = elements - self.description = description self.children = [] - self.extensions = [] + + self.version_number = 0 def set_children(self, children: list): self.children = children @@ -139,16 +155,18 @@ class Ocloud(AgRoot, Serializer): description: str = '', version_number: int = 0) -> None: super().__init__() self.oCloudId = ocloudid - self.globalcloudId = globalcloudId - self.version_number = version_number + self.globalCloudId = globalcloudId self.name = name self.description = description self.serviceUri = imsendpoint + self.resourceTypes = [] self.resourcePools = [] self.deploymentManagers = [] - self.resourceTypes = [] + self.smoRegistrationService = '' self.extensions = [] + self.version_number = version_number + # def addDeploymentManager(self, # deploymentManager: DeploymentManager): diff --git a/o2ims/domain/resource_type.py b/o2ims/domain/resource_type.py index 8267d9e..3a2271a 100644 --- a/o2ims/domain/resource_type.py +++ b/o2ims/domain/resource_type.py @@ -2,6 +2,7 @@ from enum import Enum class ResourceTypeEnum(Enum): + UNDEFINED = 0 OCLOUD = 1 RESOURCE_POOL = 2 DMS = 3 @@ -13,6 +14,12 @@ class ResourceTypeEnum(Enum): PSERVER_ETH = 16 +class ResourceKindEnum(Enum): + UNDEFINED = 0 + PHYSICAL = 1 + LOGICAL = 2 + + class InvalidOcloudState(Exception): pass diff --git a/o2ims/domain/subscription_obj.py b/o2ims/domain/subscription_obj.py index 49447d0..a5afd9f 100644 --- a/o2ims/domain/subscription_obj.py +++ b/o2ims/domain/subscription_obj.py @@ -24,11 +24,12 @@ class Subscription(AgRoot, Serializer): filter: str = '') -> None: super().__init__() self.subscriptionId = id - self.version_number = 0 self.callback = callback self.consumerSubscriptionId = consumersubid self.filter = filter + self.version_number = 0 + class NotificationEventEnum(str, Enum): CREATE = 'CREATE' diff --git a/o2ims/service/auditor/pserver_cpu_handler.py b/o2ims/service/auditor/pserver_cpu_handler.py index cac4690..6364226 100644 --- a/o2ims/service/auditor/pserver_cpu_handler.py +++ b/o2ims/service/auditor/pserver_cpu_handler.py @@ -44,7 +44,7 @@ def update_pserver_cpu( res = uow.session.execute( ''' SELECT "resourceTypeId", "oCloudId", "name" - FROM resourcetype + FROM "resourceType" WHERE "resourceTypeEnum" = :resource_type_enum ''', dict(resource_type_enum=stxobj.type.name) diff --git a/o2ims/service/auditor/pserver_eth_handler.py b/o2ims/service/auditor/pserver_eth_handler.py index 5f6c341..5731618 100644 --- a/o2ims/service/auditor/pserver_eth_handler.py +++ b/o2ims/service/auditor/pserver_eth_handler.py @@ -44,7 +44,7 @@ def update_pserver_eth( res = uow.session.execute( ''' SELECT "resourceTypeId", "oCloudId", "name" - FROM resourcetype + FROM "resourceType" WHERE "resourceTypeEnum" = :resource_type_enum ''', dict(resource_type_enum=stxobj.type.name) diff --git a/o2ims/service/auditor/pserver_handler.py b/o2ims/service/auditor/pserver_handler.py index d18d3c3..884f276 100644 --- a/o2ims/service/auditor/pserver_handler.py +++ b/o2ims/service/auditor/pserver_handler.py @@ -47,7 +47,7 @@ def update_pserver( res = uow.session.execute( ''' SELECT "resourceTypeId", "oCloudId", "name" - FROM resourcetype + FROM "resourceType" WHERE "resourceTypeEnum" = :resource_type_enum ''', dict(resource_type_enum=stxobj.type.name) diff --git a/o2ims/service/auditor/pserver_if_handler.py b/o2ims/service/auditor/pserver_if_handler.py index cd4e680..94602f7 100644 --- a/o2ims/service/auditor/pserver_if_handler.py +++ b/o2ims/service/auditor/pserver_if_handler.py @@ -44,7 +44,7 @@ def update_pserver_if( res = uow.session.execute( ''' SELECT "resourceTypeId", "oCloudId", "name" - FROM resourcetype + FROM "resourceType" WHERE "resourceTypeEnum" = :resource_type_enum ''', dict(resource_type_enum=stxobj.type.name) diff --git a/o2ims/service/auditor/pserver_mem_handler.py b/o2ims/service/auditor/pserver_mem_handler.py index 683475e..388f041 100644 --- a/o2ims/service/auditor/pserver_mem_handler.py +++ b/o2ims/service/auditor/pserver_mem_handler.py @@ -44,7 +44,7 @@ def update_pserver_mem( res = uow.session.execute( ''' SELECT "resourceTypeId", "oCloudId", "name" - FROM resourcetype + FROM "resourceType" WHERE "resourceTypeEnum" = :resource_type_enum ''', dict(resource_type_enum=stxobj.type.name) diff --git a/o2ims/service/auditor/pserver_port_handler.py b/o2ims/service/auditor/pserver_port_handler.py index bfb2e1d..bfec06f 100644 --- a/o2ims/service/auditor/pserver_port_handler.py +++ b/o2ims/service/auditor/pserver_port_handler.py @@ -44,7 +44,7 @@ def update_pserver_port( res = uow.session.execute( ''' SELECT "resourceTypeId", "oCloudId", "name" - FROM resourcetype + FROM "resourceType" WHERE "resourceTypeEnum" = :resource_type_enum ''', dict(resource_type_enum=stxobj.type.name) diff --git a/o2ims/views/__init__.py b/o2ims/views/__init__.py index 108c124..42ba58c 100644 --- a/o2ims/views/__init__.py +++ b/o2ims/views/__init__.py @@ -31,5 +31,5 @@ def configure_namespace(app): ocloud_route.configure_api_route() alarm_route.configure_api_route() - app.add_namespace(api_ns.api_ims_inventory_v1, path=apiims) - app.add_namespace(api_ns.api_monitoring_v1, path=apimonitoring) + app.add_namespace(api_ns.api_ims_inventory, path=apiims) + app.add_namespace(api_ns.api_ims_monitoring, path=apimonitoring) diff --git a/o2ims/views/alarm_dto.py b/o2ims/views/alarm_dto.py index 54bfe7d..da95a55 100644 --- a/o2ims/views/alarm_dto.py +++ b/o2ims/views/alarm_dto.py @@ -14,7 +14,7 @@ from flask_restx import fields -from o2ims.views.api_ns import api_monitoring_v1 +from o2ims.views.api_ns import api_ims_monitoring as api_monitoring_v1 class AlarmDTO: diff --git a/o2ims/views/alarm_route.py b/o2ims/views/alarm_route.py index 94bfbd4..113fc46 100644 --- a/o2ims/views/alarm_route.py +++ b/o2ims/views/alarm_route.py @@ -18,7 +18,7 @@ from flask_restx import Resource, reqparse from o2common.service.messagebus import MessageBus from o2common.views.pagination_route import link_header, PAGE_PARAM from o2ims.views import alarm_view -from o2ims.views.api_ns import api_monitoring_v1 +from o2ims.views.api_ns import api_ims_monitoring as api_monitoring_v1 from o2ims.views.alarm_dto import AlarmDTO, SubscriptionDTO from o2common.helper import o2logging @@ -31,8 +31,22 @@ def configure_api_route(): bus = MessageBus.get_instance() +# ---------- API versions ---------- # +@api_monitoring_v1.route("/v1/api_versions") +class VersionRouter(Resource): + def get(self): + return { + 'uriPrefix': request.base_url.rsplit('/', 1)[0], + 'apiVersions': [{ + 'version': '1', + # 'isDeprecated': 'False', + # 'retirementDate': '' + }] + } + + # ---------- Alarm Event Record ---------- # -@api_monitoring_v1.route("/alarms") +@api_monitoring_v1.route("/v1/alarms") @api_monitoring_v1.param(PAGE_PARAM, 'Page number of the results to fetch.' + ' Default: 1', @@ -81,7 +95,7 @@ class AlarmListRouter(Resource): return link_header(request.full_path, ret) -@api_monitoring_v1.route("/alarms/") +@api_monitoring_v1.route("/v1/alarms/") @api_monitoring_v1.param('alarmEventRecordId', 'ID of the alarm event record') @api_monitoring_v1.response(404, 'Alarm Event Record not found') @api_monitoring_v1.param( @@ -120,7 +134,7 @@ class AlarmGetRouter(Resource): # ---------- Alarm Subscriptions ---------- # -@api_monitoring_v1.route("/alarmSubscriptions") +@api_monitoring_v1.route("/v1/alarmSubscriptions") class SubscriptionsListRouter(Resource): model = SubscriptionDTO.subscription_get @@ -180,7 +194,7 @@ class SubscriptionsListRouter(Resource): return result, 201 -@api_monitoring_v1.route("/alarmSubscriptions/") +@api_monitoring_v1.route("/v1/alarmSubscriptions/") @api_monitoring_v1.param('alarmSubscriptionID', 'ID of the Alarm Subscription') @api_monitoring_v1.response(404, 'Alarm Subscription not found') class SubscriptionGetDelRouter(Resource): diff --git a/o2ims/views/api_ns.py b/o2ims/views/api_ns.py index b06cb2a..711d5d2 100644 --- a/o2ims/views/api_ns.py +++ b/o2ims/views/api_ns.py @@ -12,10 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +from flask import request +from flask_restx import Resource from o2common.views.route import O2Namespace -api_ims_inventory_v1 = O2Namespace( +api_ims_inventory = O2Namespace( "O2IMS_Inventory", description='IMS Inventory related operations.') @@ -23,6 +25,32 @@ api_provision_v1 = O2Namespace( "PROVISION", description='Provision related operations.') -api_monitoring_v1 = O2Namespace( +api_ims_monitoring = O2Namespace( "O2IMS_InfrastructureMonitoring", description='O2 IMS Monitoring related operations.') + + +@api_ims_inventory.route('/api_versions') +class InventoryVersion(Resource): + def get(): + return { + 'uriPrefix': request.base_url.rsplit('/', 1)[0], + 'apiVersions': [{ + 'version': '1', + # 'isDeprecated': 'False', + # 'retirementDate': '' + }] + } + + +@api_ims_monitoring.route('/api_versions') +class MonitoringVersion(Resource): + def get(): + return { + 'uriPrefix': request.base_url.rsplit('/', 1)[0], + 'apiVersions': [{ + 'version': '1', + # 'isDeprecated': 'False', + # 'retirementDate': '' + }] + } diff --git a/o2ims/views/ocloud_dto.py b/o2ims/views/ocloud_dto.py index df8385a..0b3291f 100644 --- a/o2ims/views/ocloud_dto.py +++ b/o2ims/views/ocloud_dto.py @@ -14,7 +14,7 @@ from flask_restx import fields -from o2ims.views.api_ns import api_ims_inventory_v1 +from o2ims.views.api_ns import api_ims_inventory as api_ims_inventory_v1 class OcloudDTO: @@ -23,15 +23,37 @@ class OcloudDTO: "OcloudDto", { 'oCloudId': fields.String(required=True), - 'globalCloudId': fields.String, + 'globalcloudId': fields.String(attribute='globalCloudId'), 'name': fields.String, 'description': fields.String, - 'infrastructureManagementServiceEndpoint': fields.String, + 'serviceUri': fields.String(attribute='serviceUri'), + # 'infrastructureManagementServiceEndpoint': fields.String( + # attribute='serviceUri'), + # 'infrastructureMangementServiceEndPoint': fields.String( + # attribute='serviceUri'), + # 'resourceTypes': fields.String, + # 'resourcePools': fields.String, + # 'deploymentManagers': fields.String, + # 'smoRegistrationService': fields.String + 'extensions': fields.String } ) class ResourceTypeDTO: + alarm_dictionary = api_ims_inventory_v1.model( + "AlarmDictionaryDto", + { + 'id': fields.String, + 'alarmDictionaryVersion': fields.String, + 'alarmDictionarySchemVersion': fields.String, + 'entityType': fields.String, + 'vendor': fields.String, + 'managementInterfaceId': fields.String, + 'pkNotificationField': fields.String, + 'alarmDefinition': fields.String, + } + ) resource_type_get = api_ims_inventory_v1.model( "ResourceTypeGetDto", @@ -39,9 +61,14 @@ class ResourceTypeDTO: 'resourceTypeId': fields.String(required=True, description='Resource type ID'), 'name': fields.String, + 'description': fields.String, 'vendor': fields.String, + 'model': fields.String, 'version': fields.String, - 'description': fields.String, + 'alarmDictionary': fields.Nested(alarm_dictionary, False, True), + # 'resourceKind': fields.String, + # 'resourceClass': fields.String, + 'extensions': fields.String } ) @@ -53,10 +80,13 @@ class ResourcePoolDTO: { 'resourcePoolId': fields.String(required=True, description='Resource pool ID'), - 'name': fields.String, 'globalLocationId': fields.String, - 'location': fields.String, + 'name': fields.String, 'description': fields.String, + 'oCloudId': fields.String, + 'location': fields.String, + # 'resources': fields.String, + 'extensions': fields.String } ) @@ -69,9 +99,12 @@ class ResourceDTO: description='Resource ID'), 'resourceTypeId': fields.String, 'resourcePoolId': fields.String, - 'name': fields.String, + 'globalAssetId': fields.String, + # 'name': fields.String, 'parentId': fields.String, 'description': fields.String, + # 'elements': fields.String, + 'extensions': fields.String } ) @@ -81,53 +114,20 @@ class ResourceDTO: description='Resource ID'), 'resourceTypeId': fields.String, 'resourcePoolId': fields.String, - 'name': fields.String, + 'globalAssetId': fields.String, + # 'name': fields.String, 'parentId': fields.String, 'description': fields.String, - 'elements': fields.String, + # 'elements': fields.String, + 'extensions': fields.String } if iteration_number: - resource_json_mapping['children'] = fields.List( + resource_json_mapping['elements'] = fields.List( fields.Nested(ResourceDTO.recursive_resource_mapping( - iteration_number-1))) + iteration_number-1)), attribute='children') return api_ims_inventory_v1.model( 'ResourceGetDto' + str(iteration_number), resource_json_mapping) - # def _recursive_resource_mapping(self, iteration_number=2): - # resource_json_mapping = { - # 'resourceId': fields.String(required=True, - # description='Resource ID'), - # 'resourceTypeId': fields.String, - # 'resourcePoolId': fields.String, - # 'name': fields.String, - # 'parentId': fields.String, - # 'description': fields.String, - # } - # if iteration_number: - # resource_json_mapping['children'] = fields.List( - # fields.Nested(self._recursive_resource_mapping( - # iteration_number-1))) - # # print(type(resource_json_mapping['children'])) - # if resource_json_mapping['children'] is None: - # del resource_json_mapping['children'] - # return resource_json_mapping - - # def get_resource_get(self): - # return api_ims_inventory_v1.model( - # 'ResourceGetDto', - # { - # 'resourceId': fields.String(required=True, - # description='Resource ID'), - # 'resourceTypeId': fields.String, - # 'resourcePoolId': fields.String, - # 'name': fields.String, - # 'parentId': fields.String, - # 'description': fields.String, - # 'children': fields.List(fields.Nested( - # self._recursive_resource_mapping())) - # } - # ) - class DeploymentManagerDTO: @@ -139,30 +139,33 @@ class DeploymentManagerDTO: description='Deployment manager ID'), 'name': fields.String, 'description': fields.String, - 'deploymentManagementServiceEndpoint': fields.String, - 'supportedLocations': fields.String, - 'capabilities': fields.String, - 'capacity': fields.String, + 'serviceUri': fields.String(attribute='serviceUri'), + # 'deploymentManagementServiceEndpoint': fields.String( + # attribute='serviceUri'), + # 'supportedLocations': fields.String, + # 'capabilities': fields.String, + # 'capacity': fields.String, 'profileSupportList': fields.List( fields.String, description='Profile support list, use default for the return \ endpoint'), + 'extensions': fields.String } ) profile = api_ims_inventory_v1.model("DeploymentManagerGetDtoProfile", { 'cluster_api_endpoint': fields.String( - attributes='cluster_api_endpoint'), - 'cluster_ca_cert': fields.String(attributes='cluster_ca_cert'), - 'admin_user': fields.String(attributes='admin_user'), - 'admin_client_cert': fields.String(attributes='admin_client_cert'), - 'admin_client_key': fields.String(attributes='admin_client_key'), - # 'kube_config_file': fields.String(attributes='kube_config_file') + attribute='cluster_api_endpoint'), + 'cluster_ca_cert': fields.String(attribute='cluster_ca_cert'), + 'admin_user': fields.String(attribute='admin_user'), + 'admin_client_cert': fields.String(attribute='admin_client_cert'), + 'admin_client_key': fields.String(attribute='admin_client_key'), + # 'kube_config_file': fields.String(attribute='kube_config_file') 'helmcli_host_with_port': fields.String( - attributes='helmcli_host_with_port'), - 'helmcli_username': fields.String(attributes='helmcli_username'), - 'helmcli_password': fields.String(attributes='helmcli_password'), - 'helmcli_kubeconfig': fields.String(attributes='helmcli_kubeconfig'), + attribute='helmcli_host_with_port'), + 'helmcli_username': fields.String(attribute='helmcli_username'), + 'helmcli_password': fields.String(attribute='helmcli_password'), + 'helmcli_kubeconfig': fields.String(attribute='helmcli_kubeconfig'), }) deployment_manager_get = api_ims_inventory_v1.model( @@ -173,12 +176,15 @@ class DeploymentManagerDTO: description='Deployment manager ID'), 'name': fields.String, 'description': fields.String, - 'deploymentManagementServiceEndpoint': fields.String, - 'supportedLocations': fields.String, - 'capabilities': fields.String, - 'capacity': fields.String, + 'serviceUri': fields.String(attribute='serviceUri'), + # 'deploymentManagementServiceEndpoint': fields.String( + # attribute='serviceUri'), + # 'supportedLocations': fields.String, + # 'capabilities': fields.String, + # 'capacity': fields.String, 'profileName': fields.String, 'profileData': fields.Nested(profile, False, True), + 'extensions': fields.String } ) diff --git a/o2ims/views/ocloud_route.py b/o2ims/views/ocloud_route.py index 26da34c..70d3aec 100644 --- a/o2ims/views/ocloud_route.py +++ b/o2ims/views/ocloud_route.py @@ -18,7 +18,7 @@ from flask_restx import Resource, reqparse from o2common.service.messagebus import MessageBus from o2common.views.pagination_route import link_header, PAGE_PARAM from o2ims.views import ocloud_view -from o2ims.views.api_ns import api_ims_inventory_v1 +from o2ims.views.api_ns import api_ims_inventory as api_ims_inventory_v1 from o2ims.views.ocloud_dto import OcloudDTO, ResourceTypeDTO,\ ResourcePoolDTO, ResourceDTO, DeploymentManagerDTO, SubscriptionDTO @@ -32,8 +32,22 @@ def configure_api_route(): bus = MessageBus.get_instance() +# ---------- API versions ---------- # +@api_ims_inventory_v1.route("/v1/api_versions") +class VersionRouter(Resource): + def get(self): + return { + 'uriPrefix': request.base_url.rsplit('/', 1)[0], + 'apiVersions': [{ + 'version': '1', + # 'isDeprecated': 'False', + # 'retirementDate': '' + }] + } + + # ---------- OClouds ---------- # -@api_ims_inventory_v1.route("/") +@api_ims_inventory_v1.route("/v1/") @api_ims_inventory_v1.response(404, 'oCloud not found') @api_ims_inventory_v1.param( 'all_fields', @@ -72,7 +86,7 @@ class OcloudsListRouter(Resource): # ---------- ResourceTypes ---------- # -@api_ims_inventory_v1.route("/resourceTypes") +@api_ims_inventory_v1.route("/v1/resourceTypes") @api_ims_inventory_v1.param(PAGE_PARAM, 'Page number of the results to fetch.' + ' Default: 1', @@ -120,7 +134,7 @@ class ResourceTypesListRouter(Resource): return link_header(request.full_path, ret) -@api_ims_inventory_v1.route("/resourceTypes/") +@api_ims_inventory_v1.route("/v1/resourceTypes/") @api_ims_inventory_v1.param('resourceTypeID', 'ID of the resource type') @api_ims_inventory_v1.response(404, 'Resource type not found') @api_ims_inventory_v1.param( @@ -158,7 +172,7 @@ class ResourceTypeGetRouter(Resource): # ---------- ResourcePools ---------- # -@api_ims_inventory_v1.route("/resourcePools") +@api_ims_inventory_v1.route("/v1/resourcePools") @api_ims_inventory_v1.param(PAGE_PARAM, 'Page number of the results to fetch.' + ' Default: 1', @@ -206,7 +220,7 @@ class ResourcePoolsListRouter(Resource): return link_header(request.full_path, ret) -@api_ims_inventory_v1.route("/resourcePools/") +@api_ims_inventory_v1.route("/v1/resourcePools/") @api_ims_inventory_v1.param('resourcePoolID', 'ID of the resource pool') @api_ims_inventory_v1.response(404, 'Resource pool not found') @api_ims_inventory_v1.param( @@ -244,7 +258,7 @@ class ResourcePoolGetRouter(Resource): # ---------- Resources ---------- # -@api_ims_inventory_v1.route("/resourcePools//resources") +@api_ims_inventory_v1.route("/v1/resourcePools//resources") @api_ims_inventory_v1.param('resourcePoolID', 'ID of the resource pool') # @api_ims_inventory_v1.param('sort', 'sort by column name', # _in='query') @@ -302,7 +316,7 @@ class ResourcesListRouter(Resource): @api_ims_inventory_v1.route( - "/resourcePools//resources/") + "/v1/resourcePools//resources/") @api_ims_inventory_v1.param('resourcePoolID', 'ID of the resource pool') @api_ims_inventory_v1.param('resourceID', 'ID of the resource') @api_ims_inventory_v1.response(404, 'Resource not found') @@ -343,7 +357,7 @@ class ResourceGetRouter(Resource): # ---------- DeploymentManagers ---------- # -@api_ims_inventory_v1.route("/deploymentManagers") +@api_ims_inventory_v1.route("/v1/deploymentManagers") @api_ims_inventory_v1.param(PAGE_PARAM, 'Page number of the results to fetch.' + ' Default: 1', @@ -391,7 +405,7 @@ class DeploymentManagersListRouter(Resource): return link_header(request.full_path, ret) -@api_ims_inventory_v1.route("/deploymentManagers/") +@api_ims_inventory_v1.route("/v1/deploymentManagers/") @api_ims_inventory_v1.param('deploymentManagerID', 'ID of the deployment manager') @api_ims_inventory_v1.param('profile', 'DMS profile: value supports "sol018"', @@ -440,7 +454,7 @@ class DeploymentManagerGetRouter(Resource): # ---------- Subscriptions ---------- # -@api_ims_inventory_v1.route("/subscriptions") +@api_ims_inventory_v1.route("/v1/subscriptions") class SubscriptionsListRouter(Resource): model = SubscriptionDTO.subscription_get @@ -500,7 +514,7 @@ class SubscriptionsListRouter(Resource): return result, 201 -@api_ims_inventory_v1.route("/subscriptions/") +@api_ims_inventory_v1.route("/v1/subscriptions/") @api_ims_inventory_v1.param('subscriptionID', 'ID of the subscription') @api_ims_inventory_v1.response(404, 'Subscription not found') class SubscriptionGetDelRouter(Resource): diff --git a/o2ims/views/ocloud_view.py b/o2ims/views/ocloud_view.py index eb6c79f..a70ebf4 100644 --- a/o2ims/views/ocloud_view.py +++ b/o2ims/views/ocloud_view.py @@ -144,11 +144,11 @@ def deployment_manager_one(deploymentManagerId: str, if ocloud.DeploymentManagerProfileDefault == profile: pass elif ocloud.DeploymentManagerProfileSOL018 == profile: - result['deploymentManagementServiceEndpoint'] = \ + result['serviceUri'] = \ profile_data['cluster_api_endpoint'] result['profileData'] = profile_data elif ocloud.DeploymentManagerProfileSOL018HelmCLI == profile: - result['deploymentManagementServiceEndpoint'] = \ + result['serviceUri'] = \ profile_data['cluster_api_endpoint'] helmcli_profile = dict() diff --git a/tests/unit/test_alarm.py b/tests/unit/test_alarm.py index 2bdb31c..5309eb5 100644 --- a/tests/unit/test_alarm.py +++ b/tests/unit/test_alarm.py @@ -131,20 +131,6 @@ def test_view_alarm_subscription_one(mock_uow): "alarmSubscriptionId")) == subscription_id1 -def test_alarm_dictionary(mock_uow): - session, uow = mock_uow - alarm_dict1 = alarm_obj.AlarmDictionary('test1') - alarm_dict1.entityType = 'test1' - with uow: - uow.alarm_dictionaries.add(alarm_dict1) - - alarm_dict2 = uow.alarm_dictionaries.get('test1') - assert alarm_dict1 == alarm_dict2 - - dict_list = uow.alarm_dictionaries.list() - assert len(dict_list) > 0 - - def test_flask_get_list(mock_flask_uow): session, app = mock_flask_uow order_by = MagicMock() @@ -152,7 +138,7 @@ def test_flask_get_list(mock_flask_uow): order_by.limit.return_value.offset.return_value = [] session.return_value.query.return_value.filter.return_value.\ order_by.return_value = order_by - apibase = config.get_o2ims_monitoring_api_base() + apibase = config.get_o2ims_monitoring_api_base() + '/v1' with app.test_client() as client: # Get list and return empty list @@ -169,7 +155,7 @@ def test_flask_get_one(mock_flask_uow): session.return_value.query.return_value.filter_by.return_value.\ first.return_value = None - apibase = config.get_o2ims_monitoring_api_base() + apibase = config.get_o2ims_monitoring_api_base() + '/v1' with app.test_client() as client: # Get one and return 404 @@ -185,7 +171,7 @@ def test_flask_get_one(mock_flask_uow): def test_flask_post(mock_flask_uow): session, app = mock_flask_uow - apibase = config.get_o2ims_monitoring_api_base() + apibase = config.get_o2ims_monitoring_api_base() + '/v1' with app.test_client() as client: session.return_value.execute.return_value = [] @@ -202,7 +188,7 @@ def test_flask_post(mock_flask_uow): def test_flask_delete(mock_flask_uow): session, app = mock_flask_uow - apibase = config.get_o2ims_monitoring_api_base() + apibase = config.get_o2ims_monitoring_api_base() + '/v1' with app.test_client() as client: session.return_value.execute.return_value.first.return_value = {} @@ -214,7 +200,7 @@ def test_flask_delete(mock_flask_uow): def test_flask_not_allowed(mock_flask_uow): _, app = mock_flask_uow - apibase = config.get_o2ims_monitoring_api_base() + apibase = config.get_o2ims_monitoring_api_base() + '/v1' with app.test_client() as client: # Testing resource type not support method diff --git a/tests/unit/test_ocloud.py b/tests/unit/test_ocloud.py index 57ba0fe..a3c0f67 100644 --- a/tests/unit/test_ocloud.py +++ b/tests/unit/test_ocloud.py @@ -294,7 +294,7 @@ def test_view_deployment_manager_one(mock_uow): session.return_value.query.return_value.filter_by.return_value.first.\ return_value.serialize.return_value = { "deploymentManagerId": deployment_manager_id1, - "deploymentManagementServiceEndpoint": dms_endpoint, + "serviceUri": dms_endpoint, "profile": {} } @@ -304,7 +304,7 @@ def test_view_deployment_manager_one(mock_uow): assert str(deployment_manager_res.get( "deploymentManagerId")) == deployment_manager_id1 assert str(deployment_manager_res.get( - 'deploymentManagementServiceEndpoint')) == dms_endpoint + 'serviceUri')) == dms_endpoint assert deployment_manager_res.get('profile') is None # profile sol018 @@ -317,7 +317,7 @@ def test_view_deployment_manager_one(mock_uow): deployment_manager_res = ocloud_view.deployment_manager_one( deployment_manager_id1, uow, profile=profileName) assert str(deployment_manager_res.get( - 'deploymentManagementServiceEndpoint')) == cluster_endpoint + 'serviceUri')) == cluster_endpoint assert str(deployment_manager_res.get( "profileName")) == profileName @@ -383,7 +383,7 @@ def test_flask_get_list(mock_flask_uow): order_by.limit.return_value.offset.return_value = [] session.return_value.query.return_value.filter.return_value.\ order_by.return_value = order_by - apibase = config.get_o2ims_api_base() + apibase = config.get_o2ims_api_base() + '/v1' # TODO: workaround for sqlalchemy not mapping with resource object setattr(ocloud.Resource, 'resourcePoolId', '') @@ -413,7 +413,7 @@ def test_flask_get_one(mock_flask_uow): session.return_value.query.return_value.filter_by.return_value.\ first.return_value = None - apibase = config.get_o2ims_api_base() + apibase = config.get_o2ims_api_base() + '/v1' with app.test_client() as client: # Get one and return 404 @@ -446,7 +446,7 @@ def test_flask_get_one(mock_flask_uow): def test_flask_post(mock_flask_uow): session, app = mock_flask_uow - apibase = config.get_o2ims_api_base() + apibase = config.get_o2ims_api_base() + '/v1' with app.test_client() as client: session.return_value.execute.return_value = [] @@ -463,7 +463,7 @@ def test_flask_post(mock_flask_uow): def test_flask_delete(mock_flask_uow): session, app = mock_flask_uow - apibase = config.get_o2ims_api_base() + apibase = config.get_o2ims_api_base() + '/v1' with app.test_client() as client: session.return_value.execute.return_value.first.return_value = {} @@ -475,7 +475,7 @@ def test_flask_delete(mock_flask_uow): def test_flask_not_allowed(mock_flask_uow): _, app = mock_flask_uow - apibase = config.get_o2ims_api_base() + apibase = config.get_o2ims_api_base() + '/v1' with app.test_client() as client: # Testing resource type not support method diff --git a/tox.ini b/tox.ini index 14651d8..9eef538 100644 --- a/tox.ini +++ b/tox.ini @@ -38,6 +38,7 @@ commands = [testenv:code] setenv = O2APP_CONFIG=configs/o2app.conf + ALARM_YAML=configs/alarm.yaml commands = pytest tests/unit -- 2.16.6