Remove some troublesome trailing slashes from paths
[catalyst.git] / modules / generic_stage_target.py
index fc54fbf263f82bd5583101cf408029b79b26111c..89b891bb0d411b718a73e3cc9ccc3a5edae18364 100644 (file)
@@ -4,6 +4,36 @@ from generic_target import *
 from stat import *
 import catalyst_lock
 
 from stat import *
 import catalyst_lock
 
+
+PORT_LOGDIR_CLEAN = \
+       'find "${PORT_LOGDIR}" -type f ! -name "summary.log*" -mtime +30 -delete'
+
+TARGET_MOUNTS_DEFAULTS = {
+       "ccache": "/var/tmp/ccache",
+       "dev": "/dev",
+       "devpts": "/dev/pts",
+       "distdir": "/usr/portage/distfiles",
+       "icecream": "/usr/lib/icecc/bin",
+       "kerncache": "/tmp/kerncache",
+       "packagedir": "/usr/portage/packages",
+       "portdir": "/usr/portage",
+       "port_tmpdir": "/var/tmp/portage",
+       "port_logdir": "/var/log/portage",
+       "proc": "/proc",
+       "shm": "/dev/shm",
+       }
+
+SOURCE_MOUNTS_DEFAULTS = {
+       "dev": "/dev",
+       "devpts": "/dev/pts",
+       "distdir": "/usr/portage/distfiles",
+       "portdir": "/usr/portage",
+       "port_tmpdir": "tmpfs",
+       "proc": "/proc",
+       "shm": "shmfs",
+       }
+
+
 class generic_stage_target(generic_target):
        """
        This class does all of the chroot setup, copying of files, etc. It is
 class generic_stage_target(generic_target):
        """
        This class does all of the chroot setup, copying of files, etc. It is
@@ -173,17 +203,24 @@ class generic_stage_target(generic_target):
                        file_locate(self.settings,["portage_confdir"],expand=0)
 
                """ Setup our mount points """
                        file_locate(self.settings,["portage_confdir"],expand=0)
 
                """ Setup our mount points """
-               if "SNAPCACHE" in self.settings:
-                       self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles","/var/tmp/portage"]
-                       self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
-                               "/usr/portage":self.settings["snapshot_cache_path"]+"/portage",\
-                               "/usr/portage/distfiles":self.settings["distdir"],"/var/tmp/portage":"tmpfs"}
-               else:
-                       self.mounts=["/proc","/dev","/usr/portage/distfiles","/var/tmp/portage"]
-                       self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
-                               "/usr/portage/distfiles":self.settings["distdir"],"/var/tmp/portage":"tmpfs"}
+               # initialize our target mounts.
+               self.target_mounts = TARGET_MOUNTS_DEFAULTS.copy()
+
+               self.mounts = ["proc", "dev", "portdir", "distdir", "port_tmpdir"]
+               # initialize our source mounts
+               self.mountmap = SOURCE_MOUNTS_DEFAULTS.copy()
+               # update them from settings
+               self.mountmap["distdir"] = self.settings["distdir"]
+               self.mountmap["portdir"] = normpath("/".join([
+                       self.settings["snapshot_cache_path"],
+                       self.settings["repo_name"],
+                       ]))
+               if "SNAPCACHE" not in self.settings:
+                       self.mounts.remove("portdir")
+                       #self.mountmap["portdir"] = None
                if os.uname()[0] == "Linux":
                if os.uname()[0] == "Linux":
-                       self.mounts.append("/dev/pts")
+                       self.mounts.append("devpts")
+                       self.mounts.append("shm")
 
                self.set_mounts()
 
 
                self.set_mounts()
 
@@ -195,16 +232,15 @@ class generic_stage_target(generic_target):
                        self.set_pkgcache_path()
                        print "Location of the package cache is "+\
                                self.settings["pkgcache_path"]
                        self.set_pkgcache_path()
                        print "Location of the package cache is "+\
                                self.settings["pkgcache_path"]
