Пример #1
0
    def render(self, session, dbuser, ip, netmask, prefixlen,
               network_environment, **arguments):
        if netmask:
            # There must me a faster way, but this is the easy one
            net = IPv4Network("127.0.0.0/%s" % netmask)
            prefixlen = net.prefixlen
        if prefixlen is None or prefixlen < 8 or prefixlen > 31:
            raise ArgumentError("The prefix length must be between 8 and 31.")

        dbnet_env = NetworkEnvironment.get_unique_or_default(
            session, network_environment)
        self.az.check_network_environment(dbuser, dbnet_env)

        dbnetwork = get_net_id_from_ip(session,
                                       ip,
                                       network_environment=dbnet_env)

        if prefixlen >= dbnetwork.cidr:
            raise ArgumentError("The specified --prefixlen must be smaller "
                                "than the current value.")

        # IPv4Network has a supernet() object, but that does not normalize the
        # IP address, i.e. IPv4Network('1.2.3.0/24').supernet() will return
        # IPv4Network('1.2.3.0/23'). Do the normalization manually.
        supernet = dbnetwork.network.supernet(new_prefix=prefixlen)
        supernet = IPv4Network("%s/%d" %
                               (supernet.network, supernet.prefixlen))

        q = session.query(Network)
        q = q.filter_by(network_environment=dbnet_env)
        q = q.filter(
            and_(Network.ip >= supernet.ip, Network.ip < supernet.broadcast))
        q = q.order_by(Network.ip)
        dbnets = q.all()

        if dbnets[0].ip == supernet.ip:
            dbsuper = dbnets.pop(0)
            dbsuper.cidr = prefixlen
        else:
            # Create a new network, copying the parameters from the one
            # specified on the command line
            dbsuper = Network(name=dbnetwork.name,
                              network=supernet,
                              network_environment=dbnet_env,
                              location=dbnetwork.location,
                              side=dbnetwork.side,
                              comments=dbnetwork.comments)
            session.add(dbsuper)

        for oldnet in dbnets:
            # Delete routers of the old subnets
            for dbrouter in oldnet.routers:
                map(delete_dns_record, dbrouter.dns_records)
            oldnet.routers = []

            fix_foreign_links(session, oldnet, dbsuper)
            session.delete(oldnet)

        session.flush()
Пример #2
0
    def render(self, session, dbuser,
               ip, netmask, prefixlen, network_environment, **arguments):
        if netmask:
            # There must me a faster way, but this is the easy one
            net = IPv4Network("127.0.0.0/%s" % netmask)
            prefixlen = net.prefixlen
        if prefixlen is None or prefixlen < 8 or prefixlen > 31:
            raise ArgumentError("The prefix length must be between 8 and 31.")

        dbnet_env = NetworkEnvironment.get_unique_or_default(session,
                                                             network_environment)
        self.az.check_network_environment(dbuser, dbnet_env)

        dbnetwork = get_net_id_from_ip(session, ip,
                                       network_environment=dbnet_env)

        if prefixlen >= dbnetwork.cidr:
            raise ArgumentError("The specified --prefixlen must be smaller "
                                "than the current value.")

        # IPv4Network has a supernet() object, but that does not normalize the
        # IP address, i.e. IPv4Network('1.2.3.0/24').supernet() will return
        # IPv4Network('1.2.3.0/23'). Do the normalization manually.
        supernet = dbnetwork.network.supernet(new_prefix=prefixlen)
        supernet = IPv4Network("%s/%d" % (supernet.network, supernet.prefixlen))

        q = session.query(Network)
        q = q.filter_by(network_environment=dbnet_env)
        q = q.filter(and_(Network.ip >= supernet.ip,
                          Network.ip < supernet.broadcast))
        q = q.order_by(Network.ip)
        dbnets = q.all()

        if dbnets[0].ip == supernet.ip:
            dbsuper = dbnets.pop(0)
            dbsuper.cidr = prefixlen
        else:
            # Create a new network, copying the parameters from the one
            # specified on the command line
            dbsuper = Network(name=dbnetwork.name, network=supernet,
                              network_environment=dbnet_env,
                              location=dbnetwork.location,
                              side=dbnetwork.side,
                              comments=dbnetwork.comments)
            session.add(dbsuper)

        for oldnet in dbnets:
            # Delete routers of the old subnets
            for dbrouter in oldnet.routers:
                map(delete_dns_record, dbrouter.dns_records)
            oldnet.routers = []

            fix_foreign_links(session, oldnet, dbsuper)
            session.delete(oldnet)

        session.flush()
