def _GetImagePath(self): """Returns the image path to use.""" image_path = translated_path = None if os.path.isfile(self.image): if not self.yes and not _IsFilePathGPTDiskImage(self.image): # TODO(wnwen): Open the tarball and if there is just one file in it, # use that instead. Existing code in upload_symbols.py. if cros_build_lib.BooleanPrompt( prolog= 'The given image file is not a valid disk image. Perhaps ' 'you forgot to untar it.', prompt='Terminate the current flash process?'): raise FlashError('Update terminated by user.') image_path = self.image elif os.path.isdir(self.image): # Ask user which image (*.bin) in the folder to use. image_path = _ChooseImageFromDirectory(self.image) else: # Translate the xbuddy path to get the exact image to use. translated_path, _ = ds_wrapper.GetImagePathWithXbuddy( self.image, self.board, static_dir=DEVSERVER_STATIC_DIR) image_path = ds_wrapper.TranslatedPathToLocalPath( translated_path, DEVSERVER_STATIC_DIR) logging.info('Using image %s', translated_path or image_path) return image_path
def fetch_image(board: str, version: str, local_path: str = None) -> str: """Downloads an image from Google Storage. Args: board: The name of the board. version: The version to download. local_path: directory to save image to. Returns: Local path to image file. """ translated_path, _ = ds_wrapper.GetImagePathWithXbuddy( 'xBuddy://remote', board, version) image_path = ds_wrapper.TranslatedPathToLocalPath(translated_path) if local_path: try: shutil.copyfile(image_path, local_path) except OSError as e: cros_build_lib.Die(f"Copy error '{image_path}' to '{local_path}': {e}") return local_path return image_path
def GetPayloadDir(self, device): """Get directory of payload for update. This method is used to obtain the directory of payload for cros-flash. The given path 'self.image' is passed in when initializing RemoteDeviceUpdater. If self.image is a directory, we directly use the provided update payload(s) in this directory. If self.image is an image, let devserver access it and generate payloads. If not in the above cases, let devserver first obtain the image path. Then devserver will access the image and generate payloads. Args: device: A ChromiumOSDevice object. Returns: A string payload_dir, that represents the payload directory. """ payload_dir = self.tempdir if os.path.isdir(self.image): # The given path is a directory. payload_dir = self.image logging.info('Using provided payloads in %s', payload_dir) elif os.path.isfile(self.image): # The given path is an image. logging.info('Using image %s', self.image) ds_wrapper.GetUpdatePayloadsFromLocalPath( self.image, payload_dir, src_image_to_delta=self.src_image_to_delta, static_dir=DEVSERVER_STATIC_DIR) else: self.board = cros_build_lib.GetBoard(device_board=device.board, override_board=self.board, force=self.yes) if not self.board: raise FlashError('No board identified') if not self.force and self.board != device.board: # If a board was specified, it must be compatible with the device. raise FlashError('Device (%s) is incompatible with board %s' % (device.board, self.board)) logging.info('Board is %s', self.board) # Translate the xbuddy path to get the exact image to use. translated_path, resolved_path = ds_wrapper.GetImagePathWithXbuddy( self.image, self.board, static_dir=DEVSERVER_STATIC_DIR, lookup_only=True) logging.info('Using image %s', translated_path) # Convert the translated path to be used in the update request. image_path = ds_wrapper.ConvertTranslatedPath( resolved_path, translated_path) # Launch a local devserver to generate/serve update payloads. ds_wrapper.GetUpdatePayloads( image_path, payload_dir, board=self.board, src_image_to_delta=self.src_image_to_delta, static_dir=DEVSERVER_STATIC_DIR) return payload_dir
def GetPayloadDir(self, device): """Get directory of payload for update. This method is used to obtain the directory of payload for cros-flash. The given path 'self.image' is passed in when initializing RemoteDeviceUpdater. If self.image is a directory, we directly use the provided update payload(s) in this directory. If self.image is an image, we will generate payloads for it and put them in our temporary directory. The reason is that people may modify a local image or override it (on the same path) with a different image, so in order to be safe each time we need to generate the payloads and not cache them. If non of the above cases, we use the xbuddy to first obtain the image path (and possibly download it). Then we will generate the payloads in the same directory the image is located. The reason is that this is what devserver used to do. The path to the image generated by the devserver (or xbuddy) is unique and normally nobody override its image with a different one. That is why I think it is safe to put the payloads next to the image. This is a poor man's version of caching but it makes cros flash faster for users who flash the same image multiple times (without doing any change to the image). Args: device: A ChromiumOSDevice object. Returns: A string payload_dir, that represents the payload directory. """ if os.path.isdir(self.image): # The given path is a directory. logging.info('Using provided payloads in %s', self.image) return self.image image_path = None if os.path.isfile(self.image): # The given path is an image. image_path = self.image payload_dir = self.tempdir else: # Assuming it is an xbuddy path. self.board = cros_build_lib.GetBoard(device_board=device.board or GetDefaultBoard(), override_board=self.board, force=self.yes, strict=True) if not self.force and self.board != device.board: # If a board was specified, it must be compatible with the device. raise FlashError('Device (%s) is incompatible with board %s' % (device.board, self.board)) logging.info('Board is %s', self.board) # TODO(crbug.com/872441): Once devserver code has been moved to chromite, # use xbuddy library directly instead of the devserver_wrapper. # Fetch the full payload and properties, and stateful files. If this # fails, fallback to downloading the image. try: translated_path, _ = ds_wrapper.GetImagePathWithXbuddy( os.path.join(self.image, artifact_info.FULL_PAYLOAD), self.board, self.version, silent=True) payload_dir = os.path.dirname( ds_wrapper.TranslatedPathToLocalPath(translated_path)) ds_wrapper.GetImagePathWithXbuddy(os.path.join( self.image, artifact_info.STATEFUL_PAYLOAD), self.board, self.version, silent=True) fetch_image = False except (ds_wrapper.ImagePathError, ds_wrapper.ArtifactDownloadError): logging.info( 'Could not find full_payload or stateful for "%s"', self.image) fetch_image = True # We didn't find the full_payload, attempt to download the image. if fetch_image: translated_path, _ = ds_wrapper.GetImagePathWithXbuddy( self.image, self.board, self.version) image_path = ds_wrapper.TranslatedPathToLocalPath( translated_path) payload_dir = os.path.join(os.path.dirname(image_path), 'payloads') logging.notice('Using image path %s and payload directory %s', image_path, payload_dir) # Generate rootfs and stateful update payloads if they do not exist. payload_path = os.path.join(payload_dir, auto_updater_transfer.ROOTFS_FILENAME) if not os.path.exists(payload_path): paygen_payload_lib.GenerateUpdatePayload( image_path, payload_path, src_image=self.src_image_to_delta) if not os.path.exists( os.path.join(payload_dir, auto_updater_transfer.STATEFUL_FILENAME)): paygen_stateful_payload_lib.GenerateStatefulPayload( image_path, payload_dir) return payload_dir