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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)