コード例 #1
0
ファイル: network_ctl.py プロジェクト: xiaomo-shu/shangcheng
 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)
コード例 #2
0
ファイル: utils.py プロジェクト: xiaomo-shu/shangcheng
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)
コード例 #3
0
ファイル: group_ctl.py プロジェクト: xiaomo-shu/shangcheng
    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)
コード例 #4
0
ファイル: network_ctl.py プロジェクト: xiaomo-shu/shangcheng
 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")
コード例 #5
0
ファイル: terminal_ctl.py プロジェクト: xiaomo-shu/shangcheng
    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
コード例 #6
0
ファイル: terminal_ctl.py プロジェクト: xiaomo-shu/shangcheng
    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)