コード例 #1
0
    def update_disk(self, params):
        """Update disk information."""
        # Only admin users can perform delete.
        if not reload_object(self.user).is_superuser:
            raise HandlerPermissionError()

        node = self.get_object(params)
        device = BlockDevice.objects.get(id=params['block_id'],
                                         node=node).actual_instance
        if device.type == 'physical':
            form = UpdatePhysicalBlockDeviceForm(instance=device, data=params)
        elif device.type == 'virtual':
            form = UpdateVirtualBlockDeviceForm(instance=device, data=params)
        else:
            raise HandlerError('Cannot update block device of type %s' %
                               device.type)
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            disk_obj = form.save()
            self._update_obj_tags(disk_obj, params)
            if 'fstype' in params:
                self.update_blockdevice_filesystem(
                    disk_obj, params['fstype'], params.get('mount_point', ''),
                    params.get('mount_options', ''))
コード例 #2
0
 def update_blockdevice_filesystem(self, blockdevice, fstype, mount_point,
                                   mount_options):
     fs = blockdevice.get_effective_filesystem()
     if not fstype:
         if fs:
             fs.delete()
         return
     if fs is None or fstype != fs.fstype:
         form = FormatBlockDeviceForm(blockdevice, {'fstype': fstype})
         if not form.is_valid():
             raise HandlerError(form.errors)
         form.save()
         fs = blockdevice.get_effective_filesystem()
     if mount_point != fs.mount_point:
         # XXX: Elsewhere, a mount_point of "" would somtimes mean that the
         # filesystem is mounted, sometimes that it is *not* mounted. Which
         # is correct was not clear from the code history, so the existing
         # behaviour is maintained here.
         if mount_point is None or mount_point == "":
             fs.mount_point = None
             fs.mount_options = None
             fs.save()
         else:
             form = MountFilesystemForm(
                 blockdevice.get_effective_filesystem(), {
                     'mount_point': mount_point,
                     'mount_options': mount_options
                 })
             if not form.is_valid():
                 raise HandlerError(form.errors)
             else:
                 form.save()
コード例 #3
0
    def create_bcache(self, params):
        """Create a bcache."""
        node = self._get_node_or_permission_error(params)
        block_id = params.get('block_id')
        partition_id = params.get('partition_id')

        data = {
            "name": params["name"],
            "cache_set": params["cache_set"],
            "cache_mode": params["cache_mode"],
        }

        if partition_id is not None:
            data["backing_partition"] = partition_id
        elif block_id is not None:
            data["backing_device"] = block_id
        else:
            raise HandlerError("Either block_id or partition_id is required.")

        form = CreateBcacheForm(node=node, data=data)
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            bcache = form.save()

        self._update_obj_tags(bcache.virtual_device, params)
        if 'fstype' in params:
            self.update_blockdevice_filesystem(bcache.virtual_device,
                                               params.get("fstype"),
                                               params.get("mount_point"),
                                               params.get("mount_options"))
コード例 #4
0
 def update_disk(self, params):
     """Update disk information."""
     node = self._get_node_or_permission_error(
         params, permission=self._meta.edit_permission)
     device = BlockDevice.objects.get(
         id=params['block_id'], node=node).actual_instance
     if device.type == 'physical':
         form = UpdatePhysicalBlockDeviceForm(
             instance=device, data=params)
     elif device.type == 'virtual':
         form = UpdateVirtualBlockDeviceForm(
             instance=device, data=params)
     else:
         raise HandlerError(
             'Cannot update block device of type %s' % device.type)
     if not form.is_valid():
         raise HandlerError(form.errors)
     else:
         disk_obj = form.save()
         self._update_obj_tags(disk_obj, params)
         if 'fstype' in params:
             self.update_blockdevice_filesystem(
                 disk_obj, params['fstype'],
                 params.get('mount_point', ''),
                 params.get('mount_options', ''))
