def update_virtual_switch(self, data): """ 更新虚拟交换机信息 限制条件比较多 1、有模板或者桌面使用基于该虚拟机交换机的网络时,不能修改节点的接口对应关系 2、修改节点的接口对应关系时,需要删除原先创建的设备,然后重新创建新的网络设备 :param data: { "uuid": "caa5d57e-3731-11ea-801e-000c295dd728", "node_uuid": "", "nic_uuid": "" } :return: """ vswitch_uuid = data.get('uuid', '') logger.info("update vswitch %s", vswitch_uuid) vswitch = db_api.get_virtual_switch(vswitch_uuid) if not vswitch: return build_result("VSwitchNotExist") # 虚拟交换机有被使用,无法修改 networks = db_api.get_network_all({"switch_uuid": vswitch.uuid}) for network in networks: templates = db_api.get_template_with_all( {"network_uuid": network.uuid}) if templates: return build_result("VSwitchUsedError", name=vswitch.name) desktops = db_api.get_desktop_with_all( {"network_uuid": network.uuid}) if desktops: return build_result("VSwitchUsedError", name=vswitch.name) # 如果没有数据网络使用该虚拟交换机,则只需要修改对应关系 try: for uplink in vswitch.uplinks: if not uplink.deleted: if data['node_uuid'] == uplink.node_uuid: if data['nic_uuid'] != uplink.nic_uuid: logger.info("update nic from %s to %s", uplink.nic_uuid, data['nic_uuid']) node = db_api.get_node_by_uuid(data['node_uuid']) nic = db_api.get_nics_first( {'uuid': data['nic_uuid']}) for network in networks: self._delete_network(node.ip, network.uuid, network.vlan_id) self._create_network(node.ip, network.uuid, network.switch_type, nic.nic, network.vlan_id) uplink.nic_uuid = data['nic_uuid'] uplink.soft_update() break except Exception as e: return build_result("OtherError") return build_result("Success")
def delete_network(self, network_uuid): network = db_api.get_network_by_uuid(network_uuid) if not network: logger.error("network [%s] info not exist", network_uuid) return build_result("NetworkInfoNotExist") virtual_switch = network.virtual_switch_of_network if not virtual_switch or virtual_switch.deleted: logger.error("network [%s] not virtual switch" % network_uuid) return build_result("NetworkNotVSError") template = db_api.get_template_with_all({'network_uuid': network_uuid}) if template: logger.error("network is in use, can not deleted") return build_result("NetworkInUse", name=network.name) network_type = virtual_switch.type if constants.VLAN_NETWORK_TYPE == network_type: vlan_id = network.vlan_id else: vlan_id = None for uplink in virtual_switch.uplinks: if not uplink.deleted: node = db_api.get_node_by_uuid(uplink.node_uuid) try: self._delete_network(node.ip, network_uuid, vlan_id) except Exception as e: logger.error("delete network in node %s failed:%s", node.ip, e, exc_info=True) # return build_result("NetworkCreateFail") subnets = db_api.get_subnet_by_network(network.uuid) for subnet in subnets: subnet.soft_delete() network.soft_delete() return build_result("Success")
def check(self): # 检测是否处于基础镜像同传状态 pools = db_api.get_resource_pool_list() for pool in pools: status = self.manger.get_base_image_status(pool) if status != 0: logger.info("pool: %s, status: %d" % (pool.name, status)) return get_error_result("ImageTaskRunning") # 检测是否有模板差异盘同传 templates = db_api.get_template_with_all({}) for template in templates: if template.status in [ constants.STATUS_SAVING, constants.STATUS_CREATING, constants.STATUS_COPING, constants.STATUS_ROLLBACK, constants.STATUS_UPDATING ]: logger.info("template: %s, status: %d" % (template.name, template.status)) return get_error_result("ImageTaskRunning") templates = db_api.get_voi_template_with_all({}) for template in templates: if template.status in [ constants.STATUS_SAVING, constants.STATUS_CREATING, constants.STATUS_COPING, constants.STATUS_ROLLBACK, constants.STATUS_UPDATING ]: logger.info("template: %s, status: %d" % (template.name, template.status)) return get_error_result("ImageTaskRunning") # status = self.manger.get_storages_status(template) # if status != 0: # logger.info("template: %s, status: %d" % (template.name, status)) # return get_error_result("ImageTaskRunning") # TODO 检测终端升级包没有处于分发状态 return get_error_result("Success")
def update_template_disk_usage(): """更新模板的磁盘使用,目前暂时只适配windows""" templates = db_api.get_template_with_all({}) voi_templates = db_api.get_item_with_all(models.YzyVoiTemplate, {}) if templates or voi_templates: node = db_api.get_controller_node() node_uuid = node.uuid template_sys = db_api.get_template_sys_storage(node_uuid) template_data = db_api.get_template_data_storage(node_uuid) if not (template_sys and template_data): logging.error("there is not storage path, skip") sys_path = os.path.join(template_sys.path, 'instances') data_path = os.path.join(template_data.path, 'datas') for template in templates: if constants.STATUS_INACTIVE == template.status: devices = db_api.get_devices_by_instance(template.uuid) for disk in devices: if constants.IMAGE_TYPE_SYSTEM == disk.type: instance_dir = os.path.join(sys_path, template.uuid) elif constants.IMAGE_TYPE_DATA == disk.type: instance_dir = os.path.join(data_path, template.uuid) else: continue file_path = os.path.join( instance_dir, constants.DISK_FILE_PREFIX + disk.uuid) try: stdout, stderror = cmdutils.execute('virt-df -a %s' % file_path, shell=True, timeout=20, run_as_root=True) logger.info("virt-df execute end, stdout:%s, stderror:%s", stdout, stderror) result = [ int(item) for item in stdout.split(' ') if item.strip() and item.isdigit() ] if result: # 一个磁盘分区包括三个数字,总数、使用数和剩余数。windows系统盘默认有个保留分区 logger.info("get disk %s result:%s", disk.device_name, result) if constants.IMAGE_TYPE_SYSTEM == disk.type: used = result[4] else: used = result[1] size_gb = round(used / (1024 * 1024), 2) logger.info("get template %s disk %s used size:%s", template.name, disk.device_name, size_gb) disk.used = size_gb disk.soft_update() except: pass for template in voi_templates: if constants.STATUS_INACTIVE == template.status: devices = db_api.get_item_with_all( models.YzyVoiDeviceInfo, {'instance_uuid': template.uuid}) for disk in devices: base_path = sys_path if disk.type == constants.IMAGE_TYPE_SYSTEM else data_path file_path = os.path.join(base_path, constants.VOI_FILE_PREFIX + disk.uuid) try: stdout, stderror = cmdutils.execute('virt-df -a %s' % file_path, shell=True, timeout=20, run_as_root=True) logger.info("virt-df execute end, stdout:%s, stderror:%s", stdout, stderror) result = [ int(item) for item in stdout.split(' ') if item.strip() and item.isdigit() ] if result: # 一个磁盘分区包括三个数字,总数、使用数和剩余数。windows系统盘默认有个保留分区 logger.info("get disk %s result:%s", disk.device_name, result) if constants.IMAGE_TYPE_SYSTEM == disk.type: used = result[4] else: used = result[1] size_gb = round(used / (1024 * 1024), 2) logger.info("get template %s disk %s used size:%s", template.name, disk.device_name, size_gb) disk.used = size_gb disk.soft_update() except: pass
def update_template_info(): templates = db_api.get_template_with_all({}) voi_templates = db_api.get_item_with_all(models.YzyVoiTemplate, {}) rep_data = dict() for item in templates: host_ip = item.host.ip _d = {"uuid": item.uuid, "name": item.name} if host_ip not in rep_data: rep_data[host_ip] = list() rep_data[host_ip].append(_d) for item in voi_templates: host_ip = item.host.ip _d = {"uuid": item.uuid, "name": item.name} if host_ip not in rep_data: rep_data[host_ip] = list() rep_data[host_ip].append(_d) for k, v in rep_data.items(): command_data = { "command": "get_status_many", "handler": "InstanceHandler", "data": { "instance": v } } logger.debug("get template state in node %s", k) rep_json = compute_post(k, command_data) logger.debug("from compute get template rep_json:{}".format(rep_json)) if rep_json.get("code", -1) != 0: continue for template in templates: for item in rep_json.get("data", []): if item["uuid"] == template.uuid: if template.status in [ constants.STATUS_ACTIVE, constants.STATUS_INACTIVE ]: if 1 == item.get("state"): status = constants.STATUS_ACTIVE else: status = constants.STATUS_INACTIVE if template.status != status: logger.info( "the template %s status change from %s to %s", template.name, template.status, status) template.status = status template.soft_update() break for template in voi_templates: for item in rep_json.get("data", []): if item["uuid"] == template.uuid: if template.status in [ constants.STATUS_ACTIVE, constants.STATUS_INACTIVE ]: if 1 == item.get("state"): status = constants.STATUS_ACTIVE else: status = constants.STATUS_INACTIVE if template.status != status: logger.info( "the template %s status change from %s to %s", template.name, template.status, status) template.status = status template.soft_update() break
def update_ha_master(): is_vip, is_master, is_backup = False, False, False current_ip = None ha_info_obj = db_api.get_ha_info_first() if ha_info_obj: # logger.info("ha_info before monitor update: %s" % ha_info_obj.dict()) # 获取本机所有启用网口的ip,查看本节点的ip在ha_info表中是master_ip还是backup_ip code, out = cmdutils.run_cmd( """ip -br a |grep ' UP ' |grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*'""", ignore_log=True) if code != 0: logger.error(out) else: ip_list = [ip for ip in out.strip('\n').split('\n')] for ip in ip_list: if ip == ha_info_obj.vip: is_vip = True elif ip == ha_info_obj.master_ip: is_master = True elif ip == ha_info_obj.backup_ip: is_backup = True if not is_vip: logger.error("server running without vip[%s]" % ha_info_obj.vip) else: if not is_master and not is_backup: logger.error( "server running without master_ip[%s], backup_ip[%s]" % (ha_info_obj.master_ip, ha_info_obj.backup_ip)) elif is_master and is_backup: logger.error( "server running with both master_ip[%s], backup_ip[%s]" % (ha_info_obj.master_ip, ha_info_obj.backup_ip)) elif is_master and not is_backup: current_ip = ha_info_obj.master_ip elif not is_master and is_backup: # 如果发现本节点的ip在ha_info表中是backup_ip,说明notify.sh脚本中调用server服务/node/master接口去更新数据库的操作失败了 # 检查并修正ha_info表中的ip current_ip = ha_info_obj.backup_ip ha_info_obj.master_ip, ha_info_obj.backup_ip = ha_info_obj.backup_ip, ha_info_obj.master_ip logger.info("update ha_info[%s] master_ip from %s to %s", (ha_info_obj.uuid, ha_info_obj.backup_ip, ha_info_obj.master_ip)) if current_ip: # current_ip所在节点应该为master,检查并修正ha_info表中node_uuid、nic、nic_uuid current_node_obj = db_api.get_node_by_ip(current_ip) if current_node_obj.uuid == ha_info_obj.backup_uuid: ha_info_obj.master_uuid, ha_info_obj.backup_uuid = ha_info_obj.backup_uuid, ha_info_obj.master_uuid logger.info( "update ha_info[%s] master_uuid from %s to %s", (ha_info_obj.uuid, ha_info_obj.backup_uuid, ha_info_obj.master_uuid)) current_ip_obj = db_api.get_nic_ip_by_ip(current_ip) if current_ip_obj.nic_uuid == ha_info_obj.backup_nic_uuid: ha_info_obj.master_nic_uuid, ha_info_obj.backup_nic_uuid = ha_info_obj.backup_nic_uuid, ha_info_obj.master_nic_uuid logger.info( "update ha_info[%s] master_nic_uuid from %s to %s", (ha_info_obj.uuid, ha_info_obj.backup_nic_uuid, ha_info_obj.master_nic_uuid)) if ha_info_obj.master_nic != ha_info_obj.backup_nic and current_ip_obj.name == ha_info_obj.backup_nic: ha_info_obj.master_nic, ha_info_obj.backup_nic = ha_info_obj.backup_nic, ha_info_obj.master_nic logger.info( "update ha_info[%s] master_nic from %s to %s", (ha_info_obj.uuid, ha_info_obj.backup_nic, ha_info_obj.master_nic)) ha_info_obj.soft_update() # 检查并修正backup_uuid节点的type real_backup_node_obj = db_api.get_node_by_uuid( ha_info_obj.backup_uuid) if real_backup_node_obj.type not in [ constants.ROLE_SLAVE_AND_COMPUTE, constants.ROLE_SLAVE ]: wrong_type = real_backup_node_obj.type if real_backup_node_obj.type in [ constants.ROLE_MASTER_AND_COMPUTE, constants.ROLE_COMPUTE ]: real_backup_node_obj.type = constants.ROLE_SLAVE_AND_COMPUTE else: real_backup_node_obj.type = constants.ROLE_SLAVE real_backup_node_obj.soft_update() logger.info( "update real_backup_node[%s] role from %s to %s", real_backup_node_obj.ip, wrong_type, real_backup_node_obj.type) # 检查并修正master_uuid节点的type if current_node_obj.type not in [ constants.ROLE_MASTER, constants.ROLE_MASTER_AND_COMPUTE ]: wrong_type = current_node_obj.type if wrong_type in [ constants.ROLE_SLAVE_AND_COMPUTE, constants.ROLE_COMPUTE ]: current_node_obj.type = constants.ROLE_MASTER_AND_COMPUTE else: current_node_obj.type = constants.ROLE_MASTER current_node_obj.soft_update() logger.info( "update current_node[%s] role from %s to %s", current_node_obj.ip, wrong_type, current_node_obj.type) # 检查并修正yzy_template、yzy_voi_template表的模板宿主机uuid templates = db_api.get_template_with_all({}) for template in templates: if constants.SYSTEM_DESKTOP == template.classify: continue if template.host_uuid != current_node_obj.uuid: template.host_uuid = current_node_obj.uuid template.soft_update() logger.info("update template %s host_uuid to %s", template.name, current_node_obj.uuid) voi_templates = db_api.get_voi_template_with_all({}) for template in voi_templates: if constants.SYSTEM_DESKTOP == template.classify: continue if template.host_uuid != current_node_obj.uuid: template.host_uuid = current_node_obj.uuid template.soft_update() logger.info( "update voi template %s host_uuid to %s", template.name, current_node_obj.uuid)
def delete_subnet(self, subnet_uuids): """ 删除子网, 批量操作 :param subnet_uuids: :return: """ prompt_info = [] try: for subnet_uuid in subnet_uuids: ### 判断子网是否已被占用 subnet = db_api.get_subnet_by_uuid(subnet_uuid) if not subnet: logger.error("subnet: %s not exist", subnet_uuid) return build_result("SubnetNotExist") templates = db_api.get_template_with_all({ 'deleted': False, 'subnet_uuid': subnet_uuid }) template_names = list( map(lambda template: template.name, templates)) if len(template_names) > 0: prompt_info.append("子网 %s 被模板 %s 所引用" % (subnet.name, ','.join(template_names))) continue groups = db_api.get_group_with_all({ 'deleted': False, 'subnet_uuid': subnet_uuid }) groups_names = list(map(lambda group: group.name, groups)) if len(groups_names) > 0: prompt_info.append("子网 %s 被分组 %s 所引用" % (subnet.name, ','.join(groups_names))) continue desktops = db_api.get_desktop_with_all({ 'deleted': False, 'subnet_uuid': subnet_uuid }) desktop_names = list( map(lambda desktop: desktop.name, desktops)) if len(desktop_names) > 0: prompt_info.append("子网 %s 被桌面 %s 所引用" % (subnet.name, ','.join(desktop_names))) continue personal_desktops = db_api.get_personal_desktop_with_all({ 'deleted': False, 'subnet_uuid': subnet_uuid }) personal_desktops_names = list( map(lambda personal_desktop: personal_desktop.name, personal_desktops)) if len(personal_desktops_names) > 0: prompt_info.append( "子网 %s 被桌面 %s 所引用" % (subnet.name, ','.join(personal_desktops_names))) continue # 判断子网是否被VOI使用 voi_templates = db_api.get_voi_template_with_all({ 'deleted': False, 'subnet_uuid': subnet_uuid }) voi_template_names = list( map(lambda template: template.name, voi_templates)) if len(voi_template_names) > 0: prompt_info.append( "子网 %s 被VOI模板 %s 所引用" % (subnet.name, ','.join(voi_template_names))) continue subnet.soft_delete() if len(prompt_info) > 0: return build_result("SubnetDeleteInfo") except Exception as e: return build_result("SubnetDeleteFail") return build_result("Success")