예제 #1
0
class OUI(models.Model):
    # oui = MACAddressField()
    # mask = MACAddressField()
    start = MACAddressField()
    stop = MACAddressField()
    shortname = models.CharField(max_length=255, blank=True, null=True)
    name = models.CharField(max_length=255, blank=True, null=True)

    def __str__(self):
        return "%s: %s" % (self.pk, self.shortname)

    class Meta:
        db_table = "ouis"
예제 #2
0
class Disabled(models.Model):
    mac = MACAddressField(primary_key=True)
    # host = models.OneToOneField('Host', primary_key=True, db_column='mac', db_constraint=False, related_name='disabled_host', on_delete=models.PROTECT)
    reason = models.TextField(blank=True, null=True)
    changed = models.DateTimeField(auto_now=True, db_column="disabled")
    changed_by = models.ForeignKey(settings.AUTH_USER_MODEL, db_column="disabled_by")

    def __init__(self, *args, **kwargs):
        # Initialize setters
        self._host = None

        super(Disabled, self).__init__(*args, **kwargs)

    def __str__(self):
        return "%s" % self.pk

    @property
    def host(self):
        if self._host:
            return self._host
        else:
            host_obj = Host.objects.filter(mac=self.mac).first()
            return host_obj.hostname if host_obj else None

    @host.setter
    def host(self, host):
        self._host = host

    class Meta:
        db_table = "disabled"
        verbose_name = "Disabled Host"
        ordering = ("-changed",)
예제 #3
0
class IgnoredMac(models.Model):
    mac = MACAddressField()
    reason = models.TextField(max_length=250)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return str(self.mac)
예제 #4
0
class MacOui(models.Model):
    oui = MACAddressField(primary_key=True)
    vendor = models.TextField()

    objects = NetManager()

    def __str__(self):
        return self.oui

    class Meta:
        db_table = "mac_oui"
예제 #5
0
class UnknownScanConflict(ScanConflict):
    ip = InetAddressField()
    mac = MACAddressField()
    lab = models.ForeignKey(Lab, on_delete=models.SET_NULL, null=True, blank=True)
    lastseen = models.DateTimeField(default=timezone.now)

    def safe_OUI_org(self):
        try:
            return self.mac.info['OUI']['org']
        except NotRegisteredError:
            return "unknown"

    def __str__(self):
        return f"[unknown conflict] {self.mac} with IP {self.ip} firstseen at {self.scan.timestamp}"
