Найти и позже удалить объекты информатики зомби

Есть ли простой способ идентифицировать и очистить неиспользуемые артефакты информатики?

Контекст: В одном из проектов много зомби-сессий/маппингов и т.п, создателей давно нет.

Я хочу сделать следующее:

  1. Список/удаление всех сеансов, не связанных с рабочим процессом.
  2. Список/удаление всех сопоставлений, которые не используются ни в одном сеансе/wf.
  3. Список/удаление всех источников/целей, которые не использовались ни в одном отображении.
  4. Список/удаление всех рабочих процессов, которые не запускались в течение последнего года.

Кто-то упомянул об использовании: Designer > Tools > Queries. Я не могу выразить приведенное выше 1/2/3/4 с помощью данной опции, может ли кто-нибудь пролить свет?

Примечание.

  • Я не ищу кликать один за другим и находить зависимости.
  • Я не ищу скачивание всего растения в виде xml и поиск зависимостей по одной

person Espresso    schedule 23.04.2014    source источник
comment
Привет! Запросы действительно не слишком полезны. Я работаю над некоторым решением. Не могли бы вы сообщить мне, если вам это все еще нужно? Я надеюсь, что он будет готов к концу недели. Мне понадобится ваша поддержка в тестировании. Пожалуйста, дайте мне знать.   -  person Maciejg    schedule 06.05.2014
comment
Это было бы прекрасно. Дайте мне знать, когда я смогу протестировать ваш скрипт. Если не сложно спросить, совместимы ли скрипты с Linux?   -  person Espresso    schedule 07.05.2014
comment
Готово. Пожалуйста, смотрите ответ ниже. Сценарии используют клиентский инструмент pmrep Windows PowerCenter. Можно было бы создать версию для Linux, но у меня нет под рукой среды. Возможно когда-нибудь ;)   -  person Maciejg    schedule 09.05.2014
comment
Привет Maciejg, вы можете вставить/прикрепить скрипты в виде обычного текстового файла сюда? загрузка zip-файла ограничена из-за проблем с безопасностью.   -  person Espresso    schedule 22.05.2014
comment
Это будет не так просто. Мое решение представляет собой простой скрипт Python, но он использует несколько разных модулей. В этом случае вам нужно создать сценарий оболочки. В общем, идея состоит в том, чтобы вызвать pmrep listobjects для всех типов объектов, а затем pmrep listobjectdependencies для каждого объекта. Если последний возвращает только 1 объект (я), то его можно удалить.   -  person Maciejg    schedule 23.05.2014


Ответы (1)


Поскольку это не так просто реализовать с помощью PowerCenter, я попытался придумать какой-нибудь простой инструмент для решения этой проблемы. Полное описание и ссылку для скачивания можно найти на этой странице.

Ниже вы найдете код, опубликованный по запросу в комментариях: Найти и позже удалить зомби информационные объекты

Не стесняйтесь использовать, делиться и улучшать :) Любой обзор кода также будет высоко оценен.

import subprocess
import os
from subprocess import *
import platform
import sys
import getpass
import configparser


#global variables declarations
currentDir=''
pmrepPath=''
domainFile=''


def connect_to_repo(Repository,Domain,User,Host,Port, UserSecurityDomain):
        #password = raw_input("Enter password for Repository: " + Repository + ", User: " + User)
        password = getpass.getpass()
        print "\nConnecting..."
        if Domain != '':
            RepoCommand="pmrep connect -r "+Repository+" -d "+Domain+" -n "+User + " -x " + password #+" -X DOMAIN_PWD"
        else:
            RepoCommand="pmrep connect -r "+Repository+" -n "+User + " -x " + password + " -h " + Host + " -o " + Port
        if UserSecurityDomain != '':
            RepoCommand += " -s " + UserSecurityDomain
        RepoCommand=RepoCommand.rstrip()
        p=subprocess.Popen(RepoCommand,stderr=subprocess.PIPE,stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)
        out,err=p.communicate()
        if p.returncode or err:
                print "Connection Failed"
                print err.strip()
                print out.strip()
                sys.stdout.flush()
                sys.stdin.flush()
        else:
                print "Connection Successful"
                sys.stdout.flush()
                sys.stdin.flush()
        return p.returncode

