File: installationTask.py

package info (click to toggle)
subuser 0.6.2-3
  • links: PTS
  • area: main
  • in suites: bookworm, bullseye, buster, forky, sid, trixie
  • size: 4,208 kB
  • sloc: python: 5,201; sh: 380; makefile: 73
file content (132 lines) | stat: -rwxr-xr-x 5,799 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# -*- coding: utf-8 -*-

"""
Implements functions involved in building/installing/updating subuser images.
"""

#external imports
import sys
#internal imports
import subuserlib.classes.installedImage
import subuserlib.verify
from subuserlib.classes.userOwnedObject import UserOwnedObject
import subuserlib.classes.exceptions as exceptions

class InstallationTask(UserOwnedObject):
  def __init__(self,user,subusersToBeUpdatedOrInstalled,checkForUpdatesExternally=False):
    UserOwnedObject.__init__(self,user)
    self.__subusersToBeUpdated = subusersToBeUpdatedOrInstalled
    self.__upToDateImageSources = set()
    self.__outOfDateImageSources = set()
    self.__outOfDateSubusers = None
    self.__subusersWhosImagesFailedToBuild = set()
    self.checkForUpdatesExternally = checkForUpdatesExternally

  def getOutOfDateSubusers(self):
    """
    Returns a list of subusers which are out of date or have no InstalledImage associated with them.
    """
    if self.__outOfDateSubusers is None:
      self.user.registry.log("Checking if images need to be updated or installed...")
      self.__outOfDateSubusers = set()
      for subuser in self.__subusersToBeUpdated:
        try:
          if (not subuser.locked) and (not (subuser.imageSource.getLatestInstalledImage() is None)):
            self.user.registry.log("Checking if subuser "+subuser.name+" is up to date.")
            for imageSource in getTargetLineage(subuser.imageSource):
              if imageSource in self.__upToDateImageSources:
                continue
              if imageSource in self.__outOfDateImageSources:
                upToDate = False
              else:
                upToDate = self.isUpToDate(imageSource)
              if upToDate:
                self.__upToDateImageSources.add(imageSource)
              else:
                self.__outOfDateImageSources.add(imageSource)
                self.__outOfDateSubusers.add(subuser)
                break
          if subuser.imageSource.getLatestInstalledImage() is None or subuser.imageId is None or not subuser.isImageInstalled():
            if subuser.locked:
              self.user.registry.log("Subuser "+subuser.name+" has no image. But is locked. Marking for installation anyways.")
            self.__outOfDateSubusers.add(subuser)
        except (exceptions.ImageBuildException, subuserlib.classes.subuser.NoImageSourceException) as e :
          self.user.registry.log(str(e))
          self.__subusersWhosImagesFailedToBuild.add(subuser)
    outOfDateSubusers = list(self.__outOfDateSubusers)
    outOfDateSubusers.sort(key=lambda s:s.name)
    return outOfDateSubusers

  def isUpToDate(self,imageSource):
    installedImage = imageSource.getLatestInstalledImage()
    if installedImage is None:
      return False
    if not installedImage.isDockerImageThere():
      return False
    targetLineage = getTargetLineage(imageSource)
    installedLineage = installedImage.getImageLineage()
    if not (len(targetLineage) == len(installedLineage)):
      return False
    sideBySideLineages = zip(installedLineage,targetLineage)
    for installed,target in sideBySideLineages:
      if target in self.__outOfDateImageSources:
        return False
      if not installed.imageId == target.getLatestInstalledImage().imageId:
        return False
    if not installedImage.imageSourceHash == imageSource.getHash():
      return False
    if self.checkForUpdatesExternally and installedImage.checkForUpdates():
      return False
    return True

  def updateOutOfDateSubusers(self,useCache=False):
    """
    Install new images for those subusers which are out of date.
    """
    parent = None
    for subuser in self.getOutOfDateSubusers():
      try:
        for imageSource in getTargetLineage(subuser.imageSource):
          if imageSource in self.__upToDateImageSources:
            parent = imageSource.getLatestInstalledImage().imageId
          elif imageSource in self.__outOfDateImageSources:
            parent = installImage(imageSource,parent=parent,useCache=useCache)
            self.__outOfDateImageSources.remove(imageSource)
            self.__upToDateImageSources.add(imageSource)
          else:
            if not self.isUpToDate(imageSource):
              parent = installImage(imageSource,parent=parent,useCache=useCache)
            else:
              parent = imageSource.getLatestInstalledImage().imageId
            self.__upToDateImageSources.add(imageSource)
        if not subuser.imageId == parent:
          subuser.imageId = parent
          subuser.user.registry.logChange("Installed new image <"+subuser.imageId+"> for subuser "+subuser.name)
      except exceptions.ImageBuildException as e:
        self.user.registry.log(str(e))
        self.__subusersWhosImagesFailedToBuild.add(subuser)

  def getSubusersWhosImagesFailedToBuild(self):
    return self.__subusersWhosImagesFailedToBuild

def installImage(imageSource,parent,useCache=False):
  """
  Install a image by building the given ImageSource.
  Register the newly installed image in the user's InstalledImages list.
  Return the Id of the newly installedImage.
  """
  imageSource.user.registry.logChange("Installing " + imageSource.name + " ...")
  imageId = imageSource.build(parent,useCache=useCache)
  imageSource.user.installedImages[imageId] = subuserlib.classes.installedImage.InstalledImage(imageSource.user,imageId,imageSource.name,imageSource.repo.name,imageSource.getHash())
  imageSource.user.installedImages.save()
  return imageId

def getTargetLineage(imageSource):
  """
  Return the lineage of the ImageSource, going from its base dependency up to itself.
  """
  sourceLineage = []
  while imageSource:
    sourceLineage.append(imageSource)
    imageSource = imageSource.getDependency()
  return list(reversed(sourceLineage))