示例#1
0
    def update_virtual_switch(self, data):
        """
        更新虚拟交换机信息
        限制条件比较多
        1、有模板或者桌面使用基于该虚拟机交换机的网络时,不能修改节点的接口对应关系
        2、修改节点的接口对应关系时,需要删除原先创建的设备,然后重新创建新的网络设备
        :param data:
            {
                "uuid": "caa5d57e-3731-11ea-801e-000c295dd728",
                "node_uuid": "",
                "nic_uuid": ""
            }
        :return:
        """
        vswitch_uuid = data.get('uuid', '')
        logger.info("update vswitch %s", vswitch_uuid)
        vswitch = db_api.get_virtual_switch(vswitch_uuid)
        if not vswitch:
            return build_result("VSwitchNotExist")
        # 虚拟交换机有被使用,无法修改
        networks = db_api.get_network_all({"switch_uuid": vswitch.uuid})
        for network in networks:
            templates = db_api.get_template_with_all(
                {"network_uuid": network.uuid})
            if templates:
                return build_result("VSwitchUsedError", name=vswitch.name)
            desktops = db_api.get_desktop_with_all(
                {"network_uuid": network.uuid})
            if desktops:
                return build_result("VSwitchUsedError", name=vswitch.name)

        # 如果没有数据网络使用该虚拟交换机,则只需要修改对应关系
        try:
            for uplink in vswitch.uplinks:
                if not uplink.deleted:
                    if data['node_uuid'] == uplink.node_uuid:
                        if data['nic_uuid'] != uplink.nic_uuid:
                            logger.info("update nic from %s to %s",
                                        uplink.nic_uuid, data['nic_uuid'])
                            node = db_api.get_node_by_uuid(data['node_uuid'])
                            nic = db_api.get_nics_first(
                                {'uuid': data['nic_uuid']})
                            for network in networks:
                                self._delete_network(node.ip, network.uuid,
                                                     network.vlan_id)
                                self._create_network(node.ip, network.uuid,
                                                     network.switch_type,
                                                     nic.nic, network.vlan_id)
                            uplink.nic_uuid = data['nic_uuid']
                            uplink.soft_update()
                            break
        except Exception as e:
            return build_result("OtherError")
        return build_result("Success")
示例#2
0
    def delete_network(self, network_uuid):
        network = db_api.get_network_by_uuid(network_uuid)
        if not network:
            logger.error("network [%s] info not exist", network_uuid)
            return build_result("NetworkInfoNotExist")

        virtual_switch = network.virtual_switch_of_network
        if not virtual_switch or virtual_switch.deleted:
            logger.error("network [%s] not virtual switch" % network_uuid)
            return build_result("NetworkNotVSError")

        template = db_api.get_template_with_all({'network_uuid': network_uuid})
        if template:
            logger.error("network is in use, can not deleted")
            return build_result("NetworkInUse", name=network.name)

        network_type = virtual_switch.type
        if constants.VLAN_NETWORK_TYPE == network_type:
            vlan_id = network.vlan_id
        else:
            vlan_id = None

        for uplink in virtual_switch.uplinks:
            if not uplink.deleted:
                node = db_api.get_node_by_uuid(uplink.node_uuid)
                try:
                    self._delete_network(node.ip, network_uuid, vlan_id)
                except Exception as e:
                    logger.error("delete network in node %s failed:%s",
                                 node.ip,
                                 e,
                                 exc_info=True)
                    # return build_result("NetworkCreateFail")

        subnets = db_api.get_subnet_by_network(network.uuid)
        for subnet in subnets:
            subnet.soft_delete()
        network.soft_delete()
        return build_result("Success")
