def __change_drprd_status(env, ip_new):
    '''
        编辑ip表
    :param env:
    :param ip_new:
    :return:
    '''
    # 更新新ip状态
    if int(env) == DataCenterType.PRD:
        segment_dr = segment_match_s.SegmentMatchService(
        ).get_segment_match_info_by_prd_segment_id(ip_new['segment_id'])
        if not segment_dr:
            return False, "无法获取当前生产IP对应容灾网段信息"
        segment_dr_data = segment_s.SegmentService().get_segment_info(
            segment_dr['dr_segment_id'])
        if not segment_dr_data:
            return False, "无法获取当前生产IP对应容灾网段详细信息"
        # 拼凑虚拟机容灾IP
        dr_ip = segment_dr_data['segment'].split('.')[0] + '.' + segment_dr_data['segment'].split('.')[1] + \
                '.' + ip_new['ip_address'].split('.')[2] + '.' + ip_new['ip_address'].split('.')[3]
        dr_ip_info = ip_s.IPService().get_ip_by_ip_address(dr_ip)
        # 如果容灾IP是未使用中状态,可以使用
        if dr_ip_info:
            if dr_ip_info['status'] == IPStatus.UNUSED:
                # 重置对应ip为未使用
                update_dr_ip_data = {'status': IPStatus.PRE_ALLOCATION}
                where_dr_ip_data = {'id': dr_ip_info['id']}
                ret_mark_ip = ip_s.IPService().update_ip_info(
                    update_dr_ip_data, where_dr_ip_data)
                if ret_mark_ip <= 0:
                    return False, "当前生产IP对应容灾IP从预分配重置为未使用状态失败"

    elif int(env) == DataCenterType.DR:
        segment_prd = segment_match_s.SegmentMatchService(
        ).get_segment_match_info_by_dr_segment_id(ip_new['segment_id'])
        if not segment_prd:
            return False, "无法获取当前容灾IP对应生产网段信息"
        segment_prd_data = segment_s.SegmentService().get_segment_info(
            segment_prd['prd_segment_id'])
        if not segment_prd_data:
            return False, "无法获取当前容灾IP对应生产网段详细信息"
        # 拼凑虚拟机生产IP
        prd_ip = segment_prd_data['segment'].split('.')[0] + '.' + segment_prd_data['segment'].split('.')[
            1] + '.' + \
                 ip_new['ip_address'].split('.')[2] + '.' + ip_new['ip_address'].split('.')[3]
        prd_ip_info = ip_s.IPService().get_ip_by_ip_address(prd_ip)
        # 如果生产环境ip是未使用中状态,可以使用
        if prd_ip_info:
            if prd_ip_info['status'] == IPStatus.UNUSED:
                # 重置对应ip为未使用
                update_dr_ip_data = {'status': IPStatus.PRE_ALLOCATION}
                where_dr_ip_data = {'id': prd_ip_info['id']}
                ret_mark_ip = ip_s.IPService().update_ip_info(
                    update_dr_ip_data, where_dr_ip_data)
                if ret_mark_ip <= 0:
                    return False, "当前容灾IP对应生产IP从预分配重置为未使用状态失败"

    return True, "生产、容灾IP状态重置成功"
Ejemplo n.º 2
0
def add_segment():
    '''
        录入一个新网段
    '''
    network_segment_match = request.json.get("network_segment_match",[])
    segment_match_dic = {}
    for index, item in enumerate(network_segment_match):
        status, res = check_prdr(item)
        if not status:
            return json_helper.format_api_resp(ErrorCode.ALL_FAIL, msg=res)
        bond_dev = NetCardTypeToDevice.MSG_DICT.get(item['segment_type'])
        insert_data = {
            'net_area_id': int(item['net_area_id']),
            'segment': item['segment'],
            'segment_type': item['segment_type'],
            'host_bridge_name': 'br_' + bond_dev,
            'netmask': str(item['netmask']),
            'vlan': str(item['vlan']),
            'gateway_ip': item['gateway'],
            'dns1': item['dns1'],
            'dns2': item['dns2'],
            'status': NetworkSegmentStatus.ENABLE,
            'created_at': get_datetime_str()
        }
        ret = segment_service.SegmentService().add_segment_info(insert_data)
        if ret['row_num'] <= 0:
            return json_helper.format_api_resp(code=ErrorCode.ALL_FAIL, msg="网段入库失败")
        if len(network_segment_match) == 2:
            dc_type = datacenter_service.DataCenterService().get_dctype_by_net_area_id(item['net_area_id'])
            if dc_type == '4':
                segment_match_dic['prd_segment_id'] = network_segment.get_network_segment_id_info_by_network_segment(
                    item['net_area_id'], item['segment'],
                    item['vlan'], item['gateway'],
                    'br_' + bond_dev)
            elif dc_type == '5':
                segment_match_dic['dr_segment_id'] = network_segment.get_network_segment_id_info_by_network_segment(
                    item['net_area_id'], item['segment'],
                    item['vlan'], item['gateway'],
                    'br_' + bond_dev)
    if len(network_segment_match) == 2:
        insert_data_match = {
            'prd_segment_id': int(segment_match_dic['prd_segment_id']['id']),
            'dr_segment_id': int(segment_match_dic['dr_segment_id']['id']),
            'isdeleted': '0'
        }
        ret_match = segment_match.SegmentMatchService().add_segment_match_info(insert_data_match)
        if ret_match['row_num'] <= 0:
            return json_helper.format_api_resp(code=ErrorCode.ALL_FAIL, msg="匹配网段入库失败")

    return json_helper.format_api_resp(code=ErrorCode.SUCCESS, msg="匹配网段已成功加入")
