Пример #1
0
    def clean_alias_v4netmaskbit(self):
        vip = self.cleaned_data.get("alias_vip")
        ip = self.cleaned_data.get("alias_v4address")
        nw = self.cleaned_data.get("alias_v4netmaskbit")
        if not nw or not ip:
            return nw
        network = IPNetwork("%s/%s" % (ip, nw))

        if vip:
            if not network.overlaps(IPNetwork("%s/%s" % (vip, nw))):
                raise forms.ValidationError(_("Virtual IP is not in the same network"))

        if self.instance.id and self.instance.alias_interface.int_interface.startswith("carp"):
            return nw
        used_networks = []
        qs = models.Interfaces.objects.all().exclude(int_interface__startswith="carp")
        if self.instance.id:
            qs = qs.exclude(id=self.instance.alias_interface.id)
        elif self.parent.instance.id:
            qs = qs.exclude(id=self.parent.instance.id)
        for iface in qs:
            if iface.int_v4netmaskbit:
                used_networks.append(IPNetwork("%s/%s" % (iface.int_ipv4address, iface.int_v4netmaskbit)))
            for alias in iface.alias_set.all():
                if alias.alias_v4netmaskbit:
                    used_networks.append(IPNetwork("%s/%s" % (alias.alias_v4address, alias.alias_v4netmaskbit)))

        for unet in used_networks:
            if unet.overlaps(network):
                raise forms.ValidationError(_("The network %s is already in use by another NIC.") % (network.masked(),))
        return nw
Пример #2
0
    def clean(self):
        cdata = self.cleaned_data

        ipv4key = 'int_ipv4address'
        ipv4addr = cdata.get(ipv4key)
        ipv4addr_b = cdata.get('int_ipv4address_b')
        ipv4net = cdata.get("int_v4netmaskbit")

        if ipv4addr and ipv4addr_b and ipv4net:
            network = IPNetwork('%s/%s' % (ipv4addr, ipv4net))
            if not network.overlaps(
                IPNetwork('%s/%s' % (ipv4addr_b, ipv4net))
            ):
                self._errors['int_ipv4address_b'] = self.error_class([
                    _('The IP must be within the same network')
                ])

        ipv6addr = cdata.get("int_ipv6address")
        ipv6net = cdata.get("int_v6netmaskbit")
        ipv4 = True if ipv4addr and ipv4net else False
        ipv6 = True if ipv6addr and ipv6net else False

        # IF one field of ipv4 is entered, require the another
        if (ipv4addr or ipv4net) and not ipv4:
            if not (ipv4addr or ipv4addr_b) and not self._errors.get(ipv4key):
                self._errors[ipv4key] = self.error_class([
                    _("You have to specify IPv4 address as well"),
                ])
            if not ipv4net and 'int_v4netmaskbit' not in self._errors:
                self._errors['int_v4netmaskbit'] = self.error_class([
                    _("You have to choose IPv4 netmask as well"),
                ])

        # IF one field of ipv6 is entered, require the another
        if (ipv6addr or ipv6net) and not ipv6:
            if not ipv6addr and not self._errors.get('int_ipv6address'):
                self._errors['int_ipv6address'] = self.error_class([
                    _("You have to specify IPv6 address as well"),
                ])
            if not ipv6net:
                self._errors['int_v6netmaskbit'] = self.error_class([
                    _("You have to choose IPv6 netmask as well"),
                ])

        if ipv6 and ipv4:
            self._errors['__all__'] = self.error_class([
                _("You have to choose between IPv4 or IPv6"),
            ])

        vip = cdata.get("int_vip")
        if vip and not ipv4addr_b:
            self._errors['int_ipv4address_b'] = self.error_class([
                _("This field is required for failover")
            ])
        if vip and not ipv4addr:
            self._errors['int_ipv4address'] = self.error_class([
                _("This field is required for failover")
            ])

        return cdata
