class ImageVersionLicenseSerializer(serializers.HyperlinkedModelSerializer): image_version = ModelRelatedField( queryset=ImageVersion.objects.all(), serializer_class=ImageVersionSummarySerializer, style={'base_template': 'input.html'}, required=False) license = ModelRelatedField( queryset=License.objects.all(), serializer_class=LicenseSummarySerializer, style={'base_template': 'input.html'}, lookup_field='uuid', required=False) url = serializers.HyperlinkedIdentityField( view_name='api:v2:imageversion_license-detail', ) class Meta: model = ImageVersionLicense validators = [ UniqueTogetherValidator( queryset=ImageVersionLicense.objects.all(), fields=('image_version', 'license') ) ] fields = ( 'id', 'url', 'image_version', 'license' )
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 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 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 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 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 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) projects = serializers.PrimaryKeyRelatedField(many=True, read_only=True) snapshot_id = serializers.CharField(write_only=True, allow_blank=True, required=False) image_id = serializers.CharField(write_only=True, allow_blank=True, required=False) 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', 'projects', 'size', 'url', 'snapshot_id', 'image_id', 'start_date', 'end_date') def validate(self, data): image_id = data.get('image') snapshot_id = data.get('snapshot') #: Only allow one at a time if snapshot_id and image_id: raise serializers.ValidationError( "Use either `snapshot_id` or `image_id` not both.") return data def create(self, validated_data): name = validated_data.get('name') size = validated_data.get('size') identifier = validated_data.get("identifier") description = validated_data.get('description') user = validated_data.get("user") start_date = validated_data.get("created_on") instance_source = validated_data.get("instance_source") identity = instance_source.get("created_by_identity") provider = identity.provider source = InstanceSource.objects.create(identifier=identifier, provider=provider, created_by=user, created_by_identity=identity) kwargs = { "name": name, "size": size, "description": description, "instance_source": source, "start_date": start_date } return Volume.objects.create(**kwargs)