예제 #1
0
    def update_voi_desktop(self, data):
        """
        :param data:
        {
            "uuid": "",
            "value": {
                "name": "",
                ...
            }
        }
        :return:
        """
        desktop_uuid = data.get('uuid', '')
        desktop = db_api.get_item_with_first(models.YzyVoiDesktop, {"uuid": desktop_uuid})
        if not desktop:
            logger.error("desktop %s not exist", desktop_uuid)
            return get_error_result("DesktopNotExist", name="")
        try:
            if data['value'].get('ip_detail'):
                data['value']['ip_detail'] = json.dumps(data['value']['ip_detail'])
            else:
                data['value']['ip_detail'] = ''
            desktop.update(data['value'])
            desktop.soft_update()

            terminal_desktop_binds = db_api.get_item_with_all(models.YzyVoiTerminalToDesktops,
                                                              {"desktop_group_uuid": desktop_uuid})
            for bind in terminal_desktop_binds:
                bind.soft_delete()
            logger.info("update voi desktop, clear terminal desktop bind success!!")
        except Exception as e:
            logger.error("update voi desktop %s failed:%s", desktop_uuid, e, exc_info=True)
            return get_error_result("DesktopUpdateFail", name=desktop.name)
        logger.info("update voi desktop %s success", desktop_uuid)
        return get_error_result("Success")
예제 #2
0
 def delete_voi_desktop(self, desktop_uuid):
     """
     删除桌面组
     """
     desktop = db_api.get_item_with_first(models.YzyVoiDesktop, {"uuid": desktop_uuid})
     if not desktop:
         logger.error("desktop %s not exist", desktop_uuid)
         return get_error_result("DesktopNotExist", name="")
     try:
         # 清除桌面组与终端的绑定关系
         terminal_desktop_binds = db_api.get_item_with_all(models.YzyVoiTerminalToDesktops,
                                                           {"desktop_group_uuid": desktop_uuid})
         for bind in terminal_desktop_binds:
             # type: 0-upload, 1-download
             bt_task = db_api.get_item_with_first(models.YzyVoiTorrentTask,
                                                  {"terminal_mac": bind.terminal_mac,
                                                   "type": 1})
             # status == 1, task running
             if bt_task and bt_task.status == 1:
                 return get_error_result("TerminalTorrentDownloading")
             bind.soft_delete()
         logger.info("delete voi desktop, clear terminal desktop bind success!!")
         
         desktop.soft_delete()
         logger.info("delete voi desktop, uuid:%s, name:%s", desktop.uuid, desktop.name)
         if desktop.default:
             default_one = db_api.get_item_with_first(models.YzyVoiDesktop, {})
             if default_one:
                 default_one.default = True
                 default_one.soft_update()
                 logger.info("the delete desktop is default, set %s as default", default_one.name)
         return get_error_result("Success")
     except Exception as e:
         logger.error("delete voi desktop failed:%s", e, exc_info=True)
         return get_error_result("DesktopDeleteFail")
예제 #3
0
def ha_sync_task():
    """
    通知备控检查文件同步情况,下载缺少的,删除多余的
    范围:iso库、数据库备份文件、VOI模板的实际启动盘、base盘、差异盘、种子文件
    """
    ha_info_obj = db_api.get_ha_info_first()
    if ha_info_obj:
        paths = list()
        for iso in db_api.get_item_with_all(models.YzyIso, {}):
            paths.append({"path": iso.path, "md5": iso.md5_sum})
        if paths:
            notify_backup_sync_file(ha_info_obj.master_ip,
                                    ha_info_obj.backup_ip,
                                    paths,
                                    check_path=os.path.dirname(
                                        paths[0]["path"]))

        backs = list()
        for backup in db_api.get_item_with_all(models.YzyDatabaseBack, {}):
            backs.append({"path": backup.path, "md5": backup.md5_sum})
        if backs:
            notify_backup_sync_file(ha_info_obj.master_ip,
                                    ha_info_obj.backup_ip,
                                    backs,
                                    check_path=os.path.dirname(
                                        backs[0]["path"]))

        templates = list()
        sys_base, data_base = get_template_storage_path(
            ha_info_obj.master_uuid)
        for dir_path in [
                sys_base,
                os.path.join(sys_base, constants.IMAGE_CACHE_DIRECTORY_NAME),
                data_base,
                os.path.join(data_base, constants.IMAGE_CACHE_DIRECTORY_NAME)
        ]:
            find_file_to_sync(dir_path, templates)
        find_xml_to_sync("/etc/libvirt/qemu/", templates)
        if templates:
            # 模板不删除多余的,容易导致正在刚创建的模板磁盘文件被删除
            notify_backup_sync_file(ha_info_obj.master_ip,
                                    ha_info_obj.backup_ip, templates)
