1 ##############################################################################
2 # Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
14 import salt.client as sclient
16 from vstf.common import cmds
18 log = logging.getLogger(__name__)
27 self.cur_path = os.path.abspath(os.path.dirname(inspect.stack()[1][1]))
28 self.salt_conf = "/etc/salt/master"
29 if not os.path.exists(self.salt_conf):
30 raise Exception("this python must be run on the salt master.")
31 self.pillar_path = str(
32 cmds.execute("grep '^pillar_roots' \
33 /etc/salt/master -A 2 | sed 1,2d | awk '{print $2}'") + '/')
34 if self.pillar_path == "":
35 log.warning("pillar path not found, make sure the pillar_roots configed")
37 os.system("mkdir -p " + self.pillar_path)
39 self.state_path = str(cmds.execute("grep '^file_roots' \
40 /etc/salt/master -A 2 | sed 1,2d | awk '{print $2}'") + '/')
41 if self.state_path == "":
42 log.warning("state path not found, make sure the file_roots configed")
44 os.system("mkdir -p " + self.state_path)
46 self.salt = sclient.LocalClient()
48 def slave_exists(self, host):
49 pslave = "/etc/salt/pki/master/minions/" + host
50 if os.path.exists(pslave):
55 def __is_dir_or_file(self, src):
56 if not os.path.exists(src):
58 if os.path.isdir(src):
60 elif os.path.isfile(src):
65 def __copy_target(self, target, flag=""):
66 if not os.path.exists(target):
67 log.error("target %(d)s not exists.", {'d': target})
71 dst = self.pillar_path
75 log.error("this file or dir not pillar or state, can not support now.")
78 if self.IS_FILE == self.__is_dir_or_file(target):
79 os.system('cp ' + target + ' ' + dst)
81 os.system("cp -r " + target + ' ' + dst)
84 def copy(self, host, src, dst):
85 """copy file or dir to slave.
87 :dst if src is a file, the dst must be like this /home/xx.py, not /home
90 '''check if the host exists on the master'''
91 if not self.slave_exists(host):
92 log.error("the host %(h)s is not held by master, please check.")
95 '''copy file to salt's file_roots'''
96 if not self.__copy_target(src, "state"):
99 if self.IS_DIR == self.__is_dir_or_file(src):
100 dir_name = os.path.basename(src)
101 self.salt.cmd(host, "cp.get_dir", ["salt://" + dir_name, dst])
102 elif self.IS_FILE == self.__is_dir_or_file(src):
103 file_name = os.path.basename(src)
104 print self.salt.cmd(host, "cp.get_file", ["salt://" + file_name, dst])
106 log.error("not file and not dir, what is it")
110 def __luxuriant_line(self, str, color):
112 return "\033[22;35;40m" + str + "\033[0m"
113 elif "green" == color:
114 return "\033[22;32;40m" + str + "\033[0m"
118 def result_check(self, ret, host):
123 for key in ret[host].keys():
124 if True == ret[host][key]['result']:
128 msg = msg + self.__luxuriant_line("Failed %d:\n" % num_f, "red")
129 msg = msg + "\t" + key + '\n'
130 msg = msg + self.__luxuriant_line("\t%s\n" % ret[host][key]['comment'], "red")
131 if True == ret[host][key]['changes'].has_key('retcode'):
132 msg = msg + "RETCODE: %s\n" % (ret[host][key]['changes']['retcode'])
133 if True == ret[host][key]['changes'].has_key('stderr'):
134 msg = msg + "STDERR: %s\n" % (ret[host][key]['changes']['stderr'])
135 if True == ret[host][key]['changes'].has_key('stdout'):
136 msg = msg + "STDOUT: %s\n" % (ret[host][key]['changes']['stdout'])
137 msg = msg + self.__luxuriant_line("total success: %d\n" % num_s, "green")
138 msg = msg + self.__luxuriant_line("failed: %d\n" % num_f, "red")
139 except Exception as e:
140 log.error("sorry, thy to check result happend error, <%(e)s>.\nret:%(ret)s",
141 {'e': e, 'ret': ret})
143 log.info(':\n' + msg)
146 def run_state(self, host, fstate, ext_pillar={}, care_result=True):
148 log.info("salt " + host + " state.sls " +
149 fstate + ' pillar=\'' + str(ext_pillar) + '\'')
150 ret = self.salt.cmd(host, 'state.sls', [fstate, 'pillar=' + str(ext_pillar)], 180, 'list')
151 except Exception as e:
152 log.error("try to init host %(host)s happend error: <%(e)s>.",
153 {'host': host, 'e': e})
154 if True == care_result:
157 if 0 != self.result_check(ret, host) and care_result:
161 def salt_cmd(self, host, cmd):
164 logging.info("Begin to run cmd %s on %s" % (host, cmd))
167 ret = self.salt.cmd(host, 'cmd.run', [cmd])
169 log.error("Remote salt execute failed.")
172 def copy_by_state(self, host, src, state_cmd, **kwargs):
173 '''the src must be a dir, and the state.sls
174 must be the name of the dir name'''
176 if not self.slave_exists(host):
177 log.error("the host %(h)s is not held by master, please check.")
180 if not self.__copy_target(src, "state"):
183 return self.run_state(host, state_cmd, kwargs, care_result=True)
185 def get_master_ip(self, host=None):
187 ret = cmds.execute("grep '^interface:' /etc/salt/master | awk '{print $2}'").strip()
190 ret = self.salt.cmd(host, "grains.item", ["master"])[host]['master']
192 log.error("salt happened error when get master ip")