def update_subnet(self, data): subnet_uuid = data.get("uuid", "") subnet = db_api.get_subnet_by_uuid(subnet_uuid) if not subnet: logger.error("subnet: %s not exist", subnet_uuid) return build_result("SubnetNotExist") subnet.name = data['name'] subnet.start_ip = data['start_ip'] subnet.end_ip = data['end_ip'] subnet.netmask = data['netmask'] subnet.gateway = data['gateway'] subnet.dns1 = data['dns1'] subnet.dns2 = data['dns2'] subnet.soft_update() logger.info("update subnet:%s success", subnet_uuid) return build_result("Success", data=subnet)
def get_voi_ha_backup_network_info(template_obj, backup_uuid, template_uuid=None): """ 获取备控节点的网络信息,用于在备控上同步创建VOI模板 :param template_obj: :param backup_uuid: :param template_uuid: :return: """ try: if template_uuid: template_obj = db_api.get_voi_instance_template(template_uuid) network_info = list() net = db_api.get_interface_by_network(template_obj.network_uuid, backup_uuid) vif_info = { "uuid": net.YzyNetworks.uuid, "vlan_id": net.YzyNetworks.vlan_id, "interface": net.nic, "bridge": constants.BRIDGE_NAME_PREFIX + net.YzyNetworks.uuid[:constants.RESOURCE_ID_LENGTH] } _d = { "fixed_ip": template_obj.bind_ip, "mac_addr": template_obj.mac, "bridge": vif_info["bridge"], "port_id": template_obj.port_uuid, "vif_info": vif_info } if template_obj.subnet_uuid: subnet = db_api.get_subnet_by_uuid(template_obj.subnet_uuid) _d["netmask"] = subnet.netmask _d["gateway"] = subnet.gateway if subnet.dns1: _d["dns_server"] = [subnet.dns1] if subnet.dns2: _d["dns_server"].append(subnet.dns2) network_info.append(_d) return network_info except Exception as e: logger.exception("%s", str(e), exc_info=True)
def create_group(self, data): """ 创建分组,包括教学分组和用户分组 """ if not self._check_params(data): return get_error_result("ParamError") if constants.EDUCATION_DESKTOP == data.get( 'group_type', constants.EDUCATION_DESKTOP): subnet = db_api.get_subnet_by_uuid(data['subnet_uuid']) if not subnet: logger.error("subnet: %s not exist", data['subnet_uuid']) return get_error_result("SubnetNotExist") groups = db_api.get_group_with_all({ 'name': data['name'], 'group_type': data['group_type'] }) if groups: return get_error_result("GroupAlreadyExists", name=data['name']) # add education group group_uuid = create_uuid() group_value = { "uuid": group_uuid, "group_type": data['group_type'], "name": data['name'], "desc": data['desc'], "network_uuid": data.get('network_uuid', ''), "subnet_uuid": data.get('subnet_uuid', ''), "start_ip": data.get('start_ip', ''), "end_ip": data.get('end_ip', '') } try: db_api.create_group(group_value) logger.info("create group %s success", data['name']) except Exception as e: logging.info("insert group info to db failed:%s", e) return get_error_result("GroupCreateError", name=data['name']) if data['group_type'] == constants.EDUCATION_DESKTOP: terminals = db_api.get_terminal_with_all({'group_uuid': None}) self.change_group_uuid(terminals, data.get('start_ip', ''), data.get('end_ip', ''), group_uuid) return get_error_result("Success", group_value)
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")
def education_instance(self, data): """教学桌面详情""" logger.info( "open the education desktop, desktop_uuid:%s, terminal_id:%s, terminal_ip:%s", data.get("desktop_uuid", ""), data.get("terminal_id", 0), data.get("ip", "")) desktop_uuid = data.get("desktop_uuid", "") terminal_id = data.get("terminal_id", 0) terminal_mac = data.get("mac", "") terminal_ip = data.get("ip", "") auth_info = LicenseManager().get_auth_info() # 0-过期 1-宽限期 2-试用期 3-正式版 # if 0 == auth_info.get('auth_type') or (1 == auth_info.get('auth_type') and auth_info.get('delay_days', 0) == 0)\ # or (2 == auth_info.get('auth_type') and auth_info.get('expire_time', 0) == 0): if auth_info.get("auth_type", 0) == 0: return build_result("AuthExpired") if self.get_links_num() >= auth_info.get('vdi_size', 0): return build_result("AuthSizeExpired") # # 授权个数控制,使用redis,配合后台监控线程每8s重置一下已连接个数 # redis = yzyRedis() # try: # redis.init_app() # self.check_auth_num(redis, auth_info.get('vdi_size', 0)) # except Exception as e: # logger.error("check auth error:%s", e) # return build_result("AuthSizeExpired") # 根据桌面组和终端序号查到桌面 instance = db_api.get_instance_with_first({ "desktop_uuid": desktop_uuid, "terminal_id": terminal_id, "classify": constants.EDUCATION_DESKTOP }) if not instance: logger.error("education instance not exist: %s %s", desktop_uuid, terminal_id) return build_result("TerminalEduInstanceNotAlloc") desktop_group = db_api.get_desktop_by_uuid(desktop_uuid) subnet = db_api.get_subnet_by_uuid(desktop_group.subnet_uuid) if not subnet: logger.error("person instance start error: not subnet %s", desktop_group.subnet_uuid) return build_result("TerminalEducationStartError") host_ip = instance.host.ip try: # 并发数控制 redis = yzyRedis() try: redis.init_app() self.check_concurrency(redis, host_ip, terminal_id, desktop_group.ram) except Exception as e: logger.error("allocate resource error:%s, instance:%s, return", e, instance.uuid) return build_result("ResourceAllocateError") # 如果已经链接,判断mac地址是否相同 spice_port = instance.spice_port # ret = dict() online = False if spice_port: ret = self.get_spice_link({host_ip: [str(spice_port)]}) if ret.get(host_ip, {}).get(str(spice_port)): online = True controller = BaseController() template = db_api.get_instance_template( desktop_group.template_uuid) sys_base, data_base = controller._get_storage_path_with_uuid( template.sys_storage, template.data_storage) logger.info( "get education instance, desktop_name:%s, terminal_id:%s, terminal_mac:%s", desktop_group.name, terminal_id, terminal_mac) if online: # spice_port有链接并且有terminal_mac才是真正有终端连接 # spice_port有链接(但实际SPICE_PORT被其他桌面复用), instance.terminal_mac 为空的情况,是需要正常启动 if (not instance.terminal_mac) or (instance.terminal_mac and instance.terminal_mac == terminal_mac): # mac相同,关闭当前开启 ins_ret = controller.create_instance(desktop_group, subnet, instance, sys_base, data_base, terminal=True) if ins_ret.get('code') != 0: logger.error("education instance start error: %s", instance.uuid) return build_result("TerminalEducationStartError") else: # mac不相同,提示终端冲突 logger.error( "education instance online terminal mac: %s, mac: %s", instance.terminal_mac, terminal_mac) return build_result("TerminalEduInstanceRepeatError") else: # 不在线 logger.info("eduction instance not link, uuid:%s, name:%s", instance.uuid, instance.name) ins_ret = controller.create_instance(desktop_group, subnet, instance, sys_base, data_base, terminal=True) if ins_ret.get('code') != 0: logger.error("education instance start error: %s", instance.uuid) return build_result("TerminalEducationStartError") instance.terminal_mac = terminal_mac instance.terminal_ip = terminal_ip instance.spice_link = 1 instance.link_time = datetime.now() instance.soft_update() data = { "spice_host": instance.host.ip, "spice_token": ins_ret['data'].get('spice_token', ''), "spice_port": ins_ret['data'].get('spice_port', ''), "name": instance.name, "uuid": instance.uuid, "os_type": desktop_group.os_type } return build_result("Success", data) except Exception as e: logger.exception("open education desktop error:%s", e) raise e finally: try: redis.rds.hdel(constants.PARALELL_QUEUE, terminal_id) except: pass
def person_instance(self, data): """ 个人桌面的详情 """ session_id = data.get("session_id", "") desktop_uuid = data.get("desktop_uuid", "") desktop_name = data.get("desktop_name", "") auth_info = LicenseManager().get_auth_info() # 0-过期 1-宽限期 2-试用期 3-正式版 # if 0 == auth_info.get('auth_type') or (1 == auth_info.get('auth_type') and auth_info.get('delay_days', 0) == 0)\ # or (2 == auth_info.get('auth_type') and auth_info.get('expire_time', 0) == 0): if auth_info.get("auth_type", 0) == 0: return build_result("AuthExpired") if self.get_links_num() >= auth_info.get('vdi_size', 0): return build_result("AuthSizeExpired") # 判断用户的登录状态 session = db_api.get_group_user_session_first( {"session_id": session_id}) if not session: logger.error( "terminal user query desktop group error: %s not exist" % session_id) return build_result("TerminalUserLogout") user = db_api.get_group_user_with_first({"uuid": session.user_uuid}) if not user: logger.error( "terminal user query desktop group error: %s not exist" % session.user_uuid) return build_result("TerminalUserNotExistError") if not user.enabled: logger.error( "terminal user query desktop group error: %s is unenabled" % user.user_name) return build_result("TerminalUserUnenabledError") desktop_group = db_api.get_personal_desktop_with_first( {"uuid": desktop_uuid}) if not desktop_group: logger.error("person desktop not exist: %s" % desktop_uuid) return build_result("DesktopNotExist", name=desktop_name) # 查找当前用户分配的随机及静态桌面 instances = list() # 静态桌面 static_instances = db_api.get_instance_with_all( {"user_uuid": user.uuid}) for obj in static_instances: instances.append(obj) random_instances = db_api.get_user_random_instance_with_all( {"user_uuid": user.uuid}) for obj in random_instances: instances.append(obj.instance) # 查找桌面的spice链接状态 host_spice_ports = dict() current_instance = None for instance in instances: host_ip = instance.host.ip if host_ip not in host_spice_ports: host_spice_ports[host_ip] = [] if instance.spice_port: host_spice_ports[host_ip].append(str(instance.spice_port)) if instance.desktop_uuid == desktop_uuid: current_instance = instance # 获取所有个人桌面的链接状态 ret = self.get_spice_link(host_spice_ports) if current_instance: host_ip = current_instance.host.ip spice_port = current_instance.spice_port if spice_port and ret.get(host_ip, {}).get(spice_port): logger.info( "terminal user request the same instance: user %s, desktop %s", user.uuid, desktop_uuid) instance_info = current_instance.instance_base_info() instance_info.update({"os_type": desktop_group.os_type}) return build_result("Success", instance_info) else: # 如果是随机桌面,需要释放 if desktop_group.desktop_type == constants.RANDOM_DESKTOP: for _obj in random_instances: if _obj.instance_uuid == current_instance.uuid: _obj.soft_delete() break current_instance.allocated = 0 current_instance.soft_update() # 判断已链接数是否大于等于2 count = 0 for k, v in ret.items(): for i, j in v.items(): if j: count += 1 if count >= 2: logger.error("user %s person desktop instance much 2", user.uuid) return build_result("TerminalPersonalInstanceNumError") # 如果桌面组状态为维护 if desktop_group.maintenance: logger.error("person desktop is maintenance: %s", desktop_uuid) return build_result("TerminalPersonMaintenance") subnet = db_api.get_subnet_by_uuid(desktop_group.subnet_uuid) # if not subnet: # logger.error("person instance start error: not subnet %s" % desktop_group.subnet_uuid) # return build_result("TerminalPersonStartError") # 启动桌面 controller = BaseController() template = db_api.get_instance_template(desktop_group.template_uuid) sys_base, data_base = controller._get_storage_path_with_uuid( template.sys_storage, template.data_storage) if desktop_group.desktop_type == constants.RANDOM_DESKTOP: # 随机桌面 instance = db_api.get_instance_by_desktop_first_alloc(desktop_uuid) if not instance: logger.error("person desktop not instance to alloc") return build_result("TerminalPersonInstanceNotAlloc") ret = controller.create_instance(desktop_group, subnet, instance, sys_base, data_base) if ret.get('code') != 0: logger.error("person instance start error: %s", instance.uuid) return build_result("TerminalPersonStartError") # 记录数据库 instance_binds = db_api.get_user_random_instance_with_all( {"instance_uuid": instance.uuid}) # 清除其他绑定关系 for random_ins in random_instances: if random_ins.desktop_uuid == desktop_uuid: instance = random_ins.instance instance.allocated = 0 instance.terminal_mac = None instance.link_time = None instance.soft_update() random_ins.soft_delete() for random_ins in instance_binds: random_ins.soft_delete() values = { "uuid": create_uuid(), "desktop_uuid": desktop_uuid, "user_uuid": user.uuid, "instance_uuid": instance.uuid } db_api.create_user_random_instance(values) instance.allocated = 1 instance.link_time = datetime.now() instance.spice_link = 1 instance.terminal_mac = user.mac instance.soft_update() logger.info("random person instance start succes: %s", instance.uuid) else: static_instance_bind = db_api.get_instance_with_first({ "desktop_uuid": desktop_uuid, "user_uuid": user.uuid }) if not static_instance_bind: logger.error( "static person desktop not bind: desktop group %s, user %s", desktop_uuid, user.uuid) return build_result("TerminalPersonInstanceNotAlloc") instance = static_instance_bind ret = controller.create_instance(desktop_group, subnet, instance, sys_base, data_base) if ret.get('code') != 0: logger.error("person instance start error: %s", instance.uuid) return build_result("TerminalPersonStartError") logger.info("static person instance start succes: %s", instance.uuid) instance.link_time = datetime.now() instance.terminal_mac = user.mac instance.spice_link = 1 instance.soft_update() data = { "spice_host": instance.host.ip, "spice_token": instance.spice_token, "spice_port": instance.spice_port, "name": instance.name, "uuid": instance.uuid, "os_type": desktop_group.os_type } edu_instance = db_api.get_instance_first({ "terminal_mac": user.mac, "classify": constants.EDUCATION_DESKTOP, "status": constants.STATUS_ACTIVE }) if edu_instance: desktop = db_api.get_desktop_by_uuid(edu_instance.desktop_uuid) controller.stop_instance(edu_instance, desktop) return build_result("Success", data)