コード例 #5
0
    def fetch(self, params):
        """Fetch the releases and the arches from the provided source."""
        # Must be administrator.
        assert self.user.is_superuser, "Permission denied."
        # Build a source, but its not saved into the database.
        boot_source = self.get_bootsource(params, from_db=False)
        try:
            # Validate the boot source fields without committing it.
            boot_source.clean_fields()
        except ValidationError as error:
            raise HandlerValidationError(error)
        source = boot_source.to_dict_without_selections()

        # FIXME: This modifies the environment of the entire process, which is
        # Not Cool. We should integrate with simplestreams in a more
        # Pythonic manner.
        set_simplestreams_env()
        with tempdir("keyrings") as keyrings_path:
            [source] = write_all_keyrings(keyrings_path, [source])
            try:
                descriptions = download_all_image_descriptions(
                    [source], user_agent=get_maas_user_agent())
            except Exception as error:
                raise HandlerError(str(error))
        items = list(descriptions.items())
        err_msg = "Mirror provides no Ubuntu images."
        if len(items) == 0:
            raise HandlerError(err_msg)
        releases = {}
        arches = {}
        for image_spec, product_info in items:
            # Only care about Ubuntu images.
            if image_spec.os != "ubuntu":
                continue
            releases[image_spec.release] = {
                "name":
                image_spec.release,
                "title":
                product_info.get(
                    "release_title",
                    format_ubuntu_distro_series(image_spec.release),
                ),
                "checked":
                False,
                "deleted":
                False,
            }
            arches[image_spec.arch] = {
                "name": image_spec.arch,
                "title": image_spec.arch,
                "checked": False,
                "deleted": False,
            }
        if len(releases) == 0 or len(arches) == 0:
            raise HandlerError(err_msg)
        return json.dumps({
            "releases": list(releases.values()),
            "arches": list(arches.values()),
        })
コード例 #6
0
ファイル: machine.py プロジェクト: rodrigogansobarbieri/maas
    def update_filesystem(self, params):
        node = self._get_node_or_permission_error(
            params, permission=NodePermission.edit)
        if node.locked:
            raise HandlerPermissionError()
        block_id = params.get("block_id")
        partition_id = params.get("partition_id")
        fstype = params.get("fstype")
        mount_point = params.get("mount_point")
        mount_options = params.get("mount_options")

        if node.status not in [NODE_STATUS.ALLOCATED, NODE_STATUS.READY]:
            raise HandlerError(
                "Node must be allocated or ready to edit storage")

        # If this is on a block device, check if the tags need to be updated.
        # (The client sends them in from the same form.)
        blockdevice = None
        if block_id is not None:
            blockdevice = BlockDevice.objects.get(id=block_id, node=node)
            tags = params.get("tags", None)
            # If the tags parameter was left out, that means "don't touch the
            # tags". (An empty list means "clear the tags".)
            if tags is not None:
                tags = [tag["text"] for tag in tags]
                if set(blockdevice.tags) != set(tags):
                    blockdevice.tags = tags
                    blockdevice.save()
        if partition_id:
            self.update_partition_filesystem(node, partition_id, fstype,
                                             mount_point, mount_options)
        elif blockdevice is not None:
            self.update_blockdevice_filesystem(blockdevice, fstype,
                                               mount_point, mount_options)
コード例 #7
0
    def update_filesystem(self, params):
        node = self.get_object(params)
        block_id = params.get('block_id')
        partition_id = params.get('partition_id')
        fstype = params.get('fstype')
        mount_point = params.get('mount_point')
        mount_options = params.get('mount_options')

        if node.status not in [NODE_STATUS.ALLOCATED, NODE_STATUS.READY]:
            raise HandlerError(
                "Node must be allocated or ready to edit storage")
        if (not reload_object(self.user).is_superuser
                and node.owner_id != self.user.id):
            raise HandlerPermissionError()

        # If this is on a block device, check if the tags need to be updated.
        # (The client sends them in from the same form.)
        blockdevice = None
        if block_id is not None:
            blockdevice = BlockDevice.objects.get(id=block_id, node=node)
            tags = params.get('tags', None)
            # If the tags parameter was left out, that means "don't touch the
            # tags". (An empty list means "clear the tags".)
            if tags is not None:
                tags = [tag['text'] for tag in tags]
                if set(blockdevice.tags) != set(tags):
                    blockdevice.tags = tags
                    blockdevice.save()
        if partition_id:
            self.update_partition_filesystem(node, partition_id, fstype,
                                             mount_point, mount_options)
        elif blockdevice is not None:
            self.update_blockdevice_filesystem(blockdevice, fstype,
                                               mount_point, mount_options)
コード例 #8
0
    def create_logical_volume(self, params):
        """Create a logical volume."""
        # Only admin users can perform delete.
        if not reload_object(self.user).is_superuser:
            raise HandlerPermissionError()

        node = self.get_object(params)
        volume_group = VolumeGroup.objects.get(id=params['volume_group_id'])
        if volume_group.get_node() != node:
            raise VolumeGroup.DoesNotExist()
        form = CreateLogicalVolumeForm(volume_group, {
            'name': params['name'],
            'size': params['size'],
        })
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            logical_volume = form.save()

        self._update_obj_tags(logical_volume, params)
        if 'fstype' in params:
            self.update_blockdevice_filesystem(logical_volume,
                                               params.get("fstype"),
                                               params.get("mount_point"),
                                               params.get("mount_options"))
