def check_required_files(self): for loc in self.required_files: try: matches = glob(self.settings[loc]) except: raise MetroError("Setting %s is set to %s; glob failed." % (loc, repr(self.settings[loc]))) if len(matches) == 0: raise MetroError("Required file " + self.settings[loc] + " not found. Aborting.") elif len(matches) > 1: raise MetroError( "Multiple matches found for required file pattern defined in '%s'; Aborting." % loc)
def cmd(self, mycmd, myexc="", badval=None): self.cr.mesg("Executing \"" + mycmd + "\"...") try: sys.stdout.flush() retval = self.cr.run(mycmd.split(), self.env) if badval: # This code is here because tar has a retval of 1 for non-fatal warnings if retval == badval: raise MetroError(myexc) else: if retval != 0: raise MetroError(myexc) except: raise
def unbind(self, attempt=0): mounts = self.get_active_mounts() while len(mounts) != 0: # now, go through our dictionary and try to unmount progress = 0 mpos = 0 while mpos < len(mounts): self.cmd("umount " + mounts[mpos], badval=10) if not ismount(mounts[mpos]): del mounts[mpos] progress += 1 else: mpos += 1 if progress == 0: break mounts = self.get_active_mounts() if len(mounts): if attempt >= 20: mstring = "" for mount in mounts: mstring += mount + "\n" raise MetroError( "The following bind mounts could not be unmounted: \n" + mstring) else: attempt += 1 self.kill_chroot_pids() self.unbind(attempt=attempt)
def bind(self): """ Perform bind mounts """ os.system(self.cmds["mount"] + " none -t proc %s/proc" % self.settings["path/work"]) for d in ["/dev/shm", "/dev/pts"]: if not os.path.exists("%s%s" % (self.settings["path/work"], d)): os.makedirs("%s%s" % (self.settings["path/work"], d)) os.system(self.cmds["mount"] + " none -t tmpfs -o mode=1777 %s/dev/shm" % self.settings["path/work"]) os.system( self.cmds["mount"] + " none -t devpts -o rw,relatime,gid=5,mode=620,ptmxmode=000 %s/dev/pts" % self.settings["path/work"]) for dst, src in list(self.mounts.items()): if not os.path.exists(src): os.makedirs(src, 0o755) wdst = self.settings["path/work"] + dst if not os.path.exists(wdst): os.makedirs(wdst, 0o755) self.cr.mesg("Mounting %s to %s ..." % (src, dst)) if os.system(self.cmds["mount"] + " -R " + src + " " + wdst) != 0: self.unbind() raise MetroError("Couldn't bind mount " + src) self.mounts["/dev/pts"] = "/dev/pts" self.mounts["/dev/shm"] = "/dev/shm" self.mounts["/proc"] = "/proc"
def run_script(self, key, chroot=None, optional=False, error_scan=False): if key not in self.settings: if optional: return raise MetroError("run_script: key '%s' not found." % (key, )) if type(self.settings[key]) != list: raise MetroError( "run_script: key '%s' is not a multi-line element." % (key, )) self.cr.mesg("run_script: running %s..." % key) if chroot: chrootfile = "/tmp/" + key + ".metro" outfile = chroot + chrootfile else: outfile = self.settings["path/tmp"] + "/pid/" + repr(os.getpid()) outdir = os.path.dirname(outfile) if not os.path.exists(outdir): os.makedirs(outdir) with open(outfile, "w") as outfd: outfd.write("\n".join(self.settings[key]) + "\n") os.chmod(outfile, 0o755) cmds = [] if chroot: if self.settings["target/arch_desc"] == "x86-32bit" and os.uname( )[4] == "x86_64": cmds.append(self.cmds["linux32"]) cmds.append(self.cmds["chroot"]) cmds.append(chroot) cmds.append(chrootfile) else: cmds.append(outfile) retval = self.cr.run(cmds, env=self.env, error_scan=error_scan) if retval != 0: raise MetroError("Command failure (key %s, return value %s) : %s" % (key, repr(retval), " ".join(cmds))) # it could have been cleaned by our outscript, so if it exists: if os.path.exists(outfile): os.unlink(outfile)
def prepare_remote(self): if self.settings["target/arch_desc"] not in ["x86-64bit", "x86-32bit"]: raise MetroError( "VirtualBox target class only supports x86 targets") for mod in ["vboxdrv", "vboxpci", "vboxnetadp", "vboxnetflt"]: self.cmd(self.cmds["modprobe"] + " " + mod) self.ssh_key_path = self.settings["path/config"] + "/keys/vagrant"
def run_script_at_remote(self, key, optional=False): if key not in self.settings: if optional: return raise MetroError("run_script: key '%s' not found." % (key, )) if type(self.settings[key]) != list: raise MetroError( "run_script: key '%s' is not a multi-line element." % (key, )) print("run_script_at_remote: running %s..." % key) ssh = self.ssh_pipe_to_remote("sudo -i /bin/bash -s") ssh.stdin.write("\n".join(self.settings[key])) ssh.stdin.close() ssh.wait() if ssh.returncode != 0: raise MetroError("Command failure (key %s, return value %s)" % (key, repr(ssh.returncode)))
def bind(self): """ Perform bind mounts """ for dst, src in list(self.mounts.items()): if not os.path.exists(src): os.makedirs(src, 0o755) wdst = self.settings["path/work"] + dst if not os.path.exists(wdst): os.makedirs(wdst, 0o755) self.cr.mesg("Mounting %s to %s ..." % (src, dst)) if os.system(self.cmds["mount"] + " -R " + src + " " + wdst) != 0: self.unbind() raise MetroError("Couldn't bind mount " + src)
def __init__(self, settings, cr): BaseTarget.__init__(self, settings, cr) # we need a source archive self.required_files.append("path/mirror/source") # define general linux mount points self.mounts = {"/proc": "/proc", "/dev": "/dev"} if "target/class" not in self.settings: return okey = "metro/options/" + self.settings["target/class"] if okey not in self.settings: return options = self.settings[okey].split() # define various mount points for our cache support (ccache, binpkgs, # genkernel, etc). caches = [ [ "path/cache/compiler", "cache/compiler", "/var/tmp/cache/compiler" ], ["path/cache/package", "cache/package", "/var/tmp/cache/package"], ["path/cache/kernel", "cache/kernel", "/var/tmp/cache/kernel"], ["path/cache/probe", "probe", "/var/tmp/cache/probe"], ] for key, name, dst in caches: if name in options: if key not in self.settings: raise MetroError( "Required setting %s not found (for %s option support)" % (key, name)) if self.settings[key] != None: # package cache dir will not be defined for snapshot... self.cr.mesg("Enabling cache: %s" % key) self.mounts[dst] = self.settings[key]
def prepare_remote(self): if self.settings["target/arch"] not in ["amd64", "x86"]: raise MetroError("EC2 target class only supports x86 targets") self.clean_remote() self.ec2.create_security_group(self.name, self.name) self.ec2.authorize_security_group(group_name=self.name, ip_protocol='tcp', from_port=22, to_port=22, cidr_ip='0.0.0.0/0') self.ssh_key_path = "%s/%s.pem" % (self.settings["path/tmp"], self.name) try: os.unlink(self.ssh_key_path) except: pass key_pair = self.ec2.create_key_pair(self.name) key_pair.save(self.settings["path/tmp"])