Exemplo n.º 1
0
 def getRuntimeCache(self):
     if not self.__runtimeCache:
         self.__runtimeCache = RuntimeCache(self.getUser(), self)
     return self.__runtimeCache
Exemplo n.º 2
0
 def getRuntimeCache(self):
   if not self.__runtimeCache:
     self.__runtimeCache = RuntimeCache(self.user,self)
   else:
     self.__runtimeCache.reload()
   return self.__runtimeCache
Exemplo n.º 3
0
class Subuser(UserOwnedObject, Describable):
  def __init__(self,user,name,imageId,executableShortcutInstalled,locked,serviceSubuserNames,imageSource=None,imageSourceName=None,repoName=None,entrypointsExposed=False,nonDefaultHomeDir=None):
    self.name = name
    self.__imageSource = imageSource
    self.__repoName = repoName
    self.__imageSourceName = imageSourceName
    self.imageId = imageId
    self.executableShortcutInstalled = executableShortcutInstalled
    self.__entryPointsExposed = entrypointsExposed
    self.__entryPointsExposedThisRun = False
    self.locked = locked
    self.serviceSubuserNames = serviceSubuserNames
    self.__x11Bridge = None
    self.__runReadyImage = None
    self.__runtime = None
    self.__runtimeCache = None
    self.__permissions = None
    self.__permissionsTemplate = None
    self.nonDefaultHomeDir = nonDefaultHomeDir
    UserOwnedObject.__init__(self,user)

  @property
  def imageSource(self):
    """
    Note, it is posssible that the subuser's image source no longer exists, in which case this function raises a NoImageSourceException.
    """
    if self.__imageSource is None:
      try:
        self.__imageSource = self.user.registry.repositories[self.__repoName][self.__imageSourceName]
      except KeyError:
        raise NoImageSourceException()
    return self.__imageSource

  @imageSource.setter
  def imageSource(self,new_image_source):
    self.__imageSource=new_image_source
    self.imageId = None

  @property
  def imageSourceName(self):
    if self.__imageSource is None:
      return self.__imageSourceName
    else:
      return self.imageSource.name

  @property
  def sourceRepoName(self):
    if self.__imageSource is None:
      return self.__repoName
    else:
      return self.imageSource.repo.name

  @property
  def entryPointsExposed(self):
    return self.__entryPointsExposed

  @entryPointsExposed.setter
  def entrypointsExposed(self,exposed):
    self.__entryPointsExposed = exposed
    if exposed:
      self.__entryPointsExposedThisRun = True

  def wereEntryPointsExposedThisRun(self):
    return self.__entryPointsExposedThisRun

  @property
  def permissionsDir(self):
    return os.path.join(self.user.config["registry-dir"],"permissions",self.name)

  @property
  def relativePermissionsDir(self):
    """
    Get the permissions directory as relative to the registry's git repository.
    """
    return os.path.join("permissions",self.name)

  def createPermissions(self,permissionsDict):
    permissionsDotJsonWritePath = os.path.join(self.permissionsDir,"permissions.json")
    self.__permissions = Permissions(self.user,initialPermissions=permissionsDict,writePath=permissionsDotJsonWritePath)
    return self.__permissions

  @property
  def permissionsDotJsonWritePath(self):
    return os.path.join(self.permissionsDir,"permissions.json")

  def loadPermissions(self):
    registryFileStructure = self.user.registry.gitRepository.getFileStructureAtCommit(self.user.registry.gitReadHash)
    try:
      initialPermissions = subuserlib.permissions.load(permissionsString=registryFileStructure.read(os.path.join(self.relativePermissionsDir,"permissions.json")),logger=self.user.registry)
    except OSError:
      raise SubuserHasNoPermissionsException("The subuser <"+self.name+"""> has no permissions.

Please run:

$ subuser repair

To repair your subuser installation.\n""")
    except SyntaxError as e:
      sys.exit("The subuser <"+self.name+""">'s permissions appear to be corrupt.

Please file a bug report explaining how you got here.\n"""+ str(e))
    self.__permissions = Permissions(self.user,initialPermissions,writePath=self.permissionsDotJsonWritePath)

  @property
  def permissions(self):
    if self.__permissions is None:
      self.loadPermissions()
    return self.__permissions

  def getPermissionsTemplate(self):
    if self.__permissionsTemplate is None:
      permissionsDotJsonWritePath = os.path.join(self.permissionsDir,"permissions-template.json")
      registryFileStructure = self.user.registry.gitRepository.getFileStructureAtCommit(self.user.registry.gitReadHash)
      if "permissions-template.json" in registryFileStructure.lsFiles(self.relativePermissionsDir):
        initialPermissions = subuserlib.permissions.load(permissionsString=registryFileStructure.read(os.path.join(self.relativePermissionsDir,"permissions-template.json")),logger=self.user.registry)
        save = False
      else:
        initialPermissions = self.imageSource.permissions
        save = True
      self.__permissionsTemplate = Permissions(self.user,initialPermissions,writePath=permissionsDotJsonWritePath)
      if save:
        self.__permissionsTemplate.save()
    return self.__permissionsTemplate

  def editPermissionsCLI(self):
    while True:
      self.user.endUser.runEditor(self.permissions.writePath)
      try:
        initialPermissions = subuserlib.permissions.load(permissionsFilePath=self.permissionsDotJsonWritePath)
        break
      except SyntaxError as e:
        print(e)
        input("Press ENTER to edit the permission file again.")
    self.__permissions = Permissions(self.user,initialPermissions,writePath=self.permissionsDotJsonWritePath)
    self.permissions.save()

  def removePermissions(self):
    """
    Remove the user set and template permission files.
    """
    try:
      self.user.registry.gitRepository.run(["rm",os.path.join(self.relativePermissionsDir,"permissions.json"),os.path.join(self.relativePermissionsDir,"permissions-template.json")])
    except subuserlib.classes.gitRepository.GitException:
      pass
    try:
      self.user.registry.gitRepository.run(["rm",os.path.join(self.relativePermissionsDir,"permissions.json"),os.path.join(self.relativePermissionsDir,"permissions-template.json")])
    except subuserlib.classes.gitRepository.GitException:
      pass

  def isImageInstalled(self):
    return self.user.dockerDaemon.getImageProperties(self.imageId) is not None

  def getRunReadyImage(self):
    if not self.__runReadyImage:
      self.__runReadyImage = RunReadyImage(self.user,self)
    return self.__runReadyImage

  @property
  def x11Bridge(self):
    """
    Return the X11 bridge object for this subuser.
    """
    if not self.__x11Bridge:
      self.__x11Bridge = X11Bridge(self.user,self)
    return self.__x11Bridge

  #TODO clean this up so that we aren't forwarding arguments in needless fluff.
  def getRuntime(self,environment,extraDockerFlags=None,entrypoint=None):
    """
    Returns the subuser's Runtime object for it's current permissions, creating it if necessary.
    """
    if not self.__runtime:
      self.__runtime = Runtime(self.user,subuser=self,environment=environment,extraDockerFlags=extraDockerFlags,entrypoint=entrypoint)
    return self.__runtime

  def getRuntimeCache(self):
    if not self.__runtimeCache:
      self.__runtimeCache = RuntimeCache(self.user,self)
    else:
      self.__runtimeCache.reload()
    return self.__runtimeCache

  def setupHomeDir(self):
    """
    Sets up the subuser's home dir, along with creating symlinks to shared user dirs.
    """
    if self.permissions["basic-common-permissions"] and self.permissions["basic-common-permissions"]["stateful-home"]:
      try:
        self.user.endUser.makedirs(self.homeDirOnHost)
      except OSError as e:
        if e.errno() == errno.EEXIST:
          pass
      if self.permissions["user-dirs"]:
        for userDir in self.permissions["user-dirs"]:
          symlinkPath = os.path.join(self.homeDirOnHost,userDir)
          # https://stackoverflow.com/questions/15718006/check-if-directory-is-symlink
          if symlinkPath.endswith("/"):
            symlinkPath = symlinkPath[:-1]
          destinationPath = os.path.join("/subuser/userdirs",userDir)
          if not os.path.islink(symlinkPath):
            if os.path.exists(symlinkPath):
              self.user.endUser.makedirs(os.path.join(self.homeDirOnHost,"subuser-user-dirs-backups"))
              os.rename(symlinkPath,os.path.join(self.homeDirOnHost,"subuser-user-dirs-backups",userDir))
            try:
              os.symlink(destinationPath,symlinkPath)
              # Arg, why are source and destination switched?
              # os.symlink(where does the symlink point to, where is the symlink)
              # I guess it's to be like cp...
            except OSError:
              pass

  @property
  def homeDirOnHost(self):
    """
    Returns the path to the subuser's home dir. Unless the subuser is configured to have a stateless home, in which case returns None.
    """
    if self.permissions["basic-common-permissions"]["stateful-home"]:
      if self.nonDefaultHomeDir is not None:
        return self.nonDefaultHomeDir
      return os.path.join(self.user.config["subuser-home-dirs-dir"],self.name)
    else:
      return None

  @property
  def dockersideHome(self):
    if self.permissions["as-root"]:
      return "/root/"
    else:
      return "/home/subuser/"

  def describe(self):
    print("Subuser: "******"------------------")
    try:
      print(self.imageSource.getIdentifier())
    except subuserlib.classes.subuser.NoImageSourceException:
      print("Warning: This subuser has no image, nor does it have a valid image source to install an image from.")
    print("Docker image Id: "+str(self.imageId))
    self.permissions.describe()
    print("")

  def installLaunchScript(self,name,script):
    """
    Install a trivial executable script into the PATH which launches the subser image.
    """
    redirect = script
    executablePath=os.path.join(self.user.config["bin-dir"], name)
    with self.user.endUser.get_file(executablePath, 'w') as file_f:
      file_f.write(redirect)
      st = os.stat(executablePath)
      os.chmod(executablePath, stat.S_IMODE(st.st_mode) | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)

  def installExecutableShortcut(self):
    self.installLaunchScript(self.name,"#!/bin/bash\nsubuser run "+self.name+" $@")

  def exposeEntrypoints(self):
    """
    Create launcher executables for the subuser's entrypoints.
    """
    for name,path in self.permissions["entrypoints"].items():
      launchScript = """#!/usr/bin/python3
import subprocess,sys
run = """+json.dumps({"subuser-name":self.name,"entrypoint":path})
      launchScript +="""
sys.exit(subprocess.call(["subuser","run","--entrypoint="+run["entrypoint"],run["subuser-name"]]))
"""
      self.installLaunchScript(name,launchScript)
