最近從新看了下salt-cp實現的過程,源代碼邏輯相對簡單,明白了salt-cp爲何只能針對文本文件、配置文件的拷貝。如今就來看看對應的代碼吧
python
源代碼文件:api
salt/cli/cp.pyapp
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}的形式返回。
ide
而後調用salt.client.LocalClient的cmd方法並調用cp.recv函數拷貝。函數
cp.recv對應代碼以下:spa
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
orm
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的實現原理這麼簡單,簡單的只能拷貝配置文件、文本文件、小文件。對於大文件的拷貝,後面會有方法。
blog