コード例 #9
0
ファイル: machine.py プロジェクト: rodrigogansobarbieri/maas
 def update_vmfs_datastore(self, params):
     """Add or remove block devices or partitions from a datastore."""
     vmfs = self._get_vmfs_datastore(params)
     form = UpdateVMFSForm(vmfs, data=params)
     if not form.is_valid():
         raise HandlerError(form.errors)
     else:
         form.save()
コード例 #10
0
 def get_form_class(self, action):
     """Return the form class used for `action`."""
     if action == "create" and self._deployed:
         return AdminMachineForm
     if action in ("create", "update"):
         return AdminMachineWithMACAddressesForm
     else:
         raise HandlerError("Unknown action: %s" % action)
コード例 #11
0
ファイル: device.py プロジェクト: ocni-dtu/maas
 def get_form_class(self, action):
     """Return the form class used for `action`."""
     if action == "create":
         return DeviceWithMACsForm
     elif action == "update":
         return DeviceForm
     else:
         raise HandlerError("Unknown action: %s" % action)
コード例 #12
0
ファイル: machine.py プロジェクト: rodrigogansobarbieri/maas
 def apply_storage_layout(self, params):
     """Apply the specified storage layout."""
     node = self._get_node_or_permission_error(
         params, permission=self._meta.edit_permission)
     form = StorageLayoutForm(required=True, data=params)
     if not form.is_valid():
         raise HandlerError(form.errors)
     storage_layout = params.get("storage_layout")
     try:
         node.set_storage_layout(storage_layout)
     except StorageLayoutMissingBootDiskError:
         raise HandlerError(
             "Machine is missing a boot disk; no storage layout can be "
             "applied.")
     except StorageLayoutError as e:
         raise HandlerError("Failed to configure storage layout '%s': %s" %
                            (storage_layout, str(e)))
コード例 #13
0
 def create_volume_group(self, params):
     """Create a volume group."""
     node = self._get_node_or_permission_error(params)
     form = CreateVolumeGroupForm(node=node, data=params)
     if not form.is_valid():
         raise HandlerError(form.errors)
     else:
         form.save()
コード例 #14
0
ファイル: machine.py プロジェクト: rodrigogansobarbieri/maas
 def create_vmfs_datastore(self, params):
     """Create a VMFS datastore."""
     node = self._get_node_or_permission_error(
         params, permission=self._meta.edit_permission)
     form = CreateVMFSForm(node, data=params)
     if not form.is_valid():
         raise HandlerError(form.errors)
     else:
         form.save()
コード例 #15
0
 def set_boot_disk(self, params):
     """Set the disk as the boot disk."""
     node = self._get_node_or_permission_error(params)
     device = BlockDevice.objects.get(id=params['block_id'],
                                      node=node).actual_instance
     if device.type != 'physical':
         raise HandlerError(
             "Only a physical disk can be set as the boot disk.")
     node.boot_disk = device
     node.save()
コード例 #16
0
    def create_cache_set(self, params):
        """Create a cache set."""
        node = self._get_node_or_permission_error(params)
        block_id = params.get('block_id')
        partition_id = params.get('partition_id')

        data = {}
        if partition_id is not None:
            data["cache_partition"] = partition_id
        elif block_id is not None:
            data["cache_device"] = block_id
        else:
            raise HandlerError("Either block_id or partition_id is required.")

        form = CreateCacheSetForm(node=node, data=data)
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            form.save()
コード例 #17
0
    def import_keys(self, params):
        """Import the requesting user's SSH keys.

        Import SSH keys for a given protocol and authorization ID in
        protocol:auth_id format.
        """
        try:
            KeySource.objects.save_keys_for_user(user=self.user,
                                                 protocol=params['protocol'],
                                                 auth_id=params['auth_id'])
        except ImportSSHKeysError as e:
            raise HandlerError(str(e))