-                       self.mounts.append("/usr/portage/packages")
-                       self.mountmap["/usr/portage/packages"]=\
-                               self.settings["pkgcache_path"]
+                       self.mounts.append("packagedir")
+                       self.mountmap["packagedir"] = self.settings["pkgcache_path"]
 
                if "KERNCACHE" in self.settings:
                        self.set_kerncache_path()
                        print "Location of the kerncache is "+\
                                self.settings["kerncache_path"]
 
                if "KERNCACHE" in self.settings:
                        self.set_kerncache_path()
                        print "Location of the kerncache is "+\
                                self.settings["kerncache_path"]
-                       self.mounts.append("/tmp/kerncache")
-                       self.mountmap["/tmp/kerncache"]=self.settings["kerncache_path"]
+                       self.mounts.append("kerncache")
+                       self.mountmap["kerncache"] = self.settings["kerncache_path"]
 
                if "CCACHE" in self.settings:
                        if "CCACHE_DIR" in os.environ:
 
                if "CCACHE" in self.settings:
                        if "CCACHE_DIR" in os.environ:
@@ -216,21 +252,22 @@ class generic_stage_target(generic_target):
                                raise CatalystError,\
                                        "Compiler cache support can't be enabled (can't find "+\
                                        ccdir+")"
                                raise CatalystError,\
                                        "Compiler cache support can't be enabled (can't find "+\
                                        ccdir+")"
-                       self.mounts.append("/var/tmp/ccache")
-                       self.mountmap["/var/tmp/ccache"]=ccdir
+                       self.mounts.append("ccache")
+                       self.mountmap["ccache"] = ccdir
                        """ for the chroot: """
                        """ for the chroot: """
-                       self.env["CCACHE_DIR"]="/var/tmp/ccache"
+                       self.env["CCACHE_DIR"] = self.target_mounts["ccache"]
 
                if "ICECREAM" in self.settings:
 
                if "ICECREAM" in self.settings:
-                       self.mounts.append("/var/cache/icecream")
-                       self.mountmap["/var/cache/icecream"]="/var/cache/icecream"
-                       self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"]
+                       self.mounts.append("icecream")
+                       self.mountmap["icecream"] = self.settings["icecream"]
+                       self.env["PATH"] = self.target_mounts["icecream"] + ":" + \
+                               self.env["PATH"]
 
                if "port_logdir" in self.settings:
 
                if "port_logdir" in self.settings:
-                       self.mounts.append("/var/log/portage")
-                       self.mountmap["/var/log/portage"]=self.settings["port_logdir"]
-                       self.env["PORT_LOGDIR"]="/var/log/portage"
-                       self.env["PORT_LOGDIR_CLEAN"]='find "${PORT_LOGDIR}" -type f ! -name "summary.log*" -mtime +30 -delete'
+                       self.mounts.append("port_logdir")
+                       self.mountmap["port_logdir"] = self.settings["port_logdir"]
+                       self.env["PORT_LOGDIR"] = self.settings["port_logdir"]
+                       self.env["PORT_LOGDIR_CLEAN"] = PORT_LOGDIR_CLEAN
 
        def override_cbuild(self):
                if "CBUILD" in self.makeconf:
 
        def override_cbuild(self):
                if "CBUILD" in self.makeconf:
@@ -410,7 +447,8 @@ class generic_stage_target(generic_target):
 
        def set_snapshot_path(self):
                self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
 
        def set_snapshot_path(self):
                self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
-                       "/snapshots/portage-"+self.settings["snapshot"]+".tar.xz")
+                       "/snapshots/" + self.settings["snapshot_name"] +
+                       self.settings["snapshot"] + ".tar.xz")
 
                if os.path.exists(self.settings["snapshot_path"]):
                        self.settings["snapshot_path_hash"]=\
 
                if os.path.exists(self.settings["snapshot_path"]):
                        self.settings["snapshot_path_hash"]=\
@@ -418,7 +456,8 @@ class generic_stage_target(generic_target):
                                hash_function=self.settings["hash_function"],verbose=False)
                else:
                        self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
                                hash_function=self.settings["hash_function"],verbose=False)
                else:
                        self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
-                               "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
+                               "/snapshots/" + self.settings["snapshot_name"] +
+                               self.settings["snapshot"] + ".tar.bz2")
 
                        if os.path.exists(self.settings["snapshot_path"]):
                                self.settings["snapshot_path_hash"]=\
 
                        if os.path.exists(self.settings["snapshot_path"]):
                                self.settings["snapshot_path_hash"]=\