예제 #4
0
 def get_history_perf(self, data):
     logger.info("get data: {}".format(data))
     node_uuid = data.get("node_uuid")
     statis_hours = data.get("statis_hours")
     step_minutes = data.get("step_minutes")
     if not (node_uuid and statis_hours and step_minutes):
         return build_result("ParamError")
     node = db_api.get_item_with_all(models.YzyNodes, {"uuid": node_uuid})
     if not node:
         return build_result("ParamError")
     _data = self.get_perf_info(node_uuid, statis_hours, step_minutes)
     _data.update({"node_uuid": node_uuid})
     return build_result("Success", data=_data)
예제 #5
0
 def education_group(self, data):
     logger.info("get data: {}".format(data))
     terminal_ip = data.get("terminal_ip", "")
     if not is_ip_addr(terminal_ip):
         return build_result("ParamError")
     _group = None
     edu_groups = db_api.get_item_with_all(
         models.YzyVoiGroup, {"group_type": constants.EDUCATION_DESKTOP})
     for group in edu_groups:
         start_ip = group.start_ip
         end_ip = group.end_ip
         if terminal_ip in find_ips(start_ip, end_ip):
             _group = group
             break
     if not _group:
         return build_result("Success")
     ret = {
         "name": _group.name,
         "uuid": _group.uuid,
     }
     logger.info("return data: {}".format(ret))
     return build_result("Success", ret)
예제 #6
0
 def education_config_groups(self):
     """
     获取所有组的ip段信息
     {
         "code": 0,
         "msg": "success"
         "data": {
             "groups": {
                 "uuid": ["ips"]
             }
         }
     }
     :return:
     """
     groups_dict = dict()
     edu_groups = db_api.get_item_with_all(
         models.YzyVoiGroup, {"group_type": constants.EDUCATION_DESKTOP})
     for group in edu_groups:
         start_ip = group.start_ip
         end_ip = group.end_ip
         ips = find_ips(start_ip, end_ip)
         groups_dict.update({group.uuid: ips})
     logger.info("terminal desktop group dict: %s" % groups_dict)
     return build_result("Success", data={"groups": groups_dict})
예제 #7
0
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
예제 #8
0
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
예제 #9
0
 def education_groups(self):
     edu_groups = db_api.get_item_with_all(
         models.YzyVoiGroup, {"group_type": constants.EDUCATION_DESKTOP})
     ret = {"groups": [x.uuid for x in edu_groups]}
     return build_result("Success", ret)
