Browse Source

Merge "Support Placement Constraints for Grant"

changes/12/784012/3
Zuul 2 weeks ago
committed by Gerrit Code Review
parent
commit
6fc64560e2
10 changed files with 583 additions and 62 deletions
  1. +5
    -0
      releasenotes/notes/bp-placement-constraints-e3256cfc2d1b2b9f.yaml
  2. +7
    -4
      tacker/conductor/conductor_server.py
  3. +6
    -4
      tacker/tests/etc/samples/etsi/nfv/functional6/BaseHOT/simple/helloworld3.yaml
  4. +4
    -0
      tacker/tests/etc/samples/etsi/nfv/functional6/BaseHOT/simple/nested/VDU1.yaml
  5. +7
    -3
      tacker/tests/etc/samples/etsi/nfv/functional6/BaseHOT/simple/nested/VDU2.yaml
  6. +5
    -5
      tacker/tests/etc/samples/etsi/nfv/functional6/Definitions/helloworld3_df_simple.yaml
  7. +8
    -0
      tacker/tests/functional/sol/vnflcm/base.py
  8. +29
    -12
      tacker/tests/functional/sol_separated_nfvo/vnflcm/test_vnf_instance_with_user_data_nfvo_separate.py
  9. +426
    -9
      tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py
  10. +86
    -25
      tacker/vnfm/infra_drivers/openstack/openstack.py

+ 5
- 0
releasenotes/notes/bp-placement-constraints-e3256cfc2d1b2b9f.yaml View File

@ -0,0 +1,5 @@
---
features:
- Add placement constraints support so that the VNFM may interoperate with 3rd
party NFVO, it enables to deploy each VM in the VNF after setting the zone
information based on the grant response from NFVO.

+ 7
- 4
tacker/conductor/conductor_server.py View File

@ -1084,12 +1084,15 @@ class Conductor(manager.Manager):
placement_obj_list = []
topo_temp = vnfd_dict.get('topology_template', {})
for policy in topo_temp.get('policies', []):
affinity_type = {
'tosca.policies.nfv.AntiAffinityRule': 'ANTI_AFFINITY',
'tosca.policies.nfv.AffinityRule': 'AFFINITY'}
for policy_name, policy_dict in policy.items():
key_type = 'tosca.policies.nfv.AntiAffinityRule'
if policy_dict['type'] == key_type:
if policy_dict['type'] in affinity_type.keys():
placement_constraint = objects.PlacementConstraint()
placement_constraint.affinity_or_anti_affinity = \
'ANTI_AFFINITY'
key = policy_dict['type']
placement_constraint.affinity_or_anti_affinity = (
affinity_type[key])
placement_constraint.scope = 'ZONE'
placement_constraint.resource = []
placement_constraint.fallback_best_effort = True


+ 6
- 4
tacker/tests/etc/samples/etsi/nfv/functional6/BaseHOT/simple/helloworld3.yaml View File

@ -23,6 +23,7 @@ resources:
net3: { get_resource: extmanageNW_1 }
net4: { get_resource: extmanageNW_2 }
net5: { get_resource: internalNW_1 }
subnet: { get_param: [nfv, CP, VDU1_CP2, fixed_ips, 0, subnet]}
VDU1_scale_out:
type: OS::Heat::ScalingPolicy
properties:
@ -41,20 +42,21 @@ resources:
type: OS::Heat::AutoScalingGroup
depends_on: VDU1
properties:
min_size: 2
max_size: 2
desired_capacity: 2
min_size: 1
max_size: 1
desired_capacity: 1
resource:
type: VDU2.yaml
properties:
flavor: { get_param: [ nfv, VDU, VDU2, flavor ] }
image: { get_param: [ nfv, VDU, VDU2, image ] }
zone: { get_param: [ nfv, vdu, VDU2, zone ] }
net1: { get_param: [ nfv, CP, VDU2_CP1, network ] }
net2: { get_param: [ nfv, CP, VDU2_CP2, network ] }
net3: { get_resource: extmanageNW_1 }
net4: { get_resource: extmanageNW_2 }
net5: { get_resource: internalNW_1 }
ip1: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 0, ip_address]}
subnet: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 0, subnet]}
VDU2_scale_out:
type: OS::Heat::ScalingPolicy
properties:


+ 4
- 0
tacker/tests/etc/samples/etsi/nfv/functional6/BaseHOT/simple/nested/VDU1.yaml View File

@ -18,6 +18,8 @@ parameters:
type: string
net5:
type: string
subnet:
type: string
resources:
VDU1:
@ -47,6 +49,8 @@ resources:
type: OS::Neutron::Port
properties:
network: { get_param: net2 }
fixed_ips:
- subnet: { get_param: subnet}
VDU1_CP3:
type: OS::Neutron::Port
properties:


