def __init__(self, writeDir, execCommands=True): """ writeDir: directory to use for generated config files (e.g. hostapd.conf). execCommands: whether or not to run commands (set to False for testing). """ self.writeDir = writeDir self.execCommands = execCommands # Make sure directory exists. pdosq.makedirs(writeDir) self.previousCommands = list() self.currentConfig = dict() self.nextSectionId = 0 # Number of objects requiring IP forwarding. # If >0, we need to enable system-wide. # If ==0, we can probably disable. self.forwardingCount = 0 # Track whether we have loaded the conntrack kernel module. We need to # make sure the module is loaded before adding iptables rules related # to connection state. self.conntrackLoaded = False # Allow threads to wait for first load to complete. This will be set # after the first load completes and will remain set thereafter. self.systemUp = threading.Event() # Track epoch number so that we know which configuration sections # were applied in the most recent epoch. self.epoch = 0
def loadSettings(mode="local", slist=[]): """ Take a list of key:value pairs, and replace any setting defined. Also search through the settings module and see if any matching environment variables exist to replace as well. :param slist: the list of key:val settings :type slist: array. :returns: None """ # Get a handle to our settings defined above mod = sys.modules[__name__] # Adjust default paths if we are running under ubuntu snappy snapPath = os.environ.get("SNAP", None) snapCommonPath = os.environ.get("SNAP_COMMON", None) snapDataPath = os.environ.get("SNAP_DATA", None) # Directories where we might find a settings.ini file. settings_file_dirs = [".", "/etc"] if mode == "local": updatePaths(os.path.join(os.path.expanduser("~"), ".paradrop/"), "/tmp/.paradrop/") mod.HOST_DATA_PARTITION = mod.CONFIG_HOME_DIR elif mode == "unittest": updatePaths("/tmp/.paradrop-test/", "/tmp/.paradrop-test/") mod.HOST_DATA_PARTITION = mod.CONFIG_HOME_DIR elif snapCommonPath is not None: settings_file_dirs.append(snapCommonPath) updatePaths(snapCommonPath, snapDataPath) mod.HOST_DATA_PARTITION = "/writable" mod.DOCKER_BIN_DIR = "/snap/bin" mod.GOVERNOR_INTERFACE = os.path.join(snapPath, "governor", "governor.socket") mod.ZEROTIER_LIB_DIR = os.path.join(snapPath, "zerotier-one") for x in [mod.LOG_DIR, mod.KEY_DIR, mod.MISC_DIR]: pdosq.makedirs(x) # First overwrite settings they may have provided with the arg list for kv in slist: k, v = kv.split(':', 1) # We can either replace an existing setting, or set a new value, we don't care setattr(mod, k, parseValue(v)) # Next check for settings from file(s) which may be located in a few # different directories. for d in settings_file_dirs: path = os.path.join(d, constants.SETTINGS_FILE_NAME) load_from_file(path) # Now search through our settings and look for environment variable matches # they defined. Environment variables override all other sources. for name, _ in iterate_module_attributes(mod): # Check for an environment variable matching the setting. value = os.environ.get(name, None) if value is not None: setattr(mod, name, parseValue(value))
def backup(self, backupToken): """ Puts a backup of this config to the location specified in @backupPath. """ pdosq.makedirs(settings.UCI_BACKUP_DIR) backupPath = "{}/{}-{}".format(settings.UCI_BACKUP_DIR, self.myname, backupToken) pdos.copy(self.filepath, backupPath)
def createVolumeDirs(update): extDataDir = update.new.getCache('externalDataDir') extSystemDir = update.new.getCache('externalSystemDir') if update.updateType == 'delete': pdos.remove(extDataDir, suppressNotFound=True) pdos.remove(extSystemDir, suppressNotFound=True) else: pdosq.makedirs(extDataDir) pdosq.makedirs(extSystemDir) os.chown(extDataDir, settings.CONTAINER_UID, -1)
def createVolumeDirs(update): """ Create directories required by the chute. """ extDataDir = update.cache_get('externalDataDir') extSystemDir = update.cache_get('externalSystemDir') if update.updateType == 'delete': pdos.remove(extDataDir, suppressNotFound=True) pdos.remove(extSystemDir, suppressNotFound=True) else: pdosq.makedirs(extDataDir) pdosq.makedirs(extSystemDir) os.chown(extDataDir, settings.CONTAINER_UID, -1)
def __init__(self, writeDir): self.writeDir = writeDir # Make sure directory exists. pdosq.makedirs(writeDir) self.previousCommands = list() self.currentConfig = dict() self.nextSectionId = 0 # Number of objects requiring IP forwarding. # If >0, we need to enable system-wide. # If ==0, we can probably disable. self.forwardingCount = 0 # Allow threads to wait for first load to complete. This will be set # after the first load completes and will remain set thereafter. self.systemUp = threading.Event()
def createVolumeDirs(update): """ Create directories required by the chute. """ extDataDir = update.cache_get('externalDataDir') extSystemDir = update.cache_get('externalSystemDir') if update.updateType == 'delete': pdos.remove(extDataDir, suppressNotFound=True) pdos.remove(extSystemDir, suppressNotFound=True) else: pdosq.makedirs(extDataDir) pdosq.makedirs(extSystemDir) try: os.chown(extDataDir, settings.CONTAINER_UID, -1) except: # chown is not permitted in strict confinement. # TODO: do we need to chmod the data directory, or does it work # fine regardless? pass
def test_pdosq(): """ Test pdosq utility functions """ # Test makedirs with an already-exists error, returns False. with patch('os.makedirs', side_effect=OSError(errno.EEXIST, "error")): assert pdosq.makedirs("/") is False # Test makedirs with a permission error, passes on the Exception. with patch('os.makedirs', side_effect=OSError(errno.EPERM, "error")): assert_raises(OSError, pdosq.makedirs, "/")
def apply(self, allConfigs): commands = list() # visibleName will be used in choosing file names for this dnsmasq # instance, must be unique if there are multiple dnsmasq instances visibleName = self.internalName if self.interface is None: interfaces = [] for section in self.findByType(allConfigs, "dhcp", "dhcp"): interfaces.append(section.interface) else: interfaces = self.interface self.__leasefile = self.leasefile if self.__leasefile is None: self.__leasefile = "{}/dnsmasq-{}.leases".format( self.manager.writeDir, visibleName) pdosq.makedirs(os.path.dirname(self.__leasefile)) pidFile = "{}/dnsmasq-{}.pid".format( self.manager.writeDir, visibleName) pdosq.makedirs(os.path.dirname(pidFile)) outputPath = "{}/dnsmasq-{}.conf".format( self.manager.writeDir, visibleName) pdosq.makedirs(os.path.dirname(outputPath)) with open(outputPath, "w") as outputFile: outputFile.write("#" * 80 + "\n") outputFile.write("# dnsmasq configuration file generated by " "pdconfd\n") outputFile.write("# Source: {}\n".format(self.source)) outputFile.write("# Section: {}\n".format(str(self))) outputFile.write("#" * 80 + "\n") outputFile.write("\n") outputFile.write("dhcp-leasefile={}\n".format(self.__leasefile)) if self.authoritative: outputFile.write("dhcp-authoritative\n") outputFile.write("cache-size={}\n".format(self.cachesize)) if self.dhcp_boot is not None: outputFile.write("dhcp-boot={}\n".format(self.dhcp_boot)) outputFile.write("dhcp-lease-max={}\n".format(self.dhcpleasemax)) if self.domain: outputFile.write("domain={}\n".format(self.domain)) if self.enable_tftp: outputFile.write("enable-tftp\n") if self.expandhosts: outputFile.write("expand-hosts\n") if self.noresolv: outputFile.write("no-resolv\n") if self.tftp_root is not None: outputFile.write("tftp-root={}\n".format(self.tftp_root)) if self.server: for server in self.server: outputFile.write("server={}\n".format(server)) # TODO: Bind interfaces allows us to have multiple instances of # dnsmasq running, but it would probably be better to have one # running and reconfigure it when we want to add or remove # interfaces. It is not very disruptive to reconfigure and restart # dnsmasq. outputFile.write("\n") outputFile.write("except-interface=lo\n") outputFile.write("bind-interfaces\n") for intfName in interfaces: interface = self.lookup(allConfigs, "network", "interface", intfName) outputFile.write("\n") outputFile.write("# Options for section interface {}\n". format(interface.name)) outputFile.write("interface={}\n".format( interface.config_ifname)) network = ipaddress.IPv4Network(u"{}/{}".format( interface.ipaddr, interface.netmask), strict=False) dhcp = self.lookup(allConfigs, "dhcp", "dhcp", intfName) outputFile.write("\n") outputFile.write("# Options for section dhcp {}\n". format(interface.name)) if None not in [dhcp.start, dhcp.limit, dhcp.leasetime]: # TODO: Error checking! firstAddress = network.network_address + dhcp.start lastAddress = firstAddress + dhcp.limit outputFile.write("dhcp-range={},{},{},{}\n".format( str(firstAddress), str(lastAddress), interface.netmask, dhcp.leasetime)) # Write options sections to the config file. for option in dhcp.dhcp_option: outputFile.write("dhcp-option={}\n".format(option)) for relay in dhcp.relay: outputFile.write("dhcp-relay={}\n".format(relay)) if dhcp.relay: outputFile.write("dhcp-proxy\n") outputFile.write("\n") for domain in self.findByType(allConfigs, "dhcp", "domain"): outputFile.write("address=/{}/{}\n".format(domain.name, domain.ip)) cmd = ["dnsmasq", "--conf-file={}".format(outputPath), "--pid-file={}".format(pidFile)] commands.append((self.PRIO_START_DAEMON, Command(cmd, self))) self.pidFile = pidFile return commands
def test_pdoqs(mOs): assert pdosq.makedirs('test') mOs.makedirs.assert_called_once_with('test')
def getSystemConfigDir(): base = settings.UCI_CONFIG_DIR pdosq.makedirs(base) return base