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', ''))
def create_bcache(self, params): """Create a bcache.""" # 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 = { "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"))
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)
def link_subnet(self, params): """Create or update the link.""" # Only admin users can perform update. if not reload_object(self.user).is_superuser: raise HandlerPermissionError() node = self.get_object(params) interface = Interface.objects.get(node=node, id=params["interface_id"]) if params['ip_assignment'] == DEVICE_IP_ASSIGNMENT_TYPE.STATIC: mode = INTERFACE_LINK_TYPE.STATIC elif params['ip_assignment'] == DEVICE_IP_ASSIGNMENT_TYPE.DYNAMIC: mode = INTERFACE_LINK_TYPE.DHCP else: mode = INTERFACE_LINK_TYPE.LINK_UP subnet = None if "subnet" in params: subnet = Subnet.objects.get(id=params["subnet"]) if ("link_id" in params and interface.ip_addresses.filter(id=params["link_id"]).exists()): # We are updating an already existing link, which may have been # removed earlier in this transaction (via update_interface.) interface.update_link_by_id(params["link_id"], mode, subnet, ip_address=params.get( "ip_address", None)) elif params['ip_assignment'] == DEVICE_IP_ASSIGNMENT_TYPE.STATIC: # We are creating a new link. interface.link_subnet(INTERFACE_LINK_TYPE.STATIC, subnet, ip_address=params.get("ip_address", None))
def create(self, params): """Create the object from params iff admin.""" if not reload_object(self.user).is_superuser: raise HandlerPermissionError() request = HttpRequest() request.user = self.user # Create by using form. form = DHCPSnippetForm(request=request, data=params) if form.is_valid(): try: obj = form.save(ENDPOINT.UI, request) except ValidationError as e: try: raise HandlerValidationError(e.message_dict) except AttributeError: raise HandlerValidationError({"__all__": e.message}) return self.full_dehydrate(obj) else: raise HandlerValidationError(form.errors) # Create by updating the fields on the object. obj = self._meta.object_class() obj = self.full_hydrate(obj, params) obj.save() return self.full_dehydrate(obj)
def revert(self, params): """Revert a value to a previous state.""" if not reload_object(self.user).is_superuser: raise HandlerPermissionError() dhcp_snippet = self.get_object(params) revert_to = params.get('to') if revert_to is None: raise HandlerValidationError('You must specify where to revert to') try: revert_to = int(revert_to) except ValueError: raise HandlerValidationError( "%s is an invalid 'to' value" % revert_to) try: def gc_hook(value): dhcp_snippet.value = value dhcp_snippet.save() dhcp_snippet.value.revert(revert_to, gc_hook=gc_hook) request = HttpRequest() request.user = self.user create_audit_event( EVENT_TYPES.SETTINGS, ENDPOINT.UI, request, None, description=( "DHCP snippet '%s' reverted to revision '%s'" % ( dhcp_snippet.name, revert_to) + " by '%(username)s'.")) except ValueError as e: raise HandlerValidationError(e.args[0])
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)
def get_object(params): # Running inside new database thread, be sure the rbac cache is # cleared so accessing information will not be already cached. rbac.clear() obj = self.get_object(params) if not self.user.has_perm(PodPermission.compose, obj): raise HandlerPermissionError() return obj
def get_object(params): # Clear rbac cache before check (this is in its own thread). rbac.clear() obj = self.get_object(params) if not self.user.has_perm(self._meta.delete_permission, obj): raise HandlerPermissionError() return obj
def clear(self, params=None): if params is None: params = dict() if not self.user.has_perm(NodePermission.admin, Discovery): raise HandlerPermissionError() if len(params) == 0: params["all"] = True Discovery.objects.clear(**params)
def set_script_result_unsuppressed(self, params): """Set unsuppressed for the ScriptResult ids.""" node = self.get_object(params) if not self.user.has_perm(NodePermission.admin, node): raise HandlerPermissionError() script_result_ids = params.get("script_result_ids") ScriptResult.objects.filter(id__in=script_result_ids).update( suppressed=False)
def unlink_subnet(self, params): """Delete the link.""" # Only admin users can perform unlink. if not reload_object(self.user).is_superuser: raise HandlerPermissionError() node = self.get_object(params) interface = Interface.objects.get(node=node, id=params["interface_id"]) interface.unlink_subnet_by_id(params["link_id"])
def _get_domain_or_permission_error(self, params): domain = params.get("domain") if domain is None: raise HandlerValidationError( {"domain": ["This field is required"]}) domain = self.get_object({"id": domain}) if not self.user.has_perm(NodePermission.admin, domain): raise HandlerPermissionError() return domain
def _get_domain_or_permission_error(self, params): domain = params.get('domain') if domain is None: raise HandlerValidationError( {'domain': ['This field is required']}) domain = self.get_object({'id': domain}) if not self.user.has_perm(NODE_PERMISSION.ADMIN, domain): raise HandlerPermissionError() return domain
def delete_interface(self, params): """Delete the interface.""" # Only admin users can perform delete. if not reload_object(self.user).is_superuser: raise HandlerPermissionError() node = self.get_object(params) interface = Interface.objects.get(node=node, id=params["interface_id"]) interface.delete()
def admin_change_password(self, params): """As Admin, update another user's password.""" if not self.user.is_superuser: raise HandlerPermissionError() user = self.get_object(params) form = AdminPasswordChangeForm(user=user, data=get_QueryDict(params)) if form.is_valid(): form.save() else: raise HandlerValidationError(form.errors)
def delete_disk(self, params): # 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') if block_id is not None: block_device = BlockDevice.objects.get(id=block_id, node=node) block_device.delete()
def delete_partition(self, params): # Only admin users can perform delete. if not reload_object(self.user).is_superuser: raise HandlerPermissionError() node = self.get_object(params) partition_id = params.get('partition_id') if partition_id is not None: partition = Partition.objects.get( id=partition_id, partition_table__block_device__node=node) partition.delete()
def create(self, params): """Create a new user, and log an event for it.""" try: result = super().create(params=params) except HandlerDoesNotExistError: raise HandlerPermissionError() self.create_audit_event( EVENT_TYPES.AUTHORISATION, "Created {} '{}'.".format( 'admin' if params['is_superuser'] else 'user', params['username'])) return result
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()
def delete_cache_set(self, params): # Only admin users can perform delete. if not reload_object(self.user).is_superuser: raise HandlerPermissionError() node = self.get_object(params) cache_set_id = params.get('cache_set_id') if cache_set_id is not None: cache_set = CacheSet.objects.get(id=cache_set_id) if cache_set.get_node() != node: raise CacheSet.DoesNotExist() cache_set.delete()
def delete(self, params): """Delete a user, and log an event for it.""" try: user = self.get_object(params, permission=self._meta.delete_permission) self.create_audit_event( EVENT_TYPES.AUTHORISATION, "Deleted {} '{}'.".format( 'admin' if user.is_superuser else 'user', user.username)) result = super().delete(params=params) except HandlerDoesNotExistError: raise HandlerPermissionError() return result
def delete_volume_group(self, params): # Only admin users can perform delete. if not reload_object(self.user).is_superuser: raise HandlerPermissionError() node = self.get_object(params) volume_group_id = params.get('volume_group_id') if volume_group_id is not None: volume_group = VolumeGroup.objects.get(id=volume_group_id) if volume_group.get_node() != node: raise VolumeGroup.DoesNotExist() volume_group.delete()
def update(self, params): """Update a user, and log an event for it.""" try: result = super().update(params=params) except HandlerDoesNotExistError: raise HandlerPermissionError() self.create_audit_event( EVENT_TYPES.AUTHORISATION, ("Updated user profile (username: {username}, " "full name: {last_name}, " "email: {email}, administrator: {is_superuser})").format( **params)) return result
def get_form(obj, params): # Clear rbac cache before check (this is in its own thread). rbac.clear() obj = self.get_object(params) if not self.user.has_perm(self._meta.edit_permission, obj): raise HandlerPermissionError() request = HttpRequest() request.user = self.user return PodForm( instance=obj, data=self.preprocess_form("refresh", params), request=request)
def register_info(self, params): """Return the registration info for a new controller. User must be a superuser to perform this action. """ if not self.user.is_superuser: raise HandlerPermissionError() rpc_shared_secret = Config.objects.get_config("rpc_shared_secret") with RegionConfiguration.open() as config: maas_url = config.maas_url return {"url": maas_url, "secret": rpc_shared_secret}
def delete_by_mac_and_ip(self, params=None): if params is None: params = dict() if not self.user.has_perm(NodePermission.admin, Discovery): raise HandlerPermissionError() ip = params.get("ip", None) if ip is None: raise ValueError("IP address required.") mac = params.get("mac", None) if mac is None: raise ValueError("MAC address required.") delete_result = Discovery.objects.delete_by_mac_and_ip(ip=ip, mac=mac) # Return the count of objects deleted. return delete_result[0]
def update(self, params): """Update the object from params.""" # Only admin users can perform update. if not reload_object(self.user).is_superuser: raise HandlerPermissionError() data = super(NodeHandler, self).update(params) node_obj = Node.objects.get(system_id=data['system_id']) # Update the tags for the node and disks. self.update_tags(node_obj, params['tags']) node_obj.save() return self.full_dehydrate(node_obj)
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()
def create_bond(self, params): """Create bond interface.""" # Only admin users can perform create. if not reload_object(self.user).is_superuser: raise HandlerPermissionError() node = self.get_object(params) form = BondInterfaceForm(node=node, data=params) if form.is_valid(): interface = form.save() self._update_obj_tags(interface, params) self._create_link_on_interface(interface, params) else: raise ValidationError(form.errors)