Ejemplo n.º 3
0
def __check_ip_resource(env, dc_name, net_area, count):
    '''
        判断IP资源是否足够
    :param hostpool_id:
    :param count:
    :return:
    '''
    # 查询指定环境、网络区域是否有所需网段,容灾微应用需要遍历联通、电信所有可用网段
    if env == str(DataCenterType.MINIARCHDR):
        ret_segment_datas_telecom = segment_s.get_segments_data_by_type(
            net_area, dc_name, env, NetCardType.INTERNEL_TELECOM)
        ret_segment_datas_unicom = segment_s.get_segments_data_by_type(
            net_area, dc_name, env, NetCardType.INTERNEL_UNICOM)
        ret_segment_datas = ret_segment_datas_telecom + ret_segment_datas_unicom
    else:
        ret_segment_datas = segment_s.get_segments_data_by_type(
            net_area, dc_name, env, NetCardType.INTERNAL)
    if not ret_segment_datas:
        return False, '集群所在机房、网络区域下没有可用网段用于分配IP', ''

    # 获取可用ip
    ret_ip_datas, ret_ip_segment_datas = ip_service.get_available_ips(
        ret_segment_datas, int(count), env)
    if not ret_ip_datas:
        return False, '集群所在机房、网络区域下无法找到%s个可用IP' % str(count), ''

    # 如果是申请生产或者容灾环境ip,需判断网段对应关系表中是否有记录
    if int(env) == DataCenterType.PRD:
        segment_dr = segment_m.SegmentMatchService(
        ).get_segment_match_info_by_prd_segment_id(ret_ip_segment_datas['id'])
        if not segment_dr:
            return False, '集群所在机房、网络区域下无法找到生产网段对应的容灾网段ID', ''
        segment_dr_data = segment_s.SegmentService().get_segment_info(
            segment_dr['dr_segment_id'])
        if not segment_dr_data:
            return False, '集群所在机房、网络区域下无法找到生产网段对应的容灾网段详细信息', ''

    elif int(env) == DataCenterType.DR:
        segment_prd = segment_m.SegmentMatchService(
        ).get_segment_match_info_by_dr_segment_id(ret_ip_segment_datas['id'])
        if not segment_prd:
            return False, '指定机房、网络区域下无法找到容灾网段对应的生产网段ID', ''
        segment_prd_data = segment_s.SegmentService().get_segment_info(
            segment_prd['prd_segment_id'])
        if not segment_prd_data:
            return False, '指定机房、网络区域下无法找到容灾网段对应的生产网段详细信息', ''

    # 标记ip为预分配
    ips_list = []
    prd_ips_list = []
    dr_ips_list = []
    for ip in ret_ip_datas:
        update_data = {'status': IPStatus.PRE_ALLOCATION}
        where_data = {'id': ip['id']}
        ret_mark_ip = ip_service.IPService().update_ip_info(
            update_data, where_data)
        if ret_mark_ip <= 0:
            continue
        ips_list.append(ip)

        # 生产环境需要预分配对应容灾环境ip,容灾环境需要预分配生产环境ip
        if int(env) == DataCenterType.PRD:
            # 拼凑虚拟机容灾ip并预分配ip
            dr_ip = segment_dr_data['segment'].split('.')[0] + '.' + segment_dr_data['segment'].split('.')[1] + \
                    '.' + ip['ip_address'].split('.')[2] + '.' + ip['ip_address'].split('.')[3]
            dr_ip_info = ip_service.IPService().get_ip_by_ip_address(dr_ip)
            # 如果容灾环境ip未初始化,默认初始化
            if not dr_ip_info:
                if not __init_ip(segment_dr_data, dr_ip):
                    continue
                dr_ip_info = ip_service.IPService().get_ip_by_ip_address(dr_ip)

            update_data = {'status': IPStatus.PRE_ALLOCATION}
            where_data = {'ip_address': dr_ip}
            ret_mark_ip = ip_service.IPService().update_ip_info(
                update_data, where_data)
            if ret_mark_ip <= 0:
                continue
            dr_ips_list.append(dr_ip_info)
        elif int(env) == DataCenterType.DR:
            # 拼凑虚拟机生产ip并预分配ip
            prd_ip = segment_prd_data['segment'].split('.')[0] + '.' + segment_prd_data['segment'].split('.')[1] + \
                     '.' + ip['ip_address'].split('.')[2] + '.' + ip['ip_address'].split('.')[3]
            prd_ip_info = ip_service.IPService().get_ip_by_ip_address(prd_ip)
            # 如果生产环境ip未初始化,默认初始化
            if not prd_ip_info:
                if not __init_ip(segment_prd_data, prd_ip):
                    continue
                prd_ip_info = ip_service.IPService().get_ip_by_ip_address(
                    prd_ip)
            update_data = {'status': IPStatus.PRE_ALLOCATION}
            where_data = {'ip_address': prd_ip}
            ret_mark_ip = ip_service.IPService().update_ip_info(
                update_data, where_data)
            if ret_mark_ip <= 0:
                continue
            prd_ips_list.append(prd_ip_info)

    if len(ips_list) <= 0:
        return False, '虚拟机创建所需%s个可用IP修改为预分配状态全部失败' % str(count), ''
    elif int(env) == DataCenterType.PRD and (
            len(ips_list) + len(dr_ips_list)) < int(count) * 2:
        return False, '生产环境虚拟机创建所需%s个可用IP修改为预分配状态部分失败' % str(count), ''
    elif int(env) == DataCenterType.DR and (
            len(ips_list) + len(prd_ips_list)) < int(count) * 2:
        return False, '容灾环境虚拟机创建所需%s个可用IP修改为预分配状态部分失败' % str(count), ''
    elif len(ips_list) < int(count):
        return False, '虚拟机创建所需%s个可用IP修改为预分配状态部分失败' % str(count), ''
    else:
        return True, ret_ip_datas, ret_ip_segment_datas
