예제 #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 add_network(self, qipinfo):
     dbnetwork = Network(name=qipinfo.name,
                         network=qipinfo.address,
                         network_type=qipinfo.network_type,
                         side=qipinfo.side,
                         location=qipinfo.location,
                         network_environment=self.net_env)
     self.session.add(dbnetwork)
     self.logger.client_info("Adding network {0:a}".format(dbnetwork))
     for ip in qipinfo.routers:
         self.add_router(dbnetwork, ip)
     self.session.flush()
     return dbnetwork
예제 #3
0
def setup():
    dmn = DnsDomain(name=DNS_DOMAIN_NAME)
    create(sess, dmn)
    assert dmn, 'no dns domain in %s' % func_name()

    pi = Building.get_unique(sess, name='pi', compel=True)

    n = IPv4Network(TEST_NET)
    net = Network(name=TEST_NET_NAME, network=n, location=pi)
    create(sess, net)
    assert net, 'no network created by %s' % func_name()

    ip = IPv4Address(TEST_IP)
    arec = ARecord(name=AREC_NAME, dns_domain=dmn, ip=ip, network=net)
    create(sess, arec)
    assert arec, 'no ARecord created by %s' % func_name()
예제 #4
0
        dbnetwork = q.first()
        if dbnetwork:
            logger.client_info("WARNING: Network name %s is already used for "
                               "address %s." %
                               (network, str(dbnetwork.network)))

        # Check if the address is free
        try:
            dbnetwork = get_net_id_from_ip(session,
                                           address.ip,
                                           network_environment=dbnet_env)
            raise ArgumentError(
                "IP address %s is part of existing network "
                "named %s with address %s." %
                (str(address.ip), dbnetwork.name, str(dbnetwork.network)))
        except NotFoundException:
            pass

        # Okay, all looks good, let's create the network
        net = Network(name=network,
                      network=address,
                      network_environment=dbnet_env,
                      network_type=type,
                      side=side,
                      location=location,
                      comments=comments)

        session.add(net)
        session.flush()
        return
예제 #5
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()