@@ -427,20 +466,20 @@ class generic_stage_target(generic_target):
 
        def set_snapcache_path(self):
                if "SNAPCACHE" in self.settings:
 
        def set_snapcache_path(self):
                if "SNAPCACHE" in self.settings:
-                       self.settings["snapshot_cache_path"]=\
-                               normpath(self.settings["snapshot_cache"]+"/"+\
-                               self.settings["snapshot"]+"/")
+                       self.settings["snapshot_cache_path"] = \
+                               normpath(self.settings["snapshot_cache"] + "/" +
+                                       self.settings["snapshot"])
                        self.snapcache_lock=\
                                catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
                        print "Caching snapshot to "+self.settings["snapshot_cache_path"]
 
        def set_chroot_path(self):
                """
                        self.snapcache_lock=\
                                catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
                        print "Caching snapshot to "+self.settings["snapshot_cache_path"]
 
        def set_chroot_path(self):
                """
-               NOTE: the trailing slash is very important!
-               Things *will* break without it!
+               NOTE: the trailing slash has been removed
+               Things *could* break if you don't use a proper join()
                """
                self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
                """
                self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
-                       "/tmp/"+self.settings["target_subpath"]+"/")
+                       "/tmp/"+self.settings["target_subpath"])
                self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
 
        def set_autoresume_path(self):
                self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
 
        def set_autoresume_path(self):
@@ -601,33 +640,34 @@ class generic_stage_target(generic_target):
                                "kill-chroot-pids script failed.",env=self.env)
 
        def mount_safety_check(self):
                                "kill-chroot-pids script failed.",env=self.env)
 
        def mount_safety_check(self):
-               mypath=self.settings["chroot_path"]
-
                """
                Check and verify that none of our paths in mypath are mounted. We don't
                want to clean up with things still mounted, and this allows us to check.
                Returns 1 on ok, 0 on "something is still mounted" case.
                """
 
                """
                Check and verify that none of our paths in mypath are mounted. We don't
                want to clean up with things still mounted, and this allows us to check.
                Returns 1 on ok, 0 on "something is still mounted" case.
                """
 
-               if not os.path.exists(mypath):
+               if not os.path.exists(self.settings["chroot_path"]):
                        return
 
                        return
 
+               print "self.mounts =", self.mounts
                for x in self.mounts:
                for x in self.mounts:
-                       if not os.path.exists(mypath+x):
+                       target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
+                       print "mount_safety_check() x =", x, target
+                       if not os.path.exists(target):
                                continue
 
                                continue
 
-                       if ismount(mypath+x):
+                       if ismount(target):
                                """ Something is still mounted "" """
                                try:
                                """ Something is still mounted "" """
                                try:
-                                       print x+" is still mounted; performing auto-bind-umount...",
+                                       print target + " is still mounted; performing auto-bind-umount...",
                                        """ Try to umount stuff ourselves """
                                        self.unbind()
                                        """ Try to umount stuff ourselves """
                                        self.unbind()
-                                       if ismount(mypath+x):
-                                               raise CatalystError, "Auto-unbind failed for "+x
+                                       if ismount(target):
+                                               raise CatalystError, "Auto-unbind failed for " + target
                                        else:
                                                print "Auto-unbind successful..."
                                except CatalystError:
                                        else:
                                                print "Auto-unbind successful..."
                                except CatalystError:
-                                       raise CatalystError, "Unable to auto-unbind "+x
+                                       raise CatalystError, "Unable to auto-unbind " + target
 
        def unpack(self):
                unpack=True
 
        def unpack(self):
                unpack=True
@@ -767,8 +807,8 @@ class generic_stage_target(generic_target):
 
                if "SNAPCACHE" in self.settings:
                        snapshot_cache_hash=\
 
                if "SNAPCACHE" in self.settings:
                        snapshot_cache_hash=\
