就是为了批量安装软件方便一点,使用方法
if __name__ == "__main__":
options, args = opt()
if len(args) == 0:
parser.print_help()
sys.exit(1)
for project in args:
try:
# 加载项目
mod = __import__('deploy.%s' % project, fromlist=True)
servers = Projects.info(project)
# 定义一个部署线程列表
deploy_list = []
for server in servers:
deploy = mod.Setup(hostname=server[0], username=server[1], password=server[2],
port=server[3], args=args, kwargs=options)
deploy_list.append(deploy)
# 启用多线程部署
for deploy in deploy_list:
deploy.start()
# 判断线程里面是否还有没结束的
for deploy in deploy_list:
while deploy.is_alive():
time.sleep(1)
except ModuleNotFoundError:
print("没有此项目部署方式")
break
class RoleRun(threading.Thread):
logger = LogUtil().getLogger(__name__)
def __init__(self, hostname=None, username=None, password=None, port=22, **kwargs):
threading.Thread.__init__(self)
self.c = Connection(host=hostname, user=username, connect_kwargs={'password': password}, port=port)
self.cmd_list = []
# success,message,curr组成了可以进度条展示的功能
self.success = None
self.message = "正在连接服务器"
self.curr = 0
self.osversion = "7"
self.logfile = "logs/deploy.log"
self.kwargs = kwargs
def local(self, cmd=None, percent=0, message=None, skip_false=False):
"""执行本地命令
:param cmd: 命令
:param percent: 命令所占的百分比
:param message: 命令含义
:param skip_false: 失败是否影响后续的执行
:return:
"""
try:
if self.success is False:
return False
res = run(cmd, warn=True, hide=True)
self.local_log(res)
if res.failed:
if skip_false is False:
self.success = False
return False
except TimeoutError:
self.success = False
self.curr = 100
self.message = "服务器超时"
return False
self.curr += percent
return True
def info(self, message):
self.logger.info(message)
def error(self, message):
self.logger.error(message)
def disable_friewalld(self):
"""禁用系统的防火墙
:return:
"""
if self.osversion == "7":
self.run_cmd("systemctl disable firewalld")
self.run_cmd("systemctl stop firewalld")
def pre_check(self):
"""预检测
:return:
"""
if self.run_cmd("cat /etc/redhat-release |awk '{print $4}'|grep 7. | wc -l"):
self.osversion = 7
def run_cmd(self, cmd=None, percent=0, message=None, skip_false=False):
"""远程执行命令
:param cmd: 命令
:param percent: 命令所占的百分比
:param message: 命令含义
:param skip_false: 失败是否影响后续的执行
:return:
"""
try:
if self.success is False:
return False
res = self.c.run(cmd, warn=True, hide=True)
self.log(res)
if res.failed:
if skip_false is False:
self.success = False
return False
except TimeoutError:
self.success = False
self.curr = 100
self.message = "服务器超时"
return False
self.curr += percent
return res.stdout
def set_process(self, message, percent=0):
"""实现百分比进度
:param message:
:param percent:
:return:
"""
self.message = message
self.curr = percent
def run(self):
""" 多线程的入口
:return:
"""
try:
self.c.open()
except TimeoutError:
self.curr = 100
self.message = "服务器链接失败"
self.success = False
return False
except AuthenticationException:
self.set_process("用户名或者密码错误", percent=100)
self.success = False
if self.c.is_connected:
pass
else:
self.success = False
return False
def get_template(self, name):
""" 返回jinja模板
:param name:
:return:
"""
env = Environment(loader=PackageLoader("deploy", "template"))
return env.get_template(name)
def set_service(self, service_name=None):
""" 设置服务,目前只支持centos7以上
:param service_name:
:return:
"""
self.message = "设置启停,开机自启"
if self.osversion == "7":
self.c.put("deploy/service/7/{0}.service".format(service_name), "/lib/systemd/system/")
self.run_cmd("systemctl daemon-reload")
self.run_cmd("systemctl enable {0}".format(service_name))
self.run_cmd("systemctl start {0}".format(service_name))
return True
def get(self):
""" 获取线程当前的状态
:return:
"""
return {"process": self.curr, "status": self.success, "message": self.message}
def upload_and_unpack_gz(self, filename=None):
"""
:param filename:
:return:
"""
self.message = "正在上传文件并解压"
try:
if self.c.run("test -f /usr/local/src/{0}".format(filename), warn=True).failed:
self.c.put('deploy/packages/{0}'.format(filename), remote='/usr/local/src/')
self.c.run('tar -zxf /usr/local/src/{0} -C /usr/local/src'.format(filename))
except FileNotFoundError as e:
self.logger.error(e)
return False
except OSError as e:
self.logger.error(e)
return True
def upload(self, local_file=None, dest_file=None):
"""上传文件
:param local_file: 本地文件路径
:param dest_file: 远程文件路径
:return:
"""
try:
self.c.put(local_file, remote=dest_file)
except FileNotFoundError as e:
self.logger.error(e)
return False
except OSError as e:
self.logger.error(e)
return True
def upload_folder(self, local_dir=None, dest_dir=None):
"""上传文件夹
:param local_dir: 本地目录路径
:param dest_dir: 远程目录路径
:return:
"""
try:
if self.c.run("mkdir -p {0}".format(dest_dir), warn=True).ok:
self.c.put(local_dir, remote='.')
except FileNotFoundError as e:
self.logger.error(e)
return False
except OSError as e:
self.logger.error(e)
return True