예제 #6
0
class CustomerIpLeaseLog(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    ip_address = models.GenericIPAddressField(_("Ip address"))
    lease_time = models.DateTimeField(_("Lease time"), auto_now_add=True)
    last_update = models.DateTimeField(_("Last update"), blank=True, null=True, default=None)
    mac_address = MACAddressField(verbose_name=_("Mac address"), null=True, default=None)
    is_dynamic = models.BooleanField(_("Is synamic"), default=False)
    event_time = models.DateTimeField(_("Event time"), auto_now_add=True)
    end_use_time = models.DateTimeField(_("Lease end use time"), null=True, blank=True, default=None)

    def __str__(self):
        return self.ip_address

    class Meta:
        db_table = "networks_ip_lease_log"
예제 #7
0
class Interface(BaseAccessLevel):
    """ Interface model """
    device = models.ForeignKey('net.Device')
    type = models.IntegerField(_('type'), max_length=2, choices=INTERFACE_TYPE_CHOICES, blank=True)
    name = models.CharField(_('name'), max_length=10, blank=True, null=True)
    mac = MACAddressField(_('mac address'), max_length=17, unique=True, default=None)
    mtu = models.IntegerField(_('MTU (Maximum Trasmission Unit)'), blank=True, null=True, default=1500)
    tx_rate = models.IntegerField(_('TX Rate'), null=True, default=None, blank=True)
    rx_rate = models.IntegerField(_('RX Rate'), null=True, default=None, blank=True)
    
    class Meta:
        app_label= 'net'
        permissions = (('can_view_interfaces', 'Can view interfaces'),)
    
    def __unicode__(self):
        return '%s %s' % (self.get_type_display(), self.mac)
예제 #8
0
class AttributeToHost(models.Model):
    attribute = models.IntegerField(null=True, blank=True, db_column="aid")
    name = models.CharField(max_length=255, blank=True, null=True)
    structured = models.BooleanField(default=None)
    required = models.BooleanField(default=False)
    mac = MACAddressField(blank=True, null=True)
    avid = models.IntegerField(blank=True, null=True)
    value = models.TextField(blank=True, null=True)

    objects = NetManager()

    def __str__(self):
        return "%s %s" % (self.attribute.name, self.name)

    class Meta:
        managed = False
        db_table = "attributes_to_hosts"
예제 #9
0
class VirtualHostsScan(models.Model):
    scan = models.ForeignKey(ScanSession, on_delete=models.CASCADE, related_name='virtualhosts')
    status = models.CharField(
        max_length=8,
        choices=[
            ('active', 'Active'),
            ('old', 'Old'),
            ('ignore', 'Ignored'),
            ('super', 'Superseded')
        ],
        null=False,
        default='active'
    )
    ip = InetAddressField()
    mac = MACAddressField()
    lab = models.ForeignKey(Lab, on_delete=models.SET_NULL, null=True, blank=True)
    lastseen = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return f"Virtual MAC: {self.mac}/{self.ip} in {self.lab}"
예제 #10
0
class Nic(models.Model):
    model = models.CharField(max_length=30, blank=True)
    mac = MACAddressField(unique=True)
    integrated = models.BooleanField(default=False)
    management = models.BooleanField(default=False)
    host = models.ForeignKey(Host, on_delete=models.CASCADE, related_name='nics', null=True, blank=True)
    ip = InetAddressField(store_prefix_length=False, blank=True, null=True)
    primary = models.BooleanField(help_text="Is this the primary NIC in the assigned host?")
    lastseen = models.DateTimeField(null=True, blank=True, help_text="Updated automatically from primary LabScan")
    objects = NetManager()

    def __str__(self):
        return str(self.mac) + ' / ' + self.model

    def clean(self):
        if self.host:
            primaries = Nic.objects.filter(Q(primary=True) & Q(host=self.host) & ~Q(pk=self.pk))
            if primaries.count() > 1:
                raise ValidationError(f"The assigned host cannot have more than one primary NIC, id(s) {primaries.all()}")

    def save(self, *args, **kwargs):
        self.full_clean()

        # update the IP fields on the card's parent host if it has one.
        if self.host!=None and self.ip:
            if self.primary:
                self.host.ip = self.ip
            elif self.host.ip == None:
                primarynic = self.host.nics.filter(primary=True)
                if primarynic:
                    if primarynic[0].ip is None:
                        self.host.ip = self.ip
            if self.host.lastseen:
                if self.lastseen > self.host.lastseen:
                    self.host.lastseen = self.lastseen
            else:
                self.host.lastseen = self.lastseen
            self.host.save()

        return super().save(*args, **kwargs)
예제 #11
0
class IXLan(models.Model):
    name = models.CharField(max_length=255, blank=True)
    descr = models.TextField(blank=True)
    mtu = models.PositiveIntegerField(null=True, blank=True)
    vlan = models.PositiveIntegerField(null=True, blank=True)
    dot1q_support = models.BooleanField(default=False)
    rs_asn = ASNField(
        verbose_name="Route Server ASN",
        allow_zero=True,
        null=True,
        blank=True,
        default=0,
    )
    arp_sponge = MACAddressField(verbose_name="ARP sponging MAC",
                                 null=True,
                                 unique=True,
                                 blank=True)
    ixf_ixp_member_list_url = models.URLField(
        verbose_name="IX-F Member Export URL", null=True, blank=True)
    ixf_ixp_member_list_url_visible = models.CharField(
        verbose_name="IX-F Member Export URL Visibility",
        max_length=64,
        choices=Visibility.choices,
        default=Visibility.PRIVATE,
    )
    ix = models.ForeignKey(
        InternetExchange,
        default=0,
        related_name="ixlan_set",
        verbose_name="Internet Exchange",
        on_delete=models.CASCADE,
    )

    class Meta:
        verbose_name = "Internet Exchange LAN"
        verbose_name_plural = "Internet Exchange LANs"
예제 #12
0
class MACTestModel(Model):
    field = MACAddressField(null=True)
    objects = NetManager()

    class Meta:
        db_table = 'mac'
예제 #13
0
class MACAddress(AbstractDatedModel):

    address = MACAddressField()
예제 #14
0
class Interface(BaseAccessLevel):
    """ Interface model """
    device = models.ForeignKey('net.Device')
    type = models.IntegerField(_('type'),
                               max_length=2,
                               choices=INTERFACE_TYPE_CHOICES,
                               blank=True)
    name = models.CharField(_('name'), max_length=10, blank=True, null=True)
    mac = MACAddressField(_('mac address'),
                          max_length=17,
                          unique=True,
                          default=None,
                          null=True,
                          blank=True)
    mtu = models.IntegerField(_('MTU'),
                              blank=True,
                              null=True,
                              default=1500,
                              help_text=_('Maximum Trasmission Unit'))
    tx_rate = models.IntegerField(_('TX Rate'),
                                  null=True,
                                  default=None,
                                  blank=True)
    rx_rate = models.IntegerField(_('RX Rate'),
                                  null=True,
                                  default=None,
                                  blank=True)

    # extra data
    data = DictionaryField(
        _('extra data'),
        null=True,
        blank=True,
        help_text=_('store extra attributes in JSON string'))
    shortcuts = ReferencesField(null=True, blank=True)

    objects = InterfaceManager()

    class Meta:
        app_label = 'net'

    def __unicode__(self):
        return '%s %s' % (self.get_type_display(), self.mac)

    def save(self, *args, **kwargs):
        """
        Custom save method does the following:
            * save shortcuts if HSTORE is enabled
        """
        if 'node' not in self.shortcuts:
            self.shortcuts['node'] = self.device.node

        if 'user' not in self.shortcuts and self.device.node.user:
            self.shortcuts['user'] = self.device.node.user

        if 'layer' not in self.shortcuts and 'nodeshot.core.layers' in settings.INSTALLED_APPS:
            self.shortcuts['layer'] = self.device.node.layer

        super(Interface, self).save(*args, **kwargs)

    @property
    def owner(self):
        if 'user' not in self.shortcuts:
            if self.device or self.device_id:
                self.save()
            else:
                raise Exception('Instance does not have a device set yet')

        return self.shortcuts['user']

    @property
    def node(self):
        if 'node' not in self.shortcuts:
            if self.device or self.device_id:
                self.save()
            else:
                raise Exception('Instance does not have a device set yet')
        return self.shortcuts['node']

    @property
    def layer(self):
        if 'nodeshot.core.layers' not in settings.INSTALLED_APPS:
            return False
        if 'layer' not in self.shortcuts:
            if self.device or self.device_id:
                self.save()
            else:
                raise Exception('Instance does not have a device set yet')
        return self.shortcuts['layer']

    @property
    def ip_addresses(self):
        try:
            addresses = self.data.get('ip_addresses', '')
        # self.data might be none, hence self.data['ip_addresses'] will raise an exception
        except AttributeError:
            addresses = ''
        return addresses.replace(' ', '').split(',') if addresses else []

    @ip_addresses.setter
    def ip_addresses(self, value):
        """ :param value: a list of ip addresses """
        if not isinstance(value, list):
            raise ValueError('ip_addresses value must be a list')
        # in soem cases self.data might be none, so let's instantiate an empty dict
        if self.data is None:
            self.data = {}
        # update field
        self.data['ip_addresses'] = ', '.join(value)

    if 'grappelli' in settings.INSTALLED_APPS:

        @staticmethod
        def autocomplete_search_fields():
            return ('mac__icontains', 'data__icontains')
예제 #15
0
class Host(DirtyFieldsMixin, models.Model):
    mac = MACAddressField("Mac Address", primary_key=True)
    hostname = models.CharField(
        max_length=255, unique=True, validators=[validate_hostname], db_index=True
    )
    description = models.TextField(blank=True, null=True)
    address_type_id = models.ForeignKey(
        "network.AddressType",
        blank=True,
        null=True,
        db_column="address_type_id",
        on_delete=models.SET_NULL,
    )
    pools = models.ManyToManyField(
        "network.Pool", through="network.HostToPool", related_name="pool_hosts"
    )
    # freeform_attributes = models.ManyToManyField('Attribute', through='FreeformAttributeToHost',
    #                                             related_name='freeform_hosts',  blank=True, null=True)
    # structured_attributes = models.ManyToManyField('Attribute', through='StructuredAttributeToHost',
    #                                               related_name='structured_hosts',  blank=True, null=True)
    dhcp_group = models.ForeignKey(
        "network.DhcpGroup",
        db_column="dhcp_group",
        verbose_name="DHCP Group",
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
    )
    expires = models.DateTimeField()
    changed = models.DateTimeField(auto_now=True)
    changed_by = models.ForeignKey(settings.AUTH_USER_MODEL, db_column="changed_by")
    last_notified = models.DateTimeField(blank=True, null=True)

    objects = HostManager.from_queryset(HostQuerySet)()

    search_index = VectorField()
    searcher = SearchManager(
        fields=("hostname", "description"),
        config="pg_catalog.english",  # this is default
        search_field="search_index",  # this is default
        auto_update_search_field=True,
    )

    def __init__(self, *args, **kwargs):

        # Initialize setters
        self._expire_days = None
        self._user_owners = None
        self._group_owners = None
        self._user = None
        self._master_dns_deleted = False

        self.ip_address = None
        self.pool = None
        self.network = None

        super(Host, self).__init__(*args, **kwargs)

    def __str__(self):
        return self.hostname

    # Overload getattr for get original values
    def __getattr__(self, name):
        if name.startswith("original_") and name.split("_", 1)[1] in list(
            self._original_state.keys()
        ):

            def _original(fieldname):
                fieldvalue = self._original_state.get(fieldname, None)
                if fieldvalue is not None:
                    return fieldvalue

            return _original(name.split("_", 1)[1])
        else:
            return self.__getattribute__(name)

    def reset_state(self):
        self._expire_days = None
        self._user_owners = None
        self._group_owners = None
        self._user = None
        self._master_dns_deleted = False

        self.ip_address = None
        self.pool = None
        self.network = None

        try:
            del self.ip_addresses
            del self.master_ip_address
            del self.owners
            del self._pools_cache
            del self._addresses_cache
        except AttributeError:
            pass

    @cached_property
    def _addresses_cache(self):
        return list(self.addresses.all())

    @cached_property
    def _pools_cache(self):
        return list(self.pools.all())

    @property
    def expire_days(self):
        if self._expire_days:
            return self._expire_days
        else:
            return self.get_expire_days()

    @expire_days.setter
    def expire_days(self, days):
        self._expire_days = days

    @cached_property
    def owners(self):
        return self.get_owners()

    def get_owners(
        self,
        ids_only=False,
        name_only=False,
        owner_detail=False,
        users_only=False,
        user_perms_prefetch=None,
        group_perms_prefetch=None,
    ):
        # users_dict = get_users_with_perms(self, attach_perms=True, with_group_users=False)
        # groups_dict = get_groups_with_perms(self, attach_perms=True)
        content_type = ContentType.objects.get_for_model(self)

        users = []
        if user_perms_prefetch:
            user_perms = list(
                filter(
                    lambda x: x.object_pk == str(self.mac)
                    and x.permission.codename == "is_owner_host",
                    user_perms_prefetch,
                )
            )
        else:
            user_perms = UserObjectPermission.objects.filter(
                content_type=content_type,
                object_pk=str(self.mac),
                permission__codename="is_owner_host",
            )
        for perm in user_perms:
            users.append(perm.user)

        groups = []
        if group_perms_prefetch:
            group_perms = list(
                filter(
                    lambda x: x.object_pk == str(self.mac)
                    and x.permission.codename == "is_owner_host",
                    group_perms_prefetch,
                )
            )
        else:
            group_perms = GroupObjectPermission.objects.filter(
                content_type=content_type,
                object_pk=str(self.mac),
                permission__codename="is_owner_host",
            )
        for perm in group_perms:
            groups.append(perm.group)

        # for user, permissions in users_dict.iteritems():
        #    if 'is_owner_host' in permissions:
        #        users.append(user)

        # groups = []
        # for group, permissions in groups_dict.iteritems():
        #    if 'is_owner_host' in permissions:
        #        groups.append(group)

        if users_only:
            User = get_user_model()
            users_from_groups = [
                user for user in User.objects.filter(groups__in=groups)
            ]
            users = list(set(users + users_from_groups))
            return users

        if owner_detail:
            users = [
                (user.pk, user.username, user.get_full_name(), user.email)
                for user in users
            ]
            groups = [(group.pk, group.name) for group in groups]

        elif ids_only:
            users = [user.pk for user in users]
            groups = [group.pk for group in groups]

        elif name_only:
            users = [user.username for user in users]
            groups = [group.name for group in groups]

        return users, groups

    @property
    def user_owners(self):
        if self._user_owners:
            return self._user_owners
        else:
            return [owner.username for owner in self.owners[0]]

    @user_owners.setter
    def user_owners(self, owners):
        self._user_owners = owners

    @property
    def user(self):
        if self._user:
            return self._user
        else:
            return self.changed_by

    @user.setter
    def user(self, value):
        self._user = value

    @property
    def master_dns_deleted(self):
        return self._master_dns_deleted

    @master_dns_deleted.setter
    def master_dns_deleted(self, value):
        self._master_dns_deleted = value

    @property
    def group_owners(self):
        if self._group_owners:
            return self._group_owners
        else:
            return [owner.name for owner in self.owners[1]]

    @group_owners.setter
    def group_owners(self, owners):
        self._group_owners = owners

    @property
    def is_dynamic(self):
        if self.is_dirty() is False:
            return True if self._pools_cache else False
        else:
            return True if self.pools.all() else False

    @property
    def is_static(self):
        return True if self.is_dynamic is False else False

    # This is set on the queryset manager now.
    # @property
    # def is_disabled(self):
    #     try:
    #         return True if self.disabled_host else False
    #     except ObjectDoesNotExist:
    #         return False

    @property
    def disabled_host(self):
        if self.is_disabled:
            return Disabled.objects.filter(pk=self.mac).first()
        else:
            return None

    @property
    def is_expired(self):
        return True if self.expires < timezone.now() else False

    @property
    def address_type(self):
        # TODO: Address type is old and eventually will be deprecated.
        # Try to set address type if doesn't exist if host already exists in DB.
        if self.pk and not self.address_type_id:
            from openipam.network.models import AddressType, NetworkRange

            addresses = self._addresses_cache
            pools = self._pools_cache

            try:
                # if (len(addresses) + len(pools)) > 1:
                #     self.address_type = None
                # elif addresses:
                if addresses:
                    try:
                        ranges = NetworkRange.objects.filter(
                            range__net_contains_or_equals=addresses[0].address
                        )
                        if ranges:
                            self.address_type_id = AddressType.objects.get(
                                ranges__in=ranges
                            )
                        else:
                            raise AddressType.DoesNotExist
                    except AddressType.DoesNotExist:
                        self.address_type_id = AddressType.objects.get(is_default=True)
                elif pools:
                    self.address_type_id = AddressType.objects.get(pool=pools[0])
            except AddressType.DoesNotExist:
                self.address_type_id = None

        return self.address_type_id

    @address_type.setter
    def address_type(self, value):
        self.address_type_id = value

    @property
    def mac_stripped(self):
        mac = str(self.mac)
        mac = [c for c in mac if c.isdigit() or c.isalpha()]
        return "".join(mac)

    @property
    def mac_last_seen(self):
        gul_mac = GulRecentArpBymac.objects.filter(mac=self.mac).order_by("-stopstamp")

        if gul_mac:
            return gul_mac[0].stopstamp
        else:
            return None

    @property
    def oui(self):
        return OUI.objects.extra(
            where=["'%s' >= ouis.start and '%s' <= ouis.stop" % (self.mac, self.mac)]
        ).first()

    @cached_property
    def master_ip_address(self):
        if self.is_static:
            if not self.ip_addresses:
                return None
            elif len(self.ip_addresses) == 1:
                return self.ip_addresses[0]
            else:
                address = self.addresses.filter(arecords__name=self.hostname).first()
                return str(address) if address else self.ip_addresses[0]
        return None

    @cached_property
    def ip_addresses(self):
        return [str(address) for address in self.addresses.all()]

    def delete_ip_address(self, user, address):

        if isinstance(address, string_types):
            address = self.addresses.filter(address=address)

        # Delete DNS PTR and A Records
        self.delete_dns_records(user=user, addresses=address)

        # Release address
        address.release(user=user)

    def add_ip_address(self, user=None, ip_address=None, network=None, hostname=None):
        from openipam.network.models import Network, Address
        from openipam.dns.models import DnsRecord, DnsType

        user = user or self._user
        if not user:
            raise Exception("A User must be given to add ip addresses.")

        if not hostname:
            raise ValidationError("A hostname is required.")

        address = None

        # Check to see if hostname already taken for any hosts other then the current one if being updated.
        used_hostname = (
            DnsRecord.objects.filter(
                dns_type__in=[DnsType.objects.A, DnsType.objects.AAAA], name=hostname
            )
            .exclude(ip_content__address=self.master_ip_address)
            .first()
        )
        if used_hostname:
            raise ValidationError(
                "Hostname %s is already assigned to DNS A Record: %s."
                % (hostname, used_hostname.ip_content)
            )

        user_pools = get_objects_for_user(
            user, ["network.add_records_to_pool", "network.change_pool"], any_perm=True
        )

        user_nets = get_objects_for_user(
            user,
            [
                "network.add_records_to_network",
                "network.is_owner_network",
                "network.change_network",
            ],
            any_perm=True,
        )

        if network:
            if isinstance(network, string_types):
                network = Network.objects.get(network=network)

            if not user_nets.filter(network=network.network):
                raise ValidationError(
                    "You do not have access to assign host '%s' to the "
                    "network specified: %s." % (hostname, network)
                )

            try:
                network_address = (
                    Address.objects.filter(
                        Q(pool__in=user_pools) | Q(pool__isnull=True),
                        Q(leases__isnull=True)
                        | Q(leases__abandoned=True)
                        | Q(leases__ends__lte=timezone.now())
                        | Q(leases__host=self),
                        network=network,
                        host__isnull=True,
                        reserved=False,
                    )
                    .order_by("address")
                    .first()
                )

                if not network_address:
                    raise Address.DoesNotExist
                else:
                    address = network_address

            except ValidationError:
                raise ValidationError("The network '%s' is invalid." % network)
            except Address.DoesNotExist:
                raise ValidationError(
                    "There are no avaiable addresses for the network entered: %s"
                    % network
                )

        elif ip_address:
            # Validate IP Address
            try:
                validate_ipv46_address(ip_address)
            except ValidationError:
                raise ValidationError(
                    "IP Address %s is invalid.  Enter a valid IPv4 or IPv6 address."
                    % ip_address
                )

            if ip_address in self.ip_addresses:
                raise ValidationError(
                    "IP address %s is already assigned to this host." % ip_address
                )

            try:
                address = Address.objects.get(
                    Q(pool__in=user_pools)
                    | Q(pool__isnull=True)
                    | Q(network__in=user_nets),
                    Q(leases__isnull=True)
                    | Q(leases__abandoned=True)
                    | Q(leases__ends__lte=timezone.now())
                    | Q(leases__host=self),
                    Q(host__isnull=True) | Q(host=self),
                    address=ip_address,
                    reserved=False,
                )
            except ValidationError:
                raise ValidationError(
                    "There IP Address %s is not available." % ip_address
                )
            except Address.DoesNotExist:
                raise ValidationError(
                    "There are no avaiable addresses for the IP entered: %s"
                    % ip_address
                )
        else:
            raise ValidationError(
                "A Network or IP Address must be given to assign this host an address."
            )

        # Make sure pool is clear on addresses we are assigning.
        address.pool_id = None
        address.host = self
        address.changed_by = user
        address.save()

        # Update A and PTR dns records
        self.add_dns_records(user=user, hostname=hostname, address=address)

        return address

    def delete_dns_records(
        self, user=None, delete_only_master_dns=False, delete_dchpdns=True, addresses=[]
    ):
        from openipam.dns.models import DnsType

        user = user or self._user
        if not user:
            raise Exception("A User must be given to delete dns records for host.")

        if self.master_dns_deleted is False:

            # If addresses list is empty, we use the master address
            # So By default we are deleting DNS for just the primary address
            if not addresses:
                addresses = self.addresses.filter(address=self.master_ip_address)

            if delete_only_master_dns:
                # Here we only delete the master DNS (A and PTR) record
                # If modifying a host, this will get recreated later in the call.
                self.dns_records.filter(
                    Q(name=self.original_hostname)
                    | Q(text_content=self.original_hostname),
                    dns_type__in=[
                        DnsType.objects.PTR,
                        DnsType.objects.A,
                        DnsType.objects.AAAA,
                    ],
                ).update(changed=timezone.now(), changed_by=user)
                # Delete Assocatiated PTR and A or AAAA records.
                self.dns_records.filter(
                    Q(name=self.original_hostname)
                    | Q(text_content=self.original_hostname),
                    dns_type__in=[
                        DnsType.objects.PTR,
                        DnsType.objects.A,
                        DnsType.objects.AAAA,
                    ],
                ).delete()
            else:
                # TODO: There is a foreign key for host on this table but we cant use it
                # cause are aren't sure this will get everything due to not all records
                # using the FK.
                # Update Changed by Assocatiated PTR and A or AAAA records.
                self.dns_records.filter(
                    Q(
                        name__in=[
                            address.address.reverse_pointer for address in addresses
                        ]
                    )
                    | Q(ip_content__in=[address for address in addresses]),
                    dns_type__in=[
                        DnsType.objects.PTR,
                        DnsType.objects.A,
                        DnsType.objects.AAAA,
                    ],
                ).update(changed=timezone.now(), changed_by=user)
                # Delete Assocatiated PTR and A or AAAA records.
                self.dns_records.filter(
                    Q(
                        name__in=[
                            address.address.reverse_pointer for address in addresses
                        ]
                    )
                    | Q(ip_content__in=[address for address in addresses]),
                    dns_type__in=[
                        DnsType.objects.PTR,
                        DnsType.objects.A,
                        DnsType.objects.AAAA,
                    ],
                ).delete()

            if delete_dchpdns:
                # Delete DHCP DNS records for dynamics if they exist.
                DhcpDnsRecord.objects.filter(
                    host__hostname=self.original_hostname
                ).delete()

            if not addresses or self.master_ip_address in [
                str(address.address) for address in addresses
            ]:
                self.master_dns_deleted = True

    def add_dns_records(self, user=None, hostname=None, address=None):
        from openipam.dns.models import DnsRecord, DnsType
        from openipam.network.models import Address

        user = user or self._user
        if not user:
            raise Exception("A User must be given to add dns records for host.")

        # Only do this on static hosts.
        if self.is_static:

            if not hostname:
                hostname = self.hostname

            if isinstance(address, string_types):
                address = Address.objects.filter(address=address).first()
            elif not address:
                address = Address.objects.filter(address=self.master_ip_address).first()

            # Add Associated PTR
            DnsRecord.objects.add_or_update_record(
                user=user,
                name=address.address.reverse_pointer,
                content=hostname,
                dns_type=DnsType.objects.PTR,
                host=self,
            )

            # Add Associated A or AAAA record
            arecord = DnsRecord.objects.filter(
                dns_type__in=[DnsType.objects.A, DnsType.objects.AAAA],
                host=self,
                name=hostname,
            ).first()
            DnsRecord.objects.add_or_update_record(
                user=user,
                name=hostname,
                content=address.address,
                dns_type=DnsType.objects.A
                if address.address.version == 4
                else DnsType.objects.AAAA,
                host=self,
                record=arecord if arecord else None,
            )

        # Reset dns deleted flag if this is the master hostname
        if hostname == self.hostname:
            self.master_dns_deleted = False

    def get_dns_records(self):
        from openipam.dns.models import DnsRecord

        addresses = self.addresses.all()
        a_record_names = (
            DnsRecord.objects.select_related("ip_content", "host", "dns_type")
            .filter(ip_content__in=addresses)
            .values_list("name")
        )
        dns_records = (
            DnsRecord.objects.select_related("ip_content", "host", "dns_type")
            .filter(
                Q(text_content__in=a_record_names)
                | Q(name__in=a_record_names)
                | Q(ip_content__in=addresses)
                | Q(host=self)
                | Q(text_content=self.hostname)  # For dynamic hosts
            )
            .order_by("dns_type__name")
        )

        return dns_records

    def get_expire_days(self):
        if self.expires:
            delta = self.expires - timezone.now()
            return delta.days if delta.days > 0 else None
        else:
            return None

    def set_expiration(self, expire_days):
        if isinstance(expire_days, int) or isinstance(expire_days, string_types):
            expire_days = timedelta(int(expire_days))
        now = timezone.now()
        self.expires = (
            datetime(now.year, now.month, now.day) + timedelta(1) + expire_days
        )
        self.expires = self.expires.replace(tzinfo=utc)

    def set_mac_address(self, new_mac_address):
        if self.mac and str(self.mac).lower() != str(new_mac_address).lower():
            cursor = connection.cursor()
            cursor.execute(
                """
                UPDATE hosts SET mac = %s WHERE mac = %s
            """,
                [str(new_mac_address), str(self.mac)],
            )
            self.mac = str(new_mac_address).lower()
        elif not self.pk:
            self.mac = str(new_mac_address).lower()

    def set_hostname(self, hostname, user=None):
        user = user or self._user
        if not user:
            raise Exception("A User must be given to save hosts.")

        self.hostname = hostname
        if (
            self.original_hostname
            and self.hostname
            and self.hostname != self.original_hostname
        ):
            self.delete_dns_records(user=user, delete_only_master_dns=True)

    # TODO: Clean this up, I dont like where this is at.
    def set_network_ip_or_pool(self, user=None, delete=False):
        user = user or self._user
        if not user:
            raise Exception("A User must be given to save hosts.")

        # Set the pool if attached to model otherwise find it by address type
        pool = self.pool
        current_pool = self._pools_cache[0] if self._pools_cache else None

        # TODO: Currently un-used function
        if delete:
            # Remove all pools
            self.pools.clear()
            # Delete DNS
            self.delete_dns_records(user=user, addresses=self.addresses.all())
            # Remove all addresses
            self.addresses.release(user=user)

        # If we have a pool, this dynamic and we assign
        if pool and pool != current_pool:
            from openipam.network.models import Pool

            # Delete DNS
            self.delete_dns_records(user=user, addresses=self.addresses.all())
            # Remove all addresses
            self.addresses.release(user=user)

            # TODO: Kill this later.
            host_pool_check = self.host_pools.all()
            if len(host_pool_check) > 1:
                self.pools.clear()

            host_pool = self.host_pools.filter(pool__name=pool).first()
            if host_pool:
                host_pool.changed_by = user
                host_pool.save()
            else:
                # Delete what is there and create a new one.
                self.pools.clear()
                # Assign new pool if it doesn't already exist
                self.host_pools.create(
                    host=self, pool=Pool.objects.get(name=pool), changed_by=user
                )

        # If we have a Network or IP address, then assign that address to host
        elif self.network or (
            self.ip_address and self.ip_address not in self.ip_addresses
        ):

            # Remove all pools
            self.pools.clear()
            # TODO: Look at delete_dns for a way to only delete dhcp dns records.
            try:
                self.dhcpdnsrecord.delete()
            except ObjectDoesNotExist:
                pass

            # Current IP
            current_ip_address = self.master_ip_address

            if current_ip_address:
                # Delete DNS
                self.delete_dns_records(user=user)
                # Release the current IP to add another
                self.addresses.filter(address=current_ip_address).release(user=user)

            # Add new IP
            self.add_ip_address(
                user=user,
                ip_address=self.ip_address,
                network=self.network,
                hostname=self.hostname,
            )

    def remove_owners(self):
        users, groups = self.get_owners()
        self.remove_user_owners(users)
        self.remove_group_owners(groups)

    def remove_user_owners(self, users=None):
        if not users:
            users = self.get_owners(users_only=True)
        for user in users:
            remove_perm("is_owner_host", user, self)

    def remove_group_owners(self, groups=None):
        if not groups:
            users, groups = self.get_owners()
        for group in groups:
            remove_perm("is_owner_host", group, self)

    def remove_owner(self, user_or_group):
        return remove_perm("is_owner_host", user_or_group, self)

    def assign_owner(self, user_or_group):
        return assign_perm("is_owner_host", user_or_group, self)

    def save(self, user=None, add_dns=True, *args, **kwargs):
        user = user or self._user
        if not user:
            raise Exception("A User must be given to save hosts.")

        # Make sure hostname is lowercase
        self.hostname = self.hostname.lower()
        # Make sure mac is lowercase
        self.mac = str(self.mac).lower()

        # Updating changed and changed_by
        self.changed_by = user
        self.changed = timezone.now()

        # If master DNS delete, re-create it
        if add_dns and self.master_dns_deleted is True:
            self.add_dns_records(user=user)

        super(Host, self).save(*args, **kwargs)

    def delete(self, user=None, *args, **kwargs):
        user = user or self._user
        if not user:
            raise Exception("A User must be given to save hosts.")

        # Delete primary DNS (PTR, A, and AAAA, updating changed and changed by)
        self.delete_dns_records(user=user, addresses=self.addresses.all())

        # Release all addresses associated with host.
        self.addresses.release(user=user)

        # Re-save so that it captures user for postgres log table
        try:
            self.save(user=user, add_dns=False, force_update=True)
        except DatabaseError:
            pass
        with transaction.atomic():
            super(Host, self).delete(*args, **kwargs)

    def clean(self):
        from openipam.dns.models import DnsRecord, DnsType
        from openipam.network.models import Address

        # Perform check to on hostname to not let users create a host
        if self.hostname and self.hostname != self.original_hostname:
            existing_hostname = Host.objects.filter(hostname=self.hostname).first()
            if existing_hostname:
                raise ValidationError(
                    "The hostname '%s' already exists." % (self.hostname)
                )

            existing_dns_hostname = (
                DnsRecord.objects.filter(
                    dns_type__in=[DnsType.objects.A, DnsType.objects.AAAA],
                    name=self.hostname,
                )
                .exclude(host=self)
                .first()
            )
            if existing_dns_hostname:
                raise ValidationError(
                    "DNS Records already exist for this hostname: %s. "
                    " Please contact an IPAM Administrator." % (self.hostname)
                )

        # Perform permission checks if user is attached to this instance
        # Domain permission checks if hostname has changed
        if self.hostname and self.hostname != self.original_hostname:
            domain_from_host = self.hostname.split(".")[1:]
            domain_from_host = ".".join(domain_from_host)

            valid_domain = get_objects_for_user(
                self.user,
                [
                    "dns.add_records_to_domain",
                    "dns.is_owner_domain",
                    "dns.change_domain",
                ],
                any_perm=True,
            ).filter(name=domain_from_host)
            if not valid_domain:
                raise ValidationError(
                    "Insufficient permissions to add hosts "
                    "for domain: %s. Please contact an IPAM Administrator."
                    % domain_from_host
                )

        # Pool and Network permission checks
        # Check for pool assignment and perms
        if self.address_type and self.address_type.pool:
            valid_pools = get_objects_for_user(
                self.user,
                ["network.add_records_to_pool", "network.change_pool"],
                any_perm=True,
            )
            if self.address_type.pool not in valid_pools:
                raise ValidationError(
                    "Insufficient permissions to add hosts to "
                    "the assigned pool: %s. Please contact an IPAM Administrator."
                    % self.address_type.pool
                )

        # If network defined check for address assignment and perms
        if self.network:
            valid_network = get_objects_for_user(
                self.user,
                [
                    "network.add_records_to_network",
                    "network.is_owner_network",
                    "network.change_network",
                ],
                any_perm=True,
            )
            if self.network.network not in [
                network.network for network in valid_network
            ]:
                raise ValidationError(
                    "Insufficient permissions to add hosts to "
                    "the assigned network: %s. Please contact an IPAM Administrator."
                    % self.network.network
                )

        # If IP Address defined, check validity and perms
        if self.ip_address:
            ip_address = self.ip_address

            user_pools = get_objects_for_user(
                self.user,
                ["network.add_records_to_pool", "network.change_pool"],
                any_perm=True,
            )
            user_nets = get_objects_for_user(
                self.user,
                [
                    "network.add_records_to_network",
                    "network.is_owner_network",
                    "network.change_network",
                ],
                any_perm=True,
            )

            # Make sure this is valid.
            validate_ipv46_address(ip_address)
            address = Address.objects.filter(
                Q(pool__in=user_pools)
                | Q(pool__isnull=True)
                | Q(network__in=user_nets),
                Q(leases__isnull=True)
                | Q(leases__abandoned=True)
                | Q(leases__ends__lte=timezone.now())
                | Q(leases__host=self),
                Q(host__isnull=True) | Q(host=self),
                address=ip_address,
                reserved=False,
            )
            if not address:
                raise ValidationError(
                    "The IP Address is reserved, in use, or not allowed. "
                    "Please contact an IPAM Administrator."
                )

    class Meta:
        db_table = "hosts"
        permissions = (("is_owner_host", "Is owner"),)
        default_permissions = ("add", "change", "delete", "view")
        ordering = ("hostname",)
예제 #16
0
class MACArrayTestModel(Model):
    field = ArrayField(MACAddressField(), blank=True, null=True)

    class Meta:
        db_table = 'macarray'
예제 #17
0
파일: ixctl.py 프로젝트: fullctl/ixctl
class InternetExchangeMember(PdbRefModel):
    """
    Describes a member at an internet exchange

    Can have a reference to a peeringdb netixlan object
    """

    ix = models.ForeignKey(
        InternetExchange,
        help_text=_("Members at this Exchange"),
        related_name="member_set",
        on_delete=models.CASCADE,
    )
    ipaddr4 = InetAddressField(blank=True,
                               null=True,
                               store_prefix_length=False)
    ipaddr6 = InetAddressField(blank=True,
                               null=True,
                               store_prefix_length=False)
    macaddr = MACAddressField(null=True, blank=True)
    as_macro_override = models.CharField(max_length=255,
                                         blank=True,
                                         null=True,
                                         validators=[validate_as_set])
    is_rs_peer = models.BooleanField(default=False)
    speed = models.PositiveIntegerField()
    asn = models.PositiveIntegerField()
    name = models.CharField(max_length=255, blank=True, null=True)

    ixf_state = models.CharField(max_length=255,
                                 default="active",
                                 choices=django_ixctl.enum.MEMBER_STATE)
    ixf_member_type = models.CharField(
        max_length=255,
        choices=django_ixctl.enum.IXF_MEMBER_TYPE,
        default="peering")

    class PdbRef(PdbRefModel.PdbRef):
        pdbctl = pdbctl.NetworkIXLan

    class HandleRef:
        tag = "member"

    class Meta:
        db_table = "ixctl_member"
        verbose_name_plural = _("Internet Exchange Members")
        verbose_name = _("Internet Exchange Member")
        unique_together = (("ipaddr4", "ix"), ("ipaddr6", "ix"), ("macaddr",
                                                                  "ix"))

    @classmethod
    def create_from_pdb(cls, pdb_object, ix, save=True, **fields):
        """
        Create `InternetExchangeMember` from peeringdb netixlan

        Argument(s):

        - pdb_object (`fullctl.service_bridge.pdbctl.NetworkIXLan`): netixlan instance
        - ix (`InternetExchange`): member of this ix

        Keyword Argument(s):

        And keyword arguments passwed will be used to inform properties
        of the InternetExchangeMember to be created
        """

        member = super().create_from_pdb(pdb_object,
                                         ix=ix,
                                         save=False,
                                         **fields)

        member.ipaddr4 = pdb_object.ipaddr4
        member.ipaddr6 = pdb_object.ipaddr6
        member.is_rs_peer = pdb_object.is_rs_peer
        member.speed = pdb_object.speed
        member.asn = pdb_object.net.asn
        member.name = pdb_object.net.name

        if save:
            member.save()

        return member

    @classmethod
    def preload_as_macro(cls, queryset):
        asns = set([member.asn for member in queryset])
        if not asns:
            return queryset
        asn_map = {}
        for net in sot.ASSet().objects(asns=list(asns)):
            asn_map[net.asn] = net
        for member in queryset:
            member._net = asn_map.get(member.asn)
            yield member

    @property
    def display_name(self):
        return self.name or f"AS{self.asn}"

    @property
    def org(self):
        return self.ix.instance.org

    @property
    def ix_name(self):
        return self.ix.name

    @property
    def as_sets(self):
        if not self.as_macro:
            return []

        return [as_set.strip() for as_set in self.as_macro.split(",")]

    @property
    def as_macro(self):
        if self.as_macro_override:
            return self.as_macro_override

        if self.net:
            if self.net.source == "peerctl":
                return self.net.as_set
            elif self.net.source == "pdbctl":
                return self.net.irr_as_set
        return ""

    @property
    def net(self):
        if hasattr(self, "_net"):
            return self._net

        self._net = sot.ASSet().first(asn=self.asn)
        return self._net

    def __str__(self):
        return f"AS{self.asn} - {self.ipaddr4} - {self.ipaddr6} ({self.id})"
예제 #18
0
class Device(BaseAbstractModel):
    _cached_manager = None

    ip_address = models.GenericIPAddressField(verbose_name=_("Ip address"),
                                              null=True,
                                              blank=True,
                                              default=None)
    mac_addr = MACAddressField(verbose_name=_("Mac address"), unique=True)
    comment = models.CharField(_("Comment"), max_length=256)
    dev_type = models.PositiveSmallIntegerField(
        _("Device type"),
        default=DEVICE_TYPE_UNKNOWN,
        choices=MyChoicesAdapter(DEVICE_TYPES))
    man_passw = models.CharField(_("SNMP password"),
                                 max_length=16,
                                 null=True,
                                 blank=True)
    group = models.ForeignKey(Group,
                              on_delete=models.SET_NULL,
                              null=True,
                              blank=True,
                              verbose_name=_("Device group"))
    parent_dev = models.ForeignKey("self",
                                   verbose_name=_("Parent device"),
                                   blank=True,
                                   null=True,
                                   on_delete=models.SET_NULL)
    snmp_extra = models.CharField(_("SNMP extra info"),
                                  max_length=256,
                                  null=True,
                                  blank=True)
    extra_data = models.JSONField(
        verbose_name=_("Extra data"),
        help_text=_(
            "Extra data in JSON format. You may use it for your custom data"),
        blank=True,
        null=True,
    )
    vlans = models.ManyToManyField(VlanIf,
                                   verbose_name=_("Available vlans"),
                                   blank=True)

    NETWORK_STATE_UNDEFINED = 0
    NETWORK_STATE_UP = 1
    NETWORK_STATE_UNREACHABLE = 2
    NETWORK_STATE_DOWN = 3
    NETWORK_STATES = (
        (NETWORK_STATE_UNDEFINED, _("Undefined")),
        (NETWORK_STATE_UP, _("Up")),
        (NETWORK_STATE_UNREACHABLE, _("Unreachable")),
        (NETWORK_STATE_DOWN, _("Down")),
    )
    status = models.PositiveSmallIntegerField(_("Status"),
                                              choices=NETWORK_STATES,
                                              default=NETWORK_STATE_UNDEFINED)

    is_noticeable = models.BooleanField(
        _("Send notify when monitoring state changed"), default=False)

    code = models.CharField(_("Code"),
                            max_length=64,
                            blank=True,
                            null=True,
                            default=None,
                            choices=_make_device_code_config_choices())

    sites = models.ManyToManyField(Site, blank=True)

    class Meta:
        db_table = "device"
        verbose_name = _("Device")
        verbose_name_plural = _("Devices")
        ordering = ("id", )
        permissions = [
            ("can_remove_from_olt", _("Can remove from OLT")),
            ("can_fix_onu", _("Can fix onu")),
            ("can_apply_onu_config", _("Can apply onu config")),
        ]

    def get_manager_klass(self):
        try:
            return next(klass for code, klass in DEVICE_TYPES
                        if code == safe_int(self.dev_type))
        except StopIteration:
            raise TypeError(
                "one of types is not subclass of BaseDeviceInterface. "
                "Or implementation of that device type is not found")

    def get_manager_object_switch(self) -> BaseSwitchInterface:
        man_klass = self.get_manager_klass()
        if self._cached_manager is None:
            self._cached_manager = man_klass(dev_instance=self,
                                             host=str(self.ip_address),
                                             snmp_community=str(
                                                 self.man_passw))
        return self._cached_manager

    def get_manager_object_olt(self) -> BasePONInterface:
        man_klass = self.get_manager_klass()
        if self._cached_manager is None:
            self._cached_manager = man_klass(dev_instance=self)
        return self._cached_manager

    def get_manager_object_onu(self) -> BasePON_ONU_Interface:
        man_klass = self.get_manager_klass()
        if self._cached_manager is None:
            self._cached_manager = man_klass(dev_instance=self)
        return self._cached_manager

    # Can attach device to customer in customer page
    def has_attachable_to_customer(self) -> bool:
        mngr = self.get_manager_klass()
        return mngr.has_attachable_to_customer

    def __str__(self):
        return "{} {}".format(self.ip_address or "", self.comment)

    def generate_config_template(self):
        mng = self.get_manager_object_switch()
        return mng.monitoring_template()

    def remove_from_olt(self):
        pdev = self.parent_dev
        if not pdev:
            raise DeviceConfigurationError(
                _("You should config parent OLT device for ONU"))
        if not pdev.extra_data:
            raise DeviceConfigurationError(
                _("You have not info in extra_data "
                  "field, please fill it in JSON"))
        mng = self.get_manager_object_olt()
        r = mng.remove_from_olt(dict(pdev.extra_data))
        if r:
            self.snmp_extra = None
            self.save(update_fields=["snmp_extra"])
        return r

    def onu_find_sn_by_mac(self) -> Tuple[Optional[int], Optional[str]]:
        parent = self.parent_dev
        if parent is not None:
            manager = parent.get_manager_object_olt()
            mac = self.mac_addr
            ports = manager.get_list_keyval(".1.3.6.1.4.1.3320.101.10.1.1.3")
            for srcmac, snmpnum in ports:
                # convert bytes mac address to str presentation mac address
                real_mac = macbin2str(srcmac)
                if mac == real_mac:
                    return safe_int(snmpnum), None
            return None, _('Onu with mac "%(onu_mac)s" not found on OLT') % {
                "onu_mac": mac
            }
        return None, _("Parent device not found")

    def fix_onu(self):
        onu_sn, err_text = self.onu_find_sn_by_mac()
        if onu_sn is not None:
            self.snmp_extra = str(onu_sn)
            self.save(update_fields=("snmp_extra", ))
            return True, _("Fixed")
        return False, err_text

    def get_if_name(self):
        mng = self.get_manager_object_olt()
        if hasattr(mng, "get_fiber_str"):
            return mng.get_fiber_str()
        return r"¯ \ _ (ツ) _ / ¯"

    def get_config_types(self) -> ListDeviceConfigType:
        mng_klass = self.get_manager_klass()
        return mng_klass.get_config_types()

    def apply_onu_config(self, config: dict) -> OptionalScriptCallResult:
        self.code = config.get("configTypeCode")
        self.save(update_fields=["code"])
        all_device_types = self.get_config_types()
        self_device_type_code = str(self.code)
        dtypes = (dtype for dtype in all_device_types
                  if dtype.short_code == self_device_type_code)
        dtype_for_run = next(dtypes, None)
        if dtype_for_run is not None:
            device_manager = dtype_for_run(title=dtype_for_run.title,
                                           code=dtype_for_run.short_code)
            return device_manager.entry_point(config=config, device=self)

    #############################
    #  Remote access(i.e. snmp)
    #############################

    def dev_get_all_vlan_list(self) -> Vlans:
        mng = self.get_manager_object_switch()
        return mng.read_all_vlan_info()

    def read_onu_vlan_info(self) -> Vlans:
        mng = self.get_manager_object_onu()
        return mng.read_onu_vlan_info()

    def default_vlan_info(self) -> Vlans:
        mng = self.get_manager_object_onu()
        return mng.default_vlan_info()

    def is_onu_registered(self) -> bool:
        return self.snmp_extra is not None

    # @_telnet_methods_wrapper
    # def dev_create_vlans(self, tln: BaseDeviceInterface, vids: Vlans) -> None:
    #     if not tln.create_vlans(vids):
    #         raise DeviceConsoleError(_('Failed while create vlans'))

    # @_telnet_methods_wrapper
    # def dev_delete_vlan(self, tln: BaseDeviceInterface, vids: Vlans) -> None:
    #     if not tln.delete_vlans(vlan_list=vids):
    #         raise DeviceConsoleError(_('Failed while removing vlan'))

    def dev_read_mac_address_vlan(self, vid: int) -> Macs:
        mng = self.get_manager_object_switch()
        return mng.read_mac_address_vlan(vid=vid)

    ##############################
    # Switch telnet methods
    ##############################

    # @_telnet_methods_wrapper
    # def telnet_switch_attach_vlan_to_port(self, tln: BaseSwitchInterface, vid: int,
    #                                       port: int, tag: bool = True) -> bool:
    #     return tln.attach_vlan_to_port(vid=vid, port=port, tag=tag)

    # @_telnet_methods_wrapper
    # def telnet_switch_detach_vlan_from_port(self, tln: BaseSwitchInterface, vid: int, port: int) -> bool:
    #     return tln.detach_vlan_from_port(vid=vid, port=port)

    def dev_switch_get_mac_address_port(self, device_port_num: int) -> Macs:
        mng = self.get_manager_object_switch()
        return mng.read_mac_address_port(port_num=device_port_num)
예제 #19
0
class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ("groupapp", "0001_initial"),
    ]

    operations = [
        migrations.CreateModel(
            name="Device",
            fields=[
                ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
                (
                    "ip_address",
                    models.GenericIPAddressField(blank=True, null=True, verbose_name="Ip address", default=None),
                ),
                ("mac_addr", MACAddressField(unique=True, verbose_name="Mac address")),
                ("comment", models.CharField(max_length=256, verbose_name="Comment")),
                (
                    "dev_type",
                    models.PositiveSmallIntegerField(
                        choices=[
                            (1, "DLink switch"),
                            (2, "PON OLT"),
                            (3, "PON ONU BDCOM"),
                            (4, "Eltex switch"),
                            (5, "OLT ZTE C320"),
                            (6, "Zte ONU F660"),
                            (7, "Zte ONU F601"),
                            (8, "Huawei switch"),
                        ],
                        default=1,
                        verbose_name="Device type",
                    ),
                ),
                ("man_passw", models.CharField(blank=True, max_length=16, null=True, verbose_name="SNMP password")),
                (
                    "snmp_extra",
                    models.CharField(blank=True, max_length=256, null=True, verbose_name="SNMP extra info"),
                ),
                (
                    "extra_data",
                    django.contrib.postgres.fields.jsonb.JSONField(
                        blank=True,
                        help_text="Extra data in JSON format. You may use it for your custom data",
                        null=True,
                        verbose_name="Extra data",
                    ),
                ),
                (
                    "status",
                    models.PositiveSmallIntegerField(
                        choices=[(0, "Undefined"), (1, "Up"), (2, "Unreachable"), (3, "Down")],
                        default=0,
                        verbose_name="Status",
                    ),
                ),
                (
                    "is_noticeable",
                    models.BooleanField(default=False, verbose_name="Send notify when monitoring state changed"),
                ),
                (
                    "group",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        to="groupapp.Group",
                        verbose_name="Device group",
                    ),
                ),
                (
                    "parent_dev",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        to="devices.Device",
                        verbose_name="Parent device",
                    ),
                ),
            ],
            options={
                "verbose_name": "Device",
                "verbose_name_plural": "Devices",
                "db_table": "device",
                "ordering": ("id",),
            },
        ),
        migrations.CreateModel(
            name="Port",
            fields=[
                ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
                ("num", models.PositiveSmallIntegerField(default=0, verbose_name="Number")),
                ("descr", models.CharField(blank=True, max_length=60, null=True, verbose_name="Description")),
                (
                    "device",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE, to="devices.Device", verbose_name="Device"
                    ),
                ),
            ],
            options={
                "verbose_name": "Port",
                "verbose_name_plural": "Ports",
                "db_table": "device_port",
                "ordering": ("num",),
                "permissions": (("can_toggle_ports", "Can toggle ports"),),
                "unique_together": {("device", "num")},
            },
        ),
    ]