Exemplo n.º 4
0
class Subuser(UserOwnedObject, Describable):
    def __init__(self, user, name, imageSource, imageId,
                 executableShortcutInstalled, locked, serviceSubusers):
        self.__name = name
        self.__imageSource = imageSource
        self.__imageId = imageId
        self.__executableShortcutInstalled = executableShortcutInstalled
        self.__locked = locked
        self.__serviceSubusers = serviceSubusers
        self.__x11Bridge = None
        self.__runReadyImage = None
        self.__runtime = None
        self.__runtimeCache = None
        self.__permissions = None
        self.__permissionsTemplate = None
        UserOwnedObject.__init__(self, user)

    def getName(self):
        return self.__name

    def getImageSource(self):
        return self.__imageSource

    def isExecutableShortcutInstalled(self):
        return self.__executableShortcutInstalled

    def setExecutableShortcutInstalled(self, installed):
        self.__executableShortcutInstalled = installed

    def getPermissionsDir(self):
        return os.path.join(self.getUser().getConfig()["registry-dir"],
                            "permissions", self.getName())

    def getRelativePermissionsDir(self):
        """
    Get the permissions directory as relative to the registry's git repository.
    """
        return os.path.join("permissions", self.getName())

    def createPermissions(self, permissionsDict):
        permissionsDotJsonWritePath = os.path.join(self.getPermissionsDir(),
                                                   "permissions.json")
        self.__permissions = Permissions(self.getUser(),
                                         initialPermissions=permissionsDict,
                                         writePath=permissionsDotJsonWritePath)
        return self.__permissions

    def getPermissionsDotJsonWritePath(self):
        return os.path.join(self.getPermissionsDir(), "permissions.json")

    def loadPermissions(self):
        registryFileStructure = self.getUser().getRegistry().getGitRepository(
        ).getFileStructureAtCommit(
            self.getUser().getRegistry().getGitReadHash())
        if registryFileStructure.exists(
                os.path.join(self.getRelativePermissionsDir(),
                             "permissions.json")):
            initialPermissions = subuserlib.permissions.getPermissions(
                permissionsString=registryFileStructure.read(
                    os.path.join(self.getRelativePermissionsDir(),
                                 "permissions.json")))
        else:
            raise SubuserHasNoPermissionsException("The subuser <" +
                                                   self.getName() +
                                                   """> has no permissions.

If you are updating sometime around August 2015, you should move ~/.subuser/permissions to ~/.subuser/registry/permissions and run:

$ git add .
$ git commit

Otherwise, please run:

$ subuser repair

To repair your subuser installation.\n""")
        self.__permissions = Permissions(
            self.getUser(),
            initialPermissions,
            writePath=self.getPermissionsDotJsonWritePath())

    def getPermissions(self):
        if self.__permissions is None:
            self.loadPermissions()
        return self.__permissions

    def getPermissionsTemplate(self):
        if self.__permissionsTemplate is None:
            permissionsDotJsonWritePath = os.path.join(
                self.getPermissionsDir(), "permissions-template.json")
            registryFileStructure = self.getUser().getRegistry(
            ).getGitRepository().getFileStructureAtCommit(
                self.getUser().getRegistry().getGitReadHash())
            if os.path.join(self.getRelativePermissionsDir(
            ), "permissions-template.json") in registryFileStructure.lsFiles(
                    self.getRelativePermissionsDir()):
                initialPermissions = subuserlib.permissions.getPermissions(
                    permissionsString=registryFileStructure.read(
                        os.path.join(self.getRelativePermissionsDir(),
                                     "permissions-template.json")))
                save = False
            else:
                initialPermissions = self.getImageSource().getPermissions()
                save = True
            self.__permissionsTemplate = Permissions(
                self.getUser(),
                initialPermissions,
                writePath=permissionsDotJsonWritePath)
            if save:
                self.__permissionsTemplate.save()
        return self.__permissionsTemplate

    def editPermissionsCLI(self):
        try:
            editor = os.environ["EDITOR"]
        except KeyError:
            editor = "/usr/bin/nano"
        subuserlib.subprocessExtras.call(
            [editor, self.getPermissions().getWritePath()])
        initialPermissions = subuserlib.permissions.getPermissions(
            permissionsFilePath=self.getPermissionsDotJsonWritePath())
        self.__permissions = Permissions(
            self.getUser(),
            initialPermissions,
            writePath=self.getPermissionsDotJsonWritePath())
        self.getPermissions().save()

    def removePermissions(self):
        """
    Remove the user set and template permission files.
    """
        self.getUser().getRegistry().getGitRepository().run([
            "rm",
            os.path.join(self.getRelativePermissionsDir(), "permissions.json"),
            os.path.join(self.getRelativePermissionsDir(),
                         "permissions-template.json")
        ])

    def getImageId(self):
        """
    Get the Id of the Docker image associated with this subuser.
    None, if the subuser has no installed image yet.
    """
        return self.__imageId

    def setImageId(self, imageId):
        """
    Set the installed image associated with this subuser.
    """
        self.__imageId = imageId

    def getServiceSubuserNames(self):
        """
    Get this subuser's service subusers.
    """
        return self.__serviceSubusers

    def addServiceSubuser(self, name):
        self.__serviceSubusers.append(name)

    def getRunReadyImage(self):
        if not self.__runReadyImage:
            self.__runReadyImage = RunReadyImage(self.getUser(), self)
        return self.__runReadyImage

    def getX11Bridge(self):
        """
    Return the X11 bridge object for this subuser.
    """
        if not self.__x11Bridge:
            self.__x11Bridge = X11Bridge(self.getUser(), self)
        return self.__x11Bridge

    def getRuntime(self, environment):
        """
    Returns the subuser's Runtime object for it's current permissions, creating it if necessary.
    """
        if not self.__runtime:
            self.__runtime = Runtime(self.getUser(),
                                     subuser=self,
                                     environment=environment)
        return self.__runtime

    def getRuntimeCache(self):
        if not self.__runtimeCache:
            self.__runtimeCache = RuntimeCache(self.getUser(), self)
        else:
            self.__runtimeCache.reload()
        return self.__runtimeCache

    def locked(self):
        """
    Returns True if the subuser is locked.  Users lock subusers in order to prevent updates and rollbacks from effecting them.
    """
        return self.__locked

    def setLocked(self, locked):
        """
    Mark the subuser as locked or unlocked.

    We lock subusers to their current states to prevent updates and rollbacks from effecting them.
    """
        self.__locked = locked

    def getHomeDirOnHost(self):
        """
    Returns the path to the subuser's home dir. Unless the subuser is configured to have a stateless home, in which case returns None.
    """
        if self.getPermissions()["stateful-home"]:
            return os.path.join(
                self.getUser().getConfig()["subuser-home-dirs-dir"],
                self.getName())
        else:
            return None

    def getDockersideHome(self):
        if self.getPermissions()["as-root"]:
            return "/root/"
        else:
            return self.getUser().homeDir

    def describe(self):
        print("Subuser: "******"------------------")
        print(self.getImageSource().getIdentifier())
        self.getPermissions().describe()
        print("")

    def installExecutableShortcut(self):
        """
    Install a trivial executable script into the PATH which launches the subser image.
    """
        redirect = """#!/bin/bash
  subuser run """ + self.getName() + """ $@
  """
        executablePath = os.path.join(self.getUser().getConfig()["bin-dir"],
                                      self.getName())
        with open(executablePath, 'w') as file_f:
            file_f.write(redirect)
            st = os.stat(executablePath)
            os.chmod(
                executablePath,
                stat.S_IMODE(st.st_mode) | stat.S_IXUSR | stat.S_IXGRP
                | stat.S_IXOTH)