+ 7
- 3
tacker/tests/etc/samples/etsi/nfv/functional6/BaseHOT/simple/nested/VDU2.yaml View File

@ -6,8 +6,6 @@ parameters:
type: string
image:
type: string
zone:
type: string
net1:
type: string
net2:
@ -18,6 +16,10 @@ parameters:
type: string
net5:
type: string
ip1:
type: string
subnet:
type: string
resources:
VDU2:
@ -37,7 +39,6 @@ resources:
get_resource: VDU2_CP4
- port:
get_resource: VDU2_CP5
availability_zone: { get_param: zone }
VDU2_CP1:
type: OS::Neutron::Port
@ -47,6 +48,9 @@ resources:
type: OS::Neutron::Port
properties:
network: { get_param: net2 }
fixed_ips:
- ip_address: { get_param: ip1}
subnet: { get_param: subnet}
VDU2_CP3:
type: OS::Neutron::Port
properties:


+ 5
- 5
tacker/tests/etc/samples/etsi/nfv/functional6/Definitions/helloworld3_df_simple.yaml View File

@ -96,8 +96,8 @@ topology_template:
name: VDU2
description: VDU2 compute node
vdu_profile:
min_number_of_instances: 2
max_number_of_instances: 2
min_number_of_instances: 1
max_number_of_instances: 1
sw_image_data:
name: cirros-0.4.0-x86_64-disk
version: '0.4.0'
@ -291,7 +291,7 @@ topology_template:
type: tosca.policies.nfv.VduInitialDelta
properties:
initial_delta:
number_of_instances: 2
number_of_instances: 1
targets: [ VDU2 ]
- VDU1_scaling_aspect_deltas:
@ -334,9 +334,9 @@ topology_template:
properties:
levels:
instantiation_level_1:
number_of_instances: 2
number_of_instances: 1
instantiation_level_2:
number_of_instances: 2
number_of_instances: 1
targets: [ VDU2 ]
- internalVL1_instantiation_levels:


+ 8
- 0
tacker/tests/functional/sol/vnflcm/base.py View File

@ -626,6 +626,14 @@ class BaseVnfLcmTest(base.BaseTackerTest):
return resource
def _get_heat_stack_template(self, stack_id, nested_depth=0):
try:
template = self.h_client.stacks.template(stack_id)
except Exception:
return None
return template
def _get_image_id_from_resource_attributes(self, stack_resource_details):
if stack_resource_details is None:
return None


+ 29
- 12
tacker/tests/functional/sol_separated_nfvo/vnflcm/test_vnf_instance_with_user_data_nfvo_separate.py View File

