def __init__(self, arg='127.0.0.1/32', strict=False): #RGX_IPV4ADDR = re.compile(r'^(\d+\.\d+\.\d+\.\d+)') #RGX_IPV4ADDR_NETMASK = re.compile(r'(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)') arg = _RGX_IPV4ADDR_NETMASK.sub(r'\1/\2', arg) # mangle IOS: 'addr mask' self.arg = arg mm = _RGX_IPV4ADDR.search(arg) assert (not (mm is None)), "IPv4Obj couldn't parse {0}".format(arg) self.network_object = IPv4Network(arg, strict=strict) self.ip_object = IPv4Address(mm.group(1))
def testIPv4Obj_attributes(self): ## Ensure that attributes are accessible and pass the smell test test_object = IPv4Obj('1.0.0.1 255.255.255.0') results_correct = [ ('ip', IPv4Address('1.0.0.1')), ('netmask', IPv4Address('255.255.255.0')), ('prefixlen', 24), ('broadcast', IPv4Address('1.0.0.255')), ('network', IPv4Network('1.0.0.0/24')), ('hostmask', IPv4Address('0.0.0.255')), ('numhosts', 256), ('version', 4), ('is_reserved', False), ('is_multicast', False), ('is_private', False), ('as_decimal', 16777217), ('as_hex_tuple', ('01', '00', '00', '01')), ('as_binary_tuple', ('00000001', '00000000', '00000000', '00000001')), ] for attribute, result_correct in results_correct: self.assertEqual(getattr(test_object, attribute), result_correct)
def test_basis(self): """Test basic configuration.""" t = Interfaces(ucr={ 'gateway': '1.2.3.4', 'ipv6/gateway': '1:2:3:4:5:6:7:8', 'interfaces/handler': 'manual', 'interfaces/primary': 'br0', }) self.assertEqual('manual', t.handler) self.assertEqual('br0', t.primary) self.assertEqual(IPv4Address('1.2.3.4'), t.ipv4_gateway) self.assertEqual(IPv6Address('1:2:3:4:5:6:7:8'), t.ipv6_gateway)
def __init__(self, network_addr, netmask_addr, options=None, pools=None, parameters=None): netmask = IPv4Address(netmask_addr) self.network = IPv4Network("{0}/{1}".format( network_addr, len(bin(netmask).translate(None, "b0")))) self.options = set(options or []) self.pools = set(pools or []) self.parameters = set(parameters or [])
def _get_rnd_ip(self, subnet_list): subnet = IPv4Network(random.choice(subnet_list)) if subnet.numhosts == 1: # A /32 IPv4 network. Only one host in it. ip = subnet[0] else: ip = IPv4Address( random.randrange( int(subnet.network) + 1, int(subnet.broadcast) - 1)) return str(ip)
def build_accessfunc_arguments(user=None, ip=None, date=None, req=None): """Build the expected arguments for the DB permission procedures has_*_access_to_node() IP and date are returned unchanged when passed to this function. For missing arguments, default values are set from request information or current date. :returns: 3-tuple of group_ids, ip and date For admin users, it returns (None, None, None) which means: ignore all access checks. Users can test for this and skip permission checks completely. """ from core.users import get_guest_user if user is None and ip is None: if req is None: req = request from core.users import user_from_session user = user_from_session(req.session) # XXX: like in mysql version, what's the real solution? try: ip = IPv4Address(req.remote_addr) except AddressValueError: logg.warn("illegal IP address %s, refusing IP-based access", req.remote_addr) ip = None if user is None: user = get_guest_user() # admin sees everything ;) if user.is_admin: return (None, None, None) if ip is None: ip = IPv4Address("0.0.0.0") if date is None: date = sqlfunc.current_date() return user.group_ids, ip, date
def interface_create(host_id): host = Host.q.get(host_id) if host is None: flash(u"Host existiert nicht.", 'error') abort(404) subnets = get_subnets_for_room(host.room) form = InterfaceForm() unused_ips = [ip for ips in get_unused_ips(subnets).values() for ip in ips] form.ips.choices = [(str(ip), str(ip)) for ip in unused_ips] unique_mac_error = None if not form.is_submitted(): form.ips.process_data([next(iter(unused_ips), None)]) else: unique_mac_error = validate_unique_mac(form, form.mac) if unique_mac_error: form.validate() form.mac.errors.append(unique_mac_error) if not unique_mac_error and form.validate_on_submit(): ips = set([IPv4Address(ip) for ip in form.ips.data]) _, success = web_execute(lib_host.interface_create, "Interface erfolgreich erstellt.", host, form.name.data, form.mac.data, ips, current_user) if success: session.session.commit() return redirect( url_for('user.user_show', user_id=host.owner.id, _anchor='hosts')) form_args = { 'form': form, 'cancel_to': url_for('user.user_show', user_id=host.owner.id) } return render_template('generic_form.html', page_title="Interface erstellen", form_args=form_args)
def parse(value): """ Parse originator id :param value: """ if len(value) > 4: raise excep.UpdateMessageError( sub_error=bgp_cons.ERR_MSG_UPDATE_ATTR_LEN, data=value) try: return IPv4Address(int(binascii.b2a_hex(value[0:4]), 16)).__str__() except Exception: raise excep.UpdateMessageError( sub_error=bgp_cons.ERR_MSG_UPDATE_ATTR_LEN, data=value)
def testIPv4Obj_attributes(): ## Ensure that attributes are accessible and pass the smell test test_object = IPv4Obj("1.0.0.1 255.255.255.0") results_correct = [ ("ip", IPv4Address("1.0.0.1")), ("ip_object", IPv4Address("1.0.0.1")), ("netmask", IPv4Address("255.255.255.0")), ("prefixlen", 24), ("broadcast", IPv4Address("1.0.0.255")), ("network", IPv4Network("1.0.0.0/24")), ("network_object", IPv4Network("1.0.0.0/24")), ("hostmask", IPv4Address("0.0.0.255")), ("numhosts", 256), ("version", 4), ("is_reserved", False), ("is_multicast", False), ("is_private", False), ("as_decimal", 16777217), ("as_hex_tuple", ("01", "00", "00", "01")), ("as_binary_tuple", ("00000001", "00000000", "00000000", "00000001")), ] for attribute, result_correct in results_correct: assert getattr(test_object, attribute) == result_correct
def testverifynetworkproto(self): command = "show network --ip %s --format proto" % self.net.tor_net2[ 0].ip out = self.commandtest(command.split(" ")) msg = self.parse_netlist_msg(out, expect=1) network = msg.networks[0] hosts = set([host.fqdn for host in network.hosts]) start = self.net.tor_net2[0].usable[2] end = self.net.tor_net2[0].usable[-3] for i in range(int(start), int(end) + 1): ip = IPv4Address(i) self.failUnless( dynname(ip) in hosts, "%s is missing from network" "protobuf output" % dynname(ip))
def testclearnetwork(self): messages = [] for ip in range(int(self.net.tor_net2[5].usable[0]), int(self.net.tor_net2[5].usable[-1]) + 1): address = IPv4Address(ip) self.dsdb_expect_delete(address) messages.append("DSDB: delete_host -ip_address %s" % address) command = [ "del_dynamic_range", "--clearnetwork", self.net.tor_net2[5].ip ] err = self.statustest(command) for message in messages: self.matchoutput(err, message, command) self.dsdb_verify()
def get_dc(ip): """Return IP's DC""" global DC if not DC: return '' try: from ipaddr import IPv4Address for dc_net, dc_name in DC.items(): if IPv4Address(ip) in dc_net: return dc_name except Exception: logging.debug("Failed to load {0}'s DC from cache".format(ip), exc_info=True) return ''
def construct(self, value, flags=None): """ encode BGP nexthop attribute. """ try: ipv4_addr = IPv4Address(value) except: raise excep.UpdateMessageError( sub_error=bgp_cons.ERR_MSG_UPDATE_INVALID_NEXTHOP, data=value) ip_addr_raw = ipv4_addr.packed if not flags: flags = self.FLAG return struct.pack('!B', flags) + struct.pack('!B', self.ID) \ + struct.pack('!B', len(ip_addr_raw)) + ip_addr_raw
def construct(self, value, flags=None): """ construct a ORIGINATOR_ID path attribute :param value: :param flags: """ if not flags: flags = self.FLAG try: return struct.pack('!B', flags) + struct.pack('!B', self.ID) \ + struct.pack('!B', 4) + IPv4Address(value).packed except Exception: raise excep.UpdateMessageError( sub_error=bgp_cons.ERR_MSG_UPDATE_ATTR_LEN, data=value)
def get_unique(cls, session, *args, **kwargs): # Fall back to the generic implementation unless the caller used exactly # one non-keyword argument. Any caller using preclude would be passing # keywords anyway. compel = kwargs.pop("compel", False) options = kwargs.pop("query_options", None) netenv = kwargs.pop("network_environment", None) if kwargs or len(args) > 1: return super(Network, cls).get_unique(session, *args, network_environment=netenv, query_options=options, compel=compel, **kwargs) # Just a single positional argumentum - do magic # The order matters here, we don't want to parse '1.2.3.4' as # IPv4Network('1.2.3.4/32') ip = None if isinstance(args[0], IPv4Address): ip = args[0] else: try: ip = IPv4Address(args[0]) except AddressValueError: pass if ip: return super(Network, cls).get_unique(session, ip=ip, network_environment=netenv, query_options=options, compel=compel) net = None if isinstance(args[0], IPv4Network): net = args[0] else: try: net = IPv4Network(args[0]) except (AddressValueError, NetmaskValueError): pass if net: return super(Network, cls).get_unique(session, ip=net.network, cidr=net.prefixlen, network_environment=netenv, query_options=options, compel=compel) return super(Network, cls).get_unique(session, name=args[0], network_environment=netenv, query_options=options, compel=compel)
def testverifyrange(self): command = "search_dns --record_type=dynamic_stub" out = self.commandtest(command.split(" ")) # Assume that first three octets are the same. start = self.net.tor_net2[0].usable[2] end = self.net.tor_net2[0].usable[-3] checked = False for i in range(int(start), int(end) + 1): checked = True ip = IPv4Address(i) self.matchoutput(out, dynname(ip), command) subcommand = ["search_dns", "--ip", ip, "--fqdn", dynname(ip)] subout = self.commandtest(subcommand) self.matchoutput(subout, dynname(ip), command) self.failUnless(checked, "Problem with test algorithm or data.")
def __init__(self, arg='127.0.0.1/32', strict=False): #RGX_IPV4ADDR = re.compile(r'^(\d+\.\d+\.\d+\.\d+)') #RGX_IPV4ADDR_NETMASK = re.compile(r'(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)') self.arg = arg self.dna = "IPv4Obj" try: mm = _RGX_IPV4ADDR_NETMASK.search(arg) except TypeError: if arg.dna == "IPv4Obj": ip_str = '{0}/{1}'.format(str(arg.ip_object), arg.prefixlen) self.network_object = IPv4Network(ip_str) self.ip_object = IPv4Address(str(arg.ip_object)) return None else: raise ValueError( "IPv4Obj doesn't understand how to parse {0}".format(arg)) ERROR = "IPv4Obj couldn't parse '{0}'".format(arg) assert (not (mm is None)), ERROR mm_result = mm.groupdict() addr = mm_result['addr0'] or mm_result['addr1'] \ or mm_result['addr2'] or '127.0.0.1' masklen = int(mm_result['masklen'] or 32) netmask = mm_result['netmask'] if netmask: ## ALWAYS check for the netmask first self.network_object = IPv4Network('{0}/{1}'.format(addr, netmask), strict=strict) self.ip_object = IPv4Address('{0}'.format(addr)) else: self.network_object = IPv4Network('{0}/{1}'.format(addr, masklen), strict=strict) self.ip_object = IPv4Address('{0}'.format(addr))
def __init__(self, arg='127.0.0.1/32', strict=False): #RGX_IPV4ADDR = re.compile(r'^(\d+\.\d+\.\d+\.\d+)') #RGX_IPV4ADDR_NETMASK = re.compile(r'(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)') self.arg = arg mm = _RGX_IPV4ADDR_NETMASK.search(arg) ERROR = "IPv4Obj couldn't parse '{0}'".format(arg) assert (not (mm is None)), ERROR mm_result = mm.groupdict() addr = mm_result['addr0'] or mm_result['addr1'] \ or mm_result['addr2'] or '127.0.0.1' masklen = int(mm_result['masklen'] or 32) netmask = mm_result['netmask'] if netmask: ## ALWAYS check for the netmask first self.network_object = IPv4Network('{0}/{1}'.format(addr, netmask), strict=strict) self.ip_object = IPv4Address('{0}'.format(addr)) else: self.network_object = IPv4Network('{0}/{1}'.format(addr, masklen), strict=strict) self.ip_object = IPv4Address('{0}'.format(addr))
def interface_edit(interface_id): interface = Interface.q.get(interface_id) if interface is None: flash(u"Interface existiert nicht.", 'error') abort(404) subnets = get_subnets_for_room(interface.host.room) current_ips = list(ip.address for ip in interface.ips) form = InterfaceForm(obj=interface) form.meta.current_mac = interface.mac unused_ips = [ip for ips in get_unused_ips(subnets).values() for ip in ips] form.ips.choices = [(str(ip), str(ip)) for ip in current_ips + unused_ips] if not form.is_submitted(): form.ips.process_data(ip for ip in current_ips) if form.validate_on_submit(): ips = set([IPv4Address(ip) for ip in form.ips.data]) _, success = web_execute(lib_host.interface_edit, "Interface erfolgreich bearbeitet.", interface, form.name.data, form.mac.data, ips, current_user ) if success: session.session.commit() return redirect( url_for('user.user_show', user_id=interface.host.owner_id, _anchor='hosts')) form_args = { 'form': form, 'cancel_to': url_for('user.user_show', user_id=interface.host.owner_id) } return render_template('generic_form.html', page_title="Interface editieren", form_args=form_args)
def _get_app_network(self): _logger.debug('Getting network for %s' % self.app) network = ucr_get(self.app.ucr_ip_key) if network: _logger.debug('Found %s' % network) try: network = IPv4Network(network) except ValueError as exc: _logger.warn('Error using the network %s: %s' % (network, exc)) return None else: return network docker0_net = IPv4Network( ucr_get('appcenter/docker/compose/network', '172.16.1.1/16')) gateway, netmask = docker0_net.exploded.split('/', 1) # '172.16.1.1', '16' used_docker_networks = [] for _app in Apps().get_all_apps( ): # TODO: find container not managed by the App Center? if _app.id == self.app.id: continue ip = ucr_get(_app.ucr_ip_key) try: app_network = IPv4Network(ip) except ValueError as exc: continue else: used_docker_networks.append(app_network) prefixlen_diff = 24 - int(netmask) if prefixlen_diff <= 0: _logger.warn( 'Cannot get a subnet big enough' ) # maybe I could... but currently, I only work with 24-netmasks return None for network in docker0_net.iter_subnets( prefixlen_diff ): # 172.16.1.1/24, 172.16.2.1/24, ..., 172.16.255.1/24 _logger.debug('Testing %s' % network) if IPv4Address(gateway) in network: _logger.debug('Refusing due to "main subnet"') continue if any( app_network.overlaps(network) for app_network in used_docker_networks): _logger.debug('Refusing due to range already used') continue return network _logger.warn('Cannot find any viable subnet')
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()
def getRemoteIP(self): """Mask the client's real IP address with a faked one. The fake client IP address is sent to the reCaptcha server, and it is either the public IP address of bridges.torproject.org (if the config option ``RECAPTCHA_REMOTE_IP`` is configured), or a random IP. :rtype: str :returns: A fake IP address to report to the reCaptcha API server. """ if self.remoteIP: remoteIP = self.remoteIP else: # generate a random IP for the captcha submission remoteIP = IPv4Address(random.randint(0, 2**32-1)).compressed return remoteIP
def testfillnetwork(self): messages = [] for ip in range(int(self.net.tor_net2[5].usable[0]), int(self.net.tor_net2[5].usable[-1]) + 1): address = IPv4Address(ip) hostname = dynname(address) self.dsdb_expect_add(hostname, address) messages.append("DSDB: add_host -host_name %s -ip_address %s " "-status aq" % (hostname, address)) command = [ "add_dynamic_range", "--fillnetwork", self.net.tor_net2[5].ip, "--dns_domain=aqd-unittest.ms.com" ] err = self.statustest(command) for message in messages: self.matchoutput(err, message, command) self.dsdb_verify()
def __init__(self, arg="127.0.0.1/32", strict=False): # RGX_IPV4ADDR = re.compile(r'^(\d+\.\d+\.\d+\.\d+)') # RGX_IPV4ADDR_NETMASK = re.compile(r'(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)') self.arg = arg self.dna = "IPv4Obj" try: mm = _RGX_IPV4ADDR_NETMASK.search(arg) except TypeError: if getattr(arg, "dna", "") == "IPv4Obj": ip_str = "{0}/{1}".format(str(arg.ip_object), arg.prefixlen) self.network_object = IPv4Network(ip_str, strict=False) self.ip_object = IPv4Address(str(arg.ip_object)) return None elif isinstance(arg, IPv4Network): self.network_object = arg self.ip_object = IPv4Address(str(arg).split("/")[0]) return None elif isinstance(arg, IPv4Address): self.network_object = IPv4Network(str(arg) + "/32") self.ip_object = IPv4Address(str(arg).split("/")[0]) return None elif isinstance(arg, int): self.ip_object = IPv4Address(arg) self.network_object = IPv4Network(str(self.ip_object) + "/32", strict=False) return None else: raise ValueError( "IPv4Obj doesn't understand how to parse {0}".format(arg)) ERROR = "IPv4Obj couldn't parse '{0}'".format(arg) assert not (mm is None), ERROR mm_result = mm.groupdict() addr = (mm_result["addr0"] or mm_result["addr1"] or mm_result["addr2"] or "127.0.0.1") ## Normalize addr if we get zero-padded strings, i.e. 172.001.001.001 addr = ".".join([str(int(ii)) for ii in addr.split(".")]) masklen = int(mm_result["masklen"] or 32) netmask = mm_result["netmask"] if netmask: ## ALWAYS check for the netmask first self.network_object = IPv4Network("{0}/{1}".format(addr, netmask), strict=strict) self.ip_object = IPv4Address("{0}".format(addr)) else: self.network_object = IPv4Network("{0}/{1}".format(addr, masklen), strict=strict) self.ip_object = IPv4Address("{0}".format(addr))
def __init__(self, arg='127.0.0.1/32', strict=False): #RGX_IPV4ADDR = re.compile(r'^(\d+\.\d+\.\d+\.\d+)') #RGX_IPV4ADDR_NETMASK = re.compile(r'(\d+\.\d+\.\d+\.\d+)\s+(\d+\.\d+\.\d+\.\d+)') self.arg = arg self.dna = "IPv4Obj" try: mm = _RGX_IPV4ADDR_NETMASK.search(arg) except TypeError: if getattr(arg, 'dna', '') == "IPv4Obj": ip_str = '{0}/{1}'.format(str(arg.ip_object), arg.prefixlen) self.network_object = IPv4Network(ip_str, strict=False) self.ip_object = IPv4Address(str(arg.ip_object)) return None elif isinstance(arg, IPv4Network): self.network_object = arg self.ip_object = IPv4Address(str(arg).split('/')[0]) return None elif isinstance(arg, IPv4Address): self.network_object = IPv4Network(str(arg) + '/32') self.ip_object = IPv4Address(str(arg).split('/')[0]) return None elif isinstance(arg, int): self.ip_object = IPv4Address(arg) self.network_object = IPv4Network(str(self.ip_object) + '/32', strict=False) return None else: raise ValueError( "IPv4Obj doesn't understand how to parse {0}".format(arg)) ERROR = "IPv4Obj couldn't parse '{0}'".format(arg) assert (not (mm is None)), ERROR mm_result = mm.groupdict() addr = mm_result['addr0'] or mm_result['addr1'] \ or mm_result['addr2'] or '127.0.0.1' ## Normalize addr if we get zero-padded strings, i.e. 172.001.001.001 addr = '.'.join([str(int(ii)) for ii in addr.split('.')]) masklen = int(mm_result['masklen'] or 32) netmask = mm_result['netmask'] if netmask: ## ALWAYS check for the netmask first self.network_object = IPv4Network('{0}/{1}'.format(addr, netmask), strict=strict) self.ip_object = IPv4Address('{0}'.format(addr)) else: self.network_object = IPv4Network('{0}/{1}'.format(addr, masklen), strict=strict) self.ip_object = IPv4Address('{0}'.format(addr))
def parse(value): """ Parse culster list :param value """ cluster_list = [] if len(value) % 4 != 0: raise excep.UpdateMessageError( sub_error=bgp_cons.ERR_MSG_UPDATE_ATTR_LEN, data=repr(value)) try: while value: cluster_list.append( IPv4Address(struct.unpack('!I', value[0:4])[0]).__str__()) value = value[4:] except Exception: raise excep.UpdateMessageError( sub_error=bgp_cons.ERR_MSG_UPDATE_ATTR_LEN, data=repr(value)) return cluster_list
def construct(self, value, flags=None): """ construct a CLUSTER_LIST path attribute :param value: :param flags: """ cluster_raw = '' if not flags: flags = self.FLAG try: for cluster in value: cluster_raw += IPv4Address(cluster).packed return struct.pack("!B", flags) + struct.pack('!B', self.ID) \ + struct.pack("!B", len(cluster_raw)) + cluster_raw except Exception: raise excep.UpdateMessageError( sub_error=bgp_cons.ERR_MSG_UPDATE_ATTR_LEN, data=struct.pack('B', flags))
def subnet_generator(prefix, numhosts): '''Given a prefix and number of hosts to carve out for subnets within this prefix, create a generator object that returns a new subnet (as an ipaddr.IPv4Network) with each subsequent call to next()''' ceil = math.ceil log = math.log ipfx = IPv4Network(prefix) prefixhosts = ipfx.numhosts numhosts += 2 numhosts = int(ceil(log(numhosts, 2)) ** 2) prefixlen = '/' + str(32 - int(log(numhosts,2))) baseint = int(ipfx) numsubnets = prefixhosts / numhosts for i in xrange(numsubnets): addr = IPv4Address(baseint + (numhosts * i)) prefix = IPv4Network(str(addr) + prefixlen) yield prefix
def __init__(self, ucr=None): if ucr is None: ucr = ConfigRegistry() ucr.load() if isinstance(ucr, ConfigRegistry): ucr = VengefulConfigRegistry(ucr) self.handler = ucr.get('interfaces/handler', 'ifplugd') self.primary = ucr.get('interfaces/primary', 'eth0') try: self.ipv4_gateway = IPv4Address(ucr['gateway']) except KeyError: self.ipv4_gateway = None except ValueError: self.ipv4_gateway = False try: # <https://tools.ietf.org/html/rfc4007#section-11> # As a common notation to specify the scope zone, an # implementation SHOULD support the following format: # <address>%<zone_id> gateway, zone_index = (ucr['ipv6/gateway'].rsplit('%', 1) + [None])[:2] self.ipv6_gateway = IPv6Address(gateway) self.ipv6_gateway_zone_index = zone_index except KeyError: self.ipv6_gateway = None self.ipv6_gateway_zone_index = None except ValueError: self.ipv6_gateway = False self.ipv6_gateway_zone_index = None self._all_interfaces = {} for key, value in ucr.items(): if not value: continue match = RE_IFACE.match(key) if not match: continue iface, subkey, ipv6_name = match.groups() data = self._all_interfaces.setdefault(iface, _Iface(name=iface)) data[subkey] = value if ipv6_name: data.ipv6_names.add(ipv6_name)
def teardown(): ip = IPv4Address(TEST_IP) arec = ARecord.get_unique(sess, fqdn='%s.%s' % (AREC_NAME, DNS_DOMAIN_NAME), compel=True) dmn = DnsDomain.get_unique(sess, DNS_DOMAIN_NAME, compel=True) #Test deletion of NSRecord doesn't affect the ARecord or DNS Domain #by deleting it first. ns = NsRecord.get_unique(sess, a_record=arec, dns_domain=dmn) sess.delete(ns) commit(sess) sess.delete(arec) commit(sess) sess.delete(dmn) commit(sess) sess.query(Network).filter_by(name=TEST_NET_NAME).delete() commit(sess)