Exemplo n.º 5
0
class Subuser(UserOwnedObject, Describable):
    def __init__(self,
                 user,
                 name,
                 imageId,
                 executableShortcutInstalled,
                 locked,
                 serviceSubusers,
                 imageSource=None,
                 imageSourceName=None,
                 repoName=None):
        self.__name = name
        self.__imageSource = imageSource
        self.__repoName = repoName
        self.__imageSourceName = imageSourceName
        self.__imageId = imageId
        self.__executableShortcutInstalled = executableShortcutInstalled
        self.__locked = locked
        self.__serviceSubusers = serviceSubusers
        self.__x11Bridge = None
        self.__runReadyImage = None
        self.__runtime = None
        self.__runtimeCache = None
        self.__permissions = None
        self.__permissionsTemplate = None
        UserOwnedObject.__init__(self, user)

    def getName(self):
        return self.__name

    def getImageSource(self):
        """
    Note, it is posssible that the subuser's image source no longer exists, in which case this function raises a NoImageSourceException.
    """
        if self.__imageSource is None:
            try:
                self.__imageSource = self.getUser().getRegistry(
                ).getRepositories()[self.__repoName][self.__imageSourceName]
            except KeyError:
                raise NoImageSourceException()
        return self.__imageSource

    def getImageSourceName(self):
        if self.__imageSource is None:
            return self.__imageSourceName
        else:
            return self.getImageSource().getName()

    def getSourceRepoName(self):
        if self.__imageSource is None:
            return self.__repoName
        else:
            return self.getImageSource().getRepository().getName()

    def isExecutableShortcutInstalled(self):
        return self.__executableShortcutInstalled

    def setExecutableShortcutInstalled(self, installed):
        self.__executableShortcutInstalled = installed

    def getPermissionsDir(self):
        return os.path.join(self.getUser().getConfig()["registry-dir"],
                            "permissions", self.getName())

    def getRelativePermissionsDir(self):
        """
    Get the permissions directory as relative to the registry's git repository.
    """
        return os.path.join("permissions", self.getName())

    def createPermissions(self, permissionsDict):
        permissionsDotJsonWritePath = os.path.join(self.getPermissionsDir(),
                                                   "permissions.json")
        self.__permissions = Permissions(self.getUser(),
                                         initialPermissions=permissionsDict,
                                         writePath=permissionsDotJsonWritePath)
        return self.__permissions

    def getPermissionsDotJsonWritePath(self):
        return os.path.join(self.getPermissionsDir(), "permissions.json")

    def loadPermissions(self):
        registryFileStructure = self.getUser().getRegistry().getGitRepository(
        ).getFileStructureAtCommit(
            self.getUser().getRegistry().getGitReadHash())
        if registryFileStructure.exists(
                os.path.join(self.getRelativePermissionsDir(),
                             "permissions.json")):
            initialPermissions = subuserlib.permissions.load(
                permissionsString=registryFileStructure.read(
                    os.path.join(self.getRelativePermissionsDir(),
                                 "permissions.json")))
        else:
            raise SubuserHasNoPermissionsException("The subuser <" +
                                                   self.getName() +
                                                   """> has no permissions.

If you are updating sometime around August 2015, you should move ~/.subuser/permissions to ~/.subuser/registry/permissions and run:

$ git add .
$ git commit

Otherwise, please run:

$ subuser repair

To repair your subuser installation.\n""")
        self.__permissions = Permissions(
            self.getUser(),
            initialPermissions,
            writePath=self.getPermissionsDotJsonWritePath())

    def getPermissions(self):
        if self.__permissions is None:
            self.loadPermissions()
        return self.__permissions

    def getPermissionsTemplate(self):
        if self.__permissionsTemplate is None:
            permissionsDotJsonWritePath = os.path.join(
                self.getPermissionsDir(), "permissions-template.json")
            registryFileStructure = self.getUser().getRegistry(
            ).getGitRepository().getFileStructureAtCommit(
                self.getUser().getRegistry().getGitReadHash())
            if os.path.join(self.getRelativePermissionsDir(
            ), "permissions-template.json") in registryFileStructure.lsFiles(
                    self.getRelativePermissionsDir()):
                initialPermissions = subuserlib.permissions.load(
                    permissionsString=registryFileStructure.read(
                        os.path.join(self.getRelativePermissionsDir(),
                                     "permissions-template.json")))
                save = False
            else:
                initialPermissions = self.getImageSource().getPermissions()
                save = True
            self.__permissionsTemplate = Permissions(
                self.getUser(),
                initialPermissions,
                writePath=permissionsDotJsonWritePath)
            if save:
                self.__permissionsTemplate.save()
        return self.__permissionsTemplate

    def editPermissionsCLI(self):
        while True:
            subuserlib.subprocessExtras.runEditor(
                self.getPermissions().getWritePath())
            try:
                initialPermissions = subuserlib.permissions.load(
                    permissionsFilePath=self.getPermissionsDotJsonWritePath())
                break
            except SyntaxError as e:
                print(e)
                raw_input("Press ENTER to edit the permission file again.")
        self.__permissions = Permissions(
            self.getUser(),
            initialPermissions,
            writePath=self.getPermissionsDotJsonWritePath())
        self.getPermissions().save()

    def removePermissions(self):
        """
    Remove the user set and template permission files.
    """
        self.getUser().getRegistry().getGitRepository().run([
            "rm",
            os.path.join(self.getRelativePermissionsDir(), "permissions.json"),
            os.path.join(self.getRelativePermissionsDir(),
                         "permissions-template.json")
        ])

    def getImageId(self):
        """
    Get the Id of the Docker image associated with this subuser.
    None, if the subuser has no installed image yet.
    """
        return self.__imageId

    def setImageId(self, imageId):
        """
    Set the installed image associated with this subuser.
    """
        self.__imageId = imageId

    def getServiceSubuserNames(self):
        """
    Get this subuser's service subusers.
    """
        return self.__serviceSubusers

    def addServiceSubuser(self, name):
        self.__serviceSubusers.append(name)

    def getRunReadyImage(self):
        if not self.__runReadyImage:
            self.__runReadyImage = RunReadyImage(self.getUser(), self)
        return self.__runReadyImage

    def getX11Bridge(self):
        """
    Return the X11 bridge object for this subuser.
    """
        if not self.__x11Bridge:
            self.__x11Bridge = X11Bridge(self.getUser(), self)
        return self.__x11Bridge

    def getRuntime(self, environment, extraDockerFlags=None):
        """
    Returns the subuser's Runtime object for it's current permissions, creating it if necessary.
    """
        if not self.__runtime:
            self.__runtime = Runtime(self.getUser(),
                                     subuser=self,
                                     environment=environment,
                                     extraDockerFlags=extraDockerFlags)
        return self.__runtime

    def getRuntimeCache(self):
        if not self.__runtimeCache:
            self.__runtimeCache = RuntimeCache(self.getUser(), self)
        else:
            self.__runtimeCache.reload()
        return self.__runtimeCache

    def setupHomeDir(self):
        """
    Sets up the subuser's home dir, along with creating symlinks to shared user dirs.
    """
        if self.getPermissions()["stateful-home"]:
            try:
                self.getUser().getEndUser().makedirs(self.getHomeDirOnHost())
            except OSError as e:
                if e.errno() == errno.EEXIST:
                    pass
            if self.getPermissions()["user-dirs"]:
                for userDir in self.getPermissions()["user-dirs"]:
                    symlinkPath = os.path.join(self.getHomeDirOnHost(),
                                               userDir)
                    # http://stackoverflow.com/questions/15718006/check-if-directory-is-symlink
                    if symlinkPath.endswith("/"):
                        symlinkPath = symlinkPath[:-1]
                    destinationPath = os.path.join("/subuser/userdirs",
                                                   userDir)
                    if not os.path.islink(symlinkPath):
                        if os.path.exists(symlinkPath):
                            os.makedirs(
                                os.path.join(self.getHomeDirOnHost(),
                                             "subuser-user-dirs-backups"))
                            os.rename(
                                symlinkPath,
                                os.path.join(self.getHomeDirOnHost(),
                                             "subuser-user-dirs-backups",
                                             userDir))
                        try:
                            os.symlink(destinationPath, symlinkPath)
                            # Arg, why are source and destination switched?
                            # os.symlink(where does the symlink point to, where is the symlink)
                            # I guess it's to be like cp...
                        except OSError:
                            pass

    def locked(self):
        """
    Returns True if the subuser is locked.  Users lock subusers in order to prevent updates and rollbacks from effecting them.
    """
        return self.__locked

    def setLocked(self, locked):
        """
    Mark the subuser as locked or unlocked.

    We lock subusers to their current states to prevent updates and rollbacks from effecting them.
    """
        self.__locked = locked

    def getHomeDirOnHost(self):
        """
    Returns the path to the subuser's home dir. Unless the subuser is configured to have a stateless home, in which case returns None.
    """
        if self.getPermissions()["stateful-home"]:
            return os.path.join(
                self.getUser().getConfig()["subuser-home-dirs-dir"],
                self.getName())
        else:
            return None

    def getDockersideHome(self):
        if self.getPermissions()["as-root"]:
            return "/root/"
        else:
            return self.getUser().getEndUser().homeDir

    def describe(self):
        print("Subuser: "******"------------------")
        print(self.getImageSource().getIdentifier())
        self.getPermissions().describe()
        print("")

    def installExecutableShortcut(self):
        """
    Install a trivial executable script into the PATH which launches the subser image.
    """
        redirect = """#!/bin/bash
  subuser run """ + self.getName() + """ $@
  """
        executablePath = os.path.join(self.getUser().getConfig()["bin-dir"],
                                      self.getName())
        with open(executablePath, 'w') as file_f:
            file_f.write(redirect)
            st = os.stat(executablePath)
            os.chmod(
                executablePath,
                stat.S_IMODE(st.st_mode) | stat.S_IXUSR | stat.S_IXGRP
                | stat.S_IXOTH)
