美文网首页Ovirt
【Ovirt 笔记】engine-cleanup 的实现原理

【Ovirt 笔记】engine-cleanup 的实现原理

作者: 58bc06151329 | 来源:发表于2017-05-21 14:36 被阅读50次

    文前说明

    作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

    本文仅供学习交流使用,侵权必删。
    不用于商业目的,转载请注明出处。

    分析整理的版本为 Ovirt 3.4.5 版本。

    命令使用方式:/usr/bin/engine-cleanup

    --log=file
        write log to this file.
    --config=file
        Load configuration files.
    --config-append=file
        Load extra configuration files or answer file.
    --generate-answer=file
        Generate answer file.
    

    命令采用了 python 方式进行实现。

    • 主要调用了 otopi
    exec "${otopidir}/otopi" "${baseenv} ${environment} ${otopienv}"
    
    baseenv="APPEND:BASE/pluginPath=str:${scriptdir}/../plugins APPEND:BASE/pluginGroups=str:ovirt-engine-common:ovirt-engine-remove"
    
    • 参数是设置 environment 的过程。
    --otopi-environment=*)
        otopienv="${v}"
    ;;
    --log=*)
        environment="${environment} CORE/logFileName=str:${v}"
    ;;
    --config=*)
        environment="${environment} APPEND:CORE/configFileName=str:${v}"
    ;;
    --config-append=*)
        environment="${environment} APPEND:CORE/configFileAppend=str:${v}"
    ;;
    --generate-answer=*)
        environment="${environment} OVESETUP_CORE/answerFile=str:${v}"
    ;;
    --help)
        usage
    ;;
    *)
    

    otopi

    otopioVirt 面向任务的可插拔安装/实施。是用于安装独立插件的系统组件。插件只需提供简单的添加的安装功能而无需复杂的事务管理。

    使用方式:otopi [variables]

    variables ::= name=type:value variables | APPEND:name=type:value | ''
    type ::= none | bool | int | str | multi-str
    
    APPEND: prefix appends as colon list string.
    
    CUSTOMIZATION
    -------------
    
    Set the following environment:
    
        DIALOG/customization=bool:True
    
    This will trigger command-line prompt before validation and
    before termination.
    
    Refer to README.dialog for more information.
    
    FILES
    -----
    
    CONFIGURATION
    
    Configuration files used to override the environment.
    
    System environment:
        OTOPI_CONFIG
    Environment:
        CORE/configFileName
    Default:
        /etc/otopi.conf
    
    Config files to be read:
        @configFileName@
        @configFileName@.d/*.conf (sorted)
    
    Structure:
    
        [environment:default]
        key=type:value
    
        [environment:init]
        key=type:value
    
        [environment:override]
        key=type:value
    
        [environment:enforce]
        key=type:value
    
    default is applied during setup without override.
    init is applied during setup with override.
    override is applied before customization with override.
    enforce is applied after customization with override.
    
    type ::= none | bool | int | str | multi-str
    
    ENVIRONMENT
    -----------
    
    Refer to README.environment
    
    UNPRIVILEDGE EXECUTION
    ----------------------
    
    Using sudo it is possible to escalate privilege. Use the following
    configuration:
    
    /etc/sudoers.d/50-otopi.conf
    
        Defaults:user1 !requiretty
        user1 ALL=(ALL) NOPASSWD: /bin/sh
    
    COMPATIBILITY
    -------------
    
    - Python-2.6
    - Python-2.7
    - Python-3.2
    

    执行流程,分析 ovirt-engine-commonovirt-engine-remove 源码。

    [ INFO  ] Stage: Transaction setup
    [ INFO  ] Stopping engine service
    [ INFO  ] Stopping websocket-proxy service
    [ INFO  ] Stage: Misc configuration
    [ INFO  ] Stage: Package installation
    [ INFO  ] Stage: Misc configuration
    [ INFO  ] Backing up PKI configuration and keys
    [ INFO  ] Backing up database localhost:engine to '/var/lib/ovirt-engine/backups/engine-20170520122832.Mtf_w7.dump'.
    [ INFO  ] Clearing Engine database engine
    [ INFO  ] Removing files
    [ INFO  ] Reverting changes to files
    [ INFO  ] Stage: Transaction commit
    [ INFO  ] Stage: Closing up
             
              --== SUMMARY ==--
             
              A backup of the Engine database is available at /var/lib/ovirt-engine/backups/engine-20170520122832.Mtf_w7.dump
              A backup of PKI configuration and keys is available at /var/lib/ovirt-engine/backups/engine-pki-20170520122832PJgsGW.tar.gz
              Engine setup successfully cleaned up
             
              --== END OF SUMMARY ==--
             
    [ INFO  ] Stage: Clean up
              Log file is located at /var/log/ovirt-engine/setup/ovirt-engine-remove-20170520122814-wughvt.log
    [ INFO  ] Generating answer file '/var/lib/ovirt-engine/setup/answers/20170520122845-cleanup.conf'
    [ INFO  ] Stage: Pre-termination
    [ INFO  ] Stage: Termination
    [ INFO  ] Execution of cleanup completed successfully
    
    • 停止 engine 服务。/usr/share/ovirt-engine/setup/plugins/ovirt-engine-common/base/core/engine.py
     def _transactionBegin(self):
            if self.services.exists(name=osetupcons.Const.ENGINE_SERVICE_NAME):
                self.logger.info(_('Stopping engine service'))
                self.services.state(
                    name=osetupcons.Const.ENGINE_SERVICE_NAME,
                    state=False
                )
    
    • 停止 websocket-proxy 服务。/usr/share/ovirt-engine/setup/plugins/ovirt-engine-common/websocket_proxy/core.py
    def _transactionBegin(self):
            if self.services.exists(
                name=osetupcons.Const.WEBSOCKET_PROXY_SERVICE_NAME,
            ):
                self.logger.info(_('Stopping websocket-proxy service'))
                self.services.state(
                    name=osetupcons.Const.WEBSOCKET_PROXY_SERVICE_NAME,
                    state=False
                )
    
    • 使用 otopi 安装 ovirt-engine-commonovirt-engine-remove 插件,使用插件功能执行下面步骤。
    • 备份 PKI 配置文件。
    def _misc(self):
            self.logger.info(
                _('Backing up PKI configuration and keys')
            )
            fd, self._bkpfile = tempfile.mkstemp(
                prefix=(
                    'engine-pki-%s' %
                    datetime.datetime.now().strftime('%Y%m%d%H%M%S')
                ),
                suffix='.tar.gz',
                dir=osetupcons.FileLocations.OVIRT_ENGINE_DB_BACKUP_DIR,
            )
            os.fchown(
                fd,
                osetuputil.getUid(
                    self.environment[osetupcons.SystemEnv.USER_ROOT]
                ),
                -1
            )
            os.fchmod(fd, 0o600)
            with os.fdopen(fd, 'wb') as fileobj:
                # fileobj is not closed, when TarFile is closed
                # cannot use with tarfile.open() <python-2.7
                tar = None
                try:
                    tar = tarfile.open(
                        mode='w:gz',
                        fileobj=fileobj
                    )
                    for n in (
                        osetupcons.FileLocations.OVIRT_ENGINE_SERVICE_CONFIG_PKI,
                        osetupcons.FileLocations.OVIRT_ENGINE_PKIDIR,
                    ):
                        if os.path.exists(n):
                            tar.add(n)
                finally:
                    if tar is not None:
                        tar.close()
    
    • 备份 数据库/usr/share/ovirt-engine/setup/ovirt_engine_setup/database.py
    def backup(
            self,
            dir,
            prefix,
        ):
            fd, backupFile = tempfile.mkstemp(
                prefix='%s-%s.' % (
                    prefix,
                    datetime.datetime.now().strftime('%Y%m%d%H%M%S')
                ),
                suffix='.dump',
                dir=dir,
            )
            os.close(fd)
    
            self.logger.info(
                _("Backing up database {host}:{database} to '{file}'.").format(
                    host=self.environment[self._dbenvkeys['host']],
                    database=self.environment[self._dbenvkeys['database']],
                    file=backupFile,
                )
            )
            self._plugin.execute(
                (
                    self.command.get('pg_dump'),
                    '-E', 'UTF8',
                    '--disable-dollar-quoting',
                    '--disable-triggers',
                    '--format=c',
                    '-U', self.environment[self._dbenvkeys['user']],
                    '-h', self.environment[self._dbenvkeys['host']],
                    '-p', str(self.environment[self._dbenvkeys['port']]),
                    '-f', backupFile,
                    self.environment[self._dbenvkeys['database']],
                ),
                envAppend={
                    'PGPASSWORD': '',
                    'PGPASSFILE': self.environment[self._dbenvkeys['pgpassfile']],
                },
            )
    
            return backupFile
    

    备份数据使用的是 pg_dump 命令

    • 删除数据库。/usr/share/ovirt-engine/setup/plugins/ovirt-engine-remove/ovirt-engine/db/clear.py
    def _misc(self):
    
            try:
                dbovirtutils = database.OvirtUtils(
                    plugin=self,
                    dbenvkeys=osetupcons.Const.ENGINE_DB_ENV_KEYS,
                )
                dbovirtutils.tryDatabaseConnect()
                self._bkpfile = dbovirtutils.backup(
                    dir=osetupcons.FileLocations.OVIRT_ENGINE_DB_BACKUP_DIR,
                    prefix=osetupcons.Const.ENGINE_DB_BACKUP_PREFIX,
                )
                self.logger.info(
                    _('Clearing Engine database {database}').format(
                        database=self.environment[osetupcons.DBEnv.DATABASE],
                    )
                )
                dbovirtutils.clearDatabase()
    ......
    

    调用了 /usr/share/ovirt-engine/setup/ovirt_engine_setup/database.pyclearDatabase 方法。

    def clearDatabase(self):
    
            self.createLanguage('plpgsql')
    
            statement = Statement(
                environment=self.environment,
                dbenvkeys=self._dbenvkeys,
            )
    
            statement.execute(
                statement="""
                    create or replace
                    function
                        oesetup_generate_drop_all_syntax()
                        returns setof text
                    AS $procedure$ begin
                        return query
                            select
                                'drop function if exists ' ||
                                ns.nspname ||
                                '.' ||
                                proname ||
                                '(' ||
                                    oidvectortypes(proargtypes) ||
                                ') cascade;'
                            from
                                pg_proc inner join pg_namespace ns on (
                                    pg_proc.pronamespace=ns.oid
                                )
                            where
                                ns.nspname = 'public'
                            union
    ......
    

    实际执行了一系列 drop 命令。

    • 删除文件 /usr/share/ovirt-engine/setup/plugins/ovirt-engine-remove/ovirt-engine/files/simple.py
    def _misc(self):
            self.logger.info(_('Removing files'))
            for f in self._toremove:
                if os.path.exists(f):
                    if self._digestFile(f) != self._files[f]:
                        self.logger.warning(
                            _(
                                "Preserving '{file}' as changed since installation"
                            ).format(
                                file=f,
                            )
                        )
                    else:
                        self._safeDelete(f)
    
                elif os.path.islink(f):
                    # dead link
                    self._safeDelete(f)
    
            self.logger.info(_('Reverting changes to files'))
            for f in self._tomodifylines:
                if os.path.exists(f):
                    self._revertChanges(f, self._lines[f])
                    
                    
            for info in self._infos:
                self._safeDelete(info)
    ......
    
    self._infos = sorted(
                glob.glob(
                    os.path.join(
                        osetupcons.FileLocations.OVIRT_ENGINE_UNINSTALL_DIR,
                        '*.conf',
                    )
                )
            )
    ......
    

    实际删除的文件:

    OVESETUP_REMOVE/filesToRemove=set:'set(['/etc/httpd/conf.d/ovirt-engine-root-redirect.conf', '/etc/pki/ovirt-engine/cacert.conf', '/var/lib/exports/iso-20170521063135/8c87de5d-b0f5-4ac2-ae42-5725a7977bc9/images/11111111-1111-1111-1111-111111111111/.keep', '/var/lib/exports/iso-20170521063135/8c87de5d-b0f5-4ac2-ae42-5725a7977bc9/dom_md/ids', '/etc/ovirt-engine/notifier/notifier.conf.d/10-setup-jboss.conf', '/var/lib/exports/iso-20170521063135/8c87de5d-b0f5-4ac2-ae42-5725a7977bc9/images/11111111-1111-1111-1111-111111111111/virtio-win_x86.vfd', '/etc/ovirt-engine/ovirt-websocket-proxy.conf.d/10-setup.conf', '/etc/pki/ovirt-engine/.truststore', '/etc/pki/ovirt-engine/cert.template', '/etc/pki/ovirt-engine/keys/apache.p12', '/etc/pki/ovirt-engine/keys/engine_id_rsa', '/var/lib/exports/iso-20170521063135/8c87de5d-b0f5-4ac2-ae42-5725a7977bc9/dom_md/inbox', '/etc/ovirt-engine/imageuploader.conf.d/10-engine-setup.conf', '/etc/pki/ovirt-engine/cert.conf', '/etc/ovirt-engine/engine.conf.d/10-setup-pki.conf', '/etc/ovirt-engine/engine.conf.d/10-setup-protocols.conf', '/etc/pki/ovirt-engine/certs/websocket-proxy.cer', '/etc/httpd/conf.d/z-ovirt-engine-proxy.conf', '/var/lib/exports/iso-20170521063135/8c87de5d-b0f5-4ac2-ae42-5725a7977bc9/images/11111111-1111-1111-1111-111111111111/virtio-win_amd64.vfd', '/etc/ovirt-engine/isouploader.conf.d/10-engine-setup.conf', '/etc/pki/ovirt-engine/keys/engine.p12', '/etc/pki/ovirt-engine/certs/apache.cer', '/etc/ovirt-engine/iptables.example', '/var/lib/exports/iso-20170521063135/8c87de5d-b0f5-4ac2-ae42-5725a7977bc9/dom_md/outbox', '/etc/pki/ovirt-engine/certs/engine.cer', '/etc/pki/ovirt-engine/keys/websocket-proxy.key.nopass', '/etc/pki/ovirt-engine/keys/apache.key.nopass', '/var/lib/exports/iso-20170521063135/8c87de5d-b0f5-4ac2-ae42-5725a7977bc9/images/11111111-1111-1111-1111-111111111111/sdcos-tools-setup.iso', '/etc/pki/ovirt-engine/keys/jboss.p12', '/etc/ovirt-engine/engine.conf.d/10-setup-database.conf', '/etc/pki/ovirt-engine/keys/websocket-proxy.p12', '/etc/pki/ovirt-engine/private/ca.pem', '/etc/pki/ovirt-engine/cacert.template', '/etc/pki/ovirt-engine/apache-ca.pem', '/var/lib/exports/iso-20170521063135/8c87de5d-b0f5-4ac2-ae42-5725a7977bc9/dom_md/leases', '/var/lib/exports/iso-20170521063135/8c87de5d-b0f5-4ac2-ae42-5725a7977bc9/images/11111111-1111-1111-1111-111111111111/virtio-win.iso', '/etc/ovirt-engine-setup.conf.d/20-setup-ovirt-post.conf', '/etc/pki/ovirt-engine/ca.pem', '/etc/ovirt-engine/logcollector.conf.d/10-engine-setup.conf', '/etc/ovirt-engine/engine.conf.d/10-setup-jboss.conf', '/var/lib/exports/iso-20170521063135/8c87de5d-b0f5-4ac2-ae42-5725a7977bc9/dom_md/metadata'])'
    

    备份后的数据库文件:/var/lib/ovirt-engine/backups/engine-20170520122832.Mtf_w7.dump

    备份后的 PKI 文件:/var/lib/ovirt-engine/backups/engine-pki-20170520122832PJgsGW.tar.gz

    相关文章

      网友评论

        本文标题:【Ovirt 笔记】engine-cleanup 的实现原理

        本文链接:https://www.haomeiwen.com/subject/keamxxtx.html