Example #1
0
class Region(MPTTModel, OrganizationalModel):
    """
    Sites can be grouped within geographic Regions.
    """

    parent = TreeForeignKey(
        to="self",
        on_delete=models.CASCADE,
        related_name="children",
        blank=True,
        null=True,
        db_index=True,
    )
    name = models.CharField(max_length=100, unique=True)
    slug = AutoSlugField(populate_from="name")
    description = models.CharField(max_length=200, blank=True)

    objects = TreeManager()

    csv_headers = ["name", "slug", "parent", "description"]

    class MPTTMeta:
        order_insertion_by = ["name"]

    def __str__(self):
        return self.name

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

    def to_csv(self):
        return (
            self.name,
            self.slug,
            self.parent.name if self.parent else None,
            self.description,
        )

    def get_site_count(self):
        return Site.objects.filter(
            Q(region=self) | Q(region__in=self.get_descendants())).count()

    def to_objectchange(self, action):
        # Remove MPTT-internal fields
        return ObjectChange(
            changed_object=self,
            object_repr=str(self),
            action=action,
            object_data=serialize_object(
                self, exclude=["level", "lft", "rght", "tree_id"]),
        )
Example #2
0
class TenantGroup(MPTTModel, OrganizationalModel):
    """
    An arbitrary collection of Tenants.
    """

    name = models.CharField(max_length=100, unique=True)
    slug = AutoSlugField(populate_from="name")
    parent = TreeForeignKey(
        to="self",
        on_delete=models.CASCADE,
        related_name="children",
        blank=True,
        null=True,
        db_index=True,
    )
    description = models.CharField(max_length=200, blank=True)

    objects = TreeManager()

    csv_headers = ["name", "slug", "parent", "description"]

    class Meta:
        ordering = ["name"]

    class MPTTMeta:
        order_insertion_by = ["name"]

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("tenancy:tenantgroup", args=[self.slug])

    def to_csv(self):
        return (
            self.name,
            self.slug,
            self.parent.name if self.parent else "",
            self.description,
        )

    def to_objectchange(self, action):
        # Remove MPTT-internal fields
        return ObjectChange(
            changed_object=self,
            object_repr=str(self),
            action=action,
            object_data=serialize_object(
                self, exclude=["level", "lft", "rght", "tree_id"]),
        )
Example #3
0
class RackGroup(MPTTModel, OrganizationalModel):
    """
    Racks can be grouped as subsets within a Site. The scope of a group will depend on how Sites are defined. For
    example, if a Site spans a corporate campus, a RackGroup might be defined to represent each building within that
    campus. If a Site instead represents a single building, a RackGroup might represent a single room or floor.
    """

    name = models.CharField(max_length=100)
    slug = models.SlugField(max_length=100)
    site = models.ForeignKey(to="dcim.Site", on_delete=models.CASCADE, related_name="rack_groups")
    parent = TreeForeignKey(
        to="self",
        on_delete=models.CASCADE,
        related_name="children",
        blank=True,
        null=True,
        db_index=True,
    )
    description = models.CharField(max_length=200, blank=True)

    objects = TreeManager()

    csv_headers = ["site", "parent", "name", "slug", "description"]

    class Meta:
        ordering = ["site", "name"]
        unique_together = [
            ["site", "name"],
            ["site", "slug"],
        ]

    class MPTTMeta:
        order_insertion_by = ["name"]

    def __str__(self):
        return self.name

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

    def to_csv(self):
        return (
            self.site,
            self.parent.name if self.parent else "",
            self.name,
            self.slug,
            self.description,
        )

    def to_objectchange(self, action):
        # Remove MPTT-internal fields
        return ObjectChange(
            changed_object=self,
            object_repr=str(self),
            action=action,
            object_data=serialize_object(self, exclude=["level", "lft", "rght", "tree_id"]),
        )

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

        # Parent RackGroup (if any) must belong to the same Site
        if self.parent and self.parent.site != self.site:
            raise ValidationError(f"Parent rack group ({self.parent}) must belong to the same site ({self.site})")
Example #4
0
class InventoryItem(MPTTModel, ComponentModel):
    """
    An InventoryItem represents a serialized piece of hardware within a Device, such as a line card or power supply.
    InventoryItems are used only for inventory purposes.
    """

    parent = TreeForeignKey(
        to="self",
        on_delete=models.CASCADE,
        related_name="child_items",
        blank=True,
        null=True,
        db_index=True,
    )
    manufacturer = models.ForeignKey(
        to="dcim.Manufacturer",
        on_delete=models.PROTECT,
        related_name="inventory_items",
        blank=True,
        null=True,
    )
    part_id = models.CharField(
        max_length=50,
        verbose_name="Part ID",
        blank=True,
        help_text="Manufacturer-assigned part identifier",
    )
    serial = models.CharField(max_length=50,
                              verbose_name="Serial number",
                              blank=True)
    asset_tag = models.CharField(
        max_length=50,
        unique=True,
        blank=True,
        null=True,
        verbose_name="Asset tag",
        help_text="A unique tag used to identify this item",
    )
    discovered = models.BooleanField(
        default=False, help_text="This item was automatically discovered")

    objects = TreeManager()

    csv_headers = [
        "device",
        "name",
        "label",
        "manufacturer",
        "part_id",
        "serial",
        "asset_tag",
        "discovered",
        "description",
    ]

    class Meta:
        ordering = ("device__id", "parent__id", "_name")
        unique_together = ("device", "parent", "name")

    def get_absolute_url(self):
        return reverse("dcim:inventoryitem", kwargs={"pk": self.pk})

    def to_csv(self):
        return (
            self.device.name or "{{{}}}".format(self.device.pk),
            self.name,
            self.label,
            self.manufacturer.name if self.manufacturer else None,
            self.part_id,
            self.serial,
            self.asset_tag,
            self.discovered,
            self.description,
        )