예제 #10
0
    def update_share_disk(self, data):
        """
        更新共享数据盘
        {
                "uuid": "xxxxxxxxxx",
                "enable": 0,
                "disk_size": 8,
                "restore": 1,
                "share_desktop": [
                    {"uuid": "xxxxxxx", "name": "xxxxx", "choice": 0},
                    {"uuid": "xxxxxxx", "name": "xxxxx", "choice": 0}
                ]
            }
        :param data:
        :return:
        """
        """
         {
            "command": "create_share",
            "handler": "VoiHandler",
            "data": {
                "disk_info": {
                    'uuid': '2f110de8-78d8-11ea-ad5d-000c29e84b9c',
                    'base_path': '/opt/slow/instances'
                }
                "version": 0
            }
        }
        """
        logger.info("terminal share disk update data: {}".format(data))
        try:
            # disk_uuid = create_uuid()
            version = 0
            disk_uuid = data["uuid"]
            sys_base, data_base = self._get_template_storage()
            share_disk = db_api.get_item_with_first(
                models.YzyVoiTerminalShareDisk, {"uuid": disk_uuid})
            disk_info = dict()
            disk_info["uuid"] = share_disk.uuid
            disk_info["base_path"] = sys_base['path']
            disk_info["size"] = data["disk_size"]
            # 判断是否大小有更新
            if data["disk_size"] != share_disk.disk_size:
                # 需要重新删除创建
                # pass
                node = db_api.get_controller_node()
                delete_command = {
                    "command": "delete_share",
                    "handler": "VoiHandler",
                    "data": {
                        "disk_info": {
                            "uuid": share_disk.uuid,
                            "base_path": sys_base['path'],
                        },
                        "version": version
                    }
                }
                ret = compute_post(node.ip, delete_command)
                if ret.get("code", -1) != 0:
                    logger.error(
                        "terminal share disk update fail, delete old fail")
                    return build_result("ShareDiskUpdateFail")
                # 创建新的容量盘
                command_data = {
                    "command": "create_share",
                    "handler": "VoiHandler",
                    "data": {
                        "disk_info": disk_info,
                        "version": version
                    }
                }
                ret_json = compute_post(node.ip, command_data)
                if ret_json.get("code", -1) != 0:
                    logger.error(
                        "terminal share disk update fail, create new fail")
                    return build_result("ShareDiskUpdateFail")
                share_disk.disk_size = data["disk_size"]
                share_disk.version += 1

            # todo 维护桌面组的绑定关系
            # import pdb; pdb.set_trace()
            desktops = db_api.get_item_with_all(
                models.YzyVoiDesktop, {"group_uuid": share_disk.group_uuid})
            desktop_binds = db_api.get_item_with_all(
                models.YzyVoiShareToDesktops, {"disk_uuid": disk_uuid})
            share_desktops = data["share_desktop"]
            copy_share_desktops = share_desktops[:]
            for desktop in share_desktops:
                # is_exist = False
                for bind in desktop_binds:
                    if desktop["uuid"] == bind.desktop_uuid:
                        # is_exist = True
                        if not int(desktop.get("choice", 0)):
                            bind.soft_delete()
                        copy_share_desktops.remove(desktop)
            insert_binds = list()
            if copy_share_desktops:
                for desktop in copy_share_desktops:
                    if desktop["choice"]:
                        for _d in desktops:
                            if desktop["uuid"] == _d.uuid:
                                insert_binds.append({
                                    "uuid":
                                    create_uuid(),
                                    "group_uuid":
                                    share_disk.group_uuid,
                                    "disk_uuid":
                                    disk_uuid,
                                    "desktop_uuid":
                                    desktop["uuid"],
                                    "desktop_name":
                                    desktop["name"]
                                })
            # 更新数据库绑定记录
            if insert_binds:
                db_api.insert_with_many(models.YzyVoiShareToDesktops,
                                        insert_binds)
            # 更新数据库记录
            share_disk.restore = data["restore"]
            share_disk.enable = data["enable"]
            share_disk.soft_update()
            # todo 生成bt种子
            # 生成种子文件
            task = Thread(target=self.create_share_disk_torrent,
                          args=(disk_info, version))
            task.start()
            logger.info(
                "update terminal voi share disk data: {} success".format(
                    share_disk))
            return build_result("Success")
        except Exception as e:
            logger.error("", exc_info=True)
            return build_result("OtherError")
