class InstanceAllocationSourceSerializer( serializers.HyperlinkedModelSerializer ): allocation_source = ModelRelatedField( queryset=AllocationSource.objects.all(), serializer_class=AllocationSourceSerializer, style={'base_template': 'input.html'} ) instance = ModelRelatedField( queryset=Instance.objects.all(), serializer_class=InstanceSerializer, style={'base_template': 'input.html'} ) url = serializers.HyperlinkedIdentityField( view_name='api:v2:instance-allocation-source-detail', ) class Meta: model = InstanceAllocationSourceSnapshot validators = [ UniqueTogetherValidator( queryset=InstanceAllocationSourceSnapshot.objects.all(), fields=('instance', 'allocation_source') ), ] fields = ('id', 'url', 'instance', 'allocation_source')
class ImageVersionBootScriptSerializer(serializers.HyperlinkedModelSerializer): image_version = ModelRelatedField( queryset=ImageVersion.objects.all(), serializer_class=ImageVersionSummarySerializer, style={'base_template': 'input.html'}, required=False ) boot_script = ModelRelatedField( queryset=BootScript.objects.all(), serializer_class=BootScriptSummarySerializer, style={'base_template': 'input.html'}, lookup_field='uuid', required=False ) url = serializers.HyperlinkedIdentityField( view_name='api:v2:imageversion_bootscript-detail', ) class Meta: model = ImageVersionBootScript validators = [ UniqueTogetherValidator( queryset=ImageVersionBootScript.objects.all(), fields=('image_version', 'boot_script') ) ] fields = ('id', 'url', 'image_version', 'boot_script')
class ResourceRequest_UpdateQuotaSerializer(serializers.Serializer): quota = ModelRelatedField(queryset=Quota.objects.all(), serializer_class=QuotaSummarySerializer, style={'base_template': 'input.html'}) identity = ModelRelatedField(lookup_field='uuid', queryset=Identity.objects.all(), serializer_class=IdentitySummarySerializer, style={'base_template': 'input.html'}) resource_request = serializers.PrimaryKeyRelatedField( queryset=ResourceRequest.objects.all()) approved_by = ModelRelatedField(lookup_field='username', queryset=AtmosphereUser.objects.all(), serializer_class=UserSummarySerializer, style={'base_template': 'input.html'}) def create(self, validated_data): """ - Convert serializer into data for event_serializer - Save event_serializer - return serialized data """ quota = validated_data.get('quota') user = validated_data.get('approved_by') resource_request = validated_data.get('resource_request') identity = validated_data.get('identity') # THIS IS A HACK -- REMOVE IT WHEN https://github.com/cyverse/atmosphere/pull/541 is merged # Hack explained: This api is designed to update a single identity's quota, instead we # update all identities for the user. This syncs the quota across all of # the user's active identities. identity_user = identity.created_by for ident in [ i for i in identity_user.identity_set.all() if i.is_active() ]: data = { 'identity': ident.id, 'resource_request': resource_request.id, 'approved_by': user.username, 'quota': quota.id } event_serializer = QuotaAssignedByResourceRequestSerializer( data=data) event_serializer.is_valid(raise_exception=True) event_serializer.save() return { 'identity': identity, 'resource_request': resource_request, 'approved_by': user, 'quota': quota }
class ImageSerializer(serializers.HyperlinkedModelSerializer): created_by = UserSummarySerializer(read_only=True) access_list = ModelRelatedField( many=True, queryset=filter_current_user_queryset, serializer_class=PatternMatchSummarySerializer, style={'base_template': 'input.html'}) tags = TagRelatedField(many=True) versions = ImageVersionRelatedField(many=True) icon = serializers.CharField(source="get_icon_url", read_only=True) is_public = SwapBooleanField(source='private') url = UUIDHyperlinkedIdentityField(view_name='api:v2:application-detail', ) metrics_url = UUIDHyperlinkedIdentityField( view_name='api:v2:applicationmetric-detail', ) class Meta: model = Image fields = ( 'id', 'url', 'uuid', 'name', # Adtl. Fields 'metrics_url', 'created_by', 'description', 'end_date', 'is_public', 'icon', 'start_date', 'access_list', 'tags', 'versions')
class QuotaAssignedByResourceRequestSerializer(QuotaAssignedSerializer): resource_request = serializers.PrimaryKeyRelatedField( queryset=ResourceRequest.objects.all()) approved_by = ModelRelatedField(lookup_field='username', queryset=AtmosphereUser.objects.all(), serializer_class=AtmosphereUserSerializer, style={'base_template': 'input.html'}) def save(self): serialized_data = self.validated_data return_data = self.data entity_id = serialized_data['identity'].created_by.username event_payload = { 'update_method': 'resource_request', 'resource_request': return_data['resource_request'], 'approved_by': serialized_data['approved_by'].username, 'quota': return_data['quota'], 'identity': return_data['identity']['uuid'], 'timestamp': return_data['timestamp'] } event = EventTable.create_event(name="quota_assigned", entity_id=entity_id, payload=event_payload) return event
class InstanceStatusHistorySerializer(serializers.HyperlinkedModelSerializer): instance = ModelRelatedField( queryset=Instance.objects.all(), serializer_class=InstanceSuperSummarySerializer, style={'base_template': 'input.html'}) size = SizeRelatedField(queryset=Size.objects.none()) provider = ProviderSummarySerializer(source='instance.get_provider') image = ImageSummarySerializer( source='instance.provider_machine.application_version.application') status = serializers.SlugRelatedField(slug_field='name', read_only=True) activity = serializers.CharField(max_length=36, allow_blank=True) url = UUIDHyperlinkedIdentityField( view_name='api:v2:instancestatushistory-detail', ) class Meta: model = InstanceStatusHistory fields = ( 'id', 'uuid', 'url', 'instance', 'status', 'activity', 'size', 'provider', 'image', 'extra', 'start_date', 'end_date', )
class LicenseSerializer(serializers.HyperlinkedModelSerializer): text = serializers.CharField(source='license_text') type = ModelRelatedField(lookup_field='name', source='license_type', queryset=LicenseType.objects.all(), serializer_class=LicenseTypeSummarySerializer, style={'base_template': 'input.html'}) url = UUIDHyperlinkedIdentityField(view_name='api:v2:license-detail', ) created_by = serializers.SlugRelatedField( slug_field='username', queryset=AtmosphereUser.objects.all(), required=False) def is_valid(self, raise_exception=False): """ """ raw_type = self.initial_data.get("type", "").lower() if 'raw text' in raw_type: LicenseType.objects.get_or_create(name="Raw Text") elif 'url' in raw_type: LicenseType.objects.get_or_create(name="URL") return super(LicenseSerializer, self).is_valid(raise_exception=raise_exception) def create(self, validated_data): if 'created_by' not in validated_data: request = self.context.get('request') if request and request.user: validated_data['created_by'] = request.user return super(LicenseSerializer, self).create(validated_data) class Meta: model = License fields = ('id', 'url', 'uuid', 'created_by', 'title', 'text', 'type')
class IdentitySerializer(serializers.HyperlinkedModelSerializer): quota = ModelRelatedField(queryset=Quota.objects.all(), serializer_class=QuotaSummarySerializer, lookup_field='id') usage = serializers.SerializerMethodField() credentials = CredentialSummarySerializer(many=True, source='credential_set') key = serializers.SerializerMethodField() is_leader = serializers.SerializerMethodField() user = UserSummarySerializer(source='created_by') members = GroupSummarySerializer(source='get_membership', many=True, read_only=True) provider = ProviderSummarySerializer() url = UUIDHyperlinkedIdentityField(view_name='api:v2:identity-detail', ) def update(self, core_identity, validated_data): quota = validated_data.get('quota') data = {'quota': quota.id, 'identity': core_identity.id} event_serializer = QuotaAssignedSerializer(data=data) if not event_serializer.is_valid(): raise serializers.ValidationError( "Validation of EventSerializer failed with: %s" % event_serializer.errors) try: event_serializer.save() except Exception as exc: logger.exception("Unexpected error occurred during Event save") raise serializers.ValidationError( "Unexpected error occurred during Event save: %s" % exc) # Synchronous call to EventTable -> Set Quota for Identity's CloudProvider -> Save the Quota to Identity identity = Identity.objects.get(uuid=core_identity.uuid) return identity def get_usage(self, identity): return -1 def get_is_leader(self, identity): """ Returns true/false if the user requesting the object is the leader. """ user = None if self.context: if 'request' in self.context: user = self.context['request'].user elif 'user' in self.context: user = self.context['user'] if user == identity.created_by: return True return Identity.shared_with_user( user, is_leader=True).filter(id=identity.id).exists() def get_key(self, identity): return identity.get_key() class Meta: model = Identity fields = ('id', 'uuid', 'url', 'key', 'quota', 'credentials', 'usage', 'is_leader', 'provider', 'members', 'user')
class ProjectExternalLinkSerializer(serializers.HyperlinkedModelSerializer): project = ModelRelatedField(queryset=Project.objects.all(), serializer_class=ProjectSummarySerializer, style={'base_template': 'input.html'}) external_link = ModelRelatedField( queryset=ExternalLink.objects.all(), serializer_class=ExternalLinkSummarySerializer, style={'base_template': 'input.html'}, source='externallink') url = serializers.HyperlinkedIdentityField( view_name='api:v2:projectlinks-detail', ) class Meta: model = ProjectExternalLink validators = [ UniqueTogetherValidator(queryset=ProjectExternalLink.objects.all(), fields=('project', 'externallink')), ] fields = ('id', 'url', 'project', 'external_link')
class UserAllocationSourceSerializer(serializers.HyperlinkedModelSerializer): allocation_source = ModelRelatedField( queryset=AllocationSource.objects.all(), serializer_class=AllocationSourceSerializer, style={'base_template': 'input.html'}) user = ModelRelatedField(queryset=AtmosphereUser.objects.all(), serializer_class=UserSerializer, style={'base_template': 'input.html'}) url = serializers.HyperlinkedIdentityField( view_name='api:v2:user-allocation-source-detail', ) class Meta: model = UserAllocationSource validators = [ UniqueTogetherValidator( queryset=UserAllocationSource.objects.all(), fields=('user', 'allocation_source')), ] fields = ('id', 'url', 'user', 'allocation_source')
class ResourceRequest_UpdateQuotaSerializer(serializers.Serializer): quota = ModelRelatedField(queryset=Quota.objects.all(), serializer_class=QuotaSummarySerializer, style={'base_template': 'input.html'}) identity = ModelRelatedField(lookup_field='uuid', queryset=Identity.objects.all(), serializer_class=IdentitySummarySerializer, style={'base_template': 'input.html'}) resource_request = serializers.PrimaryKeyRelatedField( queryset=ResourceRequest.objects.all()) approved_by = ModelRelatedField(lookup_field='username', queryset=AtmosphereUser.objects.all(), serializer_class=UserSummarySerializer, style={'base_template': 'input.html'}) def create(self, validated_data): """ - Convert serializer into data for event_serializer - Save event_serializer - return serialized data """ quota = validated_data.get('quota') user = validated_data.get('approved_by') resource_request = validated_data.get('resource_request') identity = validated_data.get('identity') data = { 'identity': identity.id, 'resource_request': resource_request.id, 'approved_by': user.username, 'quota': quota.id } event_serializer = QuotaAssignedByResourceRequestSerializer(data=data) event_serializer.is_valid(raise_exception=True) # Synchronous call to EventTable -> Set Quota for Identity's CloudProvider -> Save the Quota to Identity event_serializer.save() return { 'identity': identity, 'resource_request': resource_request, 'approved_by': user, 'quota': quota }
class ProjectApplicationSerializer(serializers.HyperlinkedModelSerializer): project = ModelRelatedField(queryset=Project.objects.all(), serializer_class=ProjectSummarySerializer, style={'base_template': 'input.html'}) image = ModelRelatedField(queryset=Application.objects.all(), serializer_class=ImageSummarySerializer, style={'base_template': 'input.html'}, source='application') url = serializers.HyperlinkedIdentityField( view_name='api:v2:projectapplication-detail', ) class Meta: model = ProjectApplication validators = [ # TODO: Fix that 'application' leaks into real-world here. UniqueTogetherValidator(queryset=ProjectApplication.objects.all(), fields=('project', 'application')), ] fields = ('id', 'url', 'project', 'image')
class VolumeSerializer(serializers.HyperlinkedModelSerializer): description = serializers.CharField(required=False, allow_blank=True) identity = ModelRelatedField(source="instance_source.created_by_identity", lookup_field="uuid", queryset=Identity.objects.all(), serializer_class=IdentitySummarySerializer, style={'base_template': 'input.html'}) provider = ModelRelatedField(source="instance_source.provider", queryset=Provider.objects.all(), serializer_class=ProviderSummarySerializer, style={'base_template': 'input.html'}, required=False) user = UserSummarySerializer(source='instance_source.created_by', read_only=True) project = ModelRelatedField(queryset=Project.objects.all(), serializer_class=ProjectSummarySerializer, style={'base_template': 'input.html'}) uuid = serializers.CharField(source='instance_source.identifier', read_only=True) # NOTE: this is still using ID instead of UUID -- due to abstract classes # and use of getattr in L271 of rest_framework/relations.py, this is a # 'kink' that has not been worked out yet. url = InstanceSourceHyperlinkedIdentityField( view_name='api:v2:volume-detail', ) class Meta: model = Volume read_only_fields = ("user", "uuid", "start_date", "end_date") fields = ('id', 'uuid', 'name', 'description', 'identity', 'user', 'provider', 'project', 'size', 'url', 'start_date', 'end_date') def validate(self, data): if not data and not self.initial_data: return data raise Exception("This serializer for GET output ONLY! -- " "Use the POST or UPDATE serializers instead!")
class UpdateVolumeSerializer(serializers.ModelSerializer): name = serializers.CharField(required=False) description = serializers.CharField(required=False) project = ModelRelatedField(queryset=Project.objects.all(), serializer_class=ProjectSummarySerializer, style={'base_template': 'input.html'}) class Meta: model = Volume view_name = 'api:v2:volume-detail' fields = ('name', 'description', 'project')
class ImageAccessListSerializer(serializers.HyperlinkedModelSerializer): image = ImageRelatedField(source='application', queryset=Image.objects.none()) match = ModelRelatedField(source='patternmatch', queryset=filter_current_user_queryset, serializer_class=PatternMatchSummarySerializer, style={'base_template': 'input.html'}) url = serializers.HyperlinkedIdentityField( view_name='api:v2:applicationaccesslist-detail', ) class Meta: model = ApplicationPatternMatch fields = ('id', 'url', 'image', 'match')
class QuotaAssignedSerializer(EventSerializer): quota = ModelRelatedField(queryset=Quota.objects.all(), serializer_class=QuotaSerializer, style={'base_template': 'input.html'}) identity = ModelRelatedField(queryset=Identity.objects.all(), serializer_class=IdentitySerializer, style={'base_template': 'input.html'}) update_method = serializers.CharField(default="API") timestamp = serializers.DateTimeField(default=timezone.now) def validate_update_method(self, value): value = value.lower() if value == 'api': return "API" elif value == 'admin': return "Admin" else: raise serializers.ValidationError( "Invalid update_method (%s). Accepted values: API, Admin" % value) return value def save(self): # Properly structure the event data as a payload serialized_data = self.validated_data return_data = self.data entity_id = serialized_data['identity'].created_by.username event_payload = { 'update_method': return_data['update_method'], 'quota': return_data['quota'], 'identity': return_data['identity']['uuid'], 'timestamp': return_data['timestamp'] } # Create the event in EventTable event = EventTable.create_event(name="quota_assigned", entity_id=entity_id, payload=event_payload) return event
class ImageVersionMembershipSerializer(serializers.HyperlinkedModelSerializer): image_version = ModelRelatedField( queryset=ImageVersion.objects.all(), serializer_class=ImageVersionSummarySerializer, style={'base_template': 'input.html'}, required=False) #NOTE: When complete, return here to disambiguate between 'membership'&&'group' group = ModelRelatedField(queryset=Membership.objects.all(), serializer_class=GroupSummarySerializer, style={'base_template': 'input.html'}, lookup_field='uuid', required=False) url = serializers.HyperlinkedIdentityField( view_name='api:v2:imageversion_membership-detail', ) class Meta: model = ImageVersionMembership validators = [ UniqueTogetherValidator( queryset=ImageVersionMembership.objects.all(), fields=('image_version', 'group')) ] fields = ('id', 'url', 'image_version', 'group')
class PatternMatchSerializer(serializers.HyperlinkedModelSerializer): type = serializers.SlugRelatedField(queryset=MatchType.objects.all(), slug_field='name') created_by = ModelRelatedField(lookup_field="username", default=serializers.CurrentUserDefault(), queryset=AtmosphereUser.objects.all(), serializer_class=UserSummarySerializer, style={'base_template': 'input.html'}) url = serializers.HyperlinkedIdentityField( view_name='api:v2:patternmatch-detail', ) class Meta: model = PatternMatch fields = ('id', 'url', 'pattern', 'type', 'created_by', 'allow_access')
class ResourceRequestSerializer(serializers.HyperlinkedModelSerializer): uuid = serializers.CharField(read_only=True) url = UUIDHyperlinkedIdentityField( view_name='api:v2:resourcerequest-detail', ) created_by = UserSummarySerializer(read_only=True) status = ModelRelatedField( default=lambda: get_status_type(status="pending"), serializer_class=StatusTypeSummarySerializer, queryset=StatusType.objects.all(), lookup_field='id') class Meta: model = ResourceRequest fields = ('id', 'uuid', 'url', 'request', 'description', 'status', 'created_by', 'admin_message', 'start_date')
class MaintenanceRecordSerializer(serializers.HyperlinkedModelSerializer): provider = ModelRelatedField(lookup_field='name', queryset=Provider.objects.all(), serializer_class=ProviderSummarySerializer, style={'base_template': 'input.html'}, required=False, allow_null=True) url = serializers.HyperlinkedIdentityField( view_name='api:v2:maintenancerecord-detail', read_only=True, ) class Meta: model = MaintenanceRecord fields = ('id', 'url', 'start_date', 'end_date', 'title', 'message', 'provider', 'disable_login')
class ImageVersionSerializer(serializers.HyperlinkedModelSerializer): """ Serializer for ApplicationVersion (aka 'image_version') """ # NOTE: Implicitly included via 'fields' # id, application parent = ImageVersionSummarySerializer() # name, change_log, allow_imaging licenses = ModelRelatedField( many=True, queryset=License.objects.all(), serializer_class=LicenseSummarySerializer, style={'base_template': 'input.html'} ) scripts = ModelRelatedField( source='boot_scripts', many=True, queryset=BootScript.objects.all(), serializer_class=BootScriptSummarySerializer, style={'base_template': 'input.html'} ) membership = serializers.SlugRelatedField( slug_field='name', read_only=True, many=True ) user = UserSummarySerializer(source='created_by') identity = IdentitySummarySerializer(source='created_by_identity') machines = serializers.SerializerMethodField('get_machines_for_user') image = ModelRelatedField( source='application', queryset=Image.objects.all(), serializer_class=ImageSummarySerializer, style={'base_template': 'input.html'} ) start_date = serializers.DateTimeField() min_mem = serializers.IntegerField(source='threshold.memory_min') min_cpu = serializers.IntegerField(source='threshold.cpu_min') end_date = serializers.DateTimeField(allow_null=True) url = UUIDHyperlinkedIdentityField( view_name='api:v2:imageversion-detail', uuid_field='id' ) def get_machines_for_user(self, obj): """ Only show version as available on providers the user has access to """ user = self.context['request'].user filtered = obj.machines.filter( Q(instance_source__provider__active=True) ) if isinstance(user, AnonymousUser): filtered = filtered.filter( Q(instance_source__provider__public=True) ) elif not user.is_staff: filtered = filtered.filter( Q(instance_source__provider_id__in=user.provider_ids()) ) serializer = ProviderMachineSummarySerializer( filtered, context=self.context, many=True ) return serializer.data class Meta: model = ImageVersion fields = ( 'id', 'url', 'parent', 'name', 'change_log', 'image', 'machines', 'allow_imaging', 'doc_object_id', 'licenses', 'membership', 'min_mem', 'min_cpu', 'scripts', 'user', 'identity', 'start_date', 'end_date' ) def update(self, instance, validated_data): if 'min_cpu' in self.initial_data or 'min_mem' in self.initial_data: self.update_threshold(instance, validated_data) return super(ImageVersionSerializer, self).update(instance, validated_data) def validate_min_cpu(self, value): if value < 0 or value > 16: raise serializers.ValidationError( "Value of CPU must be between 1 & 16" ) return value def validate_min_mem(self, value): if value < 0 or value > 32 * 1024: raise serializers.ValidationError( "Value of mem must be between 1 & 32 GB" ) return value def update_threshold(self, instance, validated_data): current_threshold = instance.get_threshold() try: current_mem_min = current_threshold.memory_min except: current_mem_min = 0 try: current_cpu_min = current_threshold.cpu_min except: current_cpu_min = 0 try: new_mem_min = validated_data.get('threshold')['memory_min'] except: new_mem_min = current_mem_min try: new_cpu_min = validated_data.get('threshold')['cpu_min'] except: new_cpu_min = current_cpu_min if not current_threshold: new_threshold = ApplicationThreshold.objects.create( application_version=instance, memory_min=new_mem_min, cpu_min=new_cpu_min ) else: new_threshold = ApplicationThreshold.objects.get( application_version=instance ) new_threshold.memory_min = new_mem_min new_threshold.cpu_min = new_cpu_min new_threshold.save() validated_data['threshold'] = new_threshold
class GroupSerializer(serializers.HyperlinkedModelSerializer): url = UUIDHyperlinkedIdentityField(view_name='api:v2:group-detail', ) users = ModelRelatedField(queryset=AtmosphereUser.objects.all(), serializer_class=UserSummarySerializer, source='get_users', style={'base_template': 'input.html'}, many=True, lookup_field='username') leaders = ModelRelatedField(queryset=AtmosphereUser.objects.all(), serializer_class=UserSummarySerializer, source='get_leaders', lookup_field='username', style={'base_template': 'input.html'}, many=True, required=False) def add_identity_memberships(self, group): for member in group.memberships.all(): user = member.user [ IdentityMembership.objects.get_or_create(identity=ident, member=group) for ident in user.identity_set.all() ] return def update_group_membership(self, group, users, leaders): for user in users: GroupMembership.objects.create(group=group, user=user) group.user_set.add(user) for user in leaders: GroupMembership.objects.create(group=group, user=user, is_leader=True) group.user_set.add(user) return def _get_request_user(self, raise_exception=True): if 'request' in self.context: return self.context['request'].user elif 'user' in self.context: return self.context['user'] elif raise_exception: raise serializers.ValidationError( "Expected 'request' or 'user' to be passed in via context for this serializer" ) return None def update(self, group, validated_data): user = self._get_request_user(True) if not user.is_staff and not group.leaders.filter(user=user).exists(): raise serializers.ValidationError( "User %s is not a project leader" % user.username) cleaned_data = {} # Leaders are 'flagged' and users are not. if 'get_users' in validated_data and 'get_leaders' in validated_data: leaders = validated_data.get('get_leaders', []) users = [ u for u in validated_data.get('get_users', []) if u not in leaders ] # TODO: Efficient update? users and leaders might be added/removed.. group.user_set.remove() group.memberships.all().delete() self.update_group_membership(group, users, leaders) elif 'get_users' in validated_data or 'get_leaders' in validated_data: raise serializers.ValidationError( "To update the membership, pass _both_ 'users' and 'leaders'") group.identity_memberships.all().delete() self.add_identity_memberships(group) return super(GroupSerializer, self).update(group, cleaned_data) def create(self, validated_data): user = self._get_request_user(True) if not user.is_staff: raise serializers.ValidationError( "Only staff users can create groups.") group_kwargs = validated_data.copy() # Leaders are 'flagged' and users are not. leaders = group_kwargs.pop('get_leaders') users = [u for u in group_kwargs.pop('get_users') if u not in leaders] new_group = Group.objects.create(**group_kwargs) self.update_group_membership(new_group, users, leaders) self.add_identity_memberships(new_group) return new_group class Meta: model = Group fields = ( 'id', 'uuid', 'url', 'name', 'users', 'leaders', )
class InstanceSerializer(serializers.HyperlinkedModelSerializer): identity = IdentitySummarySerializer(source='created_by_identity') user = UserSummarySerializer(source='created_by') provider = ProviderSummarySerializer(source='created_by_identity.provider') status = serializers.CharField(source='api_status', read_only=True) activity = serializers.CharField(source='api_activity', read_only=True) project = ModelRelatedField(queryset=Project.objects.all(), serializer_class=ProjectSummarySerializer, style={'base_template': 'input.html'}) scripts = ModelRelatedField(many=True, required=False, queryset=BootScript.objects.all(), serializer_class=BootScriptSummarySerializer, style={'base_template': 'input.html'}) size = serializers.SerializerMethodField() image = serializers.SerializerMethodField() ip_address = serializers.SerializerMethodField() usage = serializers.SerializerMethodField() version = serializers.SerializerMethodField() allocation_source = serializers.SerializerMethodField() uuid = serializers.CharField(source='provider_alias') url = UUIDHyperlinkedIdentityField(view_name='api:v2:instance-detail', lookup_field='uuid', uuid_field='provider_alias') def get_allocation_source(self, instance): snapshot = InstanceAllocationSourceSnapshot.objects.filter( instance=instance).first() if not snapshot: return None serializer = AllocationSourceSerializer(snapshot.allocation_source, context=self.context) return serializer.data def get_usage(self, instance): if not instance.allocation_source\ or not instance.allocation_source.snapshot: return -1 return instance.allocation_source.snapshot.compute_used def get_size(self, obj): size = obj.get_size() serializer = SizeSummarySerializer(size, context=self.context) return serializer.data def get_image(self, obj): if not obj.source.is_machine(): return {} image_uuid = obj.application_uuid() image = Image.objects.get(uuid=image_uuid) serializer = ImageSuperSummarySerializer(image, context=self.context) return serializer.data def get_ip_address(self, obj): status = obj.esh_status() if status in ["suspended", "shutoff", "shelved"]: return "0.0.0.0" return obj.ip_address def get_version(self, obj): if not obj.source.is_machine(): return {} version = obj.source.providermachine.application_version serializer = ImageVersionSummarySerializer(version, context=self.context) return serializer.data class Meta: model = Instance fields = ( 'id', 'uuid', 'url', 'name', 'status', 'activity', 'size', 'ip_address', 'shell', 'vnc', 'web_desktop', 'identity', 'user', 'provider', 'image', 'version', # NOTE:Should replace image? 'usage', 'scripts', 'project', 'start_date', 'end_date', 'allocation_source', )
class ProjectSerializer(serializers.HyperlinkedModelSerializer): images = ImageSummarySerializer( source='applications', many=True, read_only=True ) instances = InstanceSummarySerializer( source='active_instances', many=True, read_only=True ) links = ExternalLinkSummarySerializer(many=True, read_only=True) volumes = VolumeSummarySerializer( source='active_volumes', many=True, read_only=True ) # note: both of these requests become a single DB query, but I'm choosing # the owner.name route so the API doesn't break when we start adding users # to groups owner = UserSerializer(source='owner.user_set.first') created_by = ModelRelatedField( lookup_field="username", default=serializers.CurrentUserDefault(), queryset=AtmosphereUser.objects.all(), serializer_class=UserSummarySerializer, style={'base_template': 'input.html'} ) owner = ModelRelatedField( lookup_field="name", queryset=Group.objects.all(), serializer_class=GroupSummarySerializer, style={'base_template': 'input.html'} ) url = UUIDHyperlinkedIdentityField(view_name='api:v2:project-detail', ) users = UserSummarySerializer(source='get_users', many=True, read_only=True) leaders = UserSummarySerializer( source='get_leaders', many=True, read_only=True ) def update(self, instance, validated_data): """ Check that project does not have shared resources. If so, do not allow owner changes. """ new_owner = validated_data.get('owner') current_owner = instance.owner if new_owner and current_owner != new_owner: self.validate_ownership(instance, current_owner) return super(ProjectSerializer, self).update(instance, validated_data) def validate_ownership(self, project, current_owner): if project.has_shared_resources(): raise ValidationError( "Cannot update ownership for a project when it contains " "shared cloud resources. To update project ownership, " "all shared cloud resources must be " "moved to another project or deleted" ) request = self.context.get('request') if not request: return True request_user = request.user if request_user not in project.get_leaders(): raise ValidationError( "This project has been shared with you. " "To change a projects ownership, " "you must be the project owner." ) return True class Meta: model = Project fields = ( 'id', 'uuid', 'url', 'name', 'description', 'created_by', 'owner', 'users', 'leaders', 'instances', 'images', 'links', 'volumes', 'start_date', 'end_date' )
class MachineRequestSerializer(serializers.HyperlinkedModelSerializer): uuid = serializers.CharField(read_only=True) identity = IdentityRelatedField(source='membership.identity') # This is a *STAFF EXCLUSIVE* serializer. These are the values that make it that way: admin_message = serializers.CharField(read_only=True) parent_machine = ModelRelatedField( required=False, lookup_field="uuid", queryset=ProviderMachine.objects.all(), serializer_class=ProviderMachineSummarySerializer, style={'base_template': 'input.html'}) instance = ModelRelatedField(queryset=Instance.objects.all(), serializer_class=InstanceSummarySerializer, style={'base_template': 'input.html'}) status = StatusTypeRelatedField(allow_null=True, required=False) old_status = serializers.CharField(required=False) new_application_visibility = serializers.CharField() new_application_version = ImageVersionSummarySerializer(read_only=True) new_application_name = serializers.CharField( validators=[NoSpecialCharacters('!"#$%&\'*+,/;<=>?@[\\]^_`{|}~')]) new_application_description = serializers.CharField() access_list = serializers.CharField(allow_blank=True) system_files = serializers.CharField(allow_blank=True, required=False) installed_software = serializers.CharField() exclude_files = serializers.CharField(allow_blank=True) new_version_name = serializers.CharField() new_version_change_log = serializers.CharField(required=False, allow_blank=True) new_version_tags = serializers.CharField(required=False, allow_blank=True) new_version_memory_min = serializers.CharField() new_version_cpu_min = serializers.CharField() new_version_allow_imaging = serializers.BooleanField() new_version_forked = serializers.BooleanField() new_version_licenses = ModelRelatedField( many=True, queryset=License.objects.all(), serializer_class=LicenseSummarySerializer, style={'base_template': 'input.html'}, required=False) new_version_scripts = ModelRelatedField( many=True, queryset=BootScript.objects.all(), serializer_class=BootScriptSummarySerializer, style={'base_template': 'input.html'}, required=False) new_application_access_list = ModelRelatedField( many=True, queryset=PatternMatch.objects.all(), serializer_class=PatternMatchSummarySerializer, style={'base_template': 'input.html'}, required=False) new_version_membership = ModelRelatedField( many=True, queryset=Group.objects.all(), serializer_class=GroupSummarySerializer, style={'base_template': 'input.html'}, required=False) new_machine_provider = ModelRelatedField( queryset=Provider.objects.all(), serializer_class=ProviderSummarySerializer, style={'base_template': 'input.html'}) new_machine_owner = ModelRelatedField( queryset=User.objects.all(), serializer_class=UserSummarySerializer, style={'base_template': 'input.html'}) start_date = serializers.DateTimeField(read_only=True) end_date = serializers.DateTimeField(read_only=True) new_machine = ModelRelatedField( required=False, queryset=ProviderMachine.objects.all(), serializer_class=ProviderMachineSummarySerializer, style={'base_template': 'input.html'}) url = UUIDHyperlinkedIdentityField( view_name='api:v2:machinerequest-detail', ) class Meta: model = MachineRequest fields = ('id', 'uuid', 'url', 'instance', 'identity', 'status', 'old_status', 'parent_machine', 'admin_message', 'new_application_name', 'new_application_description', 'new_application_visibility', 'new_application_access_list', 'access_list', 'system_files', 'installed_software', 'exclude_files', 'new_version_name', 'new_version_change_log', 'new_version_tags', 'new_version_memory_min', 'new_version_cpu_min', 'new_version_allow_imaging', 'new_version_forked', 'new_version_licenses', 'new_version_scripts', 'new_version_membership', 'new_machine_provider', 'new_machine_owner', 'start_date', 'end_date', 'new_machine', 'new_application_version')
class UserMachineRequestSerializer(serializers.HyperlinkedModelSerializer): uuid = serializers.CharField(read_only=True) admin_message = serializers.CharField(read_only=True) instance = ModelRelatedField(queryset=Instance.objects.all(), serializer_class=InstanceSummarySerializer, style={'base_template': 'input.html'}) start_date = serializers.DateTimeField(read_only=True) end_date = serializers.DateTimeField(read_only=True) status = StatusTypeRelatedField(allow_null=True, required=False) old_status = serializers.CharField(source='clean_old_status', required=False) new_application_visibility = serializers.CharField() new_application_version = ImageVersionSummarySerializer(read_only=True) new_application_name = serializers.CharField( validators=[NoSpecialCharacters('!"#$%&\'*+,/;<=>?@[\\]^`{|}~')]) new_application_description = serializers.CharField() new_application_access_list = ModelRelatedField( many=True, queryset=PatternMatch.objects.all(), serializer_class=PatternMatchSummarySerializer, style={'base_template': 'input.html'}, required=False) access_list = serializers.CharField(allow_blank=True) system_files = serializers.CharField(allow_blank=True, required=False) installed_software = serializers.CharField() exclude_files = serializers.CharField(allow_blank=True) new_version_name = serializers.CharField() new_version_change_log = serializers.CharField(required=False, allow_blank=True) new_version_tags = serializers.CharField(required=False, allow_blank=True) new_version_memory_min = serializers.CharField() new_version_cpu_min = serializers.CharField() new_version_allow_imaging = serializers.BooleanField() new_version_forked = serializers.BooleanField() new_version_licenses = ModelRelatedField( many=True, queryset=License.objects.all(), serializer_class=LicenseSummarySerializer, style={'base_template': 'input.html'}, required=False) new_version_scripts = ModelRelatedField( many=True, queryset=BootScript.objects.all(), serializer_class=BootScriptSummarySerializer, style={'base_template': 'input.html'}, required=False) new_version_membership = ModelRelatedField( many=True, queryset=Group.objects.all(), serializer_class=GroupSummarySerializer, style={'base_template': 'input.html'}, required=False) new_machine_provider = ModelRelatedField( queryset=Provider.objects.all(), serializer_class=ProviderSummarySerializer, style={'base_template': 'input.html'}, required=False) new_machine = ModelRelatedField( required=False, queryset=ProviderMachine.objects.all(), serializer_class=ProviderMachineSummarySerializer, style={'base_template': 'input.html'}) # Absent: new_machine_owner -- determined by User submission url = UUIDHyperlinkedIdentityField( view_name='api:v2:machinerequest-detail', ) #FIXME: tags are missing here. # version change log is missing # class Meta: model = MachineRequest fields = ( 'id', 'uuid', 'url', 'start_date', 'end_date', 'admin_message', 'instance', 'status', 'old_status', 'new_application_visibility', 'new_application_name', 'new_application_access_list', 'new_application_description', 'access_list', 'system_files', 'installed_software', 'exclude_files', 'new_version_name', 'new_version_change_log', 'new_version_tags', 'new_version_memory_min', 'new_version_cpu_min', 'new_version_allow_imaging', 'new_version_forked', 'new_version_licenses', 'new_version_scripts', 'new_version_membership', 'new_machine_provider', 'new_application_version', 'new_machine', )