-                               read_from_clst(self.settings["snapshot_cache_path"]+\
-                               "catalyst-hash")
+                               read_from_clst(self.settings["snapshot_cache_path"] + "/" +
+                                       "catalyst-hash")
                        destdir=self.settings["snapshot_cache_path"]
                        if "bz2" == self.settings["chroot_path"][-3:]:
                                unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
                        destdir=self.settings["snapshot_cache_path"]
                        if "bz2" == self.settings["chroot_path"][-3:]:
                                unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
@@ -821,7 +861,8 @@ class generic_stage_target(generic_target):
                        cmd(unpack_cmd,unpack_errmsg,env=self.env)
 
                        if "SNAPCACHE" in self.settings:
                        cmd(unpack_cmd,unpack_errmsg,env=self.env)
 
                        if "SNAPCACHE" in self.settings:
-                               myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
+                               myf=open(self.settings["snapshot_cache_path"] +
+                                       "/" + "catalyst-hash","w")
                                myf.write(self.settings["snapshot_path_hash"])
                                myf.close()
                        else:
                                myf.write(self.settings["snapshot_path_hash"])
                                myf.close()
                        else:
@@ -872,10 +913,10 @@ class generic_stage_target(generic_target):
                                if os.path.exists(x):
                                        print "Copying overlay dir " +x
                                        cmd("mkdir -p "+self.settings["chroot_path"]+\
                                if os.path.exists(x):
                                        print "Copying overlay dir " +x
                                        cmd("mkdir -p "+self.settings["chroot_path"]+\
-                                               "/usr/local/portage",\
+                                               self.settings["local_overlay"],\
                                                "Could not make portage_overlay dir",env=self.env)
                                        cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
                                                "Could not make portage_overlay dir",env=self.env)
                                        cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
-                                               "/usr/local/portage",\
+                                               self.settings["local_overlay"],\
                                                "Could not copy portage_overlay",env=self.env)
 
        def root_overlay(self):
                                                "Could not copy portage_overlay",env=self.env)
 
        def root_overlay(self):
@@ -895,35 +936,43 @@ class generic_stage_target(generic_target):
 
        def bind(self):
                for x in self.mounts:
 
        def bind(self):
                for x in self.mounts:
-                       if not os.path.exists(self.settings["chroot_path"]+x):
-                               os.makedirs(self.settings["chroot_path"]+x,0755)
+                       #print "bind(); x =", x
+                       target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
+                       if not os.path.exists(target):
+                               os.makedirs(target, 0755)
 
                        if not os.path.exists(self.mountmap[x]):
 
                        if not os.path.exists(self.mountmap[x]):
-                               if not self.mountmap[x] == "tmpfs":
-                                       os.makedirs(self.mountmap[x],0755)
+                               if self.mountmap[x] not in ["tmpfs", "shmfs"]:
+                                       os.makedirs(self.mountmap[x], 0755)
 
                        src=self.mountmap[x]
 
                        src=self.mountmap[x]
-                       if "SNAPCACHE" in self.settings and x == "/usr/portage":
+                       #print "bind(); src =", src
+                       if "SNAPCACHE" in self.settings and x == "portdir":
                                self.snapshot_lock_object.read_lock()
                        if os.uname()[0] == "FreeBSD":
                                if src == "/dev":
                                self.snapshot_lock_object.read_lock()
                        if os.uname()[0] == "FreeBSD":
                                if src == "/dev":
-                                       retval=os.system("mount -t devfs none "+\
-                                               self.settings["chroot_path"]+x)
+                                       cmd = "mount -t devfs none " + target
+                                       retval=os.system(cmd)
                                else:
                                else:
-                                       retval=os.system("mount_nullfs "+src+" "+\
-                                               self.settings["chroot_path"]+x)
+                                       cmd = "mount_nullfs " + src + " " + target
+                                       retval=os.system(cmd)
                        else:
                                if src == "tmpfs":
                                        if "var_tmpfs_portage" in self.settings:
                        else:
                                if src == "tmpfs":
                                        if "var_tmpfs_portage" in self.settings:
