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))
|