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

【Ovirt 笔记】ovirt-engine 服务的实现原理

作者: 58bc06151329 | 来源:发表于2017-07-10 14:19 被阅读26次

    文前说明

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

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

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

    命令使用方式:Usage: /etc/init.d/ovirt-engine {start|stop|status|restart}

    if __name__ == '__main__':
    service.setupLogger()
    d = Daemon()
    d.run()
    

    根据参数打开系统日志

    logger = logging.getLogger('ovirt')
    logger.propagate = False
    if os.environ.get('OVIRT_SERVICE_DEBUG', '0') != '0':
        logger.setLevel(logging.DEBUG)
    else:
        logger.setLevel(logging.INFO)
    

    启动守护进程

    usage=_('usage: %prog [options] start'),
    
    def _daemon(self):
    
        self.logger.debug('daemon entry pid=%s', os.getpid())
        self.logger.debug('background=%s', self._options.background)
    
        os.umask(0o022)
    
        self.daemonSetup()
    
        self._daemonReady()
    ......
    
    • 设置启动参数
    ......
    parser.add_option(
        '-d', '--debug',
        dest='debug',
        action='store_true',
        default=False,
        help=_('debug mode'),
    )
    parser.add_option(
        '--pidfile',
        dest='pidfile',
        default=None,
        metavar=_('FILE'),
        help=_('pid file to use'),
    )
    parser.add_option(
        '--background',
        dest='background',
        action='store_true',
        default=False,
        help=_('Go into the background'),
    )
    parser.add_option(
        '--systemd',
        dest='systemd',
        default='simple',
        choices=['simple', 'notify'],
        help=_('Systemd type simple|notify'),
    )
    parser.add_option(
        '--redirect-output',
        dest='redirectOutput',
        action='store_true',
        default=False,
        help=_('Redirect output of daemon'),
    )
    ......
    
    • 整个服务启动的过程,就是 JBOSS 模块加载的过程
    self._executable = os.path.join(
        java.Java().getJavaHome(),
        'bin',
        'java',
    )
    
    jbossModulesJar = os.path.join(
        self._config.get('JBOSS_HOME'),
        'jboss-modules.jar',
    )
    
    • 加载参数检测
    self._checkInstallation(
        pidfile=self.pidfile,
        jbossModulesJar=jbossModulesJar,
    )
    
    self.check(
        name=self._config.get('JBOSS_HOME'),
        directory=True,
    )
    self.check(
        name=jbossModulesJar,
    )
    
    # Check the required engine directories and files:
    self.check(
        os.path.join(
            self._config.get('ENGINE_USR'),
            'services',
        ),
        directory=True,
    )
    self.check(
        self._config.get('ENGINE_CACHE'),
        directory=True,
        writable=True,
    )
    self.check(
        self._config.get('ENGINE_TMP'),
        directory=True,
        writable=True,
        mustExist=False,
    )
    self.check(
        self._config.get('ENGINE_LOG'),
        directory=True,
        writable=True,
    )
    self.check(
        name=os.path.join(
            self._config.get("ENGINE_LOG"),
            'host-deploy',
        ),
        directory=True,
        writable=True,
    )
    for log in ('engine.log', 'console.log', 'server.log'):
        self.check(
            name=os.path.join(self._config.get("ENGINE_LOG"), log),
            mustExist=False,
            writable=True,
        )
    if pidfile is not None:
        self.check(
            name=pidfile,
            writable=True,
            mustExist=False,
        )
    

    日志根据不同的需求,配置不同的日志文件:engine.logconsole.logserver.log

    • 创建运行所需的目录,设置 700 权限
    self._tempDir = service.TempDir(self._config.get('ENGINE_TMP'))
    self._tempDir.create()
    
    self._jbossRuntime = service.TempDir(self._config.get('JBOSS_RUNTIME'))
    self._jbossRuntime.create()
    
    self._setupEngineApps()
    
    jbossTempDir = os.path.join(
        self._jbossRuntime.directory,
        'tmp',
    )
    
    jbossConfigDir = os.path.join(
        self._jbossRuntime.directory,
        'config',
    )
    
    javaModulePath = self._linkModules(
        os.path.join(
            self._jbossRuntime.directory,
            'modules',
        ),
        '%s:%s' % (
            self._config.get('ENGINE_JAVA_MODULEPATH'),
            os.path.join(
                self._config.get('JBOSS_HOME'),
                'modules',
            ),
        ),
    )
    
    os.mkdir(jbossTempDir)
    os.mkdir(jbossConfigDir)
    os.chmod(jbossConfigDir, 0o700)
    
    • 创建 jboss_runtime 目录,包含 tmpconfigmodules 子目录
    cd /var/lib/ovirt-engine/jboss_runtime
    [root@localhost jboss_runtime]# ll
    total 16
    drwx------. 3 ovirt ovirt 4096 Jul  3 12:04 config
    drwxr-xr-x. 2 ovirt ovirt 4096 Jul  3 12:04 deployments
    drwxr-xr-x. 4 ovirt ovirt 4096 Jul  3 12:03 modules
    drwxr-xr-x. 5 ovirt ovirt 4096 Jul  3 12:03 tmp
    
    • 根据模板生成配置文件,设置 600 权限
    jbossBootLoggingFile = self._processTemplate(
        template=os.path.join(
            os.path.dirname(sys.argv[0]),
            'ovirt-engine-logging.properties.in'
        ),
        dir=jbossConfigDir,
    )
    
    jbossConfigFile = self._processTemplate(
        template=os.path.join(
            os.path.dirname(sys.argv[0]),
            'ovirt-engine.xml.in',
        ),
        dir=jbossConfigDir,
        mode=0o600,
    )
    
    • 设置模块启动参数信息
    self._engineArgs.extend([
        # The name or the process, as displayed by ps:
        'ovirt-engine',
    
        # Virtual machine options:
        '-server',
        '-XX:+TieredCompilation',
        '-Xms%s' % self._config.get('ENGINE_HEAP_MIN'),
        '-Xmx%s' % self._config.get('ENGINE_HEAP_MAX'),
        '-XX:PermSize=%s' % self._config.get('ENGINE_PERM_MIN'),
        '-XX:MaxPermSize=%s' % self._config.get(
            'ENGINE_PERM_MAX'
        ),
        '-Djava.net.preferIPv4Stack=true',
        '-Dsun.rmi.dgc.client.gcInterval=3600000',
        '-Dsun.rmi.dgc.server.gcInterval=3600000',
        '-Djava.awt.headless=true',
    ])
    
    # Add extra system properties provided in the configuration:
    for engineProperty in shlex.split(
        self._config.get('ENGINE_PROPERTIES')
    ):
        if not engineProperty.startswith('-D'):
            engineProperty = '-D' + engineProperty
        self._engineArgs.append(engineProperty)
    
    # Add extra jvm arguments provided in the configuration:
    for arg in shlex.split(self._config.get('ENGINE_JVM_ARGS')):
        self._engineArgs.append(arg)
    
    # Add arguments for remote debugging of the java virtual machine:
    engineDebugAddress = self._config.get('ENGINE_DEBUG_ADDRESS')
    if engineDebugAddress:
        self._engineArgs.append(
            (
                '-Xrunjdwp:transport=dt_socket,address=%s,'
                'server=y,suspend=n'
            ) % (
                engineDebugAddress
            )
        )
    
    # Enable verbose garbage collection if required:
    if self._config.getboolean('ENGINE_VERBOSE_GC'):
        self._engineArgs.extend([
            '-verbose:gc',
            '-XX:+PrintGCTimeStamps',
            '-XX:+PrintGCDetails',
        ])
    
    # Add arguments for JBoss:
    self._engineArgs.extend([
        '-Djava.util.logging.manager=org.jboss.logmanager',
        '-Dlogging.configuration=file://%s' % jbossBootLoggingFile,
        '-Dorg.jboss.resolver.warning=true',
        '-Djboss.modules.system.pkgs=org.jboss.byteman',
        '-Djboss.modules.write-indexes=false',
        '-Djboss.server.default.config=ovirt-engine',
        '-Djboss.home.dir=%s' % self._config.get(
            'JBOSS_HOME'
        ),
        '-Djboss.server.base.dir=%s' % self._config.get(
            'ENGINE_USR'
        ),
        '-Djboss.server.data.dir=%s' % self._config.get(
            'ENGINE_VAR'
        ),
        '-Djboss.server.log.dir=%s' % self._config.get(
            'ENGINE_LOG'
        ),
        '-Djboss.server.config.dir=%s' % jbossConfigDir,
        '-Djboss.server.temp.dir=%s' % jbossTempDir,
        '-Djboss.controller.temp.dir=%s' % jbossTempDir,
        '-jar', jbossModulesJar,
        '-mp', javaModulePath,
        '-jaxpmodule', 'javax.xml.jaxp-provider',
        'org.jboss.as.standalone',
        '-c', os.path.basename(jbossConfigFile),
    ])
    
    • 创建 JBOSS 启动发布模块目录
    deploymentsDir = os.path.join(
        self._jbossRuntime.directory,
        'deployments',
    )
    os.mkdir(deploymentsDir)
    
    • 与项目中的发布模块映射为链接
    for engineAppDir in shlex.split(self._config.get('ENGINE_APPS')+ " " + self._config.get('TERMINAL_APPS')):
    self.logger.debug('Deploying: %s', engineAppDir)
    if not os.path.isabs(engineAppDir):
        engineAppDir = os.path.join(
            self._config.get('ENGINE_USR'),
            engineAppDir,
        )
    if not os.path.exists(engineAppDir):
        self.logger.warning(
            _(
                "Application directory '{directory}' "
                "does not exist, it will be ignored"
            ).format(
                directory=engineAppDir,
            ),
        )
        continue
    
    engineAppLink = os.path.join(
        deploymentsDir,
        os.path.basename(engineAppDir),
    )
    os.symlink(engineAppDir, engineAppLink)
    with open('%s.dodeploy' % engineAppLink, 'w'):
        pass
    
    [root@localhost deployments]# pwd
    /var/lib/ovirt-engine/jboss_runtime/deployments
    [root@localhost deployments]# ll
    total 16
    lrwxrwxrwx. 1 ovirt ovirt 34 Jul  3 12:03 engine.ear -> /usr/share/ovirt-engine/engine.ear
    -rw-r--r--. 1 ovirt ovirt 10 Jul  3 11:30 engine.ear.deployed
    lrwxrwxrwx. 1 ovirt ovirt 54 Jul  3 12:03 ovirt-engine-reports.war -> /var/lib/ovirt-engine-reports/ovirt-engine-reports.war
    -rw-r--r--. 1 ovirt ovirt 24 Jul  3 12:03 ovirt-engine-reports.war.deployed
    lrwxrwxrwx. 1 ovirt ovirt 67 Jul  3 12:03 rhev.ear -> /usr/share/ovirt-engine/branding/rhev-1.brand/applications/rhev.ear
    -rw-r--r--. 1 ovirt ovirt  8 Jun 19 08:00 rhev.ear.deployed
    
    • 创建 modules 目录,将运行 JBOSS 模块的依赖建立链接关系
    def _linkModules(self, directory, modulePath):
        """
        Link all the JBoss modules into a temporary directory.
        This required because jboss tries to automatically update
        indexes based on timestamp even if there is no permission to do so.
        """
    
        modifiedModulePath = []
        for index, element in enumerate(modulePath.split(':')):
            modulesTmpDir = os.path.join(
                directory,
                '%02d-%s' % (
                    index,
                    '-'.join(element.split(os.sep)[-2:]),
                ),
            )
            modifiedModulePath.append(modulesTmpDir)
    
            # For each directory in the modules directory create the
            # same in the temporary directory and populate with symlinks
            # pointing to the original files (excluding indexes):
            for parentDir, childrenDirs, childrenFiles in os.walk(element):
                parentTmpDir = os.path.join(
                    modulesTmpDir,
                    os.path.relpath(
                        parentDir,
                        element
                    ),
                )
                if not os.path.exists(parentTmpDir):
                    os.makedirs(parentTmpDir)
                for childFile in childrenFiles:
                    if childFile.endswith('.index'):
                        continue
                    os.symlink(
                        os.path.join(parentDir, childFile),
                        os.path.join(parentTmpDir, childFile)
                    )
    
        return ':'.join(modifiedModulePath)
    
    [root@localhost main]# pwd
    /var/lib/ovirt-engine/jboss_runtime/modules/00-ovirt-engine-modules/com/mchange/c3p0/main
    [root@localhost main]# ll
    total 8
    lrwxrwxrwx. 1 ovirt ovirt 62 Jul  3 12:03 c3p0.jar -> /usr/share/ovirt-engine/modules/com/mchange/c3p0/main/c3p0.jar
    lrwxrwxrwx. 1 ovirt ovirt 64 Jul  3 12:03 module.xml -> /usr/share/ovirt-engine/modules/com/mchange/c3p0/main/module.xml
    

    相关文章

      网友评论

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

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