def fetch_machine():
    '''
    step 1: 检查Unaccepted Keys,展现给用户
    step 2: 检查Accepted Keys 和数据库存放的机器 是否一致,Accepted Keys中有 且 数据库中没有的机器
    step 3: 检查数据库中cluster字段是个空的机器
    '''
    context = {"Unaccepted":None,"accepted":None,"machine":None}

    try:
        #salt-key命令
        line = os.popen("salt-key -L").read()

        #查找所有Unaccepted Keys
        mac = re.findall(r"(?<=Unaccepted Keys:)([\s\S]*?)(?=Rejected Keys:)",line)
        if len(mac):
            machine_list = mac[0].split("\n")
            context["Unaccepted"] = machine_list

        #查找所有Accepted Keys, 并与数据库中数据做对比
        mac = re.findall(r"(?<=Accepted Keys:)([\s\S]*?)(?=Unaccepted Keys:)",line)
        if len(mac):
            accept_ma_list = mac[0].split("\n")


        accept_ma_info = __fetch_machine_info(accept_ma_list)

        #需要一个IP对target的映射
        _ip_target = {}
        for _target,_ip in accept_ma_info.items():
            if "IP" in _ip and not _ip["IP"] == "":
                _ip_target[_ip["IP"]] = _target

        accept_ma_ip   = map(lambda x: x["IP"] if "IP" in x else "",accept_ma_info.values())
        accept_ma_ip = set(accept_ma_ip)


        #查看salt-key所有机器是否在数据库中
        exist_ma = machine.objects.filter(IP__in=accept_ma_ip).values("IP")
        exist_ma = map(lambda x: x["IP"] if "IP" in x else "",exist_ma)
        exist_ma = set(exist_ma)

        #查看哪些机器在salt-key中出现,但是么有在数据库中出现的
        extra = accept_ma_ip - exist_ma

        extra = list(extra)
        #IP和target的对应关系也传过去
        _extra = []
        for item in extra:
            if item in _ip_target:
                _extra.append([item,_ip_target[item]])

        context["accepted"] = _extra

        #查看哪些机器出现在数据库中,但是不属于任何集群
        all_machine = machine.objects.filter(cluster=None)

        context["machine"] = all_machine

    except:
        logger.error("ser_command " + traceback.format_exc())

    return context
def _add_cluster_commit(request,flag):
    new_name       =  request.POST.get("new_name",None)
    unaccept_host  =  request.POST.get("unaccept_host",None)
    ready_to_add_host =  request.POST.get("ready_to_add_host",None)
    accept_host    =  request.POST.get("accept_host",None)


    unaccept_host     = unaccept_host.split("&&")
    ready_to_add_host = ready_to_add_host.split("&&")
    accept_host       = accept_host.split("&&")

    result_status = "ok"

    try:
        if new_name == None and flag:
            raise NameError,"cluster name is null"

        add_unaccept_host_result = []

        unaccept_host_promot_ok = []

        accept_host_result = []
        ready_add_host_result = []

        if flag:
            #存cluster
            cl = cluster()
            cl.name = new_name
            cl.save()
        else:
            cl = cluster.objects.get(id=request.POST.get("id"))

        #先处理Unaccept的机器
        if not unaccept_host == None:
            import pexpect
            #先将要promot的机器 promot进来
            for item in unaccept_host:
                if item == "":
                    continue
                result = "fail"
                child=pexpect.spawn("sudo salt-key -a " + item)
                try:
                    i = child.expect(['The following keys are going to be accepted[\s\S]*'])
                    if i == 0:
                        child.sendline("Y")
                        unaccept_host_promot_ok.append(item)
                        result = "ok" 
                except:
                    traceback.print_exc()           
                finally:
                    add_unaccept_host_result.append([item,result])

            #然后录入数据库中
            ma_info = __fetch_machine_info(unaccept_host_promot_ok)
            for key,item in ma_info.items():
                if "IP" in item and not item["IP"] == "":
                    ma = machine()
                    ma.IP = item["IP"]
                    ma.hostname = item["host"] if "host" in item else ""
                    ma.status = 1
                    ma.cluster = cl.id
                    ma.target = key
                    ma.save()


        #然后处理accept中有,但是数据库中没有的机器
        for item in accept_host:
            try:
                if item == "":
                    continue
                item,target = item.split("_")
                new_machine = machine()
                new_machine.IP = item
                new_machine.cluster = cl.id
                new_machine.target = target
                new_machine.save()
                accept_host_result.append({"host":item,"result":"ok"})
            except:
                logger.error(traceback.format_exc())
                accept_host_result.append({"host":item,"result":"fail"})


        #然后处理ready_to_add_host的机器
        for item in ready_to_add_host:
            try:
                if item == "":
                    continue
                exist_machine = machine.objects.get(IP=item)
                exist_machine.cluster = cl.id
                exist_machine.save()
                ready_add_host_result.append({"host":item,"result":"ok"})
            except:
                logger.error(traceback.format_exc())
                ready_add_host_result.append({"host":item,"result":"fail"})


    except:
        logger.error(traceback.format_exc())
        result_status = "fail"
        #这里要加 log的逻辑

    try:
        context = {"status":result_status,
                    "add_unaccept_host_result":add_unaccept_host_result,
                    "accept_host_result":accept_host_result,
                    "ready_add_host_result":ready_add_host_result}
    except:
        logger.error("ser_command " + traceback.format_exc())

    return context