def execute_pmrep_command(command, output_file_name, start_line, end_line, line_prefix):
        if len(line_prefix)>0: line_prefix+=' '
        out=open(output_file_name,'a')
        return_code=subprocess.Popen(command,stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True)
        output,error=return_code.communicate()
        for line in output.split('\r\n')[start_line:end_line]:
            out.writelines(line_prefix + line + '\n')

        out.close()
        return

def check_platform():
        global domainFile
        global currentDir
        global pmrepPath
        global platForm
        platForm=platform.system()
        print "Platform recognized : "+platForm
##        if not os.getenv('INFA_HOME', 'C:\\Informatica\\9.5.1'):
##                print "INFA_HOME env_variable not set in your "+platForm+" platform."
##                print "Please set INFA_HOME and continue."
##                raw_input()
##                sys.exit(0)
        if not os.getenv('INFA_DOMAINS_FILE'):
                print "INFA_DOMAINS_FILE env_variable not set in your "+platForm+" platform."
                print "Please set INFA_DOMAINS_FILE and continue."
                raw_input()
                sys.exit(0)
##        elif not os.getenv('DOMAIN_PWD', 'vic'):
##                print "DOMAIN_PWD env variable not set in your "+platForm+" platform."
##                print "Please set DOMAIN_PWD and continue."
##                raw_input()
##                sys.exit(0)

##        else:
##                if platForm == 'Windows':
##                        pmrepPath=os.getenv('INFA_HOME').strip()+"\clients\PowerCenterClient\client\\bin"
##                elif platForm == 'Linux':
##                        pmrepPath=os.getenv('INFA_HOME').strip()+"/server/bin"
##                currentDir=os.getcwd()
##                domainFile=os.getenv('INFA_DOMAINS_FILE','C:\\Informatica\\9.5.1\\domains.infa').strip()


config = configparser.RawConfigParser()
config.optionxform = lambda option: option
config.read('InfaRepo_ListUnusedObjects.cfg')

infaDir = config.get('Common', 'infaDir').strip()
Repository = config.get('Common', 'Repository').strip()
Domain = config.get('Common', 'Domain').strip()
Host = config.get('Common', 'Host').strip()
Port = config.get('Common', 'Port').strip()
Folder = config.get('Common', 'Folder').strip()
User = config.get('Common', 'User').strip()
UserSecurityDomain = config.get('Common', 'UserSecurityDomain').strip()
objectTypeList = config.get('Common', 'objectTypeList').split(',')

if Domain != '':
    print 'Domain provided, will be used to connect.'
else:
    print 'Domain not provided, Host and Port will be used to connect.'

for i in range(len(objectTypeList)):
    objectTypeList[i]=objectTypeList[i].strip()

currentDir=os.getcwd()
outputDir=currentDir+'\\UnusedObjectsReport'

###objectTypeList = ['mapplet', 'mapping', 'session', 'source', 'target', 'worklet']
##
##objectTypeList = ['target']

pmrepPath=infaDir.strip()+"\clients\PowerCenterClient\client\\bin"

os.chdir(pmrepPath)

outFile = outputDir + "\ListOfUnusedObjects.txt"
if not os.path.exists(os.path.dirname(outFile)):
        os.makedirs(os.path.dirname(outFile))
print 'Output file: ' + outFile
open(outFile,'w').writelines("Domain :  "+Domain+"\nRepository : "+Repository+"\nUserName : "+User+"\n")
open(outFile,'a').writelines("***************************"+"\n")
open(outFile,'a').writelines("LIST OF UNUSED OBJECTS:\n")

outBatchFile = outputDir + "\DeleteUnusedObjects.bat"
tempDir = outputDir + "\\temp"
if not os.path.exists(outputDir):
        os.makedirs(outputDir)
if not os.path.exists(tempDir):
        os.makedirs(tempDir)

for tempFile in os.listdir(tempDir):
    os.remove(os.path.join(tempDir, tempFile))

print 'Output batch file: ' + outBatchFile

if Domain != '':
    RepoCommand="pmrep connect -r "+Repository+" -d "+Domain+" -n "+User
else:
    RepoCommand="pmrep connect -r "+Repository+" -n "+User + " -h " + Host + " -o " + Port
if UserSecurityDomain != '':
    RepoCommand += " -s " + UserSecurityDomain

open(outBatchFile,'w').writelines(pmrepPath+"\\"+RepoCommand+"\n")

objectTypeCounter=0

return_code=connect_to_repo(Repository,Domain,User,Host,Port,UserSecurityDomain)

objDepDict={}

error = False
errorList = []

