diff --git a/tacker/tests/etc/samples/etsi/nfv/functional6/BaseHOT/simple/helloworld3.yaml b/tacker/tests/etc/samples/etsi/nfv/functional6/BaseHOT/simple/helloworld3.yaml index f21a9b78a..0fdbf19f8 100644 --- a/tacker/tests/etc/samples/etsi/nfv/functional6/BaseHOT/simple/helloworld3.yaml +++ b/tacker/tests/etc/samples/etsi/nfv/functional6/BaseHOT/simple/helloworld3.yaml @@ -6,7 +6,7 @@ parameters: type: json resources: - VDU1: + VDU1_scale: type: OS::Heat::AutoScalingGroup properties: min_size: 1 @@ -24,23 +24,22 @@ resources: net4: { get_resource: extmanageNW_2 } net5: { get_resource: internalNW_1 } subnet: { get_param: [nfv, CP, VDU1_CP2, fixed_ips, 0, subnet]} - VDU1_scale_out: + VDU1_scale_scale_out: type: OS::Heat::ScalingPolicy properties: scaling_adjustment: 1 auto_scaling_group_id: - get_resource: VDU1 + get_resource: VDU1_scale adjustment_type: change_in_capacity - VDU1_scale_in: + VDU1_scale_scale_in: type: OS::Heat::ScalingPolicy properties: scaling_adjustment: -1 auto_scaling_group_id: - get_resource: VDU1 + get_resource: VDU1_scale adjustment_type: change_in_capacity - VDU2: + VDU2_scale: type: OS::Heat::AutoScalingGroup - depends_on: VDU1 properties: min_size: 1 max_size: 1 @@ -57,19 +56,19 @@ resources: 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: + VDU2_scale_scale_out: type: OS::Heat::ScalingPolicy properties: scaling_adjustment: 1 auto_scaling_group_id: - get_resource: VDU2 + get_resource: VDU2_scale adjustment_type: change_in_capacity - VDU2_scale_in: + VDU2_scale_scale_in: type: OS::Heat::ScalingPolicy properties: scaling_adjustment: -1 auto_scaling_group_id: - get_resource: VDU2 + get_resource: VDU2_scale adjustment_type: change_in_capacity extmanageNW_1: type: OS::Neutron::Net diff --git a/tacker/tests/etc/samples/etsi/nfv/functional6/Definitions/helloworld3_df_simple.yaml b/tacker/tests/etc/samples/etsi/nfv/functional6/Definitions/helloworld3_df_simple.yaml index 51316e6fb..c3c0ec065 100644 --- a/tacker/tests/etc/samples/etsi/nfv/functional6/Definitions/helloworld3_df_simple.yaml +++ b/tacker/tests/etc/samples/etsi/nfv/functional6/Definitions/helloworld3_df_simple.yaml @@ -273,9 +273,9 @@ topology_template: type: tosca.policies.nfv.ScalingAspects properties: aspects: - worker_instance: - name: worker_instance_aspect - description: worker_instance scaling aspect + VDU2_scale: + name: VDU2_scale + description: VDU2 scaling aspect max_scale_level: 2 step_deltas: - delta_1 @@ -294,14 +294,14 @@ topology_template: number_of_instances: 1 targets: [ VDU2 ] - - VDU1_scaling_aspect_deltas: + - VDU2_scaling_aspect_deltas: type: tosca.policies.nfv.VduScalingAspectDeltas properties: - aspect: worker_instance + aspect: VDU2_scale deltas: delta_1: number_of_instances: 1 - targets: [ VDU1 ] + targets: [ VDU2 ] - instantiation_levels: type: tosca.policies.nfv.InstantiationLevels @@ -310,12 +310,12 @@ topology_template: instantiation_level_1: description: Smallest size scale_info: - worker_instance: + VDU2_scale: scale_level: 0 instantiation_level_2: description: Largest size scale_info: - worker_instance: + VDU2_scale: scale_level: 2 default_level: instantiation_level_1 diff --git a/tacker/tests/etc/samples/nested_hot_data.yaml b/tacker/tests/etc/samples/nested_hot_data.yaml new file mode 100644 index 000000000..1057a5148 --- /dev/null +++ b/tacker/tests/etc/samples/nested_hot_data.yaml @@ -0,0 +1,11 @@ +parameters: + vnf: test + zone: + type: string + +resources: + VDU1: + type: OS::Nova::Server + properties: + availability_zone: { get_param: zone } + diff --git a/tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py b/tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py index b3497bbbd..24d61deed 100644 --- a/tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py +++ b/tacker/tests/unit/vnfm/infra_drivers/openstack/test_openstack_driver.py @@ -185,6 +185,78 @@ class TestOpenStack(base.FixturedTestCase): yaml_file_dict = yaml.safe_load(f) return yaml_file_dict + def _read_nested_file(self): + yaml_file = os.path.abspath(os.path.join(os.path.dirname(__file__), + "../../../../etc/samples/", + "nested_hot_data.yaml")) + with open(yaml_file, 'r') as f: + yaml_file_dict = yaml.safe_load(f) + return yaml_file_dict + + def _get_grant_obj(self, zoneid=None): + 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) + 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}} + + if zoneid: + zone = { + 'id': '5e4da3c3-4a55-412a-b624-843921f8b51d', + 'zone_id': 'nova', + 'vim_connection_id': uuidsentinel.vim_id} + else: + zone = { + 'id': '5e4da3c3-4a55-412a-b624-843921f8b51d', + 'zone_id': '', + 'vim_connection_id': uuidsentinel.vim_id} + + 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] + + return grant_dict + @mock.patch('tacker.vnfm.infra_drivers.openstack.openstack' '.OpenStack._format_base_hot') @mock.patch('tacker.vnflcm.utils._get_vnflcm_interface') @@ -299,6 +371,7 @@ class TestOpenStack(base.FixturedTestCase): mock_find_stack.assert_called_once() mock_update_stack_with_user_data.assert_called_once() + @mock.patch('tacker.tosca.utils.get_scale_group') @mock.patch('tacker.vnfm.vim_client.VimClient.get_vim') @mock.patch('tacker.vnfm.infra_drivers.openstack.openstack' '.OpenStack._format_base_hot') @@ -307,7 +380,11 @@ class TestOpenStack(base.FixturedTestCase): def test_create_grant(self, mock_OpenstackClients_heat, mock_get_base_hot_dict, mock_format_base_hot, - mock_get_vim): + mock_get_vim, mock_get_scale_group): + mock_get_scale_group.return_value = { + 'scaleGroupDict': {'VDU1_scale': {'vdu': ['VDU1'], + 'num': 1, 'maxLevel': 2, 'initialNum': 1, + 'initialLevel': 0, 'default': 1}}} mock_get_vim.return_value = { 'vim_id': uuidsentinel.vnfd_id, 'vim_type': 'test', @@ -331,25 +408,28 @@ class TestOpenStack(base.FixturedTestCase): 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', - 'zone': {'type': 'string'}}, - 'resources': {'VDU1': {'properties': - {'availability_zone': {'get_param': 'zone'}}}}}} + nested_hot_dict = {'VDU1.yaml': self._read_nested_file()} base_hot_dict = self._read_file() - base_hot_dict['resources']['VDU1']['properties'].setdefault( - 'resource', {'properties': {'zone': - {'get_param': ['nfv', 'vdu', 'VDU1', 'zone']}}}) + base_hot_dict['resources'].setdefault( + 'VDU1_scale', + {'properties': {'resource': + {'properties': {'zone': { + 'get_param': ['nfv', 'VDU', 'VDU1', 'zone']}}, + 'type': 'VDU1.yaml'}}, + 'type': 'OS::Heat::AutoScalingGroup'}) 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'}], + 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'}]} + {'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', @@ -375,14 +455,15 @@ class TestOpenStack(base.FixturedTestCase): '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}} + 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 @@ -400,8 +481,8 @@ class TestOpenStack(base.FixturedTestCase): 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'] + 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') @@ -413,6 +494,216 @@ class TestOpenStack(base.FixturedTestCase): grant_info=grant_info_test, vnf_instance=vnf_instance) + @mock.patch('tacker.tosca.utils.get_scale_group') + @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_scale(self, mock_OpenstackClients_heat, + mock_get_base_hot_dict, + mock_format_base_hot, + mock_get_vim, mock_get_scale_group): + mock_get_scale_group.return_value = { + 'scaleGroupDict': {'VDU1_scale': {'vdu': ['VDU1'], + 'num': 1, 'maxLevel': 2, 'initialNum': 1, + 'initialLevel': 0, 'default': 1}}} + 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': self._read_nested_file()} + del nested_hot_dict['VDU1.yaml']['parameters']['zone'] + del (nested_hot_dict['VDU1.yaml']['resources'] + ['VDU1']['properties']['availability_zone']) + base_hot_dict = self._read_file() + base_hot_dict['resources'].setdefault( + 'VDU1_scale', + {'properties': {'resource': + {'properties': {}, + 'type': 'VDU1.yaml'}}, + 'type': 'OS::Heat::AutoScalingGroup'}) + mock_get_base_hot_dict.return_value = \ + base_hot_dict, nested_hot_dict + grant_dict = self._get_grant_obj(zoneid=True) + 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.tosca.utils.get_scale_group') + @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_scale_vdu_nolist(self, mock_OpenstackClients_heat, + mock_get_base_hot_dict, + mock_format_base_hot, + mock_get_vim, mock_get_scale_group): + mock_get_scale_group.return_value = { + 'scaleGroupDict': {'VDU1_scale': {'vdu': ['VDUX'], + 'num': 1, 'maxLevel': 2, 'initialNum': 1, + 'initialLevel': 0, 'default': 1}}} + 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': self._read_nested_file()} + del nested_hot_dict['VDU1.yaml']['parameters']['zone'] + del (nested_hot_dict['VDU1.yaml']['resources'] + ['VDU1']['properties']['availability_zone']) + base_hot_dict = self._read_file() + base_hot_dict['resources'].setdefault( + 'VDU1_scale', + {'properties': {'resource': + {'properties': {}, + 'type': 'VDU1.yaml'}}, + 'type': 'OS::Heat::AutoScalingGroup'}) + mock_get_base_hot_dict.return_value = \ + base_hot_dict, nested_hot_dict + grant_dict = self._get_grant_obj(zoneid=True) + 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_scale_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': self._read_nested_file()} + base_hot_dict = self._read_file() + base_hot_dict['resources'].setdefault( + 'VDU1', + {'properties': {'resource': + {'properties': {'zone': { + 'get_param': ['nfv', 'VDU', 'VDU1', 'zone']}}, + 'type': 'VDU1.yaml'}}, + 'type': 'OS::Heat::AutoScalingGroup'}) + mock_get_base_hot_dict.return_value = \ + base_hot_dict, nested_hot_dict + grant_dict = self._get_grant_obj(zoneid=True) + 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.tosca.utils.get_scale_group') @mock.patch('tacker.vnfm.vim_client.VimClient.get_vim') @mock.patch('tacker.vnfm.infra_drivers.openstack.openstack' '.OpenStack._format_base_hot') @@ -421,7 +712,11 @@ class TestOpenStack(base.FixturedTestCase): 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, mock_get_scale_group): + mock_get_scale_group.return_value = { + 'scaleGroupDict': {'VDU1_scale': {'vdu': ['VDU1'], + 'num': 1, 'maxLevel': 2, 'initialNum': 1, + 'initialLevel': 0, 'default': 1}}} mock_get_vim.return_value = { 'vim_id': uuidsentinel.vnfd_id, 'vim_type': 'test', @@ -445,61 +740,20 @@ class TestOpenStack(base.FixturedTestCase): 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': {}}}}} + nested_hot_dict = {'VDU1.yaml': self._read_nested_file()} + del nested_hot_dict['VDU1.yaml']['parameters']['zone'] + del (nested_hot_dict['VDU1.yaml']['resources']['VDU1'] + ['properties']['availability_zone']) + base_hot_dict = self._read_file() + base_hot_dict['resources'].setdefault( + 'VDU1_scale', + {'properties': {'resource': + {'properties': {}, + 'type': 'VDU1.yaml'}}, + 'type': 'OS::Heat::AutoScalingGroup'}) 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': '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] + base_hot_dict, nested_hot_dict + grant_dict = self._get_grant_obj(zoneid=True) grant_obj = objects.Grant.obj_from_primitive( grant_dict, context=self.context) vnf['grant'] = grant_obj @@ -508,8 +762,8 @@ class TestOpenStack(base.FixturedTestCase): 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'] + 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') @@ -521,6 +775,7 @@ class TestOpenStack(base.FixturedTestCase): grant_info=grant_info_test, vnf_instance=vnf_instance) + @mock.patch('tacker.tosca.utils.get_scale_group') @mock.patch('tacker.vnfm.vim_client.VimClient.get_vim') @mock.patch('tacker.vnfm.infra_drivers.openstack.openstack' '.OpenStack._format_base_hot') @@ -529,7 +784,11 @@ class TestOpenStack(base.FixturedTestCase): 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, mock_get_scale_group): + mock_get_scale_group.return_value = { + 'scaleGroupDict': {'VDU1_scale': {'vdu': ['VDU1'], + 'num': 1, 'maxLevel': 2, 'initialNum': 1, + 'initialLevel': 0, 'default': 1}}} mock_get_vim.return_value = { 'vim_id': uuidsentinel.vnfd_id, 'vim_type': 'test', @@ -553,61 +812,21 @@ class TestOpenStack(base.FixturedTestCase): 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': {}}}}} + nested_hot_dict = {'VDU1.yaml': self._read_nested_file()} + del nested_hot_dict['VDU1.yaml']['parameters']['zone'] + del (nested_hot_dict['VDU1.yaml']['resources']['VDU1'] + ['properties']['availability_zone']) + base_hot_dict = self._read_file() + base_hot_dict['resources'].setdefault( + 'VDU1_scale', + {'properties': + {'resource': + {'properties': {}, + 'type': 'VDU1.yaml'}}, + 'type': 'OS::Heat::AutoScali:ngGroup'}) 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] + base_hot_dict, nested_hot_dict + grant_dict = self._get_grant_obj() grant_obj = objects.Grant.obj_from_primitive( grant_dict, context=self.context) vnf['grant'] = grant_obj @@ -616,8 +835,8 @@ class TestOpenStack(base.FixturedTestCase): 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'] + 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') diff --git a/tacker/vnfm/infra_drivers/openstack/openstack.py b/tacker/vnfm/infra_drivers/openstack/openstack.py index 847e58969..a52412833 100644 --- a/tacker/vnfm/infra_drivers/openstack/openstack.py +++ b/tacker/vnfm/infra_drivers/openstack/openstack.py @@ -185,13 +185,14 @@ class OpenStack(abstract_driver.VnfAbstractDriver, vnfd_dict = yaml.safe_load(vnfd_str) LOG.debug('VNFD: %s', vnfd_dict) LOG.debug('VNF package path: %s', vnf_package_path) - scaling_group_dict = {} + scale_dict = {} + scale_group_dict = {} for name, rsc in base_hot_dict.get('resources').items(): - if rsc['type'] == 'OS::Heat::AutoScalingGroup': - scaling_group_dict[name] = name - if scaling_group_dict: + if rsc['type'] == SCALING_GROUP_RESOURCE: + scale_dict[name] = name + if scale_dict: vnf['attributes']['scaling_group_names'] = \ - jsonutils.dump_as_bytes(scaling_group_dict) + jsonutils.dump_as_bytes(scale_dict) scale_group_dict = \ tosca_utils.get_scale_group(vnf, vnfd_dict, inst_req_info) vnf['attributes']['scale_group'] = \ @@ -249,7 +250,7 @@ class OpenStack(abstract_driver.VnfAbstractDriver, "is not in dict format.") raise vnfm.LCMUserDataFailed(reason=error_reason) - if scaling_group_dict: + if scale_dict: scale_status_list = [] for name, value in scale_group_dict['scaleGroupDict'].items(): key_name = name + '_desired_capacity' @@ -264,7 +265,8 @@ class OpenStack(abstract_driver.VnfAbstractDriver, if vnf.get('grant'): 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) + base_hot_dict, nested_hot_dict, hot_param_dict, + scale_group_dict) # Add stack param to vnf_attributes vnf['attributes'].update({'stack_param': str(hot_param_dict)}) @@ -346,7 +348,8 @@ class OpenStack(abstract_driver.VnfAbstractDriver, @log.log def _setup_hot_for_grant_resources(self, vnf, vnf_instance, - base_hot_dict, nested_hot_dict, hot_param_dict): + base_hot_dict, nested_hot_dict, hot_param_dict, + scale_group_dict=None): """Setup HOT related params for grant resources Update base_hot_dict, nested_hot_dict and hot_param_dict as HOT related @@ -369,42 +372,10 @@ class OpenStack(abstract_driver.VnfAbstractDriver, 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'] + vdu_name = None + bh, nh, hparam = self._setup_hot_for_zone( + ins_inf, addrsc, bh, nh, hparam, + scale_group_dict, vdu_name, zone) if 'vim_assets' in grant and grant.vim_assets: h_vdus = hparam['nfv']['VDU'] @@ -417,6 +388,98 @@ class OpenStack(abstract_driver.VnfAbstractDriver, return bh, nh, hparam + @log.log + def _setup_hot_for_zone(self, ins_inf, addrsc, + base_hot_dict, nested_hot_dict, hot_param_dict, + scale_group_dict, vdu_name, zone): + + 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 + if not vdu_name: + continue + + if scale_group_dict: + base_hot_dict, nested_hot_dict, vdu_none_flg = \ + self._update_hot_available_scale( + base_hot_dict, nested_hot_dict, + scale_group_dict, vdu_name) + + if vdu_none_flg: + base_hot_dict = self._update_hot_not_available_scale( + base_hot_dict, vdu_name) + else: + base_hot_dict = self._update_hot_not_available_scale( + base_hot_dict, vdu_name) + + h_vdu = hot_param_dict['nfv']['VDU'][vdu_name] + if not h_vdu.get('zone') and zone.zone_id: + (hot_param_dict['nfv']['VDU'] + [vdu_name]['zone']) = zone.zone_id + if h_vdu.get('zone') and not zone.zone_id: + del hot_param_dict['nfv']['VDU'][vdu_name]['zone'] + + return base_hot_dict, nested_hot_dict, hot_param_dict + + @log.log + def _update_hot_available_scale(self, base_hot_dict, + nested_hot_dict, scale_group_dict, vdu_name): + vdu_none_flg = True + for aspect in scale_group_dict['scaleGroupDict']: + aspect_id = aspect + + # vdu_list check + if vdu_name not in (scale_group_dict['scaleGroupDict'] + [aspect]['vdu']): + continue + + vdu_none_flg = False + if base_hot_dict['resources'].get(aspect_id): + # base_hot add + vdu_prop = base_hot_dict['resources'][aspect_id]['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']} + # nested_hot add + yaml_name = vdu_prop['resource']['type'] + if not nested_hot_dict[yaml_name]['parameters'].get('zone'): + nested_hot_dict[yaml_name]['parameters']['zone'] = { + 'type': 'string'} + vdu_props = nested_hot_dict[yaml_name]['resources'][vdu_name][ + 'properties'] + if not (vdu_props.get('availability_zone')): + vdu_props['availability_zone'] = { + 'get_param': 'zone'} + + return base_hot_dict, nested_hot_dict, vdu_none_flg + + @log.log + def _update_hot_not_available_scale(self, base_hot_dict, vdu_name): + # base_hot add + if base_hot_dict['resources'].get(vdu_name): + vdu_prop = (base_hot_dict['resources'][vdu_name] + ['properties']) + if base_hot_dict['resources'][vdu_name]['type'] == \ + SCALING_GROUP_RESOURCE: + 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 base_hot_dict['resources'][vdu_name]['type'] == \ + NOVA_SERVER_RESOURCE: + if not vdu_prop.get('availability_zone'): + vdu_prop['availability_zone'] = {'get_param': + 'zone'} + return base_hot_dict + @log.log def _delete_user_data_module(self, user_data_module): # Delete module recursively. @@ -1542,7 +1605,7 @@ class OpenStack(abstract_driver.VnfAbstractDriver, scale_resurce_list = heatclient.resource_get_list( scale_rsc.physical_resource_id) for rsc in scale_resurce_list: - if rsc.resource_type == 'OS::Nova::Server': + if rsc.resource_type == NOVA_SERVER_RESOURCE: if rsc.physical_resource_id not in vnfc_rsc_list: rsc_info = heatclient.resource_get( scale_rsc.physical_resource_id, @@ -1683,7 +1746,7 @@ class OpenStack(abstract_driver.VnfAbstractDriver, after_st_list = [] after_port_list = [] for rsc in resurce_list: - if rsc.resource_type == 'OS::Nova::Server': + if rsc.resource_type == NOVA_SERVER_RESOURCE: after_vnfcs_list.append(rsc.physical_resource_id) if rsc.resource_type == 'OS::Cinder::Volume': after_st_list.append(rsc.physical_resource_id) @@ -1878,7 +1941,7 @@ class OpenStack(abstract_driver.VnfAbstractDriver, nested_hot = yaml.safe_load( vnf_info['attributes'][yaml_name]) for resource_name, resource in nested_hot['resources'].items(): - if resource['type'] == 'OS::Nova::Server': + if resource['type'] == NOVA_SERVER_RESOURCE: for i in range(size): add_uuid = uuidutils.generate_uuid() rsc = objects.ResourceDefinition( @@ -1978,7 +2041,7 @@ class OpenStack(abstract_driver.VnfAbstractDriver, for del_rsc in del_list: scale_resurce_list = heatclient.resource_get_list(del_rsc) for rsc in scale_resurce_list: - if rsc.resource_type == 'OS::Nova::Server': + if rsc.resource_type == NOVA_SERVER_RESOURCE: for vnfc_resource in inst_info.vnfc_resource_info: if vnfc_resource.\ compute_resource.resource_id == \