Ejemplo n.º 4
0
def get_available_ips(segments_list, count, env):
    '''
        从网段list中循环获取可使用的多个IP
    :param segments_list:
    :param count:
    :param env:
    :return:
    '''
    for _segment in segments_list:
        ips_list = []
        ips_info = ip.get_available_ip(_segment['id'])
        if ips_info:
            # 多线程ping去掉通的ip
            global IP_AVAILABLE_LIST
            IP_AVAILABLE_LIST = []
            threads = []
            for _per_unused_ip in ips_info:
                ip_check_thread = threading.Thread(target=__ping_ip_available,
                                                   args=(_per_unused_ip, ))
                threads.append(ip_check_thread)
                ip_check_thread.start()
            logging.info("ip available list: {}".format(IP_AVAILABLE_LIST))
            # 判断多线程是否结束
            for t in threads:
                t.join()

            if len(IP_AVAILABLE_LIST) < count:
                continue

            for _ip in IP_AVAILABLE_LIST:
                if int(env) == DataCenterType.PRD:
                    segment_dr = segment_m.SegmentMatchService(
                    ).get_segment_match_info_by_prd_segment_id(_segment['id'])
                    if not segment_dr:
                        continue
                    segment_dr_data = segment_s.SegmentService(
                    ).get_segment_info(segment_dr['dr_segment_id'])
                    if not segment_dr_data:
                        continue
                    # 拼凑虚拟机容灾IP
                    dr_ip = segment_dr_data['segment'].split('.')[0] + '.' + segment_dr_data['segment'].split('.')[1] + \
                            '.' + _ip['ip_address'].split('.')[2] + '.' + _ip['ip_address'].split('.')[3]
                    # ping ip,通的话不允许分配
                    ret_ping = __ping_ip_available_simple(dr_ip)
                    if not ret_ping:
                        continue
                    dr_ip_info = IPService().get_ip_by_ip_address(dr_ip)
                    # 如果容灾IP是未使用中状态,可以使用
                    if dr_ip_info:
                        if dr_ip_info['status'] == IPStatus.UNUSED:
                            ips_list.append(_ip)
                            if len(ips_list) == int(count):
                                return ips_list, _segment
                elif int(env) == DataCenterType.DR:
                    segment_prd = segment_m.SegmentMatchService(
                    ).get_segment_match_info_by_dr_segment_id(_segment['id'])
                    if not segment_prd:
                        continue
                    segment_prd_data = segment_s.SegmentService(
                    ).get_segment_info(segment_prd['prd_segment_id'])
                    if not segment_prd_data:
                        continue
                    # 拼凑虚拟机生产IP
                    prd_ip = segment_prd_data['segment'].split(
                        '.')[0] + '.' + segment_prd_data['segment'].split(
                            '.')[1] + '.' + _ip['ip_address'].split(
                                '.')[2] + '.' + _ip['ip_address'].split('.')[3]
                    ret_ping = __ping_ip_available_simple(prd_ip)
                    if not ret_ping:
                        continue
                    prd_ip_info = IPService().get_ip_by_ip_address(prd_ip)
                    # 如果生产环境ip是未使用中状态,可以使用
                    if prd_ip_info:
                        if prd_ip_info['status'] == IPStatus.UNUSED:
                            ips_list.append(_ip)
                            if len(ips_list) == int(count):
                                return ips_list, _segment
                else:
                    ips_list.append(_ip)
                    if len(ips_list) == int(count):
                        return ips_list, _segment

    # 如果没有获取到合适的IP,返回失败
    return False, ''
