def move_user(self, data): group = db_api.get_group_with_first({"uuid": data['group_uuid']}) if not group: logger.error("group: %s not exist" % data['group_uuid']) return get_error_result("GroupNotExists", name='') for user in data['users']: user = db_api.get_group_user_with_first({'uuid': user['uuid']}) if not user: logger.error("user %s not exist", user['user_name']) return get_error_result("GroupUserNotExists", name=user['user_name']) if user.group_uuid == group.uuid: logger.info("user %s already in group %s, skip", user.user_name, group.name) continue try: user.group_uuid = data['group_uuid'] # 移动后,原先的跟桌面绑定关系要删除 binds = db_api.get_instance_with_all({"user_uuid": user.uuid}) for bind in binds: bind.user_uuid = '' bind.soft_update() user.soft_update() except Exception as e: logger.error("move user %s to group %s failed:%s", user.user_name, group.name, e) return get_error_result("GroupUserMoveError", user_name=user.user_name, group=group.name) logger.info("move user %s to group %s success", user.user_name, group.name) return get_error_result("Success")
def get_links_num(self): count = 0 instances = db_api.get_instance_with_all({}) rep_data = dict() for instance in instances: host_ip = instance.host.ip if host_ip not in rep_data: rep_data[host_ip] = list() if instance.spice_port: rep_data[host_ip].append(instance.spice_port) for k, v in rep_data.items(): ports = ",".join(list(set(v))) if ports: ports_status = monitor_post(k, "/api/v1/monitor/port_status", {"ports": ports}) else: ports_status = {} if ports_status.get('code', -1) != 0: logger.error("from node %s get port status:%s", k, ports_status) continue logger.info("from node %s get port status:%s", k, ports_status) for port, link in ports_status.get("data", {}).items(): if link: count += 1 logger.info("the instance link count:%s", count) return count
def person_instance_close(self, data): """ 关闭个人终端的所有桌面 """ session_id = data.get("session_id", "") 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") contraller = BaseController() random_instances = db_api.get_user_random_instance_with_all( {"user_uuid": user.uuid}) static_instances = db_api.get_instance_with_all({ "classify": constants.PERSONAL_DEKSTOP, "user_uuid": user.uuid }) for i in random_instances: desktop = i.desktop instance = i.instance # sys_restore = desktop.sys_restore if not contraller.stop_instance(instance, desktop): logger.error("terminal close personal instance fail: %s" % instance.uuid) instance.allocated = 0 desktop_uuids = list() for instance in static_instances: desktop_uuid = instance.desktop_uuid if desktop_uuid not in desktop_uuids: desktop_uuids.append(desktop_uuid) desktop_dict = dict() desktops = db_api.get_personal_desktop_all_by_uuids(desktop_uuids) for desktop in desktops: desktop_dict[desktop.uuid] = desktop for instance in static_instances: desktop = desktop_dict[instance.desktop_uuid] if not contraller.stop_instance(instance, desktop): logger.error("terminal close personal instance fail: %s" % instance.uuid) logger.info("terminal close personal instance success !!!") return build_result("Success")
def person_desktop_groups(self, data): """ 个人桌面组列表 """ session_id = data.get("session_id", "") 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_uuids = list() # 随机桌面 random_desktop_groups = db_api.get_random_desktop_with_all( {"group_uuid": user.group_uuid}) for group in random_desktop_groups: desktop_uuids.append(group.desktop_uuid) # instance_uuids = list() static_instances = db_api.get_instance_with_all( {"user_uuid": user.uuid}) for instance in static_instances: desktop_uuids.append(instance.desktop_uuid) # instances = db_api.get_instance_all_by_uuids(instance_uuids) # for instance in instances: # desktop_uuids.append(instance.desktop_uuid) desktop_groups = db_api.get_personal_desktop_all_by_uuids( desktop_uuids) _groups = list() for desktop in desktop_groups: _d = { "uuid": desktop.uuid, "name": desktop.name, "desc": desktop.template.desc, "maintenance": desktop.maintenance, "order_num": desktop.order_num, "os_type": desktop.os_type } _groups.append(_d) _groups = sorted(_groups, key=lambda _groups: _groups['order_num']) logger.info("person terminal desktop group list: %s" % _groups) return build_result("Success", _groups)
def terminal_instance_match(self, data): """ 所有终端ip对应的桌面ip""" # ips = data.get("ips", "") # ips = ips.split(",") # terminal_ips = list() # for i in ips: # if not is_ip_addr(i): # continue # terminal_ips.append(i) # items = {} groups = db_api.get_group_with_all( {"group_type": constants.EDUCATION_DESKTOP}) group_dict = dict() for group in groups: start_ip = group.start_ip end_ip = group.end_ip uuid = group.uuid group_dict[uuid] = find_ips(start_ip, end_ip) desktop_group_dict = {} desktops = db_api.get_desktop_with_all_by_groups( list(group_dict.keys())) for i in desktops: desktop_group_dict[i.uuid] = i.group_uuid terminals = list() for i in data: terminal_ip = i["terminal_ip"] if not is_ip_addr(terminal_ip): continue for uuid, ips in group_dict.items(): # start_ip = group.start_ip # end_ip = group.end_ip # if find_ips(start_ip, end_ip) if terminal_ip in ips: i["group_uuid"] = uuid terminals.append(i) break # 找到所有云桌面 ret = list() instances = db_api.get_instance_with_all( {"classify": constants.EDUCATION_DESKTOP}) for terminal in terminals: group_uuid = terminal["group_uuid"] terminal_id = terminal["terminal_id"] for instance in instances: desktop_uuid = instance.desktop_uuid _group_uuid = desktop_group_dict.get(desktop_uuid) _terminal_id = instance.terminal_id _instance_ip = instance.ipaddr if _group_uuid == group_uuid and terminal_id == _terminal_id and _instance_ip: terminal["desktop_ip"] = _instance_ip ret.append(terminal) break return build_result("Success", ret)
def delete_user(self, user_uuid): user = db_api.get_group_user_with_first({'uuid': user_uuid}) if not user: logger.error("user: %s not exist" % user_uuid) return get_error_result("GroupUserNotExists", name='') binds = db_api.get_instance_with_all({"user_uuid": user.uuid}) for bind in binds: bind.user_uuid = '' bind.soft_update() user.soft_delete() logger.info("delete group user %s success", user_uuid) return get_error_result("Success")
def delete_group(self, group_uuid): group = db_api.get_group_with_first({"uuid": group_uuid}) if not group: logger.error("group: %s not exist" % group_uuid) return get_error_result("GroupNotExists", name='') # 教学分组如果在使用中,不能删除 if constants.EDUCATION_DESKTOP == group.group_type: desktop = db_api.get_desktop_with_all({"group_uuid": group_uuid}) if desktop: logger.error("group already in use", group_uuid) return get_error_result("GroupInUse", name=group.name) # 教学分组有关联课表时,不能删除 if db_api.get_course_schedule_with_all({"group_uuid": group_uuid}): logger.error("group already in use by course_schedule", group_uuid) return get_error_result("GroupInUseByCourseSchedule", name=group.name) # 个人分组删除时需要删除分组中的用户 if constants.PERSONAL_DEKSTOP == group.group_type: users = db_api.get_group_user_with_all({'group_uuid': group.uuid}) for user in users: binds = db_api.get_instance_with_all({"user_uuid": user.uuid}) for bind in binds: bind.user_uuid = '' bind.soft_update() user.soft_delete() desktops = db_api.get_personal_desktop_with_all( {"group_uuid": group_uuid}) for desktop in desktops: desktop.group_uuid = "" desktop.soft_update() group.soft_delete() logger.info("delete group %s success", group_uuid) ret = terminal_post( "/api/v1/terminal/task", { "handler": "WebTerminalHandler", "command": "delete_group", "data": { "group_uuid": group_uuid } }) return ret
def close_education_instance(self, data): """ 关闭教学桌面 """ terminal_mac = data.get("mac", "") instances = db_api.get_instance_with_all( {"terminal_mac": terminal_mac}) desktop_uuids = list() for instance in instances: desktop_uuid = instance.desktop_uuid if desktop_uuid not in desktop_uuids: desktop_uuids.append(desktop_uuid) contraller = BaseController() desktop_dict = dict() desktops = db_api.get_desktop_with_all_by_uuids(desktop_uuids) for desktop in desktops: desktop_dict[desktop.uuid] = desktop for instance in instances: desktop = desktop_dict[instance.desktop_uuid] if not contraller.stop_instance(instance, desktop): logger.error("terminal close personal instance fail: %s" % instance.uuid) return build_result("Success")
def update_instance_info(): instances = db_api.get_instance_with_all({}) rep_data = dict() instance_dict = dict() for instance in instances: instance_dict[instance.uuid] = instance host_ip = instance.host.ip _d = { "uuid": instance.uuid, "name": instance.name # "spice_port": spice_port } if host_ip not in rep_data: rep_data[host_ip] = list() rep_data[host_ip].append(_d) # link_num = 0 for k, v in rep_data.items(): command_data = { "command": "get_status_many", "handler": "InstanceHandler", "data": { "instance": v } } logger.debug("get instance state in node %s", k) rep_json = compute_post(k, command_data) logger.debug("from compute get rep_json:{}".format(rep_json)) if rep_json.get("code", -1) != 0: # 如果节点计算服务连接失败,则桌面都更新为关机状态 if rep_json.get("code", -1) == 80000: for _d in v: if instance_dict[ _d["uuid"]].status != constants.STATUS_INACTIVE: instance_dict[_d["uuid"]].update( {"status": constants.STATUS_INACTIVE}) logger.info( "compute service unavaiable at node: %s, update instance.status to inactive: %s", k, _d["uuid"]) continue for item in rep_json.get("data", []): for instance in instances: if item["uuid"] == instance.uuid: if item.get("state") in [ constants.DOMAIN_STATE['running'] ]: if constants.STATUS_INACTIVE == instance.status: instance.status = constants.STATUS_ACTIVE instance.soft_update() elif item.get('state') in [ constants.DOMAIN_STATE['shutdown'], constants.DOMAIN_STATE['shutoff'] ]: if constants.STATUS_ACTIVE == instance.status: instance.status = constants.STATUS_INACTIVE # instance.spice_port = '' # instance.spice_link = 0 # instance.allocated = 0 # instance.link_time = None # 通知终端管理 桌面关闭 # 只对绑定了终端的桌面发通知 if instance.terminal_mac: if instance.classify == 2: desktop = db_api.get_personal_desktop_with_first( {'uuid': instance.desktop_uuid}) else: desktop = db_api.get_desktop_by_uuid( desktop_uuid=instance.desktop_uuid) if desktop: data = { 'desktop_name': desktop.name, 'desktop_order': desktop.order_num, 'desktop_uuid': desktop.uuid, 'instance_uuid': instance.uuid, 'instance_name': instance.name, 'host_ip': instance.host.ip, 'port': instance.spice_port, 'token': instance.spice_token, 'os_type': desktop.os_type, 'terminal_mac': instance.terminal_mac } logger.info( 'rtn: instance.classify: %s, data: %s' % (instance.classify, data)) base_controller = BaseController() ret = base_controller.notice_terminal_instance_close( data) # 通知完成后,清除桌面与终端的绑定关系 if ret: try: instance.terminal_mac = None except Exception as e: logger.error( "update instance.terminal_mac to None: %s failed: %s", instance.uuid, e) logger.info( 'rtn: %s, desktop.uuid: %s, instance.terminal_mac: %s' % (ret, desktop.uuid, instance.terminal_mac)) instance.soft_update() else: pass # instance.soft_update() logger.debug("the instance %s state %s", instance.uuid, item.get('state', 0)) break spice_ports = list() for instance in instances: if instance.spice_port: spice_ports.append(instance.spice_port) # 查询监控服务端口 ports = ",".join(list(set(spice_ports))) if ports: ports_status = monitor_post(k, "/api/v1/monitor/port_status", {"ports": ports}) else: ports_status = {} logger.info("from node %s get port status:%s", k, ports_status) for instance in instances: if instance.host.ip == k and instance.spice_port: instance.spice_link = ports_status.get("data", {}).get( instance.spice_port, False) if not instance.spice_link: instance.allocated = 0 instance.soft_update() logger.debug("the instance %s spice_link:%s", instance.uuid, instance.spice_link)
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)