Пример #3
0
 if orig_net == supernet:
     # Split:
     #  AQ:  ******** (one big network)
     #  QIP: --**++++ (smaller networks, some may be missing)
     if keep_aqnet:
         # The first subnet was handled above by setting
         # aqnet.cidr
         qipinfo = heap_pop(qipnets)
     else:
         # The first subnet was deleted
         pass
     while qipinfo and qipinfo.address.ip in orig_net:
         newnet = self.add_network(qipinfo)
         # Redirect addresses from the split network to the new
         # subnet
         fix_foreign_links(self.session, aqnet, newnet)
         qipinfo = heap_pop(qipnets)
     if keep_aqnet:
         self.check_split_network(aqnet)
     else:
         self.del_network(aqnet)
     aqnet = heap_pop(aqnets)
 else:
     # Merge:
     #  AQ:  --++**** (smaller networks, some may be missing)
     #  QIP: ******** (one big network)
     if keep_aqnet:
         # The first subnet was handled above by setting
         # aqnet.cidr
         newnet = aqnet
         aqnet = heap_pop(aqnets)
Пример #4
0
    def render(self, session, dbuser,
               ip, netmask, prefixlen, network_environment, **arguments):
        if netmask:
            # There must me a faster way, but this is the easy one
            net = IPv4Network("127.0.0.0/%s" % netmask)
            prefixlen = net.prefixlen
        if prefixlen < 8 or prefixlen > 32:
            raise ArgumentError("The prefix length must be between 8 and 32.")

        dbnet_env = NetworkEnvironment.get_unique_or_default(session,
                                                             network_environment)
        self.az.check_network_environment(dbuser, dbnet_env)

        dbnetwork = get_net_id_from_ip(session, ip,
                                       network_environment=dbnet_env)

        if prefixlen <= dbnetwork.cidr:
            raise ArgumentError("The specified --prefixlen must be bigger "
                                "than the current value.")

        subnets = dbnetwork.network.subnet(new_prefix=prefixlen)

        # Collect IP addresses that will become network/broadcast addresses
        # after the split
        bad_ips = []
        for subnet in subnets:
            bad_ips.append(subnet.ip)
            bad_ips.append(subnet.broadcast)

        q = session.query(AddressAssignment.ip)
        q = q.filter_by(network=dbnetwork)
        q = q.filter(AddressAssignment.ip.in_(bad_ips))
        used_addrs = q.all()
        if used_addrs:
            raise ArgumentError("Network split failed, because the following "
                                "subnet IP and/or broadcast addresses are "
                                "assigned to hosts: %s" %
                                ", ".join([str(addr.ip) for addr in
                                           used_addrs]))

        q = session.query(ARecord.ip)
        q = q.filter_by(network=dbnetwork)
        q = q.filter(ARecord.ip.in_(bad_ips))
        used_addrs = q.all()
        if used_addrs:
            raise ArgumentError("Network split failed, because the following "
                                "subnet IP and/or broadcast addresses are "
                                "registered in the DNS: %s" %
                                ", ".join([str(addr.ip) for addr in
                                           used_addrs]))

        # Reason of the initial value: we keep the name of the first segment
        # (e.g.  "foo"), and the next segment will be called "foo_2"
        name_idx = 2

        dbnets = []
        for subnet in dbnetwork.network.subnet(new_prefix=prefixlen):
            # Skip the original
            if subnet.ip == dbnetwork.ip:
                continue

            # Generate a new name. Make it unique, even if the DB does not
            # enforce that currently
            while True:
                # TODO: check if the new name is too long
                name = "%s_%d" % (dbnetwork.name, name_idx)
                name_idx += 1
                q = session.query(Network)
                q = q.filter_by(network_environment=dbnet_env)
                q = q.filter_by(name=name)
                if q.count() == 0:
                    break

                # Should not happen...
                if name_idx > 1000:  # pragma: no cover
                    raise AquilonError("Could not generate a unique network "
                                       "name in a reasonable time, bailing out")

            # Inherit location & side from the supernet
            newnet = Network(name=name, network=subnet,
                             network_environment=dbnet_env,
                             location=dbnetwork.location, side=dbnetwork.side,
                             comments="Created by splitting {0:a}".format(dbnetwork))
            session.add(newnet)
            dbnets.append(newnet)

        dbnetwork.cidr = prefixlen
        session.flush()

        for newnet in dbnets:
            fix_foreign_links(session, dbnetwork, newnet)

        session.flush()