Пример #3
0
    def clean(self):
        cdata = self.cleaned_data

        ipv4vip = cdata.get("alias_vip")
        ipv4addr = cdata.get("alias_v4address")
        ipv4net = cdata.get("alias_v4netmaskbit")
        ipv6addr = cdata.get("alias_v6address")
        ipv6net = cdata.get("alias_v6netmaskbit")
        ipv4 = True if ipv4addr and ipv4net else False
        ipv6 = True if ipv6addr and ipv6net else False

        # IF one field of ipv4 is entered, require the another
        if (ipv4addr or ipv4net) and not ipv4:
            if not ipv4addr and not self._errors.get('alias_v4address'):
                self._errors['alias_v4address'] = self.error_class([
                    _("You have to specify IPv4 address as well per alias"),
                ])
            if not ipv4net and 'alias_v4netmaskbit' not in self._errors:
                self._errors['alias_v4netmaskbit'] = self.error_class([
                    _("You have to choose IPv4 netmask as well per alias"),
                ])

        # IF one field of ipv6 is entered, require the another
        if (ipv6addr or ipv6net) and not ipv6:
            if not ipv6addr and not self._errors.get('alias_v6address'):
                self._errors['alias_v6address'] = self.error_class([
                    _("You have to specify IPv6 address as well per alias"),
                ])
            if not ipv6net:
                self._errors['alias_v6netmaskbit'] = self.error_class([
                    _("You have to choose IPv6 netmask as well per alias"),
                ])

        if ipv6 and ipv4:
            self._errors['__all__'] = self.error_class([
                _("You have to choose between IPv4 or IPv6 per alias"),
            ])

        configured_vip = False
        if ipv4vip and hasattr(self, 'parent'):
            iface = self.parent.instance
            ip = IPNetwork('%s/32' % ipv4vip)
            network = IPNetwork('%s/%s' % (
                iface.int_ipv4address,
                iface.int_v4netmaskbit,
            ))
            if ip.overlaps(network):
                configured_vip = True

        if (
            not configured_vip and not ipv6 and not (ipv6addr or ipv6net) and
            not ipv4 and not (ipv4addr or ipv4net)
        ):
            self._errors['__all__'] = self.error_class([
                _("You must specify either an valid IPv4 or IPv6 with maskbit "
                    "per alias"),
            ])

        return cdata
Пример #4
0
    def clean(self):
        cdata = self.cleaned_data

        ipv4vip = cdata.get("alias_vip")
        ipv4addr = cdata.get("alias_v4address")
        ipv4net = cdata.get("alias_v4netmaskbit")
        ipv6addr = cdata.get("alias_v6address")
        ipv6net = cdata.get("alias_v6netmaskbit")
        ipv4 = True if ipv4addr and ipv4net else False
        ipv6 = True if ipv6addr and ipv6net else False

        # IF one field of ipv4 is entered, require the another
        if (ipv4addr or ipv4net) and not ipv4:
            if not ipv4addr and not self._errors.get('alias_v4address'):
                self._errors['alias_v4address'] = self.error_class([
                    _("You have to specify IPv4 address as well per alias"),
                ])
            if not ipv4net and 'alias_v4netmaskbit' not in self._errors:
                self._errors['alias_v4netmaskbit'] = self.error_class([
                    _("You have to choose IPv4 netmask as well per alias"),
                ])

        # IF one field of ipv6 is entered, require the another
        if (ipv6addr or ipv6net) and not ipv6:
            if not ipv6addr and not self._errors.get('alias_v6address'):
                self._errors['alias_v6address'] = self.error_class([
                    _("You have to specify IPv6 address as well per alias"),
                ])
            if not ipv6net:
                self._errors['alias_v6netmaskbit'] = self.error_class([
                    _("You have to choose IPv6 netmask as well per alias"),
                ])

        if ipv6 and ipv4:
            self._errors['__all__'] = self.error_class([
                _("You have to choose between IPv4 or IPv6 per alias"),
            ])

        configured_vip = False
        if ipv4vip and hasattr(self, 'parent'):
            iface = self.parent.instance
            ip = IPNetwork('%s/32' % ipv4vip)
            network = IPNetwork('%s/%s' % (
                iface.int_ipv4address,
                iface.int_v4netmaskbit,
            ))
            if ip.overlaps(network):
                configured_vip = True

        if (
            not configured_vip and not ipv6 and not (ipv6addr or ipv6net) and
            not ipv4 and not (ipv4addr or ipv4net)
        ):
            self._errors['__all__'] = self.error_class([
                _("You must specify either an valid IPv4 or IPv6 with maskbit "
                    "per alias"),
            ])

        return cdata
