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

文前说明

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

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

分析整理的版本为 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@
    @[email protected]/*.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() 
  • 备份 数据库/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 的实现原理)