def step1(self):
        LOG.info('Starting %s' % self.tc_name)

        # --------------------------------------------------------------------------------------------------------------
        # 1. Trigger NS instantiation on the NFVO
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Triggering NS instantiation on the NFVO')
        self.time_record.START('instantiate_ns')
        self.ns_instance_id, operation_status = self.mano.ns_create_and_instantiate(
            nsd_id=self.tc_input['nsd_id'],
            ns_name=generate_name(self.tc_name),
            ns_description=self.tc_input.get('ns_description'),
            flavour_id=self.tc_input.get('flavour_id'),
            sap_data=self.tc_input['mano'].get('sap_data'),
            pnf_info=self.tc_input.get('pnf_info'),
            vnf_instance_data=self.tc_input.get('vnf_instance_data'),
            nested_ns_instance_data=self.tc_input.get(
                'nested_ns_instance_data'),
            location_constraints=self.tc_input.get('location_constraints'),
            additional_param_for_ns=self.tc_input['mano'].get(
                'instantiation_params_for_ns'),
            additional_param_for_vnf=self.tc_input['mano'].get(
                'instantiation_params_for_vnf'),
            start_time=self.tc_input.get('start_time'),
            ns_instantiation_level_id=self.tc_input.get(
                'ns_instantiation_level_id'),
            additional_affinity_or_anti_affinity_rule=self.tc_input.get(
                'additional_affinity_or_anti_affinity_rule'))

        self.register_for_cleanup(
            index=10,
            function_reference=self.mano.ns_terminate_and_delete,
            verify_result=True,
            expected_result=constants.OPERATION_SUCCESS,
            ns_instance_id=self.ns_instance_id,
            terminate_time=self.tc_input.get('terminate_time'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.wait_for_ns_stable_state,
            ns_instance_id=self.ns_instance_id)

        if operation_status != constants.OPERATION_SUCCESS:
            self.tc_result['events']['instantiate_ns']['details'] = 'Fail'
            raise TestRunError('NS instantiation operation failed')

        self.time_record.END('instantiate_ns')

        self.tc_result['events']['instantiate_ns'][
            'duration'] = self.time_record.duration('instantiate_ns')
        self.tc_result['events']['instantiate_ns']['details'] = 'Success'

        LOG.debug(
            'Sleeping %s seconds to allow the VDUs to complete first boot' %
            constants.INSTANCE_FIRST_BOOT_TIME)
        sleep(constants.INSTANCE_FIRST_BOOT_TIME)
Exemplo n.º 2
0
 def create_session(self):
     try:
         user_name = 'vnflcv'
         session_name = generate_name('session')
         self.session = self.stc.new_session(user_name=user_name,
                                             session_name=session_name,
                                             kill_existing=True)
         self.project = self.stc.create(object_type='project')
     except Exception as e:
         LOG.exception(e)
         raise StcTrafficAdapterError('Unable to create session - %s' % e)
Exemplo n.º 3
0
    def step1(self):
        # TODO: Move this in generic?
        LOG.info('Starting %s' % self.tc_name)

        # --------------------------------------------------------------------------------------------------------------
        # 1. Instantiate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the VNF')
        self.time_record.START('instantiate_vnf')
        self.vnf_instance_id = self.mano.vnf_create_and_instantiate(
            vnfd_id=self.tc_input['vnfd_id'],
            flavour_id=self.tc_input.get('flavour_id'),
            vnf_instance_name=generate_name(self.tc_name),
            vnf_instance_description=self.tc_input.get(
                'vnf_instance_description'),
            instantiation_level_id=self.tc_input.get('instantiation_level_id'),
            ext_virtual_link=self.tc_input.get('ext_virtual_link'),
            ext_managed_virtual_link=self.tc_input.get(
                'ext_managed_virtual_link'),
            localization_language=self.tc_input.get('localization_language'),
            additional_param=self.tc_input['mano'].get('instantiation_params'))

        self.time_record.END('instantiate_vnf')

        self.tc_result['events']['instantiate_vnf'][
            'duration'] = self.time_record.duration('instantiate_vnf')

        self.register_for_cleanup(
            index=10,
            function_reference=self.mano.vnf_terminate_and_delete,
            vnf_instance_id=self.vnf_instance_id,
            termination_type='graceful',
            graceful_termination_timeout=self.tc_input.get(
                'graceful_termination_timeout'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.wait_for_vnf_stable_state,
            vnf_instance_id=self.vnf_instance_id)
Exemplo n.º 4
0
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # Get scaling policy properties
        sp = self.mano.get_nsd_scaling_properties(
            self.tc_input['nsd_id'], self.tc_input['scaling_policy_name'])

        # --------------------------------------------------------------------------------------------------------------
        # 1. Instantiate the NS
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the NS')
        self.time_record.START('instantiate_ns')
        self.ns_instance_id = self.mano.ns_create_and_instantiate(
            nsd_id=self.tc_input['nsd_id'],
            ns_name=generate_name(self.tc_name),
            ns_description=self.tc_input.get('ns_description'),
            flavour_id=self.tc_input.get('flavour_id'),
            sap_data=self.tc_input['mano'].get('sap_data'),
            pnf_info=self.tc_input.get('pnf_info'),
            vnf_instance_data=self.tc_input.get('vnf_instance_data'),
            nested_ns_instance_data=self.tc_input.get(
                'nested_ns_instance_data'),
            location_constraints=self.tc_input.get('location_constraints'),
            additional_param_for_ns=self.tc_input['mano'].get(
                'instantiation_params_for_ns'),
            additional_param_for_vnf=self.tc_input['mano'].get(
                'instantiation_params_for_vnf'),
            start_time=self.tc_input.get('start_time'),
            ns_instantiation_level_id=self.tc_input.get(
                'ns_instantiation_level_id'),
            additional_affinity_or_anti_affinity_rule=self.tc_input.get(
                'additional_affinity_or_anti_affinity_rule'))

        self.time_record.END('instantiate_ns')

        self.tc_result['events']['instantiate_ns'][
            'duration'] = self.time_record.duration('instantiate_ns')

        self.register_for_cleanup(
            index=10,
            function_reference=self.mano.ns_terminate_and_delete,
            ns_instance_id=self.ns_instance_id,
            terminate_time=self.tc_input.get('terminate_time'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.wait_for_ns_stable_state,
            ns_instance_id=self.ns_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Validate NS state is INSTANTIATED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating NS state is INSTANTIATED')
        ns_info = self.mano.ns_query(
            query_filter={'ns_instance_id': self.ns_instance_id})
        if ns_info.ns_state != constants.NS_INSTANTIATED:
            raise TestRunError(
                'Unexpected NS state',
                err_details=
                'NS state was not "%s" after the NS was instantiated' %
                constants.NS_INSTANTIATED)

        # --------------------------------------------------------------------------------------------------------------
        # 3. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')

        # Get the instance ID of the VNF inside the NS
        self.vnf_instance_id = ns_info.vnf_info_id[0]

        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        self.tc_result['resources'][
            'Initial'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 4. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')
        self.traffic.configure(
            traffic_load='LOW_TRAFFIC_LOAD',
            traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=30,
                                  function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=40,
                                  function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 5. Validate the provided functionality and all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating the provided functionality and all traffic goes through'
        )
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_before'] = 'LOW_TRAFFIC_LOAD'

        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        # --------------------------------------------------------------------------------------------------------------
        # 6. Trigger a resize of the NS resources to the next level by instructing the MANO to scale out the NS
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Triggering a resize of the NS resources to the next level by instructing the MANO to scale out the '
            'NS')

        # Build the ScaleNsData information element
        scale_ns_data = ScaleNsData()
        scale_ns_data.scale_ns_by_steps_data = ScaleNsByStepsData()
        scale_ns_data.scale_ns_by_steps_data.scaling_direction = 'scale_out'
        scale_ns_data.scale_ns_by_steps_data.aspect_id = sp['targets']
        scale_ns_data.scale_ns_by_steps_data.number_of_steps = sp['increment']

        self.time_record.START('scale_out_ns')
        if self.mano.ns_scale_sync(self.ns_instance_id, scale_type='SCALE_NS', scale_ns_data=scale_ns_data,
                                   scale_time=self.tc_input.get('scale_time')) \
                != constants.OPERATION_SUCCESS:
            self.tc_result['scaling_out']['status'] = 'Fail'
            raise TestRunError('MANO could not scale out the NS')

        self.time_record.END('scale_out_ns')

        self.tc_result['events']['scale_out_ns'][
            'duration'] = self.time_record.duration('scale_out_ns')

        # --------------------------------------------------------------------------------------------------------------
        # 7. Validate NS has resized to the next level
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating NS has resized to the next level')
        ns_info = self.mano.ns_query(
            query_filter={'ns_instance_id': self.ns_instance_id})
        if len(ns_info.vnf_info_id
               ) != sp['default_instances'] + sp['increment']:
            raise TestRunError('VNFs not added after NS scaled out')

        self.tc_result['resources']['After scale out'] = {}
        for vnf_instance_id in ns_info.vnf_info_id:
            self.tc_result['resources']['After scale out'].update(
                self.mano.get_allocated_vresources(
                    vnf_instance_id,
                    self.tc_input['mano'].get('query_params')))

        self.tc_result['scaling_out'][
            'level'] = sp['default_instances'] + sp['increment']

        self.tc_result['scaling_out']['status'] = 'Success'

        # --------------------------------------------------------------------------------------------------------------
        # 8. Determine if and length of service disruption
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Determining if and length of service disruption')
        self.tc_result['events']['service_disruption'][
            'duration'] = self.traffic.calculate_service_disruption_length()

        # --------------------------------------------------------------------------------------------------------------
        # 9. Start the normal traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the normal traffic load')

        # Stop the low traffic load.
        self.traffic.stop()

        # Configure stream destination address(es).
        dest_addr_list = ''
        for vnf_instance_id in ns_info.vnf_info_id:
            vnf_info = self.mano.vnf_query(
                query_filter={
                    'vnf_instance_id': vnf_instance_id,
                    'additional_param': self.tc_input['mano'].get(
                        'query_params')
                })
            for ext_cp_info in vnf_info.instantiated_vnf_info.ext_cp_info:
                if ext_cp_info.cpd_id == self.tc_input['traffic'][
                        'traffic_config']['ingress_cp_name']:
                    dest_addr_list += ext_cp_info.address[0] + ' '

        self.traffic.reconfig_traffic_dest(dest_addr_list)
        self.traffic.config_traffic_load('NORMAL_TRAFFIC_LOAD')

        # Start the normal traffic load.
        self.traffic.start(return_when_emission_starts=True)

        # --------------------------------------------------------------------------------------------------------------
        # 10. Validate increased capacity without traffic loss
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating increased capacity without traffic loss')
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Normal traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError(
                'Traffic is flowing with packet loss',
                err_details='Normal traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_after'] = 'NORMAL_TRAFFIC_LOAD'
        self.tc_result['scaling_in']['traffic_before'] = 'NORMAL_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 11. Trigger the downsize of the NS by instructing the MANO to scale in the NS
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Triggering the downsize of the NS by instructing the MANO to scale in the NS'
        )

        # Update the ScaleNsData information element
        scale_ns_data.scale_ns_by_steps_data.scaling_direction = 'scale_in'

        self.time_record.START('scale_in_ns')
        if self.mano.ns_scale_sync(self.ns_instance_id, scale_type='SCALE_NS', scale_ns_data=scale_ns_data,
                                   scale_time=self.tc_input.get('scale_time')) \
                != constants.OPERATION_SUCCESS:
            self.tc_result['scaling_out']['status'] = 'Fail'
            raise TestRunError('MANO could not scale in the NS')

        self.time_record.END('scale_in_ns')

        self.tc_result['events']['scale_in_ns'][
            'duration'] = self.time_record.duration('scale_in_ns')

        # --------------------------------------------------------------------------------------------------------------
        # 12. Validate NS has released the resources and decreased the VNFs
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating NS has released the resources and decreased the VNFs')
        ns_info = self.mano.ns_query(
            query_filter={'ns_instance_id': self.ns_instance_id})
        if len(ns_info.vnf_info_id) != sp['default_instances']:
            raise TestRunError('NS did not scale in')

        self.vnf_instance_id = ns_info.vnf_info_id[0]
        self.tc_result['resources'][
            'After scale in'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        self.tc_result['scaling_in']['level'] = sp['default_instances']

        self.tc_result['scaling_in']['status'] = 'Success'

        # --------------------------------------------------------------------------------------------------------------
        # 13. Validate traffic drop occurred
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating traffic drop occurred')
        if not self.traffic.any_traffic_loss():
            raise TestRunError('Normal traffic flew without packet loss')

        # --------------------------------------------------------------------------------------------------------------
        # 14. Reduce traffic load to level that the downsized NS should process
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Reducing traffic load to level that the downsized NS should process'
        )

        # Stop the normal traffic load.
        self.traffic.stop()

        # Configure stream destination address(es)
        dest_addr_list = ''
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        for ext_cp_info in vnf_info.instantiated_vnf_info.ext_cp_info:
            if ext_cp_info.cpd_id == self.tc_input['traffic'][
                    'traffic_config']['ingress_cp_name']:
                dest_addr_list += ext_cp_info.address[0] + ' '

        self.traffic.reconfig_traffic_dest(dest_addr_list)
        self.traffic.config_traffic_load('LOW_TRAFFIC_LOAD')

        # Start the low traffic load.
        self.traffic.start(return_when_emission_starts=True)

        # --------------------------------------------------------------------------------------------------------------
        # 15. Validate traffic flows through without issues
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating traffic flows through without issues')
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_in']['traffic_after'] = 'LOW_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 16. Terminate the NS
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the NS')
        self.time_record.START('terminate_ns')
        if self.mano.ns_terminate_sync(ns_instance_id=self.ns_instance_id,
                                       terminate_time=self.tc_input.get('terminate_time'),
                                       additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for NS termination operation',
                err_details='NS termination operation failed')

        self.time_record.END('terminate_ns')

        self.tc_result['events']['terminate_ns'][
            'duration'] = self.time_record.duration('terminate_ns')

        self.unregister_from_cleanup(index=20)
        self.unregister_from_cleanup(index=10)

        self.register_for_cleanup(index=10,
                                  function_reference=self.mano.ns_delete_id,
                                  ns_instance_id=self.ns_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 17. Validate that the NS is terminated and that all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the NS is terminated')
        ns_info_final = self.mano.ns_query(
            query_filter={
                'ns_instance_id': self.ns_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if ns_info_final.ns_state != constants.NS_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected NS instantiation state',
                err_details=
                'NS instantiation state was not "%s" after the NS was terminated'
                % constants.NS_NOT_INSTANTIATED)

        LOG.info('Verifying that all the VNF instance(s) have been terminated')
        for vnf_info in ns_info.vnf_info:
            vnf_instance_id = vnf_info.vnf_instance_id
            vnf_info = self.mano.vnf_query(
                query_filter={
                    'vnf_instance_id': vnf_instance_id,
                    'additional_param': self.tc_input['mano'].get(
                        'query_params')
                })
            if vnf_info.instantiation_state != constants.VNF_NOT_INSTANTIATED:
                raise TestRunError(
                    'VNF instance %s was not terminated correctly. Expected state was %s but got %s'
                    % (vnf_instance_id, constants.VNF_NOT_INSTANTIATED,
                       vnf_info.instantiation_state))

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_ns_released_vresources(ns_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # Get scaling policy properties
        sp = self.mano.get_vnfd_scaling_properties(
            self.tc_input['vnfd_id'], self.tc_input['scaling_policy_name'])

        # --------------------------------------------------------------------------------------------------------------
        # 1. Instantiate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the VNF')
        self.time_record.START('instantiate_vnf')
        self.vnf_instance_id = self.mano.vnf_create_and_instantiate(
            vnfd_id=self.tc_input['vnfd_id'],
            flavour_id=self.tc_input.get('flavour_id'),
            vnf_instance_name=generate_name(self.tc_name),
            vnf_instance_description=self.tc_input.get(
                'vnf_instance_description'),
            instantiation_level_id=self.tc_input.get('instantiation_level_id'),
            ext_virtual_link=self.tc_input.get('ext_virtual_link'),
            ext_managed_virtual_link=self.tc_input.get(
                'ext_managed_virtual_link'),
            localization_language=self.tc_input.get('localization_language'),
            additional_param=self.tc_input['mano'].get('instantiation_params'))

        self.time_record.END('instantiate_vnf')

        self.tc_result['events']['instantiate_vnf'][
            'duration'] = self.time_record.duration('instantiate_vnf')

        self.register_for_cleanup(
            index=10,
            function_reference=self.mano.vnf_terminate_and_delete,
            vnf_instance_id=self.vnf_instance_id,
            termination_type='graceful',
            graceful_termination_timeout=self.tc_input.get(
                'graceful_termination_timeout'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.wait_for_vnf_stable_state,
            vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        self.tc_result['resources'][
            'Initial'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 3. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')
        self.traffic.configure(
            traffic_load='LOW_TRAFFIC_LOAD',
            traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=30,
                                  function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=40,
                                  function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 4. Validate the provided functionality and all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating the provided functionality and all traffic goes through'
        )
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_before'] = 'LOW_TRAFFIC_LOAD'

        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        # --------------------------------------------------------------------------------------------------------------
        # 5. Trigger a resize of the VNF resources to the next level by instructing the MANO to scale out the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Triggering a resize of the VNF resources to the next level by instructing the MANO to scale out the '
            'VNF')
        self.time_record.START('scale_out_vnf')
        if self.mano.vnf_scale_sync(self.vnf_instance_id, scale_type='out', aspect_id=sp['targets'],
                                    additional_param={'scaling_policy_name': self.tc_input['scaling_policy_name']}) \
                != constants.OPERATION_SUCCESS:
            self.tc_result['scaling_out']['status'] = 'Fail'
            raise TestRunError('MANO could not scale out the VNF')

        self.time_record.END('scale_out_vnf')

        self.tc_result['events']['scale_out_vnf'][
            'duration'] = self.time_record.duration('scale_out_vnf')

        # --------------------------------------------------------------------------------------------------------------
        # 6. Validate VNF has resized to the next level
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF has resized to the next level')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if len(vnf_info.instantiated_vnf_info.vnfc_resource_info
               ) != sp['default_instances'] + sp['increment']:
            raise TestRunError('VNF did not scale out to the next level')

        self.tc_result['resources'][
            'After scale out'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        self.tc_result['scaling_out'][
            'level'] = sp['default_instances'] + sp['increment']

        self.tc_result['scaling_out']['status'] = 'Success'

        # --------------------------------------------------------------------------------------------------------------
        # 7. Determine if and length of service disruption
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Determining if and length of service disruption')
        self.tc_result['events']['service_disruption'][
            'duration'] = self.traffic.calculate_service_disruption_length()

        # --------------------------------------------------------------------------------------------------------------
        # 8. Start the normal traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the normal traffic load')

        # Stop the low traffic load.
        self.traffic.stop()

        # Configure stream destination address(es).
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.config_traffic_load('NORMAL_TRAFFIC_LOAD')

        # Start the normal traffic load.
        self.traffic.start(return_when_emission_starts=True)

        # --------------------------------------------------------------------------------------------------------------
        # 9. Validate increased capacity without traffic loss
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating incrreased capacity without traffic loss')
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Normal traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError(
                'Traffic is flowing with packet loss',
                err_details='Normal traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_after'] = 'NORMAL_TRAFFIC_LOAD'
        self.tc_result['scaling_in']['traffic_before'] = 'NORMAL_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 10. Trigger the downsize of the VNF by instructing the MANO to scale in the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Triggering the downsize of the VNF by instructing the MANO to scale in the VNF'
        )
        self.time_record.START('scale_in_vnf')
        if self.mano.vnf_scale_sync(self.vnf_instance_id, scale_type='in', aspect_id=sp['targets'],
                                    additional_param={'scaling_policy_name': self.tc_input['scaling_policy_name']}) \
                != constants.OPERATION_SUCCESS:
            self.tc_result['scaling_in']['status'] = 'Fail'
            raise TestRunError('MANO could not scale in the VNF')

        self.time_record.END('scale_in_vnf')

        self.tc_result['events']['scale_in_vnf'][
            'duration'] = self.time_record.duration('scale_in_vnf')

        # --------------------------------------------------------------------------------------------------------------
        # 11. Validate VNF has released the resources and decreased the VNFCs
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating VNF has released the resources and decreased the VNFCs'
        )
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if len(vnf_info.instantiated_vnf_info.vnfc_resource_info
               ) != sp['min_instances']:
            raise TestRunError('VNF did not scale in')

        self.tc_result['resources'][
            'After scale in'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        self.tc_result['scaling_in']['level'] = sp['min_instances']

        self.tc_result['scaling_in']['status'] = 'Success'

        # --------------------------------------------------------------------------------------------------------------
        # 12. Validate traffic drop occurred
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating traffic drop occurred')
        if not self.traffic.any_traffic_loss():
            raise TestRunError('Max traffic flew without packet loss')

        # --------------------------------------------------------------------------------------------------------------
        # 13. Reduce traffic load to level that the downsized VNF should process
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Reducing traffic load to level that the downsized VNF should process'
        )

        # Stop the normal traffic load.
        self.traffic.stop()

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.config_traffic_load('LOW_TRAFFIC_LOAD')

        # Start the low traffic load.
        self.traffic.start(return_when_emission_starts=True)

        # --------------------------------------------------------------------------------------------------------------
        # 14. Validate traffic flows through without issues
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating traffic flows through without issues')
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_in']['traffic_after'] = 'LOW_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 15. Terminate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the VNF')
        self.time_record.START('terminate_vnf')
        if self.mano.vnf_terminate_sync(self.vnf_instance_id, termination_type='graceful',
                                        graceful_termination_timeout=self.tc_input.get('graceful_termination_timeout'),
                                        additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for terminating VNF operation',
                err_details='VNF terminate operation failed')

        self.time_record.END('terminate_vnf')

        self.tc_result['events']['terminate_vnf'][
            'duration'] = self.time_record.duration('terminate_vnf')

        self.unregister_from_cleanup(index=20)
        self.unregister_from_cleanup(index=10)

        self.register_for_cleanup(index=10,
                                  function_reference=self.mano.vnf_delete_id,
                                  vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 16. Validate that the VNF is terminated and all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the VNF is terminated')
        vnf_info_final = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info_final.instantiation_state != constants.VNF_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was terminated'
                % constants.VNF_NOT_INSTANTIATED)

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_vnf_released_vresources(
                vnf_info_initial=vnf_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # Get scaling policy properties
        sp = self.mano.get_vnfd_scaling_properties(
            self.tc_input['vnfd_id'], self.tc_input['scaling_policy_name'])

        # --------------------------------------------------------------------------------------------------------------
        # 1. Instantiate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the VNF')
        self.time_record.START('instantiate_vnf')
        self.vnf_instance_id = self.mano.vnf_create_and_instantiate(
            vnfd_id=self.tc_input['vnfd_id'],
            flavour_id=self.tc_input.get('flavour_id'),
            vnf_instance_name=generate_name(self.tc_name),
            vnf_instance_description=self.tc_input.get(
                'vnf_instance_description'),
            instantiation_level_id=self.tc_input.get('instantiation_level_id'),
            ext_virtual_link=self.tc_input.get('ext_virtual_link'),
            ext_managed_virtual_link=self.tc_input.get(
                'ext_managed_virtual_link'),
            localization_language=self.tc_input.get('localization_language'),
            additional_param=self.tc_input['mano'].get('instantiation_params'))

        self.time_record.END('instantiate_vnf')

        self.tc_result['events']['instantiate_vnf'][
            'duration'] = self.time_record.duration('instantiate_vnf')

        self.register_for_cleanup(
            index=10,
            function_reference=self.mano.vnf_terminate_and_delete,
            vnf_instance_id=self.vnf_instance_id,
            termination_type='graceful',
            graceful_termination_timeout=self.tc_input.get(
                'graceful_termination_timeout'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.wait_for_vnf_stable_state,
            vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        self.tc_result['resources'][
            'Initial'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 3. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')
        self.traffic.configure(
            traffic_load='LOW_TRAFFIC_LOAD',
            traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=30,
                                  function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=40,
                                  function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 4. Validate the provided functionality and all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating the provided functionality and all traffic goes through'
        )
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_before'] = 'LOW_TRAFFIC_LOAD'

        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        # --------------------------------------------------------------------------------------------------------------
        # 5. Trigger a resize of the VNF resources to the maximum by increasing the traffic load to the maximum
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Triggering a resize of the VNF resources to the maximum by increasing the traffic load to the '
            'maximum')
        self.traffic.config_traffic_load('MAX_TRAFFIC_LOAD')

        # --------------------------------------------------------------------------------------------------------------
        # 6. Validate VNF has resized to the max
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF has resized to the max')
        # The scale out duration will include:
        # - the time it takes the VNF CPU load to increase (caused by the max traffic load)
        # - the time after which the scaling alarm is triggered
        # - the time it takes the VNF to scale out
        self.time_record.START('scale_out_vnf')
        elapsed_time = 0
        while elapsed_time < constants.VNF_SCALE_TIMEOUT:
            vnf_info = self.mano.vnf_query(
                query_filter={
                    'vnf_instance_id': self.vnf_instance_id,
                    'additional_param': self.tc_input['mano'].get(
                        'query_params')
                })
            if len(vnf_info.instantiated_vnf_info.vnfc_resource_info
                   ) == sp['max_instances']:
                break
            else:
                sleep(constants.POLL_INTERVAL)
                elapsed_time += constants.POLL_INTERVAL
            if elapsed_time == constants.VNF_SCALE_TIMEOUT:
                self.tc_result['scaling_out']['status'] = 'Fail'
                raise TestRunError('VNF has not resized to the max')

        self.time_record.END('scale_out_vnf')

        self.tc_result['events']['scale_out_vnf'][
            'duration'] = self.time_record.duration('scale_out_vnf')

        self.tc_result['resources'][
            'After scale out'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        self.tc_result['scaling_out']['level'] = sp['max_instances']

        self.tc_result['scaling_out']['status'] = 'Success'

        # --------------------------------------------------------------------------------------------------------------
        # 7. Determine if and length of service disruption
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Determining if and length of service disruption')
        self.tc_result['events']['service_disruption'][
            'duration'] = self.traffic.calculate_service_disruption_length()

        # --------------------------------------------------------------------------------------------------------------
        # 8. Validate max capacity without traffic loss
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating max capacity without traffic loss')
        # Because the VNF scaled out, we need to reconfigure traffic so that it passes through all VNFCs.

        # Stop the max traffic load.
        self.traffic.stop()

        # Configure stream destination address(es).
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.clear_counters()

        # Start the max traffic load.
        self.traffic.start(return_when_emission_starts=True)

        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Max traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Max traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_after'] = 'MAX_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 9. Terminate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the VNF')
        self.time_record.START('terminate_vnf')
        if self.mano.vnf_terminate_sync(self.vnf_instance_id, termination_type='graceful',
                                        graceful_termination_timeout=self.tc_input.get('graceful_termination_timeout'),
                                        additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for terminating VNF operation',
                err_details='VNF terminate operation failed')

        self.time_record.END('terminate_vnf')

        self.tc_result['events']['terminate_vnf'][
            'duration'] = self.time_record.duration('terminate_vnf')

        self.unregister_from_cleanup(index=20)
        self.unregister_from_cleanup(index=10)

        self.register_for_cleanup(index=10,
                                  function_reference=self.mano.vnf_delete_id,
                                  vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 10. Validate that the VNF is terminated and all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the VNF is terminated')
        vnf_info_final = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info_final.instantiation_state != constants.VNF_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was terminated'
                % constants.VNF_NOT_INSTANTIATED)

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_vnf_released_vresources(
                vnf_info_initial=vnf_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
Exemplo n.º 7
0
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # --------------------------------------------------------------------------------------------------------------
        # 1. Instantiate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the VNF')
        self.time_record.START('instantiate_vnf')
        self.vnf_instance_id = self.mano.vnf_create_and_instantiate(
            vnfd_id=self.tc_input['vnfd_id'],
            flavour_id=self.tc_input.get('flavour_id'),
            vnf_instance_name=generate_name(self.tc_name),
            vnf_instance_description=self.tc_input.get(
                'vnf_instance_description'),
            instantiation_level_id=self.tc_input.get('instantiation_level_id'),
            ext_virtual_link=self.tc_input.get('ext_virtual_link'),
            ext_managed_virtual_link=self.tc_input.get(
                'ext_managed_virtual_link'),
            localization_language=self.tc_input.get('localization_language'),
            additional_param=self.tc_input['mano'].get('instantiation_params'))

        self.time_record.END('instantiate_vnf')

        self.tc_result['events']['instantiate_vnf'][
            'duration'] = self.time_record.duration('instantiate_vnf')

        self.register_for_cleanup(
            index=10,
            function_reference=self.mano.vnf_terminate_and_delete,
            vnf_instance_id=self.vnf_instance_id,
            termination_type='graceful',
            graceful_termination_timeout=self.tc_input.get(
                'graceful_termination_timeout'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.wait_for_vnf_stable_state,
            vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        initial_instances = len(
            vnf_info.instantiated_vnf_info.vnfc_resource_info)

        # --------------------------------------------------------------------------------------------------------------
        # 3. Start the normal traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the normal traffic load')
        self.traffic.configure(
            traffic_load='NORMAL_TRAFFIC_LOAD',
            traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=30,
                                  function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=40,
                                  function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 4. Validate traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating traffic goes through')
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Normal traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError(
                'Traffic is flowing with packet loss',
                err_details='Normal traffic flew with packet loss')

        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        self.tc_result['resources'][
            'Initial'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 5. Stop the normal traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Stopping the normal traffic load')
        self.traffic.stop()

        # --------------------------------------------------------------------------------------------------------------
        # 6. Stop the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Stopping the VNF')
        self.time_record.START('stop_vnf')
        if self.mano.vnf_operate_sync(self.vnf_instance_id, change_state_to='stop',
                                      stop_type=self.tc_input.get('stop_type'),
                                      graceful_stop_timeout=self.tc_input.get('graceful_stop_timeout'),
                                      additional_param=self.tc_input['mano'].get('operate_params')) \
                != constants.OPERATION_SUCCESS:
            raise TestRunError('MANO could not stop the VNF')
        self.time_record.END('stop_vnf')

        self.tc_result['events']['stop_vnf'][
            'duration'] = self.time_record.duration('stop_vnf')

        # --------------------------------------------------------------------------------------------------------------
        # 7. Validate VNF instantiation state is INSTANTIATED and VNF state is STOPPED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was stopped'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STOPPED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STOPPED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details='VNF state was not "%s" after the VNF was stopped'
                % constants.VNF_STOPPED)

        # --------------------------------------------------------------------------------------------------------------
        # 8. Start the normal traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the normal traffic load')
        self.traffic.start(return_when_emission_starts=False)

        # --------------------------------------------------------------------------------------------------------------
        # 9. Validate no traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating no traffic goes through')
        if self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError(
                'Traffic is flowing',
                err_details='Traffic flew before VNF was started')

        # --------------------------------------------------------------------------------------------------------------
        # 10. Start the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the VNF')
        self.time_record.START('start_vnf')
        if self.mano.vnf_operate_sync(self.vnf_instance_id, change_state_to='start',
                                      additional_param=self.tc_input['mano'].get('operate_params')) \
                != constants.OPERATION_SUCCESS:
            raise TestRunError('MANO could not start the VNF')
        self.time_record.END('start_vnf')

        self.tc_result['events']['start_vnf'][
            'duration'] = self.time_record.duration('start_vnf')

        # --------------------------------------------------------------------------------------------------------------
        # 11. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was started'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details='VNF state was not "%s" after the VNF was started'
                % constants.VNF_STARTED)

        # --------------------------------------------------------------------------------------------------------------
        # 12. Calculate the time for activation
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Calculating the time for traffic activation')
        self.tc_result['events']['traffic_activation'][
            'duration'] = self.traffic.calculate_activation_time()

        # --------------------------------------------------------------------------------------------------------------
        # 13. Validate traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating traffic goes through')

        # Clearing counters as the traffic lost so far influences the results
        self.traffic.clear_counters()

        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Normal traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError(
                'Traffic is flowing with packet loss',
                err_details='Normal traffic flew with packet loss')

        # --------------------------------------------------------------------------------------------------------------
        # 14. Validate no scaling has occurred
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating no scaling has occurred')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if len(vnf_info.instantiated_vnf_info.vnfc_resource_info
               ) != initial_instances:
            raise TestRunError('VNF scaling occurred')

        # --------------------------------------------------------------------------------------------------------------
        # 15. Stop the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Stopping the VNF')
        if self.mano.vnf_operate_sync(self.vnf_instance_id, change_state_to='stop',
                                      stop_type=self.tc_input.get('stop_type'),
                                      graceful_stop_timeout=self.tc_input.get('graceful_stop_timeout'),
                                      additional_param=self.tc_input['mano'].get('operate_params')) \
                != constants.OPERATION_SUCCESS:
            raise TestRunError('MANO could not stop the VNF')

        # --------------------------------------------------------------------------------------------------------------
        # 16. Validate that no traffic flows once stop is completed
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that no traffic flows once stop is completed')
        if self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError(
                'Traffic is still flowing',
                err_details='Traffic still flew after VNF was stopped')

        # --------------------------------------------------------------------------------------------------------------
        # 17. Terminate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the VNF')
        self.time_record.START('terminate_vnf')
        if self.mano.vnf_terminate_sync(self.vnf_instance_id, termination_type='graceful',
                                        graceful_termination_timeout=self.tc_input.get('graceful_termination_timeout'),
                                        additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for terminating VNF operation',
                err_details='VNF terminate operation failed')

        self.time_record.END('terminate_vnf')

        self.tc_result['events']['terminate_vnf'][
            'duration'] = self.time_record.duration('terminate_vnf')

        self.unregister_from_cleanup(index=20)
        self.unregister_from_cleanup(index=10)

        self.register_for_cleanup(index=10,
                                  function_reference=self.mano.vnf_delete_id,
                                  vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 18. Validate that the VNF is terminated and all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the VNF is terminated')
        vnf_info_final = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info_final.instantiation_state != constants.VNF_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was terminated'
                % constants.VNF_NOT_INSTANTIATED)

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_vnf_released_vresources(
                vnf_info_initial=vnf_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
Exemplo n.º 8
0
    def run(self):
        LOG.info('Starting %s' % self.tc_name)
        # TODO: Check the VNFD to see if hardware acceleration is present. This check will be added after we create an
        # internal representation for the VNFD.

        # Get scaling policy properties
        sp = self.mano.get_vnfd_scaling_properties(
            self.tc_input['vnfd_id'], self.tc_input['scaling_policy_name'])

        # --------------------------------------------------------------------------------------------------------------
        # 1. Instantiate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the VNF')
        self.time_record.START('instantiate_vnf')
        self.vnf_instance_id = self.mano.vnf_create_and_instantiate(
            vnfd_id=self.tc_input['vnfd_id'],
            flavour_id=self.tc_input.get('flavour_id'),
            vnf_instance_name=generate_name(self.tc_name),
            vnf_instance_description=self.tc_input.get(
                'vnf_instance_description'),
            instantiation_level_id=self.tc_input.get('instantiation_level_id'),
            ext_virtual_link=self.tc_input.get('ext_virtual_link'),
            ext_managed_virtual_link=self.tc_input.get(
                'ext_managed_virtual_link'),
            localization_language=self.tc_input.get('localization_language'),
            additional_param=self.tc_input['mano'].get('instantiation_params'))

        self.time_record.END('instantiate_vnf')

        self.tc_result['events']['instantiate_vnf'][
            'duration'] = self.time_record.duration('instantiate_vnf')

        self.register_for_cleanup(
            index=10,
            function_reference=self.mano.vnf_terminate_and_delete,
            vnf_instance_id=self.vnf_instance_id,
            termination_type='graceful',
            graceful_termination_timeout=self.tc_input.get(
                'graceful_termination_timeout'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.wait_for_vnf_stable_state,
            vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        self.tc_result['resources'][
            'Initial'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 3. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')
        self.traffic.configure(
            traffic_load='LOW_TRAFFIC_LOAD',
            traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=30,
                                  function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=40,
                                  function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 4. Validate traffic flows through without issues
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating traffic flows through without issues')
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        self.tc_result['scaling_out']['traffic_before'] = 'LOW_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 5. Trigger a resize of the VNF resources to use more specialized hardware by altering the VIM KPI
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Triggering a resize of the VNF resources to use more specialized hardware by increasing the traffic '
            'load to the maximum')

        # The scale out is triggered by a VIM KPI threshold crossing.
        # The Virtualised Resources Performance Management interface of Or-Vi will enable the MANO to trigger a scale
        # out based on VIM KPIs.
        # There are 2 ways for MANO to obtain KPI information:
        # - by polling the VIM periodically on the Or-Vi interface (by means of PM jobs)
        # - by subscribing for notifications related to performance information with the VIM. The MANO can define
        #   thresholds that generate notifications from the VIM when they are crossed.
        # Insert here code alters the VIM KPI so that MANO can trigger scale out.

        # TODO: Insert here code to:
        # 1. alter the VNF related indicators so that MANO can trigger a VNF scale out.
        # 2. check that MANO has subscribed to VIM
        # 3. subscribe to VIM and check the notifications
        # For now we use only traffic load to trigger scale out.
        self.traffic.config_traffic_load('MAX_TRAFFIC_LOAD')

        # --------------------------------------------------------------------------------------------------------------
        # 6. Validate VNF has resized
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF has resized')
        # The scale out duration will include:
        # - the time it takes the VNF CPU load to increase (caused by the max traffic load)
        # - the time after which the scaling alarm is triggered
        # - the time it takes the VNF to scale out
        self.time_record.START('scale_out_vnf')
        elapsed_time = 0
        while elapsed_time < constants.VNF_SCALE_TIMEOUT:
            vnf_info = self.mano.vnf_query(
                query_filter={
                    'vnf_instance_id': self.vnf_instance_id,
                    'additional_param': self.tc_input['mano'].get(
                        'query_params')
                })
            if len(vnf_info.instantiated_vnf_info.vnfc_resource_info
                   ) == sp['default_instances'] + sp['increment']:
                break
            else:
                sleep(constants.POLL_INTERVAL)
                elapsed_time += constants.POLL_INTERVAL
            if elapsed_time == constants.VNF_SCALE_TIMEOUT:
                self.tc_result['scaling_out']['status'] = 'Fail'
                raise TestRunError('VNF has not resized')

        self.time_record.END('scale_out_vnf')

        self.tc_result['events']['scale_out_vnf'][
            'duration'] = self.time_record.duration('scale_out_vnf')

        self.tc_result['resources'][
            'After scale out'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        self.tc_result['scaling_out'][
            'level'] = sp['default_instances'] + sp['increment']

        self.tc_result['scaling_out']['status'] = 'Success'

        # --------------------------------------------------------------------------------------------------------------
        # 7. Validate increased capacity without traffic loss
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating increased capacity without traffic loss')
        # Because the VNF scaled out, we need to reconfigure traffic so that it passes through all VNFCs.

        # Stop the max traffic load.
        self.traffic.stop()

        # Configure stream destination address(es).
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.clear_counters()

        # Start the max traffic load.
        self.traffic.start(return_when_emission_starts=True)

        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Max traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Max traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_after'] = 'MAX_TRAFFIC_LOAD'
        self.tc_result['scaling_in']['traffic_before'] = 'MAX_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 8. Validate that MANO has allocated more specialized hardware resources
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validate that MANO has allocated more specialized hardware resources'
        )
        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        # --------------------------------------------------------------------------------------------------------------
        # 9. Trigger a resize of the VNF resources to use less specialized hardware by altering the VIM KPI
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Triggering a resize of the VNF resources to use less specialized hardware by decreasing the traffic '
            'load to the minimum')

        # The scale in is triggered by a VIM KPI threshold crossing.
        # The Virtualised Resources Performance Management interface of Or-Vi will enable the MANO to trigger a scale
        # in based on VIM KPIs.
        # There are 2 ways for MANO to obtain KPI information:
        # - by polling the VIM periodically on the Or-Vi interface (by means of PM jobs)
        # - by subscribing for notifications related to performance information with the VIM. The MANO can define
        #   thresholds that generate notifications from the VIM when they are crossed.
        # Insert here code alters the VIM KPI so that MANO can trigger scale out.

        # TODO: Insert here code to:
        # 1. alter the VNF related indicators so that MANO can trigger a VNF scale out.
        # 2. check that MANO has subscribed to VIM
        # 3. subscribe to VIM and check the notifications
        # For now we use only traffic load to trigger scale in.
        self.traffic.config_traffic_load('LOW_TRAFFIC_LOAD')

        # --------------------------------------------------------------------------------------------------------------
        # 10. Validate VNF has resized and has decreased its capacity and removed VNFCs
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating VNF has resized and has decreased its capacity and removed VNFCs'
        )
        # The scale in duration will include:
        # - the time it takes the VNF CPU load to decrease (caused by the low traffic load)
        # - the time after which the scaling alarm is triggered
        # - the time it takes the VNF to scale in
        self.time_record.START('scale_in_vnf')
        elapsed_time = 0
        while elapsed_time < constants.VNF_SCALE_TIMEOUT:
            vnf_info = self.mano.vnf_query(
                query_filter={
                    'vnf_instance_id': self.vnf_instance_id,
                    'additional_param': self.tc_input['mano'].get(
                        'query_params')
                })
            if len(vnf_info.instantiated_vnf_info.vnfc_resource_info
                   ) == sp['default_instances']:
                break
            else:
                sleep(constants.POLL_INTERVAL)
                elapsed_time += constants.POLL_INTERVAL
            if elapsed_time == constants.VNF_SCALE_TIMEOUT:
                self.tc_result['scaling_in']['status'] = 'Fail'
                raise TestRunError('VNF has not decreased the VNFCs')

        self.time_record.END('scale_in_vnf')

        self.tc_result['events']['scale_in_vnf'][
            'duration'] = self.time_record.duration('scale_in_vnf')

        self.tc_result['resources'][
            'After scale in'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        self.tc_result['scaling_in']['level'] = sp['default_instances']

        self.tc_result['scaling_in']['status'] = 'Success'

        # --------------------------------------------------------------------------------------------------------------
        # 11. Validate that MANO has allocated less specialized hardware resources and the previous specialized hardware
        #     resources have been freed up
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validate that MANO has allocated less specialized hardware resources and the previous specialized '
            'hardware resources have been freed up')
        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        # --------------------------------------------------------------------------------------------------------------
        # 12. Determine the service disruption during the resizing
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Determining the service disruption during the resizing')
        self.tc_result['events']['service_disruption'][
            'duration'] = self.traffic.calculate_service_disruption_length()

        # --------------------------------------------------------------------------------------------------------------
        # 13. Validate traffic flows through without issues
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating traffic flows through without issues')

        # Stop the low traffic load.
        self.traffic.stop()

        # Configure stream destination address(es).
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.clear_counters()

        # Start the low traffic load.
        self.traffic.start(return_when_emission_starts=True)

        # Checking the traffic flow.
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_in']['traffic_after'] = 'LOW_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 14. Terminate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the VNF')
        self.time_record.START('terminate_vnf')
        if self.mano.vnf_terminate_sync(self.vnf_instance_id, termination_type='graceful',
                                        graceful_termination_timeout=self.tc_input.get('graceful_termination_timeout'),
                                        additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for terminating VNF operation',
                err_details='VNF terminate operation failed')

        self.time_record.END('terminate_vnf')

        self.tc_result['events']['terminate_vnf'][
            'duration'] = self.time_record.duration('terminate_vnf')

        self.unregister_from_cleanup(index=20)
        self.unregister_from_cleanup(index=10)

        self.register_for_cleanup(index=10,
                                  function_reference=self.mano.vnf_delete_id,
                                  vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 15. Validate that the VNF is terminated and all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the VNF is terminated')
        vnf_info_final = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info_final.instantiation_state != constants.VNF_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was terminated'
                % constants.VNF_NOT_INSTANTIATED)

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_vnf_released_vresources(
                vnf_info_initial=vnf_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # Get scaling policy properties
        sp = self.mano.get_vnfd_scaling_properties(self.tc_input['vnfd_id'], self.tc_input['scaling_policy_name'])

        # --------------------------------------------------------------------------------------------------------------
        # 1. Ensure NFVI has vResources so that the VNF can be scaled out only desired_scale_out_steps times
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Ensuring NFVI has vResources so that the VNF can be scaled out only desired_scale_out_steps times')
        # Reserving only compute resources is enough for limiting the NFVI resources
        reservation_id = self.mano.limit_compute_resources_for_vnf_scaling(
                                                       vnfd_id=self.tc_input['vnfd_id'],
                                                       scaling_policy_name=self.tc_input['scaling_policy_name'],
                                                       desired_scale_out_steps=self.tc_input['desired_scale_out_steps'],
                                                       generic_vim_object=self.vim)
        if reservation_id is None:
            raise TestRunError('Compute resources could not be limited')

        self.register_for_cleanup(index=10, function_reference=self.vim.terminate_compute_resource_reservation,
                                  reservation_id=reservation_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Instantiate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the VNF')
        self.time_record.START('instantiate_vnf')
        self.vnf_instance_id = self.mano.vnf_create_and_instantiate(
                                                 vnfd_id=self.tc_input['vnfd_id'],
                                                 flavour_id=self.tc_input.get('flavour_id'),
                                                 vnf_instance_name=generate_name(self.tc_name),
                                                 vnf_instance_description=self.tc_input.get('vnf_instance_description'),
                                                 instantiation_level_id=self.tc_input.get('instantiation_level_id'),
                                                 ext_virtual_link=self.tc_input.get('ext_virtual_link'),
                                                 ext_managed_virtual_link=self.tc_input.get('ext_managed_virtual_link'),
                                                 localization_language=self.tc_input.get('localization_language'),
                                                 additional_param=self.tc_input['mano'].get('instantiation_params'))

        self.time_record.END('instantiate_vnf')

        self.tc_result['events']['instantiate_vnf']['duration'] = self.time_record.duration('instantiate_vnf')

        self.register_for_cleanup(index=20, function_reference=self.mano.vnf_terminate_and_delete,
                                  vnf_instance_id=self.vnf_instance_id, termination_type='graceful',
                                  graceful_termination_timeout=self.tc_input.get('graceful_termination_timeout'),
                                  additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(index=30, function_reference=self.mano.wait_for_vnf_stable_state,
                                  vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 3. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')
        vnf_info = self.mano.vnf_query(query_filter={'vnf_instance_id': self.vnf_instance_id,
                                                     'additional_param': self.tc_input['mano'].get('query_params')})
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError('Unexpected VNF instantiation state',
                               err_details='VNF instantiation state was not "%s" after the VNF was instantiated'
                                           % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError('Unexpected VNF state',
                               err_details='VNF state was not "%s" after the VNF was instantiated'
                                           % constants.VNF_STARTED)

        self.tc_result['resources']['Initial'] = self.mano.get_allocated_vresources(
                                                                              self.vnf_instance_id,
                                                                              self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 4. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')
        self.traffic.configure(traffic_load='LOW_TRAFFIC_LOAD',
                               traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=40, function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
                                                          vnf_info,
                                                          self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=50, function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 5. Validate the provided functionality and all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating the provided functionality and all traffic goes through')
        if not self.traffic.does_traffic_flow(delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing', err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss', err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_before'] = 'LOW_TRAFFIC_LOAD'

        if not self.mano.validate_vnf_allocated_vresources(self.vnf_instance_id,
                                                           self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        # --------------------------------------------------------------------------------------------------------------
        # 6. Subscribe for VNF Lifecycle change notifications
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Subscribing for VNF lifecycle change notifications')
        subscription_id = self.mano.vnf_lifecycle_change_notification_subscribe(
                                                          notification_filter={'vnf_instance_id': self.vnf_instance_id})

        # --------------------------------------------------------------------------------------------------------------
        # 7. Trigger a resize of the VNF resources to the maximum increasing the traffic load to the maximum
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Trigger a resize of the VNF resources to the maximum by increasing the traffic load to the maximum')
        self.traffic.config_traffic_load('MAX_TRAFFIC_LOAD')

        # --------------------------------------------------------------------------------------------------------------
        # 8. Verify that the scale out was triggered by the VNF
        # --------------------------------------------------------------------------------------------------------------

        # TODO: Insert code here to verify that the scale out was triggered by the EM

        # --------------------------------------------------------------------------------------------------------------
        # 9. Validate VNF scale out operation was performed desired_scale_out_steps times
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF scale out operation was performed desired_scale_out_steps times')
        notification_queue = self.mano.get_notification_queue(subscription_id)

        self.time_record.START('scale_out_vnf')
        # We are scaling the VNF (desired_scale_out_steps + 1) times and check at the next step that the VNF scaled out
        # only desired_scale_out_steps times
        for scale_out_level in range(self.tc_input['desired_scale_out_steps'] + 1):
            notification_info = self.mano.search_in_notification_queue(
                                                                      notification_queue=notification_queue,
                                                                      notification_type=VnfLifecycleChangeNotification,
                                                                      notification_pattern={'status': 'STARTED',
                                                                                            'operation': 'VNF_SCALE.*'},
                                                                      timeout=constants.VNF_SCALE_TIMEOUT)
            if notification_info is None:
                raise TestRunError('Could not validate that VNF scale out started')
            notification_info = self.mano.search_in_notification_queue(
                                                                      notification_queue=notification_queue,
                                                                      notification_type=VnfLifecycleChangeNotification,
                                                                      notification_pattern={'status': 'SUCCESS|FAILED',
                                                                                            'operation': 'VNF_SCALE.*'},
                                                                      timeout=constants.VNF_SCALE_TIMEOUT)
            if notification_info is None:
                raise TestRunError('Could not validate that VNF scale out finished')

        self.time_record.END('scale_out_vnf')

        self.tc_result['events']['scale_out_vnf']['duration'] = self.time_record.duration('scale_out_vnf')

        # --------------------------------------------------------------------------------------------------------------
        # 10. Validate VNF has resized to the max (limited by NFVI)
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF has resized to the max (limited by NFVI)')
        vnf_info = self.mano.vnf_query(query_filter={'vnf_instance_id': self.vnf_instance_id,
                                                     'additional_param': self.tc_input['mano'].get('query_params')})
        if len(vnf_info.instantiated_vnf_info.vnfc_resource_info) != sp['default_instances'] + sp['increment'] * \
                                                                     self.tc_input['desired_scale_out_steps']:
            raise TestRunError('VNF scaled out')

        self.tc_result['resources']['After scale out'] = self.mano.get_allocated_vresources(
                                                                              self.vnf_instance_id,
                                                                              self.tc_input['mano'].get('query_params'))

        self.tc_result['scaling_out']['level'] = sp['default_instances'] + self.tc_input['desired_scale_out_steps']

        self.tc_result['scaling_out']['status'] = 'Success'

        # --------------------------------------------------------------------------------------------------------------
        # 11. Determine if and length of service disruption
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Determining if and length of service disruption')
        self.tc_result['events']['service_disruption']['duration'] = self.traffic.calculate_service_disruption_length()

        # --------------------------------------------------------------------------------------------------------------
        # 12. Validate traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating traffic goes through')
        # Since the VNF scaled out only desired_scale_out_steps, we are not checking the traffic loss because we do not
        # expect all traffic to go through.
        # Decreasing the traffic load to normal would not be appropriate as it could trigger a scale in.
        if not self.traffic.does_traffic_flow(delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing', err_details='Max traffic did not flow')

        self.tc_result['scaling_out']['traffic_after'] = 'MAX_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 13. Terminate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the VNF')
        self.time_record.START('terminate_vnf')
        if self.mano.vnf_terminate_sync(self.vnf_instance_id, termination_type='graceful',
                                        graceful_termination_timeout=self.tc_input.get('graceful_termination_timeout'),
                                        additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError('Unexpected status for terminating VNF operation',
                               err_details='VNF terminate operation failed')

        self.time_record.END('terminate_vnf')

        self.tc_result['events']['terminate_vnf']['duration'] = self.time_record.duration('terminate_vnf')

        self.unregister_from_cleanup(index=30)
        self.unregister_from_cleanup(index=20)

        self.register_for_cleanup(index=20, function_reference=self.mano.vnf_delete_id,
                                  vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 14. Validate that the VNF is terminated and all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the VNF is terminated')
        vnf_info_final = self.mano.vnf_query(query_filter={'vnf_instance_id': self.vnf_instance_id,
                                                           'additional_param': self.tc_input['mano'].get(
                                                               'query_params')})
        if vnf_info_final.instantiation_state != constants.VNF_NOT_INSTANTIATED:
            raise TestRunError('Unexpected VNF instantiation state',
                               err_details='VNF instantiation state was not "%s" after the VNF was terminated'
                                           % constants.VNF_NOT_INSTANTIATED)

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_vnf_released_vresources(vnf_info_initial=vnf_info):
            raise TestRunError('Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
Exemplo n.º 10
0
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # Get scaling policy properties
        sp = self.mano.get_nsd_scaling_properties(
            self.tc_input['nsd_id'], self.tc_input['scaling_policy_name'])

        # --------------------------------------------------------------------------------------------------------------
        # 1. Instantiate the NS
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the NS')
        self.time_record.START('instantiate_ns')
        self.ns_instance_id = self.mano.ns_create_and_instantiate(
            nsd_id=self.tc_input['nsd_id'],
            ns_name=generate_name(self.tc_name),
            ns_description=self.tc_input.get('ns_description'),
            flavour_id=self.tc_input.get('flavour_id'),
            sap_data=self.tc_input['mano'].get('sap_data'),
            pnf_info=self.tc_input.get('pnf_info'),
            vnf_instance_data=self.tc_input.get('vnf_instance_data'),
            nested_ns_instance_data=self.tc_input.get(
                'nested_ns_instance_data'),
            location_constraints=self.tc_input.get('location_constraints'),
            additional_param_for_ns=self.tc_input['mano'].get(
                'instantiation_params_for_ns'),
            additional_param_for_vnf=self.tc_input['mano'].get(
                'instantiation_params_for_vnf'),
            start_time=self.tc_input.get('start_time'),
            ns_instantiation_level_id=self.tc_input.get(
                'ns_instantiation_level_id'),
            additional_affinity_or_anti_affinity_rule=self.tc_input.get(
                'additional_affinity_or_anti_affinity_rule'))

        self.time_record.END('instantiate_ns')

        self.tc_result['events']['instantiate_ns'][
            'duration'] = self.time_record.duration('instantiate_ns')

        self.register_for_cleanup(
            index=10,
            function_reference=self.mano.ns_terminate_and_delete,
            ns_instance_id=self.ns_instance_id,
            terminate_time=self.tc_input.get('terminate_time'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.wait_for_ns_stable_state,
            ns_instance_id=self.ns_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Validate NS state is INSTANTIATED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating NS state is INSTANTIATED')
        ns_info = self.mano.ns_query(
            query_filter={'ns_instance_id': self.ns_instance_id})
        if ns_info.ns_state != constants.NS_INSTANTIATED:
            raise TestRunError(
                'Unexpected NS state',
                err_details=
                'NS state was not "%s" after the NS was instantiated' %
                constants.NS_INSTANTIATED)

        # --------------------------------------------------------------------------------------------------------------
        # 3. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')

        # Get the instance ID of the VNF inside the NS
        self.vnf_instance_id = ns_info.vnf_info_id[0]

        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        self.tc_result['resources'][
            'Initial'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 4. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')
        self.traffic.configure(
            traffic_load='LOW_TRAFFIC_LOAD',
            traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=30,
                                  function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=40,
                                  function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 5. Validate the provided functionality and all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating the provided functionality and all traffic goes through'
        )
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_before'] = 'LOW_TRAFFIC_LOAD'

        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        # --------------------------------------------------------------------------------------------------------------
        # 6. Trigger a resize of the NS resources to the maximum by altering a VNF indicator that is produced by the EM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Triggering a resize of the NS resources to the maximum by altering a VNF indicator that is produced '
            'by the EM')

        # The scale out is triggered by a VNF related indicator value change.
        # The EM exposed interface Ve-Vnfm-Em will enable the MANO to trigger a scale out based on VNF Indicator
        # value changes. VNF related indicators are declared in the VNFD.
        # There are 2 ways for MANO to obtain VNF Indicator information:
        # - by GetIndicatorValue operation on the Ve-Vnfm-Em interface
        # - by subscribing for notifications related to VNF Indicator value changes with the EM.
        # The two operations involved are Subscribe and Notify.

        # TODO: Insert here code to:
        # 1. alter the VNF related indicators so that MANO can trigger an NS scale out
        # 2. check that MANO has subscribed to EM
        # 3. subscribe to EM and check the notifications
        # For now we use only traffic load to trigger the scale out (we will increase the traffic load to the maximum).
        self.traffic.config_traffic_load('MAX_TRAFFIC_LOAD')

        # --------------------------------------------------------------------------------------------------------------
        # 7. Validate NS has resized to the max
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating NS has resized to the max')
        # The scale out duration will include:
        # - the time it takes the VNF CPU load to increase (caused by the max traffic load)
        # - the time after which the scaling alarm is triggered
        # - the time it takes the NS to scale out
        self.time_record.START('scale_out_ns')
        elapsed_time = 0
        while elapsed_time < constants.NS_SCALE_TIMEOUT:
            ns_info = self.mano.ns_query(
                query_filter={'ns_instance_id': self.ns_instance_id})
            if len(ns_info.vnf_info_id) == sp['max_instances']:
                break
            else:
                sleep(constants.POLL_INTERVAL)
                elapsed_time += constants.POLL_INTERVAL
            if elapsed_time == constants.NS_SCALE_TIMEOUT:
                self.tc_result['scaling_out']['status'] = 'Fail'
                raise TestRunError('NS did not scale out to the max')

        self.time_record.END('scale_out_ns')

        self.tc_result['events']['scale_out_ns'][
            'duration'] = self.time_record.duration('scale_out_ns')

        self.tc_result['resources']['After scale out'] = {}
        for vnf_instance_id in ns_info.vnf_info_id:
            self.tc_result['resources']['After scale out'].update(
                self.mano.get_allocated_vresources(
                    vnf_instance_id,
                    self.tc_input['mano'].get('query_params')))

        self.tc_result['scaling_out']['level'] = sp['max_instances']

        self.tc_result['scaling_out']['status'] = 'Success'

        # --------------------------------------------------------------------------------------------------------------
        # 8. Determine if and length of service disruption
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Determining if and length of service disruption')
        self.tc_result['events']['service_disruption'][
            'duration'] = self.traffic.calculate_service_disruption_length()

        # --------------------------------------------------------------------------------------------------------------
        # 9. Validate max capacity without traffic loss
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating max capacity without traffic loss')
        # Because the NS scaled out, we need to reconfigure traffic so that it passes through all VNFs.

        # Stop the max traffic load.
        self.traffic.stop()

        # Configure stream destination address(es).
        dest_addr_list = ''
        for vnf_instance_id in ns_info.vnf_info_id:
            vnf_info = self.mano.vnf_query(
                query_filter={
                    'vnf_instance_id': vnf_instance_id,
                    'additional_param': self.tc_input['mano'].get(
                        'query_params')
                })
            for ext_cp_info in vnf_info.instantiated_vnf_info.ext_cp_info:
                if ext_cp_info.cpd_id == self.tc_input['traffic'][
                        'traffic_config']['ingress_cp_name']:
                    dest_addr_list += ext_cp_info.address[0] + ' '

        self.traffic.reconfig_traffic_dest(dest_addr_list)
        self.traffic.clear_counters()

        # Start the max traffic load.
        self.traffic.start(return_when_emission_starts=True)

        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Max traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Max traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_after'] = 'MAX_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 10. Terminate the NS
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the NS')
        self.time_record.START('terminate_ns')
        if self.mano.ns_terminate_sync(ns_instance_id=self.ns_instance_id,
                                       terminate_time=self.tc_input.get('terminate_time'),
                                       additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for NS termination operation',
                err_details='NS termination operation failed')

        self.time_record.END('terminate_ns')

        self.tc_result['events']['terminate_ns'][
            'duration'] = self.time_record.duration('terminate_ns')

        self.unregister_from_cleanup(index=20)
        self.unregister_from_cleanup(index=10)

        self.register_for_cleanup(index=10,
                                  function_reference=self.mano.ns_delete_id,
                                  ns_instance_id=self.ns_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 11. Validate that the NS is terminated and that all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the NS is terminated')
        ns_info_final = self.mano.ns_query(
            query_filter={
                'ns_instance_id': self.ns_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if ns_info_final.ns_state != constants.NS_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected NS instantiation state',
                err_details=
                'NS instantiation state was not "%s" after the NS was terminated'
                % constants.NS_NOT_INSTANTIATED)

        LOG.info('Verifying that all the VNF instance(s) have been terminated')
        for vnf_info in ns_info.vnf_info:
            vnf_instance_id = vnf_info.vnf_instance_id
            vnf_info = self.mano.vnf_query(
                query_filter={
                    'vnf_instance_id': vnf_instance_id,
                    'additional_param': self.tc_input['mano'].get(
                        'query_params')
                })
            if vnf_info.instantiation_state != constants.VNF_NOT_INSTANTIATED:
                raise TestRunError(
                    'VNF instance %s was not terminated correctly. Expected state was %s but got %s'
                    % (vnf_instance_id, constants.VNF_NOT_INSTANTIATED,
                       vnf_info.instantiation_state))

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_ns_released_vresources(ns_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
Exemplo n.º 11
0
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # Get scaling policy properties
        sp = self.mano.get_vnfd_scaling_properties(
            self.tc_input['vnfd_id'], self.tc_input['scaling_policy_name'])

        # --------------------------------------------------------------------------------------------------------------
        # 1. Ensure NFVI has not enough vResources for the VNF to be scaled out
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Ensure NFVI has not enough vResources for the VNF to be scaled out'
        )
        # Reserving only compute resources is enough for limiting the NFVI resources
        reservation_id = self.mano.limit_compute_resources_for_vnf_scaling(
            vnfd_id=self.tc_input['vnfd_id'],
            scaling_policy_name=self.tc_input['scaling_policy_name'],
            desired_scale_out_steps=0,
            generic_vim_object=self.vim)
        if reservation_id is None:
            raise TestRunError('Compute resources could not be limited')

        self.register_for_cleanup(
            index=10,
            function_reference=self.vim.terminate_compute_resource_reservation,
            reservation_id=reservation_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Instantiate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the VNF')
        self.time_record.START('instantiate_vnf')
        self.vnf_instance_id = self.mano.vnf_create_and_instantiate(
            vnfd_id=self.tc_input['vnfd_id'],
            flavour_id=self.tc_input.get('flavour_id'),
            vnf_instance_name=generate_name(self.tc_name),
            vnf_instance_description=self.tc_input.get(
                'vnf_instance_description'),
            instantiation_level_id=self.tc_input.get('instantiation_level_id'),
            ext_virtual_link=self.tc_input.get('ext_virtual_link'),
            ext_managed_virtual_link=self.tc_input.get(
                'ext_managed_virtual_link'),
            localization_language=self.tc_input.get('localization_language'),
            additional_param=self.tc_input['mano'].get('instantiation_params'))

        self.time_record.END('instantiate_vnf')

        self.tc_result['events']['instantiate_vnf'][
            'duration'] = self.time_record.duration('instantiate_vnf')

        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.vnf_terminate_and_delete,
            vnf_instance_id=self.vnf_instance_id,
            termination_type='graceful',
            graceful_termination_timeout=self.tc_input.get(
                'graceful_termination_timeout'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=30,
            function_reference=self.mano.wait_for_vnf_stable_state,
            vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 3. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        self.tc_result['resources'][
            'Initial'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 4. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')
        self.traffic.configure(
            traffic_load='LOW_TRAFFIC_LOAD',
            traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=40,
                                  function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=50,
                                  function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 5. Validate the provided functionality and all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating the provided functionality and all traffic goes through'
        )
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_before'] = 'LOW_TRAFFIC_LOAD'

        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        # --------------------------------------------------------------------------------------------------------------
        # 6. Subscribe for VNF Lifecycle change notifications
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Subscribing for VNF lifecycle change notifications')
        subscription_id = self.mano.vnf_lifecycle_change_notification_subscribe(
            notification_filter={'vnf_instance_id': self.vnf_instance_id})

        # --------------------------------------------------------------------------------------------------------------
        # 7. Trigger a resize of the VNF resources to the maximum by altering the VNF indicator produced by EM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Trigger a resize of the VNF resources to the maximum by altering the VNF indicator produced by EM'
        )

        # The scale in is triggered by a VIM KPI threshold crossing.
        # The Virtualised Resources Performance Management interface of Or-Vi will enable the MANO to trigger a scale
        # in based on VIM KPIs.
        # There are 2 ways for MANO to obtain KPI information:
        # - by polling the VIM periodically on the Or-Vi interface (by means of PM jobs)
        # - by subscribing for notifications related to performance information with the VIM. The MANO can define
        #   thresholds that generate notifications from the VIM when they are crossed.
        # Insert here code that alters a VIM KPI so that MANO can trigger scale out.

        # TODO: Insert here code to:
        # 1. alter the VNF related indicators so that MANO can trigger a VNF scale out.
        # 2. check that MANO has subscribed to VIM
        # 3. subscribe to VNF and check the notifications
        # For now we use only traffic load to trigger scale out.
        self.traffic.config_traffic_load('MAX_TRAFFIC_LOAD')

        # --------------------------------------------------------------------------------------------------------------
        # 8. Validate that the scaling out has been attempted and the operation finished
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the scaling out has been attempted')
        notification_info = self.mano.wait_for_notification(
            subscription_id,
            notification_type=VnfLifecycleChangeNotification,
            notification_pattern={
                'status': 'STARTED',
                'operation': 'VNF_SCALE.*'
            },
            timeout=120)
        if notification_info is None:
            raise TestRunError(
                'Could not validate that VNF scale out has been attempted')

        self.time_record.START('scale_out_vnf')

        LOG.info('Validating that the scaling out finished')
        notification_info = self.mano.wait_for_notification(
            subscription_id,
            notification_type=VnfLifecycleChangeNotification,
            notification_pattern={
                'status': 'SUCCESS|FAILED',
                'operation': 'VNF_SCALE.*'
            },
            timeout=constants.VNF_SCALE_TIMEOUT)
        if notification_info is None:
            raise TestRunError(
                'Could not validate that VNF scale out finished')

        self.time_record.END('scale_out_vnf')

        self.tc_result['events']['scale_out_vnf'][
            'duration'] = self.time_record.duration('scale_out_vnf')

        # --------------------------------------------------------------------------------------------------------------
        # 9. Validate VNF has not resized
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF has not resized')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if len(vnf_info.instantiated_vnf_info.vnfc_resource_info
               ) != sp['default_instances']:
            raise TestRunError('VNF scaled out')

        self.tc_result['resources'][
            'After scale out'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        self.tc_result['scaling_out']['level'] = sp['default_instances']

        self.tc_result['scaling_out']['status'] = notification_info.status

        # --------------------------------------------------------------------------------------------------------------
        # 10. Determine if and length of service disruption
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Determining if and length of service disruption')
        self.tc_result['events']['service_disruption'][
            'duration'] = self.traffic.calculate_service_disruption_length()

        # --------------------------------------------------------------------------------------------------------------
        # 11. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')

        # Stop the max traffic load.
        self.traffic.stop()

        # Configure the traffic load and clear counters.
        self.traffic.config_traffic_load('LOW_TRAFFIC_LOAD')
        self.traffic.clear_counters()

        # Start the low traffic load.
        self.traffic.start(return_when_emission_starts=True)

        # --------------------------------------------------------------------------------------------------------------
        # 12. Validate all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating all traffic goes through')
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_after'] = 'LOW_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 13. Terminate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the VNF')
        self.time_record.START('terminate_vnf')
        if self.mano.vnf_terminate_sync(self.vnf_instance_id, termination_type='graceful',
                                        graceful_termination_timeout=self.tc_input.get('graceful_termination_timeout'),
                                        additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for terminating VNF operation',
                err_details='VNF terminate operation failed')

        self.time_record.END('terminate_vnf')

        self.tc_result['events']['terminate_vnf'][
            'duration'] = self.time_record.duration('terminate_vnf')

        self.unregister_from_cleanup(index=30)
        self.unregister_from_cleanup(index=20)

        self.register_for_cleanup(index=20,
                                  function_reference=self.mano.vnf_delete_id,
                                  vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 14. Validate that the VNF is terminated and all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the VNF is terminated')
        vnf_info_final = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info_final.instantiation_state != constants.VNF_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was terminated'
                % constants.VNF_NOT_INSTANTIATED)

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_vnf_released_vresources(
                vnf_info_initial=vnf_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
Exemplo n.º 12
0
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # --------------------------------------------------------------------------------------------------------------
        # 1. Instantiate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the VNF')
        self.time_record.START('instantiate_vnf')
        self.vnf_instance_id = self.mano.vnf_create_id(
            vnfd_id=self.tc_input['vnfd_id'],
            vnf_instance_name=generate_name(self.tc_name),
            vnf_instance_description=self.tc_input.get(
                'vnf_instance_description'))

        if self.mano.vnf_instantiate_sync(vnf_instance_id=self.vnf_instance_id,
                                          flavour_id=self.tc_input.get('flavour_id'),
                                          instantiation_level_id=self.tc_input.get('instantiation_level_id'),
                                          ext_virtual_link=self.tc_input.get('ext_virtual_link'),
                                          ext_managed_virtual_link=self.tc_input.get('ext_managed_virtual_link'),
                                          localization_language=self.tc_input.get('localization_language'),
                                          additional_param=self.tc_input['mano'].get('instantiation_params')) \
                != constants.OPERATION_FAILED:
            raise TestRunError('VNF instantiation operation succeeded')

        self.time_record.END('instantiate_vnf')

        self.tc_result['events']['instantiate_vnf'][
            'duration'] = self.time_record.duration('instantiate_vnf')

        self.register_for_cleanup(
            index=10,
            function_reference=self.mano.vnf_terminate_and_delete,
            vnf_instance_id=self.vnf_instance_id,
            termination_type='graceful',
            graceful_termination_timeout=self.tc_input.get(
                'graceful_termination_timeout'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.wait_for_vnf_stable_state,
            vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Validate MANO reports no VNF instance and the error
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating MANO reports no VNF instance and the error')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state == constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was "%s" although the instantiation operation failed'
                % constants.VNF_INSTANTIATED)

        self.tc_result['events']['instantiate_vnf'][
            'details'] = vnf_info.metadata['error_reason']

        # --------------------------------------------------------------------------------------------------------------
        # 3. Terminate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the VNF')
        self.time_record.START('terminate_vnf')
        if self.mano.vnf_terminate_sync(self.vnf_instance_id, termination_type='graceful',
                                        graceful_termination_timeout=self.tc_input.get('graceful_termination_timeout'),
                                        additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for terminating VNF operation',
                err_details='VNF terminate operation failed')

        self.time_record.END('terminate_vnf')

        self.tc_result['events']['terminate_vnf'][
            'duration'] = self.time_record.duration('terminate_vnf')

        self.unregister_from_cleanup(index=20)
        self.unregister_from_cleanup(index=10)

        self.register_for_cleanup(index=10,
                                  function_reference=self.mano.vnf_delete_id,
                                  vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 4. Validate that the VNF is terminated and all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the VNF is terminated')
        vnf_info_final = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info_final.instantiation_state != constants.VNF_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was terminated'
                % constants.VNF_NOT_INSTANTIATED)

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_vnf_released_vresources(
                vnf_info_initial=vnf_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
Exemplo n.º 13
0
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # --------------------------------------------------------------------------------------------------------------
        # 1. Start the EM or ensure EM is up and can configure the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Starting the EM or ensure EM is up and can configure the VNF')
        # TODO

        # --------------------------------------------------------------------------------------------------------------
        # 2. Instantiate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the VNF')
        self.time_record.START('instantiate_vnf')
        self.vnf_instance_id = self.mano.vnf_create_and_instantiate(
            vnfd_id=self.tc_input['vnfd_id'],
            flavour_id=self.tc_input.get('flavour_id'),
            vnf_instance_name=generate_name(self.tc_name),
            vnf_instance_description=self.tc_input.get(
                'vnf_instance_description'),
            instantiation_level_id=self.tc_input.get('instantiation_level_id'),
            ext_virtual_link=self.tc_input.get('ext_virtual_link'),
            ext_managed_virtual_link=self.tc_input.get(
                'ext_managed_virtual_link'),
            localization_language=self.tc_input.get('localization_language'),
            additional_param=self.tc_input['mano'].get('instantiation_params'))

        self.time_record.END('instantiate_vnf')

        self.register_for_cleanup(
            index=10,
            function_reference=self.mano.vnf_terminate_and_delete,
            vnf_instance_id=self.vnf_instance_id,
            termination_type='graceful',
            graceful_termination_timeout=self.tc_input.get(
                'graceful_termination_timeout'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.wait_for_vnf_stable_state,
            vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 3. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating VNF instantiation state is INSTANTIATED and VNF state is STARTED'
        )
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        # --------------------------------------------------------------------------------------------------------------
        # 4. Modify the VNF configuration
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Modifying the VNF configuration')
        self.time_record.START('update_vnf')
        if self.em.modify_vnf_configuration(self.vnf_instance_id, vnf_configuration_data=self.tc_input['vnf']['config'],
                                            ext_virtual_link=self.tc_input.get('ext_virtual_link'),
                                            vnfc_configuration_data=self.tc_input.get('vnfc_configuration_data')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError('EM could not modify the VNF configuration')

        self.time_record.END('update_vnf')

        # --------------------------------------------------------------------------------------------------------------
        # 5. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating VNF instantiation state is INSTANTIATED and VNF state is STARTED'
        )
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        # --------------------------------------------------------------------------------------------------------------
        # 6. Validate the right vResources have been allocated
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating the right vResources have been allocated')
        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        self.tc_result['resources'][
            'Initial'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 7. Validate configuration has been applied by the EM to the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating configuration has been applied by the EM to the VNF')
        if not self.vnf.config_applied():
            raise TestRunError('Configuration has not been applied to the VNF')

        # --------------------------------------------------------------------------------------------------------------
        # 8. Validate license has been applied to the VNF (if applicable)
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating license has been applied to the VNF')
        if not self.vnf.license_applied():
            raise TestRunError('License has not been applied to the VNF')

        # --------------------------------------------------------------------------------------------------------------
        # 9. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')
        self.traffic.configure(
            traffic_load='LOW_TRAFFIC_LOAD',
            traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=30,
                                  function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=40,
                                  function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 10. Validate traffic flows
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating traffic flows')
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        # --------------------------------------------------------------------------------------------------------------
        # 11. Calculate the instantiation time
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Calculating the instantiation time')
        self.tc_result['events']['instantiate_vnf'][
            'duration'] = self.time_record.duration('instantiate_vnf')
        self.tc_result['events']['update_vnf'][
            'duration'] = self.time_record.duration('update_vnf')
        self.tc_result['events']['instantiate_update_vnf'][
            'duration'] = self.time_record.delta('instantiate_vnf.START',
                                                 'update_vnf.END')

        # --------------------------------------------------------------------------------------------------------------
        # 12. Terminate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the VNF')
        self.time_record.START('terminate_vnf')
        if self.mano.vnf_terminate_sync(self.vnf_instance_id, termination_type='graceful',
                                        graceful_termination_timeout=self.tc_input.get('graceful_termination_timeout'),
                                        additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for terminating VNF operation',
                err_details='VNF terminate operation failed')

        self.time_record.END('terminate_vnf')

        self.tc_result['events']['terminate_vnf'][
            'duration'] = self.time_record.duration('terminate_vnf')

        self.unregister_from_cleanup(index=20)
        self.unregister_from_cleanup(index=10)

        self.register_for_cleanup(index=10,
                                  function_reference=self.mano.vnf_delete_id,
                                  vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 13. Validate that the VNF is terminated and all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the VNF is terminated')
        vnf_info_final = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info_final.instantiation_state != constants.VNF_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was terminated'
                % constants.VNF_NOT_INSTANTIATED)

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_vnf_released_vresources(
                vnf_info_initial=vnf_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # Get scaling policy properties
        sp = self.mano.get_nsd_scaling_properties(
            self.tc_input['nsd_id'], self.tc_input['scaling_policy_name'])

        # --------------------------------------------------------------------------------------------------------------
        # 1. Ensure NFVI has not enough vResources for the NS to be scaled out
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Ensure NFVI has not enough vResources for the NS to be scaled out'
        )
        # Reserving only compute resources is enough for limiting the NFVI resources
        reservation_id = self.mano.limit_compute_resources_for_ns_scaling(
            nsd_id=self.tc_input['nsd_id'],
            scaling_policy_name=self.tc_input['scaling_policy_name'],
            desired_scale_out_steps=0,
            generic_vim_object=self.vim)
        if reservation_id is None:
            raise TestRunError('Compute resources could not be limited')

        self.register_for_cleanup(
            index=10,
            function_reference=self.vim.terminate_compute_resource_reservation,
            reservation_id=reservation_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Instantiate the NS
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the NS')
        self.time_record.START('instantiate_ns')
        self.ns_instance_id = self.mano.ns_create_and_instantiate(
            nsd_id=self.tc_input['nsd_id'],
            ns_name=generate_name(self.tc_name),
            ns_description=self.tc_input.get('ns_description'),
            flavour_id=self.tc_input.get('flavour_id'),
            sap_data=self.tc_input['mano'].get('sap_data'),
            pnf_info=self.tc_input.get('pnf_info'),
            vnf_instance_data=self.tc_input.get('vnf_instance_data'),
            nested_ns_instance_data=self.tc_input.get(
                'nested_ns_instance_data'),
            location_constraints=self.tc_input.get('location_constraints'),
            additional_param_for_ns=self.tc_input['mano'].get(
                'instantiation_params_for_ns'),
            additional_param_for_vnf=self.tc_input['mano'].get(
                'instantiation_params_for_vnf'),
            start_time=self.tc_input.get('start_time'),
            ns_instantiation_level_id=self.tc_input.get(
                'ns_instantiation_level_id'),
            additional_affinity_or_anti_affinity_rule=self.tc_input.get(
                'additional_affinity_or_anti_affinity_rule'))

        self.time_record.END('instantiate_ns')

        self.tc_result['events']['instantiate_ns'][
            'duration'] = self.time_record.duration('instantiate_ns')

        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.ns_terminate_and_delete,
            ns_instance_id=self.ns_instance_id,
            terminate_time=self.tc_input.get('terminate_time'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=30,
            function_reference=self.mano.wait_for_ns_stable_state,
            ns_instance_id=self.ns_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 3. Validate NS state is INSTANTIATED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating NS state is INSTANTIATED')
        ns_info = self.mano.ns_query(
            query_filter={'ns_instance_id': self.ns_instance_id})
        if ns_info.ns_state != constants.NS_INSTANTIATED:
            raise TestRunError(
                'Unexpected NS state',
                err_details=
                'NS state was not "%s" after the NS was instantiated' %
                constants.NS_INSTANTIATED)

        # --------------------------------------------------------------------------------------------------------------
        # 4. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')

        # Get the instance ID of the VNF inside the NS
        self.vnf_instance_id = ns_info.vnf_info_id[0]

        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        self.tc_result['resources'][
            'Initial'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 5. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')
        self.traffic.configure(
            traffic_load='LOW_TRAFFIC_LOAD',
            traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=40,
                                  function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=50,
                                  function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 6 Validate the provided functionality and all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating the provided functionality and all traffic goes through'
        )
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_before'] = 'LOW_TRAFFIC_LOAD'

        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        # --------------------------------------------------------------------------------------------------------------
        # 7. Subscribe for VNF Lifecycle change notifications
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Subscribing for VNF lifecycle change notifications')
        subscription_id = self.mano.vnf_lifecycle_change_notification_subscribe(
            filter={'vnf_instance_id': self.vnf_instance_id})

        # --------------------------------------------------------------------------------------------------------------
        # 8. Trigger a resize of the NS resources to the maximum by altering a VNF indicator that is produced by the EM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Triggering a resize of the NS resources to the maximum by altering a VNF indicator that is produced '
            'by the EM')

        # The scale out is triggered by a VNF related indicator value change.
        # The EM exposed interface Ve-Vnfm-Em will enable the MANO to trigger a scale out based on VNF Indicator
        # value changes. VNF related indicators are declared in the VNFD.
        # There are 2 ways for MANO to obtain VNF Indicator information:
        # - by GetIndicatorValue operation on the Ve-Vnfm-Em interface
        # - by subscribing for notifications related to VNF Indicator value changes with the EM.
        # The two operations involved are Subscribe and Notify.

        # TODO: Insert here code to:
        # 1. alter the VNF related indicators so that MANO can trigger an NS scale out
        # 2. check that MANO has subscribed to EM
        # 3. subscribe to EM and check the notifications
        # For now we use only traffic load to trigger the scale out (we will increase the traffic load to the maximum).
        self.traffic.config_traffic_load('MAX_TRAFFIC_LOAD')

        # --------------------------------------------------------------------------------------------------------------
        # 9. Validate that the scaling out started and the operation finished
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the scale out started')
        notification_info = self.mano.wait_for_notification(
            subscription_id,
            notification_type=VnfLifecycleChangeNotification,
            notification_pattern={
                'status': 'STARTED',
                'operation': 'NS_SCALE.*'
            },
            timeout=120)
        if notification_info is None:
            raise TestRunError('Could not validate that NS scale out started')

        self.time_record.START('scale_out_ns')

        LOG.info('Validating that the scale out finished')
        notification_info = self.mano.wait_for_notification(
            subscription_id,
            notification_type=VnfLifecycleChangeNotification,
            notification_pattern={
                'status': 'SUCCESS|FAILED',
                'operation': 'NS_SCALE.*'
            },
            timeout=constants.NS_SCALE_TIMEOUT)
        if notification_info is None:
            raise TestRunError('Could not validate that NS scale out finished')

        self.time_record.END('scale_out_ns')

        self.tc_result['events']['scale_out_ns'][
            'duration'] = self.time_record.duration('scale_out_ns')

        # --------------------------------------------------------------------------------------------------------------
        # 10. Validate NS has not resized
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating NS has not resized')
        ns_info = self.mano.ns_query(
            query_filter={'ns_instance_id': self.ns_instance_id})
        if len(ns_info.vnf_info_id) != sp['default_instances']:
            raise TestRunError('NS did not scale out to the max NFVI limit')

        self.tc_result['resources']['After scale out'] = {}
        for vnf_instance_id in ns_info.vnf_info_id:
            self.tc_result['resources']['After scale out'].update(
                self.mano.get_allocated_vresources(
                    vnf_instance_id,
                    self.tc_input['mano'].get('query_params')))

        self.tc_result['scaling_out']['level'] = sp['default_instances']

        self.tc_result['scaling_out']['status'] = notification_info.status

        # --------------------------------------------------------------------------------------------------------------
        # 11. Determine is and length of service disruption
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Determining if and length of service disruption')
        self.tc_result['events']['service_disruption'][
            'duration'] = self.traffic.calculate_service_disruption_length()

        # --------------------------------------------------------------------------------------------------------------
        # 12. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')

        # Stop the max traffic load.
        self.traffic.stop()

        # Configure the traffic load and clear counters.
        self.traffic.config_traffic_load('LOW_TRAFFIC_LOAD')
        self.traffic.clear_counters()

        # Start the low traffic load.
        self.traffic.start(return_when_emission_starts=True)

        # --------------------------------------------------------------------------------------------------------------
        # 13. Validate all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating all traffic goes through')
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_after'] = 'LOW_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 14. Terminate the NS
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the NS')
        self.time_record.START('terminate_ns')
        if self.mano.ns_terminate_sync(ns_instance_id=self.ns_instance_id,
                                       terminate_time=self.tc_input.get('terminate_time'),
                                       additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for NS termination operation',
                err_details='NS termination operation failed')

        self.time_record.END('terminate_ns')

        self.tc_result['events']['terminate_ns'][
            'duration'] = self.time_record.duration('terminate_ns')

        self.unregister_from_cleanup(index=30)
        self.unregister_from_cleanup(index=20)

        self.register_for_cleanup(index=20,
                                  function_reference=self.mano.ns_delete_id,
                                  ns_instance_id=self.ns_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 15. Validate that the NS is terminated and that all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the NS is terminated')
        ns_info_final = self.mano.ns_query(
            query_filter={
                'ns_instance_id': self.ns_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if ns_info_final.ns_state != constants.NS_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected NS instantiation state',
                err_details=
                'NS instantiation state was not "%s" after the NS was terminated'
                % constants.NS_NOT_INSTANTIATED)

        LOG.info('Verifying that all the VNF instance(s) have been terminated')
        for vnf_info in ns_info.vnf_info:
            vnf_instance_id = vnf_info.vnf_instance_id
            vnf_info = self.mano.vnf_query(
                query_filter={
                    'vnf_instance_id': vnf_instance_id,
                    'additional_param': self.tc_input['mano'].get(
                        'query_params')
                })
            if vnf_info.instantiation_state != constants.VNF_NOT_INSTANTIATED:
                raise TestRunError(
                    'VNF instance %s was not terminated correctly. Expected state was %s but got %s'
                    % (vnf_instance_id, constants.VNF_NOT_INSTANTIATED,
                       vnf_info.instantiation_state))

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_ns_released_vresources(ns_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)
Exemplo n.º 15
0
    def run(self):
        LOG.info('Starting %s' % self.tc_name)

        # Get scaling policy properties
        sp = self.mano.get_vnfd_scaling_properties(
            self.tc_input['vnfd_id'], self.tc_input['scaling_policy_name'])

        # --------------------------------------------------------------------------------------------------------------
        # 1. Ensure NFVI has vResources so that the VNF can be scaled out only desired_scale_out_steps times
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Ensure NFVI has vResources so that the VNF can be scaled out only desired_scale_out_steps times'
        )
        # Reserving only compute resources is enough for limiting the NFVI resources
        reservation_id = self.mano.limit_compute_resources_for_vnf_scaling(
            vnfd_id=self.tc_input['vnfd_id'],
            scaling_policy_name=self.tc_input['scaling_policy_name'],
            desired_scale_out_steps=self.tc_input['desired_scale_out_steps'],
            generic_vim_object=self.vim)
        if reservation_id is None:
            raise TestRunError('Compute resources could not be limited')

        self.register_for_cleanup(
            index=10,
            function_reference=self.vim.terminate_compute_resource_reservation,
            reservation_id=reservation_id)

        # --------------------------------------------------------------------------------------------------------------
        # 2. Instantiate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Instantiating the VNF')
        self.time_record.START('instantiate_vnf')
        self.vnf_instance_id = self.mano.vnf_create_and_instantiate(
            vnfd_id=self.tc_input['vnfd_id'],
            flavour_id=self.tc_input.get('flavour_id'),
            vnf_instance_name=generate_name(self.tc_name),
            vnf_instance_description=self.tc_input.get(
                'vnf_instance_description'),
            instantiation_level_id=self.tc_input.get('instantiation_level_id'),
            ext_virtual_link=self.tc_input.get('ext_virtual_link'),
            ext_managed_virtual_link=self.tc_input.get(
                'ext_managed_virtual_link'),
            localization_language=self.tc_input.get('localization_language'),
            additional_param=self.tc_input['mano'].get('instantiation_params'))

        self.time_record.END('instantiate_vnf')

        self.tc_result['events']['instantiate_vnf'][
            'duration'] = self.time_record.duration('instantiate_vnf')

        self.register_for_cleanup(
            index=20,
            function_reference=self.mano.vnf_terminate_and_delete,
            vnf_instance_id=self.vnf_instance_id,
            termination_type='graceful',
            graceful_termination_timeout=self.tc_input.get(
                'graceful_termination_timeout'),
            additional_param=self.tc_input['mano'].get('termination_params'))
        self.register_for_cleanup(
            index=30,
            function_reference=self.mano.wait_for_vnf_stable_state,
            vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 3. Validate VNF instantiation state is INSTANTIATED and VNF state is STARTED
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF instantiation state is INSTANTIATED')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info.instantiation_state != constants.VNF_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was instantiated'
                % constants.VNF_INSTANTIATED)

        LOG.info('Validating VNF state is STARTED')
        if vnf_info.instantiated_vnf_info.vnf_state != constants.VNF_STARTED:
            raise TestRunError(
                'Unexpected VNF state',
                err_details=
                'VNF state was not "%s" after the VNF was instantiated' %
                constants.VNF_STARTED)

        self.tc_result['resources'][
            'Initial'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        # --------------------------------------------------------------------------------------------------------------
        # 4. Start the low traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the low traffic load')
        self.traffic.configure(
            traffic_load='LOW_TRAFFIC_LOAD',
            traffic_config=self.tc_input['traffic']['traffic_config'])

        self.register_for_cleanup(index=40,
                                  function_reference=self.traffic.destroy)

        # Configure stream destination address(es)
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.start(return_when_emission_starts=True)

        self.register_for_cleanup(index=50,
                                  function_reference=self.traffic.stop)

        # --------------------------------------------------------------------------------------------------------------
        # 5. Validate the provided functionality and all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Validating the provided functionality and all traffic goes through'
        )
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Low traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError('Traffic is flowing with packet loss',
                               err_details='Low traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_before'] = 'LOW_TRAFFIC_LOAD'

        if not self.mano.validate_vnf_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params')):
            raise TestRunError('Allocated vResources could not be validated')

        # --------------------------------------------------------------------------------------------------------------
        # 6. Trigger a resize of the VNF resources to the maximum by instructing the EM to instruct the MANO to scale
        #    out the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info(
            'Triggering a resize of the VNF resources to the maximum by instructing the EM to instruct the MANO to'
            'scale out the VNF')
        self.time_record.START('scale_out_vnf')
        # We are scaling the VNF (desired_scale_out_steps + 1) times and check at the next step that the VNF scaled out
        # only desired_scale_out_steps times
        for scale_out_step in range(self.tc_input['desired_scale_out_steps'] +
                                    1):
            if self.em.vnf_scale_sync(self.vnf_instance_id, scale_type='out', aspect_id=sp['targets'],
                                      additional_param={'scaling_policy_name': self.tc_input['scaling_policy_name']}) \
                    != constants.OPERATION_SUCCESS:
                self.tc_result['scaling_out']['status'] = 'Fail'
                raise TestRunError(
                    'EM could not instruct the MANO to scale out the VNF to the next level'
                )
            sleep(sp['cooldown'])

        self.time_record.END('scale_out_vnf')

        self.tc_result['events']['scale_out_vnf'][
            'duration'] = self.time_record.duration('scale_out_vnf')

        # --------------------------------------------------------------------------------------------------------------
        # 7. Validate VNF has resized to the max (limited by NFVI)
        # The VNF should have default_instances + desired_scale_out_steps * increment VNFCs after scale out
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating VNF has resized to the max (limited by NFVI)')
        vnf_info = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if len(vnf_info.instantiated_vnf_info.vnfc_resource_info) != sp['default_instances'] + sp['increment'] * \
                                                                     self.tc_input['desired_scale_out_steps']:
            raise TestRunError('VNF did not scale out to the max NFVI limit')

        self.tc_result['resources'][
            'After scale out'] = self.mano.get_allocated_vresources(
                self.vnf_instance_id,
                self.tc_input['mano'].get('query_params'))

        self.tc_result['scaling_out']['level'] = sp['default_instances'] + sp['increment'] * \
                                                 self.tc_input['desired_scale_out_steps']

        self.tc_result['scaling_out']['status'] = 'Success'

        # --------------------------------------------------------------------------------------------------------------
        # 8. Determine the length of service disruption
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Determining the length of service disruption')
        self.tc_result['events']['service_disruption'][
            'duration'] = self.traffic.calculate_service_disruption_length()

        # --------------------------------------------------------------------------------------------------------------
        # 9. Start the normal traffic load
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Starting the normal traffic load')

        # Stop the low traffic load.
        self.traffic.stop()

        # Configure stream destination address(es).
        dest_addr_list = self.mano.get_vnf_ingress_cp_addr_list(
            vnf_info,
            self.tc_input['traffic']['traffic_config']['ingress_cp_name'])
        self.traffic.reconfig_traffic_dest(dest_addr_list)

        self.traffic.config_traffic_load('NORMAL_TRAFFIC_LOAD')

        # Start the normal traffic load.
        self.traffic.start(return_when_emission_starts=True)

        # --------------------------------------------------------------------------------------------------------------
        # 10. Validate all traffic goes through
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating all traffic goes through')
        if not self.traffic.does_traffic_flow(
                delay_time=constants.TRAFFIC_DELAY_TIME):
            raise TestRunError('Traffic is not flowing',
                               err_details='Normal traffic did not flow')

        if self.traffic.any_traffic_loss(
                tolerance=constants.TRAFFIC_TOLERANCE):
            raise TestRunError(
                'Traffic is flowing with packet loss',
                err_details='Normal traffic flew with packet loss')

        self.tc_result['scaling_out']['traffic_after'] = 'NORMAL_TRAFFIC_LOAD'

        # --------------------------------------------------------------------------------------------------------------
        # 11. Terminate the VNF
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Terminating the VNF')
        self.time_record.START('terminate_vnf')
        if self.mano.vnf_terminate_sync(self.vnf_instance_id, termination_type='graceful',
                                        graceful_termination_timeout=self.tc_input.get('graceful_termination_timeout'),
                                        additional_param=self.tc_input['mano'].get('termination_params')) != \
                constants.OPERATION_SUCCESS:
            raise TestRunError(
                'Unexpected status for terminating VNF operation',
                err_details='VNF terminate operation failed')

        self.time_record.END('terminate_vnf')

        self.tc_result['events']['terminate_vnf'][
            'duration'] = self.time_record.duration('terminate_vnf')

        self.unregister_from_cleanup(index=30)
        self.unregister_from_cleanup(index=20)

        self.register_for_cleanup(index=20,
                                  function_reference=self.mano.vnf_delete_id,
                                  vnf_instance_id=self.vnf_instance_id)

        # --------------------------------------------------------------------------------------------------------------
        # 12. Validate that the VNF is terminated and all resources have been released by the VIM
        # --------------------------------------------------------------------------------------------------------------
        LOG.info('Validating that the VNF is terminated')
        vnf_info_final = self.mano.vnf_query(
            query_filter={
                'vnf_instance_id': self.vnf_instance_id,
                'additional_param': self.tc_input['mano'].get('query_params')
            })
        if vnf_info_final.instantiation_state != constants.VNF_NOT_INSTANTIATED:
            raise TestRunError(
                'Unexpected VNF instantiation state',
                err_details=
                'VNF instantiation state was not "%s" after the VNF was terminated'
                % constants.VNF_NOT_INSTANTIATED)

        LOG.info('Validating that all resources have been released by the VIM')
        if not self.mano.validate_vnf_released_vresources(
                vnf_info_initial=vnf_info):
            raise TestRunError(
                'Allocated resources have not been released by the VIM')

        LOG.info('%s execution completed successfully' % self.tc_name)