Пример #5
0
    def clean(self):
        cdata = self.cleaned_data

        ipv4key = 'int_ipv4address'
        ipv4addr = cdata.get(ipv4key)
        ipv4addr_b = cdata.get('int_ipv4address_b')
        ipv4net = cdata.get("int_v4netmaskbit")

        if ipv4addr and ipv4addr_b and ipv4net:
            network = IPNetwork('%s/%s' % (ipv4addr, ipv4net))
            if not network.overlaps(IPNetwork('%s/%s' %
                                              (ipv4addr_b, ipv4net))):
                self._errors['int_ipv4address_b'] = self.error_class(
                    [_('The IP must be within the same network')])

        ipv6addr = cdata.get("int_ipv6address")
        ipv6net = cdata.get("int_v6netmaskbit")
        ipv4 = True if ipv4addr and ipv4net else False
        ipv6 = True if ipv6addr and ipv6net else False

        # IF one field of ipv4 is entered, require the another
        if (ipv4addr or ipv4net) and not ipv4:
            if not (ipv4addr or ipv4addr_b) and not self._errors.get(ipv4key):
                self._errors[ipv4key] = self.error_class([
                    _("You have to specify IPv4 address as well"),
                ])
            if not ipv4net and 'int_v4netmaskbit' not in self._errors:
                self._errors['int_v4netmaskbit'] = self.error_class([
                    _("You have to choose IPv4 netmask as well"),
                ])

        # IF one field of ipv6 is entered, require the another
        if (ipv6addr or ipv6net) and not ipv6:
            if not ipv6addr and not self._errors.get('int_ipv6address'):
                self._errors['int_ipv6address'] = self.error_class([
                    _("You have to specify IPv6 address as well"),
                ])
            if not ipv6net:
                self._errors['int_v6netmaskbit'] = self.error_class([
                    _("You have to choose IPv6 netmask as well"),
                ])

        if ipv6 and ipv4:
            self._errors['__all__'] = self.error_class([
                _("You have to choose between IPv4 or IPv6"),
            ])

        vip = cdata.get("int_vip")
        dhcp = cdata.get("int_dhcp")
        if not dhcp:
            if vip and not ipv4addr_b:
                self._errors['int_ipv4address_b'] = self.error_class(
                    [_("This field is required for failover")])
            if vip and not ipv4addr:
                self._errors['int_ipv4address'] = self.error_class(
                    [_("This field is required for failover")])

        return cdata
Пример #6
0
    def clean(self):
        cdata = self.cleaned_data

        _n = notifier()
        if not _n.is_freenas() and _n.failover_licensed():
            from freenasUI.failover.models import Failover

            try:
                if Failover.objects.all()[0].disabled is False:
                    self._errors["__all__"] = self.error_class(
                        [_("Failover needs to be disabled to perform network " "changes.")]
                    )
            except:
                log.warn("Failed to verify failover status", exc_info=True)

        ipv4key = "int_ipv4address"
        ipv4addr = cdata.get(ipv4key)
        ipv4addr_b = cdata.get("int_ipv4address_b")
        ipv4net = cdata.get("int_v4netmaskbit")

        if ipv4addr and ipv4addr_b and ipv4net:
            network = IPNetwork("%s/%s" % (ipv4addr, ipv4net))
            if not network.overlaps(IPNetwork("%s/%s" % (ipv4addr_b, ipv4net))):
                self._errors["int_ipv4address_b"] = self.error_class([_("The IP must be within the same network")])

        ipv6addr = cdata.get("int_ipv6address")
        ipv6net = cdata.get("int_v6netmaskbit")
        ipv4 = True if ipv4addr and ipv4net else False
        ipv6 = True if ipv6addr and ipv6net else False

        # IF one field of ipv4 is entered, require the another
        if (ipv4addr or ipv4net) and not ipv4:
            if not (ipv4addr or ipv4addr_b) and not self._errors.get(ipv4key):
                self._errors[ipv4key] = self.error_class([_("You have to specify IPv4 address as well")])
            if not ipv4net and "int_v4netmaskbit" not in self._errors:
                self._errors["int_v4netmaskbit"] = self.error_class([_("You have to choose IPv4 netmask as well")])

        # IF one field of ipv6 is entered, require the another
        if (ipv6addr or ipv6net) and not ipv6:
            if not ipv6addr and not self._errors.get("int_ipv6address"):
                self._errors["int_ipv6address"] = self.error_class([_("You have to specify IPv6 address as well")])
            if not ipv6net:
                self._errors["int_v6netmaskbit"] = self.error_class([_("You have to choose IPv6 netmask as well")])

        if ipv6 and ipv4:
            self._errors["__all__"] = self.error_class([_("You have to choose between IPv4 or IPv6")])

        vip = cdata.get("int_vip")
        dhcp = cdata.get("int_dhcp")
        if not dhcp:
            if vip and not ipv4addr_b:
                self._errors["int_ipv4address_b"] = self.error_class([_("This field is required for failover")])
            if vip and not ipv4addr:
                self._errors["int_ipv4address"] = self.error_class([_("This field is required for failover")])

        return cdata