Exemplo n.º 6
0
class Subuser(UserOwnedObject, Describable):
  def __init__(self,user,name,imageId,executableShortcutInstalled,locked,serviceSubusers,imageSource=None,imageSourceName=None,repoName=None,entrypointsExposed=False):
    self.__name = name
    self.__imageSource = imageSource
    self.__repoName = repoName
    self.__imageSourceName = imageSourceName
    self.__imageId = imageId
    self.__executableShortcutInstalled = executableShortcutInstalled
    self.__entryPointsExposed = entrypointsExposed
    self.__entryPointsExposedThisRun = False
    self.__locked = locked
    self.__serviceSubusers = serviceSubusers
    self.__x11Bridge = None
    self.__runReadyImage = None
    self.__runtime = None
    self.__runtimeCache = None
    self.__permissions = None
    self.__permissionsTemplate = None
    UserOwnedObject.__init__(self,user)

  def getName(self):
    return self.__name

  def getImageSource(self):
    """
    Note, it is posssible that the subuser's image source no longer exists, in which case this function raises a NoImageSourceException.
    """
    if self.__imageSource is None:
      try:
        self.__imageSource = self.getUser().getRegistry().getRepositories()[self.__repoName][self.__imageSourceName]
      except KeyError:
        raise NoImageSourceException()
    return self.__imageSource

  def getImageSourceName(self):
    if self.__imageSource is None:
      return self.__imageSourceName
    else:
      return self.getImageSource().getName()

  def getSourceRepoName(self):
    if self.__imageSource is None:
      return self.__repoName
    else:
      return self.getImageSource().getRepository().getName()

  def isExecutableShortcutInstalled(self):
    return self.__executableShortcutInstalled

  def setExecutableShortcutInstalled(self,installed):
    self.__executableShortcutInstalled = installed

  def areEntryPointsExposed(self):
    return self.__entryPointsExposed

  def setEntrypointsExposed(self,exposed):
    self.__entryPointsExposed = exposed
    if exposed:
      self.__entryPointsExposedThisRun = True

  def wereEntryPointsExposedThisRun(self):
    return self.__entryPointsExposedThisRun

  def getPermissionsDir(self):
    return os.path.join(self.getUser().getConfig()["registry-dir"],"permissions",self.getName())

  def getRelativePermissionsDir(self):
    """
    Get the permissions directory as relative to the registry's git repository.
    """
    return os.path.join("permissions",self.getName())

  def createPermissions(self,permissionsDict):
    permissionsDotJsonWritePath = os.path.join(self.getPermissionsDir(),"permissions.json")
    self.__permissions = Permissions(self.getUser(),initialPermissions=permissionsDict,writePath=permissionsDotJsonWritePath)
    return self.__permissions

  def getPermissionsDotJsonWritePath(self):
    return os.path.join(self.getPermissionsDir(),"permissions.json")

  def loadPermissions(self):
    registryFileStructure = self.getUser().getRegistry().getGitRepository().getFileStructureAtCommit(self.getUser().getRegistry().getGitReadHash())
    if registryFileStructure.exists(os.path.join(self.getRelativePermissionsDir(),"permissions.json")):
      initialPermissions = subuserlib.permissions.load(permissionsString=registryFileStructure.read(os.path.join(self.getRelativePermissionsDir(),"permissions.json")))
    else:
      raise SubuserHasNoPermissionsException("The subuser <"+self.getName()+"""> has no permissions.

Please run:

$ subuser repair

To repair your subuser installation.\n""")
    self.__permissions = Permissions(self.getUser(),initialPermissions,writePath=self.getPermissionsDotJsonWritePath())

  def getPermissions(self):
    if self.__permissions is None:
      self.loadPermissions()
    return self.__permissions

  def getPermissionsTemplate(self):
    if self.__permissionsTemplate is None:
      permissionsDotJsonWritePath = os.path.join(self.getPermissionsDir(),"permissions-template.json")
      registryFileStructure = self.getUser().getRegistry().getGitRepository().getFileStructureAtCommit(self.getUser().getRegistry().getGitReadHash())
      if os.path.join(self.getRelativePermissionsDir(),"permissions-template.json") in registryFileStructure.lsFiles(self.getRelativePermissionsDir()):
        initialPermissions = subuserlib.permissions.load(permissionsString=registryFileStructure.read(os.path.join(self.getRelativePermissionsDir(),"permissions-template.json")))
        save = False
      else:
        initialPermissions = self.getImageSource().getPermissions()
        save = True
      self.__permissionsTemplate = Permissions(self.getUser(),initialPermissions,writePath=permissionsDotJsonWritePath)
      if save:
        self.__permissionsTemplate.save()
    return self.__permissionsTemplate

  def editPermissionsCLI(self):
    while True:
      subuserlib.subprocessExtras.runEditor(self.getPermissions().getWritePath())
      try:
        initialPermissions = subuserlib.permissions.load(permissionsFilePath=self.getPermissionsDotJsonWritePath())
        break
      except SyntaxError as e:
        print(e)
        input("Press ENTER to edit the permission file again.")
    self.__permissions = Permissions(self.getUser(),initialPermissions,writePath=self.getPermissionsDotJsonWritePath())
    self.getPermissions().save()

  def removePermissions(self):
    """
    Remove the user set and template permission files.
    """
    self.getUser().getRegistry().getGitRepository().run(["rm",os.path.join(self.getRelativePermissionsDir(),"permissions.json"),os.path.join(self.getRelativePermissionsDir(),"permissions-template.json")])

  def getImageId(self):
    """
    Get the Id of the Docker image associated with this subuser.
    None, if the subuser has no installed image yet.
    """
    return self.__imageId

  def setImageId(self,imageId):
    """
    Set the installed image associated with this subuser.
    """
    self.__imageId = imageId

  def getServiceSubuserNames(self):
    """
    Get this subuser's service subusers.
    """
    return self.__serviceSubusers

  def addServiceSubuser(self,name):
    self.__serviceSubusers.append(name)

  def getRunReadyImage(self):
    if not self.__runReadyImage:
      self.__runReadyImage = RunReadyImage(self.getUser(),self)
    return self.__runReadyImage

  def getX11Bridge(self):
    """
    Return the X11 bridge object for this subuser.
    """
    if not self.__x11Bridge:
      self.__x11Bridge = X11Bridge(self.getUser(),self)
    return self.__x11Bridge

  #TODO clean this up so that we aren't forwarding arguments in needless fluff.
  def getRuntime(self,environment,extraDockerFlags=None,entrypoint=None):
    """
    Returns the subuser's Runtime object for it's current permissions, creating it if necessary.
    """
    if not self.__runtime:
      self.__runtime = Runtime(self.getUser(),subuser=self,environment=environment,extraDockerFlags=extraDockerFlags,entrypoint=entrypoint)
    return self.__runtime

  def getRuntimeCache(self):
    if not self.__runtimeCache:
      self.__runtimeCache = RuntimeCache(self.getUser(),self)
    else:
      self.__runtimeCache.reload()
    return self.__runtimeCache

  def setupHomeDir(self):
    """
    Sets up the subuser's home dir, along with creating symlinks to shared user dirs.
    """
    if self.getPermissions()["stateful-home"]:
      try:
        self.getUser().getEndUser().makedirs(self.getHomeDirOnHost())
      except OSError as e:
        if e.errno() == errno.EEXIST:
          pass
      if self.getPermissions()["user-dirs"]:
        for userDir in self.getPermissions()["user-dirs"]:
          symlinkPath = os.path.join(self.getHomeDirOnHost(),userDir)
          # http://stackoverflow.com/questions/15718006/check-if-directory-is-symlink
          if symlinkPath.endswith("/"):
            symlinkPath = symlinkPath[:-1]
          destinationPath = os.path.join("/subuser/userdirs",userDir)
          if not os.path.islink(symlinkPath):
            if os.path.exists(symlinkPath):
              os.makedirs(os.path.join(self.getHomeDirOnHost(),"subuser-user-dirs-backups"))
              os.rename(symlinkPath,os.path.join(self.getHomeDirOnHost(),"subuser-user-dirs-backups",userDir))
            try:
              os.symlink(destinationPath,symlinkPath)
              # Arg, why are source and destination switched?
              # os.symlink(where does the symlink point to, where is the symlink)
              # I guess it's to be like cp...
            except OSError:
              pass

  def locked(self):
    """
    Returns True if the subuser is locked.  Users lock subusers in order to prevent updates and rollbacks from effecting them.
    """
    return self.__locked

  def setLocked(self,locked):
    """
    Mark the subuser as locked or unlocked.

    We lock subusers to their current states to prevent updates and rollbacks from effecting them.
    """
    self.__locked = locked

  def getHomeDirOnHost(self):
    """
    Returns the path to the subuser's home dir. Unless the subuser is configured to have a stateless home, in which case returns None.
    """
    if self.getPermissions()["stateful-home"]:
      return os.path.join(self.getUser().getConfig()["subuser-home-dirs-dir"],self.getName())
    else:
      return None

  def getDockersideHome(self):
    if self.getPermissions()["as-root"]:
      return "/root/"
    else:
      return self.getUser().getEndUser().homeDir

  def describe(self):
    print("Subuser: "******"------------------")
    try:
      print(self.getImageSource().getIdentifier())
    except subuserlib.classes.subuser.NoImageSourceException:
      print("Warning: This subuser has no image, nor does it have a valid image source to install an image from.")
    self.getPermissions().describe()
    print("")

  def installLaunchScript(self,name,script):
    """
    Install a trivial executable script into the PATH which launches the subser image.
    """
    redirect = script
    executablePath=os.path.join(self.getUser().getConfig()["bin-dir"], name)
    with open(executablePath, 'w') as file_f:
      file_f.write(redirect)
      st = os.stat(executablePath)
      os.chmod(executablePath, stat.S_IMODE(st.st_mode) | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)

  def installExecutableShortcut(self):
    self.installLaunchScript(self.getName(),"#!/bin/bash\nsubuser run "+self.getName()+" $@")

  def exposeEntrypoints(self):
    """
    Create launcher executables for the subuser's entrypoints.
    """
    for name,path in self.getPermissions()["entrypoints"].items():
      launchScript = """#!/usr/bin/python3
import subprocess,sys
run = """+json.dumps({"subuser-name":self.getName(),"entrypoint":path})
      launchScript +="""
sys.exit(subprocess.call(["subuser","run","--entrypoint="+run["entrypoint"],run["subuser-name"]]))
"""
      self.installLaunchScript(name,launchScript)