示例#3
0
    def check(self):
        # 检测是否处于基础镜像同传状态
        pools = db_api.get_resource_pool_list()
        for pool in pools:
            status = self.manger.get_base_image_status(pool)
            if status != 0:
                logger.info("pool: %s, status: %d" % (pool.name, status))
                return get_error_result("ImageTaskRunning")

        # 检测是否有模板差异盘同传
        templates = db_api.get_template_with_all({})
        for template in templates:
            if template.status in [
                    constants.STATUS_SAVING, constants.STATUS_CREATING,
                    constants.STATUS_COPING, constants.STATUS_ROLLBACK,
                    constants.STATUS_UPDATING
            ]:
                logger.info("template: %s, status: %d" %
                            (template.name, template.status))
                return get_error_result("ImageTaskRunning")
        templates = db_api.get_voi_template_with_all({})
        for template in templates:
            if template.status in [
                    constants.STATUS_SAVING, constants.STATUS_CREATING,
                    constants.STATUS_COPING, constants.STATUS_ROLLBACK,
                    constants.STATUS_UPDATING
            ]:
                logger.info("template: %s, status: %d" %
                            (template.name, template.status))
                return get_error_result("ImageTaskRunning")
            # status = self.manger.get_storages_status(template)
            # if status != 0:
            #     logger.info("template: %s, status: %d" % (template.name, status))
            #     return get_error_result("ImageTaskRunning")

        # TODO 检测终端升级包没有处于分发状态
        return get_error_result("Success")
