最近重新看了下salt-cp实现的过程,源代码逻辑相对简单,明白了salt-cp为什么只能针对文本文件、配置文件的拷贝。现在就来看看对应的代码吧
源代码文件:
salt/cli/cp.py
class SaltCP(object): def __init__(self, opts): self.opts = opts # 读取文件内容,返回单元素字典:文件名-->文件内容 def _file_dict(self, fn_): ‘‘‘ Take a path and return the contents of the file as a string ‘‘‘ if not os.path.isfile(fn_): err = ‘The referenced file, {0} is not available.‘.format(fn_) sys.stderr.write(err + ‘\n‘) sys.exit(42) with salt.utils.fopen(fn_, ‘r‘) as fp_: data = fp_.read() return {fn_: data} # 用来迭代文件的,产生一个字典:文件名-->文件内容 def _load_files(self): ‘‘‘ Parse the files indicated in opts[‘src‘] and load them into a python object for transport ‘‘‘ files = {} for fn_ in self.opts[‘src‘]: if os.path.isfile(fn_): # 更新字典 files.update(self._file_dict(fn_)) elif os.path.isdir(fn_): print(fn_ + ‘ is a directory, only files are supported.‘) #files.update(self._recurse_dir(fn_)) # files: {‘filename1‘:content,‘filename2‘:content} return files # 调用的是salt.client.LocalClient的方法cmd,调用cp.recv函数拷贝 def run(self): ‘‘‘ Make the salt client call ‘‘‘ arg = [self._load_files(), self.opts[‘dest‘]] local = salt.client.LocalClient(self.opts[‘conf_file‘]) args = [self.opts[‘tgt‘], ‘cp.recv‘, arg, self.opts[‘timeout‘], ] selected_target_option = self.opts.get(‘selected_target_option‘, None) if selected_target_option is not None: args.append(selected_target_option) ret = local.cmd(*args) pprint.pprint(ret)
从代码可以看出,拷贝文件前,需要读取文件的内容,并以{file:data}的形式返回。
然后调用salt.client.LocalClient的cmd方法并调用cp.recv函数拷贝。
cp.recv对应代码如下:
def recv(files, dest): ‘‘‘ Used with salt-cp, pass the files dict, and the destination. This function receives small fast copy files from the master via salt-cp. It does not work via the CLI. ‘‘‘ ret = {} for path, data in files.items(): if os.path.basename(path) == os.path.basename(dest) and not os.path.isdir(dest): final = dest elif os.path.isdir(dest): final = os.path.join(dest, os.path.basename(path)) elif os.path.isdir(os.path.dirname(dest)): final = dest else: return ‘Destination unavailable‘ try: salt.utils.fopen(final, ‘w+‘).write(data) ret[final] = True except IOError: ret[final] = False return ret
我们可以直接以下面的形式调用这个api
opts = { ‘tgt‘: ‘192.168.110.132‘, # target ‘src‘: [‘file1‘,‘file2‘,] # 需要拷贝的文件路劲 ‘conf_file‘: ‘/opt/app/salt/etc/master‘, # master的配置文件 ‘dest‘: ‘/mnt‘, # 目标目录 ‘timeout‘: 5, # 过期时间 } cp = salt.cli.cp.SaltCP(opts) cp.run() # 最终调用是这样的形式 local.cmd(‘192.168.110.132‘,‘cp.recv‘,[{‘/root/data‘:content},‘/mnt‘],5)
看完之后,才知道salt-cp的实现原理这么简单,简单的只能拷贝配置文件、文本文件、小文件。对于大文件的拷贝,后面会有方法。
时间: 2024-10-01 06:49:11