Exemplo n.º 7
0
 def getRuntimeCache(self):
   if not self.__runtimeCache:
     self.__runtimeCache = RuntimeCache(self.getUser(),self)
   else:
     self.__runtimeCache.reload()
   return self.__runtimeCache
Exemplo n.º 8
0
class Subuser(UserOwnedObject, Describable):
  def __init__(self,user,name,imageId,executableShortcutInstalled,locked,serviceSubusers,imageSource=None,imageSourceName=None,repoName=None):
    self.__name = name
    self.__imageSource = imageSource
    self.__repoName = repoName
    self.__imageSourceName = imageSourceName
    self.__imageId = imageId
    self.__executableShortcutInstalled = executableShortcutInstalled
    self.__locked = locked
    self.__serviceSubusers = serviceSubusers
    self.__x11Bridge = None
    self.__runReadyImage = None
    self.__runtime = None
    self.__runtimeCache = None
    self.__permissions = None
    self.__permissionsTemplate = None
    UserOwnedObject.__init__(self,user)

  def getName(self):
    return self.__name

  def getImageSource(self):
    if self.__imageSource is None:
      self.__imageSource = self.getUser().getRegistry().getRepositories()[self.__repoName][self.__imageSourceName]
    return self.__imageSource

  def getImageSourceName(self):
    if self.__imageSource is None:
      return self.__imageSourceName
    else:
      return self.getImageSource().getName()

  def getSourceRepoName(self):
    if self.__imageSource is None:
      return self.__repoName
    else:
      return self.getImageSource().getRepository().getName()

  def isExecutableShortcutInstalled(self):
    return self.__executableShortcutInstalled

  def setExecutableShortcutInstalled(self,installed):
    self.__executableShortcutInstalled = installed

  def getPermissionsDir(self):
    return os.path.join(self.getUser().getConfig()["registry-dir"],"permissions",self.getName())

  def getRelativePermissionsDir(self):
    """
    Get the permissions directory as relative to the registry's git repository.
    """
    return os.path.join("permissions",self.getName())

  def createPermissions(self,permissionsDict):
    permissionsDotJsonWritePath = os.path.join(self.getPermissionsDir(),"permissions.json")
    self.__permissions = Permissions(self.getUser(),initialPermissions=permissionsDict,writePath=permissionsDotJsonWritePath)
    return self.__permissions

  def getPermissionsDotJsonWritePath(self):
    return os.path.join(self.getPermissionsDir(),"permissions.json")

  def loadPermissions(self):
    registryFileStructure = self.getUser().getRegistry().getGitRepository().getFileStructureAtCommit(self.getUser().getRegistry().getGitReadHash())
    if registryFileStructure.exists(os.path.join(self.getRelativePermissionsDir(),"permissions.json")):
      initialPermissions = subuserlib.permissions.load(permissionsString=registryFileStructure.read(os.path.join(self.getRelativePermissionsDir(),"permissions.json")))
    else:
      raise SubuserHasNoPermissionsException("The subuser <"+self.getName()+"""> has no permissions.

If you are updating sometime around August 2015, you should move ~/.subuser/permissions to ~/.subuser/registry/permissions and run:

$ git add .
$ git commit

Otherwise, please run:

$ subuser repair

To repair your subuser installation.\n""")
    self.__permissions = Permissions(self.getUser(),initialPermissions,writePath=self.getPermissionsDotJsonWritePath())

  def getPermissions(self):
    if self.__permissions is None:
      self.loadPermissions()
    return self.__permissions

  def getPermissionsTemplate(self):
    if self.__permissionsTemplate is None:
      permissionsDotJsonWritePath = os.path.join(self.getPermissionsDir(),"permissions-template.json")
      registryFileStructure = self.getUser().getRegistry().getGitRepository().getFileStructureAtCommit(self.getUser().getRegistry().getGitReadHash())
      if os.path.join(self.getRelativePermissionsDir(),"permissions-template.json") in registryFileStructure.lsFiles(self.getRelativePermissionsDir()):
        initialPermissions = subuserlib.permissions.load(permissionsString=registryFileStructure.read(os.path.join(self.getRelativePermissionsDir(),"permissions-template.json")))
        save = False
      else:
        initialPermissions = self.getImageSource().getPermissions()
        save = True
      self.__permissionsTemplate = Permissions(self.getUser(),initialPermissions,writePath=permissionsDotJsonWritePath)
      if save:
        self.__permissionsTemplate.save()
    return self.__permissionsTemplate

  def editPermissionsCLI(self):
    subuserlib.subprocessExtras.runEditor(self.getPermissions().getWritePath())
    initialPermissions = subuserlib.permissions.load(permissionsFilePath=self.getPermissionsDotJsonWritePath())
    self.__permissions = Permissions(self.getUser(),initialPermissions,writePath=self.getPermissionsDotJsonWritePath())
    self.getPermissions().save()

  def removePermissions(self):
    """
    Remove the user set and template permission files.
    """
    self.getUser().getRegistry().getGitRepository().run(["rm",os.path.join(self.getRelativePermissionsDir(),"permissions.json"),os.path.join(self.getRelativePermissionsDir(),"permissions-template.json")])

  def getImageId(self):
    """
    Get the Id of the Docker image associated with this subuser.
    None, if the subuser has no installed image yet.
    """
    return self.__imageId

  def setImageId(self,imageId):
    """
    Set the installed image associated with this subuser.
    """
    self.__imageId = imageId

  def getServiceSubuserNames(self):
    """
    Get this subuser's service subusers.
    """
    return self.__serviceSubusers

  def addServiceSubuser(self,name):
    self.__serviceSubusers.append(name)

  def getRunReadyImage(self):
    if not self.__runReadyImage:
      self.__runReadyImage = RunReadyImage(self.getUser(),self)
    return self.__runReadyImage

  def getX11Bridge(self):
    """
    Return the X11 bridge object for this subuser.
    """
    if not self.__x11Bridge:
      self.__x11Bridge = X11Bridge(self.getUser(),self)
    return self.__x11Bridge

  def getRuntime(self,environment,extraDockerFlags=None):
    """
    Returns the subuser's Runtime object for it's current permissions, creating it if necessary.
    """
    if not self.__runtime:
      self.__runtime = Runtime(self.getUser(),subuser=self,environment=environment,extraDockerFlags=extraDockerFlags)
    return self.__runtime

  def getRuntimeCache(self):
    if not self.__runtimeCache:
      self.__runtimeCache = RuntimeCache(self.getUser(),self)
    else:
      self.__runtimeCache.reload()
    return self.__runtimeCache

  def locked(self):
    """
    Returns True if the subuser is locked.  Users lock subusers in order to prevent updates and rollbacks from effecting them.
    """
    return self.__locked

  def setLocked(self,locked):
    """
    Mark the subuser as locked or unlocked.

    We lock subusers to their current states to prevent updates and rollbacks from effecting them.
    """
    self.__locked = locked

  def getHomeDirOnHost(self):
    """
    Returns the path to the subuser's home dir. Unless the subuser is configured to have a stateless home, in which case returns None.
    """
    if self.getPermissions()["stateful-home"]:
      return os.path.join(self.getUser().getConfig()["subuser-home-dirs-dir"],self.getName())
    else:
      return None

  def getDockersideHome(self):
    if self.getPermissions()["as-root"]:
      return "/root/"
    else:
      return self.getUser().getEndUser().homeDir

  def describe(self):
    print("Subuser: "******"------------------")
    print(self.getImageSource().getIdentifier())
    self.getPermissions().describe()
    print("")

  def installExecutableShortcut(self):
    """
    Install a trivial executable script into the PATH which launches the subser image.
    """
    redirect="""#!/bin/bash
  subuser run """+self.getName()+""" $@
  """
    executablePath=os.path.join(self.getUser().getConfig()["bin-dir"], self.getName())
    with open(executablePath, 'w') as file_f:
      file_f.write(redirect)
      st = os.stat(executablePath)
      os.chmod(executablePath, stat.S_IMODE(st.st_mode) | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)