def instance_status_change_for_miniarch(): ''' 修改虚拟机状态为v2v中,或者关机中 :return: ''' instance_uuid = request.values.get('instance_uuid') instance_status = request.values.get('instance_status') if not instance_uuid or not instance_status: return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg="请求入参缺失") if instance_status not in [VMStatus.MINIARCH_MIGRATE, VMStatus.SHUTDOWN]: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="待修改的虚拟机状态无法识别") ins_data = instance_s.InstanceService().get_instance_info_by_uuid( instance_uuid) if not ins_data: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="无法获取虚拟机信息") # 将克隆源vm状态改成关机 where_data = {'uuid': instance_uuid} update_data = {'status': instance_status} ret_change_vm_status = instance_s.InstanceService().update_instance_info( update_data, where_data) if ret_change_vm_status < 1: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="虚拟机状态更新失败") return json_helper.format_api_resp(code=ErrorCode.SUCCESS, msg="虚拟机状态更新成功")
def instance_add_netcard(instance_id): ''' kvm平台虚拟机添加网卡接口 :param instance_id: :return: ''' # 判断指定虚拟机是否存在 if not instance_id: return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg="instance_id为空,添加网卡失败") ins_data = ins_s.InstanceService().get_instance_info(instance_id) if not ins_data: return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg="无法找到待添加网卡虚拟机") # 查询指定虚拟机网卡数量,目前不能超过3块 instance_net_card = ins_s.get_net_info_of_instance(instance_id) if instance_net_card: if len(instance_net_card) >= INSTANCE_NETCARD_NUMS: return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg="虚拟机网卡数量不能超过%s张" % str(INSTANCE_NETCARD_NUMS)) # 往instance_ip表添加记录 mac = randomMAC() instance_ip_data = { 'instance_id': instance_id, 'mac': mac, 'type': InstanceNicType.NORMAL_NETWORK_NIC, 'isdeleted': '0', 'created_at': get_datetime_str() } ret_add = ins_ip_s.InstanceIPService().add_instance_ip_info(instance_ip_data) if ret_add.get('row_num') <= 0: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="虚拟机网卡创建失败") return json_helper.format_api_resp(code=ErrorCode.SUCCESS, msg="虚拟机网卡创建成功")
def instance_retry_create(request_id_list): ''' 虚拟机重新创建,通过request_id重新发送kafka消息 :return: ''' threads = [] req_ids = request_id_list #req_ids = request.values.get('request_ids') if not req_ids: return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR) req_ids_list = req_ids.split(',') for req_id in req_ids_list: ins_info = ins_s.InstanceService().get_instance_info_by_requestid(req_id) if ins_info: if ins_info['status'] != '100': continue kafka_send_thread = threading.Thread(target=instance_msg_send_to_kafka, args=(ins_info['task_id'], req_id,)) threads.append(kafka_send_thread) kafka_send_thread.start() # 判断多线程是否结束 if len(threads) == 0: return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data='没有找到需要重试的虚拟机') for t in threads: t.join() return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def rename_vm_disk(src_image_list, host_ip, request_id, uuid, user_id, instance_id): instance_data = ins_s.InstanceService().get_instance_info(instance_id) instance_name = instance_data['name'] ret_check_status, job_status = _check_job_step_done( request_id, InstaceActions.INSTANCE_CLONE_RENAME_IMAGES) if ret_check_status and job_status is 1: message = "pass" # logging.info(message) return ActionStatus.SUCCSESS, message else: _add_instance_actions(uuid, request_id, user_id, InstaceActions.INSTANCE_CLONE_RENAME_IMAGES, 'start') for image in src_image_list: image_tag = image.split('.', 1) new_im_name = instance_name + '.' + image_tag[1] dest_dir = '/app/image/' + uuid res_rename, message = ansibleCmdV2.rename_clone_image( host_ip, image, new_im_name, dest_dir) if not res_rename: status = ActionStatus.FAILD message = '重命名 %s 磁盘文件时失败' % image _update_instance_actions( uuid, request_id, user_id, InstaceActions.INSTANCE_CLONE_RENAME_IMAGES, status, message) return status, message status = ActionStatus.SUCCSESS message = '重命名磁盘文件成功' _update_instance_actions(uuid, request_id, user_id, InstaceActions.INSTANCE_CLONE_RENAME_IMAGES, status, message) return status, message
def instance_startup(): ''' 虚机开机 :return: ''' ins_ids = request.values.get('instance_ids') if not ins_ids: logging.info('no instance_ids when startup instance') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR) ins_ids_list = ins_ids.split(',') # 操作的instance数 all_num = len(ins_ids_list) if all_num > int(INSTANCE_MAX_STARTUP): logging.info('startup nums %s is greater than max %s', all_num, INSTANCE_MAX_STARTUP) return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR) msg = None fail_num = 0 for _ins_id in ins_ids_list: _ins_data = ins_s.InstanceService().get_instance_info(_ins_id) if _ins_data: # 本身是开机状态的不能再开机 if _ins_data['status'] == VMStatus.STARTUP or _ins_data[ 'status'] == VMStatus.STARTUP_ING: logging.info( 'the instance status %s is invalid when startup instance', _ins_data['status']) fail_num += 1 # 单台操作且已失败则直接跳出循环 if all_num == 1: msg = '该虚拟机已经开机,请勿重复开机' break continue else: _ret_start = ins_a_s.startup_instance(_ins_data) if not _ret_start: fail_num += 1 continue else: logging.info( 'the instance is not exist in db when startup instance') fail_num += 1 continue # 全失败 if fail_num == all_num: logging.error("startup instance all failed") if msg: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # 部分成功 if 0 < fail_num < all_num: logging.error("startup instance part failed") return json_helper.format_api_resp(code=ErrorCode.SUCCESS_PART, msg="部分虚拟机开机成功") return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def _vm_disk_snapshot_commit(task_id, uuid, user_id, request_id, source_host, src_instance_id, disk_tag_list): ret_check_status, job_status = _check_job_step_done( request_id, InstaceActions.INSTANCE_CLONE_DISK_SNAPSHOT_COMMIT) if ret_check_status and job_status is 1: message = "pass" # logging.info(message) return ActionStatus.SUCCSESS, message else: _add_instance_actions( uuid, request_id, user_id, InstaceActions.INSTANCE_CLONE_DISK_SNAPSHOT_COMMIT, 'start') src_instance_data = ins_s.InstanceService().get_instance_info( src_instance_id) src_instance_name = src_instance_data['name'] src_instance_uuid = src_instance_data['uuid'] _status = ActionStatus.SUCCSESS msg = "虚拟机 %s 整合磁盘快照成功" % src_instance_name # 整合快照文件 # for disk_tag in disk_tag_list: # flag = False # i = 0 # while i < 3 and not flag: # time.sleep(5) # ret_snapshot_commit = ansibleCmd.disk_snapshot_commit(source_host,src_instance_name,disk_tag) # if not ret_snapshot_commit: # i += 1 # err_msg = 'vm %s commit snapshot file for %s fail' % (src_instance_name, disk_tag) # logging.info(err_msg) # else: # flag = True # if not flag: # _status = ActionStatus.FAILD # msg = '虚拟机 %s 磁盘快照 %s 文件整合失败' %(src_instance_name, disk_tag) # break ret_commit, commmit_msg = vm_snapshot_commit(task_id, source_host, src_instance_name, disk_tag_list, src_instance_uuid) if not ret_commit: _status = ActionStatus.FAILD msg = commmit_msg # if _status == ActionStatus.SUCCSESS: # # 删除快照残余文件 # src_instance_uuid = src_instance_data['uuid'] # dest_dir = '/app/image/' + src_instance_uuid # ret = rm_snapfile(source_host, dest_dir) # if not ret: # _status = False # msg = "清除虚拟机%s快照残余文件失败" % src_instance_name _update_instance_actions( uuid, request_id, user_id, InstaceActions.INSTANCE_CLONE_DISK_SNAPSHOT_COMMIT, _status, msg) return _status, msg
def backup_instance_status(instance_id): ''' 这个函数作用是当热迁移失败时,由于前端VM页面并没有热迁移失败的状态码,所以在迁移过程中失败后,都直接将VM状态改为运行中 :return: ''' update_data = { 'status': VMStatus.STARTUP, 'updated_at': get_datetime_str() } where_data = {'id': instance_id} return ins_s.InstanceService().update_instance_info( update_data, where_data)
def instance_clone(instance_id): ''' 虚机克隆 :param instance_id: :return: ''' instance_newname = request.values.get('instance_newname') if not instance_id: logging.info('no instance_id when clone instance') 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 data is no exist in db when clone instance', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) ins_status = ins_data['status'] if ins_status != VMStatus.SHUTDOWN: logging.error('instance %s status %s is invalid when clone instance', instance_id, ins_status) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='只能在关机状态下克隆虚机') ins_group = ins_s.get_group_of_instance(instance_id) if not ins_group: logging.error( 'instance %s group data is no exist in db when clone instance', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) ins_flavor = ins_s.get_flavor_of_instance(instance_id) if not ins_flavor: logging.error( 'instance %s flavor data is no exist in db when clone instance', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # 检查应用组配额 ins_group_id = ins_group['group_id'] is_quota_enough, quota_msg = check_group_quota(ins_group_id, ins_flavor, 1) if not is_quota_enough: logging.error('group %s is no enough quota when clone instance', ins_group_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=quota_msg) return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def instance_recreate(): ''' 重新创建虚拟机 :return: ''' instance_id = request.values.get('instance_id') if not instance_id: logging.info('no instance_id when recreate instance') 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('no instance %s info when recreate instance', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
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 win_vm_std(request_id): v2v_task = v2v_op.v2vTaskService().get_v2v_task_by_requestid(request_id) vmip = v2v_task['vm_ip'] ostype = 'Windows' ip_data = ip_s.IPService().get_ip_by_ip_address(vmip) vmmask_int = int(ip_data['netmask']) vmmask = exchange_maskint(vmmask_int) vmgateway = ip_data['gateway_ip'] vmname = v2v_task['vm_name'] dns1 = ip_data['dns1'] dns2 = ip_data['dns2'] host_ip = v2v_task['dest_host'] cloudarea = v2v_task['cloud_area'] connect_instance = instanceManager.libvirt_get_connect( host_ip, conn_type='instance', vmname=vmname) inject_stauts, mesg = instanceManager.v2v_esx_win_inject( connect_instance, vmname, vmip, vmgateway, dns1, dns2, vmmask, ostype, cloudarea) if inject_stauts: message = "信息注入成功" threadlock = threading.Lock() threadlock.acquire() v2v_op.updata_v2v_message(request_id, message) in_a_s.update_instance_actions(request_id, esx_v2vActions.WINDOWS_STD, ActionStatus.SUCCSESS, message) v2v_op.update_v2v_step(request_id, esx_v2vActions.WINDOWS_STD) v2v_op.updata_v2v_ontask(request_id, '0') vm_uuid = v2v_op.v2vTaskService().get_v2v_task_by_requestid( request_id)['vm_uuid'] v2v_op.update_v2v_actions(request_id, 1) v2v_op.update_v2v_step(request_id, esx_v2vActions.WINDOWS_STD) where_data = {'uuid': vm_uuid} update_data = {'status': '3'} ins_s.InstanceService().update_instance_info(update_data, where_data) threadlock.release() else: message = "信息注入失败" threadlock = threading.Lock() threadlock.acquire() v2v_op.updata_v2v_message(request_id, message) v2v_op.update_v2v_actions(request_id, ActionStatus.FAILD) v2v_op.updata_v2v_ontask(request_id, '0') in_a_s.update_instance_actions(request_id, esx_v2vActions.WINDOWS_STD, ActionStatus.FAILD, message) threadlock.release()
def _vm_create_disk_snapshot(images, uuid, user_id, request_id, source_host, src_instance_id): ret_check_status, job_status = _check_job_step_done( request_id, InstaceActions.INSTANCE_CLONE_DISK_SNAPSHOT) if ret_check_status and job_status is 1: message = "pass" # logging.info(message) return ActionStatus.SUCCSESS, message else: _add_instance_actions(uuid, request_id, user_id, InstaceActions.INSTANCE_CLONE_DISK_SNAPSHOT, 'start') src_instance_data = ins_s.InstanceService().get_instance_info( src_instance_id) src_instance_name = src_instance_data['name'] src_instance_uuid = src_instance_data['uuid'] connect_instance = vmManager.libvirt_get_connect( source_host, conn_type='instance', vmname=src_instance_name) if not connect_instance: _status = ActionStatus.FAILD msg = "源vm%s创建磁盘快照失败,libvirt连接失败" % src_instance_name else: #ret_disk_snapshot = ansibleCmd.create_disk_exter_snapshot(source_host,src_instance_name,snapshot_disk_data) snapshot_disk_data = [] for image in images: image_url = '/app/image/' + src_instance_uuid + '/' + image snapshot_disk_data.append(image_url) ret_disk_snapshot = vmManager.ex_disk_snapshot( source_host, src_instance_name, snapshot_disk_data) if not ret_disk_snapshot: _status = ActionStatus.FAILD msg = "源vm %s 创建磁盘快照失败" % src_instance_name else: _status = ActionStatus.SUCCSESS msg = "源vm %s 创建磁盘快照成功" % src_instance_name _update_instance_actions(uuid, request_id, user_id, InstaceActions.INSTANCE_CLONE_DISK_SNAPSHOT, _status, msg) return _status, msg
def instance_reboot(): ''' 虚机重启/强制重启 :return: ''' ins_ids = request.values.get('instance_ids') # 区分重启和强制重启 flag = request.values.get('flag') if not ins_ids or not flag: logging.error('no instance_ids or flag when reboot instance') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR) ins_ids_list = ins_ids.split(',') # 操作的instance数 all_num = len(ins_ids_list) fail_num = 0 for _ins_id in ins_ids_list: _ins_data = ins_s.InstanceService().get_instance_info(_ins_id) if _ins_data: _ret_start = ins_a_s.reboot_instance(_ins_data) if not _ret_start: fail_num += 1 continue else: logging.info( 'the instance is not exist in db when reboot instance') fail_num += 1 continue # 全失败 if fail_num == all_num: logging.error("reboot instance all failed") return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # 部分成功 if 0 < fail_num < all_num: logging.error("reboot instance part failed") return json_helper.format_api_resp(code=ErrorCode.SUCCESS_PART, msg="部分虚拟机重启成功") return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def _get_source_vm_disks(src_instance_id, source_host): src_image_list = [] src_instance_data = ins_s.InstanceService().get_instance_info( src_instance_id) src_instance_name = src_instance_data['name'] get_device_status, vm_disks_info = vmManager.libvirt_get_instance_device( source_host, src_instance_name) if get_device_status == -100: _status = ActionStatus.FAILD msg = 'get source vm disk list fail' return _status, msg else: for disk in vm_disks_info: if disk['image'] is None: continue src_image_list.append(disk['image']) if src_image_list == []: msg = 'source vm disk list is empty' _status = ActionStatus.FAILD return _status, msg else: _status = ActionStatus.SUCCSESS return _status, src_image_list
def hot_migrate_init(instance_id): ''' 获取迁移时满足条件的目标主机 :param instance_id: :return: ''' # def _check_init(): # 检测虚拟机本身是否符合迁移条件,暂时不做 # pass def _check_cpu(): #暂时不检测CPU型号 pass def _check_mem(host, instance_mem): ''' 检测host是否有足够的内存资源和磁盘资源 :param host: :param instance_mem: :return: ''' # host已分配内存 assign_mem = host_s.get_vm_assign_mem_of_host(host['host_id']) # 已分配 + 预分配 > 总大小 if assign_mem + int(instance_mem) >= int(host['mem_size']): logging.error( 'host %s assign mem %s + instance mem %s > mem size %s', host['host_id'], assign_mem, instance_mem, host['mem_size']) return False return True if not instance_id: logging.info('no instance id when get migrate hosts') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg="参数错误") resp = MigrateHostsResp() ins_data = ins_s.InstanceService().get_instance_info(instance_id) if ins_data: resp.instance_name = ins_data['name'] resp.instance_status = ins_data['status'] ins_flavor_data = ins_s.get_flavor_of_instance(instance_id) if ins_flavor_data: resp.instance_cpu = ins_flavor_data['vcpu'] resp.instance_mem = ins_flavor_data['memory_mb'] resp.instance_disk = ins_flavor_data['root_disk_gb'] ins_ip_data = ins_s.get_ip_of_instance(instance_id) if ins_ip_data: resp.instance_ip = ins_ip_data['ip_address'] ins_host = ins_s.get_host_of_instance(instance_id) if not ins_host: logging.error( 'instance %s of host is not exist in db when get migrate host', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="无法获取虚拟机所在物理机信息") ins_group = ins_g_s.InstanceGroupService().get_instance_group_info( instance_id) if not ins_group: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="无法获取虚拟机所在应用组信息") data_disk_status, data_disk_size = ins_s.get_data_disk_size_of_instance( instance_id) if not data_disk_status: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="无法获取被迁移虚拟机磁盘配置信息") instance_disk_size = int( ins_flavor_data['root_disk_gb']) + int(data_disk_size) # 同一集群 all_hosts_nums, all_hosts_data = host_s.HostService( ).get_available_hosts_of_hostpool(ins_host['hostpool_id']) if all_hosts_nums <= 0: logging.error('no host in hostpool %s when get migrate host', ins_host['hostpool_id']) return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data={}, msg="集群下没有一台可用物理机") # 过滤host # 这里不核对host的cpu型号 hosts_after_filter = host_s_s.migrate_filter_hosts(all_hosts_data, int(all_hosts_nums)) if len(hosts_after_filter) == 0: logging.info('no available host when get migrate host') return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data={}, msg="集群内其他物理机cpu、内存使用率超过阀值,暂时不能迁移") # VM分配给HOST看是否满足迁移 vm = { "vcpu": ins_flavor_data['vcpu'], "mem_MB": ins_flavor_data['memory_mb'], "disk_GB": instance_disk_size, } host_after_match = host_s_s.migrate_match_hosts(hosts_after_filter, vm, ins_group['group_id'], least_host_num=1, max_disk=2000) if len(host_after_match) == 0: logging.info('no available host when get migrate host') return json_helper.format_api_resp( code=ErrorCode.SUCCESS, data={}, msg="集群内其他物理机cpu、内存资源不足或者应用互斥,暂时不能迁移") ins_flavor = ins_s.get_flavor_of_instance(instance_id) if not ins_flavor: logging.error( 'instance %s flavor is not exist in db when get migrate host', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="kvm平台未找到指定配置规格") for _host in host_after_match: # 去除本身host / 内存/磁盘分配足够 if _host['host_id'] != ins_host['id']: _h = { 'host_id': _host['host_id'], 'host_name': _host['name'], 'current_cpu_used': _host['current_cpu_used'], 'current_mem_used': _host['current_mem_used'], 'free_disk_space': int(_host["disk_size"]) * (100 - int(_host["current_disk_used"])) / 100 } resp.host_list.append(_h) return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data=resp.to_json())
def _create_instance_info(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): uuid = randomUUID() request_id = ins_s.generate_req_id() # 往instance表添加记录 logging.info( '创建VM 步骤10-1:插入instance表 task %s : insert instance table start when create instance', task_id) instance_data = { 'uuid': uuid, 'name': instance_name, 'displayname': instance_name, 'description': '', 'status': VMStatus.CREATING, 'typestatus': VMTypeStatus.NORMAL, 'create_source': VMCreateSource.CLOUD_SOURCE, 'isdeleted': '0', 'app_info': app_info, 'owner': owner, 'created_at': get_datetime_str(), 'password': encrypt_helper.encrypt(str(password)), # 密码加密 'request_id': request_id, 'task_id': task_id } ret = ins_s.InstanceService().add_instance_info(instance_data) if ret.get('row_num') <= 0: logging.error( 'task %s : add instance info error when create instance, insert_data: %s', task_id, instance_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) logging.info( '创建VM 步骤10-1:插入instance表成功 ' 'task %s : insert instance table successful when create instance', task_id) instance_id = ret.get('last_id') # 往instance_flavor表添加记录 logging.info( '创建VM 步骤10-2:插入instance_flavor表 ' 'task %s : insert instance_flavor table start when create instance', task_id) instance_flavor_data = { 'instance_id': instance_id, 'flavor_id': flavor_id, 'created_at': get_datetime_str() } ret1 = ins_f_s.InstanceFlavorService().add_instance_flavor_info( instance_flavor_data) if ret1.get('row_num') <= 0: logging.error( 'task %s : add instance_flavor info error when create instance, insert_data: %s', task_id, instance_flavor_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) logging.info( '创建VM 步骤10-2:插入instance_flavor表成功 ' 'task %s : insert instance_flavor table successful when create instance', task_id) # 往instance_group表添加记录 logging.info( '创建VM 步骤10-3:插入instance_group表 task %s : insert instance_group table start when create instance', task_id) instance_group_data = { 'instance_id': instance_id, 'group_id': group_id, 'created_at': get_datetime_str() } ret2 = ins_g_s.InstanceGroupService().add_instance_group_info( instance_group_data) if ret2.get('row_num') <= 0: logging.error( 'task %s : add instance_group info error when create instance, insert_data: %s', task_id, instance_group_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) logging.info( '创建VM 步骤10-3:插入instance_group表成功 task %s : insert instance_group table successful when create instance', task_id) # 往instance_host表添加记录 logging.info( '创建VM 步骤10-4:插入instance_host表 task %s : insert instance_host table start when create instance', task_id) instance_host_data = { 'instance_id': instance_id, 'instance_name': instance_name, 'host_id': vm_host['host_id'], 'host_name': vm_host['name'], 'isdeleted': '0', 'created_at': get_datetime_str() } ret3 = ins_h_s.InstanceHostService().add_instance_host_info( instance_host_data) if ret3.get('row_num') <= 0: logging.error( 'task %s : add instance_host info error when create instance, insert_data: %s', task_id, instance_host_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) logging.info( '创建VM 步骤10-4:插入instance_host表成功 ' 'task %s : insert instance_host table successful when create instance', task_id) # host预分配资源 logging.info( '创建VM 步骤10-5:host预分配资源 task %s : pre allocate host resource start when create instance', task_id) ret4 = host_s.pre_allocate_host_resource(vm_host['host_id'], flavor_info['vcpu'], flavor_info['memory_mb'], flavor_info['root_disk_gb']) if ret4 != 1: logging.error( 'task %s : pre allocate host resource to db error when create instance', task_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) logging.info( '创建VM 步骤10-5:host预分配资源成功 ' 'task %s : pre allocate host resource successful when create instance', task_id) # 往instance_image表添加记录 logging.info( '创建VM 步骤10-6:插入instance_image表 task %s : insert instance_image table start when create instance', task_id) for _image in image_data: instance_image_data = { 'instance_id': instance_id, 'image_id': _image['id'], 'created_at': get_datetime_str() } ret5 = ins_img_s.InstanceImageService().add_instance_image_info( instance_image_data) if ret5.get('row_num') <= 0: logging.error( 'task %s : add instance_image info error when create instance, insert_data: %s', task_id, instance_image_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) logging.info( '创建VM 步骤10-6:插入instance_image表成功 ' 'task %s : insert instance_image table successful when create instance', task_id) # 往instance_ip表添加记录 logging.info( '创建VM 步骤10-7:插入instance_ip表 ' 'task %s : insert instance_ip table start when create instance', task_id) mac = randomMAC() data_ip_address = ip_data['ip_address'] instance_ip_data = { 'instance_id': instance_id, 'ip_id': ip_data['id'], 'mac': mac, 'type': InstanceNicType.MAIN_NETWORK_NIC, 'isdeleted': '0', 'created_at': get_datetime_str() } ret6 = ins_ip_s.InstanceIPService().add_instance_ip_info(instance_ip_data) if ret6.get('row_num') <= 0: logging.error( 'task %s : add instance_ip info error when create instance, insert_data: %s', task_id, instance_ip_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) logging.info( '创建VM 步骤10-7:插入instance_ip表成功 ' 'task %s : insert instance_ip table successful when create instance', task_id) # 标识该IP为已使用 logging.info( '创建VM 步骤10-8:设置IP为已使用 task %s : set ip used start when create instance', task_id) update_data = {'status': IPStatus.USED} where_data = {'id': ip_data['id']} ret7 = ip_service.IPService().update_ip_info(update_data, where_data) if ret7 <= 0: logging.info( 'task %s : update ip info error when create instance, update_data: %s, where_data: %s', task_id, update_data, where_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) logging.info( '创建VM 步骤10-8:设置IP为已使用成功 task %s : set ip used successful when create instance', task_id) # 拼装消息需要的镜像信息 logging.info( '创建VM 步骤10-9:拼装所需的镜像信息 ' 'task %s : piece together need image info start when create instance', 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'], # "md5sum": _image['md5'], "image_size_gb": _image['size_gb'] # 镜像预分配大小 } # 系统盘 if _image_type == ImageType.SYSTEMDISK: _disk_name = instance_name + '.img' _info['image_dir_path'] = '/app/image/' + uuid + '/' + _disk_name _info['disk_name'] = _disk_name _info['disk_size_gb'] = None _info['dev_name'] = 'vda' # 如果只有一块盘且为系统盘,则预先分配一块数据盘的数据存入instance_disk表 if len(image_data) == 1: logging.info( 'task %s : pre insert instance_disk table that has only one system disk start when create ' 'instance', task_id) instance_disk_data = { 'instance_id': instance_id, 'size_gb': vm_disk_gb, 'mount_point': mount_point, 'dev_name': 'vdb', 'isdeleted': '0', 'created_at': get_datetime_str() } ret9 = ins_d_s.InstanceDiskService().add_instance_disk_info( instance_disk_data) if ret9.get('row_num') <= 0: logging.info( 'task %s : pre add instance_disk info that has only one system disk error when create ' 'instance, insert_data: %s', task_id, instance_disk_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) logging.info( 'task %s : pre insert instance_disk table that has only one system disk successful when ' 'create instance', task_id) else: # 数据盘 _disk_name = instance_name + '.disk' + str(data_image_num + 1) _disk_dev_name = _get_vd_map(data_image_num) _info['image_dir_path'] = '/app/image/' + uuid + '/' + _disk_name _info['disk_name'] = _disk_name _info['disk_size_gb'] = vm_disk_gb _info['dev_name'] = _disk_dev_name data_image_num += 1 # 往instance_disk表添加记录 logging.info( 'task %s : insert instance_disk table start when create instance', task_id) instance_disk_data = { 'instance_id': instance_id, 'size_gb': vm_disk_gb, 'mount_point': mount_point, 'dev_name': _disk_dev_name, 'isdeleted': '0', 'created_at': get_datetime_str() } ret8 = ins_d_s.InstanceDiskService().add_instance_disk_info( instance_disk_data) if ret8.get('row_num') <= 0: logging.info( 'task %s : add instance_disk info error when create instance, insert_data: %s', task_id, instance_disk_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) logging.info( 'task %s : insert instance_disk table successful when create instance', task_id) image_list.append(_info) logging.info( '创建VM 步骤10-9:拼装所需的镜像信息成功 ' 'task %s : piece together need image info successful when create instance', task_id) # 发送异步消息到队列 logging.info( '创建VM 步骤10-10:发送异步消息给队列 ' 'task %s : send kafka message start when create instance', task_id) data = { "routing_key": "INSTANCE.CREATE", "send_time": get_datetime_str(), "data": { "task_id": task_id, "request_id": request_id, "host_ip": vm_host['ipaddress'], "uuid": uuid, "hostname": instance_name, # 实例名 "memory_mb": flavor_info['memory_mb'], "vcpu": flavor_info['vcpu'], "ostype": instance_system, "user_id": user_id, "disks": image_list, "disk_size": vm_disk_gb, "image_name": _image['url'].split('/')[-1], "net_area_id": net_area_id, "networks": [{ "net_card_name": "br_bond0." + segment_data['vlan'], "ip": data_ip_address, "netmask": segment_data['netmask'], "dns1": segment_data['dns1'], "dns2": segment_data['dns2'], "mac": mac, "gateway": segment_data['gateway_ip'], "env": vm_env # SIT STG PRD DR }] } } ret_kafka = send_async_msg(KAFKA_TOPIC_NAME, data)
def instance_hot_migrate(instance_id, host_id): ''' 虚拟机迁移 :param instance_id: :param host_id: :return: ''' speed_limit = request.values.get('speed_limit') if not instance_id or not host_id or not speed_limit or int( speed_limit) < 0: logging.info('the params is invalid when migrate instance') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg="参数错误") host_data_s = ins_s.get_host_of_instance(instance_id) if not host_data_s: logging.error( 'instance %s of host is not exist in db when migrate instance', str(instance_id)) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) host_data_d = host_s.HostService().get_host_info(host_id) if not host_data_d: logging.error( 'target host %s is not exist in db when migrate instance', str(instance_id)) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) if host_data_d['typestatus'] == HostTypeStatus.LOCK or host_data_d[ 'typestatus'] == HostTypeStatus.MAINTAIN: logging.error( 'target host %s is in invalid status %s when migrate instance', host_id, host_data_d['typestatus']) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='不能迁移到锁定或维护的主机上') ins_flavor_data = ins_s.get_flavor_of_instance(instance_id) if not ins_flavor_data: logging.error('hot migrate can not get instance %s flavor info' % str(instance_id)) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='无法获取被迁移虚拟机的基础配置信息') ins_group = ins_g_s.InstanceGroupService().get_instance_group_info( instance_id) if not ins_group: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="无法获取虚拟机所在应用组信息") data_disk_status, data_disk_size = ins_s.get_data_disk_size_of_instance( instance_id) if not data_disk_status: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="无法获取被迁移虚拟机磁盘配置信息") instance_disk_size = int( ins_flavor_data['root_disk_gb']) + int(data_disk_size) # 获取物理机所在资源池可用物理机数量 all_hosts_nums, all_hosts_data = host_s.HostService( ).get_available_hosts_of_hostpool(host_data_d["hostpool_id"]) if all_hosts_nums < 1: return False, '集群物理机资源不足,无法满足虚拟机迁移' host_data_d_before_match = [] host_data_d_before_match.append(host_data_d) # 过滤host # 这里不核对host的cpu型号 hosts_after_filter = host_s_s.migrate_filter_hosts( host_data_d_before_match, int(all_hosts_nums)) if len(hosts_after_filter) == 0: logging.info('no available host when get migrate host') return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="集群内其他物理机cpu、内存使用率超过阀值,暂时不能迁移") # VM分配给HOST看是否满足迁移 vm = { "vcpu": ins_flavor_data['vcpu'], "mem_MB": ins_flavor_data['memory_mb'], "disk_GB": instance_disk_size, } host_after_match = host_s_s.migrate_match_hosts(hosts_after_filter, vm, ins_group['group_id'], least_host_num=1, max_disk=2000) if len(host_after_match) == 0: logging.info('no available host when get migrate host') return json_helper.format_api_resp( code=ErrorCode.SYS_ERR, msg="集群内其他物理机cpu、内存资源不足或者应用互斥,暂时不能迁移") # 不能本身 if host_data_s['id'] == host_id: logging.error('no allow migrate to the same host %s', host_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="不能迁移到原主机上") ins_data_s = ins_s.InstanceService().get_instance_info(instance_id) if not ins_data_s: logging.error('instance %s is not exist in db when migrate instance') return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # 排除非法状态,vm只能在开机状态下才能热迁移 if ins_data_s['status'] != VMStatus.STARTUP or ins_data_s[ 'typestatus'] != VMTypeStatus.NORMAL: logging.error( 'instance status %s, typestatus %s is invalid when migrate instance', ins_data_s['status'], ins_data_s['typestatus']) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='只能在关机状态下执行热迁移') # 检测目标主机是否有迁入VM if not _check_has_migrate(host_id): logging.error( 'dest host %s has other migrating instance when migrate instance', host_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='目标主机现有正在迁入的虚机,不能迁移到该主机') # 将VM状态改为热迁移中 update_data = { 'status': VMStatus.MIGRATE, # 热迁移中 'updated_at': get_datetime_str() } where_data = {'id': instance_id} ret = ins_s.InstanceService().update_instance_info(update_data, where_data) if ret != 1: logging.error( 'update instance status error when cold migrate, update_data:%s, where_data:%s', update_data, where_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) ins_data = ins_s.InstanceService().get_instance_info(instance_id) # 新增一个instance_dsthost记录,dsthost为目标host的ip # 迁移过程中失败则删除这条新增的Instance_dsthost记录,迁移成功之后则删除Instance_srchost记录 # 迁移过程中前端vm页面不会显示这条新增的记录 instance_host_data = { 'instance_id': instance_id, 'instance_name': ins_data['name'], 'host_id': host_id, 'host_name': host_data_d['name'], 'isdeleted': '0', 'created_at': get_datetime_str() } ret_h = ins_h_s.InstanceHostService().add_instance_host_info( instance_host_data) if ret_h.get('row_num') <= 0: logging.error( 'add instance host info error when hot migrate, %instance_id,%host_id' ) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # 在instance_migrate表中增加一条数据 insert_data = { 'instance_id': instance_id, 'src_host_id': host_data_s['id'], 'dst_host_id': host_id, 'migrate_status': MigrateStatus.DOING, 'created_at': get_datetime_str() } ret_m = ins_m_s.InstanceMigrateService().add_instance_migrate_info( insert_data) if ret_m.get('row_num') <= 0: logging.error( 'add instance migrate info error when cold migrate, insert_data:%s', insert_data) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # 发送异步消息到队列 data = { "routing_key": "INSTANCE.HOTMIGRATE", "send_time": get_datetime_str(), "data": { "request_id": ins_s.generate_req_id(), "user_id": get_user()['user_id'], "migrate_tab_id": ret_m.get('last_id'), "task_id": ins_s.generate_task_id(), "speed_limit": speed_limit, "ins_data_s": { "id": ins_data_s['id'], "uuid": ins_data_s['uuid'], "name": ins_data_s['name'] }, "host_data_d": { "id": host_data_d['id'], "name": host_data_d['name'], "ipaddress": host_data_d['ipaddress'] }, "host_data_s": { "id": host_data_s['id'], "name": host_data_s['name'], "ipaddress": host_data_s['ipaddress'], "sn": host_data_s['sn'] } } } # todo:这里有可能发送不成功 ret_kafka = send_async_msg(KAFKA_TOPIC_NAME, data) return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def insert_log(*argv, **kwargs): user = user_service.get_user() res = func(*argv, **kwargs) instance_data = "" try: tmp = json.loads(res.data) # 根据不同action拼接extra_data if request.values.get('instance_ids'): # 删除VM、开机、关机 try: # instance_ids = json.dumps(request.values.get('instance_ids')) ins_ids = request.values.get('instance_ids') ins_ids_list = ins_ids.split(',') for _ins_id in ins_ids_list: _ins_data = ins_s.InstanceService( ).get_instance_info(_ins_id) instance_data += "name:" + _ins_data[ 'name'] + "," + "uuid:" + _ins_data[ 'uuid'] + "; " except: pass elif operation_action == OperationAction.ADD: # 创建VM try: hostpool_id = json.dumps(kwargs['hostpool_id']) image_name = request.values.get('image_name') flavor_id = request.values.get('flavor_id') count = request.values.get('count') app_info = request.values.get('app_info') group_id = request.values.get('group_id') owner = request.values.get('owner') instance_data += "hostpool_id:" + hostpool_id + "," + "image_name:" + image_name + "," \ + "flavor_id:" + flavor_id + "," + "count:" + count + "," \ + "app_info:" + app_info + "," + "group_id:" + group_id + "," \ + "owner:" + owner + ";" except: pass elif operation_action == OperationAction.MIGRATE or operation_action == OperationAction.HOT_MIGRATE: # 冷迁移、热迁移 try: _ins_id = json.dumps(kwargs['instance_id']) _host_id = json.dumps(kwargs['host_id']) host_data_d = host_s.HostService().get_host_info( _host_id) # host_data_s = ins_s.get_host_of_instance(_ins_id) # str(host_data_s['name']) _ins_data = ins_s.InstanceService().get_instance_info( _ins_id) # TODO: add src_host instance_data += "name:" + _ins_data['name'] + "," + "uuid:" + _ins_data['uuid'] + "," \ + "src_host:" + "," + "dst_host:" + str(host_data_d['name']) + ";" except: pass elif operation_action == OperationAction.CLONE_CREATE: # 克隆创建 try: _ins_id = request.values.get('instance_id') _ins_data = ins_s.InstanceService().get_instance_info( _ins_id) instance_data += "name:" + _ins_data[ 'name'] + "," + "uuid:" + _ins_data['uuid'] + "; " except: pass elif operation_action == OperationAction.ALTER: # 修改VM配置 try: _flavor_id = request.values.get('flavor_id') # _disk_gb_list_req = request.values.get('disk_gb_list') _app_info = request.values.get('app_info') _owner = request.values.get('owner') _group_id = request.values.get('group_id') _net_conf_list_req = request.values.get( 'net_status_list') # _ins_id = request.values.get('instance_id') _ins_id = json.dumps(kwargs['instance_id']) _extend_list_req = request.values.get('extend_list') # _qemu_ga_update_req = request.values.get('qemu_ga_update') _ins_data = ins_s.InstanceService().get_instance_info( _ins_id) instance_data += "name:" + _ins_data['name'] + "," + "uuid:" + _ins_data['uuid'] + "," \ + "owner:" + _owner + "," + "group_id:" + _group_id + "," \ + "flavor_id:" + _flavor_id + "," + "app_info:" + _app_info + "," \ + "extend_list:" + _extend_list_req + "," \ + "net_conf_list_req:" + _net_conf_list_req + ";" except: pass elif kwargs: # 克隆备份 try: _ins_id = json.dumps(kwargs['instance_id']) _ins_data = ins_s.InstanceService().get_instance_info( _ins_id) instance_data += "name:" + _ins_data[ 'name'] + "," + "uuid:" + _ins_data['uuid'] + "; " except: pass else: pass except: return res if tmp["code"] == ErrorCode.SUCCESS: operation_result = "SUCCESS" elif tmp["code"] == ErrorCode.SUCCESS_PART: operation_result = "SUCCESS_PART" else: operation_result = "FAILED" try: instance_data += " ErrorMsg:" + tmp["msg"] except: pass client_ip = request.headers.get('X-Forwarded-For', '') insert_data = { "operator": user["user_id"], "operator_ip": client_ip, "operation_object": operation_object, "operation_action": operation_action, "operation_date": time_helper.get_datetime_str(), "operation_result": operation_result, "extra_data": "" + instance_data } OperationService().insert_operation(insert_data) return res
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 get_collect_request_multithreading(task_idapi, task_idkvm, vm_count, request_opr_user, request_api_origin): # 判断此工单是否有线程在追踪 try: params = { 'WHERE_AND': { '=': { 'taskid_kvm': task_idkvm, 'taskid_api': task_idapi, 'istraceing': '1' }, } } ret_traceing_nums, ret_traceing_data = request_r_s.RequestRecordService( ).request_db_query_data(**params) if ret_traceing_nums > 0: return # 标记工单为跟踪中 _update_data = { 'istraceing': '1', } _where_data = { 'taskid_kvm': task_idkvm, } ret = request_r_s.RequestRecordService().update_request_status( _update_data, _where_data) if ret <= 0: logging.error('update request %s status to db failed' % task_idkvm) ret_request_re = request_r_s.RequestRecordService( ).get_request_record_info_by_taskid_kvm(task_idkvm) request_ip = ret_request_re["request_ip"] succeed_http_code = ['200', '500'] instance_actions_succeed_params = { 'WHERE_AND': { '=': { 'task_id': task_idkvm, 'action': 'instance_inject_data', 'status': 1 }, }, } # instance_actions_failed_params = { # 'WHERE_AND': { # '=': { # 'task_id': task_idkvm, # 'status': 2 # }, # '!=': { # 'action': 'image_sync_status' # }, # }, # } instance_timeout_failed_params = { 'WHERE_AND': { '=': { 'task_id': task_idkvm, 'status': VMStatus.CREATE_ERROR }, }, } vm_succeed_count_db_ret, vm_succeed_data = instance_a_s.InstanceActionsServices( ).query_data(**instance_actions_succeed_params) # vm_failed_count_db_ret, vm_failed_data = # instance_a_s.InstanceActionsServices().query_data(**instance_actions_failed_params) vm_createtimeout_count_db_ret, vm_createtimeout_failed_data = instance_s.InstanceService( ).query_data(**instance_timeout_failed_params) if not vm_succeed_count_db_ret: vm_succeed_count_db_ret = 0 if not vm_createtimeout_count_db_ret: vm_createtimeout_count_db_ret = 0 instances_uuid = [] if vm_succeed_count_db_ret > 0: for per_request_data in vm_succeed_data: instances_uuid.append(per_request_data['instance_uuid']) if vm_count == vm_succeed_count_db_ret: # 通过虚拟机uuid查询主机名、ip、物理机序列号 vm_datas = [] for instance_uuid in instances_uuid: ret_ins = instance_s.InstanceService( ).get_instance_info_by_uuid(instance_uuid) if ret_ins: ret_ins_host = instance_s.get_host_of_instance( ret_ins['id']) ret_ins_ip = instance_s.get_net_segment_info_of_instance( ret_ins['id']) if ret_ins_host and ret_ins_ip: vm_data = { 'instance_ids': ret_ins['id'], 'host_name': ret_ins['name'], 'ip': ret_ins_ip['ip_address'], 'ip_type': ret_ins_ip['segment_type'], 'sn': ret_ins_host['sn'], 'UUID': instance_uuid, 'net_name': ret_ins_ip['segment'], 'subnet_mask': ret_ins_ip['netmask'], 'gateway': ret_ins_ip['gateway_ip'], 'vlan_id': ret_ins_ip['vlan'], 'passWord': decrypt(ret_ins['password']) } vm_datas.append(vm_data) msg_detail = {'opUser': request_opr_user, 'vm': vm_datas} # 回调外部接口 response_to_api_status = '1' if request_api_origin == ApiOrigin.VISHNU: ret_code = msg_to_vishnu(task_idapi, VsJobStatus.SUCCEED, msg_detail, request_ip) elif request_api_origin == ApiOrigin.SFSLB: ret_code = msg_to_sfslb(task_idapi, VsJobStatus.SUCCEED, msg_detail, request_ip) elif request_api_origin == ApiOrigin.FWAF: ret_code = msg_to_fwaf(task_idapi, VsJobStatus.SUCCEED, msg_detail, request_ip) else: ret_code = msg_to_vishnu(task_idapi, VsJobStatus.SUCCEED, msg_detail, request_ip) if ret_code not in succeed_http_code: response_to_api_status = '0' update_db_time = get_datetime_str() _update_data = { 'task_status': '1', 'response_to_api': response_to_api_status, 'finish_time': update_db_time, 'request_status_collect_time': update_db_time, } _where_data = { 'taskid_kvm': task_idkvm, } ret = request_r_s.RequestRecordService().update_request_status( _update_data, _where_data) if ret <= 0: logging.error('update request %s status to db failed' % task_idkvm) elif (vm_createtimeout_count_db_ret + vm_succeed_count_db_ret) == vm_count \ and vm_createtimeout_count_db_ret > vm_count * 0.2: # 回调外部接口 response_to_api_status = '1' if request_api_origin == ApiOrigin.VISHNU: ret_code = msg_to_vishnu(task_idapi, VsJobStatus.FAILED, 'all kvm instance create failed', request_ip) elif request_api_origin == ApiOrigin.SFSLB: ret_code = msg_to_sfslb(task_idapi, VsJobStatus.FAILED, 'all kvm instance create failed', request_ip) elif request_api_origin == ApiOrigin.FWAF: ret_code = msg_to_fwaf(task_idapi, VsJobStatus.FAILED, 'all kvm instance create failed', request_ip) else: ret_code = msg_to_vishnu(task_idapi, VsJobStatus.FAILED, 'all kvm instance create failed', request_ip) if ret_code not in succeed_http_code: response_to_api_status = '0' update_db_time = get_datetime_str() _update_data = { 'task_status': '2', 'response_to_api': response_to_api_status, 'finish_time': update_db_time, 'request_status_collect_time': update_db_time, } _where_data = { 'taskid_kvm': task_idkvm, } ret = request_r_s.RequestRecordService().update_request_status( _update_data, _where_data) if ret <= 0: logging.error('update request %s status to db failed' % task_idkvm) else: if (vm_createtimeout_count_db_ret + vm_succeed_count_db_ret) == vm_count: # 把成功创建的虚拟机返回外部接口 """ vm_datas = [] for instance_uuid in instances_uuid: ret_ins = instance_s.InstanceService().get_instance_info_by_uuid(instance_uuid) if ret_ins: ret_ins_host = instance_s.get_host_of_instance(ret_ins['id']) ret_ins_ip = instance_s.get_net_segment_info_of_instance(ret_ins['id']) if ret_ins_host and ret_ins_ip: vm_data = { 'host_name': ret_ins['name'], 'ip': ret_ins_ip['ip_address'], 'sn': ret_ins_host['sn'], 'UUID': instance_uuid, 'net_name': ret_ins_ip['segment'], 'subnet_mask': ret_ins_ip['netmask'], 'gateway': ret_ins_ip['gateway_ip'], 'vlan_id': ret_ins_ip['vlan'] } vm_datas.append(vm_data) msg_detail = {'opUser': request_opr_user, 'vm': vm_datas} """ # 回调外部接口 response_to_api_status = '1' if request_api_origin == ApiOrigin.VISHNU: ret_code = msg_to_vishnu( task_idapi, VsJobStatus.FAILED, 'part of kvm instance create failed', request_ip) elif request_api_origin == ApiOrigin.SFSLB: ret_code = msg_to_sfslb( task_idapi, VsJobStatus.FAILED, 'part of kvm instance create failed', request_ip) elif request_api_origin == ApiOrigin.FWAF: ret_code = msg_to_fwaf( task_idapi, VsJobStatus.FAILED, 'part of kvm instance create failed', request_ip) else: ret_code = msg_to_vishnu( task_idapi, VsJobStatus.FAILED, 'part of kvm instance create failed', request_ip) if ret_code not in succeed_http_code: response_to_api_status = '0' update_db_time = get_datetime_str() _update_data = { 'task_status': '2', 'response_to_api': response_to_api_status, 'finish_time': update_db_time, 'request_status_collect_time': update_db_time, } _where_data = { 'taskid_kvm': task_idkvm, } ret = request_r_s.RequestRecordService( ).update_request_status(_update_data, _where_data) if ret <= 0: logging.error('update request %s status to db failed' % task_idkvm) else: # 成功失败的总数量未等于count pass elif vm_createtimeout_count_db_ret > 0: # 全部虚拟机创建失败 if (vm_createtimeout_count_db_ret + vm_succeed_count_db_ret) == vm_count \ and vm_createtimeout_count_db_ret > vm_count * 0.2: # 回调外部接口 response_to_api_status = '1' if request_api_origin == ApiOrigin.VISHNU: ret_code = msg_to_vishnu(task_idapi, VsJobStatus.FAILED, 'all kvm instance create failed', request_ip) elif request_api_origin == ApiOrigin.SFSLB: ret_code = msg_to_sfslb(task_idapi, VsJobStatus.FAILED, 'all kvm instance create failed', request_ip) elif request_api_origin == ApiOrigin.FWAF: ret_code = msg_to_fwaf(task_idapi, VsJobStatus.FAILED, 'all kvm instance create failed', request_ip) else: ret_code = msg_to_vishnu(task_idapi, VsJobStatus.FAILED, 'all kvm instance create failed', request_ip) if ret_code not in succeed_http_code: response_to_api_status = '0' update_db_time = get_datetime_str() _update_data = { 'task_status': '2', 'response_to_api': response_to_api_status, 'finish_time': update_db_time, 'request_status_collect_time': update_db_time, } _where_data = { 'taskid_kvm': task_idkvm, } ret = request_r_s.RequestRecordService().update_request_status( _update_data, _where_data) if ret <= 0: logging.error('update request %s status to db failed' % task_idkvm) else: update_db_time = get_datetime_str() _update_data = {'request_status_collect_time': update_db_time} _where_data = { 'taskid_kvm': task_idkvm, } ret = request_r_s.RequestRecordService().update_request_status( _update_data, _where_data) if ret <= 0: logging.error('update request %s status to db failed' % task_idkvm) # 标记工单为完成追踪 _update_data = { 'istraceing': '0', } _where_data = { 'taskid_kvm': task_idkvm, } ret = request_r_s.RequestRecordService().update_request_status( _update_data, _where_data) if ret <= 0: logging.error( 'update request %s status to db failed when mark istraceing 1' % task_idkvm) return except Exception as e: logging.error('request {} threading exception error: {}'.format( task_idkvm, e)) return
def _instance_db_info(uuid, vmname, vm_app_info, owner, flavor_id, group_id, host, mac, vmdisk, ip_id, vmostype, requestid, ver_data): vm_ostype_todb = '' vmhost = ho_s.HostService().get_host_info_by_hostip(host) # 往instance表添加记录 instance_data = { 'uuid': uuid, 'name': vmname, 'displayname': vmname, 'description': '', 'status': VMStatus.CONVERTING, 'typestatus': VMTypeStatus.NORMAL, 'isdeleted': '0', 'app_info': vm_app_info, 'owner': owner, 'created_at': get_datetime_str(), 'create_source': VMCreateSource.ESX } ret = ins_s.InstanceService().add_instance_info(instance_data) if ret.get('row_num') <= 0: message = 'add instance info error when create instance' logging.info( 'add instance info error when create instance, insert_data: %s', instance_data) return False, message instance_id = ret.get('last_id') if vmostype == 'Windows': vm_ostype_todb = 'windows' elif vmostype == 'Linux': vm_ostype_todb = 'linux' # 往v2v_instance_info表添加记录 v2v_instance_data = { 'instance_id': instance_id, 'os_type': vm_ostype_todb, 'isdeleted': '0', 'created_at': get_datetime_str(), 'request_id': requestid, 'os_version': ver_data } ret_v2v_instance = v2v_in_i.v2vInstanceinfo().add_v2v_instance_info( v2v_instance_data) if ret_v2v_instance.get('row_num') <= 0: logging.info( 'add v2v_instance info error when create instance, v2v_instance_data: %s', v2v_instance_data) message = 'add v2v_instance info error when create instance' return False, message # 往instance_flavor表添加记录 instance_flavor_data = { 'instance_id': instance_id, 'flavor_id': flavor_id, 'created_at': get_datetime_str() } ret1 = ins_f_s.InstanceFlavorService().add_instance_flavor_info( instance_flavor_data) if ret1.get('row_num') <= 0: logging.info( 'add instance_flavor info error when create instance, insert_data: %s', instance_flavor_data) message = 'add instance_flavor info error when create instance' return False, message # 往instance_group表添加记录 instance_group_data = { 'instance_id': instance_id, 'group_id': group_id, 'created_at': get_datetime_str() } ret2 = ins_g_s.InstanceGroupService().add_instance_group_info( instance_group_data) if ret2.get('row_num') <= 0: logging.info( 'add instance_group info error when create instance, insert_data: %s', instance_group_data) message = 'add instance_group info error when create instance' return False, message # 往instance_host表添加记录 instance_host_data = { 'instance_id': instance_id, 'instance_name': vmname, 'host_id': vmhost['id'], 'host_name': vmhost['name'], 'isdeleted': '0', 'created_at': get_datetime_str() } ret3 = ins_h_s.InstanceHostService().add_instance_host_info( instance_host_data) if ret3.get('row_num') <= 0: logging.info( 'add instance_host info error when create instance, insert_data: %s', instance_host_data) message = 'add instance_host info error when create instance' return False, message # 往instance_ip表添加记录 instance_ip_data = { 'instance_id': instance_id, 'ip_id': ip_id, 'mac': mac, 'type': InstanceNicType.MAIN_NETWORK_NIC, 'isdeleted': '0', 'created_at': get_datetime_str() } ret4 = ins_ip_s.InstanceIPService().add_instance_ip_info(instance_ip_data) if ret4.get('row_num') <= 0: logging.info( 'add instance_ip info error when create instance, insert_data: %s', instance_ip_data) message = 'add instance_ip info error when create instance' return False, message # 往instance_disk表添加记录 instance_disk_data = { 'instance_id': instance_id, 'size_gb': vmdisk, 'mount_point': '', 'dev_name': '', 'isdeleted': '0', 'created_at': get_datetime_str() } ret5 = ins_d_s.InstanceDiskService().add_instance_disk_info( instance_disk_data) if ret5.get('row_num') <= 0: logging.info( 'add instance_disk info error when create instance, insert_data: %s', instance_disk_data) message = 'add instance_disk info error when create instance' return False, message message = "信息入库完成" return True, message
def v2v_openstack_del(): #获取入参信息 delete = request.values.get('delete') request_his = request.values.get('request_id') source = v2v_op.v2vTaskService().get_v2v_task_by_requestid( request_his)['source'] if not source: return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg='v2v来源缺失') if delete != '1': return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg='参数错误') #判断当前任务是否完成 data, message = v2v_op.get_v2v_deleteable(request_his) if data != '2': return_msg = message return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg=return_msg) else: if source == VMCreateSource.OPENSTACK: del_res, del_msg = del_action(request_his) if del_res == False: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=del_msg) else: tag, errmsg = esx_del_action(request_his) if not tag: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=errmsg) v2v_task = v2v_op.v2vTaskService().get_v2v_task_by_requestid( request_his) v2v_vm_uuid = v2v_task['vm_uuid'] #更新instance表 instance_info = ins_s.InstanceService().get_instance_info_by_uuid( v2v_vm_uuid) instance_id = instance_info['id'] update_data = {'isdeleted': '1', 'deleted_at': get_datetime_str()} where_data = {'id': instance_id} ret = ins_s.InstanceService().update_instance_info( update_data, where_data) if ret != 1: logging.error('删除instance %s 错误', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='删除instance错误') # instance_flavor ret_f = ins_f_s.InstanceFlavorService().delete_instance_flavor( instance_id) if ret_f != 1: logging.error('delete instance %s flavor error', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='删除instance flavor错误') # instance_group ret_g = ins_g_s.InstanceGroupService().delete_instance_group_info( instance_id) if ret_g != 1: logging.error('delete instance %s group error', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='删除instance group错误') # instance_host update_data_h = {'isdeleted': '1', 'deleted_at': get_datetime_str()} where_data_h = {'instance_id': instance_id} ret_h = ins_h_s.InstanceHostService().update_instance_host_info( update_data_h, where_data_h) if ret_h != 1: logging.error('delete instance %s host error', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='删除instance host错误') # instance_disk update_data_d = {'isdeleted': '1', 'deleted_at': get_datetime_str()} where_data_d = {'instance_id': instance_id} ret_d = ins_d_s.InstanceDiskService().update_instance_disk_info( update_data_d, where_data_d) if ret_d != 1: logging.error('delete instance %s disk error', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='删除instance disk错误') # instance_ip update_data_ip = {'isdeleted': '1', 'deleted_at': get_datetime_str()} where_data_ip = {'instance_id': instance_id} ret_i_ip = ins_ip_s.InstanceIPService().update_instance_ip_info( update_data_ip, where_data_ip) if ret_i_ip != 1: logging.error('delete instance %s ip error', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='删除instance ip错误') #更新v2v_instance_info update_data = {'isdeleted': '1', 'deleted_at': get_datetime_str()} where_data = {'instance_id': instance_id} ret_v2v_in_i = v2v_in_i.v2vInstanceinfo().update_v2v_status( update_data, where_data) if ret_v2v_in_i != 1: logging.error('delete v2v instance info error') return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='删除v2v instance info错误') # 删除vm的ip ip_data = ins_s.get_ip_of_instance(instance_id) ip_id = ip_data['id'] if ip_data: ip_s.del_ip_info(ip_id) #更新v2v_task表 where_v2v = {'request_id': request_his} update_v2v = {'destory': '1'} v2v_op.v2vTaskService().update_v2v_status(update_v2v, where_v2v) return json_helper.format_api_resp(code=ErrorCode.SUCCESS, msg='删除v2v任务完成')
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 configure_init(instance_id): ''' 修改配置时获取初始数据 :param instance_id: :return: ''' if not instance_id: logging.info('no instance id when get configure info') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg="参数错误") resp = ConfigureInitInfoResp() ins_data = ins_s.InstanceService().get_instance_info(instance_id) host_ip = ins_s.get_hostip_of_instance(instance_id) if not ins_data or not host_ip: logging.info('instance %s data is no exist in db when get configure info', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) resp.c_instance_name = ins_data['name'] resp.c_app_info = ins_data['app_info'] resp.c_owner = ins_data['owner'] ins_status = ins_data['status'] if ins_status != VMStatus.STARTUP and ins_status != VMStatus.SHUTDOWN: logging.error('instance status %s is invalid when get instance configure init info', ins_status) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='只能在开机或关机状态下修改配置') if ins_data['create_source'] == '0': ins_images_data = ins_s.get_images_of_instance(instance_id) if ins_images_data: resp.c_system = ins_images_data[0]['system'] else: ins_images_data = v2v_ins_s.V2VInstanceService().get_v2v_instance_info(instance_id) if ins_images_data: resp.c_system = ins_images_data['os_type'] """ ins_disks_data = ins_s.get_disks_of_instance(instance_id) if not ins_disks_data: logging.error('instance %s has no disk info when change instance configure', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # 关机状态、windows系统都不能修改数据盘 if ins_status != VMStatus.SHUTDOWN and resp.c_system == 'linux': for _disk in ins_disks_data: _disk_info = { 'size_gb': _disk['size_gb'], 'mount_point': _disk['mount_point'] } resp.c_disk_gb_list.append(_disk_info) """ ins_flavor_data = ins_s.get_flavor_of_instance(instance_id) if not ins_flavor_data: logging.error('instance %s has no flavor info when change instance configure', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) resp.c_flavor_id = ins_flavor_data['flavor_id'] # flavor信息 flavors_nums, flavors_data = fla_s.FlavorService().get_all_flavors() for _flavor in flavors_data: # 系统盘容量不能修改 if _flavor['root_disk_gb'] == ins_flavor_data['root_disk_gb']: # 开机状态不能修改内存 if ins_status == VMStatus.STARTUP: if _flavor['memory_mb'] == ins_flavor_data['memory_mb']: _flavor_info = flavor_init_info.FlavorInitInfo().init_from_db(_flavor) resp.flavors.append(_flavor_info) else: _flavor_info = flavor_init_info.FlavorInitInfo().init_from_db(_flavor) resp.flavors.append(_flavor_info) ins_group_data = ins_s.get_group_of_instance(instance_id) if ins_group_data: resp.c_group_id = ins_group_data['group_id'] # user_group_ids_list = current_user_group_ids() # # 超级管理员组 # if 1 in user_group_ids_list: # is_super_group = True # else: # is_super_group = False # 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 # group信息 groups_params = { 'WHERE_AND': { '=': { 'dc_type': ins_group_data['dc_type'], 'isdeleted': '0' } }, } groups_nums, groups_data = group_s.GroupService().query_data(**groups_params) for _group in groups_data: # 管理员组的成员可以显示所有组,而非管理员组的只显示当前用户所在应用组 if not is_super_group and _group['id'] not in user_group_ids_list: continue _group_info = { 'group_id': _group['id'], 'group_name': _group['name'] } resp.groups.append(_group_info) # 连接libvirtd查询虚拟机网卡状态信息 _net_online = [] _net_offline = [] _libvirt_net_ret, _libvirt_net_info = vmManager.libvirt_get_netcard_state(host_ip, ins_data['name']) if _libvirt_net_ret != 0: _nic_status = False else: _nic_status = True for _p_libvirt_net_info in _libvirt_net_info: if _p_libvirt_net_info['state'] == NetCardStatus.UP: _net_online.append(_p_libvirt_net_info['mac']) else: _net_offline.append(_p_libvirt_net_info['mac']) # 虚拟机网卡信息返回前端 _db_net_card_data = ins_s.get_net_info_of_instance(instance_id) if _db_net_card_data: for _p_db_net_card_data in _db_net_card_data: if not _nic_status: _p_ins_nic_status = '' else: if _p_db_net_card_data['mac'] in _net_online: _p_ins_nic_status = '1' elif _p_db_net_card_data['mac'] in _net_offline: _p_ins_nic_status = '0' else: _p_ins_nic_status = '2' if not _p_db_net_card_data['segment_type']: _ip_type = '-1' else: _ip_type = _p_db_net_card_data['segment_type'] _i_net_info = { 'ip_addr': _p_db_net_card_data['ip_address'], 'vlan': _p_db_net_card_data['vlan'], 'mac_addr': _p_db_net_card_data['mac'], 'nic_status': _p_ins_nic_status, 'ip_type': _ip_type, 'nic_type': _p_db_net_card_data['nic_type'] } resp.c_net.append(_i_net_info) # 获取虚拟机所在网络区域下所有ip信息 resp.c_ips = [] ins_netarea_info = ins_s.get_netarea_of_instance(instance_id) ins_datacenter_info = ins_s.get_datacenter_of_instance(instance_id) if ins_datacenter_info and ins_datacenter_info['dc_type']: if ins_netarea_info and ins_netarea_info['id']: ip_segment_num, ip_segment_datas = ip_segment_s().get_segment_datas_in_net_area(ins_netarea_info['id']) if ip_segment_num > 0: # 获取可用ip ips_available = ip_service.get_all_available_ips(ip_segment_datas, ins_datacenter_info['dc_type']) if len(ips_available) > 0: ip_list = [] for ip_info in ips_available: ip_params = { "value": ip_info['ip_address'], "vlan": ip_info['vlan'], "ip_type": ip_info['ip_type'] } ip_list.append(ip_params) resp.c_ips = ip_list return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data=resp.to_json())
def extend_disk(instance_id): """ 扩展磁盘接口 :param instance_id: :return: """ c_system = '' c_version = None qemu_ga_update = False mount_point_list = [] if not instance_id: logging.info('no instance id when get configure info') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR, msg="参数错误") ins_data = ins_s.InstanceService().get_instance_info(instance_id) uuid = ins_data['uuid'] user_id = get_user()['user_id'] request_id = ins_s.generate_req_id() host_ip = ins_s.get_hostip_of_instance(instance_id) if not ins_data or not host_ip: data_params = {'mount_point_list': mount_point_list, "qemu_ga_update": qemu_ga_update} logging.info('instance %s data is no exist in db when get configure info', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, data=data_params, msg='数据库查询错误') if ins_data['create_source'] == '0': ins_images_data = ins_s.get_images_of_instance(instance_id) if ins_images_data: c_system = ins_images_data[0]['system'] c_version = ins_images_data[0]['version'] else: ins_images_data = v2v_ins_s.V2VInstanceService().get_v2v_instance_info(instance_id) if ins_images_data: c_system = ins_images_data['os_type'] if ins_images_data['os_version'] and '6.6' in ins_images_data['os_version']: c_version = '6.6' elif ins_images_data['os_version'] and '7.2' in ins_images_data['os_version']: c_version = '7.2' # 更新qemu-guest-agent action到数据库,zitong wang 29th,9,2017 ins_a_s.add_disk_display_action_to_database(uuid, request_id, user_id, InstaceActions.INSTANCE_DISK_INFO_DISPLAY, ActionStatus.START, 'start') # 更新qemu-guest-agent,获取所有挂载点的信息,add by zitongwang in 21th,9,2017 if c_system == "linux" and c_version: c_version = CentOS_Version.CentOS_7 if c_version >= '7.0' else CentOS_Version.CentOS_6 ins_a_s.add_disk_display_action_to_database(uuid, request_id, user_id, InstaceActions.INSTANCE_UPDATE_QEMU_AGENT, ActionStatus.START, 'start') # 更新qemu-ga版本 vmManager.update_qemu_ga_instance(c_version,host_ip,ins_data['name']) connect_instance = vmManager.libvirt_get_connect(host_ip, conn_type='instance', vmname=ins_data['name']) if not connect_instance: data_params = {'mount_point_list': mount_point_list, "qemu_ga_update": qemu_ga_update} msg = "libvirt连接建立失败,无法使用libvirt管理虚拟机" ins_a_s.add_disk_display_action_to_database(uuid, request_id, ActionStatus.FAILD, InstaceActions.INSTANCE_LIBVIRT_ERROR, msg) return json_helper.format_api_resp(code=ErrorCode.ALL_FAIL, data=data_params, msg=msg) # 重新建立连接判断是否更新成功 flag, msg = connect_instance.test_update_command() qemu_ga_update = flag if flag: # 更新action数据库状态:更新成功 _message = "qemu_agent update successfully" ins_a_s.update_disk_action_to_database(request_id, InstaceActions.INSTANCE_UPDATE_QEMU_AGENT, ActionStatus.SUCCSESS, _message) # 针对v2v机器,pvs显示的LV名称有问题 connect_instance.exec_qemu_command("pvscan") # 获得所有挂载点信息 command = "lsblk -r | awk '{print $7}' | awk NF | grep '^/' | grep -v '^/boot'" flag, msg = connect_instance.exec_qemu_command(command) mount_point = msg.splitlines() # 获取挂载点文件系统,大小,类型,挂载点信息 command = "lsblk -r | awk '{print $1" + "\\\" " + "\\\"" + "$4" + "\\\" " + "\\\"" + "$6" + "\\\" " + "\\\"" + "$7}'" flag, msg = connect_instance.exec_qemu_command(command) parts_info = msg.split('\n') parts_info.pop() mount_point_list = [] mount_list = [] for mount in mount_point: disk_info = {} mount_data = filter(lambda x: x.split(' ')[-1] == mount, parts_info) data = mount_data[0].split(' ') disk_info['mount_point'] = data[-1] # 存在数据就返回 if disk_info['mount_point'] in mount_list: continue else: mount_list.append(disk_info['mount_point']) disk_info['mount_partition_name'] = data[0] disk_info['mount_point_size'] = float(data[1][0:-1]) if data[1][-1].endswith('G') else float( data[1][0:-1]) / 1024 disk_info['mount_partition_type'] = data[2] command = "df -P '%s'| awk 'NR==2 {print $5}'" % mount flag, msg = connect_instance.exec_qemu_command(command) disk_info['mount_point_use'] = msg.strip() mount_point_list.append(disk_info) data_params = {'mount_point_list': mount_point_list, "qemu_ga_update": qemu_ga_update} _message = "linux os disk information display successfully" ins_a_s.update_disk_action_to_database(request_id, InstaceActions.INSTANCE_DISK_INFO_DISPLAY, ActionStatus.SUCCSESS, _message) return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data=data_params) else: # 更新qmeu-ga失败 _message = "qemu_agent update failed" ins_a_s.update_disk_action_to_database(request_id, InstaceActions.INSTANCE_UPDATE_QEMU_AGENT, ActionStatus.FAILD, _message) data_params = {'mount_point_list': mount_point_list, "qemu_ga_update": qemu_ga_update} return json_helper.format_api_resp(code=ErrorCode.ALL_FAIL, data=data_params, msg='qemu update fail') elif c_system == "windows": connect_instance = vmManager.libvirt_get_connect(host_ip, conn_type='instance', vmname=ins_data['name']) disk_info = connect_instance.get_configure_disk_device(uuid) storage_instance = vmManager.libvirt_get_connect(host_ip, conn_type='storage', vmname=ins_data['name'], poolname=uuid) mount_point_list = [] for x in disk_info: d = {} block_info = storage_instance.get_disk_size(x['image']) d.setdefault('mount_point', x['dev']) d.setdefault('mount_point_size', '%.1f' % (float(block_info[0]) / 1073741824)) d.setdefault('mount_point_use', '%.2f' % (float(block_info[1]) / block_info[0] * 100)) d.setdefault('mount_partition_name', "") d.setdefault('mount_partition_type', "") mount_point_list.append(d) qemu_ga_update = True data_params = {'mount_point_list': mount_point_list, "qemu_ga_update": qemu_ga_update} _message = "disk information display successfully" ins_a_s.update_disk_action_to_database(request_id, InstaceActions.INSTANCE_DISK_INFO_DISPLAY, ActionStatus.SUCCSESS, _message) return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data=data_params, msg=_message) else: data_params = {'mount_point_list': mount_point_list, "qemu_ga_update": qemu_ga_update} _message = "os type unknown, please call kvm administrators" ins_a_s.update_disk_action_to_database(request_id, InstaceActions.INSTANCE_DISK_INFO_DISPLAY, ActionStatus.FAILD, _message) return json_helper.format_api_resp(code=ErrorCode.ALL_FAIL, data=data_params, msg=_message)
def instance_configure(instance_id): ''' 虚机修改配置 规则: 热修改(开机状态):cpu disk 加 冷修改(关机状态):cpu mem 加减 disk 加 :param instance_id: :return: ''' n_flavor_id = request.values.get('flavor_id') n_app_info = request.values.get('app_info') n_owner = request.values.get('owner') n_group_id = request.values.get('group_id') n_net_conf_list_req = request.values.get('net_status_list') # start n_extend_list_req = request.values.get('extend_list') n_qemu_ga_update_req = request.values.get('qemu_ga_update') c_system = '' c_version = None # end if not instance_id or not n_flavor_id or not n_group_id: logging.error('params is invalid when change instance configure') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR) ins_data = ins_s.InstanceService().get_instance_info(instance_id) ###################################add 2017/09/29#############################3 uuid = ins_data['uuid'] user_id = get_user()['user_id'] request_id = ins_s.generate_req_id() if not ins_data: logging.error('the instance %s is not exist in db when change instance configure', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # --------------------edit 2017/11/13----------------------- if ins_data['create_source'] == '0': ins_images_data = ins_s.get_images_of_instance(instance_id) if ins_images_data: c_system = ins_images_data[0]['system'] else: ins_images_data = v2v_ins_s.V2VInstanceService().get_v2v_instance_info(instance_id) if ins_images_data: c_system = ins_images_data['os_type'] ins_status = ins_data['status'] # 获取虚拟机所在物理机信息 host_data = ins_s.get_host_of_instance(instance_id) ins_datacenter_info = ins_s.get_datacenter_of_instance(instance_id) if not host_data or not ins_datacenter_info: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="无法获取虚拟机所在物理机信息、机房信息") ins_data['dc_type'] = ins_datacenter_info['dc_type'] # 新flavor信息 n_flavor_data = fla_s.FlavorService().get_flavor_info(n_flavor_id) if not n_flavor_data: logging.error('flavor %s is invalid in db when change instance configure', n_flavor_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='新的配置数据有误,无法修改配置') # 虚机现有flavor信息 c_flavor_data = ins_s.get_flavor_of_instance(instance_id) if not c_flavor_data: logging.error('instance %s flavor is invalid in db when change instance configure', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) c_group_data = ins_s.get_group_of_instance(instance_id) if c_group_data and int(c_group_data['group_id']) != int(n_group_id): # 检查新应用组的配额 is_group_enough, req_msg = _check_change_group_quota(n_group_id, n_flavor_data, c_flavor_data) if not is_group_enough: logging.error('new group %s quota is not enough to change new flavor', n_group_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=req_msg) params = {} if json_helper.loads(n_extend_list_req): # 检查当前应用组的配额 is_group_enough, req_msg = _check_change_group_quota(n_group_id, n_flavor_data, c_flavor_data, json_helper.loads(n_extend_list_req)) if not is_group_enough: logging.error('new group %s quota is not enough to change new flavor', n_group_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=req_msg) # 检查物理机当前使用率情况是否满足扩容 is_host_available, ret_msg = __check_host_capacity(host_data, n_flavor_data, c_flavor_data , json_helper.loads(n_extend_list_req)) if not is_host_available: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=ret_msg) vmname = ins_data['name'] uuid = '' host_ip = '' n_extend_list_req = json_helper.loads(n_extend_list_req) try: uuid = ins_data['uuid'] host_ip = ins_s.get_hostip_of_instance(instance_id) except: pass connect_instance = vmManager.libvirt_get_connect(host_ip, conn_type='instance', vmname=ins_data['name']) if not connect_instance: pass # 添加扩容开始action ins_a_s.update_instance_status(VMStatus.CONFIGURE_ING, instance_id) ins_a_s.add_disk_extend_action_to_database(uuid, request_id, user_id, InstaceActions.INSTANCE_DISK_EXTEND, ActionStatus.START, 'start') # 满足扩容条件 if n_qemu_ga_update_req: if c_system.strip() == 'linux': flag, msg = connect_instance.exec_qemu_command( "cat /proc/self/mounts | grep -w / | grep -v rootfs | awk '{print $3}'") if not flag: c_version = None c_version = CentOS_Version.CentOS_6 if msg.strip() == 'ext4' else CentOS_Version.CentOS_7 flag, result = ins_a_s.extend_mount_size(n_extend_list_req, host_ip, vmname, uuid, c_version, instance_id) elif c_system.strip() == 'windows': flag, result = ins_a_s.extend_dev_size(n_extend_list_req, host_ip, vmname, uuid, instance_id) else: flag = False if flag: msg = "扩容成功" ins_a_s.update_disk_action_to_database(request_id, InstaceActions.INSTANCE_DISK_EXTEND, ActionStatus.SUCCSESS, msg) ins_a_s.update_instance_status(VMStatus.STARTUP, instance_id) else: msg = "扩容失败,{}".format(result) ins_a_s.update_disk_action_to_database(request_id, InstaceActions.INSTANCE_DISK_EXTEND, ActionStatus.FAILD, msg) ins_a_s.update_instance_status(VMStatus.STARTUP, instance_id) return json_helper.format_api_resp(code=ErrorCode.ALL_FAIL, msg=msg) else : # 非linux系统,关机状态,qemu-guest-agent没有更新成功 msg = "非linux系统,扩容失败" ins_a_s.update_disk_action_to_database(request_id, InstaceActions.INSTANCE_DISK_EXTEND, ActionStatus.FAILD, msg) ins_a_s.update_instance_status(VMStatus.STARTUP, instance_id) return json_helper.format_api_resp(code=ErrorCode.ALL_FAIL, msg=msg) else: pass if c_flavor_data['vcpu'] != n_flavor_data['vcpu'] or c_flavor_data['memory_mb'] != n_flavor_data['memory_mb']: # 检查当前应用组的配额 is_group_enough, req_msg = _check_change_group_quota(n_group_id, n_flavor_data, c_flavor_data) if not is_group_enough: logging.error('new group %s quota is not enough to change new flavor', n_group_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=req_msg) # 检查物理机当前使用率情况是否满足扩容 is_host_available, ret_msg = __check_host_capacity(host_data, n_flavor_data, c_flavor_data) if not is_host_available: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=ret_msg) # 关机状态 if ins_status == VMStatus.SHUTDOWN: pass elif ins_status == VMStatus.STARTUP: # 开机状态 # cpu只能增 if c_flavor_data['vcpu'] > n_flavor_data['vcpu']: logging.error('vcpu only be increase in startup status, now vcpu %s > new vcpu %s', c_flavor_data['vcpu'], n_flavor_data['vcpu']) ins_a_s.update_instance_status(VMStatus.STARTUP, instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='开机状态下,CPU数量只能增加不能减少') # 内存不能修改 if c_flavor_data['memory_mb'] != n_flavor_data['memory_mb']: logging.error('memory only no allow be change in startup status, now mem %s, new mem %s', c_flavor_data['memory_mb'], n_flavor_data['memory_mb']) ins_a_s.update_instance_status(VMStatus.STARTUP, instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='开机状态下,不能修改内存容量') else: logging.error('instance status %s is invalid when change instance configure', ins_status) ins_a_s.update_instance_status(VMStatus.STARTUP, instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='只能在开机或关机状态下修改配置') if n_flavor_data['vcpu'] == c_flavor_data['vcpu']: pass else: params['new_vcpu'] = n_flavor_data['vcpu'] params['old_vcpu'] = c_flavor_data['vcpu'] new_mem = n_flavor_data['memory_mb'] old_mem = c_flavor_data['memory_mb'] if new_mem == old_mem: pass else: # 检查内存是否超分 if not _check_mem_allocation(instance_id, new_mem, old_mem): logging.error('instance %s mem has over allocation, new mem %s, old mem %s', instance_id, new_mem, old_mem) ins_a_s.update_instance_status(VMStatus.STARTUP, instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg='物理内存不能超分') params['new_mem'] = new_mem params['old_mem'] = old_mem # 检查网络配置是否需要修改 n_net_conf_list = json_helper.loads(n_net_conf_list_req) if n_net_conf_list: params['net_status_list'] = n_net_conf_list # 没有一个指标可以修改 if not params: logging.error('vcpu, mem, disk no one can change when change instance configure') else: host_ip = ins_s.get_hostip_of_instance(ins_data['id']) if not host_ip: logging.error('instance %s has no host ip when change instance configure', ins_data['id']) ins_a_s.update_instance_status(VMStatus.STARTUP, instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) ret_flavor = ins_a_s.change_instance_configure(host_ip, ins_data, c_flavor_data['flavor_id'], n_flavor_id, ins_status, **params) if not ret_flavor: ins_a_s.update_instance_status(VMStatus.STARTUP, instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) update_data_i = { 'app_info': n_app_info, 'owner': n_owner, 'updated_at': get_datetime_str() } where_data_i = { 'id': instance_id } ret_i = ins_s.InstanceService().update_instance_info(update_data_i, where_data_i) # if ret_i != 1: # logging.error('update instance info error when configure, update_data:%s, where_data:%s', # update_data_i, where_data_i) # return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) update_data_g = { 'group_id': n_group_id, 'updated_at': get_datetime_str() } where_data_g = { 'instance_id': instance_id } ret_g = ins_g_s.InstanceGroupService().update_instance_group_info(update_data_g, where_data_g) # if ret_g != 1: # logging.error('update group info error when configure, update_data:%s, where_data:%s', # update_data_g, where_data_g) # return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # if 'disk_gb_list' in params: # return json_helper.format_api_resp(code=ErrorCode.SUCCESS, msg='硬盘扩容任务发送成功') return json_helper.format_api_resp(code=ErrorCode.SUCCESS, msg='修改配置成功')
def collect_instances_data(host_ip): ''' 收集指定主机下所有instance的信息 :param host_ip: :return: ''' print '*' * 40 print 'start colletc host ' + host_ip + ' instance data at ' + get_datetime_str() libvirt_connect_instance = libvirt_get_connect(host=host_ip, conn_type='instances') # libvirt连接不上时需要将host下面所有虚拟机状态改为错误 if not libvirt_connect_instance: logging.error('unable to connect host %s when collect data', host_ip) instances = ins_s.get_instances_by_host_ip(host_ip) for _ins in instances: _ins_data = ins_s.InstanceService().get_instance_info_by_uuid(_ins['uuid']) if not _ins_data: logging.warn('libvirt instance uuid %s , but not exist in db when collect data', _ins['uuid']) continue # 创建中虚拟机做判断,如果处于创建中大于45分钟,更新虚拟机状态为创建失败 if _ins_data['status'] == VMStatus.CREATING: check_vm_create_status = _check_vm_creating_time(_ins_data['created_at']) if check_vm_create_status: # 如果是克隆创建的vm则更新状态为克隆创建失败 if _ins_data['clone_source_host']: _update_data_i = { 'status': VMStatus.CLONE_CREATE_ERROR, 'updated_at': get_datetime_str() } _where_data_i = { 'uuid': _ins['uuid'] } ret_i_create = ins_s.InstanceService().update_instance_info(_update_data_i, _where_data_i) if ret_i_create != 1: logging.error( 'update instance %s data error when collect instance data, update_data:%s, where_data:%s', _ins['uuid'], _update_data_i, _where_data_i) else: _update_data_i = { 'status': VMStatus.CREATE_ERROR, 'updated_at': get_datetime_str() } _where_data_i = { 'uuid': _ins['uuid'] } ret_i_create = ins_s.InstanceService().update_instance_info(_update_data_i, _where_data_i) if ret_i_create != 1: logging.error( 'update instance %s data error when collect instance data, update_data:%s, where_data:%s', _ins['uuid'], _update_data_i, _where_data_i) continue # 虚拟机处于创建中状态小于45分钟、并且虚拟机状态被放到不更新状态列表中 if _ins_data['status'] in INSTANCE_STATUS_NOT_UPDATE: logging.info('not update instance %s status when in status %s', _ins['uuid'], _ins_data['status']) continue # 如果是v2v机器、状态为转化中则不更新状态 if _ins_data['status'] == VMStatus.CONVERTING: logging.info('not update instance %s status when in status %s', _ins['uuid'], _ins_data['status']) continue _update_data_i = { 'status': VMStatus.ERROR, 'updated_at': get_datetime_str() } _where_data_i = { 'uuid': _ins['uuid'] } ret_i = ins_s.InstanceService().update_instance_info(_update_data_i, _where_data_i) if ret_i != 1: logging.error('update instance %s data error when collect instance data, update_data:%s, where_data:%s', _ins['uuid'], _update_data_i, _where_data_i) else: instances = libvirt_get_all_instances_by_host(libvirt_connect_instance, host_ip) for _ins in instances: _ins_data = ins_s.InstanceService().get_instance_info_by_uuid(_ins['uuid']) if not _ins_data: logging.warn('libvirt instance uuid %s , but not exist in db when collect data', _ins['uuid']) continue # 创建中虚拟机做判断,如果处于创建中大于45分钟,更新虚拟机状态为创建失败 if _ins_data['status'] == VMStatus.CREATING: check_vm_create_status = _check_vm_creating_time(_ins_data['created_at']) if check_vm_create_status: #如果是克隆创建的vm则更新状态为克隆创建失败 if _ins_data['clone_source_host']: _update_data_i = { 'status': VMStatus.CLONE_CREATE_ERROR, 'updated_at': get_datetime_str() } _where_data_i = { 'uuid': _ins['uuid'] } ret_i_create = ins_s.InstanceService().update_instance_info(_update_data_i, _where_data_i) if ret_i_create != 1: logging.error( 'update instance %s data error when collect instance data, update_data:%s, where_data:%s', _ins['uuid'], _update_data_i, _where_data_i) else: _update_data_i = { 'status': VMStatus.CREATE_ERROR, 'updated_at': get_datetime_str() } _where_data_i = { 'uuid': _ins['uuid'] } ret_i_create = ins_s.InstanceService().update_instance_info(_update_data_i, _where_data_i) if ret_i_create != 1: logging.error( 'update instance %s data error when collect instance data, update_data:%s, where_data:%s', _ins['uuid'], _update_data_i, _where_data_i) continue continue # 虚拟机处于创建中状态小于45分钟、并且虚拟机状态被放到不更新状态列表中 if _ins_data['status'] in INSTANCE_STATUS_NOT_UPDATE: logging.info('not update instance %s status when in status %s', _ins['uuid'], _ins_data['status']) continue # 虚拟机处于关机中,并且虚拟机真实状态为运行中,此时不做状态更新 if _ins_data['status'] == VMStatus.SHUTDOWN_ING and _ins['status'] != VMLibvirtStatus.SHUTDOWN: continue _update_data_i = { 'status': _libvirt_status_2_ins_status(_ins['status']), 'updated_at': get_datetime_str() } _where_data_i = { 'uuid': _ins['uuid'] } ret_i = ins_s.InstanceService().update_instance_info(_update_data_i, _where_data_i) if ret_i != 1: logging.error('update instance %s data error when collect instance data, update_data:%s, where_data:%s', _ins['uuid'], _update_data_i, _where_data_i) instances = ins_s.get_instances_by_host_ip(host_ip) for _ins in instances: _ins_data = ins_s.InstanceService().get_instance_info_by_uuid(_ins['uuid']) if not _ins_data: logging.warn('libvirt instance uuid %s , but not exist in db when collect data', _ins['uuid']) continue # 创建中虚拟机做判断,如果处于创建中大于45分钟,更新虚拟机状态为创建失败 if _ins_data['status'] == VMStatus.CREATING: check_vm_create_status = _check_vm_creating_time(_ins_data['created_at']) if check_vm_create_status: # 如果是克隆创建的vm则更新状态为克隆创建失败 if _ins_data['clone_source_host']: _update_data_i = { 'status': VMStatus.CLONE_CREATE_ERROR, 'updated_at': get_datetime_str() } _where_data_i = { 'uuid': _ins['uuid'] } ret_i_create = ins_s.InstanceService().update_instance_info(_update_data_i, _where_data_i) if ret_i_create != 1: logging.error( 'update instance %s data error when collect instance data, update_data:%s, where_data:%s', _ins['uuid'], _update_data_i, _where_data_i) else: _update_data_i = { 'status': VMStatus.CREATE_ERROR, 'updated_at': get_datetime_str() } _where_data_i = { 'uuid': _ins['uuid'] } ret_i_create = ins_s.InstanceService().update_instance_info(_update_data_i, _where_data_i) if ret_i_create != 1: logging.error( 'update instance %s data error when collect instance data, update_data:%s, where_data:%s', _ins['uuid'], _update_data_i, _where_data_i) # 更新收集时间 _update_data_h = { 'instances_collect_time': get_datetime_str() } _where_data_h = { 'ipaddress': host_ip, 'isdeleted': '0' } ret_h = host_s.HostService().update_host_info(_update_data_h, _where_data_h) if ret_h != 1: logging.error('update collect time error when collect instance data, update_data:%s, where_data:%s', _update_data_h, _where_data_h) print 'end colletc host ' + host_ip + ' instance data at ' + get_datetime_str() print '*' * 40
def instance_shutdown(): ''' 虚机关机/强制关机 :return: ''' ins_ids = request.values.get('instance_ids') # 区分关机和强制关机 flag = request.values.get('flag') if not ins_ids or not flag: logging.info('no instance_ids or flag when shutdown instance') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR) ins_ids_list = ins_ids.split(',') # 操作的instance数 all_num = len(ins_ids_list) if all_num > int(INSTANCE_MAX_SHUTDOWN): logging.info('shutdown nums %s is greater than max %s', all_num, INSTANCE_MAX_SHUTDOWN) return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR) msg = None fail_num = 0 for _ins_id in ins_ids_list: _ins_data = ins_s.InstanceService().get_instance_info(_ins_id) if _ins_data: # 本身是关机状态的不能再关机 # if _ins_data['status'] == VMStatus.SHUTDOWN or _ins_data['status'] == VMStatus.SHUTDOWN_ING: # logging.info('the instance status %s is invalid when shutdown instance', _ins_data['status']) # fail_num += 1 # # 单台操作且已失败则直接跳出循环 # if all_num == 1: # msg = '该虚拟机已经关机,请勿重复关机' # break # continue # else: # _ret_shut, _ret_msg = ins_a_s.shutdown_instance(_ins_data, int(flag)) # if not _ret_shut: # fail_num += 1 # # 单台操作且已失败则直接跳出循环 # if all_num == 1: # msg = _ret_msg # break # continue if _ins_data['status'] == VMStatus.SHUTDOWN: logging.info( 'the instance status %s is invalid when shutdown instance', _ins_data['status']) fail_num += 1 # 单台操作且已失败则直接跳出循环 if all_num == 1: msg = '该虚拟机已经关机,请勿重复关机' break continue elif _ins_data['status'] == VMStatus.SHUTDOWN_ING and int( flag) == 1: logging.info( 'the instance status %s is invalid when shutdown instance', _ins_data['status']) fail_num += 1 # 单台操作且已失败则直接跳出循环 if all_num == 1: msg = '该虚拟机正在关机中,请勿重复关机' break continue else: _ret_shut, _ret_msg = ins_a_s.shutdown_instance( _ins_data, int(flag)) if not _ret_shut: fail_num += 1 # 单台操作且已失败则直接跳出循环 if all_num == 1: msg = _ret_msg break continue else: logging.info( 'the instance is not exist in db when shutdown instance') fail_num += 1 continue # 全失败 if fail_num == all_num: logging.error("shutdown instance all failed") if msg: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg=msg) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # 部分成功 if 0 < fail_num < all_num: logging.error("shutdown instance part failed") return json_helper.format_api_resp(code=ErrorCode.SUCCESS_PART, msg="部分虚拟机关机成功") return json_helper.format_api_resp(code=ErrorCode.SUCCESS)
def instance_detail(instance_id): ''' 获取虚机详情 :param instance_id: :return: ''' if not instance_id: logging.info('no instance_id when get instance detail') 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 get instance detail', instance_id) return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # VM创建来源 create_source = ins_data['create_source'] ins_flavor = ins_s.get_flavor_of_instance(instance_id) if not ins_flavor: logging.error( 'instance %s flavor info is no exist in db when get instance detail', instance_id) cpu = None memory_mb = None root_disk_gb = None else: cpu = ins_flavor['vcpu'] memory_mb = ins_flavor['memory_mb'] root_disk_gb = ins_flavor['root_disk_gb'] system = None sys_version = None image_name = None # 本平台 if create_source == VMCreateSource.CLOUD_SOURCE: ins_images = ins_s.get_images_of_instance(instance_id) if not ins_images: logging.error( 'instance %s image info is no exist in db when get instance detail', instance_id) else: system = ins_images[0]['system'] sys_version = ins_images[0]['version'] image_name = ins_images[0]['displayname'] elif 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: system = ins_v2v_data['os_type'] sys_version = ins_v2v_data['os_version'] ins_group = ins_s.get_group_of_instance(instance_id) if not ins_group: logging.error( 'instance %s group info is no exist in db when get instance detail', instance_id) group_name = None else: group_name = ins_group['name'] ins_ip = ins_s.get_ip_of_instance(instance_id) if not ins_ip: logging.error( 'instance %s ip info is no exist in db when get instance detail', instance_id) ip_address = None else: ip_address = ins_ip['ip_address'] ins_netarea = ins_s.get_netarea_of_instance(instance_id) if not ins_netarea: logging.error( 'instance %s net area info is no exist in db when get instance detail', instance_id) net_area = None else: net_area = ins_netarea['name'] ins_disks = ins_s.get_disks_of_instance(instance_id) if not ins_disks: logging.error( 'instance %s disks info is no exist in db when get instance detail', instance_id) disk_gb = None else: # disk_gb = ins_disks[0]['size_gb'] disk_gb = sum([int(i['size_gb']) for i in ins_disks]) ins_datacenter = ins_s.get_datacenter_of_instance(instance_id) if not ins_datacenter: logging.error( 'instance %s datacenter info is no exist in db when get instance detail', instance_id) dc_type = None else: dc_type = ins_datacenter['dc_type'] data = { 'instance_name': ins_data['name'], 'uuid': ins_data['uuid'], 'ip_address': ip_address, 'dc_type': dc_type, 'net_area': net_area, 'system': system, 'sys_version': sys_version, 'image_name': image_name, 'cpu': cpu, 'memory_mb': memory_mb, 'root_disk_gb': root_disk_gb, 'disk_gb': disk_gb, 'app_info': ins_data['app_info'], 'owner': ins_data['owner'], 'group_name': group_name, 'create_source': create_source } return json_helper.format_api_resp(code=ErrorCode.SUCCESS, data=data)
def instance_delete(): ''' 虚机删除 关机超过一天才能删除 :return: ''' request_from_vishnu = False if get_user()['user_id'] == 'vishnu': is_admin = True request_from_vishnu = True else: # 判断操作用户身份 role_ids = current_user_role_ids() # 系统管理员 if 1 in role_ids: is_admin = True else: is_admin = False permission_limited = False ins_ids = request.values.get('instance_ids') if not ins_ids: logging.info('no instance_ids when delete instance') return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR) ins_ids_list = ins_ids.split(',') # 操作的instance数 all_num = len(ins_ids_list) if all_num > int(INSTANCE_MAX_DELETE): logging.info('delete nums %s is greater than max %s', all_num, INSTANCE_MAX_DELETE) return json_helper.format_api_resp(code=ErrorCode.PARAM_ERR) fail_num = 0 for _ins_id in ins_ids_list: # 查询虚拟机对应环境信息,应用管理员不能删除非DEV环境虚拟机 ins_group = ins_s.get_group_of_instance(_ins_id) if not ins_group: logging.error( 'instance %s group data is no exist in db when delete instance', str(_ins_id)) fail_num += 1 continue else: if not is_admin and int( ins_group['dc_type']) != DataCenterType.DEV: permission_limited = True fail_num += 1 continue _ins_data = ins_s.InstanceService().get_instance_info(_ins_id) if _ins_data: # 维石只能删除克隆备份的虚拟机 if request_from_vishnu and 'clone' not in _ins_data['name']: fail_num += 1 continue _ret_del = ins_a_s.delete_instance(_ins_data, _ins_data['status']) if not _ret_del: fail_num += 1 continue else: logging.error( 'the instance is not exist in db when delete instance') fail_num += 1 continue # 全失败 if fail_num == all_num: logging.error("delete instance all failed") if permission_limited: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR, msg="非DEV环境虚拟机请联系系统组删除") elif request_from_vishnu: return json_helper.format_api_resp(code=ErrorCode.SUCCESS) else: return json_helper.format_api_resp(code=ErrorCode.SYS_ERR) # 部分成功 if 0 < fail_num < all_num: logging.error("delete instance part failed") if permission_limited: return json_helper.format_api_resp( code=ErrorCode.SUCCESS_PART, msg="部分虚拟机删除成功, 非DEV环境虚拟机请联系系统组删除") elif request_from_vishnu: return json_helper.format_api_resp(code=ErrorCode.SUCCESS) else: return json_helper.format_api_resp(code=ErrorCode.SUCCESS_PART, msg="部分虚拟机删除成功") return json_helper.format_api_resp(code=ErrorCode.SUCCESS)