def clean(self, force=False): ''' Clean the repository's content ''' # Check if the repo is local if not self.local: raise ISError(u"Repository must be local") allmd5 = set(self.getallmd5()) repofiles = set(listdir(self.config.path)) - set([self.config.dbname, self.config.lastname]) dirtyfiles = repofiles - allmd5 if len(dirtyfiles) > 0: # print dirty files arrow("Dirty files:") for f in dirtyfiles: arrow(f, 1) # ask confirmation if not force and not confirm("Remove dirty files? (yes) "): raise ISError(u"Aborted!") # start cleaning arrow("Cleaning") for f in dirtyfiles: p = join(self.config.path, f) arrow(u"Removing %s" % p, 1) try: if isdir(p): rmdir(p) else: unlink(p) except: warn(u"Removing %s failed" % p) else: arrow("Nothing to clean")
def cat(self, filename): ''' Display filename in the tarball ''' filelist = self._tarball.getnames(glob_pattern=filename, dir=False) if len(filelist) == 0: warn(u"No file matching %s" % filename) for filename in filelist: arrow(filename) out(self._tarball.get_utf8(filename))
def update(self, *args, **kwargs): ''' Update attribute with checking value All attribute must already exists ''' # autoset parameter in cmdline for k in kwargs: if hasattr(self, k): try: setattr(self, k, kwargs[k]) except Exception as e: warn(u"Unable to set config parameter %s in repository %s: %s" % (k, self.name, e)) else: debug(u"No such repository parameter: %s" % k)
def read_metadata(self): ''' Parse tarball and return metadata dict ''' desc = {} # check format img_format = self._tarball.get_utf8("format") try: if float(img_format) >= floor(float(SourceImage.format)) + 1.0: raise Exception() except: raise ISError(u"Invalid image format %s" % img_format) desc["format"] = img_format # check description try: img_desc = self._tarball.get_utf8("description.json") desc.update(loads(img_desc)) self.check_name(desc["name"]) self.check_version(desc["version"]) if "compressor" not in desc: desc["compressor"] = "gzip = *" else: # format compressor pattern string compressor_str = "" for compressor, patterns in desc["compressor"]: # if pattern is not empty if patterns != ['']: compressor_str += "%s = %s\n" % (compressor, ", ".join(patterns)) # remove extra endline desc["compressor"] = compressor_str[:-1] # add is_min_version if not present if "is_min_version" not in desc: desc["is_min_version"] = 0 # check installsystems min version if self.compare_versions(VERSION, desc["is_min_version"]) < 0: raise ISError("Minimum Installsystems version not satisfied " "(%s)" % desc["is_min_version"]) except Exception as e: raise ISError(u"Invalid description", e) # try to load changelog try: img_changelog = self._tarball.get_utf8("changelog") desc["changelog"] = Changelog(img_changelog) except KeyError: desc["changelog"] = Changelog("") except Exception as e: warn(u"Invalid changelog: %s" % e) return desc
def validate(self): ''' Validate the configuration file according to the configuration specification If some values doesn't respect specification, she's ignored and a warning is issued. ''' res = self.config.validate(Validator(), preserve_errors=True) # If everything is fine, the validation return True # Else, it returns a list of (section, optname, error) if res is not True: for section, optname, error in flatten_errors(self.config, res): # If error is False, this mean no value as been supplied, # so we use the default value # Else, the check has failed if error: warn("%s: %s Skipped" % (optname, error)) # remove wrong value to avoid merging it with argparse value del self.config[section[0]][optname]
def create(self, config): db = None if not config.offline: try: db = Database(config.dbpath) except ISWarning as e: warn('[%s]: %s' % (config.name, e)) config.offline = True except ISError: debug(u"Unable to load database %s" % config.dbpath) config.offline = True if config.offline: debug(u"Repository %s is offline" % config.name) if db is None: return Repository2(config) else: return self.repo_class[int(db.version)](config, db)
nettype = 'network' netsource = "network='%s'" % (namespace.nat if namespace.nat is not None else 'default') arrow('Defining libvirt domain', 1) with tempfile.NamedTemporaryFile() as tmp: tmp.file.write(vm_template.format(name=namespace.fqdn, memory=(namespace.memory * 1024), cpu=namespace.cpu, disk=namespace.disk, nettype=nettype, netsource=netsource)) tmp.flush() check_call(['virsh', 'define', tmp.name], close_fds=True) # retrieve autogenerated mac address xml = check_output(['virsh', 'dumpxml', namespace.fqdn], close_fds=True) namespace.mac = re.search("mac address='([^']+)'", xml).groups()[0] if namespace.autostart: arrow('Set domain as autostart', 1) try: check_call(['virsh', 'autostart', namespace.fqdn], close_fds=True) except CalledProcessError as e: warn('Unable to set autostart domain: %s' % e) if namespace.start: arrow('Starting domain') check_call(['virsh', 'start', namespace.fqdn], close_fds=True)
# -*- python -* # -*- coding: utf-8 -*- import os from installsystems.printer import arrow, warn if namespace.snmp: arrow('Enable snmpd') snmp_v3 = (namespace.snmp_user, namespace.snmp_auth, namespace.snmp_enc) if any(snmp_v3) and not all(snmp_v3): warn('If you want to use snmp v3, please provide all arguments: user, ' 'auth pass phrase and encryption pass phrase') else: arrow('Add snmp v3 user "%s"' % namespace.snmp_user) with open(os.path.join(namespace.target, 'usr', 'share', 'snmp', 'snmpd.conf'), 'w') as fi: fi.write('rouser %s' % namespace.snmp_user) with open(os.path.join(namespace.target, 'var', 'lib', 'snmp', 'snmpd.conf'), 'w') as fi: fi.write('createUser %s SHA %s AES %s' % (namespace.snmp_user, namespace.snmp_auth, namespace.snmp_enc))
def create(cls, path, force=False): ''' Create an empty source image ''' # check local repository if not isfile(path): raise NotImplementedError("SourceImage must be local") # main path build_path = join(path, "build") parser_path = join(path, "parser") setup_path = join(path, "setup") payload_path = join(path, "payload") lib_path = join(path, "lib") # create base directories arrow("Creating base directories") try: for d in (path, build_path, parser_path, setup_path, payload_path, lib_path): if not exists(d) or not isdir(d): mkdir(d) except Exception as e: raise ISError(u"Unable to create directory: %s" % d, e) # create example files arrow("Creating examples") arrowlevel(1) # create dict of file to create examples = {} # create description example from template examples["description"] = { "path": "description", "content": DESCRIPTION_TPL % { "name": "", "version": "1", "description": "", "author": "", "is_min_version": VERSION, "compressor": "gzip = *\nnone = *.gz, *.bz2, *.xz"} } # create changelog example from template examples["changelog"] = {"path": "changelog", "content": CHANGELOG_TPL} # create build example from template examples["build"] = {"path": "build/01-build.py", "content": BUILD_TPL} # create parser example from template examples["parser"] = {"path": "parser/01-parser.py", "content": PARSER_TPL} # create setup example from template examples["setup"] = {"path": "setup/01-setup.py", "content": SETUP_TPL} for name in examples: try: arrow(u"Creating %s example" % name) expath = join(path, examples[name]["path"]) if not force and exists(expath): warn(u"%s already exists. Skipping!" % expath) continue open(expath, "w").write(examples[name]["content"]) except Exception as e: raise ISError(u"Unable to create example file", e) try: # setting executable rights on files in setup and parser arrow("Setting executable rights on scripts") oldmask = umask(0) umask(oldmask) for dpath in (build_path, parser_path, setup_path): for f in listdir(dpath): chrights(join(dpath, f), mode=0777 & ~oldmask) except Exception as e: raise ISError(u"Unable to set rights", e) arrowlevel(-1)
def setmotd(self, value=""): ''' Don't set repository message of the day. Not supported by v1. ''' # check local repository warn(u"Repository v1 doesn't support motd. Unable to set")
# -*- python -*- # -*- coding: utf-8 -*- from subprocess import call from installsystems.printer import warn if namespace.chroot: warn('You are in a chroot. Nothing should stay started inside it. This ' 'will cause failures in setup process!') call(['chroot', namespace.target, '/bin/bash'], close_fds=True)
def unprepare_chroot(path, mount=True): ''' Rollback preparation of a chroot environment inside a directory ''' arrow("Untricks") # check path is a kind of linux FHS if exists(join(path, "etc")) and exists(join(path, "usr")): # untrick mtab mtab_path = join(path, "etc", "mtab") mtab_backup_path = join(path, "etc", "mtab.isbackup") mtab_trick_path = join(path, "etc", "mtab.istrick") if exists(mtab_backup_path) or exists(mtab_trick_path): arrow("mtab", 1) # order matter ! if exists(mtab_trick_path): try: unlink(mtab_path) except OSError: pass try: unlink(mtab_trick_path) except OSError: warn(u"Unable to remove %s" % mtab_trick_path) if exists(mtab_backup_path): try: unlink(mtab_path) except OSError: pass try: rename(mtab_backup_path, mtab_path) except OSError: warn(u"Unable to restore %s" % mtab_backup_path) # untrick resolv.conf resolv_path = join(path, "etc", "resolv.conf") resolv_backup_path = join(path, "etc", "resolv.conf.isbackup") resolv_trick_path = join(path, "etc", "resolv.conf.istrick") if exists(resolv_backup_path) or exists(resolv_trick_path): arrow("resolv.conf", 1) # order matter ! if exists(resolv_trick_path): try: unlink(resolv_path) except OSError: pass try: unlink(resolv_trick_path) except OSError: warn(u"Unable to remove %s" % resolv_trick_path) if exists(resolv_backup_path): try: unlink(resolv_path) except OSError: pass try: rename(resolv_backup_path, resolv_path) except OSError: warn(u"Unable to restore %s" % resolv_backup_path) # try to guest distro distro = guess_distro(path) # cleaning debian stuff if distro == "debian": arrow("Debian specific", 1) for f in ("etc/debian_chroot", "usr/sbin/policy-rc.d"): try: unlink(join(path, f)) except: pass # unmounting if mount: mps = ("proc", "sys", "dev", "dev/pts", "dev/shm") arrow("Unmounting filesystems") for mp in reversed(mps): target = join(path, mp) if ismount(target): arrow(target, 1) call(["umount", target], close_fds=True)
def prepare_chroot(path, mount=True): ''' Prepare a chroot environment by mounting /{proc,sys,dev,dev/pts} and try to guess dest os to avoid daemon launching ''' # try to mount /proc /sys /dev /dev/pts /dev/shm if mount: mps = ("proc", "sys", "dev", "dev/pts", "dev/shm") arrow("Mounting filesystems") for mp in mps: origin = u"/%s" % mp target = join(path, mp) if ismount(target): warn(u"%s is already a mountpoint, skipped" % target) elif ismount(origin) and isdir(target): arrow(u"%s -> %s" % (origin, target), 1) try: check_call(["mount", "--bind", origin, target], close_fds=True) except CalledProcessError as e: warn(u"Mount failed: %s.\n" % e) arrow("Tricks") # check path is a kind of linux FHS if not exists(join(path, "etc")) or not exists(join(path, "usr")): return # trick resolv.conf try: resolv_path = join(path, "etc", "resolv.conf") resolv_backup_path = join(path, "etc", "resolv.conf.isbackup") resolv_trick_path = join(path, "etc", "resolv.conf.istrick") if (exists("/etc/resolv.conf") and not exists(resolv_backup_path) and not exists(resolv_trick_path)): arrow("resolv.conf", 1) if exists(resolv_path): rename(resolv_path, resolv_backup_path) else: open(resolv_trick_path, "wb") copy("/etc/resolv.conf", resolv_path) except Exception as e: warn(u"resolv.conf tricks fail: %s" % e) # trick mtab try: mtab_path = join(path, "etc", "mtab") mtab_backup_path = join(path, "etc", "mtab.isbackup") mtab_trick_path = join(path, "etc", "mtab.istrick") if not exists(mtab_backup_path) and not exists(mtab_trick_path): arrow("mtab", 1) if exists(mtab_path): rename(mtab_path, mtab_backup_path) symlink("/proc/self/mounts", mtab_path) except Exception as e: warn(u"mtab tricks fail: %s" % e) # try to guest distro distro = guess_distro(path) # in case of debian disable policy if distro == "debian": arrow("Debian specific", 1) # create a chroot header try: open(join(path, "etc", "debian_chroot"), "w").write("CHROOT") except: pass # fake policy-rc.d. It must exit 101, it's an expected exitcode. policy_path = join(path, "usr", "sbin", "policy-rc.d") try: open(policy_path, "w").write("#!/bin/bash\nexit 101\n") except: pass # policy-rc.d needs to be executable chrights(policy_path, mode=0755)