示例#4
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
示例#5
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
示例#6
0
def update_ha_master():
    is_vip, is_master, is_backup = False, False, False
    current_ip = None
    ha_info_obj = db_api.get_ha_info_first()
    if ha_info_obj:
        # logger.info("ha_info before monitor update: %s" % ha_info_obj.dict())

        # 获取本机所有启用网口的ip,查看本节点的ip在ha_info表中是master_ip还是backup_ip
        code, out = cmdutils.run_cmd(
            """ip -br a |grep ' UP ' |grep -o '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*'""",
            ignore_log=True)
        if code != 0:
            logger.error(out)
        else:
            ip_list = [ip for ip in out.strip('\n').split('\n')]
            for ip in ip_list:
                if ip == ha_info_obj.vip:
                    is_vip = True
                elif ip == ha_info_obj.master_ip:
                    is_master = True
                elif ip == ha_info_obj.backup_ip:
                    is_backup = True

            if not is_vip:
                logger.error("server running without vip[%s]" %
                             ha_info_obj.vip)
            else:
                if not is_master and not is_backup:
                    logger.error(
                        "server running without master_ip[%s], backup_ip[%s]" %
                        (ha_info_obj.master_ip, ha_info_obj.backup_ip))
                elif is_master and is_backup:
                    logger.error(
                        "server running with both master_ip[%s], backup_ip[%s]"
                        % (ha_info_obj.master_ip, ha_info_obj.backup_ip))
                elif is_master and not is_backup:
                    current_ip = ha_info_obj.master_ip
                elif not is_master and is_backup:
                    # 如果发现本节点的ip在ha_info表中是backup_ip,说明notify.sh脚本中调用server服务/node/master接口去更新数据库的操作失败了
                    # 检查并修正ha_info表中的ip
                    current_ip = ha_info_obj.backup_ip
                    ha_info_obj.master_ip, ha_info_obj.backup_ip = ha_info_obj.backup_ip, ha_info_obj.master_ip
                    logger.info("update ha_info[%s] master_ip from %s to %s",
                                (ha_info_obj.uuid, ha_info_obj.backup_ip,
                                 ha_info_obj.master_ip))

                if current_ip:
                    # current_ip所在节点应该为master,检查并修正ha_info表中node_uuid、nic、nic_uuid
                    current_node_obj = db_api.get_node_by_ip(current_ip)
                    if current_node_obj.uuid == ha_info_obj.backup_uuid:
                        ha_info_obj.master_uuid, ha_info_obj.backup_uuid = ha_info_obj.backup_uuid, ha_info_obj.master_uuid
                        logger.info(
                            "update ha_info[%s] master_uuid from %s to %s",
                            (ha_info_obj.uuid, ha_info_obj.backup_uuid,
                             ha_info_obj.master_uuid))
                    current_ip_obj = db_api.get_nic_ip_by_ip(current_ip)
                    if current_ip_obj.nic_uuid == ha_info_obj.backup_nic_uuid:
                        ha_info_obj.master_nic_uuid, ha_info_obj.backup_nic_uuid = ha_info_obj.backup_nic_uuid, ha_info_obj.master_nic_uuid
                        logger.info(
                            "update ha_info[%s] master_nic_uuid from %s to %s",
                            (ha_info_obj.uuid, ha_info_obj.backup_nic_uuid,
                             ha_info_obj.master_nic_uuid))
                    if ha_info_obj.master_nic != ha_info_obj.backup_nic and current_ip_obj.name == ha_info_obj.backup_nic:
                        ha_info_obj.master_nic, ha_info_obj.backup_nic = ha_info_obj.backup_nic, ha_info_obj.master_nic
                        logger.info(
                            "update ha_info[%s] master_nic from %s to %s",
                            (ha_info_obj.uuid, ha_info_obj.backup_nic,
                             ha_info_obj.master_nic))
                    ha_info_obj.soft_update()

                    # 检查并修正backup_uuid节点的type
                    real_backup_node_obj = db_api.get_node_by_uuid(
                        ha_info_obj.backup_uuid)
                    if real_backup_node_obj.type not in [
                            constants.ROLE_SLAVE_AND_COMPUTE,
                            constants.ROLE_SLAVE
                    ]:
                        wrong_type = real_backup_node_obj.type
                        if real_backup_node_obj.type in [
                                constants.ROLE_MASTER_AND_COMPUTE,
                                constants.ROLE_COMPUTE
                        ]:
                            real_backup_node_obj.type = constants.ROLE_SLAVE_AND_COMPUTE
                        else:
                            real_backup_node_obj.type = constants.ROLE_SLAVE
                        real_backup_node_obj.soft_update()
                        logger.info(
                            "update real_backup_node[%s] role from %s to %s",
                            real_backup_node_obj.ip, wrong_type,
                            real_backup_node_obj.type)

                    # 检查并修正master_uuid节点的type
                    if current_node_obj.type not in [
                            constants.ROLE_MASTER,
                            constants.ROLE_MASTER_AND_COMPUTE
                    ]:
                        wrong_type = current_node_obj.type
                        if wrong_type in [
                                constants.ROLE_SLAVE_AND_COMPUTE,
                                constants.ROLE_COMPUTE
                        ]:
                            current_node_obj.type = constants.ROLE_MASTER_AND_COMPUTE
                        else:
                            current_node_obj.type = constants.ROLE_MASTER
                        current_node_obj.soft_update()
                        logger.info(
                            "update current_node[%s] role from %s to %s",
                            current_node_obj.ip, wrong_type,
                            current_node_obj.type)

                    # 检查并修正yzy_template、yzy_voi_template表的模板宿主机uuid
                    templates = db_api.get_template_with_all({})
                    for template in templates:
                        if constants.SYSTEM_DESKTOP == template.classify:
                            continue
                        if template.host_uuid != current_node_obj.uuid:
                            template.host_uuid = current_node_obj.uuid
                            template.soft_update()
                            logger.info("update template %s host_uuid to %s",
                                        template.name, current_node_obj.uuid)

                    voi_templates = db_api.get_voi_template_with_all({})
                    for template in voi_templates:
                        if constants.SYSTEM_DESKTOP == template.classify:
                            continue
                        if template.host_uuid != current_node_obj.uuid:
                            template.host_uuid = current_node_obj.uuid
                            template.soft_update()
                            logger.info(
                                "update voi template %s host_uuid to %s",
                                template.name, current_node_obj.uuid)
示例#7
0
 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")