Пример #5
0
 if orig_net == supernet:
     # Split:
     #  AQ:  ******** (one big network)
     #  QIP: --**++++ (smaller networks, some may be missing)
     if keep_aqnet:
         # The first subnet was handled above by setting
         # aqnet.cidr
         qipinfo = heap_pop(qipnets)
     else:
         # The first subnet was deleted
         pass
     while qipinfo and qipinfo.address.ip in orig_net:
         newnet = self.add_network(qipinfo)
         # Redirect addresses from the split network to the new
         # subnet
         fix_foreign_links(self.session, aqnet, newnet)
         qipinfo = heap_pop(qipnets)
     if keep_aqnet:
         self.check_split_network(aqnet)
     else:
         self.del_network(aqnet)
     aqnet = heap_pop(aqnets)
 else:
     # Merge:
     #  AQ:  --++**** (smaller networks, some may be missing)
     #  QIP: ******** (one big network)
     if keep_aqnet:
         # The first subnet was handled above by setting
         # aqnet.cidr
         newnet = aqnet
         aqnet = heap_pop(aqnets)
Пример #6
0
    def render(self, session, dbuser, ip, netmask, prefixlen,
               network_environment, **arguments):
        if netmask:
            # There must me a faster way, but this is the easy one
            net = IPv4Network("127.0.0.0/%s" % netmask)
            prefixlen = net.prefixlen
        if prefixlen < 8 or prefixlen > 32:
            raise ArgumentError("The prefix length must be between 8 and 32.")

        dbnet_env = NetworkEnvironment.get_unique_or_default(
            session, network_environment)
        self.az.check_network_environment(dbuser, dbnet_env)

        dbnetwork = get_net_id_from_ip(session,
                                       ip,
                                       network_environment=dbnet_env)

        if prefixlen <= dbnetwork.cidr:
            raise ArgumentError("The specified --prefixlen must be bigger "
                                "than the current value.")

        subnets = dbnetwork.network.subnet(new_prefix=prefixlen)

        # Collect IP addresses that will become network/broadcast addresses
        # after the split
        bad_ips = []
        for subnet in subnets:
            bad_ips.append(subnet.ip)
            bad_ips.append(subnet.broadcast)

        q = session.query(AddressAssignment.ip)
        q = q.filter_by(network=dbnetwork)
        q = q.filter(AddressAssignment.ip.in_(bad_ips))
        used_addrs = q.all()
        if used_addrs:
            raise ArgumentError(
                "Network split failed, because the following "
                "subnet IP and/or broadcast addresses are "
                "assigned to hosts: %s" %
                ", ".join([str(addr.ip) for addr in used_addrs]))

        q = session.query(ARecord.ip)
        q = q.filter_by(network=dbnetwork)
        q = q.filter(ARecord.ip.in_(bad_ips))
        used_addrs = q.all()
        if used_addrs:
            raise ArgumentError(
                "Network split failed, because the following "
                "subnet IP and/or broadcast addresses are "
                "registered in the DNS: %s" %
                ", ".join([str(addr.ip) for addr in used_addrs]))

        # Reason of the initial value: we keep the name of the first segment
        # (e.g.  "foo"), and the next segment will be called "foo_2"
        name_idx = 2

        dbnets = []
        for subnet in dbnetwork.network.subnet(new_prefix=prefixlen):
            # Skip the original
            if subnet.ip == dbnetwork.ip:
                continue

            # Generate a new name. Make it unique, even if the DB does not
            # enforce that currently
            while True:
                # TODO: check if the new name is too long
                name = "%s_%d" % (dbnetwork.name, name_idx)
                name_idx += 1
                q = session.query(Network)
                q = q.filter_by(network_environment=dbnet_env)
                q = q.filter_by(name=name)
                if q.count() == 0:
                    break

                # Should not happen...
                if name_idx > 1000:  # pragma: no cover
                    raise AquilonError(
                        "Could not generate a unique network "
                        "name in a reasonable time, bailing out")

            # Inherit location & side from the supernet
            newnet = Network(
                name=name,
                network=subnet,
                network_environment=dbnet_env,
                location=dbnetwork.location,
                side=dbnetwork.side,
                comments="Created by splitting {0:a}".format(dbnetwork))
            session.add(newnet)
            dbnets.append(newnet)

        dbnetwork.cidr = prefixlen
        session.flush()

        for newnet in dbnets:
            fix_foreign_links(session, dbnetwork, newnet)

        session.flush()