def btc_xmi_logoff(self): """ Perform BAPI XMI Log Off OSS Notes: 1770388 - Enhancements in the XBP interface :return:Fail(error Message """ self.logger.debug('starting BAPI_XMI_LOGOFF') result = self.call_fm('BAPI_XMI_LOGOFF', INTERFACE='XBP') if result.fail: return result result=result.data if result['RETURN']['TYPE'] == 'E': if result['RETURN']['NUMBER'] != '028': logMessage = 'BAPI_XMI_LOGOFF: {:s}'.format(result['RETURN']['MESSAGE']) self.logger.error(logMessage) return Fail(message=logMessage) else: self.logger.debug('user was not logged on to interface') return Result(data=True) else: self.logger.debug('BAPI_XMI_LOGOFF successful') return Result(data=True)
def execute(self): checkobj = self.checkObject for id, parameterSet in enumerate(checkobj.params): self.logger.debug('Parameter Set {}, Options: {}'.format( id, pformat(parameterSet.__repr__))) record = dict(RATING='pass', WHERE_CLAUSE=parameterSet.where_clause, TABLE=parameterSet.table_name, EXPECTED=parameterSet.expected_count, OPERATOR=self.operators.lookup( parameterSet.operator), PARAMETERSET=parameterSet.param_set_name) tab_fields = parameterSet.table_fields.split(';') result = self.retrieveData(tabname=record['TABLE'], where_clause=record['WHERE_CLAUSE'], tab_fields=tab_fields) if not result.fail: downloaded_data = result.data['data'] record['CONFIGURED'] = len(downloaded_data) else: record['CONFIGURED'] = result.fail record['RATING'] = 'error' self.actionResult.add_result(record) self.actionResult.rating = 'error' return Result(self.actionResult) record = self.rateIndividualResult(record) self.actionResult.addResult(record) self.rateOverallResult() return Result(data=self.actionResult)
def _profileContents(self): """ Get Contents of all profiles :param profilename: Profile Name Parameter values spanning over multiple lines, are identified by column COMNR. """ result=self._profileNames() if result.fail: return result profilenames=result.data self.logger.debug('Reading Profile Contents') self.logger.debug('Reading Default Profile from DB') profileContents=dict(DEFAULT=[], INSTANCE=[], START=[]) for type, names in profilenames.items(): for name in names: result=self._singleProfileContent(name) if result.fail: return result profileContents[type].extend(result.data) return Result(data=profileContents)
def btc_xbp_job_definition_get(self, jobname:str, jobcount:str): """ Retrive the definition of a specfic job using function module BAPI_XBP_JOB_DEFINITION_GET. :param jobname: Name of the job :param jobcount: Job Nubmber :param extUserName: External User name :return: """ self.logger.debug('starting BAPI_XBP_JOB_DEFINITION_GET') fmParameters = dict(JOBNAME=jobname, JOBCOUNT=jobcount, EXTERNAL_USER_NAME=self.XBP_EXT_USER) result = self.call_fm('BAPI_XBP_JOB_DEFINITION_GET', **fmParameters) if result.fail: return result result=result.data if result['RETURN']['TYPE'] == 'E': logMessage = 'BAPI_XBP_JOB_DEFINITION_GET for job {} ({}) failed: {}'.format(jobname, str(jobcount), result['RETURN']['MESSAGE']) self.logger.error(logMessage) return Fail(message=logMessage) else: self.logger.debug('BAPI_XBP_JOB_DEFINITION_GET successful: ' + pformat(result)) return Result(data=result)
def logon(self, logon_info:dict, mock:bool=False, mockdata:dict=False)->Union[Result, Fail]: """ Logon to the specified system :param logon_info: Information required to logon to a system :param mock: If True, then no real pyRFC conection will be established. This is for testing. :param moockdata: Data that should be used for the mock testing """ if logon_info is False: return Fail(message='Logon Info Incomplete') self.mock = mock self.logger = logging.getLogger('{}.{}'.format(__name__, self.__class__.__name__)) result = Result(message='Connection Successful') if mock: try: self.conn = MockConnection(mockdata=mockdata) except Exception as err: return Fail('Mock Connection Setup Failed') else: try: self.logger.debug('Logon Details: %s', pformat(logon_info)) self.conn = pyrfc.Connection(**logon_info) except Exception as err: result = self._handle_exception(err) return result
def btc_xbp_job_close(self, jobname, jobcount): """ Closes the job definition OSS Notes: 1770388 - Enhancements in the XBP interface :param jobname: Job Name :param jobcount: Unique job count number for the background job :return: Result(True) if successful Fail(Error Message) """ self.logger.debug('starting BAPI_XBP_JOB_CLOSE') result = self.call_fm('BAPI_XBP_JOB_CLOSE', JOBNAME=jobname, JOBCOUNT=jobcount, EXTERNAL_USER_NAME=self.XBP_EXT_USER) if result.fail: return result result=result.data if result['RETURN']['TYPE'] == 'E': logMessage = 'BAPI_XBP_JOB_CLOSE for {:s} ({:s}: '.format(jobname, jobcount, result['RETURN']['MESSAGE']) self.logger.error(logMessage) return Fail(message=logMessage) else: self.logger.debug('schedule_job_immediately: BAPI_XBP_JOB_CLOSE successful') return Result(data=True)
def btc_xmi_logon(self, interface:str='XBP'): """Starting BAPI XMI logon process OSS Notes: 1770388 - Enhancements in the XBP interface :param externalCompany: Name of the external company :param externalProduct: Name of the external product :param interface: Interface to logon to :param version: Version of the interface :return: Fail(error Message) or Result(True) """ self.logger.debug('starting BAPI_XMI_LOGON') result = self.call_fm('BAPI_XMI_LOGON', EXTCOMPANY=self.XBP_EXT_COMPANY, EXTPRODUCT=self.XBP_EXT_PRODUCT, INTERFACE=interface, VERSION=self.XPB_INTERFACE_VERS) if result.fail: return result result=result.data if result['RETURN']['TYPE'] == 'E' and result['RETURN']['MESSAGE'] != 'Tool already logged on in interface XBP': logMessage = 'BAPI_XMI_LOGON: {:s}'.format(result['RETURN']['MESSAGE']) sid = self.sid() client = self.conn.get_connection_attributes().get('client') self.logger.error('%s Client %s: %s', sid, client, logMessage) return Fail(message=logMessage) else: self.logger.debug('BAPI_XMI_LOGON successful') result=Result(data=True) return result
def btc_xbp_job_start_immediately(self, jobname, jobcount): """ Starts a defined job immediately OSS Notes: 1770388 - Enhancements in the XBP interface :param jobname: Name of the Job :param jobcount: Unique job count number for the background job :return: """ self.logger.debug('starting BAPI_XBP_JOB_START_IMMEDIATELY') result = self.call_fm('BAPI_XBP_JOB_START_IMMEDIATELY', JOBNAME=jobname, JOBCOUNT=jobcount, EXTERNAL_USER_NAME=self.XBP_EXT_USER) if result.fail: return result result=result.data if result['RETURN']['TYPE'] == 'E': logMessage = 'BAPI_XBP_JOB_START_IMMEDIATELY for {:s} ({:s}): {:s}'.format(jobname, jobcount, result['RETURN']['MESSAGE']) self.logger.error(logMessage) return Fail(message=logMessage) else: self.logger.debug('schedule_job_immediately: BAPI_XBP_JOB_START_IMMEDIATELY successful') return Result(data=True)
def instances(self) -> Union[Result, Fail]: """ Returns the names of the instances as list""" fm_result = self.call_fm('TH_SERVER_LIST') if fm_result.fail: return fm_result result = [instance['NAME'] for instance in fm_result.data['LIST']] return Result(data=result)
def call_fm(self, fm: str, **kwargs) -> Union[Result, Fail]: """ Call Function Module with Exception Handling""" self.logger.debug('Executing Function Module {}'.format(fm)) try: data = self.conn.call(fm, **kwargs) except Exception as err: return(self._handle_exception(err)) return Result(message='call to {} successful'.format(fm), data=data)
def component(self, component:str)-> Result: """ Check whether a component is installed and retrieve the versions :param component: the name of the component """ where_clause="COMPONENT EQ '{}'".format(component.upper()) result=self.download_table('CVERS', where_clause=where_clause, tab_fields=['COMPONENT']) if result.fail: return result data=result.data.get('data') if len(data): return Result(data=data[0]) else: return Result(data=[])
def get_connection(logon_info:dict)->Union[Result, Fail]: """ Establish a connection to an ABAP System """ connection = Connection() result = connection.logon(logon_info) if not result.fail: result=Result(message='Logon Successful', data=connection) return result
def btc_xbp_job_log_read(self, jobname, jobcount, protNew=None, lines=None, direction=None): """ Read the log of the specified job. :param protNew: :param lines: :param direction: :param jobname: Name of the job :param jobcount: Job Nubmber :param extUserName: External User name :return: """ self.logger.debug('starting BAPI_XBP_JOB_JOBLOG_READ') fmParameters = dict(JOBNAME=jobname, JOBCOUNT=jobcount, EXTERNAL_USER_NAME=self.XBP_EXT_USER) if protNew: fmParameters['PROT_NEW'] = protNew if lines: fmParameters['LINES'] = lines if direction: fmParameters['DIRECTION'] = direction result = self.call_fm('BAPI_XBP_JOB_JOBLOG_READ', **fmParameters) if result.fail: return result result=result.data if result['RETURN']['TYPE'] == 'E': logMessage = 'BAPI_XBP_JOB_JOBLOG_READ for job {:s} ({:d}) failed: {:s}'.format(jobname, int(jobcount), result['RETURN'][ 'MESSAGE']) self.logger.error(logMessage) return Fail(logMessage) else: self.logger.debug('BAPI_XBP_JOB_JOBLOG_READ successful: ' + pformat(result)) return Result(result)
def _profileNames(self)->Result: """ Get the names of the Profiles in the database """ self.logger.debug('reading profiles from system') instance_profiles = None start_profiles = None result = self.systemConnection.call_fm('PFL_GET_PROF_LIST') if result.fail: return result instance_profiles = set( [record['PFNAME'] for record in result.data['HEADER_TAB'] if record['TYPE'] == 'I']) start_profiles = set( [record['PFNAME'] for record in result.data['HEADER_TAB'] if record['TYPE'] == 'S']) default_profiles = set( [record['PFNAME'] for record in result.data['HEADER_TAB'] if record['TYPE'] == 'D']) result=Result(data={'DEFAULT':default_profiles, 'INSTANCE':instance_profiles, 'START':start_profiles}) return result
def get_runtime_parameter(self, parameter): """ Get the value of the specified profile parameter :param configParameter: profile parameter to query :return: Result({value:... , name:parameter}) or Fail(message) """ result = self.call_fm('SXPG_PROFILE_PARAMETER_GET', PARAMETER_NAME=parameter) if result.fail: return result response=result.data if response['RET']!=0: return Fail('Error Retrieving Value of {}'.format(parameter)) return Result(data={'value': response['PARAMETER_VALUE'], 'name': parameter})
def systemtime(self): """ Get System Timezone The function calls function module TH_GET_START_TIME2. A sample execution is documented below. START_TIME is the number of seconds since 01.01.1970 (epoch). Uptime is specified in seconds. TS_GMTIME is the start time in UTC, TS_LOCALTIME is the start time in the local time zone of the server. -------------------------------------------------------------------------------- | Export parameters |Value | -------------------------------------------------------------------------------- | START_TIME |1484444152 | | START_TIME_STR |Sun Jan 15 01:35:52 2017 | | UPTIME |1,157 | | TS_GMTIME |20170115013552 | | TS_LOCALTIME |20170115013552 | -------------------------------------------------------------------------------- """ self.logger.debug('retrieving system time') result=self.call_fm('TH_GET_START_TIME2') if result.fail: self.logger.debug('Failed to retrieve system time: %s', result.message) return result uptime=int(result.data['UPTIME']) starttime=int(result.data['START_TIME']) localstarttime=datetime.datetime.strptime(result.data['TS_LOCALTIME'],'%Y%m%d%H%M%S') localtime=localstarttime + datetime.timedelta(seconds=uptime) utcstarttime=datetime.datetime.strptime(result.data['TS_GMTIME'],'%Y%m%d%H%M%S') utctime=localstarttime + datetime.timedelta(seconds=uptime) result=dict(uptime = uptime, starttime = starttime, localtime = localtime, localstarttime = localstarttime, utctime=utctime, utcstarttime=utcstarttime) self.logger.debug('System Times: %s', pformat(result)) return Result(data=result)
def importChecks(path=None, session=None): """ Import all Checks :param path: The path to the checks """ logger.debug('Import Checks') success = dict() #will be used for status tracking failed = dict() #will be used for status tracking if path is None: logger.debug('No path specified, using default path') path = get_absolute_systemcheck_path('checks/dump') logger.debug('Path: %s', path) checkFiles = [ f for f in listdir(path) if isfile(join(path, f)) and f.endswith('.yaml') ] logger.debug('idenfied files: %s', pformat(checkFiles)) logger.debug('starting import:') for checkFile in checkFiles: logger.debug(' - %s', checkFile) result = importCheck(filename=join(path, checkFile), session=session) if result.fail: logger.error('Import of %s failed: %s', checkFile, result.message) failed[checkFile] = result.message else: logger.debug('Import of %s succeeded', checkFile) success[checkFile] = result.message if len(failed) > 0: message = 'Some imports failed!' else: message = 'Imports Succeeded' data = {'successful': success, 'failed': failed} return Result(message=message, data=data)
def btc_xbp_get_spool_as_dat(self, spoolRequest, firstPage=None, lastPage=None): """ Download spool request as .csv file This procedure requires function module BAPI_XBP_GET_SPOOL_AS_DAT which is delivered in the OSS note below: 1515293 - Transferring spool requests as delimited tab text files :param spoolRequest: Spool Request Number :param firstPage: First page of the spool request to download :param lastPage: Last page of the spool request to download. :return: Result(data) if successful or Fail(Message) if error """ self.logger.debug('starting BAPI_XBP_GET_SPOOL_AS_DAT') fmParameters = dict(SPOOL_REQUEST=int(spoolRequest), EXTERNAL_USER_NAME=self.XBP_EXT_USER) if firstPage: fmParameters['FIRST_PAGE'] = firstPage if lastPage: fmParameters['LAST_PAGE'] = lastPage result = self.call_fm('BAPI_XBP_GET_SPOOL_AS_DAT', **fmParameters) if result.fail: return result result = result.data if result['RETURN']['TYPE'] == 'E': logMessage = 'BAPI_XBP_GET_SPOOL_AS_DAT for spool request {:s}: {:s}'.format(spoolRequest, result['RETURN'][ 'MESSAGE']) self.logger.error(logMessage) return Fail(logMessage) self.logger.debug('BAPI_XBP_GET_SPOOL_AS_DAT successful') return Result(data=result)
def execute(self): checkobj = self.checkObject result = self.systemConnection.call_fm('TH_SERVER_LIST') if not result.fail: instances=result.data else: self.rateOverallResult(error=True, errormessage=result.fail) return Result(data=self.actionResult) for parameterSet in checkobj.params: for instance in instances['LIST_IPV6']: record = dict(RATING='pass', PARAMETERSET=parameterSet.param_set_name, PARAMETER=parameterSet.parameter, EXPECTED=parameterSet.expected_value, INSTANCE=instance['NAME'], OPERATOR=self.operators.lookup(parameterSet.operator)) logonInfo=self._adaptLogonInfo(instance) result=ABAP.utils.get_connection(logonInfo) if result.fail: record['RATING']='error' record['CONFIGURED']=result.fail self.actionResult.addResult(record) else: connection=result.data result=connection.get_runtime_parameter(record['PARAMETER']) if result.fail: record['RATING'] = 'error' record['CONFIGURED']=result.fail self.actionResult.addResult(record) else: response=result.data record['CONFIGURED']=response['value'] record = self.rateIndividualResult(record) self.actionResult.addResult(record) connection.close() self.rateOverallResult()
def _singleProfileContent(self, profilename:str): """ Get the content of a single profile :param profilename: NAme of the profile to download """ result = self.systemConnection.call_fm('PFL_READ_PROFILE_FROM_DB', PROFILE_NAME=profilename) if result.fail: return result profileData = result.data.get('DTAB') parameter = None value = None configuredParameters = list() # Append an empty row at the end of the data profileData.append({'PARNAME': None, 'COMNR': '0001'}) for counter, row in enumerate(profileData): if row['PARNAME'] and row['COMNR'] == '9990': if parameter and value and profilename: configuredParameters.append(dict(PVALUE=value, PARNAME=parameter, PFNAME=profilename)) parameter = row['PARNAME'] value = row['PVALUE'] profilename=row['PFNAME'] elif row['COMNR'] in ['9991', '9992', '9993', '9994', '9995', '9996', '9997', '9998', '9999']: value += row['PVALUE'] elif row['COMNR'] == '0001': if parameter and value: record=dict(PVALUE = value, PARNAME = parameter, PFNAME = profilename) configuredParameters.append(record) parameter = None value = None profilename = None return Result(data=configuredParameters)
def btc_xbp_add_ext_job_step(self, jobname, jobcount, extProgramName, extProgramParameters, sapUserName, destinationHost=None): """ Add external program as Step to the Job OSS Notes: 1770388 - Enhancements in the XBP interface :param extProgramName: Name of the external program :param extProgramParameters: Parameters for the external program :param sapUserName: SAP Username :param jobname: Name of the background job :param jobcount: Unique job count number for the background job :param program: ABAP Program Name :return: Result(True) if the message succeeds Fail(Message) if step fails. """ fmOptions = dict(JOBNAME=jobname, JOBCOUNT=jobcount, EXTERNAL_USER_NAME=self.XBP_EXT_USER, EXT_PROGRAM_NAME=extProgramName, EXT_PROGRAM_PARAMETERS=extProgramParameters, SAP_USER_NAME=sapUserName) if destinationHost: fmOptions['TARGET_HOST'] = destinationHost self.logger.debug('calling function module BAPI_XBP_JOB_ADD_EXT_STEP with parameters %s', pformat(fmOptions)) result = self.call_fm('BAPI_XBP_JOB_ADD_EXT_STEP', **fmOptions) if result.fail: return result result=result.data if result['RETURN']['TYPE'] == 'E': self.logger.error('BAPI_XBP_JOB_ADD_EXT_STEP:' + result['RETURN']['MESSAGE']) return Fail('BAPI_XBP_JOB_ADD_EXT_STEP:' + result['RETURN']['MESSAGE']) else: self.logger.debug('BAPI_XBP_JOB_ADD_EXT_STEP successful') return Result(data=True)
def execute(self): result = self._profileContents() if result.fail: self.rateOverallResult(error=True, errormessage=result.fail) return Result(data=self.actionResult) profileContents=result.data profileReference=ProfileParameterReference(profileContents) for parameterSet in self.checkObject.params: profiledata = profileReference.getValue(parameterSet.parameter, parameterSet.profiletype) if len(profiledata) == 0: record = dict(PARAMETERSET=parameterSet.param_set_name, PARAMETER=parameterSet.parameter, RATING='pass', PROFILETYPE=parameterSet.profiletype, OPERATOR=self.operators.lookup(parameterSet.operator), EXPECTED=parameterSet.expected, PROFILENAME='', CONFIGURED=None) record=self.rateIndividualResult(record) self.actionResult.addResult(record) else: for data in profiledata: record = dict(PARAMETERSET=parameterSet.param_set_name, PARAMETER=parameterSet.parameter, RATING='pass', PROFILETYPE=parameterSet.profiletype, OPERATOR=self.operators.lookup(parameterSet.operator), PROFILENAME=data.get('PFNAME'), EXPECTED=parameterSet.expected, CONFIGURED=data.get('PVALUE')) record = self.rateIndividualResult(record) self.actionResult.addResult(record)
def btc_xbp_variant_delete(self, abapProgramName:str, abapVariantName:str): """ Delete variant for ABAP program :param abapProgramName: Program name :param abapVariantName: variant name :return: """ result = self.btc_xmi_logon() if result.fail: self.logger.debug('logon to XBP interface failed {:s}/{:s}'.format(self.XBP_EXT_COMPANY, self.XBP_EXT_PRODUCT)) return result self.logger.debug('logon to XBP interface successful') # result = self.btc_xbp_variant_info_get(self, abapProgramName) # if not result.fail: # variants=[record['VARIANT'] for record in result.data.get('ABAP_VARIANT_TABLE')] # if abapVariantName in variants: fmParameters = dict() fmParameters['ABAP_PROGRAM_NAME'] = abapProgramName fmParameters['ABAP_VARIANT_NAME'] = abapVariantName fmParameters['EXTERNAM_USER_NAME']= self.XBP_EXT_USER result = self.call_fm('BAPI_XBP_VARIANT_DELETE', **fmParameters) if result.fail: return result if result.data['RETURN']['TYPE'] == 'E': return Fail(message=result.data['RETURN']['MESSAGE']) else: return Result('Variant Deleted')
def btc_xbp_job_open(self, jobName): """ Perform BAPI_XBP_JOB_OPEN OSS Notes: 1770388 - Enhancements in the XBP interface :param jobName:Name of the background job :return: Either Fail(True) or Result(jobcount) """ result = self.call_fm('BAPI_XBP_JOB_OPEN', JOBNAME=jobName, EXTERNAL_USER_NAME=self.XBP_EXT_USER) if result.fail: return result result=result.data if result['RETURN']['TYPE'] == 'E': logMessage = 'BAPI_XBP_JOB_OPEN {:s}: {:s}'.format(jobName, result['RETURN']['MESSAGE']) self.logger.error(logMessage) return Fail(message=logMessage) else: jobcount = result['JOBCOUNT'] self.logger.debug('BAPI_XBP_JOB_OPEN successful for job %s with job count %s', jobName, str(jobcount)) return Result(data=jobcount)
def execute(self): checkobj = self.checkObject for parameterSet in checkobj.params: record = dict( PARAMETERSET=parameterSet.param_set_name, EXPECTED=parameterSet.expected_count, OPERATOR=self.operators.lookup(parameterSet.operator), INTERVAL=parameterSet.interval, INTERVAL_TYPE=self.INTERVALS.get(parameterSet.interval_type), ABAPNAME=parameterSet.abapname, JOBNAME=parameterSet.sel_jobname, JOBCOUNT=parameterSet.sel_jobcount, JOBGROUP=parameterSet.sel_jobgroup, USERNAME=parameterSet.sel_username, NODATE=self.boolmapper(parameterSet.sel_no_date), WITH_PRED=self.boolmapper(parameterSet.sel_with_pred), EVENTID=parameterSet.sel_eventid, EVENTPARA=parameterSet.sel_eventpara, PRELIM=self.boolmapper(parameterSet.sel_prelim), SCHEDUL=self.boolmapper(parameterSet.sel_schedul), READY=self.boolmapper(parameterSet.sel_ready), RUNNING=self.boolmapper(parameterSet.sel_running), FINISHED=self.boolmapper(parameterSet.sel_finished), ABORTED=self.boolmapper(parameterSet.sel_aborted), ) parameters = dict() if parameterSet.abapname: parameters['ABAPNAME'] = parameterSet.abapname parameters['JOB_SELECT_PARAM'] = dict() parameters['JOB_SELECT_PARAM'][ 'JOBNAME'] = parameterSet.sel_jobname or '*' parameters['JOB_SELECT_PARAM'][ 'USERNAME'] = parameterSet.sel_username or '*' if parameterSet.sel_jobcount: parameters['JOB_SELECT_PARAM'][ 'JOBCOUNT'] = parameterSet.sel_jobcount if parameterSet.sel_jobgroup: parameters['JOB_SELECT_PARAM'][ 'JOBGROUP'] = parameterSet.sel_jobgroup if parameterSet.sel_no_date: parameters['JOB_SELECT_PARAM']['NODATE'] = self.boolmapper( parameterSet.sel_no_date) if parameterSet.sel_with_pred: parameters['JOB_SELECT_PARAM']['WITH_PRED'] = self.boolmapper( parameterSet.sel_with_pred) if parameterSet.sel_eventid: parameters['JOB_SELECT_PARAM'][ 'EVENTID'] = parameterSet.sel_eventid if parameterSet.sel_eventpara: parameters['JOB_SELECT_PARAM'][ 'EVENTPARA'] = parameterSet.sel_eventpara if parameterSet.sel_prelim: parameters['JOB_SELECT_PARAM']['PRELIM'] = self.boolmapper( parameterSet.sel_prelim) if parameterSet.sel_schedul: parameters['JOB_SELECT_PARAM']['SCHEDUL'] = self.boolmapper( parameterSet.sel_schedul) if parameterSet.sel_ready: parameters['JOB_SELECT_PARAM']['READY'] = self.boolmapper( parameterSet.sel_ready) if parameterSet.sel_running: parameters['JOB_SELECT_PARAM']['RUNNING'] = self.boolmapper( parameterSet.sel_running) if parameterSet.sel_finished: parameters['JOB_SELECT_PARAM']['FINISHED'] = self.boolmapper( parameterSet.sel_finished) if parameterSet.sel_aborted: parameters['JOB_SELECT_PARAM']['ABORTED'] = self.boolmapper( parameterSet.sel_aborted) result = self.systemConnection.systemtime if result.fail: record['CONFIGURED'] = result.fail record['RATING'] = 'error' self.actionResult.addResult(record) self.actionResult.rating = 'error' return Result(self.actionResult) if parameterSet.sel_from_date is None and \ parameterSet.sel_from_time is None and \ parameterSet.sel_to_date is None and \ parameterSet.sel_to_time is None: self.logger.debug('No Time frame specified') basetime = result.data['localtime'] self.logger.debug('basetime: %s', pformat(basetime)) intervall = datecalc.getIntervalDate( parameterSet.interval, parameterSet.interval_type, basetime, '-') self.logger.debug('interval border: %s', pformat(intervall)) parameters['JOB_SELECT_PARAM'][ 'FROM_DATE'] = intervall.strftime("%Y%m%d") parameters['JOB_SELECT_PARAM']['TO_DATE'] = basetime.strftime( "%Y%m%d") parameters['JOB_SELECT_PARAM'][ 'FROM_TIME'] = intervall.strftime("%H%M%S") parameters['JOB_SELECT_PARAM']['TO_TIME'] = basetime.strftime( "%H%M%S") self.logger.debug('Attempting Job Selection: %s', pformat(parameters)) result = self.retrieveData(**parameters) if not result.fail: downloaded_data = result.data record['CONFIGURED'] = len(downloaded_data['SELECTED_JOBS']) else: record['CONFIGURED'] = result.fail record['RATING'] = 'error' self.actionResult.addResult(record) self.actionResult.rating = 'error' return Result(self.actionResult) record = self.rateIndividualResult(record) self.actionResult.addResult(record) self.rateOverallResult() return Result(data=self.actionResult)
def btc_xbp_variant_create(self, abapProgramName, abapVariantName, abapVariantText, dia=None, protected=None, variantInfo=None, variantInfoL=None): """ Create variant for ABAP program :param abapProgramName: str Program name :param abapVariantName: str variant name :param abapVariantText: str desciption for variant :param dia: batch or dialog? :param protected: :param extUserName: external xmi username :param variantInfo: actual data of the variant :param variantInfoL: data of the variant with longnr parameters :return: variantInfo and variantInfoL are internal tables that need to be specified as a list of dictionaries. each row consisting of these fields: REPORT Report Name VARIANT Variant Name PNAME ABAP/4: Name of SELECT-OPTION / PARAMETER PKIND ABAP: Type of selection POLEN ABAP: Output length of selection condition PTEXT CHAR30 for SYST PSIGN ABAP: ID: I/E (include/exclude values) POPTION ABAP: Selection option (EQ/BT/CP/...) PLOW Selection variants: Field content (LOW/HIGH) PHIGH Selection variants: Field content (LOW/HIGH) """ result = self.btc_xmi_logon() if result.fail: self.logger.debug('logon to XBP interface failed {:s}/{:s}'.format(self.XBP_EXT_COMPANY, self.XBP_EXT_PRODUCT)) return result self.logger.debug('logon to XBP interface successful') # result = self.btc_xbp_variant_info_get(self, abapProgramName) # if not result.fail: # variants=[record['VARIANT'] for record in result.data.get('ABAP_VARIANT_TABLE')] # if abapVariantName in variants: fmParameters = dict() fmParameters['ABAP_PROGRAM_NAME'] = abapProgramName fmParameters['ABAP_VARIANT_NAME'] = abapVariantName fmParameters['ABAP_VARIANT_TEXT'] = abapVariantText if dia: fmParameters['DIA'] = dia if protected: fmParameters['DIA'] = protected if variantInfoL: fmParameters['VARIANT_INFO_L'] = variantInfoL elif variantInfo: fmParameters['VARIANT_INFO'] = variantInfo else: return Fail('Missing Variant Information') result = self.call_fm('BAPI_XBP_VARIANT_CREATE', **fmParameters) if result.fail: return result if result.data['RETURN']['TYPE'] == 'E': return Fail(message=result.data['RETURN']['MESSAGE']) else: return Result('Variant Created')
def download_table(self, tabname: str, where_clause: str = None, tab_fields: list = None, fetchsize: int = 1000) -> Union[Result, Fail]: '''Downloads a Table .. warning:: This can be memory intensive and is also restricted to a line length of 512 characters, :param where_clause: Where clause to restrict result set in ABAP syntax :param tab_fields: list of fields :param fetchsize: number of records to retrieve :param tabname: Table name :return: Result(data={data: <list of dictionaries>, headers: <list of headers>}) or Fail(message=message) ''' # TODO: Make more memory efficient # TODO: download records larger than 512 characters from pprint import pformat self.logger.debug('trying to download table ' + tabname) # Configure function module call fm_params = dict(QUERY_TABLE=tabname, DELIMITER='|') if where_clause: n = 72 # max. length of one where clause input value. fm_params['OPTIONS'] = [{'TEXT': where_clause[i:i + n]} for i in range(0, len(where_clause), n)] if tab_fields: fm_params['FIELDS'] = [{'FIELDNAME': x} for x in tab_fields] self.logger.debug('specified table fields: {:s}'.format(pformat(fm_params['FIELDS']))) fm_params['ROWCOUNT'] = fetchsize self.logger.debug('RFC_READ_TABLE parameters: {:s}'.format(pformat(fm_params))) result = self.call_fm('RFC_READ_TABLE', NO_DATA='X', **fm_params) if result.fail: return result fm_tbl_fields = result.data['FIELDS'] # this will contain the table definition including field length. fm_tbl_headers = [x['FIELDNAME'] for x in fm_tbl_fields] record_size = sum([int(x['LENGTH']) for x in fm_tbl_fields]) self.logger.debug('Record Size: {:d}'.format(record_size)) if record_size > 512: message = 'requested column length of {:d} is larger than maximum possible (512)'.format(record_size) self.logger.error(message) return Fail(message=message, data=fm_tbl_fields) iteration = 0 recordcounter = 1 table_data = [] while recordcounter > 0: self.logger.debug( 'starting function module RFC_READ_TABLE with data retrieval. Iteration: {:d}'.format(iteration)) rowskips = iteration * fetchsize fm_params['ROWSKIPS'] = rowskips result = self.call_fm('RFC_READ_TABLE', **fm_params) if result.fail: return result data = result.data['DATA'] if len(data) > 0: self.logger.debug( 'generating result set from returned records. fetchsize={:d}, iteration={:d}'.format(fetchsize, iteration)) for row in data: splitRow = row['WA'].strip().split('|') splitRow = [x.strip() for x in splitRow] record = dict(zip(fm_tbl_headers, splitRow)) table_data.append(record) else: recordcounter = 0 if iteration == 0: return Result(data={'data': [], 'headers': fm_tbl_headers}) iteration += 1 else: return Result(data={'data': table_data, 'headers': fm_tbl_headers})
def execute(self, connection, **kwargs): """ Verifies the system parameters according to config file. :param credentials: profile parameter to be checked. """ paramkeys = {item.upper() for item in self.actionResult['Parameters']} result = connection.fm_interface(self.FM) if result.fail: self.actionResult.rating = 'error' self.actionResult.rating = 'info' fm_interface = result.data fmkeys = {item['PARAMETER'] for item in fm_interface['PARAMS']} relevantParams = paramkeys & fmkeys fmcallparams = {} for parameter in relevantParams: param_value = self.actionResult['Parameters'].get(parameter, raw=True) if param_value == '': param_value = ' ' fmcallparams[parameter] = param_value self.logger.debug('parameters for SUIM API Call: %s', pformat(fmcallparams)) result = connection.call_fm(self.FM, **fmcallparams) if result.fail: raise SystemError fm_data = result.data message = 'The plugin showed some additional results: \n' #Analyzing the return structure return_data = fm_data.get('RETURN') if len(return_data) > 0: msg_types = [item['TYPE'] for item in return_data] for rec in return_data: message += '{}: {}\n'.format( self.BAPI_MSG_TYPES[rec.get('TYPE')], rec['MESSAGE']) self.actionResult.message = message if 'E' in msg_types or 'A' in msg_types: self.actionResult.rating = 'error' elif 'W' in msg_types: self.actionResult.rating = 'warning' self.actionResult.result = fm_data.get(self.RETURNSTRUCTURE) if len(self.actionResult.result) > 0: self.actionResult.rating = 'fail' else: self.actionResult.rating = 'pass' return Result(data=self.actionResult)
def importCheck(filename, session=None, format='yaml'): """ Import Checks :param filename: Name of the file that should get imported :param session: The session that should be used for importing the export :param format: The of the file """ logger.debug('Importing Check from file %s', filename) try: data = readChecksYaml(filename) except Exception as err: return Fail( message='Error reading Checks file: {}'.format(pformat(err))) if session is None: session = systemcheck.session.SESSION try: result = buildSaObject(data['object']) except Exception as err: logger.exception(err) return Fail(message='Error When Creating Check object: ' + pformat(err)) if result.fail: return result checkNode = result.data #Now we need to build the tree structure node = systemcheck.utils.get_or_create( session, model=systemcheck.checks.models.Check, parent_id=None) logger.debug('Building Tree Structure for %s', pformat(data.get('treepath'))) for level, branch in enumerate(data.get('treepath')): name = branch.get('name') saClassname = branch.get('type') description = branch.get('description') logger.debug('Level: %s, Name: %s, Class: %s', str(level), name, saClassname) saClass = models.get_class_by_name(models.meta.Base, saClassname) nodeFound = False for child in node.children: if isinstance(child, saClass) and child.name == branch.get('name'): logger.debug('Found existing node "%s" ', name) node = child nodeFound = True break if not nodeFound: logger.debug( 'Node with name %s and class %s does not exist. Create new', name, saClassname) node = saClass(name=name, description=description, parent_node=node) models.meta.base.Base.metadata.create_all(session.bind) try: session.commit() except Exception as err: return Fail(message='Error During Import: '.format(pformat(err))) # Finally, adding the object to the tree node.children.append(checkNode) try: session.commit() except Exception as err: return Fail(message='Error During Import: '.format(pformat(err))) return Result(data=checkNode)
def buildSaObject(saData: dict, saClass=None): """ Build a SQLAlchemy Object from the retrieved dictionary :param saData: The dictionary representation of the Object :param saClass: a hint for the recursive processing to provide a correct class """ logger.debug('building sqlalchemy object from data: %s') params = dict() if saClass is None: logger.debug('No Class Specified, determine class') saClassName = saData.get('type') saClass = models.get_class_by_name(models.meta.Base, saClassName) for key, value in saData.items(): if not isinstance(value, list): # Lists are lists of other SQLAlchemy models. We need to ignore them when instantiating for the first time params[key] = value logger.debug('Parameter to instantiate SQLAlchemy Object: %s', pformat(params)) try: saObject = saClass(**params) except Exception as err: logger.exception(err) return Fail(message='Error Building SQLAlchemy Object', data=err) for key, value in saData.items(): if isinstance(value, list): logger.debug('%s is a list', key) for subitem in value: if key == 'params': # Parameters do not inherit from the Checks tree, but are simple references. In this case, the name # of the class is the parent's class name with '__params' as suffix. newClassName = saClassName + '__params' logger.debug('Class name of key %s is %s', key, newClassName) elif key == 'restrictions': # Similar to parameters, restrictions do not inherit from the Checks tree either. In this case, the name # of the class is the parent's class name with '__restrictions' as suffix. newClassName = saClassName + '__restrictions' logger.debug('Class name of key %s is %s', key, newClassName) else: newClassName = subitem.get('type') if newClassName is not None: newClass = systemcheck.models.utils.get_class_by_name( models.meta.Base, newClassName) result = buildSaObject(subitem, newClass) if result.fail: return result newObject = result.data getattr(saObject, key).append(newObject) else: logger.error( 'Class Name for attribute %s could notbe determined (%s)', key, pformat(subitem)) return Result(message='SQLAlchem Object Built', data=saObject)