Ejemplo n.º 5
0
def get_all_available_segment_ip(segment_id, env):
    '''
        返回指定网段所有可用ip
    :param segment_id:
    :param env:
    :return:
    '''
    ips_list = []
    ips_info = ip.get_available_ip(segment_id)
    if ips_info:
        # 多线程ping去掉通的ip
        global IP_AVAILABLE_LIST
        IP_AVAILABLE_LIST = []
        threads = []
        for _per_unused_ip in ips_info:
            ip_check_thread = threading.Thread(target=__ping_ip_available,
                                               args=(_per_unused_ip, ))
            threads.append(ip_check_thread)
            ip_check_thread.start()
        # 判断多线程是否结束
        for t in threads:
            t.join()

        if len(IP_AVAILABLE_LIST) > 0:
            for _ip in IP_AVAILABLE_LIST:
                if int(env) == DataCenterType.PRD:
                    segment_dr = segment_m.SegmentMatchService(
                    ).get_segment_match_info_by_prd_segment_id(segment_id)
                    if not segment_dr:
                        continue
                    segment_dr_data = segment_s.SegmentService(
                    ).get_segment_info(segment_dr['dr_segment_id'])
                    if not segment_dr_data:
                        continue
                    # 拼凑虚拟机容灾IP
                    dr_ip = segment_dr_data['segment'].split('.')[0] + '.' + segment_dr_data['segment'].split('.')[1] + \
                            '.' + _ip['ip_address'].split('.')[2] + '.' + _ip['ip_address'].split('.')[3]
                    # ping ip,通的话不允许分配
                    # ret_ping = __ping_ip_available_simple(dr_ip)
                    # if not ret_ping:
                    #     continue
                    dr_ip_info = IPService().get_ip_by_ip_address(dr_ip)
                    # 如果容灾IP是未使用中状态,可以使用
                    if dr_ip_info:
                        if dr_ip_info['status'] == IPStatus.UNUSED:
                            ips_list.append(_ip)
                elif int(env) == DataCenterType.DR:
                    segment_prd = segment_m.SegmentMatchService(
                    ).get_segment_match_info_by_dr_segment_id(segment_id)
                    if not segment_prd:
                        continue
                    segment_prd_data = segment_s.SegmentService(
                    ).get_segment_info(segment_prd['prd_segment_id'])
                    if not segment_prd_data:
                        continue
                    # 拼凑虚拟机生产IP
                    prd_ip = segment_prd_data['segment'].split(
                        '.')[0] + '.' + segment_prd_data['segment'].split(
                            '.')[1] + '.' + _ip['ip_address'].split(
                                '.')[2] + '.' + _ip['ip_address'].split('.')[3]
                    # ping ip,通的话不允许分配
                    # ret_ping = __ping_ip_available_simple(prd_ip)
                    # if not ret_ping:
                    #     continue
                    prd_ip_info = IPService().get_ip_by_ip_address(prd_ip)
                    # 如果生产环境ip是未使用中状态,可以使用
                    if prd_ip_info:
                        if prd_ip_info['status'] == IPStatus.UNUSED:
                            ips_list.append(_ip)
                else:
                    ips_list.append(_ip)

    # 如果没有获取到合适的IP,返回失败
    return True, ips_list
