Support of version 2.4.1 on Modify VNF
Version 2.4.1 of Modify VNF is supported. Implements: blueprint support-etsi-nfv-specs Spec: https://specs.openstack.org/openstack/tacker-specs/specs/victoria/enhancement_enhance-vnf-lcm-api-support.html Change-Id: I6dd978463511672bc26034cc3ff339bd92090c33
This commit is contained in:
parent
797554a378
commit
e29026f3fc
@ -611,6 +611,7 @@ Request Parameters
|
|||||||
- vnfInstanceName: vnf_instance_modify_request_name
|
- vnfInstanceName: vnf_instance_modify_request_name
|
||||||
- vnfInstanceDescription: vnf_instance_modify_request_description
|
- vnfInstanceDescription: vnf_instance_modify_request_description
|
||||||
- vnfdId: vnf_instance_modify_request_vnfd_id
|
- vnfdId: vnf_instance_modify_request_vnfd_id
|
||||||
|
- vnfPkgId: vnf_instance_modify_request_vnf_pkg_id
|
||||||
- metadata: vnf_instance_modify_request_metadata
|
- metadata: vnf_instance_modify_request_metadata
|
||||||
- vimConnectionInfo: vnf_instance_modify_request_vim_connection_info
|
- vimConnectionInfo: vnf_instance_modify_request_vim_connection_info
|
||||||
- id: vim_connection_info_id
|
- id: vim_connection_info_id
|
||||||
|
@ -600,7 +600,8 @@ class VnfLcmController(wsgi.Controller):
|
|||||||
self._instantiate(context, vnf_instance, vnf, body)
|
self._instantiate(context, vnf_instance, vnf, body)
|
||||||
|
|
||||||
@check_vnf_state(action="terminate",
|
@check_vnf_state(action="terminate",
|
||||||
instantiation_state=[fields.VnfInstanceState.INSTANTIATED],
|
instantiation_state=[
|
||||||
|
fields.VnfInstanceState.INSTANTIATED],
|
||||||
task_state=[None])
|
task_state=[None])
|
||||||
def _terminate(self, context, vnf_instance, request_body, vnf):
|
def _terminate(self, context, vnf_instance, request_body, vnf):
|
||||||
req_body = utils.convert_camelcase_to_snakecase(request_body)
|
req_body = utils.convert_camelcase_to_snakecase(request_body)
|
||||||
@ -641,8 +642,9 @@ class VnfLcmController(wsgi.Controller):
|
|||||||
req_body = utils.convert_camelcase_to_snakecase(request_body)
|
req_body = utils.convert_camelcase_to_snakecase(request_body)
|
||||||
heal_vnf_request = objects.HealVnfRequest(context=context, **req_body)
|
heal_vnf_request = objects.HealVnfRequest(context=context, **req_body)
|
||||||
inst_vnf_info = vnf_instance.instantiated_vnf_info
|
inst_vnf_info = vnf_instance.instantiated_vnf_info
|
||||||
vnfc_resource_info_ids = [vnfc_resource_info.id for
|
vnfc_resource_info_ids = [
|
||||||
vnfc_resource_info in inst_vnf_info.vnfc_resource_info]
|
vnfc_resource_info.id for vnfc_resource_info in
|
||||||
|
inst_vnf_info.vnfc_resource_info]
|
||||||
|
|
||||||
for vnfc_id in heal_vnf_request.vnfc_instance_id:
|
for vnfc_id in heal_vnf_request.vnfc_instance_id:
|
||||||
# check if vnfc_id exists in vnfc_resource_info
|
# check if vnfc_id exists in vnfc_resource_info
|
||||||
@ -702,7 +704,13 @@ class VnfLcmController(wsgi.Controller):
|
|||||||
context.can(vnf_lcm_policies.VNFLCM % 'update_vnf')
|
context.can(vnf_lcm_policies.VNFLCM % 'update_vnf')
|
||||||
|
|
||||||
# get body
|
# get body
|
||||||
req_body = utils.convert_camelcase_to_snakecase(body)
|
body_data = {}
|
||||||
|
body_data['vnf_instance_name'] = body.get('vnfInstanceName')
|
||||||
|
body_data['vnf_instance_description'] = body.get(
|
||||||
|
'vnfInstanceDescription')
|
||||||
|
body_data['vnfd_id'] = body.get('vnfdId')
|
||||||
|
if (body.get('vnfdId') is None and body.get('vnfPkgId')):
|
||||||
|
body_data['vnf_pkg_id'] = body.get('vnfPkgId')
|
||||||
|
|
||||||
# According to the ETSI NFV SOL document,
|
# According to the ETSI NFV SOL document,
|
||||||
# there is no API request/response
|
# there is no API request/response
|
||||||
@ -725,8 +733,12 @@ class VnfLcmController(wsgi.Controller):
|
|||||||
if (vnf_data.get("status") != fields.VnfStatus.ACTIVE and
|
if (vnf_data.get("status") != fields.VnfStatus.ACTIVE and
|
||||||
vnf_data.get("status") != fields.VnfStatus.INACTIVE):
|
vnf_data.get("status") != fields.VnfStatus.INACTIVE):
|
||||||
msg = _("VNF %(id)s status is %(state)s")
|
msg = _("VNF %(id)s status is %(state)s")
|
||||||
return self._make_problem_detail(msg % {"id": id,
|
return self._make_problem_detail(
|
||||||
"state": vnf_data.get("status")}, 409, 'Conflict')
|
msg % {
|
||||||
|
"id": id,
|
||||||
|
"state": vnf_data.get("status")},
|
||||||
|
409,
|
||||||
|
'Conflict')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
vnf_instance_data = objects.VnfInstanceList.vnf_instance_list(
|
vnf_instance_data = objects.VnfInstanceList.vnf_instance_list(
|
||||||
@ -739,19 +751,27 @@ class VnfLcmController(wsgi.Controller):
|
|||||||
return self._make_problem_detail(
|
return self._make_problem_detail(
|
||||||
str(e), 500, 'Internal Server Error')
|
str(e), 500, 'Internal Server Error')
|
||||||
|
|
||||||
if req_body['vnfd_id']:
|
vnfd_pkg_data = {}
|
||||||
|
if (body_data.get('vnfd_id') or body_data.get('vnf_pkg_id')):
|
||||||
try:
|
try:
|
||||||
pkg_obj = objects.VnfPackageVnfd(context=context)
|
pkg_obj = objects.VnfPackageVnfd(context=context)
|
||||||
vnfd_pkg = pkg_obj.get_vnf_package_vnfd(req_body['vnfd_id'])
|
if (body_data.get('vnfd_id')):
|
||||||
|
input_id = 'vnfd_id'
|
||||||
|
vnfd_pkg = pkg_obj.get_vnf_package_vnfd(
|
||||||
|
body_data[input_id])
|
||||||
|
elif (body_data.get('vnf_pkg_id')):
|
||||||
|
input_id = 'vnf_pkg_id'
|
||||||
|
vnfd_pkg = pkg_obj.get_vnf_package_vnfd(
|
||||||
|
body_data[input_id], package_uuid=True)
|
||||||
if not vnfd_pkg:
|
if not vnfd_pkg:
|
||||||
msg = _(
|
msg = _(
|
||||||
"Can not find requested vnf package vnfd: %s") %\
|
"Can not find requested vnf package vnfd: %s") %\
|
||||||
req_body['vnfd_id']
|
body_data[input_id]
|
||||||
return self._make_problem_detail(msg, 400, 'Bad Request')
|
return self._make_problem_detail(msg, 400, 'Bad Request')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return self._make_problem_detail(
|
return self._make_problem_detail(
|
||||||
str(e), 500, 'Internal Server Error')
|
str(e), 500, 'Internal Server Error')
|
||||||
vnfd_pkg_data = {}
|
|
||||||
vnfd_pkg_data['vnf_provider'] = vnfd_pkg.get('vnf_provider')
|
vnfd_pkg_data['vnf_provider'] = vnfd_pkg.get('vnf_provider')
|
||||||
vnfd_pkg_data['vnf_product_name'] = vnfd_pkg.get(
|
vnfd_pkg_data['vnf_product_name'] = vnfd_pkg.get(
|
||||||
'vnf_product_name')
|
'vnf_product_name')
|
||||||
@ -759,13 +779,12 @@ class VnfLcmController(wsgi.Controller):
|
|||||||
'vnf_software_version')
|
'vnf_software_version')
|
||||||
vnfd_pkg_data['vnfd_version'] = vnfd_pkg.get('vnfd_version')
|
vnfd_pkg_data['vnfd_version'] = vnfd_pkg.get('vnfd_version')
|
||||||
vnfd_pkg_data['package_uuid'] = vnfd_pkg.get('package_uuid')
|
vnfd_pkg_data['package_uuid'] = vnfd_pkg.get('package_uuid')
|
||||||
|
vnfd_pkg_data['vnfd_id'] = vnfd_pkg.get('vnfd_id')
|
||||||
|
|
||||||
# make op_occs_uuid
|
# make op_occs_uuid
|
||||||
op_occs_uuid = uuidutils.generate_uuid()
|
op_occs_uuid = uuidutils.generate_uuid()
|
||||||
|
|
||||||
# process vnf
|
# process vnf
|
||||||
if not req_body['vnfd_id']:
|
|
||||||
vnfd_pkg_data = ""
|
|
||||||
vnf_lcm_opoccs = {
|
vnf_lcm_opoccs = {
|
||||||
'vnf_instance_id': id,
|
'vnf_instance_id': id,
|
||||||
'id': op_occs_uuid,
|
'id': op_occs_uuid,
|
||||||
@ -775,7 +794,7 @@ class VnfLcmController(wsgi.Controller):
|
|||||||
self.rpc_api.update(
|
self.rpc_api.update(
|
||||||
context,
|
context,
|
||||||
vnf_lcm_opoccs,
|
vnf_lcm_opoccs,
|
||||||
req_body,
|
body_data,
|
||||||
vnfd_pkg_data,
|
vnfd_pkg_data,
|
||||||
vnf_data.get('vnfd_id'))
|
vnf_data.get('vnfd_id'))
|
||||||
|
|
||||||
|
@ -1241,18 +1241,15 @@ class Conductor(manager.Manager):
|
|||||||
raise Exception(str(msg))
|
raise Exception(str(msg))
|
||||||
|
|
||||||
# update lcm_op_occs
|
# update lcm_op_occs
|
||||||
|
if vnfd_pkg_data and len(vnfd_pkg_data) > 0:
|
||||||
|
changed_info = \
|
||||||
|
objects.vnf_lcm_op_occs.VnfInfoModifications._from_dict(
|
||||||
|
vnfd_pkg_data)
|
||||||
|
else:
|
||||||
changed_info = objects.vnf_lcm_op_occs.VnfInfoModifications()
|
changed_info = objects.vnf_lcm_op_occs.VnfInfoModifications()
|
||||||
changed_info.vnf_instance_name = body_data.get('vnf_instance_name')
|
changed_info.vnf_instance_name = body_data.get('vnf_instance_name')
|
||||||
changed_info.vnf_instance_description = body_data.get(
|
changed_info.vnf_instance_description = body_data.get(
|
||||||
'vnf_instance_description')
|
'vnf_instance_description')
|
||||||
if body_data.get('vnfd_id'):
|
|
||||||
changed_info.vnfd_id = body_data.get('vnfd_id')
|
|
||||||
changed_info.vnf_provider = vnfd_pkg_data.get('vnf_provider')
|
|
||||||
changed_info.vnf_product_name = vnfd_pkg_data.get(
|
|
||||||
'vnf_product_name')
|
|
||||||
changed_info.vnf_software_version = vnfd_pkg_data.get(
|
|
||||||
'vnf_software_version')
|
|
||||||
changed_info.vnfd_version = vnfd_pkg_data.get('vnfd_version')
|
|
||||||
|
|
||||||
# update vnf_lcm_op_occs
|
# update vnf_lcm_op_occs
|
||||||
now = timeutils.utcnow()
|
now = timeutils.utcnow()
|
||||||
|
@ -85,6 +85,26 @@ class VNFLcmRPCAPI(object):
|
|||||||
vnfd_pkg_data=vnfd_pkg_data,
|
vnfd_pkg_data=vnfd_pkg_data,
|
||||||
vnfd_id=vnfd_id)
|
vnfd_id=vnfd_id)
|
||||||
|
|
||||||
|
def update_vnf_instance_content(
|
||||||
|
self,
|
||||||
|
context,
|
||||||
|
vnf_lcm_opoccs,
|
||||||
|
body_data,
|
||||||
|
vnfd_pkg_data,
|
||||||
|
vnfd_id,
|
||||||
|
cast=True):
|
||||||
|
serializer = objects_base.TackerObjectSerializer()
|
||||||
|
|
||||||
|
client = rpc.get_client(self.target, version_cap=None,
|
||||||
|
serializer=serializer)
|
||||||
|
cctxt = client.prepare()
|
||||||
|
rpc_method = cctxt.cast if cast else cctxt.call
|
||||||
|
return rpc_method(context, 'update_lcm',
|
||||||
|
vnf_lcm_opoccs=vnf_lcm_opoccs,
|
||||||
|
body_data=body_data,
|
||||||
|
vnfd_pkg_data=vnfd_pkg_data,
|
||||||
|
vnfd_id=vnfd_id)
|
||||||
|
|
||||||
def send_notification(self, context, notification, cast=True):
|
def send_notification(self, context, notification, cast=True):
|
||||||
serializer = objects_base.TackerObjectSerializer()
|
serializer = objects_base.TackerObjectSerializer()
|
||||||
|
|
||||||
|
@ -80,6 +80,19 @@ class VnfSoftwareImage(model_base.BASE, models.SoftDeleteMixin,
|
|||||||
return {m.key: m.value for m in self._metadata}
|
return {m.key: m.value for m in self._metadata}
|
||||||
|
|
||||||
|
|
||||||
|
class VnfArtifactMetadata(model_base.BASE, models.SoftDeleteMixin,
|
||||||
|
models.TimestampMixin):
|
||||||
|
"""Contains all info about vnf packages artifacts metadata."""
|
||||||
|
|
||||||
|
__tablename__ = 'vnf_artifact_metadata'
|
||||||
|
id = sa.Column(sa.Integer, nullable=False, primary_key=True)
|
||||||
|
artifact_uuid = sa.Column(sa.String(36),
|
||||||
|
sa.ForeignKey('vnf_artifacts.id'),
|
||||||
|
nullable=False)
|
||||||
|
key = sa.Column(sa.String(255), nullable=False)
|
||||||
|
value = sa.Column(sa.String(255), nullable=False)
|
||||||
|
|
||||||
|
|
||||||
class VnfDeploymentFlavour(model_base.BASE, models.SoftDeleteMixin,
|
class VnfDeploymentFlavour(model_base.BASE, models.SoftDeleteMixin,
|
||||||
models.TimestampMixin, models_v1.HasId):
|
models.TimestampMixin, models_v1.HasId):
|
||||||
"""Contains all info about vnf packages Deployment Flavours."""
|
"""Contains all info about vnf packages Deployment Flavours."""
|
||||||
@ -115,7 +128,9 @@ class VnfPackageVnfd(model_base.BASE, VnfPackageVnfdSoftDeleteMixin,
|
|||||||
|
|
||||||
__tablename__ = 'vnf_package_vnfd'
|
__tablename__ = 'vnf_package_vnfd'
|
||||||
__table_args__ = (
|
__table_args__ = (
|
||||||
sa.schema.UniqueConstraint("vnfd_id", "deleted",
|
sa.schema.UniqueConstraint(
|
||||||
|
"vnfd_id",
|
||||||
|
"deleted",
|
||||||
name="uniq_vnf_package_vnfd0vnfd_id0deleted"),
|
name="uniq_vnf_package_vnfd0vnfd_id0deleted"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -201,6 +216,7 @@ class VnfInstance(model_base.BASE, models.SoftDeleteMixin,
|
|||||||
task_state = sa.Column(sa.String(255), nullable=True)
|
task_state = sa.Column(sa.String(255), nullable=True)
|
||||||
vim_connection_info = sa.Column(sa.JSON(), nullable=True)
|
vim_connection_info = sa.Column(sa.JSON(), nullable=True)
|
||||||
tenant_id = sa.Column('tenant_id', sa.String(length=64), nullable=False)
|
tenant_id = sa.Column('tenant_id', sa.String(length=64), nullable=False)
|
||||||
|
vnf_pkg_id = sa.Column(types.Uuid, nullable=False)
|
||||||
vnf_metadata = sa.Column(sa.JSON(), nullable=True)
|
vnf_metadata = sa.Column(sa.JSON(), nullable=True)
|
||||||
|
|
||||||
|
|
||||||
@ -226,8 +242,11 @@ class VnfInstantiatedInfo(model_base.BASE, models.SoftDeleteMixin,
|
|||||||
instantiation_level_id = sa.Column(sa.String(255), nullable=True)
|
instantiation_level_id = sa.Column(sa.String(255), nullable=True)
|
||||||
additional_params = sa.Column(sa.JSON(), nullable=True)
|
additional_params = sa.Column(sa.JSON(), nullable=True)
|
||||||
|
|
||||||
vnf_instance = orm.relationship(VnfInstance,
|
vnf_instance = orm.relationship(
|
||||||
backref=orm.backref('instantiated_vnf_info', uselist=False),
|
VnfInstance,
|
||||||
|
backref=orm.backref(
|
||||||
|
'instantiated_vnf_info',
|
||||||
|
uselist=False),
|
||||||
foreign_keys=vnf_instance_id,
|
foreign_keys=vnf_instance_id,
|
||||||
primaryjoin='and_(VnfInstantiatedInfo.vnf_instance_id == '
|
primaryjoin='and_(VnfInstantiatedInfo.vnf_instance_id == '
|
||||||
'VnfInstance.id, VnfInstantiatedInfo.deleted == 0)')
|
'VnfInstance.id, VnfInstantiatedInfo.deleted == 0)')
|
||||||
|
@ -238,24 +238,30 @@ def _update_vnf_instances(
|
|||||||
|
|
||||||
updated_values['vim_connection_info'] = merge_vim_connection_info
|
updated_values['vim_connection_info'] = merge_vim_connection_info
|
||||||
|
|
||||||
if body_data.get('vnfd_id'):
|
if vnfd_pkg_data and len(vnfd_pkg_data) > 0:
|
||||||
updated_values['vnfd_id'] = body_data.get('vnfd_id')
|
updated_values['vnfd_id'] = vnfd_pkg_data.get('vnfd_id')
|
||||||
updated_values['vnf_provider'] = vnfd_pkg_data.get('vnf_provider')
|
updated_values['vnf_provider'] = vnfd_pkg_data.get('vnf_provider')
|
||||||
updated_values['vnf_product_name'] = vnfd_pkg_data.get(
|
updated_values['vnf_product_name'] = vnfd_pkg_data.get(
|
||||||
'vnf_product_name')
|
'vnf_product_name')
|
||||||
updated_values['vnf_software_version'] = vnfd_pkg_data.get(
|
updated_values['vnf_software_version'] = vnfd_pkg_data.get(
|
||||||
'vnf_software_version')
|
'vnf_software_version')
|
||||||
|
updated_values['vnf_pkg_id'] = vnfd_pkg_data.get('package_uuid')
|
||||||
|
|
||||||
api.model_query(context, models.VnfInstance). \
|
api.model_query(context, models.VnfInstance). \
|
||||||
filter_by(id=vnf_lcm_opoccs.get('vnf_instance_id')). \
|
filter_by(id=vnf_lcm_opoccs.get('vnf_instance_id')). \
|
||||||
update(updated_values, synchronize_session=False)
|
update(updated_values, synchronize_session=False)
|
||||||
|
|
||||||
vnf_now = timeutils.utcnow()
|
vnf_now = timeutils.utcnow()
|
||||||
if body_data.get('vnfd_id'):
|
if (body_data.get('vnfd_id') or body_data.get('vnf_pkg_id')):
|
||||||
# update vnf
|
# update vnf
|
||||||
|
if body_data.get('vnfd_id'):
|
||||||
updated_values = {'vnfd_id': body_data.get('vnfd_id'),
|
updated_values = {'vnfd_id': body_data.get('vnfd_id'),
|
||||||
'updated_at': vnf_now
|
'updated_at': vnf_now
|
||||||
}
|
}
|
||||||
|
elif body_data.get('vnf_pkg_id'):
|
||||||
|
updated_values = {'vnfd_id': vnfd_pkg_data.get('vnfd_id'),
|
||||||
|
'updated_at': vnf_now
|
||||||
|
}
|
||||||
api.model_query(context, vnfm_db.VNF).\
|
api.model_query(context, vnfm_db.VNF).\
|
||||||
filter_by(id=vnf_lcm_opoccs.get('vnf_instance_id')). \
|
filter_by(id=vnf_lcm_opoccs.get('vnf_instance_id')). \
|
||||||
update(updated_values, synchronize_session=False)
|
update(updated_values, synchronize_session=False)
|
||||||
@ -308,7 +314,9 @@ class VnfInstance(base.TackerObject, base.TackerPersistentObject,
|
|||||||
'id': fields.UUIDField(nullable=False),
|
'id': fields.UUIDField(nullable=False),
|
||||||
'vnf_instance_name': fields.StringField(nullable=True),
|
'vnf_instance_name': fields.StringField(nullable=True),
|
||||||
'vnf_instance_description': fields.StringField(nullable=True),
|
'vnf_instance_description': fields.StringField(nullable=True),
|
||||||
'instantiation_state': fields.VnfInstanceStateField(nullable=False,
|
'instantiation_state':
|
||||||
|
fields.VnfInstanceStateField(
|
||||||
|
nullable=False,
|
||||||
default=fields.VnfInstanceState.NOT_INSTANTIATED),
|
default=fields.VnfInstanceState.NOT_INSTANTIATED),
|
||||||
'task_state': fields.StringField(nullable=True, default=None),
|
'task_state': fields.StringField(nullable=True, default=None),
|
||||||
'vnfd_id': fields.StringField(nullable=False),
|
'vnfd_id': fields.StringField(nullable=False),
|
||||||
@ -320,6 +328,7 @@ class VnfInstance(base.TackerObject, base.TackerPersistentObject,
|
|||||||
'VimConnectionInfo', nullable=True, default=[]),
|
'VimConnectionInfo', nullable=True, default=[]),
|
||||||
'tenant_id': fields.StringField(nullable=False),
|
'tenant_id': fields.StringField(nullable=False),
|
||||||
'vnf_metadata': fields.DictOfStringsField(nullable=True, default={}),
|
'vnf_metadata': fields.DictOfStringsField(nullable=True, default={}),
|
||||||
|
'vnf_pkg_id': fields.StringField(nullable=False),
|
||||||
'instantiated_vnf_info': fields.ObjectField('InstantiatedVnfInfo',
|
'instantiated_vnf_info': fields.ObjectField('InstantiatedVnfInfo',
|
||||||
nullable=True, default=None)
|
nullable=True, default=None)
|
||||||
}
|
}
|
||||||
@ -367,8 +376,8 @@ class VnfInstance(base.TackerObject, base.TackerPersistentObject,
|
|||||||
|
|
||||||
setattr(vnf_instance, key, db_vnf_instance[key])
|
setattr(vnf_instance, key, db_vnf_instance[key])
|
||||||
|
|
||||||
VnfInstance._load_instantiated_vnf_info_from_db_object(context,
|
VnfInstance._load_instantiated_vnf_info_from_db_object(
|
||||||
vnf_instance, db_vnf_instance)
|
context, vnf_instance, db_vnf_instance)
|
||||||
|
|
||||||
vim_connection_info = db_vnf_instance['vim_connection_info']
|
vim_connection_info = db_vnf_instance['vim_connection_info']
|
||||||
vim_connection_list = [objects.VimConnectionInfo.obj_from_primitive(
|
vim_connection_list = [objects.VimConnectionInfo.obj_from_primitive(
|
||||||
@ -384,9 +393,8 @@ class VnfInstance(base.TackerObject, base.TackerPersistentObject,
|
|||||||
def _load_instantiated_vnf_info_from_db_object(context, vnf_instance,
|
def _load_instantiated_vnf_info_from_db_object(context, vnf_instance,
|
||||||
db_vnf_instance):
|
db_vnf_instance):
|
||||||
if db_vnf_instance['instantiated_vnf_info']:
|
if db_vnf_instance['instantiated_vnf_info']:
|
||||||
inst_vnf_info = \
|
inst_vnf_info = objects.InstantiatedVnfInfo.obj_from_db_obj(
|
||||||
objects.InstantiatedVnfInfo.obj_from_db_obj(context,
|
context, db_vnf_instance['instantiated_vnf_info'])
|
||||||
db_vnf_instance['instantiated_vnf_info'])
|
|
||||||
vnf_instance.instantiated_vnf_info = inst_vnf_info
|
vnf_instance.instantiated_vnf_info = inst_vnf_info
|
||||||
|
|
||||||
@base.remotable
|
@base.remotable
|
||||||
|
@ -201,7 +201,8 @@ def _model_non_instantiated_vnf_instance(**updates):
|
|||||||
'vnf_software_version': '1.0',
|
'vnf_software_version': '1.0',
|
||||||
'tenant_id': uuidsentinel.tenant_id,
|
'tenant_id': uuidsentinel.tenant_id,
|
||||||
'vnfd_id': uuidsentinel.vnfd_id,
|
'vnfd_id': uuidsentinel.vnfd_id,
|
||||||
'vnfd_version': '1.0'}
|
'vnfd_version': '1.0',
|
||||||
|
'vnfPkgId': uuidsentinel.vnf_pkg_id}
|
||||||
|
|
||||||
if updates:
|
if updates:
|
||||||
vnf_instance.update(**updates)
|
vnf_instance.update(**updates)
|
||||||
|
@ -133,6 +133,7 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
body_data['vnfd_id'] = "2c69a161-0000-4b0f-bcf8-391f8fc76600"
|
body_data['vnfd_id'] = "2c69a161-0000-4b0f-bcf8-391f8fc76600"
|
||||||
body_data['vnf_configurable_properties'] = {"test": "test_value"}
|
body_data['vnf_configurable_properties'] = {"test": "test_value"}
|
||||||
body_data['vnfc_info_modifications_delete_ids'] = ["test1"]
|
body_data['vnfc_info_modifications_delete_ids'] = ["test1"]
|
||||||
|
body_data['vnf_pkg_id'] = uuidsentinel.vnf_pkg_id
|
||||||
return body_data
|
return body_data
|
||||||
|
|
||||||
def _create_vnf_lcm_opoccs(self):
|
def _create_vnf_lcm_opoccs(self):
|
||||||
@ -337,8 +338,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
@mock.patch.object(objects.VnfPackage, 'is_package_in_use')
|
@mock.patch.object(objects.VnfPackage, 'is_package_in_use')
|
||||||
@mock.patch('tacker.conductor.conductor_server.LOG')
|
@mock.patch('tacker.conductor.conductor_server.LOG')
|
||||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||||
def test_instantiate_vnf_instance_already_instantiated(self,
|
def test_instantiate_vnf_instance_already_instantiated(
|
||||||
mock_vnf_by_id, mock_log, mock_package_in_use, mock_get_lock,
|
self, mock_vnf_by_id, mock_log, mock_package_in_use, mock_get_lock,
|
||||||
mock_save):
|
mock_save):
|
||||||
lcm_op_occs_data = fakes.get_lcm_op_occs_data()
|
lcm_op_occs_data = fakes.get_lcm_op_occs_data()
|
||||||
mock_vnf_by_id.return_value = \
|
mock_vnf_by_id.return_value = \
|
||||||
@ -361,8 +362,9 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
self.vnflcm_driver.instantiate_vnf.assert_not_called()
|
self.vnflcm_driver.instantiate_vnf.assert_not_called()
|
||||||
mock_package_in_use.assert_not_called()
|
mock_package_in_use.assert_not_called()
|
||||||
expected_log = 'Vnf instance %(id)s is already in %(state)s state.'
|
expected_log = 'Vnf instance %(id)s is already in %(state)s state.'
|
||||||
mock_log.error.assert_called_once_with(expected_log,
|
mock_log.error.assert_called_once_with(
|
||||||
{'id': vnf_instance.id,
|
expected_log, {
|
||||||
|
'id': vnf_instance.id,
|
||||||
'state': fields.VnfInstanceState.INSTANTIATED})
|
'state': fields.VnfInstanceState.INSTANTIATED})
|
||||||
|
|
||||||
@unittest.skip("Such test is no longer feasible.")
|
@unittest.skip("Such test is no longer feasible.")
|
||||||
@ -372,10 +374,13 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
@mock.patch.object(objects.LccnSubscriptionRequest,
|
@mock.patch.object(objects.LccnSubscriptionRequest,
|
||||||
'vnf_lcm_subscriptions_get')
|
'vnf_lcm_subscriptions_get')
|
||||||
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id")
|
||||||
def test_instantiate_vnf_instance_with_vnf_package_in_use(self,
|
def test_instantiate_vnf_instance_with_vnf_package_in_use(
|
||||||
|
self,
|
||||||
mock_vnf_by_id,
|
mock_vnf_by_id,
|
||||||
mock_vnf_lcm_subscriptions_get,
|
mock_vnf_lcm_subscriptions_get,
|
||||||
mock_vnf_package_in_use, mock_get_lock, mock_save):
|
mock_vnf_package_in_use,
|
||||||
|
mock_get_lock,
|
||||||
|
mock_save):
|
||||||
lcm_op_occs_data = fakes.get_lcm_op_occs_data()
|
lcm_op_occs_data = fakes.get_lcm_op_occs_data()
|
||||||
mock_vnf_by_id.return_value = \
|
mock_vnf_by_id.return_value = \
|
||||||
objects.VnfLcmOpOcc(context=self.context,
|
objects.VnfLcmOpOcc(context=self.context,
|
||||||
@ -531,8 +536,9 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
mock_package_in_use.assert_not_called()
|
mock_package_in_use.assert_not_called()
|
||||||
expected_log = ('Terminate action cannot be performed on vnf %(id)s '
|
expected_log = ('Terminate action cannot be performed on vnf %(id)s '
|
||||||
'which is in %(state)s state.')
|
'which is in %(state)s state.')
|
||||||
mock_log.error.assert_called_once_with(expected_log,
|
mock_log.error.assert_called_once_with(
|
||||||
{'id': vnf_instance.id,
|
expected_log, {
|
||||||
|
'id': vnf_instance.id,
|
||||||
'state': fields.VnfInstanceState.NOT_INSTANTIATED})
|
'state': fields.VnfInstanceState.NOT_INSTANTIATED})
|
||||||
|
|
||||||
@unittest.skip("Such test is no longer feasible.")
|
@unittest.skip("Such test is no longer feasible.")
|
||||||
@ -707,8 +713,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
@unittest.skip("Such test is no longer feasible.")
|
@unittest.skip("Such test is no longer feasible.")
|
||||||
@mock.patch.object(coordination.Coordinator, 'get_lock')
|
@mock.patch.object(coordination.Coordinator, 'get_lock')
|
||||||
@mock.patch('tacker.conductor.conductor_server.LOG')
|
@mock.patch('tacker.conductor.conductor_server.LOG')
|
||||||
def test_heal_vnf_instance_already_not_instantiated(self,
|
def test_heal_vnf_instance_already_not_instantiated(
|
||||||
mock_log, mock_get_lock):
|
self, mock_log, mock_get_lock):
|
||||||
vnf_package_vnfd = self._create_and_upload_vnf_package()
|
vnf_package_vnfd = self._create_and_upload_vnf_package()
|
||||||
vnf_instance_data = fake_obj.get_vnf_instance_data(
|
vnf_instance_data = fake_obj.get_vnf_instance_data(
|
||||||
vnf_package_vnfd.vnfd_id)
|
vnf_package_vnfd.vnfd_id)
|
||||||
@ -728,8 +734,9 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
self.vnflcm_driver.heal_vnf.assert_not_called()
|
self.vnflcm_driver.heal_vnf.assert_not_called()
|
||||||
expected_log = ('Heal action cannot be performed on vnf %(id)s '
|
expected_log = ('Heal action cannot be performed on vnf %(id)s '
|
||||||
'which is in %(state)s state.')
|
'which is in %(state)s state.')
|
||||||
mock_log.error.assert_called_once_with(expected_log,
|
mock_log.error.assert_called_once_with(
|
||||||
{'id': vnf_instance.id,
|
expected_log, {
|
||||||
|
'id': vnf_instance.id,
|
||||||
'state': fields.VnfInstanceState.NOT_INSTANTIATED})
|
'state': fields.VnfInstanceState.NOT_INSTANTIATED})
|
||||||
|
|
||||||
@mock.patch.object(os, 'remove')
|
@mock.patch.object(os, 'remove')
|
||||||
@ -812,7 +819,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
mock_subscriptions_get):
|
mock_subscriptions_get):
|
||||||
self.requests_mock.register_uri('POST',
|
self.requests_mock.register_uri('POST',
|
||||||
"https://localhost/callback",
|
"https://localhost/callback",
|
||||||
headers={'Content-Type': 'application/json'},
|
headers={
|
||||||
|
'Content-Type': 'application/json'},
|
||||||
status_code=204)
|
status_code=204)
|
||||||
|
|
||||||
mock_subscriptions_get.return_value = self._create_subscriptions()
|
mock_subscriptions_get.return_value = self._create_subscriptions()
|
||||||
@ -837,9 +845,11 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
'vnf_lcm_subscriptions_get')
|
'vnf_lcm_subscriptions_get')
|
||||||
def test_sendNotification_vnfIdentifierCreation(self,
|
def test_sendNotification_vnfIdentifierCreation(self,
|
||||||
mock_subscriptions_get):
|
mock_subscriptions_get):
|
||||||
self.requests_mock.register_uri('POST',
|
self.requests_mock.register_uri(
|
||||||
|
'POST',
|
||||||
"https://localhost/callback",
|
"https://localhost/callback",
|
||||||
headers={'Content-Type': 'application/json'},
|
headers={
|
||||||
|
'Content-Type': 'application/json'},
|
||||||
status_code=204)
|
status_code=204)
|
||||||
|
|
||||||
mock_subscriptions_get.return_value = self._create_subscriptions()
|
mock_subscriptions_get.return_value = self._create_subscriptions()
|
||||||
@ -861,9 +871,11 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
@mock.patch.object(objects.LccnSubscriptionRequest,
|
@mock.patch.object(objects.LccnSubscriptionRequest,
|
||||||
'vnf_lcm_subscriptions_get')
|
'vnf_lcm_subscriptions_get')
|
||||||
def test_sendNotification_with_auth_basic(self, mock_subscriptions_get):
|
def test_sendNotification_with_auth_basic(self, mock_subscriptions_get):
|
||||||
self.requests_mock.register_uri('POST',
|
self.requests_mock.register_uri(
|
||||||
|
'POST',
|
||||||
"https://localhost/callback",
|
"https://localhost/callback",
|
||||||
headers={'Content-Type': 'application/json'},
|
headers={
|
||||||
|
'Content-Type': 'application/json'},
|
||||||
status_code=204)
|
status_code=204)
|
||||||
|
|
||||||
auth_user_name = 'test_user'
|
auth_user_name = 'test_user'
|
||||||
@ -897,17 +909,19 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
def test_sendNotification_with_auth_client_credentials(
|
def test_sendNotification_with_auth_client_credentials(
|
||||||
self, mock_subscriptions_get):
|
self, mock_subscriptions_get):
|
||||||
auth.auth_manager = auth._AuthManager()
|
auth.auth_manager = auth._AuthManager()
|
||||||
self.requests_mock.register_uri('POST',
|
self.requests_mock.register_uri(
|
||||||
|
'POST',
|
||||||
"https://localhost/callback",
|
"https://localhost/callback",
|
||||||
headers={'Content-Type': 'application/json'},
|
headers={
|
||||||
|
'Content-Type': 'application/json'},
|
||||||
status_code=204)
|
status_code=204)
|
||||||
|
|
||||||
auth_user_name = 'test_user'
|
auth_user_name = 'test_user'
|
||||||
auth_password = 'test_password'
|
auth_password = 'test_password'
|
||||||
token_endpoint = 'https://oauth2/tokens'
|
token_endpoint = 'https://oauth2/tokens'
|
||||||
self.requests_mock.register_uri('GET',
|
self.requests_mock.register_uri(
|
||||||
token_endpoint,
|
'GET', token_endpoint, json={
|
||||||
json={'access_token': 'test_token', 'token_type': 'bearer'},
|
'access_token': 'test_token', 'token_type': 'bearer'},
|
||||||
headers={'Content-Type': 'application/json'},
|
headers={'Content-Type': 'application/json'},
|
||||||
status_code=200)
|
status_code=200)
|
||||||
|
|
||||||
@ -939,9 +953,11 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
'vnf_lcm_subscriptions_get')
|
'vnf_lcm_subscriptions_get')
|
||||||
def test_sendNotification_retyNotification(self,
|
def test_sendNotification_retyNotification(self,
|
||||||
mock_subscriptions_get):
|
mock_subscriptions_get):
|
||||||
self.requests_mock.register_uri('POST',
|
self.requests_mock.register_uri(
|
||||||
|
'POST',
|
||||||
"https://localhost/callback",
|
"https://localhost/callback",
|
||||||
headers={'Content-Type': 'application/json'},
|
headers={
|
||||||
|
'Content-Type': 'application/json'},
|
||||||
status_code=400)
|
status_code=400)
|
||||||
|
|
||||||
mock_subscriptions_get.return_value = self._create_subscriptions()
|
mock_subscriptions_get.return_value = self._create_subscriptions()
|
||||||
@ -964,7 +980,8 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
'vnf_lcm_subscriptions_get')
|
'vnf_lcm_subscriptions_get')
|
||||||
def test_sendNotification_sendError(self,
|
def test_sendNotification_sendError(self,
|
||||||
mock_subscriptions_get):
|
mock_subscriptions_get):
|
||||||
self.requests_mock.register_uri('POST',
|
self.requests_mock.register_uri(
|
||||||
|
'POST',
|
||||||
"https://localhost/callback",
|
"https://localhost/callback",
|
||||||
exc=requests.exceptions.HTTPError("MockException"))
|
exc=requests.exceptions.HTTPError("MockException"))
|
||||||
|
|
||||||
@ -1019,3 +1036,25 @@ class TestConductor(SqlTestCase, unit_base.FixturedTestCase):
|
|||||||
self.body_data,
|
self.body_data,
|
||||||
self.vnfd_pkg_data,
|
self.vnfd_pkg_data,
|
||||||
vnfd_id)
|
vnfd_id)
|
||||||
|
|
||||||
|
@mock.patch.object(conductor_server, 'revert_update_lcm')
|
||||||
|
@mock.patch.object(t_context.get_admin_context().session, "add")
|
||||||
|
@mock.patch.object(objects.vnf_lcm_op_occs.VnfLcmOpOcc, "save")
|
||||||
|
@mock.patch.object(objects.VnfInstance, "update")
|
||||||
|
@mock.patch.object(objects.vnf_lcm_op_occs.VnfLcmOpOcc, "create")
|
||||||
|
def test_update_lcm_with_vnf_pkg_id(self, mock_create,
|
||||||
|
mock_update, mock_save,
|
||||||
|
mock_add, mock_revert):
|
||||||
|
mock_create.return_value = "OK"
|
||||||
|
mock_update.return_value = datetime.datetime(
|
||||||
|
1900, 1, 1, 1, 1, 1, tzinfo=iso8601.UTC)
|
||||||
|
mock_add.return_value = "OK"
|
||||||
|
mock_save.return_value = "OK"
|
||||||
|
vnfd_id = "2c69a161-0000-4b0f-bcf8-391f8fc76600"
|
||||||
|
|
||||||
|
self.conductor.update(
|
||||||
|
self.context,
|
||||||
|
self.vnf_lcm_opoccs,
|
||||||
|
self.body_data,
|
||||||
|
self.vnfd_pkg_data,
|
||||||
|
vnfd_id)
|
||||||
|
@ -178,6 +178,28 @@ vnf_artifacts = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def fake_vnf_package_vnfd_dict(**updates):
|
||||||
|
vnf_pkg_vnfd = {
|
||||||
|
'package_uuid': uuidsentinel.package_uuid,
|
||||||
|
'vnfd_id': uuidsentinel.vnfd_id,
|
||||||
|
'vnf_provider': 'test vnf provider',
|
||||||
|
'vnf_product_name': 'Sample VNF',
|
||||||
|
'vnf_software_version': '1.0',
|
||||||
|
'vnfd_version': '1.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
if updates:
|
||||||
|
vnf_pkg_vnfd.update(updates)
|
||||||
|
|
||||||
|
return vnf_pkg_vnfd
|
||||||
|
|
||||||
|
|
||||||
|
def return_vnf_package_vnfd_data():
|
||||||
|
model_obj = models.VnfPackageVnfd()
|
||||||
|
model_obj.update(fake_vnf_package_vnfd_dict())
|
||||||
|
return model_obj
|
||||||
|
|
||||||
|
|
||||||
def get_vnf_package_vnfd_data(vnf_package_id, vnfd_id):
|
def get_vnf_package_vnfd_data(vnf_package_id, vnfd_id):
|
||||||
return {
|
return {
|
||||||
'package_uuid': vnf_package_id,
|
'package_uuid': vnf_package_id,
|
||||||
@ -185,6 +207,7 @@ def get_vnf_package_vnfd_data(vnf_package_id, vnfd_id):
|
|||||||
'vnf_provider': 'test vnf provider',
|
'vnf_provider': 'test vnf provider',
|
||||||
'vnf_product_name': 'Sample VNF',
|
'vnf_product_name': 'Sample VNF',
|
||||||
'vnf_software_version': '1.0',
|
'vnf_software_version': '1.0',
|
||||||
|
"vnf_pkg_id": uuidsentinel.vnf_pkg_id,
|
||||||
'vnfd_version': '1.0',
|
'vnfd_version': '1.0',
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +224,7 @@ def get_vnf_instance_data(vnfd_id):
|
|||||||
"vnfd_version": "1.0",
|
"vnfd_version": "1.0",
|
||||||
"tenant_id": uuidsentinel.tenant_id,
|
"tenant_id": uuidsentinel.tenant_id,
|
||||||
"vnf_pkg_id": uuidsentinel.vnf_pkg_id,
|
"vnf_pkg_id": uuidsentinel.vnf_pkg_id,
|
||||||
"vnf_metadata": {"key": "value"}
|
"vnf_metadata": {"key": "value"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -218,7 +241,7 @@ def get_vnf_instance_data_with_id(vnfd_id):
|
|||||||
"vnfd_version": "1.0",
|
"vnfd_version": "1.0",
|
||||||
"tenant_id": uuidsentinel.tenant_id,
|
"tenant_id": uuidsentinel.tenant_id,
|
||||||
"vnf_pkg_id": uuidsentinel.vnf_pkg_id,
|
"vnf_pkg_id": uuidsentinel.vnf_pkg_id,
|
||||||
"vnf_metadata": {"key": "value"}
|
"vnf_metadata": {"key": "value"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -254,9 +277,9 @@ def fake_vnf_instance_model_dict(**updates):
|
|||||||
'instantiation_state': 'NOT_INSTANTIATED',
|
'instantiation_state': 'NOT_INSTANTIATED',
|
||||||
'vim_connection_info': [],
|
'vim_connection_info': [],
|
||||||
'tenant_id': '33f8dbdae36142eebf214c1869eb4e4c',
|
'tenant_id': '33f8dbdae36142eebf214c1869eb4e4c',
|
||||||
'id': constants.UUID,
|
|
||||||
'vnf_pkg_id': uuidsentinel.vnf_pkg_id,
|
'vnf_pkg_id': uuidsentinel.vnf_pkg_id,
|
||||||
'vnf_metadata': {'key': 'value'}
|
'id': constants.UUID,
|
||||||
|
'vnf_metadata': {"key": "value"},
|
||||||
}
|
}
|
||||||
|
|
||||||
if updates:
|
if updates:
|
||||||
@ -454,7 +477,7 @@ def vnf_instance_model_object(vnf_instance):
|
|||||||
'tenant_id': vnf_instance.tenant_id,
|
'tenant_id': vnf_instance.tenant_id,
|
||||||
'created_at': vnf_instance.created_at,
|
'created_at': vnf_instance.created_at,
|
||||||
'vnf_pkg_id': vnf_instance.vnf_pkg_id,
|
'vnf_pkg_id': vnf_instance.vnf_pkg_id,
|
||||||
'vnf_metadata': vnf_instance.vnf_metadata
|
'vnf_metadata': vnf_instance.vnf_metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
vnf_instance_db_obj = models.VnfInstance()
|
vnf_instance_db_obj = models.VnfInstance()
|
||||||
|
@ -13,16 +13,17 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import ddt
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from tacker.common import exceptions
|
from tacker.common import exceptions
|
||||||
from tacker import context
|
from tacker import context
|
||||||
from tacker.db import api as sqlalchemy_api
|
from tacker.db import api as sqlalchemy_api
|
||||||
from tacker.db.db_sqlalchemy import api
|
|
||||||
from tacker.db.nfvo import nfvo_db
|
from tacker.db.nfvo import nfvo_db
|
||||||
from tacker import objects
|
from tacker import objects
|
||||||
from tacker.tests.unit.db.base import SqlTestCase
|
from tacker.tests.unit.db.base import SqlTestCase
|
||||||
from tacker.tests.unit.objects import fakes
|
from tacker.tests.unit.objects import fakes
|
||||||
|
from tacker.tests.unit.vnflcm import fakes as fakes_vnflcm
|
||||||
from tacker.tests import uuidsentinel
|
from tacker.tests import uuidsentinel
|
||||||
|
|
||||||
get_engine = sqlalchemy_api.get_engine
|
get_engine = sqlalchemy_api.get_engine
|
||||||
@ -54,6 +55,7 @@ class FakeApiModelQuery:
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
class TestVnfInstance(SqlTestCase):
|
class TestVnfInstance(SqlTestCase):
|
||||||
|
|
||||||
maxDiff = None
|
maxDiff = None
|
||||||
@ -65,8 +67,12 @@ class TestVnfInstance(SqlTestCase):
|
|||||||
self.vims = nfvo_db.Vim(**fakes.vim_data)
|
self.vims = nfvo_db.Vim(**fakes.vim_data)
|
||||||
self.engine = get_engine()
|
self.engine = get_engine()
|
||||||
self.conn = self.engine.connect()
|
self.conn = self.engine.connect()
|
||||||
|
self.body_data = self._create_body_data()
|
||||||
|
self.vnfd_pkg_data = self._create_vnfd_pkg_data()
|
||||||
|
self.vim = nfvo_db.Vim()
|
||||||
|
|
||||||
def _create_and_upload_vnf_package(self):
|
@mock.patch.object(objects.VnfPackageVnfd, 'create')
|
||||||
|
def _create_and_upload_vnf_package(self, mock_create):
|
||||||
vnf_package = objects.VnfPackage(context=self.context,
|
vnf_package = objects.VnfPackage(context=self.context,
|
||||||
**fakes.vnf_package_data)
|
**fakes.vnf_package_data)
|
||||||
vnf_package.create()
|
vnf_package.create()
|
||||||
@ -74,6 +80,7 @@ class TestVnfInstance(SqlTestCase):
|
|||||||
vnf_pack_vnfd = fakes.get_vnf_package_vnfd_data(
|
vnf_pack_vnfd = fakes.get_vnf_package_vnfd_data(
|
||||||
vnf_package.id, uuidsentinel.vnfd_id)
|
vnf_package.id, uuidsentinel.vnfd_id)
|
||||||
|
|
||||||
|
mock_create.return_value = fakes.return_vnf_package_vnfd_data()
|
||||||
vnf_pack_vnfd_obj = objects.VnfPackageVnfd(
|
vnf_pack_vnfd_obj = objects.VnfPackageVnfd(
|
||||||
context=self.context, **vnf_pack_vnfd)
|
context=self.context, **vnf_pack_vnfd)
|
||||||
vnf_pack_vnfd_obj.create()
|
vnf_pack_vnfd_obj.create()
|
||||||
@ -83,6 +90,32 @@ class TestVnfInstance(SqlTestCase):
|
|||||||
|
|
||||||
return vnf_pack_vnfd_obj
|
return vnf_pack_vnfd_obj
|
||||||
|
|
||||||
|
def _create_body_data(self):
|
||||||
|
body_data = {}
|
||||||
|
body_data['vnf_instance_name'] = "new_instance_name"
|
||||||
|
body_data['vnf_instance_description'] = "new_instance_discription"
|
||||||
|
body_data['vnfd_id'] = "2c69a161-0000-4b0f-bcf8-391f8fc76600"
|
||||||
|
body_data['vnf_configurable_properties'] = {"test": "test_value"}
|
||||||
|
body_data['vnfc_info_modifications_delete_ids'] = ["test1"]
|
||||||
|
body_data['vnf_pkg_id'] = uuidsentinel.vnf_pkg_id
|
||||||
|
return body_data
|
||||||
|
|
||||||
|
def _create_vnfd_pkg_data(self):
|
||||||
|
vnfd_pkg_data = {}
|
||||||
|
vnfd_pkg_data['vnf_provider'] =\
|
||||||
|
fakes.return_vnf_package_vnfd_data().get('vnf_provider')
|
||||||
|
vnfd_pkg_data['vnf_product_name'] =\
|
||||||
|
fakes.return_vnf_package_vnfd_data().get('vnf_product_name')
|
||||||
|
vnfd_pkg_data['vnf_software_version'] =\
|
||||||
|
fakes.return_vnf_package_vnfd_data().get('vnf_software_version')
|
||||||
|
vnfd_pkg_data['vnfd_version'] =\
|
||||||
|
fakes.return_vnf_package_vnfd_data().get('vnfd_version')
|
||||||
|
vnfd_pkg_data['package_uuid'] =\
|
||||||
|
fakes.return_vnf_package_vnfd_data().get('package_uuid')
|
||||||
|
vnfd_pkg_data['vnfd_id'] =\
|
||||||
|
fakes.return_vnf_package_vnfd_data().get('vnfd_id')
|
||||||
|
return vnfd_pkg_data
|
||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
vnf_instance_data = fakes.get_vnf_instance_data(
|
vnf_instance_data = fakes.get_vnf_instance_data(
|
||||||
self.vnf_package.vnfd_id)
|
self.vnf_package.vnfd_id)
|
||||||
@ -189,155 +222,21 @@ class TestVnfInstance(SqlTestCase):
|
|||||||
self.assertRaises(exceptions.ObjectActionError,
|
self.assertRaises(exceptions.ObjectActionError,
|
||||||
vnf_instance_obj.destroy, self.context)
|
vnf_instance_obj.destroy, self.context)
|
||||||
|
|
||||||
@mock.patch('tacker.objects.vnf_instance._get_vnf_instance')
|
@mock.patch.object(objects.vnf_package.VnfPackage, 'get_by_id')
|
||||||
@mock.patch('tacker.objects.vnf_package.VnfPackage.get_by_id')
|
def test_update(self, mock_get_by_id):
|
||||||
@mock.patch.object(api, 'model_query')
|
mock_get_by_id.return_value =\
|
||||||
def test_update_vnf_instances(
|
fakes_vnflcm.return_vnf_package_with_deployment_flavour()
|
||||||
self,
|
vnf_instance_data = fakes.get_vnf_instance_data(
|
||||||
mock_model_query,
|
self.vnf_package.vnfd_id)
|
||||||
mock_get_vnf_package,
|
vnf_instance = objects.VnfInstance(context=self.context,
|
||||||
mock_get_vnf):
|
**vnf_instance_data)
|
||||||
|
vnf_instance.create()
|
||||||
vnf_instance_data = fakes.fake_vnf_instance_model_dict(**{
|
vnf_lcm_oppccs = fakes.get_lcm_op_occs_data(
|
||||||
"vim_connection_info": [
|
vnf_instance.id)
|
||||||
objects.VimConnectionInfo._from_dict({
|
|
||||||
"id": "testid",
|
|
||||||
"vim_id": "aaa",
|
|
||||||
"vim_type": "openstack-1",
|
|
||||||
"interface_info": {"endpoint": "endpoint"},
|
|
||||||
"access_info": {"username": "xxxxx",
|
|
||||||
"region": "region",
|
|
||||||
"password": "password",
|
|
||||||
"tenant": "tenant"}}),
|
|
||||||
objects.VimConnectionInfo._from_dict({
|
|
||||||
"id": "testid3",
|
|
||||||
"vim_id": "ccc",
|
|
||||||
"vim_type": "openstack-2",
|
|
||||||
"interface_info": {"endpoint": "endpoint22"},
|
|
||||||
"access_info": {"username": "xxxxx",
|
|
||||||
"region": "region",
|
|
||||||
"password": "password"}}),
|
|
||||||
objects.VimConnectionInfo._from_dict({
|
|
||||||
"id": "testid5",
|
|
||||||
"vim_id": "eee",
|
|
||||||
"vim_type": "openstack-4"})
|
|
||||||
],
|
|
||||||
"vnf_metadata": {"testkey": "test_value"}})
|
|
||||||
vnf_instance = objects.VnfInstance(
|
|
||||||
context=self.context, **vnf_instance_data)
|
|
||||||
mock_get_vnf.return_value = \
|
|
||||||
fakes.vnf_instance_model_object(vnf_instance)
|
|
||||||
|
|
||||||
def mock_filter(id=None):
|
|
||||||
print('### mock_filter ###', id)
|
|
||||||
|
|
||||||
def mock_update(updated_values, synchronize_session=False):
|
|
||||||
print('### mock_update ###', updated_values)
|
|
||||||
|
|
||||||
if 'vim_connection_info' not in updated_values:
|
|
||||||
return
|
|
||||||
|
|
||||||
compar_updated_values = {}
|
|
||||||
compar_updated_values['vnf_instance_name'] = "new_instance_name"
|
|
||||||
compar_updated_values['vnf_instance_description'] = \
|
|
||||||
"new_instance_discription"
|
|
||||||
compar_updated_values['vnf_metadata'] = {
|
|
||||||
"testkey": "test_value1", "testkey2": "test_value2"}
|
|
||||||
compar_updated_values['vim_connection_info'] = [
|
|
||||||
objects.VimConnectionInfo._from_dict({
|
|
||||||
"id": "testid",
|
|
||||||
"vim_id": "bbb",
|
|
||||||
"vim_type": "openstack-1A",
|
|
||||||
"interface_info": {"endpoint": "endpoint11"},
|
|
||||||
"access_info": {"username": "xxxxx1",
|
|
||||||
"region": "region1",
|
|
||||||
"password": "password1",
|
|
||||||
"tenant": "tenant1"}}),
|
|
||||||
objects.VimConnectionInfo._from_dict({
|
|
||||||
"id": "testid3",
|
|
||||||
"vim_id": "ccc",
|
|
||||||
"vim_type": "openstack-2",
|
|
||||||
"interface_info": {"endpoint": "endpoint22"},
|
|
||||||
"access_info": {"username": "xxxxx",
|
|
||||||
"region": "region",
|
|
||||||
"password": "password2",
|
|
||||||
"tenant": "tenant2"}}),
|
|
||||||
objects.VimConnectionInfo._from_dict({
|
|
||||||
"id": "testid5",
|
|
||||||
"vim_id": "eee",
|
|
||||||
"vim_type": "openstack-4"}),
|
|
||||||
objects.VimConnectionInfo._from_dict({
|
|
||||||
"id": "testid7",
|
|
||||||
"vim_id": "fff",
|
|
||||||
"vim_type": "openstack-5A",
|
|
||||||
"interface_info": {"endpoint": "endpoint55"},
|
|
||||||
"access_info": {"username": "xxxxx5",
|
|
||||||
"region": "region5",
|
|
||||||
"password": "password5",
|
|
||||||
"tenant": "tenant5"}})
|
|
||||||
]
|
|
||||||
compar_updated_values['vnfd_id'] = \
|
|
||||||
"2c69a161-0000-4b0f-bcf8-391f8fc76600"
|
|
||||||
compar_updated_values['vnf_provider'] = \
|
|
||||||
self.vnf_package.get('vnf_provider')
|
|
||||||
compar_updated_values['vnf_product_name'] = \
|
|
||||||
self.vnf_package.get('vnf_product_name')
|
|
||||||
compar_updated_values['vnf_software_version'] = \
|
|
||||||
self.vnf_package.get('vnf_software_version')
|
|
||||||
|
|
||||||
expected_vci = sorted(compar_updated_values.pop(
|
|
||||||
'vim_connection_info'), key=lambda x: x.id)
|
|
||||||
actual_vci = sorted(
|
|
||||||
updated_values.pop('vim_connection_info'),
|
|
||||||
key=lambda x: x.id)
|
|
||||||
for e, a in zip(expected_vci, actual_vci):
|
|
||||||
self.assertDictEqual(
|
|
||||||
e.to_dict(),
|
|
||||||
a.to_dict())
|
|
||||||
|
|
||||||
self.assertDictEqual(
|
|
||||||
compar_updated_values,
|
|
||||||
updated_values)
|
|
||||||
|
|
||||||
fake_api_model_query = FakeApiModelQuery(
|
|
||||||
callback_filter_by=mock_filter, callback_update=mock_update)
|
|
||||||
mock_model_query.return_value = fake_api_model_query
|
|
||||||
|
|
||||||
vnf_lcm_opoccs = {}
|
|
||||||
|
|
||||||
body = {"vnf_instance_name": "new_instance_name",
|
|
||||||
"vnf_instance_description": "new_instance_discription",
|
|
||||||
"vnfd_id": "2c69a161-0000-4b0f-bcf8-391f8fc76600",
|
|
||||||
"vnf_configurable_properties": {"test": "test_value1"},
|
|
||||||
"vnfc_info_modifications_delete_ids": ["test1"],
|
|
||||||
"metadata": {"testkey": "test_value1",
|
|
||||||
"testkey2": "test_value2"},
|
|
||||||
"vim_connection_info": [
|
|
||||||
{"id": "testid",
|
|
||||||
"vim_id": "bbb",
|
|
||||||
"vim_type": "openstack-1A",
|
|
||||||
"interface_info": {"endpoint": "endpoint11"},
|
|
||||||
"access_info": {"username": "xxxxx1",
|
|
||||||
"region": "region1",
|
|
||||||
"password": "password1",
|
|
||||||
"tenant": "tenant1"}},
|
|
||||||
{"id": "testid3",
|
|
||||||
"vim_type": "openstack-2",
|
|
||||||
"access_info": {"password": "password2",
|
|
||||||
"tenant": "tenant2"}},
|
|
||||||
{"id": "testid7",
|
|
||||||
"vim_id": "fff",
|
|
||||||
"vim_type": "openstack-5A",
|
|
||||||
"interface_info": {"endpoint": "endpoint55"},
|
|
||||||
"access_info": {"username": "xxxxx5",
|
|
||||||
"region": "region5",
|
|
||||||
"password": "password5",
|
|
||||||
"tenant": "tenant5"}},
|
|
||||||
]}
|
|
||||||
|
|
||||||
vnf_instance.update(
|
vnf_instance.update(
|
||||||
self.context,
|
self.context,
|
||||||
vnf_lcm_opoccs,
|
vnf_lcm_oppccs,
|
||||||
body,
|
self.body_data,
|
||||||
self.vnf_package,
|
self.vnfd_pkg_data,
|
||||||
self.vnf_package.id)
|
vnf_instance_data['vnfd_id'])
|
||||||
|
@ -120,6 +120,7 @@ def _model_non_instantiated_vnf_instance(**updates):
|
|||||||
'tenant_id': uuidsentinel.tenant_id,
|
'tenant_id': uuidsentinel.tenant_id,
|
||||||
'vnfd_id': uuidsentinel.vnfd_id,
|
'vnfd_id': uuidsentinel.vnfd_id,
|
||||||
'vnfd_version': '1.0',
|
'vnfd_version': '1.0',
|
||||||
|
'vnf_pkg_id': uuidsentinel.vnf_pkg_id,
|
||||||
'vnf_metadata': {"key": "value"}}
|
'vnf_metadata': {"key": "value"}}
|
||||||
|
|
||||||
if updates:
|
if updates:
|
||||||
@ -218,13 +219,15 @@ def _fake_vnf_instance_not_instantiated_response(
|
|||||||
'vnfInstanceName': 'Vnf instance name',
|
'vnfInstanceName': 'Vnf instance name',
|
||||||
'vnfProductName': 'Sample VNF',
|
'vnfProductName': 'Sample VNF',
|
||||||
'_links': {
|
'_links': {
|
||||||
'self': {'href': os.path.join('/vnflcm/v1/vnf_instances/',
|
'self': {
|
||||||
|
'href': os.path.join(
|
||||||
|
'/vnflcm/v1/vnf_instances/',
|
||||||
uuidsentinel.vnf_instance_id)},
|
uuidsentinel.vnf_instance_id)},
|
||||||
'instantiate': {
|
'instantiate': {
|
||||||
'href': os.path.join('/vnflcm/v1/vnf_instances',
|
'href': os.path.join(
|
||||||
uuidsentinel.vnf_instance_id, 'instantiate')
|
'/vnflcm/v1/vnf_instances',
|
||||||
}
|
uuidsentinel.vnf_instance_id,
|
||||||
},
|
'instantiate')}},
|
||||||
'instantiationState': 'NOT_INSTANTIATED',
|
'instantiationState': 'NOT_INSTANTIATED',
|
||||||
'vnfProvider': 'Vnf provider',
|
'vnfProvider': 'Vnf provider',
|
||||||
'vnfdId': uuidsentinel.vnfd_id,
|
'vnfdId': uuidsentinel.vnfd_id,
|
||||||
|
@ -310,8 +310,10 @@ class TestController(base.TestCase):
|
|||||||
'expected_type': 'description'}
|
'expected_type': 'description'}
|
||||||
)
|
)
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
def test_create_with_invalid_request_body(
|
def test_create_with_invalid_request_body(
|
||||||
self, attribute, value, expected_type):
|
self, mock_get_service_plugins, attribute, value, expected_type):
|
||||||
"""value of attribute in body is of invalid type"""
|
"""value of attribute in body is of invalid type"""
|
||||||
body = {"vnfInstanceName": "SampleVnf",
|
body = {"vnfInstanceName": "SampleVnf",
|
||||||
"vnfdId": "29c770a3-02bc-4dfc-b4be-eb173ac00567",
|
"vnfdId": "29c770a3-02bc-4dfc-b4be-eb173ac00567",
|
||||||
@ -500,8 +502,11 @@ class TestController(base.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(http_client.BAD_REQUEST, resp.status_code)
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code)
|
||||||
|
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@ddt.data('PATCH', 'PUT', 'HEAD', 'DELETE')
|
@ddt.data('PATCH', 'PUT', 'HEAD', 'DELETE')
|
||||||
def test_create_not_allowed_http_method(self, method):
|
def test_create_not_allowed_http_method(self, method,
|
||||||
|
mock_get_service_plugins):
|
||||||
"""Wrong HTTP method"""
|
"""Wrong HTTP method"""
|
||||||
body = {"vnfdId": uuidsentinel.vnfd_id}
|
body = {"vnfdId": uuidsentinel.vnfd_id}
|
||||||
req = fake_request.HTTPRequest.blank('/vnf_instances')
|
req = fake_request.HTTPRequest.blank('/vnf_instances')
|
||||||
@ -942,8 +947,8 @@ class TestController(base.TestCase):
|
|||||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||||
'VnfLcmController._get_vnf')
|
'VnfLcmController._get_vnf')
|
||||||
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
||||||
def test_instantiate_incorrect_instantiation_state(self, mock_vnf_by_id,
|
def test_instantiate_incorrect_instantiation_state(
|
||||||
mock_get_vnf, mock_get_service_plugins):
|
self, mock_vnf_by_id, mock_get_vnf, mock_get_service_plugins):
|
||||||
vnf_instance = fakes.return_vnf_instance_model()
|
vnf_instance = fakes.return_vnf_instance_model()
|
||||||
vnf_instance.instantiation_state = 'INSTANTIATED'
|
vnf_instance.instantiation_state = 'INSTANTIATED'
|
||||||
mock_vnf_by_id.return_value = vnf_instance
|
mock_vnf_by_id.return_value = vnf_instance
|
||||||
@ -964,8 +969,11 @@ class TestController(base.TestCase):
|
|||||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||||
'VnfLcmController._get_vnf')
|
'VnfLcmController._get_vnf')
|
||||||
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
||||||
def test_instantiate_incorrect_task_state(self, mock_vnf_by_id,
|
def test_instantiate_incorrect_task_state(
|
||||||
mock_get_vnf, mock_get_service_plugins):
|
self,
|
||||||
|
mock_vnf_by_id,
|
||||||
|
mock_get_vnf,
|
||||||
|
mock_get_service_plugins):
|
||||||
vnf_instance = fakes.return_vnf_instance_model(
|
vnf_instance = fakes.return_vnf_instance_model(
|
||||||
task_state=fields.VnfInstanceTaskState.INSTANTIATING)
|
task_state=fields.VnfInstanceTaskState.INSTANTIATING)
|
||||||
mock_vnf_by_id.return_value = vnf_instance
|
mock_vnf_by_id.return_value = vnf_instance
|
||||||
@ -1001,8 +1009,10 @@ class TestController(base.TestCase):
|
|||||||
'expected_type': 'object'},
|
'expected_type': 'object'},
|
||||||
)
|
)
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
def test_instantiate_with_invalid_request_body(
|
def test_instantiate_with_invalid_request_body(
|
||||||
self, attribute, value, expected_type):
|
self, mock_get_service_plugins, attribute, value, expected_type):
|
||||||
body = fakes.get_vnf_instantiation_request_body()
|
body = fakes.get_vnf_instantiation_request_body()
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id)
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id)
|
||||||
@ -1023,7 +1033,10 @@ class TestController(base.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(expected_message, exception.msg)
|
self.assertEqual(expected_message, exception.msg)
|
||||||
|
|
||||||
def test_instantiate_without_flavour_id(self):
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
|
def test_instantiate_without_flavour_id(self,
|
||||||
|
mock_get_service_plugins):
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id)
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id)
|
||||||
req.body = jsonutils.dump_as_bytes({})
|
req.body = jsonutils.dump_as_bytes({})
|
||||||
@ -1037,7 +1050,10 @@ class TestController(base.TestCase):
|
|||||||
self.assertEqual("'flavourId' is a required property",
|
self.assertEqual("'flavourId' is a required property",
|
||||||
resp.json['badRequest']['message'])
|
resp.json['badRequest']['message'])
|
||||||
|
|
||||||
def test_instantiate_invalid_request_parameter(self):
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
|
def test_instantiate_invalid_request_parameter(self,
|
||||||
|
mock_get_service_plugins):
|
||||||
body = {"flavourId": "simple"}
|
body = {"flavourId": "simple"}
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id)
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id)
|
||||||
@ -1058,7 +1074,10 @@ class TestController(base.TestCase):
|
|||||||
"('additional_property' was unexpected)",
|
"('additional_property' was unexpected)",
|
||||||
resp.json['badRequest']['message'])
|
resp.json['badRequest']['message'])
|
||||||
|
|
||||||
def test_instantiate_with_invalid_uuid(self):
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
|
def test_instantiate_with_invalid_uuid(self,
|
||||||
|
mock_get_service_plugins):
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s/instantiate' % constants.INVALID_UUID)
|
'/vnf_instances/%s/instantiate' % constants.INVALID_UUID)
|
||||||
body = {"flavourId": "simple"}
|
body = {"flavourId": "simple"}
|
||||||
@ -1099,8 +1118,11 @@ class TestController(base.TestCase):
|
|||||||
resp.json['itemNotFound']['message'])
|
resp.json['itemNotFound']['message'])
|
||||||
mock_get_vnf.assert_called_once()
|
mock_get_vnf.assert_called_once()
|
||||||
|
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@ddt.data('HEAD', 'PUT', 'DELETE', 'PATCH', 'GET')
|
@ddt.data('HEAD', 'PUT', 'DELETE', 'PATCH', 'GET')
|
||||||
def test_instantiate_invalid_http_method(self, method):
|
def test_instantiate_invalid_http_method(self, method,
|
||||||
|
mock_get_service_plugins):
|
||||||
# Wrong HTTP method
|
# Wrong HTTP method
|
||||||
body = fakes.get_vnf_instantiation_request_body()
|
body = fakes.get_vnf_instantiation_request_body()
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
@ -1120,8 +1142,11 @@ class TestController(base.TestCase):
|
|||||||
res_dict = self.controller.show(req, uuidsentinel.instance_id)
|
res_dict = self.controller.show(req, uuidsentinel.instance_id)
|
||||||
self.assertEqual(expected_result, res_dict)
|
self.assertEqual(expected_result, res_dict)
|
||||||
|
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||||
def test_show_vnf_instantiated(self, mock_vnf_by_id):
|
def test_show_vnf_instantiated(self, mock_vnf_by_id,
|
||||||
|
mock_get_service_plugins):
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s' % uuidsentinel.instance_id)
|
'/vnf_instances/%s' % uuidsentinel.instance_id)
|
||||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance(
|
mock_vnf_by_id.return_value = fakes.return_vnf_instance(
|
||||||
@ -1131,8 +1156,11 @@ class TestController(base.TestCase):
|
|||||||
res_dict = self.controller.show(req, uuidsentinel.instance_id)
|
res_dict = self.controller.show(req, uuidsentinel.instance_id)
|
||||||
self.assertEqual(expected_result, res_dict)
|
self.assertEqual(expected_result, res_dict)
|
||||||
|
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
||||||
def test_show_with_non_existing_vnf_instance(self, mock_vnf_by_id):
|
def test_show_with_non_existing_vnf_instance(self, mock_vnf_by_id,
|
||||||
|
mock_get_service_plugins):
|
||||||
mock_vnf_by_id.side_effect = exceptions.VnfInstanceNotFound
|
mock_vnf_by_id.side_effect = exceptions.VnfInstanceNotFound
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id)
|
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id)
|
||||||
@ -1241,7 +1269,10 @@ class TestController(base.TestCase):
|
|||||||
req, constants.UUID, body=body)
|
req, constants.UUID, body=body)
|
||||||
self.assertIn(expected_message, exception.msg)
|
self.assertIn(expected_message, exception.msg)
|
||||||
|
|
||||||
def test_terminate_missing_termination_type(self):
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
|
def test_terminate_missing_termination_type(self,
|
||||||
|
mock_get_service_plugins):
|
||||||
body = {'gracefulTerminationTimeout': 10}
|
body = {'gracefulTerminationTimeout': 10}
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s/terminate' % uuidsentinel.vnf_instance_id)
|
'/vnf_instances/%s/terminate' % uuidsentinel.vnf_instance_id)
|
||||||
@ -1255,8 +1286,11 @@ class TestController(base.TestCase):
|
|||||||
self.assertEqual("'terminationType' is a required property",
|
self.assertEqual("'terminationType' is a required property",
|
||||||
resp.json['badRequest']['message'])
|
resp.json['badRequest']['message'])
|
||||||
|
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@ddt.data('GET', 'HEAD', 'PUT', 'DELETE', 'PATCH')
|
@ddt.data('GET', 'HEAD', 'PUT', 'DELETE', 'PATCH')
|
||||||
def test_terminate_invalid_http_method(self, method):
|
def test_terminate_invalid_http_method(self, method,
|
||||||
|
mock_get_service_plugins):
|
||||||
# Wrong HTTP method
|
# Wrong HTTP method
|
||||||
body = {'terminationType': 'GRACEFUL',
|
body = {'terminationType': 'GRACEFUL',
|
||||||
'gracefulTerminationTimeout': 10}
|
'gracefulTerminationTimeout': 10}
|
||||||
@ -1273,8 +1307,8 @@ class TestController(base.TestCase):
|
|||||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||||
'VnfLcmController._get_vnf')
|
'VnfLcmController._get_vnf')
|
||||||
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
||||||
def test_terminate_non_existing_vnf_instance(self, mock_vnf_by_id,
|
def test_terminate_non_existing_vnf_instance(
|
||||||
mock_get_vnf, mock_get_service_plugins):
|
self, mock_vnf_by_id, mock_get_vnf, mock_get_service_plugins):
|
||||||
body = {'terminationType': 'GRACEFUL',
|
body = {'terminationType': 'GRACEFUL',
|
||||||
'gracefulTerminationTimeout': 10}
|
'gracefulTerminationTimeout': 10}
|
||||||
mock_vnf_by_id.side_effect = exceptions.VnfInstanceNotFound
|
mock_vnf_by_id.side_effect = exceptions.VnfInstanceNotFound
|
||||||
@ -1297,8 +1331,8 @@ class TestController(base.TestCase):
|
|||||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||||
'VnfLcmController._get_vnf')
|
'VnfLcmController._get_vnf')
|
||||||
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
||||||
def test_terminate_incorrect_instantiation_state(self, mock_vnf_by_id,
|
def test_terminate_incorrect_instantiation_state(
|
||||||
mock_get_vnf, mock_get_service_plugins):
|
self, mock_vnf_by_id, mock_get_vnf, mock_get_service_plugins):
|
||||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance()
|
mock_vnf_by_id.return_value = fakes.return_vnf_instance()
|
||||||
body = {"terminationType": "FORCEFUL"}
|
body = {"terminationType": "FORCEFUL"}
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
@ -1322,8 +1356,11 @@ class TestController(base.TestCase):
|
|||||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||||
'VnfLcmController._get_vnf')
|
'VnfLcmController._get_vnf')
|
||||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||||
def test_terminate_incorrect_task_state(self, mock_vnf_by_id,
|
def test_terminate_incorrect_task_state(
|
||||||
mock_get_vnf, mock_get_service_plugins):
|
self,
|
||||||
|
mock_vnf_by_id,
|
||||||
|
mock_get_vnf,
|
||||||
|
mock_get_service_plugins):
|
||||||
vnf_instance = fakes.return_vnf_instance(
|
vnf_instance = fakes.return_vnf_instance(
|
||||||
instantiated_state=fields.VnfInstanceState.INSTANTIATED,
|
instantiated_state=fields.VnfInstanceState.INSTANTIATED,
|
||||||
task_state=fields.VnfInstanceTaskState.TERMINATING)
|
task_state=fields.VnfInstanceTaskState.TERMINATING)
|
||||||
@ -1376,7 +1413,10 @@ class TestController(base.TestCase):
|
|||||||
self.assertEqual(http_client.ACCEPTED, resp.status_code)
|
self.assertEqual(http_client.ACCEPTED, resp.status_code)
|
||||||
mock_rpc_heal.assert_called_once()
|
mock_rpc_heal.assert_called_once()
|
||||||
|
|
||||||
def test_heal_cause_max_length_exceeded(self):
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
|
def test_heal_cause_max_length_exceeded(self,
|
||||||
|
mock_get_service_plugins):
|
||||||
body = {'cause': 'A' * 256}
|
body = {'cause': 'A' * 256}
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s/heal' % uuidsentinel.vnf_instance_id)
|
'/vnf_instances/%s/heal' % uuidsentinel.vnf_instance_id)
|
||||||
@ -1394,8 +1434,12 @@ class TestController(base.TestCase):
|
|||||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||||
'VnfLcmController._get_vnf')
|
'VnfLcmController._get_vnf')
|
||||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||||
def test_heal_incorrect_instantiated_state(self, mock_vnf_by_id,
|
def test_heal_incorrect_instantiated_state(
|
||||||
mock_get_vnf, mock_notif, mock_get_service_plugins):
|
self,
|
||||||
|
mock_vnf_by_id,
|
||||||
|
mock_get_vnf,
|
||||||
|
mock_notif,
|
||||||
|
mock_get_service_plugins):
|
||||||
vnf_instance_obj = fakes.return_vnf_instance(
|
vnf_instance_obj = fakes.return_vnf_instance(
|
||||||
fields.VnfInstanceState.NOT_INSTANTIATED)
|
fields.VnfInstanceState.NOT_INSTANTIATED)
|
||||||
mock_vnf_by_id.return_value = vnf_instance_obj
|
mock_vnf_by_id.return_value = vnf_instance_obj
|
||||||
@ -1451,8 +1495,12 @@ class TestController(base.TestCase):
|
|||||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||||
'VnfLcmController._get_vnf')
|
'VnfLcmController._get_vnf')
|
||||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||||
def test_heal_with_invalid_vnfc_id(self, mock_vnf_by_id,
|
def test_heal_with_invalid_vnfc_id(
|
||||||
mock_get_vnf, mock_notif, mock_get_service_plugins):
|
self,
|
||||||
|
mock_vnf_by_id,
|
||||||
|
mock_get_vnf,
|
||||||
|
mock_notif,
|
||||||
|
mock_get_service_plugins):
|
||||||
vnf_instance_obj = fakes.return_vnf_instance(
|
vnf_instance_obj = fakes.return_vnf_instance(
|
||||||
fields.VnfInstanceState.INSTANTIATED)
|
fields.VnfInstanceState.INSTANTIATED)
|
||||||
mock_vnf_by_id.return_value = vnf_instance_obj
|
mock_vnf_by_id.return_value = vnf_instance_obj
|
||||||
@ -1473,8 +1521,11 @@ class TestController(base.TestCase):
|
|||||||
uuidsentinel.vnf_instance_id),
|
uuidsentinel.vnf_instance_id),
|
||||||
resp.json['badRequest']['message'])
|
resp.json['badRequest']['message'])
|
||||||
|
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@ddt.data('HEAD', 'PUT', 'DELETE', 'PATCH', 'GET')
|
@ddt.data('HEAD', 'PUT', 'DELETE', 'PATCH', 'GET')
|
||||||
def test_heal_invalid_http_method(self, method):
|
def test_heal_invalid_http_method(self, method,
|
||||||
|
mock_get_service_plugins):
|
||||||
body = {}
|
body = {}
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s/heal' % uuidsentinel.vnf_instance_id)
|
'/vnf_instances/%s/heal' % uuidsentinel.vnf_instance_id)
|
||||||
@ -1496,8 +1547,10 @@ class TestController(base.TestCase):
|
|||||||
'expected_type': 'array'},
|
'expected_type': 'array'},
|
||||||
)
|
)
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
def test_heal_with_invalid_request_body(
|
def test_heal_with_invalid_request_body(
|
||||||
self, attribute, value, expected_type):
|
self, mock_get_service_plugins, attribute, value, expected_type):
|
||||||
body = {}
|
body = {}
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/29c770a3-02bc-4dfc-b4be-eb173ac00567/heal')
|
'/vnf_instances/29c770a3-02bc-4dfc-b4be-eb173ac00567/heal')
|
||||||
@ -1537,8 +1590,11 @@ class TestController(base.TestCase):
|
|||||||
resp = self.controller.index(req)
|
resp = self.controller.index(req)
|
||||||
self.assertEqual([], resp)
|
self.assertEqual([], resp)
|
||||||
|
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@ddt.data('HEAD', 'PUT', 'DELETE', 'PATCH')
|
@ddt.data('HEAD', 'PUT', 'DELETE', 'PATCH')
|
||||||
def test_index_invalid_http_method(self, method):
|
def test_index_invalid_http_method(self, method,
|
||||||
|
mock_get_service_plugins):
|
||||||
# Wrong HTTP method
|
# Wrong HTTP method
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances')
|
'/vnf_instances')
|
||||||
@ -1566,8 +1622,11 @@ class TestController(base.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(http_client.NO_CONTENT, resp.status_code)
|
self.assertEqual(http_client.NO_CONTENT, resp.status_code)
|
||||||
|
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||||
def test_delete_with_non_existing_vnf_instance(self, mock_vnf_by_id):
|
def test_delete_with_non_existing_vnf_instance(self, mock_vnf_by_id,
|
||||||
|
mock_get_service_plugins):
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id)
|
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id)
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
@ -1582,7 +1641,9 @@ class TestController(base.TestCase):
|
|||||||
uuidsentinel.vnf_instance_id,
|
uuidsentinel.vnf_instance_id,
|
||||||
resp.json['itemNotFound']['message'])
|
resp.json['itemNotFound']['message'])
|
||||||
|
|
||||||
def test_delete_with_invalid_uuid(self):
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
|
def test_delete_with_invalid_uuid(self, mock_get_service_plugins):
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s' % constants.INVALID_UUID)
|
'/vnf_instances/%s' % constants.INVALID_UUID)
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
@ -1595,8 +1656,11 @@ class TestController(base.TestCase):
|
|||||||
constants.INVALID_UUID,
|
constants.INVALID_UUID,
|
||||||
resp.json['itemNotFound']['message'])
|
resp.json['itemNotFound']['message'])
|
||||||
|
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||||
def test_delete_with_incorrect_instantiation_state(self, mock_vnf_by_id):
|
def test_delete_with_incorrect_instantiation_state(
|
||||||
|
self, mock_vnf_by_id, mock_get_service_plugins):
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id)
|
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id)
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
@ -1615,8 +1679,11 @@ class TestController(base.TestCase):
|
|||||||
self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id,
|
self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id,
|
||||||
resp.json['conflictingRequest']['message'])
|
resp.json['conflictingRequest']['message'])
|
||||||
|
|
||||||
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||||
def test_delete_with_incorrect_task_state(self, mock_vnf_by_id):
|
def test_delete_with_incorrect_task_state(self, mock_vnf_by_id,
|
||||||
|
mock_get_service_plugins):
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id)
|
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id)
|
||||||
req.method = 'DELETE'
|
req.method = 'DELETE'
|
||||||
@ -1985,22 +2052,23 @@ class TestController(base.TestCase):
|
|||||||
req.method = 'PATCH'
|
req.method = 'PATCH'
|
||||||
|
|
||||||
vnf_data = fakes._get_vnf()
|
vnf_data = fakes._get_vnf()
|
||||||
msg = _("Can not find requested vnf instance data: %s") % vnf_data.get(
|
msg = ("Can not find requested vnf instance data: %s") % vnf_data.get(
|
||||||
'vnfd_id')
|
'vnfd_id')
|
||||||
res = self._make_problem_detail(msg, 404, title='Not Found')
|
res = self._make_problem_detail(msg, 404, title='Not Found')
|
||||||
|
|
||||||
resp = req.get_response(self.app)
|
resp = req.get_response(self.app)
|
||||||
self.assertEqual(res.text, resp.text)
|
self.assertEqual(res.text, resp.text)
|
||||||
|
|
||||||
|
@ddt.data('vnfdId', 'vnfPkgId')
|
||||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||||
return_value={'VNFM': FakeVNFMPlugin()})
|
return_value={'VNFM': FakeVNFMPlugin()})
|
||||||
@mock.patch.object(objects.VNF, "vnf_index_list")
|
@mock.patch.object(objects.VNF, "vnf_index_list")
|
||||||
@mock.patch.object(objects.VnfInstanceList, "vnf_instance_list")
|
@mock.patch.object(objects.VnfInstanceList, "vnf_instance_list")
|
||||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_vnf_package_vnfd')
|
@mock.patch.object(objects.VnfPackageVnfd, 'get_vnf_package_vnfd')
|
||||||
@mock.patch.object(VNFLcmRPCAPI, "update")
|
@mock.patch.object(VNFLcmRPCAPI, "update_vnf_instance_content")
|
||||||
def test_update_vnf_none_vnfd_data(
|
def test_update_vnf_none_vnfd_data(
|
||||||
self,
|
self, input_id,
|
||||||
mock_update,
|
mock_update_vnf_instance_content,
|
||||||
mock_vnf_package_vnf_get_vnf_package_vnfd,
|
mock_vnf_package_vnf_get_vnf_package_vnfd,
|
||||||
mock_vnf_instance_list,
|
mock_vnf_instance_list,
|
||||||
mock_vnf_index_list,
|
mock_vnf_index_list,
|
||||||
@ -2011,15 +2079,12 @@ class TestController(base.TestCase):
|
|||||||
fields.VnfInstanceState.INSTANTIATED)
|
fields.VnfInstanceState.INSTANTIATED)
|
||||||
mock_vnf_package_vnf_get_vnf_package_vnfd.return_value = ""
|
mock_vnf_package_vnf_get_vnf_package_vnfd.return_value = ""
|
||||||
|
|
||||||
body = {"vnfInstanceName": "new_instance_name",
|
body = {"vnfInstanceName": "new_instance_name\
|
||||||
"vnfInstanceDescription": "new_instance_discription",
|
", "vnfInstanceDescription": "new_instance_discription\
|
||||||
"vnfdId": "2c69a161-0000-4b0f-bcf8-391f8fc76600",
|
", input_id: "2c69a161-0000-4b0f-bcf8-391f8fc76600\
|
||||||
"vnfConfigurableProperties": {
|
", "vnfConfigurableProperties\
|
||||||
"test": "test_value"
|
": {"test": "test_value\
|
||||||
},
|
"}, "vnfcInfoModificationsDeleteIds": ["test1"]}
|
||||||
"vnfcInfoModificationsDeleteIds": ["test1"],
|
|
||||||
"metadata": {"testkey": "test_value"},
|
|
||||||
"vimConnectionInfo": {"id": "testid"}}
|
|
||||||
req = fake_request.HTTPRequest.blank(
|
req = fake_request.HTTPRequest.blank(
|
||||||
'/vnf_instances/%s' % constants.UUID)
|
'/vnf_instances/%s' % constants.UUID)
|
||||||
req.body = jsonutils.dump_as_bytes(body)
|
req.body = jsonutils.dump_as_bytes(body)
|
||||||
@ -2027,8 +2092,8 @@ class TestController(base.TestCase):
|
|||||||
req.method = 'PATCH'
|
req.method = 'PATCH'
|
||||||
|
|
||||||
fakes._get_vnf()
|
fakes._get_vnf()
|
||||||
msg = _("Can not find requested vnf package vnfd: %s") %\
|
msg = ("Can not find requested vnf package vnfd: %s") %\
|
||||||
body.get('vnfdId')
|
body.get(input_id)
|
||||||
res = self._make_problem_detail(msg, 400, 'Bad Request')
|
res = self._make_problem_detail(msg, 400, 'Bad Request')
|
||||||
|
|
||||||
resp = req.get_response(self.app)
|
resp = req.get_response(self.app)
|
||||||
|
Loading…
Reference in New Issue
Block a user