1c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# Use of this source code is governed by a BSD-style license that can be 3c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam# found in the LICENSE file. 4c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 5be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam"""A module to provide interface to gpt information. 6c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 7c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamgpt stands for GUID partition table, it is a data structure describing 8c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tampartitions present of a storage device. cgpt is a utility which allows to read 9c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamand modify gpt. This module parses cgpt output to create a dictionary 10c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamincluding information about all defined partitions including their properties. 11c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong TamIt also allows to modify partition properties as required. 12be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam""" 13c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 14c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass CgptError(Exception): 15c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam pass 16c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 17c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tamclass CgptHandler(object): 18be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Object representing one or more gpts present in the system. 19c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 20c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Attributes: 21ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam os_if: an instance of OSInterface, initialized by the caller. 22c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam devices: a dictionary keyed by the storage device names (as in 23c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam /dev/sda), the contents are dictionaries of cgpt information, 24c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam where keys are partiton names, and contents are in turn 25c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam dictionaries of partition properties, something like the below 26c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam (compressed for brevity): 27c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam {'/dev/sda': { 28c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'OEM': {'partition': 8, 'Type': 'Linux data', 'UUID': 'xxx'}, 29c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'ROOT-A': {'partition': 3, 'Type': 'ChromeOS rootfs', 'UUID': 'xyz'}, 30c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'ROOT-C': {'partition': 7, 'Type': 'ChromeOS rootfs', 'UUID': 'xzz'}, 31c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'ROOT-B': {'partition': 5, 'Type': 'ChromeOS rootfs', 'UUID': 'aaa'}, 32c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ... 33c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam } 34c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam } 35c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 36be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 37c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 38c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # This dictionary maps gpt attributes the user can modify into the cgpt 39c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # utility command line options. 40c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam ATTR_TO_COMMAND = { 41c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'priority' : 'P', 42c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'tries' : 'T', 43c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'successful' : 'S' 44c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam } 45c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 46ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam def __init__(self, os_if): 47ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam self.os_if = os_if 48c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.devices = {} 49c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 50c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def read_device_info(self, dev_name): 51be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Get device information from cgpt and parse it into a dictionary. 52c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 53c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Inputs: 54c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam dev_name: a string the Linux storage device name, (i.e. '/dev/sda') 55be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 56c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 57ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam device_dump = self.os_if.run_shell_command_get_output( 58c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 'cgpt show %s' % dev_name) 59c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam label = None 60c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam label_data = {} 61c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam device_data = {} 62c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for line in [x.strip() for x in device_dump]: 63c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if 'Label:' in line: 64c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if label and label not in device_data: 65c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam device_data[label] = label_data 66c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam _, _, partition, _, label = line.split() 67c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam label = line.split('Label:')[1].strip('" ') 68c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam label_data = {'partition': int(partition)} 69c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam continue 70c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if ':' in line: 71c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam name, value = line.strip().split(':') 72c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if name != 'Attr': 73c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam label_data[name] = value.strip() 74c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam continue 75c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # Attributes are split around '=', each attribute becomes a 76c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam # separate partition property. 77c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam attrs = value.strip().split() 78c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for attr in attrs: 79c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam name, value = attr.split('=') 80c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam label_data[name] = int(value) 81c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if label_data: 82c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam device_data[label] = label_data 83c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 84c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.devices[dev_name] = device_data 85c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 86c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def get_partition(self, device, partition_name): 87be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Retrieve a dictionary representing a partition on a device. 88c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 89c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Inputs: 90c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam device: a string, the Linux device name 91c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam partition_name: a string, the partition name as reported by cgpt. 92c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 93c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Raises: 94c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam CgptError in case the device or partiton on that device are not 95c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam known. 96be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 97c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 98c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam try: 99c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam result = self.devices[device][partition_name] 100c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam except KeyError: 101c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise CgptError('could not retrieve partiton %s of device %s' % ( 102c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam partition_name, device)) 103c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return result 104c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 105c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam def set_partition(self, device, partition_name, partition_value): 106be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """Set partition properties. 107c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 108c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Inputs: 109c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam device: a string, the Linux device name 110c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam partition_name: a string, the partition name as reported by cgpt. 111c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam partiton_value: a dictionary, where keys are strings, names of the 112c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam properties which need to be modified, and values are the 113c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam values to set the properties to. The only properties which 114c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam can be modified are those which are keys of ATTR_TO_COMMAND 115c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam defined above. 116c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam Raises: 117c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam CgptError in case a property name is not known or not supposed to 118c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam be modified. 119be15328b1bbcf94c43e3435bbb4777a5dab259bbTom Wai-Hong Tam """ 120c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 121c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam current = self.get_partition(device, partition_name) 122c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam options = [] 123c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam for prop, value in partition_value.iteritems(): 124c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam try: 125c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if value == current[prop]: 126c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam continue 127c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam options.append('-%s %d' % ( 128c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam self.ATTR_TO_COMMAND[prop], value)) 129c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam except KeyError: 130c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam raise CgptError("unknown or immutable property '%s'" % prop) 131c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 132c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam if not options: 133c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam return 134c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam 135c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam command = 'cgpt add -i %d %s %s' % ( 136c0168917ffb61c59c7746cd39fc53c1dd134723bTom Wai-Hong Tam current['partition'], ' '.join(options), device) 137ba5e3e52352ba60c43212f17c1d133006ef31ebdTom Wai-Hong Tam self.os_if.run_shell_command(command) 138