def ips_apply_from_other_platform():
    '''
        外部平台申请KVM IP, IP会置为预分配
    :return:
    '''
    data_from_api = request.data
    logging.info(data_from_api)
    data_requset = json_helper.loads(data_from_api)
    req_datacenter = data_requset['dataCenter']
    req_env = data_requset['env']
    req_net_area = data_requset['netArea']
    count = data_requset['ipNums']
    netcare_type = data_requset.get('netCardType', NetCardType.INTERNAL)

    # 校验入参是否为空
    if not req_net_area or not req_datacenter or not req_env or not count:
        return json_helper.format_api_resp_msg(code=ErrorCode.PARAM_ERR, job_status=VsJobStatus.FAILED,
                                               detail='机房、环境、网络区域或ip数量入参为空')

    # 查询指定环境、网络区域是否有所需网段,容灾微应用需要遍历联通、电信所有可用网段
    if DataCenterTypeForVishnu.TYPE_DICT[req_env] == DataCenterType.MINIARCHDR:
        ret_segment_datas_telecom = segment_s.get_segments_data_by_type(req_net_area, req_datacenter,
                                                                        str(DataCenterTypeForVishnu.TYPE_DICT[req_env]),
                                                                        NetCardType.INTERNEL_TELECOM)
        ret_segment_datas_unicom = segment_s.get_segments_data_by_type(req_net_area, req_datacenter,
                                                                       str(DataCenterTypeForVishnu.TYPE_DICT[req_env]),
                                                                       NetCardType.INTERNEL_UNICOM)
        ret_segment_datas = ret_segment_datas_telecom + ret_segment_datas_unicom

    else:
        ret_segment_datas = segment_s.get_segments_data_by_type(req_net_area, req_datacenter,
                                                                str(DataCenterTypeForVishnu.TYPE_DICT[req_env]),
                                                                netcare_type)
    if not ret_segment_datas:
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail='指定机房、网络区域下没有可用网段用于分配IP')

    # 获取IP资源,先判断是否有人也在分配IP资源,有则等待1s,时间之后再优化
    ip_lock_unused = False
    while not ip_lock_unused:
        ret_ip_lock_status = ip_l_s.IpLockService().get_ip_lock_info('ip')
        if not ret_ip_lock_status:
            logging.error('外部接口分配vip:检查IP时无法获取资源锁状态')
            return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                   detail='检查IP时无法获取资源锁状态')
        if ret_ip_lock_status['istraceing'] == IpLockStatus.USED:
            time.sleep(1)
        else:
            ip_lock_unused = True

    # 更新ip_lock表istraceing字段为1
    ret_ip_lock_used_status, ret_ip_lock_used_datas = __update_ip_lock_used()
    if not ret_ip_lock_used_status:
        logging.error(ret_ip_lock_used_datas)
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail=ret_ip_lock_used_datas)

    try:
        # 获取可用ip
        ret_ip_datas, ret_ip_segment_datas = ip_service.get_available_ips(ret_segment_datas, int(count), str(DataCenterTypeForVishnu.TYPE_DICT[req_env]))
        if not ret_ip_datas:
            ret_ip_lock_unused_status, ret_ip_lock_unused_datas = __update_ip_lock_unused()
            if not ret_ip_lock_unused_status:
                logging.error(ret_ip_lock_unused_datas)
                return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                       detail=ret_ip_lock_unused_datas)
            return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                   detail='指定机房、网络区域下无法找到%s个可用IP' % str(count))

        # 如果是申请生产或者容灾环境ip,需判断网段对应关系表中是否有记录
        if req_env == 'PRD':
            segment_dr = segment_m.SegmentMatchService().get_segment_match_info_by_prd_segment_id(ret_ip_segment_datas['id'])
            if not segment_dr:
                ret_ip_lock_unused_status, ret_ip_lock_unused_datas = __update_ip_lock_unused()
                if not ret_ip_lock_unused_status:
                    logging.error(ret_ip_lock_unused_datas)
                    return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                           detail=ret_ip_lock_unused_datas)
                return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                       detail='指定机房、网络区域下无法找到生产网段对应的容灾网段ID')
            segment_dr_data = segment_s.SegmentService().get_segment_info(segment_dr['dr_segment_id'])
            if not segment_dr_data:
                ret_ip_lock_unused_status, ret_ip_lock_unused_datas = __update_ip_lock_unused()
                if not ret_ip_lock_unused_status:
                    logging.error(ret_ip_lock_unused_datas)
                    return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                           detail=ret_ip_lock_unused_datas)
                return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                       detail='指定机房、网络区域下无法找到生产网段对应的容灾网段详细信息')

        elif req_env == 'DR':
            segment_prd = segment_m.SegmentMatchService().get_segment_match_info_by_dr_segment_id(ret_ip_segment_datas['id'])
            if not segment_prd:
                ret_ip_lock_unused_status, ret_ip_lock_unused_datas = __update_ip_lock_unused()
                if not ret_ip_lock_unused_status:
                    logging.error(ret_ip_lock_unused_datas)
                    return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                           detail=ret_ip_lock_unused_datas)
                return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                       detail='指定机房、网络区域下无法找到容灾网段对应的生产网段ID')
            segment_prd_data = segment_s.SegmentService().get_segment_info(segment_prd['prd_segment_id'])
            if not segment_prd_data:
                ret_ip_lock_unused_status, ret_ip_lock_unused_datas = __update_ip_lock_unused()
                if not ret_ip_lock_unused_status:
                    logging.error(ret_ip_lock_unused_datas)
                    return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                           detail=ret_ip_lock_unused_datas)
                return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                       detail='指定机房、网络区域下无法找到容灾网段对应的生产网段详细信息')

        # 标记ip为预分配
        logging.info(ret_ip_datas)
        ips_list = []
        prd_ips_list = []
        dr_ips_list = []
        ip_details = {}
        for ip in ret_ip_datas:
            update_data = {
                'status': IPStatus.PRE_ALLOCATION,
                'updated_at': get_datetime_str()
            }
            where_data = {
                'id': ip['id']
            }
            ret_mark_ip = ip_service.IPService().update_ip_info(update_data, where_data)
            if ret_mark_ip <= 0:
                continue
            ip_datas = {
                'ip': ip['ip_address'],
                'vlanId': ip['vlan'],
                'subnetMask': __exchange_maskint(int(ip['netmask'])),
                'gateway': ip['gateway_ip'],
                'ip_type': ret_ip_segment_datas['segment_type']
            }
            ips_list.append(ip_datas)

            # 生产环境需要预分配对应容灾环境ip,容灾环境需要预分配生产环境ip
            if req_env == 'PRD':
                # 拼凑虚拟机容灾ip并预分配ip
                dr_ip = segment_dr_data['segment'].split('.')[0] + '.' + segment_dr_data['segment'].split('.')[1] + \
                        '.' + ip['ip_address'].split('.')[2] + '.' + ip['ip_address'].split('.')[3]
                dr_ip_info = ip_service.IPService().get_ip_by_ip_address(dr_ip)
                # 如果容灾环境ip未初始化,默认初始化
                if not dr_ip_info:
                    if not __init_ip(segment_dr_data, dr_ip):
                        continue
                    dr_ip_info = ip_service.IPService().get_ip_by_ip_address(dr_ip)

                update_data = {
                    'status': IPStatus.PRE_ALLOCATION
                }
                where_data = {
                    'ip_address': dr_ip
                }
                ret_mark_ip = ip_service.IPService().update_ip_info(update_data, where_data)
                if ret_mark_ip <= 0:
                    continue

                # 拼装容灾ip信息
                dr_ip_datas = {
                    'ip': dr_ip_info['ip_address'],
                    'vlanId': dr_ip_info['vlan'],
                    'subnetMask': __exchange_maskint(int(dr_ip_info['netmask'])),
                    'gateway': dr_ip_info['gateway_ip']
                }
                dr_ips_list.append(dr_ip_datas)
            elif req_env == 'DR':
                # 拼凑虚拟机生产ip并预分配ip
                prd_ip = segment_prd_data['segment'].split('.')[0] + '.' + segment_prd_data['segment'].split('.')[1] + \
                         '.' + ip['ip_address'].split('.')[2] + '.' + ip['ip_address'].split('.')[3]
                prd_ip_info = ip_service.IPService().get_ip_by_ip_address(prd_ip)
                # 如果生产环境ip未初始化,默认初始化
                if not prd_ip_info:
                    if not __init_ip(segment_prd_data, prd_ip):
                        continue
                    prd_ip_info = ip_service.IPService().get_ip_by_ip_address(prd_ip)
                update_data = {
                    'status': IPStatus.PRE_ALLOCATION
                }
                where_data = {
                    'ip_address': prd_ip
                }
                ret_mark_ip = ip_service.IPService().update_ip_info(update_data, where_data)
                if ret_mark_ip <= 0:
                    continue

                # 拼装生产ip信息
                prd_ip_datas = {
                    'ip': prd_ip_info['ip_address'],
                    'vlanId': prd_ip_info['vlan'],
                    'subnetMask': __exchange_maskint(int(prd_ip_info['netmask'])),
                    'gateway': prd_ip_info['gateway_ip']
                }
                prd_ips_list.append(prd_ip_datas)
    except Exception as e:
        _msg = '外部接口预分配IP:预分配ip出现异常: distribution ip exception,err:%s' %e
        logging.error(_msg)
        ret_ip_lock_unused_status, ret_ip_lock_unused_datas = __update_ip_lock_unused()
        if not ret_ip_lock_unused_status:
            logging.error(ret_ip_lock_unused_datas)
            return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=ret_ip_lock_unused_datas)
        return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=_msg)
    # 更新ip_lock表istraceing字段为0
    ret_ip_lock_unused_status, ret_ip_lock_unused_datas = __update_ip_lock_unused()
    if not ret_ip_lock_unused_status:
        logging.error(ret_ip_lock_unused_datas)
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail=ret_ip_lock_unused_datas)

    if len(ips_list) <= 0:
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail='指定机房、网络区域下%s个可用IP修改为预分配状态全部失败' % str(count))
    elif req_env == 'PRD' and (len(ips_list) + len(dr_ips_list)) < int(count)*2:
        return json_helper.format_api_resp_msg(code=ErrorCode.SUCCESS_PART, job_status=VsJobStatus.FAILED,
                                               detail='生产环境指定机房、网络区域下%s个可用IP修改为预分配状态部分失败' % str(count))
    elif req_env == 'DR' and (len(ips_list) + len(prd_ips_list)) < int(count)*2:
        return json_helper.format_api_resp_msg(code=ErrorCode.SUCCESS_PART, job_status=VsJobStatus.FAILED,
                                               detail='容灾环境指定机房、网络区域下%s个可用IP修改为预分配状态部分失败' % str(count))
    elif len(ips_list) < int(count):
        return json_helper.format_api_resp_msg(code=ErrorCode.SUCCESS_PART, job_status=VsJobStatus.FAILED,
                                               detail='指定机房、网络区域下%s个可用IP修改为预分配状态部分失败' % str(count))
    else:
        if req_env == 'PRD':
            ip_details['prd'] = ips_list
            ip_details['dr'] = dr_ips_list
        elif req_env == 'DR':
            ip_details['dr'] = ips_list
            ip_details['prd'] = prd_ips_list
        else:
            ip_details['default'] = ips_list
        logging.info(ip_details)
        return json_helper.format_api_resp_msg(code=ErrorCode.SUCCESS, job_status=VsJobStatus.SUCCEED,
                                               detail=ip_details)