Пример #7
0
    def clean_alias_v4netmaskbit(self):
        vip = self.cleaned_data.get("alias_vip")
        ip = self.cleaned_data.get("alias_v4address")
        nw = self.cleaned_data.get("alias_v4netmaskbit")
        if not nw or not ip:
            return nw
        network = IPNetwork('%s/%s' % (ip, nw))

        if vip:
            if not network.overlaps(IPNetwork('%s/%s' % (vip, nw))):
                raise forms.ValidationError(_(
                    'Virtual IP is not in the same network'
                ))

        if (
            self.instance.id and
            self.instance.alias_interface.int_interface.startswith('carp')
        ):
            return nw
        used_networks = []
        qs = models.Interfaces.objects.all().exclude(
            int_interface__startswith='carp'
        )
        if self.instance.id:
            qs = qs.exclude(id=self.instance.alias_interface.id)
        elif self.parent.instance.id:
            qs = qs.exclude(id=self.parent.instance.id)
        for iface in qs:
            if iface.int_v4netmaskbit:
                used_networks.append(
                    IPNetwork('%s/%s' % (
                        iface.int_ipv4address,
                        iface.int_v4netmaskbit,
                    ))
                )
            for alias in iface.alias_set.all():
                if alias.alias_v4netmaskbit:
                    used_networks.append(
                        IPNetwork('%s/%s' % (
                            alias.alias_v4address,
                            alias.alias_v4netmaskbit,
                        ))
                    )

        for unet in used_networks:
            if unet.overlaps(network):
                raise forms.ValidationError(
                    _("The network %s is already in use by another NIC.") % (
                        network.masked(),
                    )
                )
        return nw
Пример #8
0
 def clean_nfs_network(self):
     net = self.cleaned_data['nfs_network']
     net = re.sub(r'\s{2,}|\n', ' ', net).strip()
     if not net:
         return net
     seen_networks = []
     for n in net.split(' '):
         try:
             netobj = IPNetwork(n)
             if n.find("/") == -1:
                 raise ValueError(n)
             for i in seen_networks:
                 if netobj.overlaps(i):
                     raise forms.ValidationError(
                         _('The following networks overlap: %(net1)s - %(net2)s'
                           ) % {
                               'net1': netobj,
                               'net2': i,
                           })
             seen_networks.append(netobj)
         except (AddressValueError, NetmaskValueError, ValueError):
             raise forms.ValidationError(
                 _("This is not a valid network: %s") % n)
     return net