コード例 #18
0
    def create_volume_group(self, params):
        """Create a volume group."""
        # Only admin users can perform delete.
        if not reload_object(self.user).is_superuser:
            raise HandlerPermissionError()

        node = self.get_object(params)
        form = CreateVolumeGroupForm(node=node, data=params)
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            form.save()
コード例 #19
0
ファイル: machine.py プロジェクト: th3architect/maas
 def update_partition_filesystem(
     self, node, partition_id, fstype, mount_point, mount_options
 ):
     partition = Partition.objects.get(
         id=partition_id, partition_table__block_device__node=node
     )
     fs = partition.get_effective_filesystem()
     if not fstype:
         if fs:
             fs.delete()
             return
     if fs is None or fstype != fs.fstype:
         form = FormatPartitionForm(partition, {"fstype": fstype})
         if not form.is_valid():
             raise HandlerError(form.errors)
         form.save()
         fs = partition.get_effective_filesystem()
     if mount_point != fs.mount_point:
         # XXX: Elsewhere, a mount_point of "" would somtimes mean that the
         # filesystem is mounted, sometimes that it is *not* mounted. Which
         # is correct was not clear from the code history, so the existing
         # behaviour is maintained here.
         if mount_point is None or mount_point == "":
             fs.mount_point = None
             fs.mount_options = None
             fs.save()
         else:
             form = MountFilesystemForm(
                 partition.get_effective_filesystem(),
                 {
                     "mount_point": mount_point,
                     "mount_options": mount_options,
                 },
             )
             if not form.is_valid():
                 raise HandlerError(form.errors)
             else:
                 form.save()
コード例 #20
0
    def create_raid(self, params):
        """Create a RAID."""
        node = self._get_node_or_permission_error(params)
        form = CreateRaidForm(node=node, data=params)
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            raid = form.save()

        self._update_obj_tags(raid.virtual_device, params)
        if 'fstype' in params:
            self.update_blockdevice_filesystem(
                raid.virtual_device, params.get("fstype"),
                params.get("mount_point"), params.get("mount_options"))
コード例 #21
0
    def set_boot_disk(self, params):
        """Set the disk as the boot disk."""
        # Only admin users can perform delete.
        if not reload_object(self.user).is_superuser:
            raise HandlerPermissionError()

        node = self.get_object(params)
        device = BlockDevice.objects.get(id=params['block_id'],
                                         node=node).actual_instance
        if device.type != 'physical':
            raise HandlerError(
                "Only a physical disk can be set as the boot disk.")
        node.boot_disk = device
        node.save()
コード例 #22
0
    def create_cache_set(self, params):
        """Create a cache set."""
        # Only admin users can perform delete.
        if not reload_object(self.user).is_superuser:
            raise HandlerPermissionError()

        node = self.get_object(params)
        block_id = params.get('block_id')
        partition_id = params.get('partition_id')

        data = {}
        if partition_id is not None:
            data["cache_partition"] = partition_id
        elif block_id is not None:
            data["cache_device"] = block_id
        else:
            raise HandlerError("Either block_id or partition_id is required.")

        form = CreateCacheSetForm(node=node, data=data)
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            form.save()
コード例 #23
0
    def create_partition(self, params):
        """Create a partition."""
        node = self._get_node_or_permission_error(params)
        disk_obj = BlockDevice.objects.get(id=params['block_id'], node=node)
        form = AddPartitionForm(disk_obj, {
            'size': params['partition_size'],
        })
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            partition = form.save()

        if 'fstype' in params:
            self.update_partition_filesystem(node, partition.id,
                                             params.get("fstype"),
                                             params.get("mount_point"),
                                             params.get("mount_options"))
コード例 #24
0
ファイル: sshkey.py プロジェクト: jamal-fuma/maas
    def import_keys(self, params):
        """Import the requesting user's SSH keys.

        Import SSH keys for a given protocol and authorization ID in
        protocol:auth_id format.
        """
        try:
            KeySource.objects.save_keys_for_user(
                user=self.user,
                protocol=params['protocol'],
                auth_id=params['auth_id'])
            request = HttpRequest()
            request.user = self.user
            create_audit_event(
                EVENT_TYPES.AUTHORISATION, ENDPOINT.UI, request,
                None, description="Imported SSH keys.")
        except ImportSSHKeysError as e:
            raise HandlerError(str(e))
コード例 #25
0
    def create_raid(self, params):
        """Create a RAID."""
        # Only admin users can perform delete.
        if not reload_object(self.user).is_superuser:
            raise HandlerPermissionError()

        node = self.get_object(params)
        form = CreateRaidForm(node=node, data=params)
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            raid = form.save()

        self._update_obj_tags(raid.virtual_device, params)
        if 'fstype' in params:
            self.update_blockdevice_filesystem(raid.virtual_device,
                                               params.get("fstype"),
                                               params.get("mount_point"),
                                               params.get("mount_options"))
