def test_remove_dup_scriptable(stc): ctor = CScriptableCreator() project = CStcSystem.Instance().GetObject("Project") dev1 = ctor.Create("EmulatedDevice", project) dev2 = ctor.Create("EmulatedDevice", project) tags = project.GetObject("Tags") assert tags # Order is maintained res_val = dm_utils.remove_dup_scriptable([dev1, dev2, dev1, project]) assert len(res_val) == 3 assert res_val[0].GetObjectHandle() == dev1.GetObjectHandle() assert res_val[1].GetObjectHandle() == dev2.GetObjectHandle() assert res_val[2].GetObjectHandle() == project.GetObjectHandle()
def process_wizard_args(tmpl_cfg, wiz_list): ''' Inputs: Template config and list of wizard dictionaries containing targetTagList, srcObjectTagName, createdRoutesTagName, commandName ''' plLogger = PLLogger.GetLogger('methodology') this_cmd = get_this_cmd() for wiz in wiz_list: targ_tag_list = wiz.get('targetTagList') src_tag = wiz.get('srcObjectTagName') route_tag_name = wiz.get('createdRoutesTagName') command_name = wiz.get('commandName') # FIXME: It seems curious that the bllWizardExpand section has a # target tag list, when the command itself has the same list as a # input property -- evaluate whether this can be eliminated if not targ_tag_list: err = "No target tag list given" plLogger.LogError(err) this_cmd.Set('Status', err) return False if not src_tag: err = "No source object tag given" plLogger.LogError(err) this_cmd.Set('Status', err) return False if not command_name: err = "Command name not specified" plLogger.LogError(err) this_cmd.Set('Status', err) return False rtr_list = tag_utils.get_tagged_objects_from_string_names(targ_tag_list) # Remove duplicates by using an ordered dictionary rtr_list = dm_utils.remove_dup_scriptable(rtr_list) if len(rtr_list) == 0: err = "targetTagList results in an empty list" plLogger.LogError(err) this_cmd.Set('Status', err) return False pf_state, status = 'FAILED', '' with AutoCommand(PKG + '.ExpandTemplateCommand') as cmd: cmd.SetCollection('StmTemplateConfigList', [tmpl_cfg.GetObjectHandle()]) cmd.SetCollection('SrcTagList', [src_tag]) cmd.Execute() pf_state = cmd.Get('PassFailState') status = cmd.Get('Status') if pf_state == 'FAILED': err = '{}.ExpandTemplateCommand failed: {}' \ .format(PKG, status) plLogger.LogError(err) this_cmd.Set('Status', err) return False # Call the wizard once the configuration is loaded cfg_obj_list = tag_utils.get_tagged_objects_from_string_names([src_tag]) if not cfg_obj_list: err = 'Failed to load expected configuration object for {}' \ .format(tmpl_cfg.Get('Name')) plLogger.LogError(err) this_cmd.Set('Status', err) return False if len(cfg_obj_list) > 1: err = 'More than one configuration objects loaded from {}' \ .format(tmpl_cfg.Get('Name')) plLogger.LogInfo(err) # We check the object list just to prevent bad input. The target # command operates on the tag only, so we don't need to manipulate the # objects beyond getting the count pf_state, status = 'FAILED', '' tag_created = False if not route_tag_name: route_tag_name = 'Tmp Imported Routes' tag_created = True with AutoCommand(command_name) as cmd: # Set the parameters depending on the command used if 'Import' in command_name: cmd.SetCollection('RouterTagList', targ_tag_list) cmd.Set('BgpImportParamsTagName', src_tag) cmd.Set('CreatedRoutesTagName', route_tag_name) elif 'Prefix' in command_name: cmd.SetCollection('RouterTagList', targ_tag_list) cmd.Set('SrcObjectTagName', src_tag) cmd.Set('CreatedRoutesTagName', route_tag_name) cmd.Execute() pf_state = cmd.Get('PassFailState') status = cmd.Get('Status') if pf_state == 'FAILED': err = '{} failed: {}'.format(command_name, status) plLogger.LogError(err) this_cmd.Set('Status', err) return False # After a successful run, we need to associate the newly-created # routes to the template with the GeneratedObject relation added_route_list = \ tag_utils.get_tagged_objects_from_string_names([route_tag_name]) for route in added_route_list: tmpl_cfg.AddObject(route, RelationType('GeneratedObject')) # If we created a temporary tag, delete it here if tag_created: tag_obj = tag_utils.get_tag_object(route_tag_name) tag_obj.MarkDelete() return True
def run(TargetObjectList, TargetObjectTagList, SrcObjectList, SrcObjectTagList, RouteCount): plLogger = PLLogger.GetLogger("methodology") this_cmd = get_this_cmd() # Process targets for RouterConfigs routers_dict = get_routers(TargetObjectList, TargetObjectTagList) # If we get empty dictionary here, error has already been created if not routers_dict: return False # Process sources for RouteConfig XMLs rmix_list = [] if SrcObjectList: rmix_list = CCommandEx.ProcessInputHandleVec('StmTemplateMix', SrcObjectList) if SrcObjectTagList: rmix_list = rmix_list + \ tag_utils.get_tagged_objects_from_string_names(SrcObjectTagList) rmix_list = dm_utils.remove_dup_scriptable(rmix_list) if len(rmix_list) == 0: err = "Neither SrcObjectList nor SrcObjectTagList " \ "specified a valid SrcObjectList object." plLogger.LogError(err) this_cmd.Set('Status', err) return False # Each RouteConfig we find in the StmTemplateMix'es StmTemplateConfigs is # a source point to use in a ExpandTemplateCommand (with targets being # routers from the StmProtocolMix) for rmix in rmix_list: r_mi = rmix.Get('MixInfo') if r_mi == '': err = "MixInfo is empty for {}".format(rmix.Get('Name')) plLogger.LogError(err) this_cmd.Set('Status', err) return False err_str = json_utils.validate_json(r_mi, this_cmd.Get('MixInfoJsonSchema')) if err_str != '': err = "MixInfo in the StmTemplateMix does not conform to the " \ "schema " + this_cmd.Get('MixInfoJsonSchema') plLogger.LogError(err) this_cmd.Set('Status', err) return False err_str, mix_data = json_utils.load_json(r_mi) if err_str != "": plLogger.LogError(err_str) this_cmd.Set("Status", err_str) return False mix_comp_list = mix_data.get('components') if mix_comp_list is None: err = "Invalid JSON in MixInfo: MixInfo does not " \ "contain components." plLogger.LogError(err) this_cmd.Set('Status', err) return False tmpl_cfg_list = rmix.GetObjects('StmTemplateConfig') for tmpl_cfg, mix_comp in zip(tmpl_cfg_list, mix_comp_list): # At this point, we have the template and associated component # entry, and we need to determine what kind of template file is # being loaded # First check the expand exp_list = mix_comp.get('postExpandModify', []) wiz_list = [] for exp in exp_list: wiz = exp.get('bllWizardExpand') if wiz is None: continue wiz_list.append(wiz) if wiz_list: if not process_wizard_args(tmpl_cfg, wiz_list): # Error message handled in called functions return False else: if not process_route_args(tmpl_cfg, routers_dict): # Error message handled in called function return False # After the routes are created, call allocate for each argument with AutoCommand(PKG_RTG + '.AllocateRouteMixCountCommand') as cmd: cmd.SetCollection('RouteMixList', [r.GetObjectHandle() for r in rmix_list]) cmd.Set('RouteCount', RouteCount) cmd.Execute() pf_state = cmd.Get('PassFailState') status = cmd.Get('Status') if pf_state == 'FAILED': err = '{}.AllocateRouteMixCountCommand failed: {}' \ .format(PKG_RTG, status) plLogger.LogError(err) this_cmd.Set('Status', err) return False return True