Add support cnf auto scale via threshold interface
Add the Performance Management Threshold CLI to support AutoScale. The Performance Management Threshold API is based on ETSI NFV-SOL 002 v3.3.1 and ETSI NFV-SOL 003 v3.3.1, which is Version "2.0.0" API of Tacker. Implements: blueprint support-auto-lcm Change-Id: Idd313d6abe47dfa41fc86ddc614d00f99f3fc3b2
This commit is contained in:
parent
82bf387f77
commit
8b45c8082b
@ -110,3 +110,8 @@ of individual command can be referred by **openstack help <command-name>**.
|
||||
openstack vnfpm job update Update PM job.
|
||||
openstack vnfpm job delete Delete PM job.
|
||||
openstack vnfpm report show Show PM report.
|
||||
openstack vnfpm threshold create Create PM threshold.
|
||||
openstack vnfpm threshold list List PM threshold.
|
||||
openstack vnfpm threshold show Show PM threshold.
|
||||
openstack vnfpm threshold update Update PM threshold.
|
||||
openstack vnfpm threshold delete Delete PM threshold.
|
||||
|
@ -137,6 +137,11 @@ openstack.tackerclient.v2 =
|
||||
vnfpm_job_update = tackerclient.osc.v2.vnfpm.vnfpm_job:UpdateVnfPmJob
|
||||
vnfpm_job_delete = tackerclient.osc.v2.vnfpm.vnfpm_job:DeleteVnfPmJob
|
||||
vnfpm_report_show = tackerclient.osc.v2.vnfpm.vnfpm_report:ShowVnfPmReport
|
||||
vnfpm_threshold_create = tackerclient.osc.v2.vnfpm.vnfpm_threshold:CreateVnfPmThreshold
|
||||
vnfpm_threshold_list = tackerclient.osc.v2.vnfpm.vnfpm_threshold:ListVnfPmThreshold
|
||||
vnfpm_threshold_show = tackerclient.osc.v2.vnfpm.vnfpm_threshold:ShowVnfPmThreshold
|
||||
vnfpm_threshold_update = tackerclient.osc.v2.vnfpm.vnfpm_threshold:UpdateVnfPmThreshold
|
||||
vnfpm_threshold_delete = tackerclient.osc.v2.vnfpm.vnfpm_threshold:DeleteVnfPmThreshold
|
||||
vnffm_alarm_list = tackerclient.osc.v2.vnffm.vnffm_alarm:ListVnfFmAlarm
|
||||
vnffm_alarm_show = tackerclient.osc.v2.vnffm.vnffm_alarm:ShowVnfFmAlarm
|
||||
vnffm_alarm_update = tackerclient.osc.v2.vnffm.vnffm_alarm:UpdateVnfFmAlarm
|
||||
|
@ -20,7 +20,9 @@ Stuffs specific to tackerclient OSC plugin should not be added
|
||||
to this module. They should go to tackerclient.osc.v1.utils.
|
||||
"""
|
||||
|
||||
import json
|
||||
import operator
|
||||
import os
|
||||
|
||||
from cliff import columns as cliff_columns
|
||||
from keystoneclient import exceptions as identity_exc
|
||||
@ -29,6 +31,7 @@ from keystoneclient.v3 import projects
|
||||
from osc_lib import utils
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.i18n import _
|
||||
|
||||
|
||||
@ -212,3 +215,29 @@ class FormatComplexDataColumn(cliff_columns.FormattableColumn):
|
||||
|
||||
def human_readable(self):
|
||||
return format_dict_with_indention(self._value)
|
||||
|
||||
|
||||
def jsonfile2body(file_path):
|
||||
|
||||
if file_path is None:
|
||||
msg = _("File %s does not exist")
|
||||
reason = msg % file_path
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
if os.access(file_path, os.R_OK) is False:
|
||||
msg = _("User does not have read privileges to it")
|
||||
raise exceptions.InvalidInput(reason=msg)
|
||||
|
||||
try:
|
||||
with open(file_path) as f:
|
||||
body = json.load(f)
|
||||
except (IOError, ValueError) as ex:
|
||||
msg = _("Failed to load parameter file. Error: %s")
|
||||
reason = msg % ex
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
if not body:
|
||||
reason = _('The parameter file is empty')
|
||||
raise exceptions.EmptyInput(reason=reason)
|
||||
|
||||
return body
|
||||
|
@ -13,9 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
|
||||
from osc_lib.command import command
|
||||
@ -113,7 +111,7 @@ class CreateVnfLcm(command.ShowOne):
|
||||
body = {}
|
||||
|
||||
if file_path:
|
||||
return jsonfile2body(file_path)
|
||||
return tacker_osc_utils.jsonfile2body(file_path)
|
||||
|
||||
body['vnfdId'] = parsed_args.vnfd_id
|
||||
|
||||
@ -184,29 +182,6 @@ class ListVnfLcm(command.Lister):
|
||||
) for s in vnf_instances))
|
||||
|
||||
|
||||
def jsonfile2body(file_path):
|
||||
|
||||
if file_path is not None and os.access(file_path, os.R_OK) is False:
|
||||
msg = _("File %s does not exist or user does not have read "
|
||||
"privileges to it")
|
||||
reason = msg % file_path
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
try:
|
||||
with open(file_path) as f:
|
||||
body = json.load(f)
|
||||
except (IOError, ValueError) as ex:
|
||||
msg = _("Failed to load parameter file. Error: %s")
|
||||
reason = msg % ex
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
if not body:
|
||||
reason = _('The parameter file is empty')
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
return body
|
||||
|
||||
|
||||
class InstantiateVnfLcm(command.Command):
|
||||
_description = _("Instantiate a VNF Instance")
|
||||
|
||||
@ -226,7 +201,7 @@ class InstantiateVnfLcm(command.Command):
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
result = client.instantiate_vnf_instance(
|
||||
parsed_args.vnf_instance, jsonfile2body(
|
||||
parsed_args.vnf_instance, tacker_osc_utils.jsonfile2body(
|
||||
parsed_args.instantiation_request_file))
|
||||
if not result:
|
||||
print((_('Instantiate request for VNF Instance %(id)s has been'
|
||||
@ -271,7 +246,8 @@ class HealVnfLcm(command.Command):
|
||||
if parsed_args.vnfc_instance:
|
||||
body['vnfcInstanceId'] = parsed_args.vnfc_instance
|
||||
if parsed_args.additional_param_file:
|
||||
body.update(jsonfile2body(parsed_args.additional_param_file))
|
||||
body.update(tacker_osc_utils.jsonfile2body(
|
||||
parsed_args.additional_param_file))
|
||||
|
||||
return body
|
||||
|
||||
@ -461,7 +437,7 @@ class UpdateVnfLcm(command.Command):
|
||||
body = {}
|
||||
|
||||
if file_path:
|
||||
return jsonfile2body(file_path)
|
||||
return tacker_osc_utils.jsonfile2body(file_path)
|
||||
|
||||
return body
|
||||
|
||||
@ -535,7 +511,8 @@ class ScaleVnfLcm(command.Command):
|
||||
body['numberOfSteps'] = parsed_args.number_of_steps
|
||||
|
||||
if parsed_args.additional_param_file:
|
||||
body.update(jsonfile2body(parsed_args.additional_param_file))
|
||||
body.update(tacker_osc_utils.jsonfile2body(
|
||||
parsed_args.additional_param_file))
|
||||
|
||||
return body
|
||||
|
||||
@ -574,7 +551,7 @@ class ChangeExtConnVnfLcm(command.Command):
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
result = client.change_ext_conn_vnf_instance(
|
||||
parsed_args.vnf_instance, jsonfile2body(
|
||||
parsed_args.vnf_instance, tacker_osc_utils.jsonfile2body(
|
||||
parsed_args.request_file))
|
||||
if not result:
|
||||
print((_('Change External VNF Connectivity for VNF Instance %s '
|
||||
@ -601,7 +578,7 @@ class ChangeVnfPkgVnfLcm(command.Command):
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
result = client.change_vnfpkg_vnf_instance(
|
||||
parsed_args.vnf_instance, jsonfile2body(
|
||||
parsed_args.vnf_instance, tacker_osc_utils.jsonfile2body(
|
||||
parsed_args.request_file))
|
||||
if not result:
|
||||
print((_('Change Current VNF Package for VNF Instance %s '
|
||||
|
@ -13,9 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
@ -49,29 +47,6 @@ def _get_columns(lccn_subsc_obj):
|
||||
column_map)
|
||||
|
||||
|
||||
def jsonfile2body(file_path):
|
||||
|
||||
if file_path is not None and os.access(file_path, os.R_OK) is False:
|
||||
msg = _("File %s does not exist or user does not have read "
|
||||
"privileges to it")
|
||||
reason = msg % file_path
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
try:
|
||||
with open(file_path) as f:
|
||||
body = json.load(f)
|
||||
except (IOError, ValueError) as ex:
|
||||
msg = _("Failed to load parameter file. Error: %s")
|
||||
reason = msg % ex
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
if not body:
|
||||
reason = _('The parameter file is empty')
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
return body
|
||||
|
||||
|
||||
class CreateLccnSubscription(command.ShowOne):
|
||||
_description = _("Create a new Lccn Subscription")
|
||||
|
||||
@ -86,7 +61,7 @@ class CreateLccnSubscription(command.ShowOne):
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
subsc = client.create_lccn_subscription(
|
||||
jsonfile2body(parsed_args.create_request_file))
|
||||
tacker_osc_utils.jsonfile2body(parsed_args.create_request_file))
|
||||
display_columns, columns = _get_columns(subsc)
|
||||
data = utils.get_item_properties(sdk_utils.DictModel(subsc),
|
||||
columns, formatters=_FORMATTERS,
|
||||
|
@ -13,9 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
@ -56,32 +54,6 @@ def _get_columns(vnffm_sub_obj):
|
||||
vnffm_sub_obj, column_map)
|
||||
|
||||
|
||||
def jsonfile2body(file_path):
|
||||
|
||||
if file_path is None:
|
||||
msg = _("File %s does not exist")
|
||||
reason = msg % file_path
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
if os.access(file_path, os.R_OK) is False:
|
||||
msg = _("User does not have read privileges to it")
|
||||
raise exceptions.InvalidInput(reason=msg)
|
||||
|
||||
try:
|
||||
with open(file_path) as f:
|
||||
body = json.load(f)
|
||||
except (IOError, ValueError) as ex:
|
||||
msg = _("Failed to load parameter file. Error: %s")
|
||||
reason = msg % ex
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
if not body:
|
||||
reason = _('The parameter file is empty')
|
||||
raise exceptions.EmptyInput(reason=reason)
|
||||
|
||||
return body
|
||||
|
||||
|
||||
class CreateVnfFmSub(command.ShowOne):
|
||||
_description = _("Create a new VNF FM subscription")
|
||||
|
||||
@ -97,7 +69,7 @@ class CreateVnfFmSub(command.ShowOne):
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
vnf_fm_sub = client.create_vnf_fm_sub(
|
||||
jsonfile2body(parsed_args.request_file))
|
||||
tacker_osc_utils.jsonfile2body(parsed_args.request_file))
|
||||
display_columns, columns = _get_columns(vnf_fm_sub)
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vnf_fm_sub), columns,
|
||||
|
@ -0,0 +1,40 @@
|
||||
{
|
||||
"objectType": "Vnfc",
|
||||
"objectInstanceId": "object-instance-id-1",
|
||||
"subObjectInstanceIds": [
|
||||
"sub-object-instance-id-2"
|
||||
],
|
||||
"criteria": {
|
||||
"performanceMetric": "VCpuUsageMeanVnf.object-instance-id-1",
|
||||
"thresholdType": "SIMPLE",
|
||||
"simpleThresholdDetails": {
|
||||
"thresholdValue": 400.5,
|
||||
"hysteresis": 10.3
|
||||
}
|
||||
},
|
||||
"callbackUri": "/nfvo/notify/threshold",
|
||||
"authentication": {
|
||||
"authType": [
|
||||
"BASIC",
|
||||
"OAUTH2_CLIENT_CREDENTIALS",
|
||||
"OAUTH2_CLIENT_CERT"
|
||||
],
|
||||
"paramsBasic": {
|
||||
"userName": "nfvo",
|
||||
"password": "nfvopwd"
|
||||
},
|
||||
"paramsOauth2ClientCredentials": {
|
||||
"clientId": "auth_user_name",
|
||||
"clientPassword": "auth_password",
|
||||
"tokenEndpoint": "token_endpoint"
|
||||
},
|
||||
"paramsOauth2ClientCert": {
|
||||
"clientId": "test",
|
||||
"certificateRef": {
|
||||
"type": "x5t#256",
|
||||
"value": "03c6e188d1fe5d3da8c9bc9a8dc531a2b3e"
|
||||
},
|
||||
"tokenEndpoint": "http://127.0.0.1/token"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"callbackUri": "/nfvo/notify/threshold",
|
||||
"authentication": {
|
||||
"authType": [
|
||||
"BASIC",
|
||||
"OAUTH2_CLIENT_CREDENTIALS",
|
||||
"OAUTH2_CLIENT_CERT"
|
||||
],
|
||||
"paramsBasic": {
|
||||
"userName": "nfvo",
|
||||
"password": "nfvopwd"
|
||||
},
|
||||
"paramsOauth2ClientCredentials": {
|
||||
"clientId": "auth_user_name",
|
||||
"clientPassword": "auth_password",
|
||||
"tokenEndpoint": "token_endpoint"
|
||||
},
|
||||
"paramsOauth2ClientCert": {
|
||||
"clientId": "test",
|
||||
"certificateRef": {
|
||||
"type": "x5t#256",
|
||||
"value": "03c6e188d1fe5d3da8c9bc9a8dc531a2b3e"
|
||||
},
|
||||
"tokenEndpoint": "http://127.0.0.1/token"
|
||||
}
|
||||
}
|
||||
}
|
@ -13,9 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
from functools import reduce
|
||||
from osc_lib.command import command
|
||||
@ -78,32 +76,6 @@ def _get_columns(vnfpm_job_obj, action=None):
|
||||
vnfpm_job_obj, column_map)
|
||||
|
||||
|
||||
def jsonfile2body(file_path):
|
||||
|
||||
if file_path is None:
|
||||
msg = _("File %s does not exist")
|
||||
reason = msg % file_path
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
if os.access(file_path, os.R_OK) is False:
|
||||
msg = _("User does not have read privileges to it")
|
||||
raise exceptions.InvalidInput(reason=msg)
|
||||
|
||||
try:
|
||||
with open(file_path) as f:
|
||||
body = json.load(f)
|
||||
except (IOError, ValueError) as ex:
|
||||
msg = _("Failed to load parameter file. Error: %s")
|
||||
reason = msg % ex
|
||||
raise exceptions.InvalidInput(reason=reason)
|
||||
|
||||
if not body:
|
||||
reason = _('The parameter file is empty')
|
||||
raise exceptions.EmptyInput(reason=reason)
|
||||
|
||||
return body
|
||||
|
||||
|
||||
class CreateVnfPmJob(command.ShowOne):
|
||||
_description = _("Create a new VNF PM job")
|
||||
|
||||
@ -119,7 +91,7 @@ class CreateVnfPmJob(command.ShowOne):
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
vnf_pm_job = client.create_vnf_pm_job(
|
||||
jsonfile2body(parsed_args.request_file))
|
||||
tacker_osc_utils.jsonfile2body(parsed_args.request_file))
|
||||
display_columns, columns = _get_columns(vnf_pm_job)
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vnf_pm_job), columns,
|
||||
@ -284,7 +256,7 @@ class UpdateVnfPmJob(command.ShowOne):
|
||||
client = self.app.client_manager.tackerclient
|
||||
updated_values = client.update_vnf_pm_job(
|
||||
parsed_args.vnf_pm_job_id,
|
||||
jsonfile2body(parsed_args.request_file))
|
||||
tacker_osc_utils.jsonfile2body(parsed_args.request_file))
|
||||
display_columns, columns = _get_columns(updated_values, 'update')
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(updated_values),
|
||||
|
216
tackerclient/osc/v2/vnfpm/vnfpm_threshold.py
Normal file
216
tackerclient/osc/v2/vnfpm/vnfpm_threshold.py
Normal file
@ -0,0 +1,216 @@
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import logging
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.i18n import _
|
||||
from tackerclient.osc import sdk_utils
|
||||
from tackerclient.osc import utils as tacker_osc_utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
_ATTR_MAP = (
|
||||
('id', 'ID', tacker_osc_utils.LIST_BOTH),
|
||||
('objectType', 'Object Type', tacker_osc_utils.LIST_BOTH),
|
||||
('_links', 'Links', tacker_osc_utils.LIST_BOTH)
|
||||
)
|
||||
|
||||
_FORMATTERS = {
|
||||
'subObjectInstanceIds': tacker_osc_utils.FormatComplexDataColumn,
|
||||
'criteria': tacker_osc_utils.FormatComplexDataColumn,
|
||||
'_links': tacker_osc_utils.FormatComplexDataColumn
|
||||
}
|
||||
|
||||
_MIXED_CASE_FIELDS = (
|
||||
'objectType', 'objectInstanceId', 'subObjectInstanceIds', 'callbackUri'
|
||||
)
|
||||
|
||||
_MIXED_CASE_FIELDS_UPDATE = (
|
||||
'callbackUri'
|
||||
)
|
||||
|
||||
_VNF_PM_THRESHOLD_ID = 'vnf_pm_threshold_id'
|
||||
|
||||
|
||||
def _get_columns(vnf_pm_threshold, action=None):
|
||||
if action == 'update':
|
||||
column_map = {
|
||||
'callbackUri': 'Callback Uri'
|
||||
}
|
||||
else:
|
||||
column_map = {
|
||||
'id': 'ID',
|
||||
'objectType': 'Object Type',
|
||||
'objectInstanceId': 'Object Instance Id',
|
||||
'subObjectInstanceIds': 'Sub Object Instance Ids',
|
||||
'criteria': 'Criteria',
|
||||
'callbackUri': 'Callback Uri',
|
||||
'_links': 'Links'
|
||||
}
|
||||
return sdk_utils.get_osc_show_columns_for_sdk_resource(
|
||||
vnf_pm_threshold, column_map)
|
||||
|
||||
|
||||
class CreateVnfPmThreshold(command.ShowOne):
|
||||
_description = _("Create a new VNF PM threshold")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
LOG.debug('get_parser(%s)', prog_name)
|
||||
parser = super(CreateVnfPmThreshold, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'request_file',
|
||||
metavar="<param-file>",
|
||||
help=_('Specify create VNF PM threshold request '
|
||||
'parameters in a json file.'))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
vnf_pm_threshold = client.create_vnf_pm_threshold(
|
||||
tacker_osc_utils.jsonfile2body(parsed_args.request_file))
|
||||
display_columns, columns = _get_columns(vnf_pm_threshold)
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(vnf_pm_threshold), columns,
|
||||
formatters=_FORMATTERS, mixed_case_fields=_MIXED_CASE_FIELDS)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class ListVnfPmThreshold(command.Lister):
|
||||
_description = _("List VNF PM thresholds")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
LOG.debug('get_parser(%s)', prog_name)
|
||||
parser = super(ListVnfPmThreshold, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
"--filter",
|
||||
metavar="<filter>",
|
||||
help=_("Attribute-based-filtering parameters"),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
_params = {}
|
||||
|
||||
if parsed_args.filter:
|
||||
_params['filter'] = parsed_args.filter
|
||||
|
||||
client = self.app.client_manager.tackerclient
|
||||
data = client.list_vnf_pm_thresholds(**_params)
|
||||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
_ATTR_MAP, long_listing=True)
|
||||
return (headers,
|
||||
(utils.get_dict_properties(
|
||||
s, columns, formatters=_FORMATTERS,
|
||||
mixed_case_fields=_MIXED_CASE_FIELDS,
|
||||
) for s in data['vnf_pm_thresholds']))
|
||||
|
||||
|
||||
class ShowVnfPmThreshold(command.ShowOne):
|
||||
_description = _("Display VNF PM threshold details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
LOG.debug('get_parser(%s)', prog_name)
|
||||
parser = super(ShowVnfPmThreshold, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNF_PM_THRESHOLD_ID,
|
||||
metavar="<vnf-pm-threshold-id>",
|
||||
help=_("VNF PM threshold ID to display"))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
obj = client.show_vnf_pm_threshold(parsed_args.vnf_pm_threshold_id)
|
||||
display_columns, columns = _get_columns(obj)
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(obj), columns,
|
||||
mixed_case_fields=_MIXED_CASE_FIELDS,
|
||||
formatters=_FORMATTERS)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class UpdateVnfPmThreshold(command.ShowOne):
|
||||
_description = _("Update information about an individual VNF PM threshold")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
LOG.debug('get_parser(%s)', prog_name)
|
||||
parser = super(UpdateVnfPmThreshold, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNF_PM_THRESHOLD_ID,
|
||||
metavar="<vnf-pm-threshold-id>",
|
||||
help=_("VNF PM threshold ID to update.")
|
||||
)
|
||||
parser.add_argument(
|
||||
'request_file',
|
||||
metavar="<param-file>",
|
||||
help=_('Specify update PM threshold request '
|
||||
'parameters in a json file.'))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
updated_values = client.update_vnf_pm_threshold(
|
||||
parsed_args.vnf_pm_threshold_id,
|
||||
tacker_osc_utils.jsonfile2body(parsed_args.request_file))
|
||||
display_columns, columns = _get_columns(updated_values, 'update')
|
||||
data = utils.get_item_properties(
|
||||
sdk_utils.DictModel(updated_values), columns,
|
||||
mixed_case_fields=_MIXED_CASE_FIELDS_UPDATE)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class DeleteVnfPmThreshold(command.Command):
|
||||
_description = _("Delete VNF PM threshold")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
LOG.debug('get_parser(%s)', prog_name)
|
||||
parser = super(DeleteVnfPmThreshold, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
_VNF_PM_THRESHOLD_ID,
|
||||
metavar="<vnf-pm-threshold-id>",
|
||||
nargs="+",
|
||||
help=_("VNF PM threshold ID(s) to delete"))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
error_count = 0
|
||||
client = self.app.client_manager.tackerclient
|
||||
vnf_pm_threshold_ids = parsed_args.vnf_pm_threshold_id
|
||||
|
||||
for threshold_id in vnf_pm_threshold_ids:
|
||||
try:
|
||||
client.delete_vnf_pm_threshold(threshold_id)
|
||||
except Exception as e:
|
||||
error_count += 1
|
||||
LOG.error(_("Failed to delete VNF PM threshold with "
|
||||
"ID '%(threshold_id)s': %(e)s"),
|
||||
{'threshold_id': threshold_id, 'e': e})
|
||||
|
||||
total = len(vnf_pm_threshold_ids)
|
||||
if error_count > 0:
|
||||
msg = (_("Failed to delete %(error_count)s of %(total)s "
|
||||
"VNF PM thresholds.") %
|
||||
{'error_count': error_count, 'total': total})
|
||||
raise exceptions.CommandError(message=msg)
|
||||
|
||||
if total > 1:
|
||||
print(_('All specified VNF PM thresholds are deleted '
|
||||
'successfully'))
|
||||
return
|
||||
print(_("VNF PM threshold '%s' deleted "
|
||||
"successfully") % vnf_pm_threshold_ids[0])
|
@ -297,9 +297,9 @@ class TestInstantiateVnfLcm(TestVnfLcm):
|
||||
self.instantiate_vnf_lcm.take_action,
|
||||
parsed_args)
|
||||
|
||||
expected_msg = ("Invalid input: File %s does not exist "
|
||||
"or user does not have read privileges to it")
|
||||
self.assertEqual(expected_msg % sample_param_file, str(ex))
|
||||
expected_msg = ("Invalid input: "
|
||||
"User does not have read privileges to it")
|
||||
self.assertEqual(expected_msg, str(ex))
|
||||
|
||||
@mock.patch("os.open")
|
||||
@mock.patch("os.access")
|
||||
@ -403,9 +403,9 @@ class TestHealVnfLcm(TestVnfLcm):
|
||||
ex = self.assertRaises(exceptions.InvalidInput,
|
||||
self.heal_vnf_lcm.take_action, parsed_args)
|
||||
|
||||
expected_msg = ("Invalid input: File %s does not exist "
|
||||
"or user does not have read privileges to it")
|
||||
self.assertEqual(expected_msg % sample_param_file, str(ex))
|
||||
expected_msg = ("Invalid input: "
|
||||
"User does not have read privileges to it")
|
||||
self.assertEqual(expected_msg, str(ex))
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@ -774,9 +774,9 @@ class TestScaleVnfLcm(TestVnfLcm):
|
||||
ex = self.assertRaises(exceptions.InvalidInput,
|
||||
self.scale_vnf_lcm.take_action, parsed_args)
|
||||
|
||||
expected_msg = ("Invalid input: File %s does not exist "
|
||||
"or user does not have read privileges to it")
|
||||
self.assertEqual(expected_msg % sample_param_file, str(ex))
|
||||
expected_msg = ("Invalid input: "
|
||||
"User does not have read privileges to it")
|
||||
self.assertEqual(expected_msg, str(ex))
|
||||
|
||||
@ddt.data('SCALE_IN', 'SCALE_OUT')
|
||||
def test_take_action_vnf_instance_not_found(self, scale_type):
|
||||
@ -888,9 +888,9 @@ class TestChangeExtConnVnfLcm(TestVnfLcm):
|
||||
self.change_ext_conn_vnf_lcm.take_action,
|
||||
parsed_args)
|
||||
|
||||
expected_msg = ("Invalid input: File %s does not exist "
|
||||
"or user does not have read privileges to it")
|
||||
self.assertEqual(expected_msg % sample_param_file, str(ex))
|
||||
expected_msg = ("Invalid input: "
|
||||
"User does not have read privileges to it")
|
||||
self.assertEqual(expected_msg, str(ex))
|
||||
|
||||
@mock.patch("os.open")
|
||||
@mock.patch("os.access")
|
||||
|
@ -121,9 +121,9 @@ class TestChangeVnfPkgVnfLcm(test_vnflcm.TestVnfLcm):
|
||||
self.change_vnfpkg_vnf_lcm.take_action,
|
||||
parsed_args)
|
||||
|
||||
expected_msg = ("Invalid input: File %s does not exist "
|
||||
"or user does not have read privileges to it")
|
||||
self.assertEqual(expected_msg % sample_param_file, str(ex))
|
||||
expected_msg = ("Invalid input: "
|
||||
"User does not have read privileges to it")
|
||||
self.assertEqual(expected_msg, str(ex))
|
||||
|
||||
@mock.patch("os.open")
|
||||
@mock.patch("os.access")
|
||||
|
398
tackerclient/tests/unit/osc/v2/test_vnfpm_threshold.py
Normal file
398
tackerclient/tests/unit/osc/v2/test_vnfpm_threshold.py
Normal file
@ -0,0 +1,398 @@
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import ddt
|
||||
import os
|
||||
import sys
|
||||
|
||||
from io import StringIO
|
||||
from oslo_utils.fixture import uuidsentinel
|
||||
from unittest import mock
|
||||
|
||||
from tackerclient.common import exceptions
|
||||
from tackerclient.osc import utils as tacker_osc_utils
|
||||
from tackerclient.osc.v2.vnfpm import vnfpm_threshold
|
||||
from tackerclient.tests.unit.osc import base
|
||||
from tackerclient.tests.unit.osc.v1.fixture_data import client
|
||||
from tackerclient.tests.unit.osc.v2 import vnfpm_threshold_fakes
|
||||
|
||||
|
||||
class TestVnfPmThreshold(base.FixturedTestCase):
|
||||
client_fixture_class = client.ClientFixture
|
||||
|
||||
def setUp(self):
|
||||
super(TestVnfPmThreshold, self).setUp()
|
||||
self.url = client.TACKER_URL
|
||||
self.header = {'content-type': 'application/json'}
|
||||
self.app = mock.Mock()
|
||||
self.app_args = mock.Mock()
|
||||
self.client_manager = self.cs
|
||||
self.app.client_manager.tackerclient = self.client_manager
|
||||
|
||||
|
||||
def _get_columns_vnfpm_threshold(action=None):
|
||||
if action == 'update':
|
||||
columns = ['Callback Uri']
|
||||
else:
|
||||
columns = ['ID', 'Object Type', 'Object Instance Id',
|
||||
'Sub Object Instance Ids', 'Criteria', 'Callback Uri',
|
||||
'Links']
|
||||
if action == 'list':
|
||||
columns = [
|
||||
'ID', 'Object Type', 'Links'
|
||||
]
|
||||
return columns
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestCreateVnfPmThreshold(TestVnfPmThreshold):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCreateVnfPmThreshold, self).setUp()
|
||||
self.create_vnf_pm_threshold = vnfpm_threshold.CreateVnfPmThreshold(
|
||||
self.app, self.app_args, cmd_name='vnfpm threshold create')
|
||||
|
||||
def test_create_no_args(self):
|
||||
self.assertRaises(base.ParserException, self.check_parser,
|
||||
self.create_vnf_pm_threshold, [], [])
|
||||
|
||||
@ddt.unpack
|
||||
def test_take_action(self):
|
||||
param_file = ("./tackerclient/osc/v2/vnfpm/samples/"
|
||||
"create_vnf_pm_threshold_param_sample.json")
|
||||
|
||||
arg_list = [param_file]
|
||||
verify_list = [('request_file', param_file)]
|
||||
|
||||
parsed_args = self.check_parser(self.create_vnf_pm_threshold, arg_list,
|
||||
verify_list)
|
||||
|
||||
response_json = vnfpm_threshold_fakes.vnf_pm_threshold_response()
|
||||
self.requests_mock.register_uri(
|
||||
'POST', os.path.join(self.url, 'vnfpm/v2/thresholds'),
|
||||
json=response_json, headers=self.header)
|
||||
|
||||
actual_columns, data = (
|
||||
self.create_vnf_pm_threshold.take_action(parsed_args))
|
||||
self.assertCountEqual(_get_columns_vnfpm_threshold(),
|
||||
actual_columns)
|
||||
|
||||
_, attributes = vnfpm_threshold._get_columns(response_json)
|
||||
expected_data = vnfpm_threshold_fakes.get_vnfpm_threshold_data(
|
||||
response_json, columns=attributes)
|
||||
self.assertListItemsEqual(expected_data, data)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestListVnfPmThreshold(TestVnfPmThreshold):
|
||||
|
||||
def setUp(self):
|
||||
super(TestListVnfPmThreshold, self).setUp()
|
||||
self.list_vnf_pm_thresholds = vnfpm_threshold.ListVnfPmThreshold(
|
||||
self.app, self.app_args, cmd_name='vnfpm threshold list')
|
||||
|
||||
def test_take_action(self):
|
||||
vnf_pm_threshold_objs = vnfpm_threshold_fakes.create_vnf_pm_thresholds(
|
||||
count=3)
|
||||
parsed_args = self.check_parser(self.list_vnf_pm_thresholds, [], [])
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
os.path.join(self.url, 'vnfpm/v2/thresholds'),
|
||||
json=vnf_pm_threshold_objs, headers=self.header)
|
||||
|
||||
actual_columns, data = self.list_vnf_pm_thresholds.take_action(
|
||||
parsed_args)
|
||||
|
||||
_, columns = tacker_osc_utils.get_column_definitions(
|
||||
vnfpm_threshold._ATTR_MAP, long_listing=True)
|
||||
|
||||
expected_data = []
|
||||
for vnf_pm_threshold_obj_idx in vnf_pm_threshold_objs:
|
||||
expected_data.append(
|
||||
vnfpm_threshold_fakes.get_vnfpm_threshold_data(
|
||||
vnf_pm_threshold_obj_idx, columns=columns))
|
||||
|
||||
self.assertCountEqual(_get_columns_vnfpm_threshold(action='list'),
|
||||
actual_columns)
|
||||
self.assertCountEqual(expected_data, list(data))
|
||||
|
||||
def test_take_action_with_filter(self):
|
||||
vnf_pm_threshold_objs = vnfpm_threshold_fakes.create_vnf_pm_thresholds(
|
||||
count=3)
|
||||
parsed_args = self.check_parser(
|
||||
self.list_vnf_pm_thresholds,
|
||||
["--filter", '(eq,perceivedSeverity,WARNING)'],
|
||||
[('filter', '(eq,perceivedSeverity,WARNING)')])
|
||||
self.requests_mock.register_uri(
|
||||
'GET', os.path.join(
|
||||
self.url,
|
||||
'vnfpm/v2/thresholds?filter=(eq,perceivedSeverity,WARNING)'),
|
||||
json=vnf_pm_threshold_objs, headers=self.header)
|
||||
|
||||
actual_columns, data = self.list_vnf_pm_thresholds.take_action(
|
||||
parsed_args)
|
||||
|
||||
_, columns = tacker_osc_utils.get_column_definitions(
|
||||
vnfpm_threshold._ATTR_MAP, long_listing=True)
|
||||
|
||||
expected_data = []
|
||||
for vnf_pm_threshold_obj_idx in vnf_pm_threshold_objs:
|
||||
expected_data.append(
|
||||
vnfpm_threshold_fakes.get_vnfpm_threshold_data(
|
||||
vnf_pm_threshold_obj_idx, columns=columns))
|
||||
|
||||
self.assertCountEqual(_get_columns_vnfpm_threshold(action='list'),
|
||||
actual_columns)
|
||||
self.assertListItemsEqual(expected_data, list(data))
|
||||
|
||||
def test_take_action_with_incorrect_filter(self):
|
||||
parsed_args = self.check_parser(
|
||||
self.list_vnf_pm_thresholds,
|
||||
["--filter", '(perceivedSeverity)'],
|
||||
[('filter', '(perceivedSeverity)')])
|
||||
|
||||
url = os.path.join(
|
||||
self.url, 'vnfpm/v2/thresholds?filter=(perceivedSeverity)')
|
||||
|
||||
self.requests_mock.register_uri(
|
||||
'GET', url, headers=self.header, status_code=400, json={})
|
||||
|
||||
self.assertRaises(exceptions.TackerClientException,
|
||||
self.list_vnf_pm_thresholds.take_action,
|
||||
parsed_args)
|
||||
|
||||
def test_take_action_internal_server_error(self):
|
||||
parsed_args = self.check_parser(
|
||||
self.list_vnf_pm_thresholds,
|
||||
["--filter", '(eq,perceivedSeverity,WARNING)'],
|
||||
[('filter', '(eq,perceivedSeverity,WARNING)')])
|
||||
|
||||
url = os.path.join(
|
||||
self.url,
|
||||
'vnfpm/v2/thresholds?filter=(eq,perceivedSeverity,WARNING)')
|
||||
|
||||
self.requests_mock.register_uri(
|
||||
'GET', url, headers=self.header, status_code=500, json={})
|
||||
|
||||
self.assertRaises(exceptions.TackerClientException,
|
||||
self.list_vnf_pm_thresholds.take_action,
|
||||
parsed_args)
|
||||
|
||||
|
||||
class TestShowVnfPmThreshold(TestVnfPmThreshold):
|
||||
|
||||
def setUp(self):
|
||||
super(TestShowVnfPmThreshold, self).setUp()
|
||||
self.show_vnf_pm_thresholds = vnfpm_threshold.ShowVnfPmThreshold(
|
||||
self.app, self.app_args, cmd_name='vnfpm threshold show')
|
||||
|
||||
def test_take_action(self):
|
||||
vnfpm_threshold_obj = vnfpm_threshold_fakes.vnf_pm_threshold_response()
|
||||
|
||||
arg_list = [vnfpm_threshold_obj['id']]
|
||||
verify_list = [('vnf_pm_threshold_id', vnfpm_threshold_obj['id'])]
|
||||
|
||||
# command param
|
||||
parsed_args = self.check_parser(
|
||||
self.show_vnf_pm_thresholds, arg_list, verify_list)
|
||||
url = os.path.join(
|
||||
self.url, 'vnfpm/v2/thresholds', vnfpm_threshold_obj['id'])
|
||||
|
||||
self.requests_mock.register_uri(
|
||||
'GET', url, headers=self.header, json=vnfpm_threshold_obj)
|
||||
|
||||
columns, data = (self.show_vnf_pm_thresholds.take_action(parsed_args))
|
||||
|
||||
self.assertCountEqual(_get_columns_vnfpm_threshold('show'), columns)
|
||||
|
||||
_, attributes = vnfpm_threshold._get_columns(vnfpm_threshold_obj)
|
||||
self.assertListItemsEqual(
|
||||
vnfpm_threshold_fakes.get_vnfpm_threshold_data(
|
||||
vnfpm_threshold_obj, columns=attributes), data)
|
||||
|
||||
def test_take_action_vnf_pm_threshold_id_not_found(self):
|
||||
arg_list = [uuidsentinel.vnf_pm_threshold_id]
|
||||
verify_list = [('vnf_pm_threshold_id',
|
||||
uuidsentinel.vnf_pm_threshold_id)]
|
||||
|
||||
# command param
|
||||
parsed_args = self.check_parser(
|
||||
self.show_vnf_pm_thresholds, arg_list, verify_list)
|
||||
|
||||
url = os.path.join(
|
||||
self.url, 'vnfpm/v2/thresholds',
|
||||
uuidsentinel.vnf_pm_threshold_id)
|
||||
self.requests_mock.register_uri(
|
||||
'GET', url, headers=self.header, status_code=404, json={})
|
||||
|
||||
self.assertRaises(exceptions.TackerClientException,
|
||||
self.show_vnf_pm_thresholds.take_action,
|
||||
parsed_args)
|
||||
|
||||
def test_take_action_internal_server_error(self):
|
||||
arg_list = [uuidsentinel.vnf_pm_threshold_id]
|
||||
verify_list = [('vnf_pm_threshold_id',
|
||||
uuidsentinel.vnf_pm_threshold_id)]
|
||||
|
||||
# command param
|
||||
parsed_args = self.check_parser(
|
||||
self.show_vnf_pm_thresholds, arg_list, verify_list)
|
||||
|
||||
url = os.path.join(
|
||||
self.url, 'vnfpm/v2/thresholds',
|
||||
uuidsentinel.vnf_pm_threshold_id)
|
||||
self.requests_mock.register_uri(
|
||||
'GET', url, headers=self.header, status_code=500, json={})
|
||||
|
||||
self.assertRaises(exceptions.TackerClientException,
|
||||
self.show_vnf_pm_thresholds.take_action,
|
||||
parsed_args)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestUpdateVnfPmThreshold(TestVnfPmThreshold):
|
||||
|
||||
def setUp(self):
|
||||
super(TestUpdateVnfPmThreshold, self).setUp()
|
||||
self.update_vnf_pm_threshold = vnfpm_threshold.UpdateVnfPmThreshold(
|
||||
self.app, self.app_args, cmd_name='vnfpm threshold update')
|
||||
|
||||
def test_take_action(self):
|
||||
param_file = ("./tackerclient/osc/v2/vnfpm/samples/"
|
||||
"update_vnf_pm_threshold_param_sample.json")
|
||||
arg_list = [uuidsentinel.vnf_pm_threshold_id, param_file]
|
||||
verify_list = [
|
||||
('vnf_pm_threshold_id', uuidsentinel.vnf_pm_threshold_id),
|
||||
('request_file', param_file)
|
||||
]
|
||||
vnfpm_threshold_obj = vnfpm_threshold_fakes.vnf_pm_threshold_response(
|
||||
None, 'update')
|
||||
|
||||
# command param
|
||||
parsed_args = self.check_parser(
|
||||
self.update_vnf_pm_threshold, arg_list, verify_list)
|
||||
url = os.path.join(
|
||||
self.url, 'vnfpm/v2/thresholds',
|
||||
uuidsentinel.vnf_pm_threshold_id)
|
||||
self.requests_mock.register_uri(
|
||||
'PATCH', url, headers=self.header, json=vnfpm_threshold_obj)
|
||||
|
||||
actual_columns, data = (
|
||||
self.update_vnf_pm_threshold.take_action(parsed_args))
|
||||
expected_columns = _get_columns_vnfpm_threshold(action='update')
|
||||
self.assertCountEqual(expected_columns, actual_columns)
|
||||
|
||||
_, columns = vnfpm_threshold._get_columns(
|
||||
vnfpm_threshold_obj, action='update')
|
||||
expected_data = vnfpm_threshold_fakes.get_vnfpm_threshold_data(
|
||||
vnfpm_threshold_obj, columns=columns)
|
||||
self.assertEqual(expected_data, data)
|
||||
|
||||
def test_take_action_vnf_pm_threshold_id_not_found(self):
|
||||
param_file = ("./tackerclient/osc/v2/vnfpm/samples/"
|
||||
"update_vnf_pm_threshold_param_sample.json")
|
||||
arg_list = [uuidsentinel.vnf_pm_threshold_id, param_file]
|
||||
verify_list = [
|
||||
('vnf_pm_threshold_id', uuidsentinel.vnf_pm_threshold_id),
|
||||
('request_file', param_file)
|
||||
]
|
||||
|
||||
# command param
|
||||
parsed_args = self.check_parser(
|
||||
self.update_vnf_pm_threshold, arg_list, verify_list)
|
||||
url = os.path.join(
|
||||
self.url, 'vnfpm/v2/thresholds',
|
||||
uuidsentinel.vnf_pm_threshold_id)
|
||||
self.requests_mock.register_uri(
|
||||
'PATCH', url, headers=self.header, status_code=404, json={})
|
||||
self.assertRaises(exceptions.TackerClientException,
|
||||
self.update_vnf_pm_threshold.take_action,
|
||||
parsed_args)
|
||||
|
||||
|
||||
class TestDeleteVnfPmThreshold(TestVnfPmThreshold):
|
||||
|
||||
def setUp(self):
|
||||
super(TestDeleteVnfPmThreshold, self).setUp()
|
||||
self.delete_vnf_pm_threshold = vnfpm_threshold.DeleteVnfPmThreshold(
|
||||
self.app, self.app_args, cmd_name='vnfpm threshold delete')
|
||||
|
||||
# Vnf Pm threshold to delete
|
||||
self.vnf_pm_thresholds = (
|
||||
vnfpm_threshold_fakes.create_vnf_pm_thresholds(count=3))
|
||||
|
||||
def _mock_request_url_for_delete(self, index):
|
||||
url = os.path.join(self.url, 'vnfpm/v2/thresholds',
|
||||
self.vnf_pm_thresholds[index]['id'])
|
||||
|
||||
self.requests_mock.register_uri('DELETE', url,
|
||||
headers=self.header, json={})
|
||||
|
||||
def test_delete_one_vnf_pm_threshold(self):
|
||||
arg_list = [self.vnf_pm_thresholds[0]['id']]
|
||||
verify_list = [('vnf_pm_threshold_id',
|
||||
[self.vnf_pm_thresholds[0]['id']])]
|
||||
|
||||
parsed_args = self.check_parser(self.delete_vnf_pm_threshold, arg_list,
|
||||
verify_list)
|
||||
|
||||
self._mock_request_url_for_delete(0)
|
||||
sys.stdout = buffer = StringIO()
|
||||
result = self.delete_vnf_pm_threshold.take_action(parsed_args)
|
||||
self.assertIsNone(result)
|
||||
self.assertEqual(
|
||||
(f"VNF PM threshold '{self.vnf_pm_thresholds[0]['id']}' "
|
||||
f"deleted successfully"), buffer.getvalue().strip())
|
||||
|
||||
def test_delete_multiple_vnf_pm_threshold(self):
|
||||
arg_list = []
|
||||
for obj in self.vnf_pm_thresholds:
|
||||
arg_list.append(obj['id'])
|
||||
verify_list = [('vnf_pm_threshold_id', arg_list)]
|
||||
parsed_args = self.check_parser(self.delete_vnf_pm_threshold, arg_list,
|
||||
verify_list)
|
||||
for i in range(0, len(self.vnf_pm_thresholds)):
|
||||
self._mock_request_url_for_delete(i)
|
||||
sys.stdout = buffer = StringIO()
|
||||
result = self.delete_vnf_pm_threshold.take_action(parsed_args)
|
||||
self.assertIsNone(result)
|
||||
self.assertEqual('All specified VNF PM thresholds are deleted '
|
||||
'successfully', buffer.getvalue().strip())
|
||||
|
||||
def test_delete_multiple_vnf_pm_threshold_exception(self):
|
||||
arg_list = [
|
||||
self.vnf_pm_thresholds[0]['id'],
|
||||
'xxxx-yyyy-zzzz',
|
||||
self.vnf_pm_thresholds[1]['id'],
|
||||
]
|
||||
verify_list = [('vnf_pm_threshold_id', arg_list)]
|
||||
parsed_args = self.check_parser(self.delete_vnf_pm_threshold,
|
||||
arg_list, verify_list)
|
||||
|
||||
self._mock_request_url_for_delete(0)
|
||||
|
||||
url = os.path.join(self.url, 'vnfpm/v2/thresholds',
|
||||
'xxxx-yyyy-zzzz')
|
||||
self.requests_mock.register_uri(
|
||||
'GET', url, exc=exceptions.ConnectionFailed)
|
||||
|
||||
self._mock_request_url_for_delete(1)
|
||||
exception = self.assertRaises(exceptions.CommandError,
|
||||
self.delete_vnf_pm_threshold.take_action,
|
||||
parsed_args)
|
||||
|
||||
self.assertEqual(
|
||||
f'Failed to delete 1 of {len(self.vnf_pm_thresholds)} '
|
||||
'VNF PM thresholds.', exception.message)
|
111
tackerclient/tests/unit/osc/v2/vnfpm_threshold_fakes.py
Normal file
111
tackerclient/tests/unit/osc/v2/vnfpm_threshold_fakes.py
Normal file
@ -0,0 +1,111 @@
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 oslo_utils import uuidutils
|
||||
|
||||
from tackerclient.osc import utils as tacker_osc_utils
|
||||
|
||||
|
||||
def create_vnf_pm_thresholds(count=2):
|
||||
"""Create multiple fake vnf pm thresholds.
|
||||
|
||||
:param int count:
|
||||
The number of vnf_pm_thresholds to fake
|
||||
:return:
|
||||
A list of fake vnf pm thresholds dictionary
|
||||
"""
|
||||
vnf_pm_thresholds = []
|
||||
for _ in range(0, count):
|
||||
unique_id = uuidutils.generate_uuid()
|
||||
vnf_pm_thresholds.append(vnf_pm_threshold_response(
|
||||
attrs={'id': unique_id}))
|
||||
return vnf_pm_thresholds
|
||||
|
||||
|
||||
def vnf_pm_threshold_response(attrs=None, action=None):
|
||||
"""Create a fake vnf pm threshold.
|
||||
|
||||
:param Dictionary attrs:
|
||||
A dictionary with all attributes
|
||||
:param String action:
|
||||
The operation performed on threshold
|
||||
:return:
|
||||
A pm threshold dict
|
||||
"""
|
||||
if action == 'update':
|
||||
fake_vnf_pm_threshold = {
|
||||
"callbackUri": "/nfvo/notify/threshold",
|
||||
}
|
||||
return fake_vnf_pm_threshold
|
||||
|
||||
attrs = attrs or {}
|
||||
# Set default attributes.
|
||||
fake_vnf_pm_threshold = {
|
||||
"id": "2bb72d78-b1d9-48fe-8c64-332654ffeb5d",
|
||||
"objectType": "Vnfc",
|
||||
"objectInstanceId": "object-instance-id-1",
|
||||
"subObjectInstanceIds": [
|
||||
"sub-object-instance-id-2"
|
||||
],
|
||||
"criteria": {
|
||||
"performanceMetric": "VCpuUsageMeanVnf.object-instance-id-1",
|
||||
"thresholdType": "SIMPLE",
|
||||
"simpleThresholdDetails": {
|
||||
"thresholdValue": 500.5,
|
||||
"hysteresis": 10.5
|
||||
}
|
||||
},
|
||||
"callbackUri": "/nfvo/notify/threshold",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/vnfpm/v2/thresholds/"
|
||||
"78a39661-60a8-4824-b989-88c1b0c3534a"
|
||||
},
|
||||
"object": {
|
||||
"href": "/vnflcm/v1/vnf_instances/"
|
||||
"0e5f3086-4e79-47ed-a694-54c29155fa26"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Overwrite default attributes.
|
||||
fake_vnf_pm_threshold.update(attrs)
|
||||
|
||||
return fake_vnf_pm_threshold
|
||||
|
||||
|
||||
def get_vnfpm_threshold_data(vnf_pm_threshold, columns=None):
|
||||
"""Get the vnfpm threshold.
|
||||
|
||||
:param Dictionary vnf_pm_threshold:
|
||||
A dictionary with vnf_pm_threshold
|
||||
:param List columns:
|
||||
A list of column names
|
||||
:return:
|
||||
A tuple object sorted based on the name of the columns.
|
||||
"""
|
||||
complex_attributes = ['subObjectInstanceIds',
|
||||
'criteria', '_links', 'authentication']
|
||||
|
||||
for attribute in complex_attributes:
|
||||
if vnf_pm_threshold.get(attribute):
|
||||
vnf_pm_threshold.update(
|
||||
{attribute: tacker_osc_utils.FormatComplexDataColumn(
|
||||
vnf_pm_threshold[attribute])})
|
||||
|
||||
# return the list of data as per column order
|
||||
if columns is None:
|
||||
columns = sorted(vnf_pm_threshold.keys())
|
||||
return tuple([vnf_pm_threshold[key] for key in columns])
|
@ -1104,6 +1104,8 @@ class VnfPMClient(ClientBase):
|
||||
vnf_pm_jobs_path = '/vnfpm/v2/pm_jobs'
|
||||
vnf_pm_job_path = '/vnfpm/v2/pm_jobs/%s'
|
||||
vnf_pm_reports_path = '/vnfpm/v2/pm_jobs/%(job_id)s/reports/%(report_id)s'
|
||||
vnf_pm_thresholds_path = '/vnfpm/v2/thresholds'
|
||||
vnf_pm_threshold_path = '/vnfpm/v2/thresholds/%s'
|
||||
|
||||
def build_action(self, action):
|
||||
return action
|
||||
@ -1143,6 +1145,35 @@ class VnfPMClient(ClientBase):
|
||||
'job_id': vnf_pm_job_id, 'report_id': vnf_pm_report_id
|
||||
}, headers=self.headers)
|
||||
|
||||
@APIParamsCall
|
||||
def create_vnf_pm_threshold(self, body):
|
||||
return self.post(
|
||||
self.vnf_pm_thresholds_path, body=body, headers=self.headers)
|
||||
|
||||
@APIParamsCall
|
||||
def list_vnf_pm_thresholds(self, retrieve_all=True, **_params):
|
||||
return self.list(
|
||||
"vnf_pm_thresholds", self.vnf_pm_thresholds_path, retrieve_all,
|
||||
headers=self.headers, **_params)
|
||||
|
||||
@APIParamsCall
|
||||
def show_vnf_pm_threshold(self, vnf_pm_threshold_id):
|
||||
return self.get(
|
||||
self.vnf_pm_threshold_path % vnf_pm_threshold_id,
|
||||
headers=self.headers)
|
||||
|
||||
@APIParamsCall
|
||||
def update_vnf_pm_threshold(self, vnf_pm_threshold_id, body):
|
||||
return self.patch(
|
||||
self.vnf_pm_threshold_path % vnf_pm_threshold_id, body=body,
|
||||
headers=self.headers)
|
||||
|
||||
@APIParamsCall
|
||||
def delete_vnf_pm_threshold(self, vnf_pm_threshold_id):
|
||||
return self.delete(
|
||||
self.vnf_pm_threshold_path % vnf_pm_threshold_id,
|
||||
headers=self.headers)
|
||||
|
||||
|
||||
class Client(object):
|
||||
"""Unified interface to interact with multiple applications of tacker service.
|
||||
@ -1527,3 +1558,20 @@ class Client(object):
|
||||
def show_vnf_pm_report(self, vnf_pm_job_id, vnf_pm_report_id):
|
||||
return self.vnf_pm_client.show_vnf_pm_report(
|
||||
vnf_pm_job_id, vnf_pm_report_id)
|
||||
|
||||
def create_vnf_pm_threshold(self, body):
|
||||
return self.vnf_pm_client.create_vnf_pm_threshold(body)
|
||||
|
||||
def list_vnf_pm_thresholds(self, retrieve_all=True, **_params):
|
||||
return self.vnf_pm_client.list_vnf_pm_thresholds(
|
||||
retrieve_all=retrieve_all, **_params)
|
||||
|
||||
def show_vnf_pm_threshold(self, vnf_pm_threshold_id):
|
||||
return self.vnf_pm_client.show_vnf_pm_threshold(vnf_pm_threshold_id)
|
||||
|
||||
def update_vnf_pm_threshold(self, vnf_pm_threshold_id, body):
|
||||
return self.vnf_pm_client.update_vnf_pm_threshold(
|
||||
vnf_pm_threshold_id, body)
|
||||
|
||||
def delete_vnf_pm_threshold(self, vnf_pm_threshold_id):
|
||||
return self.vnf_pm_client.delete_vnf_pm_threshold(vnf_pm_threshold_id)
|
||||
|
Loading…
Reference in New Issue
Block a user