Ejemplo n.º 1
0
    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
        domain = VmDomain(host_ip=host.ipv4, vm_uuid=vm.hex_uuid)
        try:
            if not domain.detach_device(xml=xml_desc):
                raise VirtError(msg='从虚拟机卸载设备失败')
        except VirtError as e:
            raise DeviceError(msg=str(e))

        try:
            dev.umount()
        except DeviceError as e:
            domain.attach_device(xml=xml_desc)
            raise DeviceError(msg=f'与虚拟机解除挂载关系失败, {str(e)}')

        return True
Ejemplo n.º 2
0
    def mount(self, vm):
        """
        设备元数据层面与虚拟机建立挂载关系

        :return:
            True                # success
            raise DeviceError   # failed

        :raise: DeviceError
        """
        try:
            with transaction.atomic():
                db = PCIDevice.objects.select_for_update().get(pk=self._db.pk)
                if not db.enable:
                    raise DeviceError(msg='设备未开启使用')

                if db.vm_id == vm.hex_uuid:
                    return True

                if db.vm_id:
                    raise DeviceError(msg='设备已被挂载于其他主机')

                db.vm = vm
                db.attach_time = timezone.now()
                db.save(update_fields=['vm', 'attach_time'])
                self._db = db
                return True
        except Exception as e:
            raise DeviceError(msg=str(e))
Ejemplo n.º 3
0
    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 VmDomain(host_ip=host.ipv4,
                        vm_uuid=vm.hex_uuid).attach_device(xml=xml_desc):
                return True
            raise VirtError(msg='挂载到虚拟机失败')
        except VirtError as e:
            try:
                dev.umount()
            except:
                pass
            raise DeviceError(msg=str(e))
Ejemplo n.º 4
0
 def __init__(self, db):
     address = db.address.split(':')
     if len(address) != 4:
         raise DeviceError(msg='DEVICE BDF设备号有误')
     self._domain = address[0]
     self._bus = address[1]
     self._slot = address[2]
     self._function = address[3]
     super().__init__(db)
Ejemplo n.º 5
0
    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()
Ejemplo n.º 6
0
    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_all_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()
Ejemplo n.º 7
0
 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))
Ejemplo n.º 8
0
    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='未知设备')
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
    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()
Ejemplo n.º 11
0
    def get_pci_queryset_by_group(self, group):
        '''
        宿主机组下的PCI设备查询集

        :param group: Group对象或id
        :return:
            QuerySet()

        :raises: DeviceError
        '''
        try:
            ids = self._group_manager.get_enable_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()
Ejemplo n.º 12
0
    def umount(self):
        """
        设备元数据层面与虚拟机解除挂载关系

        :return:
            True                # success
            raise DeviceError   # failed

        :raise: DeviceError
        """
        try:
            with transaction.atomic():
                db = PCIDevice.objects.select_for_update().get(pk=self._db.pk)
                if not db.vm_id:
                    return True

                db.vm = None
                db.attach_time = None
                db.save(update_fields=['vm', 'attach_time'])
                self._db = db
                return True
        except Exception as e:
            raise DeviceError(msg=str(e))
Ejemplo n.º 13
0
    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).select_related(
                    *related_fields).all()

            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()