예제 #11
0
    def order_terminal_desktop_ip(self, data):
        """
            "terminal_id_list": terminal_id_list,
            "group_uuid": group_uuid,
            "terminal_mac_list": terminal_mac_list
        """
        logger.info("order terminal desktop ip data: {}".format(data))
        try:
            group_uuid = data.get("group_uuid", "")
            terminal_mac_list = data.get("terminal_mac_list", "")
            terminal_id_list = data.get("terminal_id_list", "")
            if terminal_mac_list:
                terminals_list = list(zip(terminal_id_list, terminal_mac_list))
                terminals_list = sorted(terminals_list, key=lambda x: x[0])
            else:
                logger.warning(
                    'request terminal_mac_list is null, please check!!1')
                return build_result("Success")
            # group_uuid get all desktop groups
            qry_desktop_groups = db_api.get_item_with_all(
                models.YzyVoiDesktop, {'group_uuid': group_uuid})
            for desktop_group in qry_desktop_groups:
                if not desktop_group.use_bottom_ip and desktop_group.ip_detail:
                    ip_detail = json.loads(desktop_group.ip_detail)
                    desktop_is_dhcp = ip_detail.get("auto", True)
                    if not desktop_is_dhcp:
                        desktop_start_ip = ip_detail.get("start_ip", "")
                        desktop_mask = ip_detail.get("netmask", "")
                        desktop_gateway = ip_detail.get("gateway", "")
                        desktop_dns1 = ip_detail.get("dns_master", "")
                        desktop_dns2 = ip_detail.get("dns_slave", "")
                        netmask_bits = netaddr.IPAddress(
                            desktop_mask).netmask_bits()
                        network = ipaddress.ip_interface(
                            desktop_start_ip + '/' + str(netmask_bits)).network
                        desktop_ip_pool = [
                            x for x in network.hosts()
                            if x >= ipaddress.IPv4Address(desktop_start_ip)
                        ]
                        if desktop_ip_pool:
                            for terminal_id, terminal_mac in terminals_list:
                                set_ip_detail = {}
                                if desktop_ip_pool:
                                    desktop_ip = min(desktop_ip_pool)
                                    set_ip_detail = {
                                        "desktop_is_dhcp": 0,
                                        "desktop_ip": desktop_ip.compressed,
                                        "desktop_mask": desktop_mask,
                                        "desktop_gateway": desktop_gateway,
                                        "desktop_dns1": desktop_dns1,
                                        "desktop_dns2": desktop_dns2,
                                    }
                                    desktop_ip_pool.remove(desktop_ip)
                                    logger.debug(
                                        'terminal_id: {}, terminal_mac: {}, ip: {}'
                                        .format(terminal_id, terminal_mac,
                                                desktop_ip))
                                else:
                                    # no more available ip, set desktop ip use bottom ip
                                    requst_data = {
                                        "handler": "WebTerminalHandler",
                                        "command": "get_terminal_ip",
                                        "data": {
                                            'mac': terminal_mac
                                        }
                                    }
                                    ret = voi_terminal_post(
                                        "/api/v1/voi/terminal/command/",
                                        requst_data)
                                    if ret.get("code", -1) != 0:
                                        logger.error(
                                            "voi_terminal_post request: {}, ret: {}"
                                            .format(requst_data, ret))
                                        return ret
                                    bottom_ip = ret.get("data", None)
                                    set_ip_detail = {
                                        "desktop_is_dhcp": 0,
                                        "desktop_ip": bottom_ip['ip'],
                                        "desktop_mask": bottom_ip['mask'],
                                        "desktop_gateway":
                                        bottom_ip['gateway'],
                                        "desktop_dns1": bottom_ip['dns1'],
                                        "desktop_dns2": bottom_ip['dns2'],
                                    }
                                # update database table  set_ip_detail
                                db_api.update_voi_terminal_desktop_bind(
                                    desktop_group.uuid, terminal_mac,
                                    set_ip_detail)
                        else:
                            logger.warning(
                                'desktop group ip setup error, no available ip'
                            )

            return build_result("Success")
        except Exception as e:
            logger.error("", exc_info=True)
            return build_result("OtherError")