Пример #9
0
    def clean(self):
        cdata = self.cleaned_data

        _n = notifier()
        if (
            not _n.is_freenas() and _n.failover_licensed() and
            _n.failover_status() != 'SINGLE' and (
                self.instance.id and self.instance.int_vip
            )
        ):
            from freenasUI.failover.models import Failover
            try:
                if Failover.objects.all()[0].disabled is False:
                    self._errors['__all__'] = self.error_class([_(
                        'Failover needs to be disabled to perform network '
                        'changes.'
                    )])
            except:
                log.warn('Failed to verify failover status', exc_info=True)

        ipv4key = 'int_ipv4address'
        ipv4addr = cdata.get(ipv4key)
        ipv4addr_b = cdata.get('int_ipv4address_b')
        ipv4net = cdata.get("int_v4netmaskbit")

        if ipv4addr and ipv4addr_b and ipv4net:
            network = IPNetwork('%s/%s' % (ipv4addr, ipv4net))
            if not network.overlaps(
                IPNetwork('%s/%s' % (ipv4addr_b, ipv4net))
            ):
                self._errors['int_ipv4address_b'] = self.error_class([
                    _('The IP must be within the same network')
                ])

        ipv6addr = cdata.get("int_ipv6address")
        ipv6net = cdata.get("int_v6netmaskbit")
        ipv4 = True if ipv4addr and ipv4net else False
        ipv6 = True if ipv6addr and ipv6net else False

        # IF one field of ipv4 is entered, require the another
        if (ipv4addr or ipv4net) and not ipv4:
            if not (ipv4addr or ipv4addr_b) and not self._errors.get(ipv4key):
                self._errors[ipv4key] = self.error_class([
                    _("You have to specify IPv4 address as well"),
                ])
            if not ipv4net and 'int_v4netmaskbit' not in self._errors:
                self._errors['int_v4netmaskbit'] = self.error_class([
                    _("You have to choose IPv4 netmask as well"),
                ])

        # IF one field of ipv6 is entered, require the another
        if (ipv6addr or ipv6net) and not ipv6:
            if not ipv6addr and not self._errors.get('int_ipv6address'):
                self._errors['int_ipv6address'] = self.error_class([
                    _("You have to specify IPv6 address as well"),
                ])
            if not ipv6net:
                self._errors['int_v6netmaskbit'] = self.error_class([
                    _("You have to choose IPv6 netmask as well"),
                ])

        vip = cdata.get("int_vip")
        dhcp = cdata.get("int_dhcp")
        if not dhcp:
            if vip and not ipv4addr_b:
                self._errors['int_ipv4address_b'] = self.error_class([
                    _("This field is required for failover")
                ])
            if vip and not ipv4addr:
                self._errors['int_ipv4address'] = self.error_class([
                    _("This field is required for failover")
                ])

        return cdata
Пример #10
0
    def cleanformset_nfs_share_path(self, formset, forms):
        dev = None
        valid = True
        ismp = False
        for form in forms:
            if not hasattr(form, "cleaned_data"):
                continue
            path = form.cleaned_data.get("path")
            if not path:
                continue
            parent = os.path.join(path, "..")
            try:
                stat = os.stat(path.encode("utf8"))
                if dev is None:
                    dev = stat.st_dev
                elif dev != stat.st_dev:
                    self._fserrors = self.error_class([
                        _("Paths for a NFS share must reside within the same "
                          "filesystem")
                    ])
                    valid = False
                    break
                if os.stat(parent.encode("utf8")).st_dev != stat.st_dev:
                    ismp = True
                if ismp and len(forms) > 1:
                    self._fserrors = self.error_class([
                        _("You cannot share a mount point and subdirectories "
                          "all at once")
                    ])
                    valid = False
                    break

            except OSError:
                pass

        if not ismp and self.cleaned_data.get('nfs_alldirs'):
            self._errors['nfs_alldirs'] = self.error_class(
                [_("This option can only be used for datasets.")])
            valid = False

        networks = self.cleaned_data.get("nfs_network", "")
        if not networks:
            networks = ['0.0.0.0/0']
        else:
            networks = networks.split(" ")

        qs = models.NFS_Share.objects.all()
        if self.instance.id:
            qs = qs.exclude(id=self.instance.id)

        used_networks = []
        for share in qs:
            try:
                stdev = os.stat(
                    share.paths.all()[0].path.encode("utf8")).st_dev
            except:
                continue
            if share.nfs_network:
                used_networks.extend([(y, stdev)
                                      for y in share.nfs_network.split(" ")])
            else:
                used_networks.append(('0.0.0.0/0', stdev))
            if (self.cleaned_data.get("nfs_alldirs") and share.nfs_alldirs
                    and stdev == dev):
                self._errors['nfs_alldirs'] = self.error_class(
                    [_("This option is only available once per mountpoint")])
                valid = False
                break

        for network in networks:
            networkobj = IPNetwork(network)
            for unetwork, ustdev in used_networks:
                try:
                    unetworkobj = IPNetwork(unetwork)
                except Exception:
                    # If for some reason other values in db are not valid networks
                    unetworkobj = IPNetwork('0.0.0.0/0')
                if networkobj.overlaps(unetworkobj) and dev == ustdev:
                    self._errors['nfs_network'] = self.error_class([
                        _("The network %s is already being shared and cannot "
                          "be used twice for the same filesystem") %
                        (network, )
                    ])
                    valid = False
                    break

        return valid
