def ip_resource_display_to_other_platform_new(): ''' 将kvm已有的网段展示给其他平台新接口,查询指定网段可用的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['netArea'] req_net_name = data_requset['netName'] # 校验入参是否为空 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_to_vishnu_resource(job_status=VsJobStatus.FAILED, detail='入参有空值') # 查询指定环境、网络区域是否有所需网段 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_to_vishnu_resource(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_to_vishnu_resource(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_to_vishnu_resource(job_status=VsJobStatus.FAILED, detail="无法找到指定机房信息") if req_env not in DataCenterTypeForVishnu.TYPE_DICT: return json_helper.format_api_resp_msg_to_vishnu_resource(job_status=VsJobStatus.FAILED, detail="无法找到指定机房类型信息") if str(DataCenterTypeForVishnu.TYPE_DICT[req_env]) != ret_datacenter_info['dc_type']: return json_helper.format_api_resp_msg_to_vishnu_resource(job_status=VsJobStatus.FAILED, detail="无法找到指定网络区域对应网段信息") # 获取可用ip ret_ip_available_status, ret_ip_available = ip_service.get_all_available_segment_ip(ret_segment['id'], str( DataCenterTypeForVishnu.TYPE_DICT[req_env])) if not ret_ip_available_status: ret_params = { "ip_num": 0 } return json_helper.format_api_resp_msg_to_vishnu_resource(job_status=VsJobStatus.SUCCEED, detail=ret_params) ret_params = { "ip_num": len(ret_ip_available) } return json_helper.format_api_resp_msg_to_vishnu_resource(job_status=VsJobStatus.SUCCEED, detail=ret_params)
def instance_os_version_modify(instance_id): ''' 修改os版本为unknown的虚拟机 :param instance_id: :json param : :return: ''' req_json = request.data req_data = json_helper.loads(req_json) n_os_version = req_data["os_version"] if not instance_id or not str(n_os_version): logging.info( 'no instance_id or os_version when modify instance os version') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR) ins_data = ins_s.InstanceService().get_instance_info(instance_id) if not ins_data: logging.error( 'instance %s info is no exist in db when modify instance os version', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # VM创建来源 create_source = ins_data['create_source'] # 本平台 if create_source == VMCreateSource.OPENSTACK or create_source == VMCreateSource.ESX: # v2v迁移的VM ins_v2v_data = v2v_i_i_s.v2vInstanceinfo( ).get_v2v_instance_info_by_instance_id(instance_id) if ins_v2v_data: if ins_v2v_data['os_version'] and ins_v2v_data[ 'os_version'] == "unknown": # 更新v2v虚拟机os版本 update_data = {'os_version': n_os_version} where_data = {'instance_id': instance_id} v2v_i_i_s.v2vInstanceinfo().update_v2v_status( update_data, where_data) else: # todo: kvm2.0需要增加对平台自身创建虚拟机操作系统版本校验,unknown的可以修改 pass return json_helper.format_api_resp(code=ErrorCode.SUCCESS, msg="操作系统版本更新成功")
def host_perform_data_to_db(): ''' 此函数用于将物理机上报上来的性能数据写入数据库 :return: ''' data_from_host = request.data data = json_helper.loads(data_from_host) if not data or not data['ip']: # 物理机性能数据中ip为空,不做任何操作 return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='无法获取上传性能数据中的物理机ip信息,录入性能数据失败') # ret_msg = _msg_format(host_ip=data['ip'], host_name=data['hostname'], cpu_core=data['cpu_core'], # mem_size=data['mem_size'], disk_size=data['disk_size'], net_size=data['net_size'], # current_cpu_used=data['current_cpu_used'], # current_mem_used=data['current_mem_used'], # current_disk_used=data['current_disk_used'], # week_cpu_p95_used=data['week_cpu_p95_used'], # week_mem_p95_used=data['week_mem_p95_used'], # current_net_rx_used=data['current_net_rx_used'], # current_net_tx_used=data['current_net_tx_used'], # start_time=data['start_time'], # libvirt_port=data['libvirt_port'], # libvirt_status=data['libvirt_status'], # images=data['images']) # 更新host表 __update_host_table(data['ip'], data['ostype'], data['cpu_core'], data['mem_size'], data['disk_size'], data['net_size'], data['current_cpu_used'], data['current_mem_used'], data['current_disk_used'], data['week_cpu_p95_used'], data['week_mem_p95_used'], data['current_net_rx_used'], data['current_net_tx_used'], data['start_time'], data['libvirt_port'], data['images'], data['libvirt_status']) # flush_host_perform_data_to_db(datadict=ret_msg) return json_helper.format_api_resp(code=ErrorCode.SUCCESS, msg='%s:录入性能数据成功' % data['ip'])
def segment_capacity_to_other_platform(): ''' 外部平台获取kvm网段或IP资源使用信息 :return: ''' data_from_vishnu = request.data logging.info(data_from_vishnu) data_requset = json_helper.loads(data_from_vishnu) datacenter = data_requset['dataCenter'] env = data_requset['env'] net_area = data_requset['netArea'] network_segment = data_requset['networkSegment'] page_num = data_requset['currentPage'] page_size = data_requset['pageSize'] if not datacenter or not env: return json_helper.format_api_resp_msg_to_vishnu_resource( job_status=VsJobStatus.FAILED, detail='输入机房、环境信息为空') get_network_segment_detail = False if network_segment: get_network_segment_detail = True get_net_area_detail = False if net_area: get_net_area_detail = True if get_net_area_detail and get_network_segment_detail: db_network_segment_datas = get_network_segments_data_by_segment_name( datacenter, str(DataCenterTypeForVishnu.TYPE_DICT[env]), net_area, network_segment) if not db_network_segment_datas: network_segments_params = {"result": []} return json_helper.format_api_resp_msg_to_vishnu_resource( job_status=VsJobStatus.SUCCEED, detail=network_segments_params) ip_data_lists = [] all_ip_datas = get_ip_datas_by_segmentid( db_network_segment_datas['id']) if not all_ip_datas: # 计算该网段应该有的所有ip for __per_calculate_ip in IPy.IP( db_network_segment_datas['segment'] + '/' + db_network_segment_datas['netmask']): ip_params = {"ip": __per_calculate_ip, "status": IpType.UNINIT} ip_data_lists.append(ip_params) all_ip_params = {"result": ip_data_lists} return json_helper.format_api_resp_msg_to_vishnu_resource( job_status=VsJobStatus.SUCCEED, detail=all_ip_params) # 计算该网段应该有的所有ip calculate_ip_lists = [] calculate_ip_data_lists = [] for __per_calculate_ip in IPy.IP(db_network_segment_datas['segment'] + '/' + db_network_segment_datas['netmask']): __per_calculate_ip_params = { "ip": str(__per_calculate_ip), "status": IpTypeTransform.MSG_DICT[IpType.UNINIT] } calculate_ip_data_lists.append(__per_calculate_ip_params) calculate_ip_lists.append(str(__per_calculate_ip)) for per_ip in all_ip_datas: if str(per_ip['ip_address']) in calculate_ip_lists: for __per_calculate_ip_data in calculate_ip_data_lists: if __per_calculate_ip_data['ip'] == str( per_ip['ip_address']): __per_calculate_ip_data[ 'status'] = IpTypeTransform.MSG_DICT[ per_ip['status']] all_ip_params = {"result": calculate_ip_data_lists} return json_helper.format_api_resp_msg_to_vishnu_resource( job_status=VsJobStatus.SUCCEED, detail=all_ip_params) elif get_net_area_detail: # 获取指定机房、环境、网络环境下的所有网段信息,需要分页 network_segment_nums, db_network_segment_datas = get_network_segments_data_paging( datacenter, str(DataCenterTypeForVishnu.TYPE_DICT[env]), net_area, page_num, page_size) if network_segment_nums <= 0: network_segments_params = { "rows": [], "current": page_num, "rowCount": page_size, "total": 0 } return json_helper.format_api_resp_msg_to_vishnu_resource( job_status=VsJobStatus.SUCCEED, detail=network_segments_params) network_segment_datas = [] for network_segment in db_network_segment_datas: ip_init_datas = ip_service.ip_inited_in_segment( network_segment['id']) ret_ip_available_status, ip_availables = ip_service.get_available_ip_by_segment_id( network_segment['id']) if not ip_init_datas: ip_total = 0 ip_canallocated = 0 ip_usedrate = 0 else: if len(ip_init_datas) <= 0: ip_total = 0 ip_canallocated = 0 ip_usedrate = 0 else: ip_total = len(ip_init_datas) if not ret_ip_available_status: ip_canallocated = 0 ip_canallocated = ip_availables ip_usedrate = float( '%.4f' % (float(ip_total - ip_canallocated) / float(ip_total))) per_network_segment_datas = { "canAllocated": ip_canallocated, "environment": env, "gateway": network_segment['gateway_ip'], "netDomain": net_area, "netName": network_segment['segment'], "networkId": '', "outerId": '', "subnetMask": network_segment['netmask'], "total": ip_total, "usedRate": ip_usedrate, "userType": "KVM", "vlanId": network_segment['vlan'] } network_segment_datas.append(per_network_segment_datas) network_segments_params = { "rows": network_segment_datas, "current": page_num, "rowCount": page_size, "total": network_segment_nums } return json_helper.format_api_resp_msg_to_vishnu_resource( job_status=VsJobStatus.SUCCEED, detail=network_segments_params) else: # 返回指定机房、环境下的所有网段信息,需要分页 network_segment_nums, db_network_segment_datas = get_network_segments_data_in_dc_paging( datacenter, str(DataCenterTypeForVishnu.TYPE_DICT[env]), page_num, page_size) if network_segment_nums <= 0: network_segments_params = { "rows": [], "current": page_num, "rowCount": page_size, "total": 0 } return json_helper.format_api_resp_msg_to_vishnu_resource( job_status=VsJobStatus.SUCCEED, detail=network_segments_params) network_segment_datas = [] for network_segment in db_network_segment_datas: ip_init_datas = ip_service.ip_inited_in_segment( network_segment['id']) ret_ip_available_status, ip_availables = ip_service.get_available_ip_by_segment_id( network_segment['id']) if not ip_init_datas: ip_total = 0 ip_canallocated = 0 ip_usedrate = 0 else: if len(ip_init_datas) <= 0: ip_total = 0 ip_canallocated = 0 ip_usedrate = 0 else: ip_total = len(ip_init_datas) if not ret_ip_available_status: ip_canallocated = 0 ip_canallocated = ip_availables ip_usedrate = float( '%.4f' % (float(ip_total - ip_canallocated) / float(ip_total))) per_network_segment_datas = { "canAllocated": ip_canallocated, "environment": env, "gateway": network_segment['gateway_ip'], "netDomain": network_segment['net_area'], "netName": network_segment['segment'], "networkId": '', "outerId": '', "subnetMask": network_segment['netmask'], "total": ip_total, "usedRate": ip_usedrate, "userType": "KVM", "vlanId": network_segment['vlan'] } network_segment_datas.append(per_network_segment_datas) network_segments_params = { "rows": network_segment_datas, "current": page_num, "rowCount": page_size, "total": network_segment_nums } return json_helper.format_api_resp_msg_to_vishnu_resource( job_status=VsJobStatus.SUCCEED, detail=network_segments_params)
def hostpool_capacity_to_other_platform(): ''' 外部平台获取kvm物理集群资源信息 :return: ''' data_from_vishnu = request.data logging.info(data_from_vishnu) data_requset = json_helper.loads(data_from_vishnu) # data_requset = request.values.get("data") # data_requset = json.loads(data_requset) datacenter = data_requset['datacenter'] env = data_requset['env'] vcpu = data_requset['vcpu'] mem_mb = data_requset['mem_MB'] disk_gb = data_requset['disk_GB'] page_num = data_requset['currentPage'] page_size = data_requset['pageSize'] net_area = data_requset['net_area'] all_available_vm_count = 0 # 获取指定机房详细信息存入dc_list列表 dc_list = [] dc_ret, dc_datas = dc_s().get_all_datacenters_by_name(datacenter) if not dc_ret: return json_helper.format_api_resp_msg_to_vishnu_resource(job_status=VsJobStatus.FAILED, detail='无法找到指定机房信息') for one_dc_data in dc_datas: dc_type = DataCenterTypeTransform.MSG_DICT.get(int(one_dc_data['dc_type'])) if env.lower() == dc_type: dc_detail = { "dc_id": one_dc_data['id'], "dc_name": one_dc_data['name'], "dc_area_id": one_dc_data['area_id'], "dc_type": DataCenterTypeTransform.MSG_DICT.get(int(one_dc_data['dc_type'])), } dc_list.append(dc_detail) if len(dc_list) != 1: return json_helper.format_api_resp_msg_to_vishnu_resource(job_status=VsJobStatus.FAILED, detail='无法找到机房中对应环境%s的信息' % env) # 查询指定环境、机房下的网络区域信息 if net_area: net_area_info = get_netarea_info_by_name(str(DataCenterTypeForVishnu.TYPE_DICT[env]), datacenter, net_area) if net_area_info: available_ip_count = __all_ip_available_num(dc_list[0]['dc_id'], net_area_info['id']) else: available_ip_count = 0 else: available_ip_count = __all_ip_available_num(dc_list[0]['dc_id']) # 如果net_area为空,获取指定机房下所有集群信息。否则查询指定机房指定网络区域下的集群信息 hostpool_num, hostpool_infos = hostpool.get_datacenter_hostpool_list(dc_list[0]['dc_id'], net_area, page_num, page_size) if hostpool_num <= 0: params = { "currentPage": int(page_num), "pageSize": int(page_size), "total": 0, "available_vm_count": all_available_vm_count, "available_ip_count": available_ip_count, "cluster_datas": [] } return json_helper.format_api_resp_msg_to_vishnu_resource(job_status=VsJobStatus.SUCCEED, detail=params) capacity_detail = [] for per_hostpool_info in hostpool_infos: if not per_hostpool_info['cluster_id']: pass else: # 查找每一个集群使用情况,以及集群中每一台物理机使用情况 _all_host_num, _all_host_data = host_s.HostService().get_hosts_of_hostpool(per_hostpool_info['cluster_id']) if _all_host_num > 0: # # 过滤超过50台虚拟机的物理机 v_filter = instance_filter.instance_nums_filter(INSTANCE_MAX_NUMS_IN_HOST) hosts = filter(v_filter, _all_host_data) if not hosts: pass else: _host_pool_cpu_mem_used = get_hostpool_mem_cpu_disk_used(hosts, mem_mb, disk_gb , per_hostpool_info['cluster_id']) host_pool_params = { "cluster_id": per_hostpool_info['cluster_id'], "cluster_app_code": per_hostpool_info['cluster_app_code'], "cluster_type": per_hostpool_info["cluster_type"], "cluster_name": per_hostpool_info['cluster_name'], "env": env, "datacenter": datacenter, "net_area": per_hostpool_info['net_area_name'], "available_host_num": _host_pool_cpu_mem_used['all_available_host_num'], "total_capacity": { "mem_mb": _host_pool_cpu_mem_used['mem_all'], "vcpu": _host_pool_cpu_mem_used['cpu_all'], "disk_gb": _host_pool_cpu_mem_used['disk_all'] }, "assign_capacity": { "mem_mb": _host_pool_cpu_mem_used['mem_assign'], "vcpu": _host_pool_cpu_mem_used['cpu_assign'], "disk_gb": _host_pool_cpu_mem_used['disk_assign'] }, "available_capacity": { "mem_mb": _host_pool_cpu_mem_used['mem_available'], "vcpu": _host_pool_cpu_mem_used['cpu_unused'], "disk_gb": _host_pool_cpu_mem_used['disk_available'], "vm_count": _host_pool_cpu_mem_used['available_create_vm'], "ip_count": __all_ip_available_num(dc_list[0]['dc_id'], per_hostpool_info['net_area_id']) }, "performance": { "mem_usage": _host_pool_cpu_mem_used['mem_used_per'], "vcpu_usage": _host_pool_cpu_mem_used['cpu_used_per'], "disk_usage": _host_pool_cpu_mem_used['disk_used_per'] }, "host_datas": _host_pool_cpu_mem_used['all_host_performance_datas'] } capacity_detail.append(host_pool_params) all_available_vm_count += _host_pool_cpu_mem_used['available_create_vm'] # TODO 维石之后取消 # net_set = [] # delete_set = [] # # for index, each in enumerate(capacity_detail): # net_area = each["net_area"] # if net_area in net_set: # delete_set.append(each) # else: # net_set.append(net_area) # for delete_each in delete_set: # capacity_detail.remove(delete_each) # TODO 结束 params = { "currentPage": int(page_num), "pageSize": int(page_size), "total": len(capacity_detail), "available_vm_count": all_available_vm_count, "available_ip_count": available_ip_count, "cluster_datas": capacity_detail } return json_helper.format_api_resp_msg_to_vishnu_resource(job_status=VsJobStatus.SUCCEED, detail=params)
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)
def instance_create_from_other_platform_with_ip(): ''' 外部平台虚拟机创建 :return: ''' _init_log('instanc_create_request_from_other_platform') data_from_other_platform = request.data logging.info(data_from_other_platform) data_requset = json_helper.loads(data_from_other_platform) image_name = data_requset['image'] vcpu = data_requset['vcpu'] mem_mb = data_requset['mem_MB'] disk_gb = data_requset['disk_GB'] count = data_requset['count'] sys_code = data_requset['sys_code'] opuser = data_requset['opUser'] taskid_vs = data_requset['taskid'] req_env = data_requset['env'] req_net_area = data_requset['net_area'] req_datacenter = data_requset['datacenter'] task_id_kvm = ins_s.generate_task_id() sys_opr_name = data_requset['Op_Main_Engineer_Primary'] sys_opr_id = data_requset['Op_Main_Engineer_Prim'] cluster_id = data_requset['cluster_id'] vip_needed = data_requset['vip_needed'] # 是否需要vip,0为不需要,1需要 vm_ip_info = data_requset['vm_info'] vip_info = data_requset['vip_info'] api_origin = data_requset[ 'apiOrigin'] # api名称,维石为vishnu, 软负载为sfslb, 其他的需要定义 # 前端暂时不是传虚拟机root密码过来 password = None app_info = data_requset['application_info'] # hostpool_id = int(data_requset['hostpool_id']) # 特殊类型应用,返回集群id hostpool_id = '' logging.info('task %s : check params start when create instance', task_id_kvm) if not taskid_vs or not api_origin: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='empty input of taskid or api_origin when create ' 'instance') # 判断工单是否为失败重做 check_job_data = { 'WHERE_AND': { '=': { 'taskid_api': taskid_vs }, }, } ret_job_num, ret_job_data = request_r_s.RequestRecordService( ).request_db_query_data(**check_job_data) if ret_job_num == 1: for _job_data in ret_job_data: if _job_data['task_status'] == '0': return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='task is now doing, wait a moment, ' 'do not repeat create') elif _job_data['task_status'] == '1': # 将request_record数据库表中“task_status”、“response_to_api”重置为0重启任务 update_db_time = get_datetime_str() _update_data = { 'task_status': '0', 'response_to_api': '0', 'finish_time': update_db_time, 'request_status_collect_time': update_db_time, } _where_data = { 'taskid_api': taskid_vs, } ret = request_r_s.RequestRecordService().update_request_status( _update_data, _where_data) if ret <= 0: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='update request status failed, ' 'please call kvm system manager ' 'or retry create again') return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.SUCCEED, detail='start to recreate vm') elif _job_data['task_status'] == '2': threads = [] # 将request_record数据库表中“task_status”、“response_to_api”重置为0重启任务 update_db_time = get_datetime_str() _update_data = { 'task_status': '0', 'response_to_api': '0', 'finish_time': update_db_time, 'request_status_collect_time': update_db_time, } _where_data = { 'taskid_api': taskid_vs, } ret = request_r_s.RequestRecordService().update_request_status( _update_data, _where_data) if ret <= 0: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='update request status failed, ' 'please call kvm system manager ' 'or retry create again') # 找到工单对应的虚拟机,发送task_id、request_id到kafka重新创建 ins_params = { 'WHERE_AND': { "=": { 'task_id': _job_data['taskid_kvm'], 'isdeleted': '0', 'status': '100' } }, } ins_num, ins_data = ins_s.InstanceService().query_data( **ins_params) if ins_num > 0: for per_ins_data in ins_data: kafka_send_thread = threading.Thread( target=instance_msg_send_to_kafka, args=( per_ins_data['task_id'], per_ins_data['request_id'], )) threads.append(kafka_send_thread) kafka_send_thread.start() # 判断多线程是否结束 for t in threads: t.join() return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.SUCCEED, detail='start to recreate vm') if api_origin == ApiOriginString.VISHNU: api_origin = ApiOrigin.VISHNU elif api_origin == ApiOriginString.SFSLB: api_origin = ApiOrigin.SFSLB elif api_origin == ApiOriginString.FWAF: api_origin = ApiOrigin.FWAF else: api_origin = ApiOrigin.VISHNU if vip_needed == '1' and len(vip_info) <= 0: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='empty input of vip datas when create instance') # 校验前端vip是否存在数据库中且ip为预保留状态 if vip_needed == '1': vip_available = 0 vip_info_list = [] for per_vip in vip_info: per_vip_info = ip_service.IPService().get_ip_by_ip_address( per_vip['ip']) if per_vip_info and per_vip_info[ 'status'] == IPStatus.PRE_ALLOCATION: vip_info_list.append(per_vip_info) vip_available += 1 if vip_available != len(vip_info): return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='vip nums from vishnu not equal apply vip nums ' 'when create instance') # 校验前端ip是否存在数据库中且ip为预保留状态 ip_available = 0 ip_info_list = [] for per_ip in vm_ip_info: per_ip_info = ip_service.IPService().get_ip_by_ip_address(per_ip['ip']) if per_ip_info and per_ip_info['status'] == IPStatus.PRE_ALLOCATION: ip_info_list.append(per_ip_info) ip_available += 1 if ip_available != int(count): return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='vm ip nums from vishnu not equal apply vm nums ' 'when create instance') # 获取ip对应的网段信息 segment_info = segment_service.SegmentService().get_segment_info( ip_info_list[0]['segment_id']) if not segment_info: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='can not find segment infomation for ip ' 'when create instance') # 根据维石平台输入的虚拟机cpu、内存选择模板 if not vcpu or not mem_mb: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='empty input of vcpu or mem_MB when create instance') flavor_query = flavor_service.get_flavor_by_vcpu_and_memory(vcpu, mem_mb) if not flavor_query: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='can not get flavor information when create instance') flavor_id = flavor_query['id'] # 根据维石平台输入的环境、网络区域查找对应的物理集群 if not req_env or not req_net_area: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='empty input of req_net_area or req_env ' 'when create instance') if not hostpool_id: hostpool_query = hostpool_service.get_hostpool_info_by_name( str(DataCenterTypeForVishnu.TYPE_DICT[req_env]), req_datacenter, req_net_area) if not hostpool_query: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='can not get host_pool information ' 'when create instance') hostpool_id = hostpool_query['hostpool_id'] # 根据维石平台输入的系统运维人员工号维护对应应用组信息 if not sys_opr_id or not cluster_id: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='empty input of sys_opr_name, sys_opr_id ' 'or cluster_id when create instance') ret_group, group_id = _user_group_check( str(DataCenterTypeForVishnu.TYPE_DICT[req_env]), sys_code, sys_opr_name, sys_opr_id, cluster_id) if not ret_group: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail=group_id) if not hostpool_id or not image_name or not flavor_id or not disk_gb or not group_id \ or not count or int(count) < 1: logging.error('task %s : params are invalid when create instance', task_id_kvm) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='empty input of image_name, disk_gb ' 'or count when create instance') if int(count) > int(INSTANCE_MAX_CREATE): logging.error( 'task %s : create count %s > max num %s when create instance', task_id_kvm, count, INSTANCE_MAX_CREATE) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='批量创建最大实例数不能超过32个') logging.info('task %s : check params successful when create instance', task_id_kvm) # 数据盘最少50GB # 这里只是一个数据盘,后面有多个数据盘 vm_disk_gb = int(disk_gb) if int(disk_gb) > DATA_DISK_GB else DATA_DISK_GB # 获取主机列表(不包括锁定、维护状态) logging.info( 'task %s : get all hosts in hostpool %s start when create instance', task_id_kvm, hostpool_id) all_hosts_nums, all_hosts_data = host_s.HostService( ).get_available_hosts_of_hostpool(hostpool_id) # 可用物理机数量不足 least_host_num = hostpool_service.HostPoolService().get_least_host_num( hostpool_id) if all_hosts_nums < least_host_num or all_hosts_nums < 1: logging.error( 'task %s : available host resource not enough when create instance', task_id_kvm) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='集群不够资源,无法创建实例') logging.info( 'task %s : get all hosts in hostpool %s successful, all hosts nums %s when create instance', task_id_kvm, hostpool_id, all_hosts_nums) # 过滤host logging.info('task %s : filter hosts start when create instance', task_id_kvm) hosts_after_filter = host_s_s.filter_hosts(all_hosts_data) if len(hosts_after_filter ) == 0 or len(hosts_after_filter) < least_host_num: logging.error('task %s : no available host when create instance', task_id_kvm) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='没有适合的主机,无法创建实例') logging.info('task %s : filter hosts successful when create instance', task_id_kvm) logging.info('task %s : get need info start when create instance', task_id_kvm) # 获取flavor信息 flavor_info = flavor_service.FlavorService().get_flavor_info(flavor_id) if not flavor_info: logging.error( 'task %s : flavor %s info not in db when create instance', task_id_kvm, flavor_id) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='实例规格数据有误,无法创建实例') # VM分配给HOST logging.info('task %s : match hosts start when create instance', task_id_kvm) vm = { "vcpu": flavor_info['vcpu'], "mem_MB": flavor_info['memory_mb'], "disk_GB": flavor_info['root_disk_gb'] + vm_disk_gb, # 系统盘加数据盘 "group_id": group_id, "count": count } host_list = host_s_s.match_hosts(hosts_after_filter, vm, least_host_num=least_host_num, max_disk=2000) host_len = len(host_list) if host_len == 0: logging.error( 'task %s : match host resource not enough when create instance', task_id_kvm) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='没有适合的主机,无法创建实例') logging.info('task %s : match hosts successful when create instance', task_id_kvm) # 获取hostpool的net area信息 hostpool_info = hostpool_service.HostPoolService().get_hostpool_info( hostpool_id) if not hostpool_info: logging.error( 'task %s : hostpool %s info not in db when create instance', task_id_kvm, hostpool_id) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='物理机池所属网络区域信息有误,无法创建实例') net_area_id = hostpool_info['net_area_id'] logging.info('task %s : get need info successful when create instance', task_id_kvm) # 组配额控制 logging.info('task %s : check group quota start when create instance', task_id_kvm) is_quota_enough, quota_msg = check_group_quota(group_id, flavor_info, vm_disk_gb, count) if not is_quota_enough: logging.error( 'task %s : group %s is no enough quota when create instance', task_id_kvm, group_id) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='资源组配额不足,无法创建实例') logging.info('task %s : check group quota successful when create instance', task_id_kvm) ips_list = ip_info_list segment_data = segment_info logging.info('task %s : check ip resource start when create instance', task_id_kvm) logging.info('task %s : get need 1 info start when create instance', task_id_kvm) # 获取镜像信息,一个image_name可能对应多个id image_nums, image_data = image_service.ImageService().get_images_by_name( image_name) if image_nums <= 0: logging.info('task %s : no image %s info in db when create instance', task_id_kvm, image_name) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='没有镜像资源,无法创建实例') # 获取集群所在的环境 vm_env = hostpool_service.get_env_of_hostpool(hostpool_id) # hostpool对应的机房名 dc_name = hostpool_service.get_dc_name_of_hostpool(hostpool_id) # 实例操作系统 instance_system = image_data[0]['system'] logging.info('task %s : get need 1 info successful when create instance', task_id_kvm) # 获取虚机名资源 logging.info( 'task %s : check instance name resource start when create instance', task_id_kvm) is_name_enough, instance_name_list = _check_instance_name_resource( vm_env, dc_name, instance_system, count) if not is_name_enough: logging.error( 'task %s : datacenter %s has no enough instance name resource', task_id_kvm, dc_name) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='主机名资源不足,无法创建实例') logging.info( 'task %s : check instance name resource successful when create instance', task_id_kvm) # 如果需要vip,分配第‘count + 1’个同时记录vip_info表格 if vip_needed == '1': for per_avalible_vip in vip_info_list: # 标记ip已使用 update_vip_data = {'status': IPStatus.USED} where_vip_data = {'id': per_avalible_vip['id']} ret_mark_ip = ip_service.IPService().update_ip_info( update_vip_data, where_vip_data) if ret_mark_ip <= 0: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail="标记ip为已使用状态失败,请重新申请") # 录入vip信息到数据库中 insert_vip_data = { 'ip_id': per_avalible_vip['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: return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail="录入ip信息失败,请联系系统管理员") # 挂载点 if instance_system == 'linux': mount_point = '/app' else: mount_point = 'E' logging.info('task %s : create thread start when create instance', task_id_kvm) user_id = get_user()['user_id'] all_threads = [] for i in range(int(count)): instance_name = str(instance_name_list[i]) ip_data = ips_list[i] # 轮询host index = i % host_len vm_host = host_list[index] create_ins_t = threading.Thread( target=_create_instance_info, args=(task_id_kvm, instance_name, app_info, sys_opr_id, password, flavor_id, group_id, vm_host, flavor_info, image_data, ip_data, vm_disk_gb, mount_point, instance_system, net_area_id, segment_data, vm_env, user_id, cluster_id), name='thread-instance-create-' + task_id_kvm) all_threads.append(create_ins_t) create_ins_t.start() for thread in all_threads: thread.join() logging.info('task %s : create thread successful when create instance', task_id_kvm) # 录入外应用的taskid到工单表格中 time_now_for_insert_request_to_db = get_datetime_str() request_info_data = { "taskid_api": taskid_vs, "api_origin": api_origin, "taskid_kvm": task_id_kvm, "vm_count": count, "user_id": opuser, "start_time": time_now_for_insert_request_to_db, "task_status": "0", # 代表任务执行中 "response_to_api": "0", "istraceing": "0", "request_status_collect_time": time_now_for_insert_request_to_db } request_record_db_ret = request_r_s.RequestRecordService( ).add_request_record_info(request_info_data) if request_record_db_ret.get('row_num') <= 0: logging.error( 'task %s : can not add request record information to db when create instance', task_id_kvm) return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.FAILED, detail='录入工单信息到数据库失败') return json_helper.format_api_resp_msg_to_vishnu( req_id=taskid_vs, job_status=VsJobStatus.SUCCEED, detail='start to create vm')
def instance_add_netcard_from_other_platform(): ''' kvm平台虚拟机添加网卡外部接口 入参说明: { "instanceMainIp": "虚拟机主网ip列表" "apiOrigin": "", "netCardType": "" } :return: ''' _init_log('instance_add_netcard_from_other_platform') logging.info(request.data) logging.info(request.values) logging.info(request.form) req_json = request.data req_data = json_helper.loads(req_json) instance_ip_list = req_data["instanceMainIp"] req_origin = req_data["apiOrigin"] netcard_type = req_data["netCardType"] # 判断需要配置网卡所有虚拟机是否存在 if not instance_ip_list or not req_origin or not netcard_type: return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED, detail='入参有空值,请检查') _ip_datas_list = [] instance_data_list = [] env_list = [] dc_list = [] net_area_list = [] ip_str = "" # 判断ip列表中是否有不存在于kvm平台的 for _ip in instance_ip_list: _instance_info = ip_s.get_instance_info_by_ip(_ip['ip']) if not _instance_info: ip_str += _ip['ip'] + " " else: _instance_params = { "instance_ip": _ip['ip'], "instance_uuid": _instance_info['instance_uuid'], "instance_id": _instance_info['instance_id'], "instance_name": _instance_info['instance_name'], "host_ip": _instance_info['host_ip'], "env": _instance_info['env'], "net_area": _instance_info['net_area_name'], "dc_name": _instance_info['datacenter_name'], } instance_data_list.append(_instance_params) env_list.append(_instance_info['env']) dc_list.append(_instance_info['datacenter_name']) net_area_list.append(_instance_info['net_area_name']) if ip_str: return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED, detail='ip:%s无法在kvm平台中找到' % ip_str) if len(set(env_list)) > 1: return json_helper.format_api_resp_msg( code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED, detail='需要配置网卡的虚拟机属于不同环境,不允许同时配置') if len(set(dc_list)) > 1: return json_helper.format_api_resp_msg( code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED, detail='需要配置网卡的虚拟机属于不同机房,不允许同时配置') if len(set(net_area_list)) > 1: return json_helper.format_api_resp_msg( code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED, detail='需要配置网卡的虚拟机属于不同网络区域,不允许同时配置') instance_str = "" instance_data_filter_list = [] # 查询指定虚拟机网卡数量,目前不能超过3块,同一类型网卡只能有一块 for _instance in instance_data_list: instance_same_netcard_type_str = "" instance_net_card = instance_s.get_net_info_of_instance( _instance['instance_id']) if instance_net_card: for _net_card in instance_net_card: if _net_card['segment_type'] == netcard_type: instance_same_netcard_type_str += _instance[ 'instance_ip'] + " " _ip_datas = { "instanceIp": _instance['instance_ip'], "nasIp": _net_card['ip_address'] } _ip_datas_list.append(_ip_datas) if not instance_same_netcard_type_str: instance_data_filter_list.append(_instance) if len(instance_net_card) >= INSTANCE_NETCARD_NUMS: instance_str += _instance['instance_ip'] + " " if instance_str: return json_helper.format_api_resp_msg( code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED, detail='虚拟机:%s网卡数量不能大于%s' % (ip_str, str(INSTANCE_NETCARD_NUMS))) # if instance_same_netcar_type_str: # return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED, # detail='虚拟机:%s已配置相同类型网卡,不可重复申请' % ip_str) if len(instance_data_filter_list) == 0: return json_helper.format_api_resp_msg(code=ErrorCode.SUCCESS, job_status=VsJobStatus.SUCCEED, detail=_ip_datas_list) # 判断虚拟机虚拟机是否开机中 instance_unstarting_str = "" for _instance in instance_data_filter_list: vm_status = vmManager.libvirt_instance_status( _instance['host_ip'], _instance['instance_name']) # 虚拟机开机状态才可以做网卡配置 if vm_status != VMLibvirtStatus.STARTUP: instance_unstarting_str += _instance['instance_ip'] + " " if instance_unstarting_str: return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED, detail='虚拟机:%s非运行中状态,无法添加网卡' % ip_str) # 识别需要创建的网卡类型并分配ip net_type = [ NetCardType.INTERNAL, NetCardType.INTERNEL_TELECOM, NetCardType.INTERNEL_UNICOM, NetCardType.INTERNAL_IMAGE, NetCardType.INTERNAL_NAS ] if netcard_type not in net_type: return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED, detail='KVM虚拟机没有网卡类型:%s ' % netcard_type) # 获取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('外部接口新增网卡分配ip:检查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: ret_segment_datas = segment_s.get_segments_data_by_type( net_area_list[0], dc_list[0], str(env_list[0]), str(netcard_type)) if not ret_segment_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='虚拟机所在网络区域没有指定网卡类型可用网段') # 获取可用ip并标记为已使用 ret_ip_status, ret_ip_data, ret_ip_msg = __check_ip_resource( ret_segment_datas, str(env_list[0]), len(instance_data_filter_list)) if not ret_ip_status: _change_db_ip_unused(ret_ip_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=ret_ip_msg) except Exception as e: _msg = '添加网卡外部接口:获取网段标记ip出现异常 %s: check ip resource exception when instance add nic from platform,err:%s' % ( ip_str, 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: _change_db_ip_unused(ret_ip_data) 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) error_msg = [] # 拼装虚拟机网卡信息用于配置网卡 i = 0 for _instance in instance_data_filter_list: mac = randomMAC() _instance['ip_addr_new'] = ret_ip_data[i]['ip_address'] _instance['mac_addr'] = mac i += 1 ret_status, ret_error_msg = __instance_add_netcard(_instance) if not ret_status: _msg = {"ip": _instance['instance_ip'], "error_msg": ret_error_msg} error_msg.append(_msg) else: _ip_datas = { "instanceIp": _instance['instance_ip'], "nasIp": _instance['ip_addr_new'] } _ip_datas_list.append(_ip_datas) if error_msg: return json_helper.format_api_resp_msg(code=ErrorCode.SYS_ERR, job_status=VsJobStatus.FAILED, detail=error_msg) return json_helper.format_api_resp_msg(code=ErrorCode.SUCCESS, job_status=VsJobStatus.SUCCEED, detail=_ip_datas_list)