예제 #12
0
    def create_terminal_desktop_bind_bak(self, data):
        """
            'group_uuid','terminal_uuid','terminal_id','mac',
            'ip','mask','gateway','dns1','dns2','is_dhcp',
        """
        logger.info("create terminal desktop bind data: {}".format(data))
        try:
            terminal_uuid = data.get("terminal_uuid", "")
            terminal_id = data.get("terminal_id", "")
            group_uuid = data.get("group_uuid", "")
            terminal_mac = data.get("mac", "")
            bind_info = {}
            # group_uuid != input group_uuid, then delete all old data
            db_api.delete_voi_terminal_desktops(group_uuid, terminal_uuid)
            # get all desktop groups
            qry_desktop_groups = db_api.get_item_with_all(
                models.YzyVoiDesktop, {"group_uuid": group_uuid})
            # 查找所有该终端、桌面组对应关系

            for qry in qry_desktop_groups:
                desktop_group_uuid = qry.uuid
                # one (desktop_group_uuid, terminal_id) only one row
                qry_exists = db_api.get_item_with_first(
                    models.YzyVoiTerminalToDesktops, {
                        "desktop_group_uuid": desktop_group_uuid,
                        "terminal_uuid": terminal_uuid
                    })
                if qry_exists:
                    logger.info('continue: {}'.format(terminal_mac))
                    continue
                logger.info('desktop_group_uuid: {}, qry.ip_detail: {}'.format(
                    desktop_group_uuid, qry.ip_detail))
                desktop_is_dhcp = 0
                if qry.ip_detail:
                    ip_detail = json.loads(qry.ip_detail)
                    desktop_is_dhcp = int(ip_detail.get("auto", True))
                    desktop_start_ip = ip_detail.get("start_ip", "")
                    desktop_mask = ip_detail.get("netmask", "")
                    desktop_gateway = ip_detail.get("gateway", "")
                    desktop_dns1 = ip_detail.get("dns_master", "")
                    desktop_dns2 = ip_detail.get("dns_slave", "")
                desktop_ip_info = {}
                if bool(qry.use_bottom_ip):
                    logger.info(
                        'desktop_group_uuid: {}, qry.use_bottom_ip: {}'.format(
                            desktop_group_uuid, qry.use_bottom_ip))
                    desktop_ip_info = {
                        "desktop_is_dhcp": data.get("is_dhcp", ""),
                        "desktop_ip": data.get("ip", ""),
                        "desktop_mask": data.get("mask", ""),
                        "desktop_gateway": data.get("gateway", ""),
                        "desktop_dns1": data.get("dns1", ""),
                        "desktop_dns2": data.get("dns2", ""),
                    }
                elif desktop_is_dhcp:
                    logger.info(
                        'desktop_group_uuid: {}, desktop_is_dhcp: {}'.format(
                            desktop_group_uuid, desktop_is_dhcp))
                    desktop_ip_info = {
                        "desktop_is_dhcp": 1,
                        "desktop_ip": "",
                        "desktop_mask": "",
                        "desktop_gateway": "",
                        "desktop_dns1": "",
                        "desktop_dns2": "",
                    }
                else:
                    logger.info('desktop_group_uuid: {}, static ip'.format(
                        desktop_group_uuid))
                    # get ip pool use start_ip and netmask, filter yzy_voi_terminal_desktops ips, get least ip
                    netmask_bits = netaddr.IPAddress(
                        desktop_mask).netmask_bits()
                    network = ipaddress.ip_interface(desktop_start_ip + '/' +
                                                     str(netmask_bits)).network
                    original_ip_pool = [
                        x for x in network.hosts()
                        if x >= ipaddress.IPv4Address(desktop_start_ip)
                    ]
                    # get used ip in this desktop_group_uuid
                    qry_ips = db_api.get_item_with_all(
                        models.YzyVoiTerminalToDesktops,
                        {"desktop_group_uuid": desktop_group_uuid})
                    used_ip_pool = [
                        ipaddress.IPv4Address(qry.desktop_ip)
                        for qry in qry_ips
                    ]
                    available_ip_pool = [
                        ip for ip in original_ip_pool if ip not in used_ip_pool
                    ]
                    if available_ip_pool:
                        desktop_ip = min(available_ip_pool).compressed
                        desktop_ip_info = {
                            "desktop_is_dhcp": 0,
                            "desktop_ip": desktop_ip,
                            "desktop_mask": desktop_mask,
                            "desktop_gateway": desktop_gateway,
                            "desktop_dns1": desktop_dns1,
                            "desktop_dns2": desktop_dns2,
                        }
                    else:  # use use_bottom_ip
                        logger.info(
                            'desktop_group_uuid: {}, no availabel_ip'.format(
                                desktop_group_uuid))
                        desktop_ip_info = {
                            "desktop_is_dhcp": data.get("is_dhcp", ""),
                            "desktop_ip": data.get("ip", ""),
                            "desktop_mask": data.get("mask", ""),
                            "desktop_gateway": data.get("gateway", ""),
                            "desktop_dns1": data.get("dns1", ""),
                            "desktop_dns2": data.get("dns2", ""),
                        }
                bind_info = {
                    "uuid": create_uuid(),
                    "group_uuid": group_uuid,
                    "terminal_uuid": terminal_uuid,
                    "desktop_group_uuid": desktop_group_uuid,
                    "terminal_mac": terminal_mac,
                }
                bind_info.update(desktop_ip_info)
                db_api.create_voi_terminal_desktop_bind(bind_info)
            logger.info(
                "terminal desktop bind data: {} success".format(bind_info))
            return build_result("Success")
        except Exception as e:
            logger.error("", exc_info=True)
            return build_result("OtherError")