#check if repository connection is successfull
if return_code==0:
    for objectType in objectTypeList:
        objectTypeCounter+=1
        print "Step {0} of {1}: {2}".format(objectTypeCounter, len(objectTypeList), objectType)

        objectFile = tempDir + "\\" + objectType + ".txt"
        open(objectFile,'w').writelines("")

        objectDepFile = tempDir + "\\" + objectType + "_dep.txt"
        open(objectDepFile,'w').writelines("")
        execute_pmrep_command("pmrep listobjects -f " + Folder + " -o " + objectType, objectFile, 8, -4, '')

        objectList=open(objectFile).readlines()

        objectCounter=0

        if len(objectList) == 0:
            print '\tNo {0}s found'.format(objectType)

        elif objectList[0][:3] == ' [[':
            error=True
            for line in objectList:
                errorList += [line.replace('\n','')]
            break


        for line in objectList:
                objectCounter+=1
                fields=line.split(' ')
                if len(fields) == 2:
                    objectType=fields[0]
                    objectName=fields[1][:-1]
                else:
                    objectType=fields[0]
                    objectName=fields[2][:-1]
                    #if the object is non-reusable, it obviously is in some workflow, so skipp it
                    if fields[1] == 'non-reusable':
                        print "\t{0} {1} of {2}: {3} is not a reusable {4} - skipping".format(objectType, objectCounter, len(objectList), objectName, objectType)
                        continue

                command = "pmrep listobjectdependencies -f " + Folder + " -n " + objectName + " -o " + objectType + " -p parents"
                #print "Getting object dependencies for " + objectType + " " + objectName

                print "\t{0} {1} of {2}: {3}".format(objectType, objectCounter, len(objectList), objectName)

                execute_pmrep_command(command, objectDepFile, 8, -6, objectName)

        #find unused objects

        for fileLine in open(objectDepFile,'r').readlines():
            line = fileLine.split(' ')
            if len(line) == 3:
                Name = line[0]
                ParentType = line[1]
                ParentName = line[2]
            else:
                Name = line[0]
                ParentType = line[1]
                ParentName = line[3]
            try:
                objDepDict[objectType + ': ' + Name]+=[ParentType + ' ' + ParentName]
            except:
                objDepDict[objectType + ': ' + Name]=[ParentType + ' ' + ParentName]


    found = False
    for objectKey in objDepDict.iterkeys():
        objectType, objName = objectKey.replace(' ','').split(':')
        if len(objDepDict[objectKey]) <= 1:
            if not found:
                print '\n'
                print 'Following unused objects have been found:'
                found = True
            print '\t{0}: {1}'.format(objectType, objName)
            open(outFile,'a').writelines('{0}: {1}\n'.format(objectType, objName))
            open(outBatchFile,'a').writelines("rem {0}\\pmrep deleteobject -f {1} -o {2} -n {3}\n".format(pmrepPath, Folder, objectType, objName))

    execute_pmrep_command('pmrep cleanup', 'log.txt', 0, 0, '')

    open(outBatchFile,'a').writelines(pmrepPath+'\\pmrep cleanup' + '\n')

    if not error:
        if not found:
            print 'No unused objects found.'
        print '\nDone.'
        print 'Output file: ' + outFile
        print 'Output batch file: ' + outBatchFile
    else:
        print 'Following errors occured:'
        for e in errorList:
            print '\t', e
#wait for key press
print '\nHit Enter to quit...'
raw_input()
#End of program
person Maciejg    schedule 07.05.2014
comment
Полезно, если ваш ответ/сценарий находится на этой же странице. Я зашел на вашу страницу и проверил, там нет ни скрипта, ни zip файла (был там несколько месяцев назад). Не могли бы вы добавить сюда код скрипта для всеобщего обозрения? - person Espresso; 04.12.2014
comment
Застежка-молния вернулась — приносим извинения за неудобства. Однако я не хочу публиковать код. Он работает нормально, но потребует некоторой доработки и рефакторинга, прежде чем я осмелюсь показать его миру. - person Maciejg; 04.12.2014
comment
Этот форум имеет дух открытости для улучшения сотрудничества. В этом духе лучше выложить код. Если только у вас нет намерения мониторить, замаскированного под «переделку». Другие помогут улучшить код, сделать его универсальным и т. д. - person Espresso; 04.12.2014
comment
Привет Maciejg, попробую протестировать код, хотя я перешел в другой проект. - person Espresso; 06.12.2014