@ -108,8 +108,7 @@ class VnfLcmWithNfvoSeparator(vnflcm_base.BaseVnfLcmTest):
- Delete subscription.
- Show subscription.
"""
vnf_package_info = self._register_vnf_package_mock_response(
package_dir="functional5")
vnf_package_info = self._register_vnf_package_mock_response()
glance_image = self._list_glance_image()[0]
# Create subscription and register it.
@ -143,9 +142,10 @@ class VnfLcmWithNfvoSeparator(vnflcm_base.BaseVnfLcmTest):
self.vim['tenant_id'], glance_image.id))
# Instantiate vnf instance
request_body = fake_vnflcm.VnfInstances.make_inst_request_body(
self.vim['tenant_id'], self.ext_networks, self.ext_mngd_networks,
self.ext_link_ports, self.ext_subnets)
request_body = fake_vnflcm.VnfInstances.\
make_inst_request_body_include_num_dynamic(
self.vim['tenant_id'], self.ext_networks,
self.ext_mngd_networks, self.ext_link_ports, self.ext_subnets)
resp, _ = self._instantiate_vnf_instance(vnf_instance_id, request_body)
self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id)
self._assert_instantiate_vnf(resp, vnf_instance_id)
@ -284,12 +284,14 @@ class VnfLcmWithNfvoSeparator(vnflcm_base.BaseVnfLcmTest):
self.vim['tenant_id'], glance_image.id))
# Instantiate vnf instance
request_body = fake_vnflcm.VnfInstances.make_inst_request_body(
self.vim['tenant_id'], self.ext_networks, self.ext_mngd_networks,
self.ext_link_ports, self.ext_subnets)
request_body = fake_vnflcm.VnfInstances.\
make_inst_request_body_include_num_dynamic(
self.vim['tenant_id'], self.ext_networks,
self.ext_mngd_networks, self.ext_link_ports, self.ext_subnets)
resp, _ = self._instantiate_vnf_instance(vnf_instance_id, request_body)
self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id)
self._assert_instantiate_vnf(resp, vnf_instance_id)
self._assert_stack_template(vnf_instance_id)
# Show vnf instance
resp, vnf_instance = self._show_vnf_instance(vnf_instance_id)
@ -303,15 +305,19 @@ class VnfLcmWithNfvoSeparator(vnflcm_base.BaseVnfLcmTest):
self.vim['tenant_id'], glance_image.id))
# Heal vnf (exists vnfc_instace_id)
vnfc_instance_id_list = [
vnfc.get('id') for vnfc in vnf_instance.get(
'instantiatedVnfInfo', {}).get(
'vnfcResourceInfo', [])]
vnfc_instance_id_list = []
for vnfc in vnf_instance.get('instantiatedVnfInfo', {}).\
get('vnfcResourceInfo', []):
if vnfc.get('vduId') == 'VDU1':
vnfc_instance_id_list.append(vnfc.get('id'))
request_body = fake_vnflcm.VnfInstances.make_heal_request_body(
vnfc_instance_id_list)
resp, _ = self._heal_vnf_instance(vnf_instance_id, request_body)
self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id)
self._assert_heal_vnf(resp, vnf_instance_id)
self._assert_stack_template(vnf_instance_id)
# Set Fake server response for Grant-Req(Terminate)
vnflcm_base.FAKE_SERVER_MANAGER.set_callback('POST',
@ -522,3 +528,14 @@ class VnfLcmWithNfvoSeparator(vnflcm_base.BaseVnfLcmTest):
ans_list.append(detail.attributes['fixed_ips'])
return ans_list
def _assert_stack_template(self, vnf_instance_id):
stack = self._get_heat_stack(vnf_instance_id)
resources_list\
= self._get_heat_resource_list(stack.id, nested_depth=2)
stack_name_wd = vnf_instance_id + "-VDU2"
physical_resource_id = [r.physical_resource_id for r
in resources_list if stack_name_wd in r.stack_name]
template = self._get_heat_stack_template(physical_resource_id[0])
template_count = str(template).count("zone")
self.assertEqual(template_count, 3)

+ 426
- 9
tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py View File

@ -264,10 +264,126 @@ class TestOpenStack(base.FixturedTestCase):
vnf_resource = type('', (), {})
vnf_resource.resource_identifier = constants.INVALID_UUID
grant_info_test = {'vdu_name': {vnf_resource}}
nested_hot_dict = {'parameters': {'vnf': 'test'}}
nested_hot_dict = {
'VDU1.yaml': {'parameters': {'vnf': 'test',
'zone': {'type': 'string'}},
'resources': {'VDU1': {'properties':
{'availability_zone': {'get_param': 'zone'}}}}}}
base_hot_dict = self._read_file()
base_hot_dict['resources']['VDU1']['properties'].setdefault(
'resource', {'properties': {'zone':
{'get_param': ['nfv', 'vdu', 'VDU1', 'zone']}}})
mock_get_base_hot_dict.return_value = \
base_hot_dict, nested_hot_dict
vim_assets = {'compute_resource_flavours': [
{'vim_connection_id': uuidsentinel.vim_id,
'vnfd_virtual_compute_desc_id': 'VDU1',
'vim_flavour_id': 'm1.tiny'}],
'softwareImages': [
{'vim_connection_id': uuidsentinel.vim_id,
'vnfd_software_image_id': 'VDU1',
'vim_software_image_id': 'cirros'}]}
res_add_resource = []
resource = {
'resource_definition_id': '2c6e5cc7-240d-4458-a683-1fe648351280',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
res_add_resource.append(resource)
resource = {
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa9',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
res_add_resource.append(resource)
resource = {
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa0',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
res_add_resource.append(resource)
resource = {
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa1',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
res_add_resource.append(resource)
zone = {
'id': '5e4da3c3-4a55-412a-b624-843921f8b51d',
'zone_id': 'nova',
'vim_connection_id': uuidsentinel.vim_id}
vim_obj = {'id': '0b9c66bb-9e1f-4bb2-92c3-913074e52e2b',
'vim_id': uuidsentinel.vim_id,
'vim_type': 'openstack',
'access_info': {
'password': 'test_pw',
'username': 'test_user',
'region': 'test_region',
'tenant': uuidsentinel.tenant}}
grant_dict = {}
grant_dict['id'] = 'c213e465-8220-487e-9464-f79104e81e96'
grant_dict['vnf_instance_id'] = uuidsentinel.vnf_instance_id
grant_dict['vnf_lcm_op_occ_id'] = uuidsentinel.vnf_lcm_op_occ_id
grant_dict['add_resources'] = []
grant_dict['add_resources'].extend(res_add_resource)
grant_dict['vim_assets'] = vim_assets
grant_dict['zones'] = [zone]
grant_dict['vim_connections'] = [vim_obj]
grant_obj = objects.Grant.obj_from_primitive(
grant_dict, context=self.context)
vnf['grant'] = grant_obj
vnf_instance = fd_utils.get_vnf_instance_object()
vnf_instance.instantiated_vnf_info.reinitialize()
vnfc_obj = objects.VnfcResourceInfo()
vnfc_obj.id = '2c6e5cc7-240d-4458-a683-1fe648351280'
vnfc_obj.vdu_id = 'VDU1'
vnfc_obj.storage_resource_ids = \
['faf14707-da7c-4eec-be99-8099fa1e9fa0']
compute_resource = objects.ResourceHandle(
vim_connection_id=uuidsentinel.vim_id,
resource_id='6e1c286d-c023-4b34-8369-831c6e84cce2')
vnfc_obj.compute_resource = compute_resource
vnf_instance.instantiated_vnf_info.vnfc_resource_info = [vnfc_obj]
self.openstack.create(self.plugin, self.context, vnf,
self.auth_attr, inst_req_info=inst_req_info_test,
vnf_package_path=vnf_package_path_test,
grant_info=grant_info_test,
vnf_instance=vnf_instance)
@mock.patch('tacker.vnfm.vim_client.VimClient.get_vim')
@mock.patch('tacker.vnfm.infra_drivers.openstack.openstack'
'.OpenStack._format_base_hot')
@mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict')
@mock.patch('tacker.common.clients.OpenstackClients')
def test_create_grant_zone_add(self, mock_OpenstackClients_heat,
mock_get_base_hot_dict,
mock_format_base_hot,
mock_get_vim):
mock_get_vim.return_value = {
'vim_id': uuidsentinel.vnfd_id,
'vim_type': 'test',
'vim_auth': {'username': 'test', 'password': 'test'},
'placement_attr': {'region': 'TestRegionOne'},
'tenant': 'test'
}
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
flavour='simple')
vnf['placement_attr'] = {'region_name': 'dummy_region'}
vnf_package_path_test = os.path.abspath(
os.path.join(os.path.dirname(__file__),
"../../../../etc/samples/etsi/nfv",
"user_data_sample_normal"))
inst_req_info_test = type('', (), {})
test_json = self._json_load(
'instantiate_vnf_request_lcm_userdata.json')
inst_req_info_test.additional_params = test_json['additionalParams']
inst_req_info_test.ext_virtual_links = None
inst_req_info_test.flavour_id = 'simple'
vnf_resource = type('', (), {})
vnf_resource.resource_identifier = constants.INVALID_UUID
grant_info_test = {'vdu_name': {vnf_resource}}
nested_hot_dict = {
'VDU1.yaml': {'parameters': {'vnf': 'test'},
'resources': {'VDU1': {'properties': {}}}}}
mock_get_base_hot_dict.return_value = \
self._read_file(), nested_hot_dict
vimAssets = {'compute_resource_flavours': [
vim_assets = {'compute_resource_flavours': [
{'vim_connection_id': uuidsentinel.vim_id,
'vnfd_virtual_compute_desc_id': 'VDU1',
'vim_flavour_id': 'm1.tiny'}],
@ -275,27 +391,27 @@ class TestOpenStack(base.FixturedTestCase):
{'vim_connection_id': uuidsentinel.vim_id,
'vnfd_software_image_id': 'VDU1',
'vim_software_image_id': 'cirros'}]}
resAddResource = []
res_add_resource = []
resource = {
'resource_definition_id': '2c6e5cc7-240d-4458-a683-1fe648351280',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
resAddResource.append(resource)
res_add_resource.append(resource)
resource = {
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa9',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
resAddResource.append(resource)
res_add_resource.append(resource)
resource = {
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa0',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
resAddResource.append(resource)
res_add_resource.append(resource)
resource = {
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa1',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
resAddResource.append(resource)
res_add_resource.append(resource)
zone = {
'id': '5e4da3c3-4a55-412a-b624-843921f8b51d',
'zone_id': 'nova',
@ -313,8 +429,116 @@ class TestOpenStack(base.FixturedTestCase):
grant_dict['vnf_instance_id'] = uuidsentinel.vnf_instance_id
grant_dict['vnf_lcm_op_occ_id'] = uuidsentinel.vnf_lcm_op_occ_id
grant_dict['add_resources'] = []
grant_dict['add_resources'].extend(resAddResource)
grant_dict['vim_assets'] = vimAssets
grant_dict['add_resources'].extend(res_add_resource)
grant_dict['vim_assets'] = vim_assets
grant_dict['zones'] = [zone]
grant_dict['vim_connections'] = [vim_obj]
grant_obj = objects.Grant.obj_from_primitive(
grant_dict, context=self.context)
vnf['grant'] = grant_obj
vnf_instance = fd_utils.get_vnf_instance_object()
vnf_instance.instantiated_vnf_info.reinitialize()
vnfc_obj = objects.VnfcResourceInfo()
vnfc_obj.id = '2c6e5cc7-240d-4458-a683-1fe648351280'
vnfc_obj.vdu_id = 'VDU1'
vnfc_obj.storage_resource_ids = \
['faf14707-da7c-4eec-be99-8099fa1e9fa0']
compute_resource = objects.ResourceHandle(
vim_connection_id=uuidsentinel.vim_id,
resource_id='6e1c286d-c023-4b34-8369-831c6e84cce2')
vnfc_obj.compute_resource = compute_resource
vnf_instance.instantiated_vnf_info.vnfc_resource_info = [vnfc_obj]
self.openstack.create(self.plugin, self.context, vnf,
self.auth_attr, inst_req_info=inst_req_info_test,
vnf_package_path=vnf_package_path_test,
grant_info=grant_info_test,
vnf_instance=vnf_instance)
@mock.patch('tacker.vnfm.vim_client.VimClient.get_vim')
@mock.patch('tacker.vnfm.infra_drivers.openstack.openstack'
'.OpenStack._format_base_hot')
@mock.patch('tacker.vnflcm.utils.get_base_nest_hot_dict')
@mock.patch('tacker.common.clients.OpenstackClients')
def test_create_grant_zone_id_none(self, mock_OpenstackClients_heat,
mock_get_base_hot_dict,
mock_format_base_hot,
mock_get_vim):
mock_get_vim.return_value = {
'vim_id': uuidsentinel.vnfd_id,
'vim_type': 'test',
'vim_auth': {'username': 'test', 'password': 'test'},
'placement_attr': {'region': 'TestRegionOne'},
'tenant': 'test'
}
vnf = utils.get_dummy_vnf_etsi(instance_id=self.instance_uuid,
flavour='simple')
vnf['placement_attr'] = {'region_name': 'dummy_region'}
vnf_package_path_test = os.path.abspath(
os.path.join(os.path.dirname(__file__),
"../../../../etc/samples/etsi/nfv",
"user_data_sample_normal"))
inst_req_info_test = type('', (), {})
test_json = self._json_load(
'instantiate_vnf_request_lcm_userdata.json')
inst_req_info_test.additional_params = test_json['additionalParams']
inst_req_info_test.ext_virtual_links = None
inst_req_info_test.flavour_id = 'simple'
vnf_resource = type('', (), {})
vnf_resource.resource_identifier = constants.INVALID_UUID
grant_info_test = {'vdu_name': {vnf_resource}}
nested_hot_dict = {
'VDU1.yaml': {'parameters': {'vnf': 'test'},
'resources': {'VDU1': {'properties': {}}}}}
mock_get_base_hot_dict.return_value = \
self._read_file(), nested_hot_dict
vim_assets = {'compute_resource_flavours': [
{'vim_connection_id': uuidsentinel.vim_id,
'vnfd_virtual_compute_desc_id': 'VDU1',
'vim_flavour_id': 'm1.tiny'}],
'softwareImages': [
{'vim_connection_id': uuidsentinel.vim_id,
'vnfd_software_image_id': 'VDU1',
'vim_software_image_id': 'cirros'}]}
res_add_resource = []
resource = {
'resource_definition_id': '2c6e5cc7-240d-4458-a683-1fe648351280',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
res_add_resource.append(resource)
resource = {
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa9',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
res_add_resource.append(resource)
resource = {
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa0',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
res_add_resource.append(resource)
resource = {
'resource_definition_id': 'faf14707-da7c-4eec-be99-8099fa1e9fa1',
'vim_connection_id': uuidsentinel.vim_id,
'zone_id': '5e4da3c3-4a55-412a-b624-843921f8b51d'}
res_add_resource.append(resource)
zone = {
'id': '5e4da3c3-4a55-412a-b624-843921f8b51d',
'zone_id': '',
'vim_connection_id': uuidsentinel.vim_id}
vim_obj = {'id': '0b9c66bb-9e1f-4bb2-92c3-913074e52e2b',
'vim_id': uuidsentinel.vim_id,
'vim_type': 'openstack',
'access_info': {
'password': 'test_pw',
'username': 'test_user',
'region': 'test_region',
'tenant': uuidsentinel.tenant}}
grant_dict = {}
grant_dict['id'] = 'c213e465-8220-487e-9464-f79104e81e96'
grant_dict['vnf_instance_id'] = uuidsentinel.vnf_instance_id
grant_dict['vnf_lcm_op_occ_id'] = uuidsentinel.vnf_lcm_op_occ_id
grant_dict['add_resources'] = []
grant_dict['add_resources'].extend(res_add_resource)
grant_dict['vim_assets'] = vim_assets
grant_dict['zones'] = [zone]
grant_dict['vim_connections'] = [vim_obj]
grant_obj = objects.Grant.obj_from_primitive(
@ -2085,6 +2309,199 @@ class TestOpenStack(base.FixturedTestCase):
region_name=None
)
@mock.patch.object(hc.HeatClient, "update")
def test_scale_out_initial_zone_none(self, mock_update):
scale_vnf_request = objects.ScaleVnfRequest(type='SCALE_OUT',
aspect_id='SP1',
number_of_steps=1)
vnf_info = {}
add_resources = []
resource = objects.ResourceDefinition(
id='2c6e5cc7-240d-4458-a683-1fe648351280',
type='COMPUTE',
vdu_id='VDU1',
resource_template_id='VDU1')
add_resources.append(resource)
resource = objects.ResourceDefinition(
id='faf14707-da7c-4eec-be99-8099fa1e9fa9',
type='LINKPORT',
vdu_id='VDU1',
resource_template_id='PORT1')
add_resources.append(resource)
resource = objects.ResourceDefinition(
id='faf14707-da7c-4eec-be99-8099fa1e9fa9',
type='STORAGE',
vdu_id='VDU1',
resource_template_id='ST1')
add_resources.append(resource)
vnf_info['addResources'] = add_resources
vnf_info['attributes'] = {}
vnf_info['attributes']['scale_group'] = '{\"scaleGroupDict\": ' + \
'{ \"SP1\": { \"vdu\": [\"VDU1\"], \"num\": ' + \
'1, \"maxLevel\": 3, \"initialNum\": 0, ' + \
'\"initialLevel\": 0, \"default\": 0 }}}'
vnf_info['attributes']['heat_template'] = \
utils.get_dummy_scale_initial_hot()
vnf_info['attributes']['SP1_res.yaml'] = \
utils.get_dummy_scale_nest_initial_hot()
stack_param_dict = {}
stack_param_dict['nfv'] = {}
stack_param_dict['nfv']['VDU'] = {}
stack_param_dict['nfv']['VDU']['VDU1'] = {}
stack_param_dict['nfv']['VDU']['VDU1']['flavor'] = ''
stack_param_dict['nfv']['VDU']['VDU1']['image'] = ''
vnf_info['attributes'].update({'stack_param': str(stack_param_dict)})
vnf_info['instance_id'] = uuidsentinel.stack_id
testjson = '{"id": "c213e465-8220-487e-9464-f79104e81e96", ' + \
'"vnf_instance_id": ' + \
'"47101fb6-bd18-4e04-b2b5-22370a023448", ' + \
'"vnf_lcm_op_occ_id": ' + \
'"f26f181d-7891-4720-b022-b074ec1733ef", ' + \
'"zones": [{' + \
'"id": ' + \
'"5e4da3c3-4a55-412a-b624-843921f8b51d", ' + \
'"zone_id": ' + \
'"nova", ' + \
'"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187"}], ' + \
'"add_resources": [{"resource_definition_id": ' + \
'"2c6e5cc7-240d-4458-a683-1fe648351280", ' + \
'"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
'"zone_id": "5e4da3c3-4a55-412a-b624-843921f8b51d"}' + \
', {"resource_definition_id": ' + \
'"faf14707-da7c-4eec-be99-8099fa1e9fa9", ' + \
'"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
'"zone_id": "5e4da3c3-4a55-412a-b624-843921f8b51d"}' + \
', {"resource_definition_id": ' + \
'"faf14707-da7c-4eec-be99-8099fa1e9fa9", ' + \
'"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
'"zone_id": ' + \
'"5e4da3c3-4a55-412a-b624-843921f8b51d"}], ' + \
'"vim_assets": {"compute_resource_flavours": ' + \
'[{"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
'"vnfd_virtual_compute_desc_id": "VDU1", ' + \
'"vim_flavour_id": "m1.tiny"}], "software_images": ' + \
'[{"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
'"vnfd_software_image_id": "VDU1", ' + \
'"vim_software_image_id": "cirros"}]}}'
res_body = jsonutils.loads(testjson)
res_dict = cutils.convert_camelcase_to_snakecase(res_body)
grant_obj = objects.Grant.obj_from_primitive(
res_dict, context=context)
vnf_info['grant'] = grant_obj
self.openstack.scale_out_initial(context=self.context,
plugin=self,
auth_attr=None,
vnf_info=vnf_info,
scale_vnf_request=scale_vnf_request,
region_name=None
)
@mock.patch.object(hc.HeatClient, "update")
def test_scale_out_initial_zone_id_none(self, mock_update):
scale_vnf_request = objects.ScaleVnfRequest(type='SCALE_OUT',
aspect_id='SP1',
number_of_steps=1)
vnf_info = {}
add_resources = []
resource = objects.ResourceDefinition(
id='2c6e5cc7-240d-4458-a683-1fe648351280',
type='COMPUTE',
vdu_id='VDU1',
resource_template_id='VDU1')
add_resources.append(resource)
resource = objects.ResourceDefinition(
id='faf14707-da7c-4eec-be99-8099fa1e9fa9',
type='LINKPORT',
vdu_id='VDU1',
resource_template_id='PORT1')
add_resources.append(resource)
resource = objects.ResourceDefinition(
id='faf14707-da7c-4eec-be99-8099fa1e9fa9',
type='STORAGE',
vdu_id='VDU1',
resource_template_id='ST1')
add_resources.append(resource)
vnf_info['addResources'] = add_resources
vnf_info['attributes'] = {}
vnf_info['attributes']['scale_group'] = '{\"scaleGroupDict\": ' + \
'{ \"SP1\": { \"vdu\": [\"VDU1\"], \"num\": ' + \
'1, \"maxLevel\": 3, \"initialNum\": 0, ' + \
'\"initialLevel\": 0, \"default\": 0 }}}'
vnf_info['attributes']['heat_template'] = \
utils.get_dummy_scale_initial_hot()
vnf_info['attributes']['SP1_res.yaml'] = \
utils.get_dummy_scale_nest_initial_hot()
stack_param_dict = {}
stack_param_dict['nfv'] = {}
stack_param_dict['nfv']['VDU'] = {}
stack_param_dict['nfv']['VDU']['VDU1'] = {}
stack_param_dict['nfv']['VDU']['VDU1']['zone'] = ''
stack_param_dict['nfv']['VDU']['VDU1']['flavor'] = ''
stack_param_dict['nfv']['VDU']['VDU1']['image'] = ''
vnf_info['attributes'].update({'stack_param': str(stack_param_dict)})
vnf_info['instance_id'] = uuidsentinel.stack_id
testjson = '{"id": "c213e465-8220-487e-9464-f79104e81e96", ' + \
'"vnf_instance_id": ' + \
'"47101fb6-bd18-4e04-b2b5-22370a023448", ' + \
'"vnf_lcm_op_occ_id": ' + \
'"f26f181d-7891-4720-b022-b074ec1733ef", ' + \
'"zones": [{' + \
'"id": ' + \
'"5e4da3c3-4a55-412a-b624-843921f8b51d", ' + \
'"zone_id": ' + \
'"", ' + \
'"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187"}], ' + \
'"add_resources": [{"resource_definition_id": ' + \
'"2c6e5cc7-240d-4458-a683-1fe648351280", ' + \
'"id": ' + \
'"2c6e5cc7-240d-4458-a683-1fe648351280", ' + \
'"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
'"zone_id": "5e4da3c3-4a55-412a-b624-843921f8b51d"}' + \
', {"resource_definition_id": ' + \
'"faf14707-da7c-4eec-be99-8099fa1e9fa9", ' + \
'"id": ' + \
'"faf14707-da7c-4eec-be99-8099fa1e9fa9", ' + \
'"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
'"zone_id": "5e4da3c3-4a55-412a-b624-843921f8b51d"}' + \
', {"resource_definition_id": ' + \
'"faf14707-da7c-4eec-be99-8099fa1e9fa9", ' + \
'"id": ' + \
'"faf14707-da7c-4eec-be99-8099fa1e9fa9", ' + \
'"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
'"zone_id": ' + \
'"5e4da3c3-4a55-412a-b624-843921f8b51d"}], ' + \
'"vim_assets": {"compute_resource_flavours": ' + \
'[{"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
'"vnfd_virtual_compute_desc_id": "VDU1", ' + \
'"vim_flavour_id": "m1.tiny"}], "software_images": ' + \
'[{"vim_connection_id": ' + \
'"b6eacd1b-5a9e-41ea-a33b-9d7196cd9187", ' + \
'"vnfd_software_image_id": "VDU1", ' + \
'"vim_software_image_id": "cirros"}]}}'
res_body = jsonutils.loads(testjson)
res_dict = cutils.convert_camelcase_to_snakecase(res_body)
grant_obj = objects.Grant.obj_from_primitive(
res_dict, context=context)
vnf_info['grant'] = grant_obj
self.openstack.scale_out_initial(context=self.context,
plugin=self,
auth_attr=None,
vnf_info=vnf_info,
scale_vnf_request=scale_vnf_request,
region_name=None
)
@mock.patch.object(hc.HeatClient, "resource_get")
@mock.patch.object(hc.HeatClient, "resource_get_list")
def test_get_rollback_ids(self, mock_list, mock_resource):


+ 86
- 25
tacker/vnfm/infra_drivers/openstack/openstack.py View File

@ -264,29 +264,9 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
scale_status_list.append(scale_status)
vnf['scale_status'] = scale_status_list
if vnf.get('grant'):
grant = vnf['grant']
ins_inf = vnf_instance.instantiated_vnf_info.vnfc_resource_info
for addrsc in grant.add_resources:
for zone in grant.zones:
if zone.id == addrsc.zone_id:
vdu_name = None
for rsc in ins_inf:
if addrsc.resource_definition_id == rsc.id:
vdu_name = rsc.vdu_id
break
if not vdu_name:
continue
hot_param_dict['nfv']['VDU'][vdu_name]['zone'] = \
zone.zone_id
if 'vim_assets' in grant and grant.vim_assets:
for flavour in grant.vim_assets.compute_resource_flavours:
vdu_name = flavour.vnfd_virtual_compute_desc_id
hot_param_dict['nfv']['VDU'][vdu_name]['flavor'] = \
flavour.vim_flavour_id
for image in grant.vim_assets.software_images:
vdu_name = image.vnfd_software_image_id
hot_param_dict['nfv']['VDU'][vdu_name]['image'] = \
image.vim_software_image_id
base_hot_dict, nested_hot_dict, hot_param_dict = \
self._setup_hot_for_grant_resources(vnf, vnf_instance,
base_hot_dict, nested_hot_dict, hot_param_dict)
# Add stack param to vnf_attributes
vnf['attributes'].update({'stack_param': str(hot_param_dict)})
@ -366,6 +346,79 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
return stack['stack']['id']
@log.log
def _setup_hot_for_grant_resources(self, vnf, vnf_instance,
base_hot_dict, nested_hot_dict, hot_param_dict):
"""Setup HOT related params for grant resources
Update base_hot_dict, nested_hot_dict and hot_param_dict as HOT related
params for grant resources.
:param vnf:
:param vnf_instance:
:param base_hot_dict:
:param nested_hot_dict:
:param hot_param_dict:
:returns: updated base_hot_dict, nested_hot_dict and hot_param_dict
"""
# Rename for readability
grant = vnf['grant']
bh = base_hot_dict
nh = nested_hot_dict
hparam = hot_param_dict
ins_inf = vnf_instance.instantiated_vnf_info.vnfc_resource_info
for addrsc in grant.add_resources:
for zone in grant.zones:
if zone.id == addrsc.zone_id:
vdu_name = None
for rsc in ins_inf:
if addrsc.resource_definition_id == rsc.id:
vdu_name = rsc.vdu_id
break
if not vdu_name:
continue
vdu_prop = bh['resources'][vdu_name]['properties']
if not vdu_prop.get('resource'):
vdu_prop['resource'] = {'properties': {}}
vdu_rsrc_prop = vdu_prop['resource']['properties']
if not vdu_rsrc_prop.get('zone'):
vdu_rsrc_prop['zone'] = {'get_param':
['nfv', 'vdu', vdu_name, 'zone']}
if nh:
for yaml_name in nh:
if not (vdu_name in yaml_name):
continue
if not nh[yaml_name]['parameters'].get('zone'):
nh[yaml_name]['parameters']['zone'] = {
'type': 'string'}
vdu_props = nh[yaml_name]['resources'][vdu_name][
'properties']
if not (vdu_props.get('availability_zone')):
vdu_props['availability_zone'] = {
'get_param': 'zone'}
h_vdu = hparam['nfv']['VDU'][vdu_name]
if not h_vdu.get('zone') and zone.zone_id:
hparam['nfv']['VDU'][vdu_name]['zone'] = zone.zone_id
if h_vdu.get('zone') and not zone.zone_id:
del hparam['nfv']['VDU'][vdu_name]['zone']
if 'vim_assets' in grant and grant.vim_assets:
h_vdus = hparam['nfv']['VDU']
for flv in grant.vim_assets.compute_resource_flavours:
vdu_name = flv.vnfd_virtual_compute_desc_id
h_vdus[vdu_name]['flavor'] = flv.vim_flavour_id
for img in grant.vim_assets.software_images:
vdu_name = img.vnfd_software_image_id
h_vdus[vdu_name]['image'] = img.vim_software_image_id
return bh, nh, hparam
@log.log
def _delete_user_data_module(self, user_data_module):
# Delete module recursively.
@ -1674,10 +1727,18 @@ class OpenStack(abstract_driver.VnfAbstractDriver,
for zone in grant.zones:
if zone.id == addrsc.zone_id:
for rsc in vnf_info['addResources']:
if addrsc.id == rsc.id:
if addrsc.resource_definition_id == rsc.id:
vdu_name = rsc.vdu_id
break
stack_param['nfv']['VDU'][vdu_name]['zone'] = zone.zone_id
if not (stack_param['nfv']['VDU']
[vdu_name]).get('zone') and\
zone.zone_id:
stack_param['nfv']['VDU'][vdu_name]['zone'] = \
zone.zone_id
if (stack_param['nfv']['VDU']
[vdu_name]).get('zone') and\
not zone.zone_id:
del stack_param['nfv']['VDU'][vdu_name]['zone']
if 'vim_assets' in grant and grant.vim_assets:
for flavour in grant.vim_assets.compute_resource_flavours:
vdu_name = flavour.vnfd_virtual_compute_desc_id


Loading…
Cancel
Save