1*760c253cSXin Li# -*- coding: utf-8 -*- 2*760c253cSXin Li# Copyright 2011 The ChromiumOS Authors 3*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be 4*760c253cSXin Li# found in the LICENSE file. 5*760c253cSXin Li 6*760c253cSXin Li"""Compute image checksum.""" 7*760c253cSXin Li 8*760c253cSXin Li 9*760c253cSXin Liimport os 10*760c253cSXin Liimport threading 11*760c253cSXin Li 12*760c253cSXin Lifrom cros_utils import logger 13*760c253cSXin Lifrom cros_utils.file_utils import FileUtils 14*760c253cSXin Li 15*760c253cSXin Li 16*760c253cSXin Liclass ImageChecksummer(object): 17*760c253cSXin Li """Compute image checksum.""" 18*760c253cSXin Li 19*760c253cSXin Li class PerImageChecksummer(object): 20*760c253cSXin Li """Compute checksum for an image.""" 21*760c253cSXin Li 22*760c253cSXin Li def __init__(self, label, log_level): 23*760c253cSXin Li self._lock = threading.Lock() 24*760c253cSXin Li self.label = label 25*760c253cSXin Li self._checksum = None 26*760c253cSXin Li self.log_level = log_level 27*760c253cSXin Li 28*760c253cSXin Li def Checksum(self): 29*760c253cSXin Li with self._lock: 30*760c253cSXin Li if not self._checksum: 31*760c253cSXin Li logger.GetLogger().LogOutput( 32*760c253cSXin Li "Acquiring checksum for '%s'." % self.label.name 33*760c253cSXin Li ) 34*760c253cSXin Li self._checksum = None 35*760c253cSXin Li if self.label.image_type != "local": 36*760c253cSXin Li raise RuntimeError( 37*760c253cSXin Li "Called Checksum on non-local image!" 38*760c253cSXin Li ) 39*760c253cSXin Li if self.label.chromeos_image: 40*760c253cSXin Li if os.path.exists(self.label.chromeos_image): 41*760c253cSXin Li self._checksum = FileUtils().Md5File( 42*760c253cSXin Li self.label.chromeos_image, 43*760c253cSXin Li log_level=self.log_level, 44*760c253cSXin Li ) 45*760c253cSXin Li logger.GetLogger().LogOutput( 46*760c253cSXin Li "Computed checksum is " ": %s" % self._checksum 47*760c253cSXin Li ) 48*760c253cSXin Li if not self._checksum: 49*760c253cSXin Li raise RuntimeError("Checksum computing error.") 50*760c253cSXin Li logger.GetLogger().LogOutput( 51*760c253cSXin Li "Checksum is: %s" % self._checksum 52*760c253cSXin Li ) 53*760c253cSXin Li return self._checksum 54*760c253cSXin Li 55*760c253cSXin Li _instance = None 56*760c253cSXin Li _lock = threading.Lock() 57*760c253cSXin Li _per_image_checksummers = {} 58*760c253cSXin Li 59*760c253cSXin Li def __new__(cls, *args, **kwargs): 60*760c253cSXin Li with cls._lock: 61*760c253cSXin Li if not cls._instance: 62*760c253cSXin Li cls._instance = super(ImageChecksummer, cls).__new__( 63*760c253cSXin Li cls, *args, **kwargs 64*760c253cSXin Li ) 65*760c253cSXin Li return cls._instance 66*760c253cSXin Li 67*760c253cSXin Li def Checksum(self, label, log_level): 68*760c253cSXin Li if label.image_type != "local": 69*760c253cSXin Li raise RuntimeError("Attempt to call Checksum on non-local image.") 70*760c253cSXin Li with self._lock: 71*760c253cSXin Li if label.name not in self._per_image_checksummers: 72*760c253cSXin Li self._per_image_checksummers[ 73*760c253cSXin Li label.name 74*760c253cSXin Li ] = ImageChecksummer.PerImageChecksummer(label, log_level) 75*760c253cSXin Li checksummer = self._per_image_checksummers[label.name] 76*760c253cSXin Li 77*760c253cSXin Li try: 78*760c253cSXin Li return checksummer.Checksum() 79*760c253cSXin Li except: 80*760c253cSXin Li logger.GetLogger().LogError( 81*760c253cSXin Li "Could not compute checksum of image in label" 82*760c253cSXin Li " '%s'." % label.name 83*760c253cSXin Li ) 84*760c253cSXin Li raise 85