def ip_apply_from_other_platform():
    '''
        外部平台申请ip
    :return:
    '''
    data_from_vishnu = request.data
    logging.info(data_from_vishnu)
    data_requset = json_helper.loads(data_from_vishnu)
    req_datacenter = data_requset['datacenter']
    req_env = data_requset['env']
    req_net_area = data_requset['net_area']
    req_net_name = data_requset['net_name']
    cluster_id = data_requset['cluster_id']
    opuser = data_requset['opUser']
    sys_code = data_requset['sys_code']
    taskid_vs = data_requset['taskid']
    ip_count = data_requset['ipCount']
    prd_dr_ip_all_needed = data_requset['prdDrAllNeeded']  # '0'代表普通申请,'1'需要同时申请prd、dr环境的ip

    # 校验入参是否为空
    if not req_env or not req_net_area or not req_net_name or not req_datacenter:
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail='empty input of env, net area information or net name '
                                                      'when apply ip')
    if not cluster_id or not opuser or not sys_code or not taskid_vs:
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail='empty input of cluster_id, opuser, '
                                                      'task id or sys_code when apply ip')

    if not str(ip_count) or not str(prd_dr_ip_all_needed):
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail='empty input of ipCount or prdDrAllNeeded when apply ip')

    # 查询指定环境、网络区域是否有所需网段
    ret_segment = segment_service.SegmentService().get_segment_info_bysegment(req_net_name.split('/')[0])
    if not ret_segment:
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail="无法找到需要申请的网段")

    ret_net_area_info = net_area.NetAreaService().get_net_area_info(ret_segment['net_area_id'])
    if not ret_net_area_info:
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail="无法找到指定网段所属网络区域信息")

    ret_datacenter_info = datacenter_service.DataCenterService().get_datacenter_info(ret_net_area_info['datacenter_id'])
    if not ret_datacenter_info:
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail="无法找到指定机房信息")
    if req_env not in DataCenterTypeForVishnu.TYPE_DICT:
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail="无法找到指定机房类型信息")
    if str(DataCenterTypeForVishnu.TYPE_DICT[req_env]) != ret_datacenter_info['dc_type']:
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail="无法找到指定网络区域对应网段信息")

    # 如果是申请生产或者容灾环境ip,需判断网段对应关系表中是否有记录
    if req_env == 'PRD':
        segment_dr = segment_m.SegmentMatchService().get_segment_match_info_by_prd_segment_id(
            ret_segment['id'])
        if not segment_dr:
            return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                   detail='指定机房、网络区域下无法找到生产网段对应的容灾网段ID')
        segment_dr_data = segment_s.SegmentService().get_segment_info(segment_dr['dr_segment_id'])
        if not segment_dr_data:
            return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                   detail='指定机房、网络区域下无法找到生产网段对应的容灾网段详细信息')

    elif req_env == 'DR':
        segment_prd = segment_m.SegmentMatchService().get_segment_match_info_by_dr_segment_id(
            ret_segment['id'])
        if not segment_prd:
            return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                   detail='指定机房、网络区域下无法找到容灾网段对应的生产网段ID')
        segment_prd_data = segment_s.SegmentService().get_segment_info(segment_prd['prd_segment_id'])
        if not segment_prd_data:
            return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                   detail='指定机房、网络区域下无法找到容灾网段对应的生产网段详细信息')

    # 获取IP资源,先判断是否有人也在分配IP资源,有则等待1s,时间之后再优化
    ip_lock_unused = False
    while not ip_lock_unused:
        ret_ip_lock_status = ip_l_s.IpLockService().get_ip_lock_info('ip')
        if not ret_ip_lock_status:
            logging.error('外部接口分配vip:检查IP时无法获取资源锁状态')
            return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                   detail='检查IP时无法获取资源锁状态')
        if ret_ip_lock_status['istraceing'] == IpLockStatus.USED:
            time.sleep(1)
        else:
            ip_lock_unused = True

    # 更新ip_lock表istraceing字段为1
    ret_ip_lock_used_status, ret_ip_lock_used_datas = __update_ip_lock_used()
    if not ret_ip_lock_used_status:
        logging.error(ret_ip_lock_used_datas)
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail=ret_ip_lock_used_datas)
    try:
        segments_data_list = []
        segments_data_list.append(ret_segment)
        # 获取可用ip
        ret_ip_datas, ret_ip_segment_datas = ip_service.get_available_ips(segments_data_list, int(ip_count), str(
            DataCenterTypeForVishnu.TYPE_DICT[req_env]))
        if not ret_ip_datas:
            ret_ip_lock_unused_status, ret_ip_lock_unused_datas = __update_ip_lock_unused()
            if not ret_ip_lock_unused_status:
                logging.error(ret_ip_lock_unused_datas)
                return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                       detail=ret_ip_lock_unused_datas)
            return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                                   detail='指定机房、网络区域下无法找到%s个可用IP' % str(ip_count))

        # 标记ip为预分配
        logging.info(ret_ip_datas)
        ips_list = []
        prd_ips_list = []
        dr_ips_list = []
        ip_details = {}
        for ip in ret_ip_datas:
            update_data = {
                'status': IPStatus.USED
            }
            where_data = {
                'id': ip['id']
            }
            ret_mark_ip = ip_service.IPService().update_ip_info(update_data, where_data)
            if ret_mark_ip <= 0:
                continue

            # 录入vip信息到数据库中
            insert_vip_data = {
                'ip_id': ip['id'],
                'cluster_id': cluster_id,
                'apply_user_id': opuser,
                'sys_code': sys_code,
                'isdeleted': '0',
                'created_at': get_datetime_str()
            }
            ret_vip = vip_service.VIPService().add_vip_info(insert_vip_data)
            if ret_vip.get('row_num') <= 0:
                continue

            ip_datas = {
                'ip': ip['ip_address'],
                'vlanId': ip['vlan'],
                'subnetMask': __exchange_maskint(int(ip['netmask'])),
                'gateway': ip['gateway_ip']
            }
            ips_list.append(ip_datas)

            # 生产环境需要预分配对应容灾环境ip,容灾环境需要预分配生产环境ip
            if req_env == 'PRD':
                # 拼凑虚拟机容灾ip并预分配ip
                dr_ip = segment_dr_data['segment'].split('.')[0] + '.' + segment_dr_data['segment'].split('.')[1] + \
                        '.' + ip['ip_address'].split('.')[2] + '.' + ip['ip_address'].split('.')[3]
                dr_ip_info = ip_service.IPService().get_ip_by_ip_address(dr_ip)
                # 如果容灾环境ip未初始化,默认初始化
                if not dr_ip_info:
                    if not __init_ip(segment_dr_data, dr_ip):
                        continue
                    dr_ip_info = ip_service.IPService().get_ip_by_ip_address(dr_ip)

                if prd_dr_ip_all_needed == '1':
                    update_data = {
                        'status': IPStatus.USED
                    }
                    where_data = {
                        'id': dr_ip_info['id']
                    }
                    ret_mark_ip = ip_service.IPService().update_ip_info(update_data, where_data)
                    if ret_mark_ip <= 0:
                        continue

                    # 录入vip信息到数据库中
                    insert_vip_data = {
                        'ip_id': dr_ip_info['id'],
                        'cluster_id': cluster_id,
                        'apply_user_id': opuser,
                        'sys_code': sys_code,
                        'isdeleted': '0',
                        'created_at': get_datetime_str()
                    }
                    ret_vip = vip_service.VIPService().add_vip_info(insert_vip_data)
                    if ret_vip.get('row_num') <= 0:
                        continue
                else:
                    update_data = {
                        'status': IPStatus.PRE_ALLOCATION
                    }
                    where_data = {
                        'ip_address': dr_ip
                    }
                    ret_mark_ip = ip_service.IPService().update_ip_info(update_data, where_data)
                    if ret_mark_ip <= 0:
                        continue

                # 拼装容灾ip信息
                dr_ip_datas = {
                    'ip': dr_ip_info['ip_address'],
                    'vlanId': dr_ip_info['vlan'],
                    'subnetMask': __exchange_maskint(int(dr_ip_info['netmask'])),
                    'gateway': dr_ip_info['gateway_ip']
                }
                dr_ips_list.append(dr_ip_datas)
            elif req_env == 'DR':
                # 拼凑虚拟机生产ip并预分配ip
                prd_ip = segment_prd_data['segment'].split('.')[0] + '.' + segment_prd_data['segment'].split('.')[1] + \
                         '.' + ip['ip_address'].split('.')[2] + '.' + ip['ip_address'].split('.')[3]
                prd_ip_info = ip_service.IPService().get_ip_by_ip_address(prd_ip)
                # 如果生产环境ip未初始化,默认初始化
                if not prd_ip_info:
                    if not __init_ip(segment_prd_data, prd_ip):
                        continue
                    prd_ip_info = ip_service.IPService().get_ip_by_ip_address(prd_ip)

                if prd_dr_ip_all_needed == '1':
                    update_data = {
                        'status': IPStatus.USED
                    }
                    where_data = {
                        'id': prd_ip_info['id']
                    }
                    ret_mark_ip = ip_service.IPService().update_ip_info(update_data, where_data)
                    if ret_mark_ip <= 0:
                        continue

                    # 录入vip信息到数据库中
                    insert_vip_data = {
                        'ip_id': prd_ip_info['id'],
                        'cluster_id': cluster_id,
                        'apply_user_id': opuser,
                        'sys_code': sys_code,
                        'isdeleted': '0',
                        'created_at': get_datetime_str()
                    }
                    ret_vip = vip_service.VIPService().add_vip_info(insert_vip_data)
                    if ret_vip.get('row_num') <= 0:
                        continue
                else:
                    update_data = {
                        'status': IPStatus.PRE_ALLOCATION
                    }
                    where_data = {
                        'ip_address': prd_ip
                    }
                    ret_mark_ip = ip_service.IPService().update_ip_info(update_data, where_data)
                    if ret_mark_ip <= 0:
                        continue

                # 拼装生产ip信息
                prd_ip_datas = {
                    'ip': prd_ip_info['ip_address'],
                    'vlanId': prd_ip_info['vlan'],
                    'subnetMask': __exchange_maskint(int(prd_ip_info['netmask'])),
                    'gateway': prd_ip_info['gateway_ip']
                }
                prd_ips_list.append(prd_ip_datas)
    except Exception as e:
        _msg = '外部平台申请IP:预分配ip出现异常: distribution ip exception,err:%s'%e
        logging.error(_msg)
        ret_ip_lock_unused_status, ret_ip_lock_unused_datas = __update_ip_lock_unused()
        if not ret_ip_lock_unused_status:
            logging.error(ret_ip_lock_unused_datas)
            return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=ret_ip_lock_unused_datas)
        return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=_msg)

    # 更新ip_lock表istraceing字段为0
    ret_ip_lock_unused_status, ret_ip_lock_unused_datas = __update_ip_lock_unused()
    if not ret_ip_lock_unused_status:
        logging.error(ret_ip_lock_unused_datas)
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail=ret_ip_lock_unused_datas)

    if len(ips_list) <= 0:
        return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED,
                                               detail='指定机房、网络区域下%s个可用IP修改为预分配状态全部失败' % str(ip_count))
    elif req_env == 'PRD' and (len(ips_list) + len(dr_ips_list)) < int(ip_count) * 2:
        return json_helper.format_api_resp_msg(code=ErrorCode.SUCCESS_PART, job_status=VsJobStatus.FAILED,
                                               detail='生产环境指定机房、网络区域下%s个可用IP修改为预分配状态部分失败' % str(ip_count))
    elif req_env == 'DR' and (len(ips_list) + len(prd_ips_list)) < int(ip_count) * 2:
        return json_helper.format_api_resp_msg(code=ErrorCode.SUCCESS_PART, job_status=VsJobStatus.FAILED,
                                               detail='容灾环境指定机房、网络区域下%s个可用IP修改为预分配状态部分失败' % str(ip_count))
    elif len(ips_list) < int(ip_count):
        return json_helper.format_api_resp_msg(code=ErrorCode.SUCCESS_PART, job_status=VsJobStatus.FAILED,
                                               detail='指定机房、网络区域下%s个可用IP修改为预分配状态部分失败' % str(ip_count))
    else:
        if req_env == 'PRD':
            ip_details['prd'] = ips_list
            ip_details['dr'] = dr_ips_list
        elif req_env == 'DR':
            ip_details['dr'] = ips_list
            ip_details['prd'] = prd_ips_list
        else:
            ip_details['default'] = ips_list
        return json_helper.format_api_resp_msg(code=ErrorCode.SUCCESS, job_status=VsJobStatus.SUCCEED,
                                               detail=ip_details)