From 78ff7f2189da06e445fac26b52f3a101e8f088b5 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 3 Aug 2017 12:44:08 -0700 Subject: [PATCH] quick pass for small cleanup within bsd nodes --- daemon/core/bsd/netgraph.py | 56 ++++++++++++++++++------- daemon/core/bsd/nodes.py | 62 ++++++++++++++------------- daemon/core/bsd/vnet.py | 60 +++++++++++++------------- daemon/core/bsd/vnode.py | 84 ++++++++++++++++++------------------- 4 files changed, 146 insertions(+), 116 deletions(-) diff --git a/daemon/core/bsd/netgraph.py b/daemon/core/bsd/netgraph.py index c1cd4eb0..c928378f 100644 --- a/daemon/core/bsd/netgraph.py +++ b/daemon/core/bsd/netgraph.py @@ -16,58 +16,82 @@ import subprocess from core import constants from core.misc import utils -utils.checkexec([constants.NGCTL_BIN]) +utils.check_executables([constants.NGCTL_BIN]) -def createngnode(type, hookstr, name=None): +def createngnode(node_type, hookstr, name=None): """ Create a new Netgraph node of type and optionally assign name. The hook string hookstr should contain two names. This is a string so other commands may be inserted after the two names. Return the name and netgraph ID of the new node. + + :param node_type: node type to create + :param hookstr: hook string + :param name: name + :return: name and id + :rtype: tuple """ hook1 = hookstr.split()[0] - ngcmd = "mkpeer %s %s \n show .%s" % (type, hookstr, hook1) + ngcmd = "mkpeer %s %s \n show .%s" % (node_type, hookstr, hook1) cmd = [constants.NGCTL_BIN, "-f", "-"] - cmdid = subprocess.Popen(cmd, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + cmdid = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # err will always be None result, err = cmdid.communicate(input=ngcmd) status = cmdid.wait() if status > 0: - raise Exception("error creating Netgraph node %s (%s): %s" % (type, ngcmd, result)) + raise Exception("error creating Netgraph node %s (%s): %s" % (node_type, ngcmd, result)) results = result.split() ngname = results[1] ngid = results[5] if name: - utils.check_call([constants.NGCTL_BIN, "name", "[0x%s]:" % ngid, name]) + subprocess.check_call([constants.NGCTL_BIN, "name", "[0x%s]:" % ngid, name]) return ngname, ngid def destroyngnode(name): - """ Shutdown a Netgraph node having the given name. """ - utils.check_call([constants.NGCTL_BIN, "shutdown", "%s:" % name]) + Shutdown a Netgraph node having the given name. + + :param str name: node name + :return: nothing + """ + subprocess.check_call([constants.NGCTL_BIN, "shutdown", "%s:" % name]) def connectngnodes(name1, name2, hook1, hook2): - """ Connect two hooks of two Netgraph nodes given by their names. + """ + Connect two hooks of two Netgraph nodes given by their names. + + :param str name1: name one + :param str name2: name two + :param str hook1: hook one + :param str hook2: hook two + :return: nothing """ node1 = "%s:" % name1 node2 = "%s:" % name2 - utils.check_call([constants.NGCTL_BIN, "connect", node1, node2, hook1, hook2]) + subprocess.check_call([constants.NGCTL_BIN, "connect", node1, node2, hook1, hook2]) def ngmessage(name, msg): - """ Send a Netgraph message to the node named name. + """ + Send a Netgraph message to the node named name. + + :param str name: node name + :param list msg: message + :return: nothing """ cmd = [constants.NGCTL_BIN, "msg", "%s:" % name] + msg - utils.check_call(cmd) + subprocess.check_call(cmd) def ngloadkernelmodule(name): - """ Load a kernel module by invoking kldstat. This is needed for the - ng_ether module which automatically creates Netgraph nodes when loaded. + """ + Load a kernel module by invoking kldstat. This is needed for the + ng_ether module which automatically creates Netgraph nodes when loaded. + + :param str name: module name + :return: nothing """ utils.mutecall(["kldload", name]) diff --git a/daemon/core/bsd/nodes.py b/daemon/core/bsd/nodes.py index df696796..44eda5e1 100644 --- a/daemon/core/bsd/nodes.py +++ b/daemon/core/bsd/nodes.py @@ -12,6 +12,7 @@ from the CoreNode, implementing specific node types. """ import socket +import subprocess from core import constants from core.api import coreapi @@ -25,9 +26,12 @@ from core.enumerations import LinkTypes from core.enumerations import NodeTypes from core.enumerations import RegisterTlvs from core.misc import ipaddress +from core.misc import log from core.misc import utils -utils.checkexec([constants.IFCONFIG_BIN]) +logger = log.get_logger(__name__) + +utils.check_executables([constants.IFCONFIG_BIN]) class CoreNode(JailNode): @@ -36,14 +40,16 @@ class CoreNode(JailNode): class PtpNet(NetgraphPipeNet): def tonodemsg(self, flags): - """ Do not generate a Node Message for point-to-point links. They are - built using a link message instead. + """ + Do not generate a Node Message for point-to-point links. They are + built using a link message instead. """ pass def tolinkmsgs(self, flags): - """ Build CORE API TLVs for a point-to-point link. One Link message - describes this network. + """ + Build CORE API TLVs for a point-to-point link. One Link message + describes this network. """ tlvdata = "" if len(self._netif) != 2: @@ -74,7 +80,7 @@ class PtpNet(NetgraphPipeNet): if if1.hwaddr: tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_MAC.value, if1.hwaddr) for addr in if1.addrlist: - (ip, sep, mask) = addr.partition("/") + ip, sep, mask = addr.partition("/") mask = int(mask) if ipaddress.is_ipv4_address(ip): family = socket.AF_INET @@ -92,7 +98,7 @@ class PtpNet(NetgraphPipeNet): if if2.hwaddr: tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_MAC.value, if2.hwaddr) for addr in if2.addrlist: - (ip, sep, mask) = addr.partition("/") + ip, sep, mask = addr.partition("/") mask = int(mask) if ipaddress.is_ipv4_address(ip): family = socket.AF_INET @@ -131,9 +137,8 @@ class WlanNode(NetgraphNet): linktype = LinkTypes.WIRELESS.value policy = "DROP" - def __init__(self, session, objid=None, name=None, verbose=False, - start=True, policy=None): - NetgraphNet.__init__(self, session, objid, name, verbose, start, policy) + def __init__(self, session, objid=None, name=None, start=True, policy=None): + NetgraphNet.__init__(self, session, objid, name, start, policy) # wireless model such as basic range self.model = None # mobility model such as scripted @@ -142,40 +147,42 @@ class WlanNode(NetgraphNet): def attach(self, netif): NetgraphNet.attach(self, netif) if self.model: - netif.poshook = self.model._positioncallback + netif.poshook = self.model.position_callback if netif.node is None: return x, y, z = netif.node.position.get() netif.poshook(netif, x, y, z) def setmodel(self, model, config): - """ Mobility and wireless model. """ - if self.verbose: - self.info("adding model %s" % model._name) - if model._type == RegisterTlvs.WIRELESS.value: - self.model = model(session=self.session, objid=self.objid, - verbose=self.verbose, values=config) - if self.model._positioncallback: + Mobility and wireless model. + + :param core.mobility.WirelessModel.cls model: model to set + :param dict config: configuration for model + :return: + """ + logger.info("adding model %s" % model.name) + if model.config_type == RegisterTlvs.WIRELESS.value: + self.model = model(session=self.session, objid=self.objid, values=config) + if self.model.position_callback: for netif in self.netifs(): - netif.poshook = self.model._positioncallback + netif.poshook = self.model.position_callback if netif.node is not None: - (x, y, z) = netif.node.position.get() + x, y, z = netif.node.position.get() netif.poshook(netif, x, y, z) self.model.setlinkparams() - elif model._type == RegisterTlvs.MOBILITY.value: - self.mobility = model(session=self.session, objid=self.objid, - verbose=self.verbose, values=config) + elif model.config_type == RegisterTlvs.MOBILITY.value: + self.mobility = model(session=self.session, objid=self.objid, values=config) class RJ45Node(NetgraphPipeNet): apitype = NodeTypes.RJ45.value policy = "ACCEPT" - def __init__(self, session, objid, name, verbose, start=True): + def __init__(self, session, objid, name, start=True): if start: ngloadkernelmodule("ng_ether") - NetgraphPipeNet.__init__(self, session, objid, name, verbose, start) + NetgraphPipeNet.__init__(self, session, objid, name, start) if start: self.setpromisc(True) @@ -187,12 +194,11 @@ class RJ45Node(NetgraphPipeNet): p = "promisc" if not promisc: p = "-" + p - utils.check_call([constants.IFCONFIG_BIN, self.name, "up", p]) + subprocess.check_call([constants.IFCONFIG_BIN, self.name, "up", p]) def attach(self, netif): if len(self._netif) > 0: - raise ValueError, \ - "RJ45 networks support at most 1 network interface" + raise ValueError("RJ45 networks support at most 1 network interface") NetgraphPipeNet.attach(self, netif) connectngnodes(self.ngname, self.name, self.gethook(), "lower") diff --git a/daemon/core/bsd/vnet.py b/daemon/core/bsd/vnet.py index e9d30726..cadf8877 100644 --- a/daemon/core/bsd/vnet.py +++ b/daemon/core/bsd/vnet.py @@ -16,14 +16,16 @@ from core.bsd.netgraph import createngnode from core.bsd.netgraph import destroyngnode from core.bsd.netgraph import ngmessage from core.coreobj import PyCoreNet +from core.misc import log + +logger = log.get_logger(__name__) class NetgraphNet(PyCoreNet): ngtype = None nghooks = () - def __init__(self, session, objid=None, name=None, verbose=False, - start=True, policy=None): + def __init__(self, session, objid=None, name=None, start=True, policy=None): PyCoreNet.__init__(self, session, objid, name) if name is None: name = str(self.objid) @@ -32,7 +34,6 @@ class NetgraphNet(PyCoreNet): self.name = name self.ngname = "n_%s_%s" % (str(self.objid), self.session.session_id) self.ngid = None - self.verbose = verbose self._netif = {} self._linked = {} self.up = False @@ -40,7 +41,7 @@ class NetgraphNet(PyCoreNet): self.startup() def startup(self): - tmp, self.ngid = createngnode(type=self.ngtype, hookstr=self.nghooks, name=self.ngname) + tmp, self.ngid = createngnode(node_type=self.ngtype, hookstr=self.nghooks, name=self.ngname) self.up = True def shutdown(self): @@ -61,12 +62,13 @@ class NetgraphNet(PyCoreNet): destroyngnode(self.ngname) def attach(self, netif): - """ Attach an interface to this netgraph node. Create a pipe between - the interface and the hub/switch/wlan node. - (Note that the PtpNet subclass overrides this method.) + """ + Attach an interface to this netgraph node. Create a pipe between + the interface and the hub/switch/wlan node. + (Note that the PtpNet subclass overrides this method.) """ if self.up: - pipe = self.session.addobj(cls=NetgraphPipeNet, verbose=self.verbose, start=True) + pipe = self.session.addobj(cls=NetgraphPipeNet, start=True) pipe.attach(netif) hook = "link%d" % len(self._netif) pipe.attachnet(self, hook) @@ -107,17 +109,19 @@ class NetgraphNet(PyCoreNet): self._linked[netif1][netif2] = True def linknet(self, net): - """ Link this bridge with another by creating a veth pair and installing - each device into each bridge. + """ + Link this bridge with another by creating a veth pair and installing + each device into each bridge. """ raise NotImplementedError def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None): - """ Set link effects by modifying the pipe connected to an interface. + """ + Set link effects by modifying the pipe connected to an interface. """ if not netif.pipe: - self.warn("linkconfig for %s but interface %s has no pipe" % (self.name, netif.name)) + logger.warn("linkconfig for %s but interface %s has no pipe", self.name, netif.name) return return netif.pipe.linkconfig(netif, bw, delay, loss, duplicate, jitter, netif2) @@ -126,41 +130,40 @@ class NetgraphPipeNet(NetgraphNet): ngtype = "pipe" nghooks = "upper lower" - def __init__(self, session, objid=None, name=None, verbose=False, - start=True, policy=None): - NetgraphNet.__init__(self, session, objid, name, verbose, start, policy) + def __init__(self, session, objid=None, name=None, start=True, policy=None): + NetgraphNet.__init__(self, session, objid, name, start, policy) if start: # account for Ethernet header ngmessage(self.ngname, ["setcfg", "{", "header_offset=14", "}"]) def attach(self, netif): - """ Attach an interface to this pipe node. - The first interface is connected to the "upper" hook, the second - connected to the "lower" hook. + """ + Attach an interface to this pipe node. + The first interface is connected to the "upper" hook, the second + connected to the "lower" hook. """ if len(self._netif) > 1: - raise ValueError, \ - "Netgraph pipes support at most 2 network interfaces" + raise ValueError("Netgraph pipes support at most 2 network interfaces") if self.up: hook = self.gethook() connectngnodes(self.ngname, netif.localname, hook, netif.hook) if netif.pipe: - raise ValueError, \ - "Interface %s already attached to pipe %s" % \ - (netif.name, netif.pipe.name) + raise ValueError("Interface %s already attached to pipe %s" % (netif.name, netif.pipe.name)) netif.pipe = self self._netif[netif] = netif self._linked[netif] = {} def attachnet(self, net, hook): - """ Attach another NetgraphNet to this pipe node. + """ + Attach another NetgraphNet to this pipe node. """ localhook = self.gethook() connectngnodes(self.ngname, net.ngname, localhook, hook) def gethook(self): - """ Returns the first hook (e.g. "upper") then the second hook - (e.g. "lower") based on the number of connections. + """ + Returns the first hook (e.g. "upper") then the second hook + (e.g. "lower") based on the number of connections. """ hooks = self.nghooks.split() if len(self._netif) == 0: @@ -170,7 +173,8 @@ class NetgraphPipeNet(NetgraphNet): def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None): - """ Set link effects by sending a Netgraph setcfg message to the pipe. + """ + Set link effects by sending a Netgraph setcfg message to the pipe. """ netif.setparam("bw", bw) netif.setparam("delay", delay) @@ -201,7 +205,7 @@ class NetgraphPipeNet(NetgraphNet): upstream += ["duplicate=%s" % duplicate, ] downstream += ["duplicate=%s" % duplicate, ] if jitter: - self.warn("jitter parameter ignored for link %s" % self.name) + logger.warn("jitter parameter ignored for link %s", self.name) if len(params) > 0 or len(upstream) > 0 or len(downstream) > 0: setcfg = ["setcfg", "{", ] + params if len(upstream) > 0: diff --git a/daemon/core/bsd/vnode.py b/daemon/core/bsd/vnode.py index 44ddbcf8..c270b491 100644 --- a/daemon/core/bsd/vnode.py +++ b/daemon/core/bsd/vnode.py @@ -20,9 +20,12 @@ from core.bsd.netgraph import createngnode from core.bsd.netgraph import destroyngnode from core.coreobj import PyCoreNetIf from core.coreobj import PyCoreNode +from core.misc import log from core.misc import utils -utils.checkexec([constants.IFCONFIG_BIN, constants.VIMAGE_BIN]) +logger = log.get_logger(__name__) + +utils.check_executables([constants.IFCONFIG_BIN, constants.VIMAGE_BIN]) class VEth(PyCoreNetIf): @@ -46,11 +49,10 @@ class VEth(PyCoreNetIf): def startup(self): hookstr = "%s %s" % (self.hook, self.hook) - ngname, ngid = createngnode(type="eiface", hookstr=hookstr, - name=self.localname) + ngname, ngid = createngnode(node_type="eiface", hookstr=hookstr, name=self.localname) self.name = ngname self.ngid = ngid - utils.check_call([constants.IFCONFIG_BIN, ngname, "up"]) + subprocess.check_call([constants.IFCONFIG_BIN, ngname, "up"]) self.up = True def shutdown(self): @@ -81,19 +83,18 @@ class VEth(PyCoreNetIf): class TunTap(PyCoreNetIf): - """TUN/TAP virtual device in TAP mode""" + """ + TUN/TAP virtual device in TAP mode + """ - def __init__(self, node, name, localname, mtu=None, net=None, - start=True): + def __init__(self, node, name, localname, mtu=None, net=None, start=True): raise NotImplementedError class SimpleJailNode(PyCoreNode): - def __init__(self, session, objid=None, name=None, nodedir=None, - verbose=False): + def __init__(self, session, objid=None, name=None, nodedir=None): PyCoreNode.__init__(self, session, objid, name) self.nodedir = nodedir - self.verbose = verbose self.pid = None self.up = False self.lock = threading.RLock() @@ -101,16 +102,15 @@ class SimpleJailNode(PyCoreNode): def startup(self): if self.up: - raise Exception, "already up" + raise Exception("already up") vimg = [constants.VIMAGE_BIN, "-c", self.name] try: os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, *vimg) except OSError: - raise Exception, ("vimage command not found while running: %s" % \ - vimg) - self.info("bringing up loopback interface") + raise Exception("vimage command not found while running: %s" % vimg) + logger.info("bringing up loopback interface") self.cmd([constants.IFCONFIG_BIN, "lo0", "127.0.0.1"]) - self.info("setting hostname: %s" % self.name) + logger.info("setting hostname: %s", self.name) self.cmd(["hostname", self.name]) self.cmd([constants.SYSCTL_BIN, "vfs.morphing_symlinks=1"]) self.up = True @@ -134,11 +134,11 @@ class SimpleJailNode(PyCoreNode): mode = os.P_WAIT else: mode = os.P_NOWAIT - tmp = utils.call([constants.VIMAGE_BIN, self.name] + args, cwd=self.nodedir) + tmp = subprocess.call([constants.VIMAGE_BIN, self.name] + args, cwd=self.nodedir) if not wait: tmp = None if tmp: - self.warn("cmd exited with status %s: %s" % (tmp, str(args))) + logger.warn("cmd exited with status %s: %s", tmp, str(args)) return tmp def cmdresult(self, args, wait=True): @@ -170,8 +170,9 @@ class SimpleJailNode(PyCoreNode): "-title", self.name, "-e", constants.VIMAGE_BIN, self.name, sh) def termcmdstring(self, sh="/bin/sh"): - """ We add "sudo" to the command string because the GUI runs as a - normal user. + """ + We add "sudo" to the command string because the GUI runs as a + normal user. """ return "cd %s && sudo %s %s %s" % (self.nodedir, constants.VIMAGE_BIN, self.name, sh) @@ -183,11 +184,11 @@ class SimpleJailNode(PyCoreNode): def mount(self, source, target): source = os.path.abspath(source) - self.info("mounting %s at %s" % (source, target)) + logger.info("mounting %s at %s", source, target) self.addsymlink(path=target, file=None) def umount(self, target): - self.info("unmounting %s" % target) + logger.info("unmounting %s", target) def newveth(self, ifindex=None, ifname=None, net=None): self.lock.acquire() @@ -204,7 +205,7 @@ class SimpleJailNode(PyCoreNode): mtu=1500, net=net, start=self.up) if self.up: # install into jail - utils.check_call([constants.IFCONFIG_BIN, veth.name, "vnet", self.name]) + subprocess.check_call([constants.IFCONFIG_BIN, veth.name, "vnet", self.name]) # rename from "ngeth0" to "eth0" self.cmd([constants.IFCONFIG_BIN, veth.name, "name", ifname]) @@ -223,8 +224,7 @@ class SimpleJailNode(PyCoreNode): def sethwaddr(self, ifindex, addr): self._netif[ifindex].sethwaddr(addr) if self.up: - self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), "link", - str(addr)]) + self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), "link", str(addr)]) def addaddr(self, ifindex, addr): if self.up: @@ -232,15 +232,14 @@ class SimpleJailNode(PyCoreNode): family = "inet6" else: family = "inet" - self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), family, "alias", - str(addr)]) + self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), family, "alias", str(addr)]) self._netif[ifindex].addaddr(addr) def deladdr(self, ifindex, addr): try: self._netif[ifindex].deladdr(addr) except ValueError: - self.warn("trying to delete unknown address: %s" % addr) + logger.warn("trying to delete unknown address: %s", addr) if self.up: if ":" in addr: family = "inet6" @@ -255,8 +254,7 @@ class SimpleJailNode(PyCoreNode): addr = self.getaddr(self.ifname(ifindex), rescan=True) for t in addrtypes: if t not in self.valid_deladdrtype: - raise ValueError, "addr type must be in: " + \ - " ".join(self.valid_deladdrtype) + raise ValueError("addr type must be in: " + " ".join(self.valid_deladdrtype)) for a in addr[t]: self.deladdr(ifindex, a) # update cached information @@ -297,8 +295,9 @@ class SimpleJailNode(PyCoreNode): # return self.vnodeclient.getaddr(ifname = ifname, rescan = rescan) def addsymlink(self, path, file): - """ Create a symbolic link from /path/name/file -> - /tmp/pycore.nnnnn/@.conf/path.name/file + """ + Create a symbolic link from /path/name/file -> + /tmp/pycore.nnnnn/@.conf/path.name/file """ dirname = path if dirname and dirname[0] == "/": @@ -318,20 +317,15 @@ class SimpleJailNode(PyCoreNode): os.unlink(pathname) else: if os.path.exists(pathname): - self.warn("did not create symlink for %s since path " \ - "exists on host" % pathname) + logger.warn("did not create symlink for %s since path exists on host", pathname) return - self.info("creating symlink %s -> %s" % (pathname, sym)) + logger.info("creating symlink %s -> %s", pathname, sym) os.symlink(sym, pathname) class JailNode(SimpleJailNode): - def __init__(self, session, objid=None, name=None, - nodedir=None, bootsh="boot.sh", verbose=False, - start=True): - super(JailNode, self).__init__(session=session, objid=objid, - name=name, nodedir=nodedir, - verbose=verbose) + def __init__(self, session, objid=None, name=None, nodedir=None, bootsh="boot.sh", start=True): + super(JailNode, self).__init__(session=session, objid=objid, name=name, nodedir=nodedir) self.bootsh = bootsh if not start: return @@ -369,8 +363,10 @@ class JailNode(SimpleJailNode): def privatedir(self, path): if path[0] != "/": raise ValueError, "path not fully qualified: " + path - hostpath = os.path.join(self.nodedir, - os.path.normpath(path).strip("/").replace("/", ".")) + hostpath = os.path.join( + self.nodedir, + os.path.normpath(path).strip("/").replace("/", ".") + ) try: os.mkdir(hostpath) except OSError: @@ -383,7 +379,7 @@ class JailNode(SimpleJailNode): dirname, basename = os.path.split(filename) # self.addsymlink(path=dirname, file=basename) if not basename: - raise ValueError, "no basename for filename: " + filename + raise ValueError("no basename for filename: %s" % filename) if dirname and dirname[0] == "/": dirname = dirname[1:] dirname = dirname.replace("/", ".") @@ -398,4 +394,4 @@ class JailNode(SimpleJailNode): f.write(contents) os.chmod(f.name, mode) f.close() - self.info("created nodefile: %s; mode: 0%o" % (f.name, mode)) + logger.info("created nodefile: %s; mode: 0%o", f.name, mode)