def image_status_check(image_name,host_id): host_data = host_s.HostService().get_host_info(host_id) if not host_data: message = "获取host信息失败" return False, message res, image_data = im_s.ImageService().get_images_by_name_t(image_name) if not res: message = "获取镜像信息失败" return False, message image_local_md5,message = image_md5_get(host_data['ipaddress'],image_name) if not image_local_md5: return False,False,message else: res, image_data = im_s.ImageService().get_images_by_name_t(image_name) if not res: message = '镜像:%s不在远端镜像列表中' %image_name return False,'1',message else: image_remote_md5 = image_data[0]['md5'] if image_local_md5 == image_remote_md5: message = "镜像为最新" return True,'0',message else: message = "镜像需更新" return True,'1',message
def local_image_return(host_id): #获取host上当前的image清单 res1, local_image_list = get_host_local_image(host_id) local_image_return_list = [] #如果本地没有镜像 if not res1: return True,local_image_list #如果本地有镜像 else: #针对本地的每个镜像获取其是否为最新 for image in local_image_list: image_status_tag = False tag = 0 #重试3次获取是否最新 while not image_status_tag and tag < 3: image_status_tag, checktag, checkmsg = image_status_check(image, host_id) tag = tag +1 #获取镜像是否最新失败 if not image_status_tag: if checktag == '1': ret_msg = '本地镜像%s不在远端镜像服务器列表中' %image res_data = { 'image_info': image, 'msg': ret_msg, 'check_data': 'faile' } local_image_return_list.append(res_data) else: res_data = { 'image_info':image, 'msg':'获取镜像失败', 'check_data':'faile' } local_image_return_list.append(res_data) #获取镜像是否最新成功 else: #如果该image为最新,则只返回image的信息 if checktag == '0': res, image_data = im_s.ImageService().get_images_by_name_t(image) check_data = { 'image_info': image_data[0], 'check_data': checktag, 'msg': checkmsg } local_image_return_list.append(check_data) #如果该image非最新,则获取其任务状态并一并返回 else: res,image_info = im_s.ImageService().get_images_by_name_t(image) image_id = image_info[0]['id'] task_data = image_task_get(host_id,image_id) res, image_data = im_s.ImageService().get_images_by_name_t(image) check_data = { 'image_info': image_data[0], 'check_data': checktag, 'msg': checkmsg, 'task_info':task_data } local_image_return_list.append(check_data) return True,local_image_return_list
def add_image(): name = request.values.get('name') displayname = request.values.get('displayname') system = request.values.get('system') description = request.values.get('description') version = request.values.get('version') url = request.values.get('url') md5 = request.values.get('md5') format = request.values.get('format') actual_size_mb = request.values.get('actual_size_mb') size_gb = request.values.get('size_gb') type = request.values.get('type') if not name or not system or not url or not md5 or not format or not actual_size_mb or not size_gb or not type: logging.info('入参缺失') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg='入参缺失') # url唯一 image_db = image_service.ImageService().get_image_by_url(url) is_image = image_db[1] if is_image: logging.info('image url %s is duplicated when add image', url) return json_helper.format_api_resp(code=ErrorCode.DUPLICATED_ERR, msg="镜像路径不能重复") # 系统盘唯一判断 if type == '0': image_res = image_service.ImageService().image_sys_disk_confirm( name)[1] if image_res: logging.info('image sys disk is unique can not add more') return json_helper.format_api_resp(code=ErrorCode.DUPLICATED_ERR, msg="镜像系统盘唯一无法再添加") insert_data = { 'name': name, 'displayname': displayname, 'system': system, 'version': version, 'description': description, 'md5': md5, 'format': format, 'actual_size_mb': actual_size_mb, 'size_gb': size_gb, 'isdeleted': '0', 'created_at': get_datetime_str(), 'url': url, 'type': type, } ret = image_service.ImageService().add_image_info(insert_data) if ret.get('row_num') <= 0: logging.error("add image error, insert_data:%s", str(insert_data)) error_msg = "添加新镜像 %s 失败", str(insert_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def image_status_check(image_name, host_ip): image_dir = '/app/image/' + image_name check_file_exists, msg = ansibleCmdV2.check_file_exists(host_ip, image_dir) print 'remote image check result########################################' print check_file_exists, msg if check_file_exists: image_local_md5, message = ansibleCmdV2.image_md5_get( host_ip, image_name) print 'local image md5 get result############################' print image_local_md5 print message if not image_local_md5: return False, False, message else: res, image_data = im_s.ImageService().get_images_by_name_t( image_name) image_remote_md5 = image_data[0]['md5'] print 'remote image md5########################' print image_remote_md5 if image_local_md5 == image_remote_md5: message = "镜像为最新" return True, '0', message else: message = "镜像需更新" return True, '1', message else: message = "镜像需更新" return True, '1', message
def image_list(): params = { 'WHERE_AND': { '=': { 'isdeleted': '0', }, }, 'ORDER': [ ['id', 'desc'], ], 'PAGINATION': { 'page_size': request.values.get('page_size', 20), 'page_no': request.values.get('page_no', 1), } } total_nums, data = image_service.ImageService().query_data(**params) resp = ImageListResp() resp.total = total_nums for i in data: _image_info = image_info.ImageInfo().init_from_db(i) resp.rows.append(_image_info) return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data=resp.to_json())
def image_remote_list(host_id): #获取当前所有image的list image_num, image_total_list = image_list() remote_image_list = [] #获取当前本地image的list res, image_local_list = get_host_local_image(host_id) if not res: return False, image_local_list else: if image_local_list == []: remote_image_list = image_total_list return True, remote_image_list else: _local_imageid_list = [] #获取当前所有local_Image的id list for local_image in image_local_list: res, _local_image_info = im_s.ImageService( ).get_images_by_name_t(local_image) if res: _local_image_id = _local_image_info[0]['id'] _local_imageid_list.append(_local_image_id) #如果发现总的image中有id不在本地image list中,则加入remote_List for image in image_total_list: if image['id'] not in _local_imageid_list: remote_image_list.append(image) return True, remote_image_list
def _update_image_info(actual_size_mb, size_gb, md5, image_id): update_data = { 'actual_size_mb': actual_size_mb, 'size_gb': size_gb, 'md5': md5 } where_data = {'id': image_id} return image_service.ImageService().update_image_info( update_data, where_data)
def remote_image_list_ch(remote_image_list, task_image_list): remote_imageid_list = [] for remote_image_data in remote_image_list: remote_imageid = remote_image_data['id'] remote_imageid_list.append(str(remote_imageid)) for task_image_info in task_image_list: # 如果发现库中有任务的image在remote_image_list中 if task_image_info['image_id'] in remote_imageid_list: image_info = im_s.ImageService().get_image_info( task_image_info['image_id']) remote_image_list.remove(image_info) return remote_image_list
def image_list(): params = { 'WHERE_AND': { '=': { 'isdeleted': '0', }, }, } total_nums, data = im_s.ImageService().query_data(**params) image_total_list = [] for i in data: image_total_list.append(i) return total_nums, image_total_list
def check_image_status(host_ip, task_id): task_info = im_sy_s.ImageSyncService().get_image_sync_info(task_id) image_id = task_info['image_id'] image_info = im_s.ImageService().get_image_info(image_id) image_name = image_info['url'].split('/')[2] image_status_tag, checktag, checkmsg = image_status_check( image_name, host_ip) if not image_status_tag: return False, False else: #镜像最新返回'0' if checktag == '0': return True, '0' else: #镜像非最新返回'1' return True, '1'
def check_new_task_time(image_task_info, host_id, image_id): task_info_list = image_task_info['task_list'] task_num = len(task_info_list) new_task_time_list = [] image_info = im_s.ImageService().get_image_info(image_id) image_name = image_info['name'] image_descrp = image_info['description'] image_return_to_user = image_name + '(' + image_descrp + ')' # 如果存在结束时间大于开始时间则报错 for i in range(int(task_num)): task_starttime_str = task_info_list[i]['sch_starttime'] task_endtime_str = task_info_list[i]['sch_endtime'] task_starttime = datetime.strptime(task_starttime_str, "%Y-%m-%d %X") task_endtime = datetime.strptime(task_endtime_str, "%Y-%m-%d %X") if task_starttime > task_endtime: err_msg = '计划任务的结束时间大于开始时间,相关镜像为 %s 错误的开始时间为 %s ' \ '错误的结束时间为 %s' %(image_return_to_user,task_starttime_str,task_endtime_str) err_data = { 'image_task': image_task_info, 'error_message': err_msg } return False, err_data else: new_task_time_list.append(task_starttime) new_task_time_list.append(task_endtime) #判断当前库中是否有running的任务时间点与新增有冲突 image_ondo_task_list = image_task_get(host_id, image_id) if image_ondo_task_list == []: return True, 'success' else: #针对新增任务的每个时间点,对表中的每个running task做时间冲突的判断 for image_ondo_task in image_ondo_task_list: imagetask_starttime = image_ondo_task['sch_starttime'] imagetask_endtime = image_ondo_task['sch_endtime'] for new_task_time in new_task_time_list: res = Checktime(imagetask_starttime, imagetask_endtime, new_task_time) if res: task_starttime_to_user = imagetask_starttime.strftime( "%Y-%m-%d %X") task_endtime_to_user = imagetask_endtime.strftime( "%Y-%m-%d %X") msg = '新增计划的时间与当前在运行的任务时间有冲突,' \ '相关镜像为 %s,与库中存在的时间段为%s %s 的任务有冲突' %(image_return_to_user,task_starttime_to_user,task_endtime_to_user) return False, msg return True, 'success'
def local_image_list_ch(host_id,local_image_list,task_image_list): local_imageid_list = [] for local_image_data in local_image_list: if local_image_data['check_data'] != 'faile': local_image_info = local_image_data['image_info'] local_imageid = local_image_info['id'] local_imageid_list.append(str(local_imageid)) for task_image_info in task_image_list: #如果发现库中有任务的image不在当前host上 if task_image_info['image_id'] not in local_imageid_list: #获取其任务信息并装填入local_image_list中 task_data = image_task_get(host_id, task_image_info['image_id']) image_info = im_s.ImageService().get_image_info(task_image_info['image_id']) checkmsg = '库中已有任务,本地尚无镜像' check_data = { 'image_info': image_info, 'check_data': '1', 'msg': checkmsg, 'task_info': task_data } local_image_list.append(check_data) return local_image_list
def local_image_list_return(local_image_list,image_list,host_id): return_list = [] for local_image_data in local_image_list: if local_image_data['image_info']['id'] in image_list: insert_data = { 'image_data':local_image_data, 'image_id':local_image_data['image_info']['id'], 'new':'1' } return_list.append(insert_data) image_list.remove(local_image_data['image_info']['id']) if len(image_list) == 0: return True,return_list else: for image_id in image_list: image_info = im_s.ImageService().get_image_info(image_id) insert_data = { 'image_data':image_info, 'image_id':image_id, 'new':'0' } return_list.append(insert_data) return True,return_list
def image_create_exist_init(): # 根据已有镜像生成镜像的初始值接口 params = { 'WHERE_AND': { 'in': { 'system': ['linux', 'windows'] }, }, 'ORDER': [ ['id', 'desc'], ], } ret = image_service.ImageService().query_data(**params) ret_new = ret[1] for i in ret_new: for y in i.keys(): if y != 'system' and y != 'version' and y != 'name' and y != 'tag' and y != 'displayname': del i[y] news_ids = [] for id in ret_new: if id not in news_ids: news_ids.append(id) return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data=news_ids)
def image_release_by_exist(): # 发布已有模板的镜像 ''' image_info_list = [{'actual_size_mb':1200.8, 'md5':'32234234234342'}] :return: ''' name = request.values.get('name') if not name: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='入参缺失') image_manage_data = im_s.ImageManageService().get_img_manage_data_by_name( name) create_type = image_manage_data[1]['create_type'] # 判断当前image状态是否正常 image_manage_stat = image_manage_data[1]["status"] if image_manage_stat != ImageManage.CHECKOUT: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='当前模板机状态不允许此操作') # 更新image_manage状态为发布中 message = '' eimage_name = name im_s.ImageManageService().update_image_manage_status( eimage_name, message, ImageManage.RELEASING) image_info_list = image_disk_md5_together(name) # 获取镜像文件的list res, image_list_info = ansibleCmdV2.get_image_disk_list( IMAGE_EDIT_SERVER, eimage_name) update_action = im_m_act.RELEASE_IMGSERVER if not res: # 更新image_manage表和iamge_update_status error_msg = image_list_info state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, message) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) image_disk_list = list(image_list_info) # 更新镜像服务器 ret, message = img_server_update_img(eimage_name, image_disk_list, create_type) if not ret: error_msg = message state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, error_msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) if create_type == image_ceate_type.ALL_NEW or create_type == image_ceate_type.FROM_EXIST: pass else: # 更新镜像缓存服务器 ret, message = img_cache_server_update_img(eimage_name, image_disk_list) update_action = im_m_act.RELEASE_CACHESERVER if not ret: error_msg = message state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, error_msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) # 更新db for index, i in enumerate(image_info_list): if index == 0: url_i = ('/' + name) * 2 else: url_i = ('/' + name) * 2 + '_disk' + str(index + 1) update_data = { 'md5': i['md5'], 'actual_size_mb': i['actual_size_mb'], 'updated_at': get_datetime_str(), } where_data = { 'url': url_i, } ret = im_s.ImageService().update_image_info(update_data, where_data) if ret < 0: logging.error("release image error, update_data:%s", str(update_data)) error_msg = "发布镜像 %s 失败,更新image表信息失败", str(update_data) state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, error_msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) update_data = { 'status': ImageManage.USABLE, 'create_type': image_ceate_type.USING } where_data = {'eimage_name': name} change_status = im_s.ImageManageService().update_image_info( update_data, where_data) if change_status < 0: logging.error("release image error, update_data:%s", str(update_data)) error_msg = "发布镜像 %s 失败,更新image_manage表信息失败" % eimage_name state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, error_msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) state_tag = im_m_act_sta.SUCCESSED message = '发布成功' im_s.ImageStatusService().add_image_status_action(eimage_name, update_action, state_tag, message) return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def host_image_task_intodb(): #获取单台host的入库信息 front_data = request.get_data() front_data_dict = json.loads(front_data) host_id = front_data_dict['host_id'] image_list = front_data_dict['image_list'] if not host_id or not image_list: err_msg = '入参缺失' return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=err_msg) #判断host_id是否异常 host_data = host_s.HostService().get_host_info(host_id) host_ip = host_data['ipaddress'] if not host_data: err_msg = '获取host信息失败' return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=err_msg) #定义两个list来存成功的image_task和失败的image_task correct_image_task_list = [] error_image_task_list = [] # #判断前台发来的image_list总长度不能大于7 # image_list_num = len(image_list) # if int(image_list_num) > 7 : # err_msg = 'image任务数量不能大于7' # return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=err_msg) #判断前台传输的image id信息是否有重复值 image_id_rep_check = image_id_check_rep(image_list) if not image_id_rep_check: err_msg = '同步任务中出现重复的image id记录' return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=err_msg) # 判断镜像信息是否异常 for image_task_info in image_list: image_id = image_task_info['image_id'] image_info = im_s.ImageService().get_image_info(image_id) #如果判断image_id异常 if not image_info: err_msg = '获取镜像id为' + image_id + '信息失败' err_data = { 'image_task': image_task_info, 'error_message': err_msg } error_image_task_list.append(err_data) image_list.remove(image_task_info) else: #判断新增任务时间是否异常 res, msg = check_new_task_time(image_task_info, host_id, image_id) if not res: err_msg = msg err_data = { 'image_task': image_task_info, 'error_message': err_msg } error_image_task_list.append(err_data) image_list.remove(image_task_info) print 1 #针对check后的任务清单做入库处理 for image_task_info in image_list: # 判断任务是新增还是加入计划任务 image_id = image_task_info['image_id'] image_task_ondo = im_sy_s.get_ondo_task(host_ip, image_id) #如果为新增任务 if not image_task_ondo: task_start_time_str = image_task_info['start_time'] task_start_time = datetime.strptime(task_start_time_str, "%Y-%m-%d %X") task_info_list = image_task_info['task_list'] task_num = len(task_info_list) #判断计划任务数是否大于7 if task_num > 7: image_info = im_s.ImageService().get_image_info(image_id) image_name = image_info['name'] image_descrp = image_info['description'] err_msg = '该image ' + image_name + ' ' + image_descrp + ' 所添加的计划任务数量大于7' err_data = { 'error_message': err_msg, 'image_task': image_task_info } error_image_task_list.append(err_data) image_list.remove(image_task_info) speed_limit = image_task_info['speed_limit'] host_ip = host_s.HostService().get_host_info(host_id)['ipaddress'] #将每个image_task入image_sync_task表 insert_data = { 'image_id': image_id, 'host_ip': host_ip, 'status': '0', 'type': '1', 'schedule_num': task_num, 'start_time': task_start_time, 'isdeleted': '0', 'on_task': '0', 'speed_limit': speed_limit, 'process_id': 'undefined' } res1 = im_sy_s.ImageSyncService().add_image_sync_task(insert_data) if not res1: message = '插入image_sync_task表失败' err_data = { 'image_task': image_task_info, 'error_message': message } error_image_task_list.append(err_data) image_list.remove(image_task_info) #如入image_sync_task表成功,则继续入image_sync_schedult表 else: image_sync_task_id = res1.get('last_id') for sch_task in task_info_list: sch_starttime_str = sch_task['sch_starttime'] sch_endtime_str = sch_task['sch_endtime'] sch_starttime = datetime.strptime(sch_starttime_str, "%Y-%m-%d %X") sch_endtime = datetime.strptime(sch_endtime_str, "%Y-%m-%d %X") insert_data = { 'image_task_id': image_sync_task_id, 'sch_state': '0', 'sch_starttime': sch_starttime, 'sch_endtime': sch_endtime, 'isdeleted': '0' } res = im_sy_sch.ImageSyncScheduleService( ).add_image_sync_sch(insert_data) #如果入库失败则跳出循环并将上步入库的task_sync表的isdeleted置为1 if not res: where_data = {'id': image_sync_task_id} update_data = {'isdeleted': '1'} im_sy_s.ImageSyncService().update_image_sync_task( update_data, where_data) err_msg = '插入计划任务失败' err_data = { 'error_message': err_msg, 'image_task': image_task_info } error_image_task_list.append(err_data) image_list.remove(image_task_info) error_image_task_list.append(err_data) break #如果已存在image_id,只是新增计划任务 else: #获取当前image_id下在running的计划任务数 image_sync_task_id = image_task_ondo[0]['id'] sch_ondo_num, sch_ondo_data = im_sy_sch.get_ondo_sch_list( image_sync_task_id) #判断前台输入的image任务数量是否大于当前可添加的数量 sch_add_num = len(image_task_info['task_list']) if sch_add_num + sch_ondo_num > 7: image_info = im_s.ImageService().get_image_info(image_id) image_name = image_info['name'] image_descrp = image_info['description'] message = '镜像' + image_name + ' ' + image_descrp + '可添加任务数量大于最大值' err_data = { 'image_task': image_task_info, 'error_message': message } error_image_task_list.append(err_data) image_list.remove(image_task_info) #如果前台输入的计划任务数量不超过最大值则入库 else: task_info_list = image_task_info['task_list'] for sch_task in task_info_list: sch_starttime_str = sch_task['sch_starttime'] sch_endtime_str = sch_task['sch_endtime'] sch_starttime = datetime.strptime(sch_starttime_str, "%Y-%m-%d %X") sch_endtime = datetime.strptime(sch_endtime_str, "%Y-%m-%d %X") insert_data = { 'image_task_id': image_sync_task_id, 'sch_state': '0', 'sch_starttime': sch_starttime, 'sch_endtime': sch_endtime, 'isdeleted': '0' } im_sy_sch.ImageSyncScheduleService().add_image_sync_sch( insert_data) #统计总的入库成功list和失败list并返回给前台 for image_task in image_list: correct_image_task_list.append(image_task) #计算总的失败数 total_image_task_num = len(image_list) total_fail_task_num = len(error_image_task_list) if total_image_task_num == 0: tag = ErrorCode.ALL_FAIL else: tag = ErrorCode.SUCCESS return_data = { 'fail_task_num': str(total_fail_task_num), 'fail_task_list': error_image_task_list, 'succss_task_list': correct_image_task_list } return json_helper.format_api_resp(code=tag, data=return_data)
def instance_create(hostpool_id): ''' 创建虚机 :param hostpool_id: :return: ''' image_name = request.values.get('image_name') flavor_id = request.values.get('flavor_id') disk_gb = request.values.get('disk_gb') count = request.values.get('count') app_info = request.values.get('app_info') group_id = request.values.get('group_id') owner = request.values.get('owner') password = request.values.get('password') task_id = ins_s.generate_task_id() logging.info( '创建VM 步骤1:检查参数 task %s : check params start when create instance', task_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( '创建VM 步骤1:检查参数失败 参数错误 task %s : params are invalid when create instance', task_id) return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg='参数错误') if int(count) > int(INSTANCE_MAX_CREATE): logging.error( '创建VM 步骤1:检查参数失败 批量创建数超过最大数 ' 'task %s : create count %s > max num %s when create instance', task_id, count, INSTANCE_MAX_CREATE) return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg='批量创建最大实例数不能超过' + INSTANCE_MAX_CREATE + '个') owner_exist = user_s.UserService().check_userid_exist(owner) if not owner_exist: logging.error( '创建VM 步骤1:检查参数失败 应用管理员工号不存在 ' 'task %s : no such user %s in db when create instance', task_id, owner) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='应用管理员工号不存在,无法创建实例') logging.info( '创建VM 步骤1:检查参数成功 task %s : check params successful when create instance', task_id) # 数据盘最少50GB # todo:这里只是一个数据盘,后面有多个数据盘 vm_disk_gb = int(disk_gb) if int(disk_gb) > DATA_DISK_GB else DATA_DISK_GB # 获取主机列表(不包括锁定、维护状态) logging.info( '创建VM 步骤2:获取集群所有HOST列表 ' 'task %s : get all hosts in hostpool %s start when create instance', task_id, 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( '创建VM 步骤2:获取集群所有HOST列表失败 集群不够资源 ' 'task %s : available host resource not enough when create instance', task_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='集群不够资源,无法创建实例') logging.info( '创建VM 步骤2:获取集群所有HOST列表成功,总host数:%s ' 'task %s : get all hosts in hostpool %s successful, all hosts nums %s when create instance', all_hosts_nums, task_id, hostpool_id, all_hosts_nums) # 过滤host logging.info( '创建VM 步骤3:HOST过滤 task %s : filter hosts start when create instance', task_id) 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( '创建VM 步骤3:HOST过滤失败 没有合适主机 ' 'task %s : no available host when create instance', task_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='集群物理机资源无法满足你的申请需求,请联系系统组同事') logging.info( '创建VM 步骤3:HOST过滤成功 task %s : filter hosts successful when create instance', task_id) # 获取flavor信息 logging.info( '创建VM 步骤4:获取必需信息 task %s : get need info start when create instance', task_id) flavor_info = flavor_service.FlavorService().get_flavor_info(flavor_id) if not flavor_info: logging.error( '创建VM 步骤4:获取必需信息失败 实例规格数据有误 ' 'task %s : flavor %s info not in db when create instance', task_id, flavor_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='实例规格数据有误,无法创建实例') # VM分配给HOST logging.info( '创建VM 步骤5:HOST分配 task %s : match hosts start when create instance', task_id) 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( '创建VM 步骤5:HOST分配失败 没有合适主机 ' 'task %s : match host resource not enough when create instance', task_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='集群物理机资源无法满足你的申请需求,请联系系统组同事') logging.info( '创建VM 步骤5:HOST分配成功 task %s : match hosts successful when create instance', task_id) # 获取hostpool的net area信息 hostpool_info = hostpool_service.HostPoolService().get_hostpool_info( hostpool_id) if not hostpool_info: logging.error( '创建VM 步骤6:获取必需信息失败 物理机池所属网络区域信息有误 ' 'task %s : hostpool %s info not in db when create instance', task_id, hostpool_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='物理机池所属网络区域信息有误,无法创建实例') net_area_id = hostpool_info['net_area_id'] logging.info( '创建VM 步骤6:获取必需信息成功 task %s : get need info successful when create instance', task_id) # 组配额控制 logging.info( '创建VM 步骤7:检查组配额 task %s : check group quota start when create instance', task_id) is_quota_enough, quota_msg = check_group_quota(group_id, flavor_info, vm_disk_gb, count) if not is_quota_enough: logging.error( '创建VM 步骤7:检查组配额失败 配额不足 ' 'task %s : group %s is no enough quota when create instance', task_id, group_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=quota_msg) logging.info( '创建VM 步骤7:检查组配额成功 task %s : check group quota successful when create instance', task_id) logging.info( '创建VM 步骤8:获取必需信息 task %s : get need 1 info start when create instance', task_id) # 获取镜像信息,一个image_name可能对应多个id image_nums, image_data = image_service.ImageService().get_images_by_name( image_name) if image_nums <= 0: logging.info( '创建VM 步骤8:获取必需信息失败 镜像资源不足 ' 'task %s : no image %s info in db when create instance', task_id, image_name) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='没有镜像资源,无法创建实例') # 实例操作系统 instance_system = image_data[0]['system'] logging.info( '创建VM 步骤8:获取必需信息成功 ' 'task %s : get need 1 info successful when create instance', task_id) # 获取集群所在的环境 vm_env = hostpool_service.get_env_of_hostpool(hostpool_id) # hostpool对应的机房名 dc_name = hostpool_service.get_dc_name_of_hostpool(hostpool_id) # 获取集群所在网络区域名 net_area_name = hostpool_service.get_level_info_by_id(hostpool_id).get( 'net_area_name', '') # 获取虚机名资源 logging.info( '创建VM 步骤9:获取主机名资源 ' 'task %s : check instance name resource start when create instance', task_id) is_name_enough, instance_name_list = _check_instance_name_resource( vm_env, dc_name, instance_system, count) if not is_name_enough: logging.error( '创建VM 步骤9:获取主机名资源失败 主机名资源不足 ' 'task %s : datacenter %s has no enough instance name resource', task_id, dc_name) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='主机名资源不足,无法创建实例') logging.info( '创建VM 步骤9:获取主机名资源成功 ' 'task %s : check instance name resource successful when create instance', task_id) # 获取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( '创建VM 步骤10:检查IP时无法获取资源锁状态' 'task %s : check ip resource can not get lock', task_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='检查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(code=ErrorCode.SYS_ERR, msg=ret_ip_lock_used_datas) try: ret_ips_status, ret_ips_data, ret_segment = __check_ip_resource( vm_env, dc_name, net_area_name, count) except Exception as e: _msg = '创建VM 步骤10:检查IP资源是否足够出现异常task_id %s: check ip resource exception when instance create,err:%s' % ( task_id, 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) if not ret_ips_status: 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=ret_ips_data) # 更新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(code=ErrorCode.SYS_ERR, msg=ret_ip_lock_unused_datas) ips_list = ret_ips_data segment_data = ret_segment logging.info( '创建VM 步骤10:检查IP资源成功 task %s : check ip resource successful when create instance', task_id) # 挂载点 if instance_system == 'linux': mount_point = '/app' else: mount_point = 'E' logging.info( '创建VM 步骤11:多线程发送创建信息 task %s : create thread start when create instance', task_id) 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, instance_name, app_info, owner, 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), name='thread-instance-create-' + task_id) all_threads.append(create_ins_t) create_ins_t.start() for thread in all_threads: thread.join() logging.info( '创建VM 步骤11:多线程发送创建信息成功 ' 'task %s : create thread successful when create instance', task_id) return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def instance_msg_send_to_kafka(task_id, request_id): ''' 通过传入的task_id, request_id拼凑消息发送kafka,可供外部接口调用 :param request_id: :return: ''' _ins_info = ins_s.InstanceService().get_instance_info_by_requestid(request_id) if not _ins_info: return logging.error('task %s : can not find instance info ' 'when retry create instance send kafka msg', task_id) if _ins_info['isdeleted'] == '1': return logging.error('task %s : instance has been deleted ' 'when retry create instance send kafka msg', task_id) _ins_host_ip = ins_s.get_hostip_of_instance(_ins_info['id']) _ins_hostpool_db_info = ins_s.get_hostpool_of_instance(_ins_info['id']) _ins_flavor_db_info = ins_s.get_flavor_of_instance(_ins_info['id']) if not _ins_host_ip or not _ins_hostpool_db_info or not _ins_flavor_db_info: return logging.error('task %s : instance host, hostpool or flavor information' 'when retry create instance send kafka msg', task_id) # 获取虚拟机数据盘大小 ret_disk_status, vm_disk_gb = ins_s.get_data_disk_size_of_instance(_ins_info['id']) if not ret_disk_status: return logging.error('task %s : instance data disk size can not find' 'when retry create instance send kafka msg', task_id) # 获取虚拟机对应网段信息 segment_data = ins_s.get_net_segment_info_of_instance(_ins_info['id']) if not segment_data: return logging.error('task %s : instance segment information can not find' 'when retry create instance send kafka msg', task_id) # 获取虚拟机所在机房类型 vm_env = hostpool_service.get_env_of_hostpool(_ins_hostpool_db_info['id']) if not vm_env: return logging.error('task %s : instance env information can not find' 'when retry create instance send kafka msg', task_id) ins_images = ins_s.get_images_of_instance(_ins_info['id']) if not ins_images: return logging.error('task %s : instance image information can not find' 'when retry create instance send kafka msg', task_id) else: instance_system = ins_images[0]['system'] image_name = ins_images[0]['name'] # 获取镜像信息,一个image_name可能对应多个id image_nums, image_data = image_service.ImageService().get_images_by_name(image_name) if image_nums <= 0: return logging.error('task %s : instance image information can not find' 'when retry create instance send kafka msg', task_id) # 拼装消息需要的镜像信息 image_list = [] # 数据盘数量 data_image_num = 0 for _image in image_data: _image_type = _image['type'] _info = { "disk_format": _image['format'], "url": _image['url'], "image_size_gb": _image['size_gb'] # 镜像预分配大小 } # 系统盘 if _image_type == ImageType.SYSTEMDISK: _disk_name = _ins_info['name'] + '.img' _info['image_dir_path'] = '/app/image/' + _ins_info['uuid'] + '/' + _disk_name _info['disk_name'] = _disk_name _info['disk_size_gb'] = None _info['dev_name'] = 'vda' else: # 数据盘 _disk_name = _ins_info['name'] + '.disk' + str(data_image_num + 1) _disk_dev_name = _get_vd_map(data_image_num) _info['image_dir_path'] = '/app/image/' + _ins_info['uuid'] + '/' + _disk_name _info['disk_name'] = _disk_name _info['disk_size_gb'] = int(vm_disk_gb) _info['dev_name'] = _disk_dev_name data_image_num += 1 image_list.append(_info) # 发送异步消息到队列 data = { "routing_key": "INSTANCE.CREATE", "send_time": get_datetime_str(), "data": { "task_id": task_id, "request_id": request_id, "host_ip": _ins_host_ip, "uuid": _ins_info['uuid'], "hostname": _ins_info['name'], # 实例名 "memory_mb": _ins_flavor_db_info['memory_mb'], "vcpu": _ins_flavor_db_info['vcpu'], "ostype": instance_system, "user_id": _ins_info['owner'], "disks": image_list, "disk_size": int(vm_disk_gb), "image_name": image_name, "net_area_id": segment_data['net_area_id'], "networks": [ { "net_card_name": "br_bond0." + segment_data['vlan'], "ip": segment_data['ip_address'], "netmask": segment_data['netmask'], "dns1": segment_data['dns1'], "dns2": segment_data['dns2'], "mac": segment_data['mac'], "gateway": segment_data['gateway_ip'], "env": vm_env # SIT STG PRD DR } ] } } ret_kafka = send_async_msg(KAFKA_TOPIC_NAME, data) # 修改虚拟机状态为创建中 update_data = { 'status': VMStatus.CREATING, 'created_at': get_datetime_str(), 'updated_at': get_datetime_str() } where_data = { 'uuid': _ins_info['uuid'] } ins_s.InstanceService().update_instance_info(update_data, where_data) return 'all done'
def image_update_by_exist(): eimage_name = request.values.get('eimage_name') displayname = request.values.get('displayname') version = request.values.get('version') template_ostype = request.values.get('os_type') tag = randomUUID() if not eimage_name or not displayname or not version or not template_ostype: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='入参缺失') # 判断当前image表是否有该镜像信息 image_nums, image_data = image_service.ImageService().get_images_by_name( eimage_name) if not image_data: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='image表不存在此镜像') # 判断当前image_manage表是否有同名镜像 eimage_data = image_service.ImageManageService( ).get_image_manage_info_by_name(eimage_name) if eimage_data: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='image_manage表已存在同名镜像') # 获取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('创建新镜像 %s 失败:检查IP时无法获取资源锁状态') % eimage_name return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='检查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(code=ErrorCode.SYS_ERR, msg=ret_ip_lock_used_datas) try: ret_ips_status, ret_ips_data = __check_ip_resource() except Exception as e: _msg = '已有镜像补录:判断IP资源是否足够出现异常 : check ip resource exception when image update by exist ,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) if not ret_ips_status: 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=ret_ips_data) # 更新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(code=ErrorCode.SYS_ERR, msg=ret_ip_lock_unused_datas) ip_data = ret_ips_data message = '模板机 %s 创建预分配IP成功' % eimage_name logging.info(message) # 在镜像编辑服务器上创建相应文件夹 dest_dir = '/app/image/' + eimage_name ret, msg = ansibleCmdV2.create_destdir(IMAGE_EDIT_SERVER, dest_dir) if not ret: logging.error(msg) _set_ip_init(ip_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=msg) # 获取新镜像文件的list到镜像编辑服务器 ret, message = im_man_act._img_create_from_exist(eimage_name, eimage_name) if not ret: logging.error(message) _set_ip_init(ip_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=message) # 模板机define ret, message = im_man_act._img_tem_define(eimage_name) if not ret: logging.error(message) _set_ip_init(ip_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=message) # 根据已有镜像生成镜像的接口 insert_data = { 'eimage_name': eimage_name, 'displayname': displayname, # status=-1:初始化;0:使用中;1:编辑中;2:待发布 'status': ImageManage.INIT, 'related_image_tag': tag, 'version': version, # 根据已有的镜像创建,template_status只默认1 'template_status': img_tmp_status.SHUTDOWN, 'template_vm_ip': ip_data['ip_address'], 'message': '创建完成', 'create_type': image_ceate_type.UPDATE_EXIST, 'create_time': get_datetime_str(), 'os_type': template_ostype, } ret = image_service.ImageManageService().add_image_info(insert_data) if ret.get('row_num') <= 0: logging.error("add image error, insert_data:%s", str(insert_data)) error_msg = "添加新镜像 %s 失败", str(insert_data) _set_ip_init(ip_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def image_create_new(): eimage_name = request.values.get('image_name') displayname = request.values.get('displayname') template_ostype = request.values.get('os_type') version = request.values.get('version') if not eimage_name or not displayname or not version or not template_ostype: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='入参缺失') # 判断当前image表是否有同名镜像 image_nums, image_data = image_service.ImageService().get_images_by_name( eimage_name) if image_data: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='image表已存在同名镜像') # 判断当前image_manage表是否有同名镜像 eimage_data = image_service.ImageManageService( ).get_image_manage_info_by_name(eimage_name) if eimage_data: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='image_manage表已存在同名镜像') # 获取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('创建新镜像 %s 失败:检查IP时无法获取资源锁状态') % eimage_name return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='检查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(code=ErrorCode.SYS_ERR, msg=ret_ip_lock_used_datas) try: ret_ips_status, ret_ips_data = __check_ip_resource() except Exception as e: _msg = '创建全新镜像:判断IP资源是否足够出现异常 : check ip resource exception when create new image ,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) if not ret_ips_status: 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=ret_ips_data) # 更新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(code=ErrorCode.SYS_ERR, msg=ret_ip_lock_unused_datas) #segment_data = segment_s.SegmentService().get_segment_for_img_tmp() ip_data = ret_ips_data message = '模板机 %s 创建预分配IP成功' % eimage_name logging.info(message) # 模板机define ret, message = im_man_act._img_tem_define(eimage_name) if not ret: logging.error(message) # 将预分频的ip释放 _set_ip_init(ip_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=message) tag = randomUUID() # 添加信息到image_manage表 insert_data = { 'eimage_name': eimage_name, 'displayname': displayname, # status=-1:初始化;0:使用中;1:编辑中;2:待发布 'status': ImageManage.INIT, 'related_image_tag': tag, 'os_type': template_ostype, 'version': version, #创建全新镜像,template_status值默认1 'template_status': img_tmp_status.SHUTDOWN, 'template_vm_ip': ip_data['ip_address'], 'message': '创建完成', 'create_type': image_ceate_type.ALL_NEW, 'create_time': get_datetime_str() } # 创建全新的镜像 ret = image_service.ImageManageService().add_image_info(insert_data) if ret.get('row_num') <= 0: logging.error("add image error, insert_data:%s", str(insert_data)) error_msg = "添加新镜像 %s 失败", str(insert_data) _set_ip_init(ip_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def image_release_by_new(): name = request.values.get('name') displayname = request.values.get('displayname'), system = request.values.get('system'), version = request.values.get('version') image_manage_data = im_s.ImageManageService().get_img_manage_data_by_name( name) create_type = image_manage_data[1]['create_type'] if not name or not displayname or not system or not version: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='入参缺失') # 判断当前image状态是否正常 image_manage_stat = image_manage_data[1]["status"] if image_manage_stat != ImageManage.CHECKOUT: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='当前模板机状态不允许此操作') # 更新image_manage状态为发布中 message = '' eimage_name = name im_s.ImageManageService().update_image_manage_status( eimage_name, message, ImageManage.RELEASING) image_info_list = image_disk_md5_together(name) # 获取镜像文件的list res, image_list_info = ansibleCmdV2.get_image_disk_list( IMAGE_EDIT_SERVER, eimage_name) update_action = im_m_act.RELEASE_IMGSERVER if not res: # 更新image_manage表和image_update_status error_msg = image_list_info state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, message) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) image_disk_list = list(image_list_info) # 更新镜像服务器 ret, message = img_server_update_img(eimage_name, image_disk_list, create_type) if not ret: error_msg = message state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, error_msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) # 如果为全新创建则跳过更新缓存服务器 if create_type == image_ceate_type.ALL_NEW or create_type == image_ceate_type.FROM_EXIST: pass else: # 更新镜像缓存服务器 ret, message = img_cache_server_update_img(eimage_name, image_disk_list) update_action = im_m_act.RELEASE_CACHESERVER if not ret: error_msg = message state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, error_msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) # 更新db tag = randomUUID() # 如果类型为现有补录,则update image表 if create_type == image_ceate_type.UPDATE_EXIST: for index, i in enumerate(image_info_list): if index == 0: url_i = ('/' + name) * 2 else: url_i = ('/' + name) * 2 + '_disk' + str(index + 1) update_data = { 'md5': i['md5'], 'actual_size_mb': i['actual_size_mb'], 'tag': tag, 'updated_at': get_datetime_str(), } where_data = { 'url': url_i, } ret = im_s.ImageService().update_image_info( update_data, where_data) if ret < 0: logging.error("release image error, update_data:%s", str(update_data)) error_msg = "发布镜像 %s 失败,更新image表信息失败", str(update_data) state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, error_msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) # 新建镜像则add image表记录 else: for index, i in enumerate(image_info_list): if index == 0: url_i = ('/' + name) * 2 # image_info_list中第一个数据是系统盘 type = '0' description = u'系统盘' size_gb = get_image_size_gb(name, name) else: url_i = ('/' + name) * 2 + '_disk' + str(index + 1) name_i = name + '_disk' + str(index + 1) type = '1' description = u'数据盘' size_gb = get_image_size_gb(name, name_i) insert_data = { 'name': name, 'displayname': displayname, 'system': system, 'version': version, 'description': description, 'md5': i['md5'], 'format': 'qcow2', 'actual_size_mb': i['actual_size_mb'], 'size_gb': size_gb, 'isdeleted': '0', 'created_at': get_datetime_str(), 'url': url_i, 'type': type, # todo;uuid 'tag': tag, } ret = im_s.ImageService().add_image_info(insert_data) if ret.get('row_num') <= 0: logging.error("add image error, insert_data:%s", str(insert_data)) error_msg = "发布新镜像 %s 失败,更新image表失败" % eimage_name state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, error_msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) update_data = {'status': '0', 'create_type': image_ceate_type.USING} where_data = {'eimage_name': name} chan_status = im_s.ImageManageService().update_image_info( update_data, where_data) if chan_status < 0: logging.error("release image error, update_data:%s", str(update_data)) error_msg = "发布镜像 %s 失败,更新image_manage表信息失败", eimage_name state_tag = im_m_act_sta.FAILED im_s.ImageManageService().update_image_manage_status( eimage_name, error_msg, ImageManage.CHECKOUT) im_s.ImageStatusService().add_image_status_action( eimage_name, update_action, state_tag, error_msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=error_msg) state_tag = im_m_act_sta.SUCCESSED message = '发布成功' im_s.ImageStatusService().add_image_status_action(eimage_name, update_action, state_tag, message) return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def instance_msg_send_to_kafka(task_id, request_id): ''' 通过传入的task_id, request_id拼凑消息发送kafka,可供外部接口调用 :param request_id: :return: ''' _ins_info = ins_s.InstanceService().get_instance_info_by_requestid(request_id) if not _ins_info: logging.error('task %s : can not find instance info ' 'when retry create instance send kafka msg', task_id) return False, "can not find instance info", _ins_info['name'] if _ins_info['isdeleted'] == '1': logging.error('task %s : instance has been deleted ' 'when retry create instance send kafka msg', task_id) return False, "instance has been deleted", _ins_info['name'] _ins_host_ip = ins_s.get_hostip_of_instance(_ins_info['id']) _ins_hostpool_db_info = ins_s.get_hostpool_of_instance(_ins_info['id']) _ins_flavor_db_info = ins_s.get_flavor_of_instance(_ins_info['id']) if not _ins_host_ip or not _ins_hostpool_db_info or not _ins_flavor_db_info: logging.error('task %s : instance host, hostpool or flavor information' 'when retry create instance send kafka msg', task_id) return False, "instance host, hostpool or flavor information error", _ins_info['name'] # 获取虚拟机数据盘大小 src_instance_sys_disk_size = _ins_flavor_db_info['root_disk_gb'] data_disk_status, src_instance_data_disk_size = ins_s.get_data_disk_size_of_instance(_ins_info['id']) if not data_disk_status: logging.error('task %s : instance data disk size can not find' 'when retry create instance send kafka msg', task_id) return False, "instance data disk size can not find", _ins_info['name'] src_instance_disk_size = int(src_instance_data_disk_size) + int(src_instance_sys_disk_size) _ins_flavor_db_info['src_instance_disk_size'] = src_instance_disk_size vm_disk_gb = int(src_instance_disk_size) if int(src_instance_disk_size) > 50 else 50 # 获取虚拟机对应网段信息 segment_data = ins_s.get_net_segment_info_of_instance(_ins_info['id']) if not segment_data: logging.error('task %s : instance segment information can not find' 'when retry create instance send kafka msg', task_id) return False, "instance segment information can not find", _ins_info['name'] # 获取虚拟机所在机房类型 vm_env = hostpool_service.get_env_of_hostpool(_ins_hostpool_db_info['id']) if not vm_env: logging.error('task %s : instance env information can not find' 'when retry create instance send kafka msg', task_id) return False, "instance env information can not find", _ins_info['name'] ins_images = ins_s.get_images_of_instance(_ins_info['id']) if not ins_images: logging.error('task %s : instance image information can not find' 'when retry create instance send kafka msg', task_id) return False, "instance image information can not find", _ins_info['name'] else: instance_system = ins_images[0]['system'] image_name = ins_images[0]['name'] # 获取镜像信息,一个image_name可能对应多个id image_nums, image_data = image_service.ImageService().get_images_by_name(image_name) if image_nums <= 0: logging.error('task %s : instance image information can not find' 'when retry create instance send kafka msg', task_id) return False, "instance image information can not find", _ins_info['name'] #BT源信息获取 source_ip = _ins_info['clone_source_host'] source_vm = _ins_info['clone_source_vm'] #instance相关信息 instance_id = _ins_info['id'] uuid = _ins_info['uuid'] host_id = ins_h_s.get_ins_host_info_by_ins_id(instance_id)['host_id'] host_ip = ho_s.HostService().get_host_info(host_id)['ipaddress'] instance_name = _ins_info['name'] #获取source_disk_list source_instance_info = ins_s.InstanceService().get_instance_info_by_name(source_vm) if not source_instance_info: logging.info('克隆源vm %s 不存在' % source_vm) return False, "克隆源vm %s 不存在" % source_vm source_instance_id = source_instance_info['id'] instance_clone_create_data = ins_c_c.get_ins_clone_create_info_by_task_id(task_id) if not instance_clone_create_data: logging.info('获取克隆创建源vm信息失败') return False, "获取克隆创建源vm信息失败" clone_image_num = instance_clone_create_data['torrent_num'] source_disk_list = [] for i in range(int(clone_image_num)): clone_image_name = source_vm + '_' + task_id + '_' + str(i) source_disk_list.append(clone_image_name) # 获取源vm的镜像名称 sour_instance_image = ins_i_s.get_ins_image_info_by_ins_id(source_instance_id) total_size = instance_clone_create_data["total_size"] trans_type = instance_clone_create_data["trans_type"] http_port = instance_clone_create_data["http_port"] md5_check = instance_clone_create_data["md5_check"] sour_image_id = sour_instance_image['image_id'] sour_image_data = image_service.ImageService().get_image_info(sour_image_id) image_name = sour_image_data['name'] # 发送异步消息到队列 data = { "routing_key": "INSTANCE.CLONECREATE", "send_time": get_datetime_str(), "data": { "task_id": task_id, "source_ip":source_ip, "request_id": request_id, "instance_id":instance_id, "host_ip": host_ip, "uuid": uuid, "trans_type": trans_type, "http_port": http_port, "md5_check": md5_check, 'source_vm':source_vm, "hostname": instance_name, # 实例名 "memory_mb": _ins_flavor_db_info['memory_mb'], "vcpu": _ins_flavor_db_info['vcpu'], "ostype": instance_system, "user_id": _ins_info['owner'], "clone_image_num": clone_image_num, "disks":source_disk_list, "total_size": total_size, "image_name": image_name, "net_area_id": segment_data['net_area_id'], "networks": [ { "net_card_name": "br_bond0." + segment_data['vlan'], "ip": segment_data['ip_address'], "netmask": segment_data['netmask'], "dns1": segment_data['dns1'], "dns2": segment_data['dns2'], "mac": segment_data['mac'], "gateway": segment_data['gateway_ip'], "env": vm_env # SIT STG PRD DR } ] } } ret_kafka = send_async_msg(KAFKA_TOPIC_NAME, data) # 修改虚拟机状态为创建中 update_data = { 'status': VMStatus.CREATING, 'created_at': get_datetime_str(), 'updated_at': get_datetime_str() } where_data = { 'uuid': _ins_info['uuid'] } ins_s.InstanceService().update_instance_info(update_data, where_data) return 'done'
def single_task_do(host_ip, task_id): im_sy_s.update_task_ondotag(task_id, '1') task_info = im_sy_s.ImageSyncService().get_image_sync_info(task_id) image_id = task_info['image_id'] speed_limit = task_info['speed_limit'] #获取当前任务的时间段 task_num, task_time_list = get_task_worktime(task_id) #如果当前记录没有任务,return True if not task_num: return_data = 'no_job' message = '当前任务无可继续执行的计划' im_sy_s.update_task_ondotag(task_id, '0') return True, return_data, message else: #如果任务状态非已完成,且当前时间小于最后一条任务的时间 while im_sy_s.ImageSyncService().get_image_sync_info(task_id)['status'] != '2'\ and datetime.strptime(get_datetime_str(), "%Y-%m-%d %X") < get_task_endtime(task_id): #获取当前时间 now_time_str = get_datetime_str() for task_time_info in task_time_list: task_starttime = task_time_info['task_starttime'] task_endtime = task_time_info['task_endtime'] sch_task_id = task_time_info['id'] #判断该计划任务时间段是否可执行任务 now_time = datetime.strptime(now_time_str, "%Y-%m-%d %X") res_checktime = Checktime(task_starttime, task_endtime, now_time) # 如果可执行则下发 if res_checktime: endtime = task_endtime res_wget, res_msg, md5_tag = wget_func( host_ip, image_id, speed_limit, task_id, endtime, sch_task_id) #wget下发成功则改变库中任务信息 if res_wget: #如果发现镜像为最新 if md5_tag == '0': where_data = {'id': task_id} update_data = { 'on_task': '0', 'status': '2', 'message': res_msg } im_sy_s.ImageSyncService().update_image_sync_task( update_data, where_data) print('now sleep 1min to check again') time.sleep(60) #如果发现镜像非最新 else: #获取后台wget的进程号并存入DB image_info = im_s.ImageService().get_image_info( image_id) image_url = image_info['url'] wget_pid_res, wget_pid, wget_pid_msg = ansibleCmdV2.get_wget_pid( host_ip, image_url) if not wget_pid_res: wget_pid = '0' where_data = { 'id': task_id, } update_data = {'process_id': wget_pid} im_sy_s.ImageSyncService().update_image_sync_task( update_data, where_data) message = res_msg + '尝试时间为 %s' % get_datetime_str() where_data = {'id': task_id} update_data = { 'on_task': '1', 'status': '1', 'message': message } #将image_sync_task表的on_task置为1 im_sy_s.ImageSyncService().update_image_sync_task( update_data, where_data) #将image_sync_schedule表对应的sch_state置为1 where_data = {'id': sch_task_id} update_data = {'sch_state': '1'} im_sy_sch.ImageSyncScheduleService( ).update_image_sync_sch(update_data, where_data) print('now sleep 1min to check again') time.sleep(60) #wget下发不成功处理 else: message = "wget 下发不成功,尝试时间为 %s" % get_datetime_str() im_sy_s.update_wget_message(task_id, message) # 每过10min尝试wget一次 wget_retry_tag = False while not wget_retry_tag and datetime.strptime( get_datetime_str(), "%Y-%m-%d %X") < task_endtime: time.sleep(600) print 'befor wget_func' print task_id res_wget, res_msg, md5_tag = wget_func( host_ip, image_id, speed_limit, task_id, endtime, sch_task_id) if res_wget: wget_retry_tag = True message = res_msg + '尝试时间为 %s' % get_datetime_str( ) else: message = "wget 下发不成功,尝试时间为 %s" % get_datetime_str( ) im_sy_s.update_wget_message(task_id, message) #如果重试成功,库状态更新 if res_wget: #如果镜像为最新 if md5_tag == '0': where_data = {'id': task_id} update_data = { 'on_task': '0', 'status': '2', 'message': res_msg } im_sy_s.ImageSyncService( ).update_image_sync_task( update_data, where_data) print('now sleep 1min to check again') time.sleep(60) #如果镜像非最新 else: where_data = {'id': task_id} update_data = {'on_task': '1', 'status': '1'} # 更新task_sync_task表 im_sy_s.ImageSyncService( ).update_image_sync_task( update_data, where_data) # 将image_sync_schedule表对应的sch_state置为1 where_data = {'id': sch_task_id} update_data = {'sch_state': '1'} im_sy_sch.ImageSyncScheduleService( ).update_image_sync_sch( update_data, where_data) print('now sleep 1min to check again') time.sleep(60) #如果重试失败,库状态更新 else: time.sleep(5) where_data = {'id': task_id} update_data = {'on_task': '0', 'status': '3'} # 更新task_sync_task表 im_sy_s.ImageSyncService().update_image_sync_task( update_data, where_data) # 将image_sync_schedule表对应的sch_state置为1 where_data = {'id': sch_task_id} update_data = {'sch_state': '3'} im_sy_sch.ImageSyncScheduleService( ).update_image_sync_sch(update_data, where_data) print('now sleep 1min to check again') time.sleep(60)
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 wget_func(host_ip, image_id, speed_limit, task_id, endtime, sch_task_id): #比对镜像是否最新 check_md5_tag, check_md5_msg = check_image_status(host_ip, task_id) if not check_md5_tag: print 'md5 check return######################################' print check_md5_msg return False, check_md5_msg, '1' else: #镜像为最新返回 if check_md5_msg == '0': msg = '镜像为最新无需更新' return True, msg, '0' else: check_dir = DIR_DEFAULT image_info = im_s.ImageService().get_image_info(image_id) image_url = image_info['url'] image_type = image_info['type'] image_name = image_info['name'] print 'in wget_func' print task_id wget_conf_tag, wget_conf_data = ansibleCmdV2.wget_confirm( host_ip, image_url) print 'wget_confirm_msg###########################################' print wget_conf_tag print wget_conf_data print 'done#################################' if not wget_conf_tag: message = wget_conf_data return False, message, '1' else: image_info = im_s.ImageService().get_image_info(image_id) image_url = image_info['url'] speed_limit_parm = '--limit-rate ' + speed_limit + 'm' host_info = ho_s.HostService().get_host_info_by_hostip(host_ip) host_id = host_info['id'] net_area_id_get = ho_s.get_host_net_area_id(host_id) net_area_id = net_area_id_get[0]['net_area_id'] print type(net_area_id) print 'net area id is ' print net_area_id res, image_server, image_cache_server = _confirm_image_copy_url( str(net_area_id)) print 'get image server##########################' print res print image_server print image_cache_server print 'done##############################################' #获取镜像服务器和缓存服务器 if not res: return False, image_server, '1' # 如果后台没有wget命令在下载image,则下发ansible下载 if wget_conf_data == '2': print 'print wget parm#########################' print host_ip print speed_limit_parm print image_url print 'done###############################' print 'before send_wget' print task_id send_wget_tag, send_message = send_wget( host_ip, image_url, image_server, speed_limit_parm, check_dir, endtime, sch_task_id) return send_wget_tag, send_message, '1' #如果后台有wget命令在运行,判断是否为当前镜像 else: if wget_conf_data == str(image_type): message = '后台已在下载任务镜像' logging.info(message) return True, message, '1' else: logging.info('后台未下载任务所需镜像,可下发') send_wget_tag, send_message = send_wget( host_ip, image_url, image_server, speed_limit_parm, check_dir, endtime, sch_task_id) return send_wget_tag, send_message, '1'
def instance_init_info(): def _filter_least_host_num(hostpool_id, least_host_num): ''' 过滤掉不满足最少host数的集群 :param hostpool_id: :param least_host_num: :return: ''' # 获取主机列表 all_hosts_nums, all_hosts_data = host_s.HostService().get_hosts_of_hostpool(hostpool_id) if all_hosts_nums < least_host_num or all_hosts_nums < 1: logging.info('filter hostpool %s that has no least host nums %s when get create init info', hostpool_id, least_host_num) return False return True def _filter_no_segment_info(hostpool_id): ''' 过滤掉没有网段信息的集群 :param hostpool_id: :return: ''' segments_list = hostpool_service.get_segment_info(hostpool_id) if not segments_list: logging.error('filter hostpool %s that has no segment info when get create init info', hostpool_id) return False return True resp = InstanceInitInfoResp() user_all_area_ids = current_user_all_area_ids() # area层级信息 - 总部 area_zb_data = hostpool_service.get_level_info_hostpool_zb() for i in area_zb_data: # 不显示不满足最少host数的集群 if not _filter_least_host_num(i['hostpool_id'], i['least_host_num']): continue # 不显示没有网段信息的集群 if not _filter_no_segment_info(i['hostpool_id']): continue # 只显示当前用户所属的区域 if user_all_area_ids and i['area_id'] not in user_all_area_ids: continue resp.area_ZB.append(i) # area层级信息 - 地区 area_dq_data = hostpool_service.get_level_info_hostpool_dq() for i in area_dq_data: # 不显示不满足最少host数的集群 if not _filter_least_host_num(i['hostpool_id'], i['least_host_num']): continue # 不显示没有网段信息的集群 if not _filter_no_segment_info(i['hostpool_id']): continue # 只显示当前用户所属的区域 if user_all_area_ids and i['area_id'] not in user_all_area_ids: continue _area_dq_info = area_dq_init_info.AreaDQInitInfo().init_from_db(i) # 表示有父区域 if i['parent_id']: _parent_info = area_service.AreaService().get_area_info(i['parent_id']) if _parent_info: _area_dq_info.area_name = _parent_info['displayname'] _area_dq_info.child_area_name = i['area_name'] else: # 有父区域ID但没有相应信息,则当做没有父区域 _area_dq_info.area_name = i['area_name'] else: _area_dq_info.area_name = i['area_name'] resp.area_DQ.append(_area_dq_info) # flavor信息 flavors_nums, flavors_data = flavor_service.FlavorService().get_all_flavors() for i in flavors_data: _flavor_info = flavor_init_info.FlavorInitInfo().init_from_db(i) resp.flavors.append(_flavor_info) # image信息 - windows images_windows_nums, images_windows_data = image_service.ImageService().get_all_images('windows') for i in images_windows_data: _image_windows_info = image_init_info.ImageInitInfo().init_from_db(i) resp.images_windows.append(_image_windows_info) # image信息 - linux images_linux_nums, images_linux_data = image_service.ImageService().get_all_images('linux') for i in images_linux_data: _image_linux_info = image_init_info.ImageInitInfo().init_from_db(i) resp.images_linux.append(_image_linux_info) # group信息 user_groups = current_user_groups() user_group_ids_list = [] is_super_group = False for _groups in user_groups: user_group_ids_list.append(_groups['id']) # 超级管理员组 if _groups['name'] == "supergroup": is_super_group = True groups_params = { 'WHERE_AND': { '=': { 'isdeleted': '0' } }, } groups_nums, groups_data = group_service.GroupService().query_data(**groups_params) for i in groups_data: # 管理员组的成员可以显示所有组,而非管理员组的只显示当前用户所在应用组 if not is_super_group and i['id'] not in user_group_ids_list: continue _group_info = group_info.GroupInitInfo().init_from_db_1(i) resp.groups.append(_group_info) return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data=resp.to_json())