def get(self, request, *args, **kwargs): center_id = str_to_int_or_default(request.GET.get('center', 0), 0) group_id = str_to_int_or_default(request.GET.get('group', 0), 0) host_id = str_to_int_or_default(request.GET.get('host', 0), 0) user_id = str_to_int_or_default(request.GET.get('user', 0), 0) search = request.GET.get('search', '') # 超级用户可以有用户下拉框选项 auth = request.user if auth.is_superuser: users = User.objects.all() else: # 普通用户只能查看自己的虚拟机,无用户下拉框选项 users = None user_id = auth.id v_manager = VmManager() try: queryset = v_manager.filter_vms_queryset( center_id=center_id, group_id=group_id, host_id=host_id, search=search, user_id=user_id, all_no_filters=auth.is_superuser) except VmError as e: return render(request, 'error.html', {'errors': ['查询虚拟机时错误', str(e)]}) queryset = queryset.prefetch_related('vdisk_set') # 反向预查询硬盘(避免多次访问数据库) try: c_manager = CenterManager() g_manager = GroupManager() centers = c_manager.get_center_queryset() if center_id > 0: groups = c_manager.get_group_queryset_by_center(center_id) else: groups = g_manager.get_group_queryset() if group_id > 0: hosts = g_manager.get_all_host_queryset_by_group(group_id) else: hosts = None except ComputeError as e: return render(request, 'error.html', {'errors': ['查询虚拟机时错误', str(e)]}) context = { 'center_id': center_id if center_id > 0 else None, 'centers': centers, 'groups': groups, 'group_id': group_id if group_id > 0 else None, 'hosts': hosts, 'host_id': host_id if host_id > 0 else None, 'search': search, 'users': users, 'user_id': user_id } context = self.get_vms_list_context(request, queryset, context) return render(request, 'vms_list.html', context=context)
def get(self, request, *args, **kwargs): center_id = str_to_int_or_default(request.GET.get('center', 0), 0) group_id = str_to_int_or_default(request.GET.get('group', 0), 0) host_id = str_to_int_or_default(request.GET.get('host', 0), 0) type_id = str_to_int_or_default(request.GET.get('type', 0), 0) search = request.GET.get('search', '') user = request.user c_manager = CenterManager() g_manager = GroupManager() p_manager = PCIDeviceManager() p_manager._group_manager = g_manager try: queryset = p_manager.filter_pci_queryset(center_id=center_id, group_id=group_id, host_id=host_id, search=search, type_id=type_id, user=user, all_no_filters=True) except DeviceError as e: return render(request, 'error.html', {'errors': ['查询PCI设备时错误', str(e)]}) try: centers = c_manager.get_center_queryset() if center_id > 0: groups = c_manager.get_user_group_queryset_by_center( center_or_id=center_id, user=user) else: groups = c_manager.get_user_group_queryset(user=user) if group_id > 0: hosts = g_manager.get_all_host_queryset_by_group(group_id) else: hosts = None except ComputeError as e: return render(request, 'error.html', {'errors': ['查询PCI设备时错误', str(e)]}) context = { 'center_id': center_id if center_id > 0 else None, 'centers': centers, 'groups': groups, 'group_id': group_id if group_id > 0 else None, 'hosts': hosts, 'host_id': host_id if host_id > 0 else None, 'search': search, 'types': PCIDevice.CHOICES_TYPE, 'type_id': type_id } context = self.get_vms_list_context(request, queryset, context) return render(request, 'pci_list.html', context=context)
def schedule_quota(self, size: int, user, center=None, group=None): """ 分配合适的硬盘CEPH存储池 :param size: :param user: :param center: :param group: :return: Quota() # None # 没有合适的硬盘CEPH存储池可用 :raises: VdiskError """ if group: if isinstance(group, int): group = GroupManager().get_group_by_id(group) if group is None: raise errors.VdiskError.from_error( errors.NotFoundError(msg='指定的宿主机组不存在')) if not group.user_has_perms(user): raise errors.VdiskError.from_error( errors.GroupAccessDeniedError()) queryset = self.get_quota_queryset_by_group(group=group) elif center: ids = user.group_set.filter(center=center).values_list('id', flat=True) queryset = self.get_quota_queryset_by_group_ids(ids) else: raise errors.VdiskInvalidParams(msg='必须指定一个"group"或者"center"') schedule_quota = None for quota in queryset: if not quota.check_disk_size_limit(size=size): continue if not quota.meet_needs(size=size): continue # 向硬盘CEPH存储池申请容量 if not quota.claim(size=size): continue schedule_quota = quota break if schedule_quota: return schedule_quota return None
def get(self, request, *args, **kwargs): center_id = str_to_int_or_default(request.GET.get('center', 0), 0) group_id = str_to_int_or_default(request.GET.get('group', 0), 0) quota_id = str_to_int_or_default(request.GET.get('quota', 0), 0) user_id = str_to_int_or_default(request.GET.get('user', 0), 0) search = request.GET.get('search', '') # 超级用户可以有用户下拉框选项 auth = request.user if auth.is_superuser: users = User.objects.all() else: # 普通用户只能查看自己的虚拟机,无用户下拉框选项 users = None user_id = auth.id manager = VdiskManager() try: queryset = manager.filter_vdisk_queryset( center_id=center_id, group_id=group_id, quota_id=quota_id, search=search, user_id=user_id, all_no_filters=auth.is_superuser) except VdiskError as e: return render(request, 'error.html', {'errors': ['查询云硬盘时错误', str(e)]}) try: c_manager = CenterManager() centers = c_manager.get_center_queryset() if center_id > 0: groups = c_manager.get_group_queryset_by_center(center_id) else: groups = GroupManager().get_group_queryset() except ComputeError as e: return render(request, 'error.html', {'errors': ['查询机组时错误', str(e)]}) if group_id > 0: quotas = manager.get_quota_queryset_by_group(group_id) else: quotas = None context = {} context['center_id'] = center_id if center_id > 0 else None context['centers'] = centers context['groups'] = groups context['group_id'] = group_id if group_id > 0 else None context['quotas'] = quotas context['quota_id'] = quota_id if quota_id > 0 else None context['search'] = search context['users'] = users context['user_id'] = user_id context = self.get_disks_list_context(request, queryset, context) return render(request, 'vdisk_list.html', context=context)
def get_user_pci_queryset(self, user): """ 用户有访问权限的PCI设备查询集 :param user: 用户对象 :return: QuerySet() :raises: DeviceError """ try: h_ids = GroupManager().get_user_host_ids(user=user) qs = self.get_device_queryset().filter(id__in=h_ids).all() except ComputeError as e: raise DeviceError(msg=str(e)) return qs
def get_host_list(group): """ 获取指定宿主机组的宿主机列表 :param group: 宿主机组Group(),只获取此组的宿主机 :return: list # success raise ScheduleError # failed ,未找到宿主机或发生错误 :raise ScheduleError """ try: host_list = list(GroupManager().get_enable_host_queryset_by_group(group_or_id=group)) except (ComputeError, Exception) as e: raise ScheduleError(msg=f'获取宿主机list错误,{str(e)}') return host_list
def get(self, request, *args, **kwargs): if not request.user.is_superuser: return HttpResponse('您无权访问此页面') centers = CenterManager().get_stat_center_queryset().values( 'id', 'name', 'mem_total', 'mem_allocated', 'real_cpu', 'vcpu_total', 'vcpu_allocated', 'vm_created') groups = GroupManager().get_stat_group_queryset().values( 'id', 'name', 'center__name', 'mem_total', 'mem_allocated', 'real_cpu', 'vcpu_total', 'vcpu_allocated', 'vm_created') hosts = Host.objects.select_related('group').values( 'id', 'ipv4', 'group__name', 'mem_total', 'mem_allocated', 'real_cpu', 'vcpu_total', 'vcpu_allocated', 'vm_created').all() return render(request, 'reports_list.html', context={ 'centers': centers, 'groups': groups, 'hosts': hosts })
def _get_host_list(self, group, vlan=None): ''' 获取指定宿主机组的属于vlan子网的宿主机列表 :param vlan: 子网对象Vlan() :param group_id: 宿主机组Group(),只获取此组的宿主机 :return: list # success raise ScheduleError # failed ,未找到宿主机或发生错误 :raise ScheduleError ''' try: if vlan: host_list = HostManager().get_hosts_by_group_and_vlan( group_or_id=group, vlan=vlan) else: host_list = list(GroupManager().get_host_queryset_by_group( group_or_id=group)) except (ComputeError, Exception) as e: raise ScheduleError(msg=f'获取宿主机list错误,{str(e)}') return host_list
def filter_vlan_queryset(self, center: int = None, group: int = None, is_public: bool = None, user=None): """ 筛选vlan查询集 :param center: 分中心id :param group: 宿主机组id :param is_public: 公网或私网 :param user: 用户实例,用于过滤用户有权限使用的vlan :return: QuerySet() """ group_set = None if user: group_set = user.group_set.all() if group: if not group_set: group_set = GroupManager().get_group_queryset() group_set = group_set.filter(id=group) elif center: if group_set: group_set = group_set.filter(center=center) else: group_set = CenterManager().get_group_queryset_by_center( center) queryset = self.get_vlan_queryset() if is_public is True: queryset = queryset.filter(tag=Vlan.NET_TAG_PUBLIC) elif is_public is False: queryset = queryset.filter(tag=Vlan.NET_TAG_PRIVATE) if group_set: queryset = queryset.filter( group__in=Subquery(group_set.values('id'))).all() return queryset
class PCIDeviceManager: DeviceError = DeviceError def __init__(self): self._center_manager = CenterManager() self._group_manager = GroupManager() self._host_manager = HostManager() def get_device_queryset(self): ''' 获取所有PCI设备的查询集 :return: QuerySet() ''' return PCIDevice.objects.all() def get_device_by_id(self, device_id: int, related_fields=('host', )): ''' :return: PCIDevice() # success None # not exists :raises: DeviceError ''' qs = self.get_device_queryset() try: if related_fields: qs = qs.select_related(*related_fields).all() return qs.filter(pk=device_id).first() except Exception as e: raise DeviceError(msg=str(e)) def get_device_by_address(self, address: str): ''' :return: PCIDevice() # success None # not exists ''' return self.get_device_queryset().filter(address=address).first() def get_user_pci_queryset(self, user): """ 用户有访问权限的PCI设备查询集 :param user: 用户对象 :return: QuerySet() :raises: DeviceError """ try: h_ids = GroupManager().get_user_host_ids(user=user) qs = self.get_device_queryset().filter(id__in=h_ids).all() except ComputeError as e: raise DeviceError(msg=str(e)) return qs def get_pci_queryset_by_center(self, center): """ 分中心下的PCI设备查询集 :param center: Center对象或id :return: QuerySet() :raises: DeviceError """ try: group_ids = self._center_manager.get_group_ids_by_center(center) host_ids = self._group_manager.get_host_ids_by_group_ids(group_ids) except ComputeError as e: raise DeviceError(msg=str(e)) return self.get_device_queryset().filter(host__in=host_ids).all() def get_user_pci_queryset_by_center(self, center, user): """ 用户有访问权限的,分中心下的PCI设备查询集 :param center: Center对象或id :param user: 用户对象 :return: QuerySet() :raises: DeviceError """ try: group_ids = self._center_manager.get_user_group_ids_by_center( center=center, user=user) host_ids = self._group_manager.get_host_ids_by_group_ids(group_ids) except ComputeError as e: raise DeviceError(msg=str(e)) return self.get_device_queryset().filter(host__in=host_ids).all() def get_pci_queryset_by_group(self, group): ''' 宿主机组下的PCI设备查询集 :param group: Group对象或id :return: QuerySet() :raises: DeviceError ''' try: ids = self._group_manager.get_host_ids_by_group(group_or_id=group) except ComputeError as e: raise DeviceError(msg=str(e)) return self.get_device_queryset().filter(host__in=ids).all() def get_user_pci_queryset_by_group(self, group, user): ''' 用户有访问权限的,机组下的PCI设备查询集 :param group: Group对象或id :param user: 用户对象 :return: QuerySet() :raises: DeviceError ''' gm = self._group_manager try: group = gm.enforce_group_obj(group) if not group.user_has_perms(user=user): raise DeviceError(msg='无宿主机组的访问权限') ids = gm.get_host_ids_by_group(group_or_id=group) except ComputeError as e: raise DeviceError(msg=str(e)) return self.get_device_queryset().filter(host__in=ids).all() def get_pci_queryset_by_host(self, host): """ 宿主机的PCI设备查询集 :param host: Host对象或id :return: QuerySet() :raises: DeviceError """ return self.get_device_queryset().filter(host=host).all() def get_user_pci_queryset_by_host(self, host, user): """ 用户有访问权限的,宿主机的PCI设备查询集 :param host: Host对象或id :param user: 用户对象 :return: QuerySet() :raises: DeviceError """ try: host = self._host_manager.enforce_host_obj(host) except ComputeError as e: raise DeviceError(msg=str(e)) if not host.user_has_perms(user=user): raise DeviceError(msg='无宿主机的访问权限') return self.get_device_queryset().filter(host=host).all() def device_wrapper(self, device: PCIDevice): ''' PCI设备对象的包装器 :param device:PCI设备对象 :return: BasePCIDevice子类 # GPUDevice :raises: DeviceError ''' if device.type == device.TYPE_GPU: return GPUDevice(db=device) return DeviceError(msg='未知设备') def mount_to_vm(self, device: PCIDevice, vm): ''' 挂载设备到虚拟机 :param device: pci设备对象 :param vm: 虚拟机对象 :return: True # success :raises: DeviceError ''' host = vm.host dev = self.device_wrapper(device) if dev.need_in_same_host(): if dev.host_id != host.id: raise DeviceError(msg='设备和虚拟机不在同一宿主机') try: dev.mount(vm=vm) except DeviceError as e: raise DeviceError(msg=f'与虚拟机建立挂载关系失败, {str(e)}') xml_desc = dev.xml_desc try: if VirtAPI().attach_device(host_ipv4=host.ipv4, vm_uuid=vm.hex_uuid, xml=xml_desc): return True raise VirtError(msg='挂载到虚拟机失败') except VirtError as e: try: dev.umount() except: pass raise DeviceError(msg=str(e)) def umount_from_vm(self, device: PCIDevice): ''' 卸载设备从虚拟机 :param device: pci设备对象 :return: True # success :raises: DeviceError ''' dev = self.device_wrapper(device) vm = dev.vm if not vm: return True host = vm.host xml_desc = dev.xml_desc v_api = VirtAPI() try: if not v_api.detach_device( host_ipv4=host.ipv4, vm_uuid=vm.hex_uuid, xml=xml_desc): raise VirtError(msg='从虚拟机卸载设备失败') except VirtError as e: raise DeviceError(msg=str(e)) try: dev.umount() except DeviceError as e: v_api.attach_device(host_ipv4=host.ipv4, vm_uuid=vm.hex_uuid, xml=xml_desc) raise DeviceError(msg=f'与虚拟机解除挂载关系失败, {str(e)}') return True def filter_pci_queryset(self, center_id: int = 0, group_id: int = 0, host_id: int = 0, type_id: int = 0, search: str = '', user=None, all_no_filters: bool = False, related_fields: tuple = ()): """ 通过条件筛选虚拟机查询集 :param center_id: 分中心id,大于0有效 :param group_id: 机组id,大于0有效 :param host_id: 宿主机id,大于0有效 :param type_id: 设备类型id,大于0有效 :param search: 关键字筛选条件 :param user: 用户对象 :param all_no_filters: 筛选条件都无效时;True: 返回所有; False: 抛出错误 :param related_fields: 外键字段;外键字段直接一起获取,而不是惰性的用时再获取 :return: QuerySet # success :raise: DeviceError """ if not related_fields: related_fields = ('host__group', 'vm__mac_ip') if center_id <= 0 and group_id <= 0 and host_id <= 0 and type_id <= 0 and not search: if user and user.id: return self.get_user_pci_queryset(user=user) if not all_no_filters: raise DeviceError(msg='无有效的查询条件') return self.get_device_queryset().select_related( *related_fields).all() queryset = None if host_id > 0: queryset = self.get_user_pci_queryset_by_host(host=host_id, user=user) elif group_id > 0: queryset = self.get_user_pci_queryset_by_group(group_id, user=user) elif center_id > 0: queryset = self.get_user_pci_queryset_by_center(center=center_id, user=user) if type_id > 0: if queryset is not None: queryset = queryset.filter(type=type_id).all() else: queryset = self.get_device_queryset().filter( type=type_id).all() if search: if queryset is not None: queryset = queryset.filter( Q(remarks__icontains=search) | Q(host__ipv4__icontains=search)).all() else: queryset = self.get_device_queryset().filter( Q(remarks__icontains=search) | Q(host__ipv4__icontains=search)).all() return queryset.select_related(*related_fields).all()
def __init__(self): self._center_manager = CenterManager() self._group_manager = GroupManager() self._host_manager = HostManager()