Пример #11
0
    def clean(self):
        cdata = self.cleaned_data

        _n = notifier()
        if (
            not _n.is_freenas() and _n.failover_licensed() and
            _n.failover_status() != 'SINGLE' and (
                self.instance.id and self.instance.int_vip
            )
        ):
            from freenasUI.failover.models import Failover
            try:
                if Failover.objects.all()[0].disabled is False:
                    self._errors['__all__'] = self.error_class([_(
                        'Failover needs to be disabled to perform network '
                        'changes.'
                    )])
            except:
                log.warn('Failed to verify failover status', exc_info=True)

        ipv4key = 'int_ipv4address'
        ipv4addr = cdata.get(ipv4key)
        ipv4addr_b = cdata.get('int_ipv4address_b')
        ipv4net = cdata.get("int_v4netmaskbit")

        if ipv4addr and ipv4addr_b and ipv4net:
            network = IPNetwork('%s/%s' % (ipv4addr, ipv4net))
            if not network.overlaps(
                IPNetwork('%s/%s' % (ipv4addr_b, ipv4net))
            ):
                self._errors['int_ipv4address_b'] = self.error_class([
                    _('The IP must be within the same network')
                ])

        ipv6addr = cdata.get("int_ipv6address")
        ipv6net = cdata.get("int_v6netmaskbit")
        ipv4 = True if ipv4addr and ipv4net else False
        ipv6 = True if ipv6addr and ipv6net else False

        # IF one field of ipv4 is entered, require the another
        if (ipv4addr or ipv4net) and not ipv4:
            if not (ipv4addr or ipv4addr_b) and not self._errors.get(ipv4key):
                self._errors[ipv4key] = self.error_class([
                    _("You have to specify IPv4 address as well"),
                ])
            if not ipv4net and 'int_v4netmaskbit' not in self._errors:
                self._errors['int_v4netmaskbit'] = self.error_class([
                    _("You have to choose IPv4 netmask as well"),
                ])

        # IF one field of ipv6 is entered, require the another
        if (ipv6addr or ipv6net) and not ipv6:
            if not ipv6addr and not self._errors.get('int_ipv6address'):
                self._errors['int_ipv6address'] = self.error_class([
                    _("You have to specify IPv6 address as well"),
                ])
            if not ipv6net:
                self._errors['int_v6netmaskbit'] = self.error_class([
                    _("You have to choose IPv6 netmask as well"),
                ])

        vip = cdata.get("int_vip")
        dhcp = cdata.get("int_dhcp")
        if not dhcp:
            if vip and not ipv4addr_b:
                self._errors['int_ipv4address_b'] = self.error_class([
                    _("This field is required for failover")
                ])
            if vip and not ipv4addr:
                self._errors['int_ipv4address'] = self.error_class([
                    _("This field is required for failover")
                ])
        else:
            cdata['int_ipv4address'] = ''
            cdata['int_v4netmaskbit'] = ''

        # API backward compatibility
        options = cdata.get('int_options')
        if options:
            reg = RE_MTU.search(options)
            if reg:
                cdata['int_mtu'] = int(reg.group(1))
                cdata['int_options'] = options.replace(reg.group(0), '')

        return cdata