-                                               retval=os.system("mount -t tmpfs -o size="+\
-                                                       self.settings["var_tmpfs_portage"]+"G "+src+" "+\
-                                                       self.settings["chroot_path"]+x)
+                                               cmd = "mount -t tmpfs -o size=" + \
+                                                       self.settings["var_tmpfs_portage"] + "G " + \
+                                                       src + " " + target
+                                               retval=os.system(cmd)
+                               elif src == "shmfs":
+                                       cmd = "mount -t tmpfs -o noexec,nosuid,nodev shm " + target
+                                       retval=os.system(cmd)
                                else:
                                else:
-                                       retval=os.system("mount --bind "+src+" "+\
-                                               self.settings["chroot_path"]+x)
+                                       cmd = "mount --bind " + src + " " + target
+                                       #print "bind(); cmd =", cmd
+                                       retval=os.system(cmd)
                        if retval!=0:
                                self.unbind()
                        if retval!=0:
                                self.unbind()
-                               raise CatalystError,"Couldn't bind mount "+src
+                               raise CatalystError,"Couldn't bind mount " + src
 
        def unbind(self):
                ouch=0
 
        def unbind(self):
                ouch=0
@@ -932,25 +981,25 @@ class generic_stage_target(generic_target):
                myrevmounts.reverse()
                """ Unmount in reverse order for nested bind-mounts """
                for x in myrevmounts:
                myrevmounts.reverse()
                """ Unmount in reverse order for nested bind-mounts """
                for x in myrevmounts:
-                       if not os.path.exists(mypath+x):
+                       target = normpath(mypath + self.target_mounts[x])
+                       if not os.path.exists(target):
                                continue
 
                                continue
 
-                       if not ismount(mypath+x):
+                       if not ismount(target):
                                continue
 
                                continue
 
-                       retval=os.system("umount "+\
-                               os.path.join(mypath,x.lstrip(os.path.sep)))
+                       retval=os.system("umount " + target)
 
                        if retval!=0:
 
                        if retval!=0:
-                               warn("First attempt to unmount: "+mypath+x+" failed.")
+                               warn("First attempt to unmount: " + target + " failed.")
                                warn("Killing any pids still running in the chroot")
 
                                self.kill_chroot_pids()
 
                                warn("Killing any pids still running in the chroot")
 
                                self.kill_chroot_pids()
 
-                               retval2=os.system("umount "+mypath+x)
+                               retval2 = os.system("umount " + target)
                                if retval2!=0:
                                        ouch=1
                                if retval2!=0:
                                        ouch=1
-                                       warn("Couldn't umount bind mount: "+mypath+x)
+                                       warn("Couldn't umount bind mount: " + target)
 
                        if "SNAPCACHE" in self.settings and x == "/usr/portage":
                                try:
 
                        if "SNAPCACHE" in self.settings and x == "/usr/portage":
                                try:
@@ -1066,7 +1115,7 @@ class generic_stage_target(generic_target):
 
                        myf.write('PORTDIR="%s"\n' % self.settings['portdir'])
                        myf.write('DISTDIR="%s"\n' % self.settings['distdir'])
 
                        myf.write('PORTDIR="%s"\n' % self.settings['portdir'])
                        myf.write('DISTDIR="%s"\n' % self.settings['distdir'])
-                       myf.write('PKGDIR="${PORTDIR}/packages"\n')
+                       myf.write('PKGDIR="%s"\n' % self.settings['packagedir'])
 
                        """ Setup the portage overlay """
                        if "portage_overlay" in self.settings:
 
                        """ Setup the portage overlay """
                        if "portage_overlay" in self.settings:
@@ -1116,9 +1165,9 @@ class generic_stage_target(generic_target):
                                "Could not replace /etc/hosts",env=self.env)
 
                """ Remove our overlay """
                                "Could not replace /etc/hosts",env=self.env)
 
                """ Remove our overlay """
-               if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
-                       cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
-                               "Could not remove /usr/local/portage",env=self.env)
+               if os.path.exists(self.settings["chroot_path"] + self.settings["local_overlay"]):
+                       cmd("rm -rf " + self.settings["chroot_path"] + self.settings["local_overlay"],
+                               "Could not remove " + self.settings["local_overlay"], env=self.env)
                        cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
                                "/etc/portage/make.conf",\
                                "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
                        cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
                                "/etc/portage/make.conf",\
                                "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)