예제 #20
0
class CustomerIpLeaseModel(models.Model):
    ip_address = models.GenericIPAddressField(_("Ip address"), unique=True)
    pool = models.ForeignKey(NetworkIpPool, on_delete=models.CASCADE)
    lease_time = models.DateTimeField(_("Lease time"), auto_now_add=True)
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, null=True)
    mac_address = MACAddressField(verbose_name=_("Mac address"), null=True, default=None)
    is_dynamic = models.BooleanField(_("Is synamic"), default=False)
    last_update = models.DateTimeField(_("Last update"), blank=True, null=True, default=None)

    objects = CustomerIpLeaseModelQuerySet.as_manager()

    def __str__(self):
        return f"{self.ip_address} [{self.mac_address}]"

    @staticmethod
    def find_customer_by_device_credentials(device_mac: str, device_port: int = 0) -> Optional[Customer]:
        with connection.cursor() as cur:
            cur.execute(
                "SELECT * FROM find_customer_by_device_credentials(%s::macaddr, %s::smallint)",
                (device_mac, device_port),
            )
            res = cur.fetchone()
        if res is None or res[0] is None:
            return None
        (
            baseaccount_id,
            balance,
            ip_addr,
            descr,
            house,
            is_dyn_ip,
            auto_renw_srv,
            markers,
            curr_srv_id,
            dev_port_id,
            dev_id,
            gw_id,
            grp_id,
            last_srv_id,
            street_id,
            *others,
        ) = res
        return Customer(
            pk=baseaccount_id,
            balance=balance,
            description=descr,
            house=house,
            is_dynamic_ip=is_dyn_ip,
            auto_renewal_service=auto_renw_srv,
            markers=markers,
            current_service_id=curr_srv_id,
            device_id=dev_id,
            dev_port_id=dev_port_id,
            gateway_id=gw_id,
            group_id=grp_id,
            last_connected_service_id=last_srv_id,
            street_id=street_id,
        )

    @staticmethod
    def get_service_permit_by_ip(ip_addr: str) -> bool:
        with connection.cursor() as cur:
            cur.execute("select * from find_service_permit(%s::inet)", [ip_addr])
            res = cur.fetchone()
        return res[0] if len(res) > 0 else False

    @process_lock()
    def ping_icmp(self, num_count=10, arp=False) -> bool:
        host_ip = str(self.ip_address)
        return icmp_ping(ip_addr=host_ip, count=num_count, arp=arp)

    @staticmethod
    def lease_commit_add_update(client_ip: str, mac_addr: str, dev_mac: str, dev_port: int):
        """
        When external system assign ip address for customer
        then it ip address may be store to billing via this method.
        :param client_ip: client ip address
        :param mac_addr: client mac address
        :param dev_mac: device mac address
        :param dev_port: device port number
        :return: str about result
        """
        dev_port = safe_int(dev_port)
        dev_port = dev_port if dev_port > 0 else None
        try:
            with connection.cursor() as cur:
                cur.execute(
                    "SELECT * FROM lease_commit_add_update" "(%s::inet, %s::macaddr, %s::macaddr, %s::smallint)",
                    (client_ip, mac_addr, dev_mac, dev_port),
                )
                res = cur.fetchone()
            # lease_id, ip_addr, pool_id, lease_time, mac_addr, customer_id, is_dynamic, last_update = res
            return res
        except InternalError as err:
            raise LogicError(str(err))

    class Meta:
        db_table = "networks_ip_leases"
        verbose_name = _("IP lease")
        verbose_name_plural = _("IP leases")
        unique_together = ("ip_address", "mac_address", "pool", "customer")
        ordering = ("id",)