在ceph-deploy 中使用remoto 这个第三方库来访问远程host.这个库的源码的路径为https://github.com/alfredodeza/remoto
例如在E:\ceph-deploy-master\ceph-deploy-master\ceph_deploy\hosts\common.py 中
def ceph_version(conn):
"""
Log the remote ceph-version by calling `ceph --version`
"""
return remoto.process.run(conn, ['ceph', '--version'])
通过remoto.process.run在远程host 上运行ceph --version
其源码分析如下:
路径为https://github.com/alfredodeza/remoto/blob/222014a3da8bb77cb462bace3a6c0e7200e5ea08/remoto/process.py
def run(conn, command, exit=False, timeout=None, **kw):
"""
A real-time-logging implementation of a remote subprocess.Popen call where
a command is just executed on the remote end and no other handling is done.
:param conn: A connection oject
:param command: The command to pass in to the remote subprocess.Popen
:param exit: If this call should close the connection at the end
:param timeout: How many seconds to wait after no remote data is received
(defaults to wait for ever)
"""
stop_on_error = kw.pop('stop_on_error', True)
if not kw.get('env'):
# get the remote environment's env so we can explicitly add
# the path without wiping out everything
kw = extend_path(conn, kw)
timeout = timeout or conn.global_timeout
conn.logger.info('Running command: %s' % ' '.join(admin_command(conn.sudo, command)))
result = conn.execute(_remote_run, cmd=command, **kw)
可见这里调用_remote_run,
def _remote_run(channel, cmd, **kw):
import subprocess
import sys
from select import select
stop_on_nonzero = kw.pop('stop_on_nonzero', True)
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True,
**kw
)
原来最后还是调用subprocess 这个第三方库来运行命令,可见remoto 只是subprocess的一个包装
第二个ceph-deploy的例子
def mon_create(distro, args, monitor_keyring):
hostname = distro.conn.remote_module.shortname()
这里的remote_module定义如下:
路径为https://github.com/alfredodeza/remoto/blob/1e4fbd0f1af5e68ef0d824dd8b93139c3b86aa05/remoto/connection.py
class Connection(object):
def __init__(self, hostname, logger=None, sudo=False, threads=1, eager=True,
detect_sudo=False, interpreter=None):
self.sudo = sudo
self.hostname = hostname
self.logger = logger or FakeRemoteLogger()
self.remote_module = None
self.channel = None
self.global_timeout = None # wait for ever
self.interpreter = interpreter or 'python%s' % sys.version_info[0]
def _make_gateway(self, hostname):
gateway = execnet.makegateway(
self._make_connection_string(hostname)
)
def import_module(self, module):
self.remote_module = ModuleExecute(self.gateway, module, self.logger)
return self.remote_module
ModuleExecute 是一个类,定义如下:
class ModuleExecute(object):
def __init__(self, gateway, module, logger=None):
self.channel = gateway.remote_exec(module)
self.module = module
self.logger = logger
所以ceph-depoly中的remote_module.shortname()其实调用的gateway中的shortname()。而gateway的赋值如下:
def _make_gateway(self, hostname):
gateway = execnet.makegateway(
self._make_connection_string(hostname)
)
可见是通过execnet 这个第三方库完成的。这里就是调用python解释器去执行_make_connection_string产生的命令
execnet的介绍为http://codespeak.net/execnet/
execnet provides a share-nothing model with channel-send/receive communication for distributing execution across many Python interpreters across version, platform and network barriers. It has a minimal and fast API targetting the following uses:
distribute tasks to (many) local or remote CPUs
write and deploy hybrid multi-process applications
write scripts to administer multiple environments
ceph-deploy 中使用remoto
最新推荐文章于 2023-01-30 15:24:49 发布