Exemple #1
0
class ObjectPermission(BaseModel):
    """
    A mapping of view, add, change, and/or delete permission for users and/or groups to an arbitrary set of objects
    identified by ORM query parameters.
    """

    name = models.CharField(max_length=100)
    description = models.CharField(max_length=200, blank=True)
    enabled = models.BooleanField(default=True)
    object_types = models.ManyToManyField(
        to=ContentType,
        limit_choices_to=Q(
            ~Q(app_label__in=[
                "admin",
                "auth",
                "contenttypes",
                "sessions",
                "taggit",
                "users",
            ])
            | Q(app_label="auth", model__in=["group", "user"])
            | Q(app_label="users", model__in=["objectpermission", "token"])),
        related_name="object_permissions",
    )
    groups = models.ManyToManyField(to=Group,
                                    blank=True,
                                    related_name="object_permissions")
    users = models.ManyToManyField(to=settings.AUTH_USER_MODEL,
                                   blank=True,
                                   related_name="object_permissions")
    actions = JSONArrayField(
        base_field=models.CharField(max_length=30),
        help_text="The list of actions granted by this permission",
    )
    constraints = models.JSONField(
        encoder=DjangoJSONEncoder,
        blank=True,
        null=True,
        help_text=
        "Queryset filter matching the applicable objects of the selected type(s)",
    )

    objects = RestrictedQuerySet.as_manager()

    class Meta:
        ordering = ["name"]
        verbose_name = "permission"

    def __str__(self):
        return self.name

    def list_constraints(self):
        """
        Return all constraint sets as a list (even if only a single set is defined).
        """
        if type(self.constraints) is not list:
            return [self.constraints]
        return self.constraints
Exemple #2
0
class Service(PrimaryModel):
    """
    A Service represents a layer-four service (e.g. HTTP or SSH) running on a Device or VirtualMachine. A Service may
    optionally be tied to one or more specific IPAddresses belonging to its parent.
    """

    device = models.ForeignKey(
        to="dcim.Device",
        on_delete=models.CASCADE,
        related_name="services",
        verbose_name="device",
        null=True,
        blank=True,
    )
    virtual_machine = models.ForeignKey(
        to="virtualization.VirtualMachine",
        on_delete=models.CASCADE,
        related_name="services",
        null=True,
        blank=True,
    )
    name = models.CharField(max_length=100)
    protocol = models.CharField(max_length=50, choices=ServiceProtocolChoices)
    ports = JSONArrayField(
        base_field=models.PositiveIntegerField(validators=[
            MinValueValidator(SERVICE_PORT_MIN),
            MaxValueValidator(SERVICE_PORT_MAX),
        ]),
        verbose_name="Port numbers",
    )
    ipaddresses = models.ManyToManyField(
        to="ipam.IPAddress",
        related_name="services",
        blank=True,
        verbose_name="IP addresses",
    )
    description = models.CharField(max_length=200, blank=True)

    csv_headers = [
        "device",
        "virtual_machine",
        "name",
        "protocol",
        "ports",
        "description",
    ]

    class Meta:
        ordering = (
            "protocol",
            "ports",
        )  # (protocol, port) may be non-unique

    def __str__(self):
        return f"{self.name} ({self.get_protocol_display()}/{self.port_list})"

    def get_absolute_url(self):
        return reverse("ipam:service", args=[self.pk])

    @property
    def parent(self):
        return self.device or self.virtual_machine

    def clean(self):
        super().clean()

        # A Service must belong to a Device *or* to a VirtualMachine
        if self.device and self.virtual_machine:
            raise ValidationError(
                "A service cannot be associated with both a device and a virtual machine."
            )
        if not self.device and not self.virtual_machine:
            raise ValidationError(
                "A service must be associated with either a device or a virtual machine."
            )

    def to_csv(self):
        return (
            self.device.name if self.device else None,
            self.virtual_machine.name if self.virtual_machine else None,
            self.name,
            self.get_protocol_display(),
            self.ports,
            self.description,
        )

    @property
    def port_list(self):
        return array_to_string(self.ports)
Exemple #3
0
class RackReservation(PrimaryModel):
    """
    One or more reserved units within a Rack.
    """

    rack = models.ForeignKey(to="dcim.Rack", on_delete=models.CASCADE, related_name="reservations")
    units = JSONArrayField(base_field=models.PositiveSmallIntegerField())
    tenant = models.ForeignKey(
        to="tenancy.Tenant",
        on_delete=models.PROTECT,
        related_name="rackreservations",
        blank=True,
        null=True,
    )
    user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
    description = models.CharField(max_length=200)

    csv_headers = [
        "site",
        "rack_group",
        "rack",
        "units",
        "tenant",
        "user",
        "description",
    ]

    class Meta:
        ordering = ["created"]

    def __str__(self):
        return "Reservation for rack {}".format(self.rack)

    def get_absolute_url(self):
        return reverse("dcim:rackreservation", args=[self.pk])

    def clean(self):
        super().clean()

        if hasattr(self, "rack") and self.units:

            # Validate that all specified units exist in the Rack.
            invalid_units = [u for u in self.units if u not in self.rack.units]
            if invalid_units:
                raise ValidationError(
                    {
                        "units": "Invalid unit(s) for {}U rack: {}".format(
                            self.rack.u_height,
                            ", ".join([str(u) for u in invalid_units]),
                        ),
                    }
                )

            # Check that none of the units has already been reserved for this Rack.
            reserved_units = []
            for resv in self.rack.reservations.exclude(pk=self.pk):
                reserved_units += resv.units
            conflicting_units = [u for u in self.units if u in reserved_units]
            if conflicting_units:
                raise ValidationError(
                    {
                        "units": "The following units have already been reserved: {}".format(
                            ", ".join([str(u) for u in conflicting_units]),
                        )
                    }
                )

    def to_csv(self):
        return (
            self.rack.site.name,
            self.rack.group if self.rack.group else None,
            self.rack.name,
            ",".join([str(u) for u in self.units]),
            self.tenant.name if self.tenant else None,
            self.user.username,
            self.description,
        )

    @property
    def unit_list(self):
        return array_to_string(self.units)