コード例 #26
0
ファイル: machine.py プロジェクト: rodrigogansobarbieri/maas
    def create_partition(self, params):
        """Create a partition."""
        node = self._get_node_or_permission_error(
            params, permission=self._meta.edit_permission)
        disk_obj = BlockDevice.objects.get(id=params["block_id"], node=node)
        form = AddPartitionForm(disk_obj, {"size": params["partition_size"]})
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            partition = form.save()

        self._update_obj_tags(partition, params)
        if "fstype" in params:
            self.update_partition_filesystem(
                node,
                partition.id,
                params.get("fstype"),
                params.get("mount_point"),
                params.get("mount_options"),
            )
コード例 #27
0
    def create_partition(self, params):
        """Create a partition."""
        # Only admin users can perform delete.
        if not reload_object(self.user).is_superuser:
            raise HandlerPermissionError()

        node = self.get_object(params)
        disk_obj = BlockDevice.objects.get(id=params['block_id'], node=node)
        form = AddPartitionForm(disk_obj, {
            'size': params['partition_size'],
        })
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            partition = form.save()

        if 'fstype' in params:
            self.update_partition_filesystem(node, partition.id,
                                             params.get("fstype"),
                                             params.get("mount_point"),
                                             params.get("mount_options"))
コード例 #28
0
ファイル: node.py プロジェクト: tai271828/maas
    def update_tags(self, node_obj, tags):
        # Loop through the nodes current tags. If the tag exists in `tags` then
        # nothing needs to be done so its removed from `tags`. If it does not
        # exists then the tag was removed from the node and should be removed
        # from the nodes set of tags.
        for tag in node_obj.tags.all():
            if tag.name not in tags:
                node_obj.tags.remove(tag)
            else:
                tags.remove(tag.name)

        # All the tags remaining in `tags` are tags that are not linked to
        # node. Get or create that tag and add the node to the tags set.
        for tag_name in tags:
            tag_obj, _ = Tag.objects.get_or_create(name=tag_name)
            if tag_obj.is_defined:
                raise HandlerError(
                    "Cannot add tag %s to node because it has a "
                    "definition." % tag_name)
            tag_obj.node_set.add(node_obj)
            tag_obj.save()
コード例 #29
0
    def create_logical_volume(self, params):
        """Create a logical volume."""
        node = self._get_node_or_permission_error(
            params, permission=self._meta.edit_permission)
        volume_group = VolumeGroup.objects.get(id=params['volume_group_id'])
        if volume_group.get_node() != node:
            raise VolumeGroup.DoesNotExist()
        form = CreateLogicalVolumeForm(
            volume_group, {
                'name': params['name'],
                'size': params['size'],
            })
        if not form.is_valid():
            raise HandlerError(form.errors)
        else:
            logical_volume = form.save()

        self._update_obj_tags(logical_volume, params)
        if 'fstype' in params:
            self.update_blockdevice_filesystem(
                logical_volume, params.get("fstype"),
                params.get("mount_point"), params.get("mount_options"))
コード例 #30
0
    def get_bootsource(self, params, from_db=False):
        source_type = params.get("source_type", "custom")
        if source_type == "maas.io":
            url = DEFAULT_IMAGES_URL
            keyring_filename = DEFAULT_KEYRINGS_PATH
            keyring_data = b""
        elif source_type == "custom":
            url = params["url"]
            keyring_filename = params.get("keyring_filename", "")
            keyring_data = params.get("keyring_data", "").encode("utf-8")
            if keyring_filename == "" and keyring_data == b"":
                keyring_filename = DEFAULT_KEYRINGS_PATH
        else:
            raise HandlerError("Unknown source_type: %s" % source_type)

        if from_db:
            source, created = BootSource.objects.get_or_create(
                url=url,
                defaults={
                    "keyring_filename": keyring_filename,
                    "keyring_data": keyring_data,
                },
            )
            if not created:
                source.keyring_filename = keyring_filename
                source.keyring_data = keyring_data
                source.save()
            else:
                # This was a new source, make sure its the only source in the
                # database. This is because the UI only supports handling one
                # source at a time.
                BootSource.objects.exclude(id=source.id).delete()
            return source
        else:
            return BootSource(
                url=url,
                keyring_filename=keyring_filename,
                keyring_data=keyring_data,
            )