예제 #13
0
    def create_terminal_desktop_bind(self, data):
        """
            'group_uuid','terminal_uuid','terminal_id','mac',
            'ip','mask','gateway','dns1','dns2','is_dhcp',
            {'group_uuid': 'a0cd32c9-9502-4ddc-b7a2-115203e4df0c',
            'terminal_uuid': '891fa480-8f9b-4d25-8df3-a59798e302c4',
            'terminal_id': 210, 'mac': 'E4:3A:6E:35:5C:A4', 'ip': '10.100.20.150', 'mask': '255.255.255.0',
            'gateway': '10.100.20.254', 'dns1': '10.10.0.2', 'dns2': '', 'is_dhcp': 1}
        """
        logger.info("create terminal desktop bind data: {}".format(data))
        try:
            terminal_uuid = data.get("terminal_uuid", "")
            terminal_id = data.get("terminal_id", "")
            group_uuid = data.get("group_uuid", "")
            terminal_mac = data.get("mac", "")
            bind_info = {}
            # group_uuid != input group_uuid, then delete all old data
            with redis_lock.Lock(self._redis.rds,
                                 'create_terminal_desktop_bind_lock', 2):
                db_api.delete_voi_terminal_desktops(group_uuid, terminal_uuid)
                # get all desktop groups
                qry_desktop_groups = db_api.get_item_with_all(
                    models.YzyVoiDesktop, {"group_uuid": group_uuid})
                # 查找所有该终端、桌面组对应关系
                terminal_desktop_relations = db_api.get_item_with_all(
                    models.YzyVoiTerminalToDesktops,
                    {"terminal_uuid": terminal_uuid})
                for qry in qry_desktop_groups:
                    desktop_group_uuid = qry.uuid
                    # one (desktop_group_uuid, terminal_id) only one row
                    # qry_exists = db_api.get_item_with_first(models.YzyVoiTerminalToDesktops,
                    #                                         {"desktop_group_uuid": desktop_group_uuid,
                    #                                          "terminal_uuid": terminal_uuid})
                    relation_exists = False
                    for relation in terminal_desktop_relations:
                        if relation.desktop_group_uuid == desktop_group_uuid:
                            relation_exists = True
                            break

                    if relation_exists:
                        logger.info('continue: {}'.format(terminal_mac))
                        continue

                    logger.info(
                        'desktop_group_uuid: {}, qry.ip_detail: {}'.format(
                            desktop_group_uuid, qry.ip_detail))

                    if bool(qry.use_bottom_ip):
                        logger.info(
                            'desktop_group_uuid: {}, qry.use_bottom_ip: {}'.
                            format(desktop_group_uuid, qry.use_bottom_ip))
                        desktop_ip_info = {
                            "desktop_is_dhcp": data.get("is_dhcp", ""),
                            "desktop_ip": data.get("ip", ""),
                            "desktop_mask": data.get("mask", ""),
                            "desktop_gateway": data.get("gateway", ""),
                            "desktop_dns1": data.get("dns1", ""),
                            "desktop_dns2": data.get("dns2", ""),
                        }
                    else:
                        desktop_is_dhcp = 0
                        if qry.ip_detail:
                            ip_detail = json.loads(qry.ip_detail)
                            desktop_is_dhcp = int(ip_detail.get("auto", True))
                            desktop_start_ip = ip_detail.get("start_ip", "")
                            desktop_mask = ip_detail.get("netmask", "")
                            desktop_gateway = ip_detail.get("gateway", "")
                            desktop_dns1 = ip_detail.get("dns_master", "")
                            desktop_dns2 = ip_detail.get("dns_slave", "")

                        if desktop_is_dhcp:
                            logger.info(
                                'desktop_group_uuid: {}, desktop_is_dhcp: {}'.
                                format(desktop_group_uuid, desktop_is_dhcp))
                            desktop_ip_info = {
                                "desktop_is_dhcp": 1,
                                "desktop_ip": "",
                                "desktop_mask": "",
                                "desktop_gateway": "",
                                "desktop_dns1": "",
                                "desktop_dns2": "",
                            }
                        else:
                            logger.info(
                                'desktop_group_uuid: {}, static ip'.format(
                                    desktop_group_uuid))
                            # get ip pool use start_ip and netmask, filter yzy_voi_terminal_desktops ips, get least ip
                            netmask_bits = netaddr.IPAddress(
                                desktop_mask).netmask_bits()
                            network = ipaddress.ip_interface(
                                desktop_start_ip + '/' +
                                str(netmask_bits)).network
                            original_ip_pool = [
                                x for x in network.hosts()
                                if x >= ipaddress.IPv4Address(desktop_start_ip)
                            ]
                            # get used ip in this desktop_group_uuid

                            # with redis_lock.Lock(self._redis.rds, 'create_terminal_desktop_bind_lock', 2):
                            qry_ips = db_api.get_item_with_all(
                                models.YzyVoiTerminalToDesktops,
                                {"desktop_group_uuid": desktop_group_uuid})
                            used_ip_pool = [
                                ipaddress.IPv4Address(qry.desktop_ip)
                                for qry in qry_ips
                            ]
                            available_ip_pool = [
                                ip for ip in original_ip_pool
                                if ip not in used_ip_pool
                            ]
                            if available_ip_pool:
                                desktop_ip = min(available_ip_pool).compressed
                                desktop_ip_info = {
                                    "desktop_is_dhcp": 0,
                                    "desktop_ip": desktop_ip,
                                    "desktop_mask": desktop_mask,
                                    "desktop_gateway": desktop_gateway,
                                    "desktop_dns1": desktop_dns1,
                                    "desktop_dns2": desktop_dns2,
                                }
                            else:  # use use_bottom_ip
                                logger.info(
                                    'desktop_group_uuid: {}, no availabel_ip'.
                                    format(desktop_group_uuid))
                                desktop_ip_info = {
                                    "desktop_is_dhcp": data.get("is_dhcp", ""),
                                    "desktop_ip": data.get("ip", ""),
                                    "desktop_mask": data.get("mask", ""),
                                    "desktop_gateway": data.get("gateway", ""),
                                    "desktop_dns1": data.get("dns1", ""),
                                    "desktop_dns2": data.get("dns2", ""),
                                }
                    bind_info = {
                        "uuid": create_uuid(),
                        "group_uuid": group_uuid,
                        "terminal_uuid": terminal_uuid,
                        "desktop_group_uuid": desktop_group_uuid,
                        "terminal_mac": terminal_mac,
                    }
                    bind_info.update(desktop_ip_info)
                    db_api.create_voi_terminal_desktop_bind(bind_info)
                logger.info(
                    "terminal desktop bind data: {} success".format(bind_info))
                return build_result("Success")
        except Exception as e:
            logger.error("", exc_info=True)
            return build_result("OtherError")