from flask import Blueprint, request from apps.assets.models import Host, HostExtend from apps.deploy.models import AppHostRel from libs.tools import json_response, JsonParser, Argument from apps.setting import utils, Setting from libs import ssh from libs.utils import DockerClient, DockerException import math from public import db from libs.decorators import require_permission from apps.assets.utils import excel_parse blueprint = Blueprint(__name__, __name__) @blueprint.route('/', methods=['GET']) @require_permission('assets_host_view | publish_app_publish_host_select | ' 'job_task_add | job_task_edit | assets_host_exec') def get(): form, error = JsonParser(Argument('page', type=int, default=1, required=False), Argument('pagesize', type=int, default=10, required=False), Argument('host_query', type=dict, required=False), ).parse(request.args) if error is None: print('host_ng', form) host_data = Host.query if form.page == -1: return json_response({'data': [x.to_json() for x in host_data.all()], 'total': -1}) if form.host_query.get('name_field'): host_data = host_data.filter(Host.name.like('%{}%'.format(form.host_query['name_field']))) if form.host_query.get('zone_field'): host_data = host_data.filter_by(zone=form.host_query['zone_field']) result = host_data.limit(form.pagesize).offset((form.page - 1) * form.pagesize).all() return json_response({'data': [x.to_json() for x in result], 'total': host_data.count()}) return json_response(message=error) @blueprint.route('/', methods=['POST']) @require_permission('assets_host_add') def post(): form, error = JsonParser('name', 'type', 'zone', 'docker_uri', 'ssh_ip', 'ssh_port', Argument('desc', nullable=True, required=False)).parse() if error is None: host = Host(**form) host.save() return json_response(host) return json_response(message=error) @blueprint.route('/', methods=['DELETE']) @require_permission('assets_host_del') def delete(host_id): host = Host.query.get_or_404(host_id) if AppHostRel.query.filter_by(host_id=host_id).first(): return json_response(message='请先取消与应用的关联后,再尝试删除该主机。') host.delete() return json_response() @blueprint.route('/', methods=['PUT']) @require_permission('assets_host_edit') def put(host_id): form, error = JsonParser('name', 'type', 'zone', 'docker_uri', 'ssh_ip', 'ssh_port', Argument('desc', nullable=True, required=False)).parse() if error is None: host = Host.query.get_or_404(host_id) host.update(**form) return json_response(host) return json_response(message=error) @blueprint.route('//valid', methods=['GET']) @require_permission('assets_host_valid') def get_valid(host_id): cli = Host.query.get_or_404(host_id) if not Setting.has('ssh_private_key'): utils.generate_and_save_ssh_key() if ssh.ssh_ping(cli.ssh_ip, cli.ssh_port): try: sync_host_info(host_id, cli.docker_uri) except DockerException: return json_response(message='docker fail') else: return json_response(message='ssh fail') return json_response() @blueprint.route('//valid', methods=['POST']) @require_permission('assets_host_valid') def post_valid(host_id): form, error = JsonParser(Argument('secret', help='请输入root用户的密码!')).parse() if error is None: cli = Host.query.get_or_404(host_id) ssh.add_public_key(cli.ssh_ip, cli.ssh_port, form.secret) if ssh.ssh_ping(cli.ssh_ip, cli.ssh_port): try: sync_host_info(host_id, cli.docker_uri) except DockerException: return json_response(message='获取扩展信息失败,请检查docker是否可以正常连接!') else: return json_response(message='验证失败!') return json_response(message=error) @blueprint.route('//extend/', methods=['GET']) @require_permission('assets_host_valid') def get_extend(host_id): host_extend = HostExtend.query.filter_by(host_id=host_id).first() return json_response(host_extend) @blueprint.route('/zone/', methods=['GET']) @require_permission('assets_host_valid | assets_host_exec') def fetch_groups(): zones = db.session.query(Host.zone.distinct().label('zone')).all() return json_response([x.zone for x in zones]) @blueprint.route('/import', methods=['POST']) @require_permission('assets_host_add') def host_import(): data = excel_parse() if data: index_map = {key: index for index, key in enumerate(data.keys())} for row in zip(*data.values()): print(row) Host( name=row[index_map['主机名称']], desc=row[index_map['备注信息']], type=row[index_map['主机类型']], zone=row[index_map['所属区域']], docker_uri=row[index_map['Docker连接地址']], ssh_ip=row[index_map['SSH连接地址']], ssh_port=row[index_map['SSH端口']], ).add() db.session.commit() return json_response(data='导入成功') def sync_host_info(host_id, uri): host_info = DockerClient(base_url=uri).docker_info() operate_system = host_info.get('OperatingSystem') memory = math.ceil(int(host_info.get('MemTotal'))/1024/1024/1024) cpu = host_info.get('NCPU') # outer_ip = 1 # inner_ip = 2 HostExtend.upsert({'host_id': host_id}, host_id=host_id, operate_system=operate_system, memory=memory, cpu=cpu) return True