~ubuntu-branches/ubuntu/utopic/curtin/utopic

« back to all changes in this revision

Viewing changes to curtin/commands/block_meta.py

  • Committer: Package Import Robot
  • Author(s): Scott Moser
  • Date: 2014-07-22 18:53:38 UTC
  • mfrom: (1.1.13)
  • Revision ID: package-import@ubuntu.com-20140722185338-2nm6ekaottq6ldge
Tags: 0.1.0~bzr142-0ubuntu1
* New upstream snapshot.
  * add utility for parsing /etc/network/interfaces
  * aarm64 support [Newell Jensen]
    * run update-initramfs in aarm64
    * create boot partition when necessary (LP: #1338851 LP: #1340942)
  * know kernel mapping for utopic (3.16)
  * properly write fstype into /etc/fstab per provided fstype
  * add support for disk images as type 'dd-tgz'
  * correctly call finalize in target (LP: #1328521)
  * support invoking tar with --xattrs if available (LP: #1307636)
  * increase size of uefi partition to 512M (LP: #1306164)

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 
23
23
from . import populate_one_subcmd
24
24
 
 
25
import os
 
26
import platform
 
27
 
 
28
SIMPLE = 'simple'
 
29
SIMPLE_BOOT = 'simple-boot'
 
30
 
25
31
CMD_ARGUMENTS = (
26
32
    ((('-D', '--devices'),
27
33
      {'help': 'which devices to operate on', 'action': 'append',
28
34
       'metavar': 'DEVICE', 'default': None, }),
29
 
     ('--fstype', {'help': 'root filesystem type',
 
35
     ('--fstype', {'help': 'root partition filesystem type',
30
36
                   'choices': ['ext4', 'ext3'], 'default': 'ext4'}),
31
 
     ('mode', {'help': 'meta-mode to use', 'choices': ['raid0', 'simple']}),
 
37
     ('--boot-fstype', {'help': 'boot partition filesystem type',
 
38
                        'choices': ['ext4', 'ext3'], 'default': None}),
 
39
     ('mode', {'help': 'meta-mode to use',
 
40
               'choices': ['raid0', SIMPLE, SIMPLE_BOOT]}),
32
41
     )
33
42
)
34
43
 
35
44
 
36
45
def block_meta(args):
37
46
    # main entry point for the block-meta command.
38
 
    if args.mode == "simple":
 
47
    if args.mode in (SIMPLE, SIMPLE_BOOT):
39
48
        meta_simple(args)
40
49
    else:
41
 
        raise NotImplementedError("mode=%s is not implemenbed" % args.mode)
 
50
        raise NotImplementedError("mode=%s is not implemented" % args.mode)
42
51
 
43
52
 
44
53
def logtime(msg, func, *args, **kwargs):
46
55
        return func(*args, **kwargs)
47
56
 
48
57
 
 
58
def write_image_to_disk(source, dev):
 
59
    """
 
60
    Write disk image to block device
 
61
    """
 
62
    (devname, devnode) = block.get_dev_name_entry(dev)
 
63
    util.subp(args=['sh', '-c',
 
64
                    ('wget "$1" --progress=dot:mega -O - |'
 
65
                     'tar -SxOzf - | dd of="$2"'),
 
66
                    '--', source, devnode])
 
67
    util.subp(['partprobe'])
 
68
    util.subp(['udevadm', 'settle'])
 
69
    return block.get_root_device([devname, ])
 
70
 
 
71
 
 
72
def get_bootpt_cfg(cfg, enabled=False, fstype=None):
 
73
    # 'cfg' looks like:
 
74
    #   enabled: boolean
 
75
    #   fstype: filesystem type (default to 'fstype')
 
76
    #   label:  filesystem label (default to 'boot')
 
77
    # parm enable can enable, but not disable
 
78
    # parm fstype overrides cfg['fstype']
 
79
    def_boot = platform.machine() in ('aarch64')
 
80
    ret = {'enabled': def_boot, 'fstype': None, 'label': 'boot'}
 
81
    ret.update(cfg)
 
82
    if enabled:
 
83
        ret['enabled'] = True
 
84
    if ret['enabled']:
 
85
        if fstype and not ret['fstype']:
 
86
            ret['fstype'] = fstype
 
87
    return ret
 
88
 
 
89
 
49
90
def meta_simple(args):
 
91
    """Creates a root partition. If args.mode == SIMPLE_BOOT, it will also
 
92
    create a separate /boot partition.
 
93
    """
50
94
    state = util.load_command_environment()
51
95
 
52
96
    cfg = util.load_command_config(args, state)
55
99
    if devices is None:
56
100
        devices = cfg.get('block-meta', {}).get('devices', [])
57
101
 
 
102
    bootpt = get_bootpt_cfg(
 
103
        cfg.get('block-meta', {}).get('boot-partition', {}),
 
104
        enabled=args.mode == SIMPLE_BOOT, fstype=args.boot_fstype)
 
105
 
58
106
    # Remove duplicates but maintain ordering.
59
107
    devices = list(OrderedDict.fromkeys(devices))
60
108
 
61
109
    if len(devices) == 0:
62
110
        devices = block.get_installable_blockdevs()
63
 
        LOG.warn("simple mode, no devices given. unused list: %s", devices)
 
111
        LOG.warn("'%s' mode, no devices given. unused list: %s",
 
112
                 (args.mode, devices))
64
113
 
65
114
    if len(devices) > 1:
66
115
        if args.devices is not None:
67
 
            LOG.warn("simple mode but multiple devices given. "
68
 
                     "using first found")
 
116
            LOG.warn("'%s' mode but multiple devices given. "
 
117
                     "using first found", args.mode)
69
118
        available = [f for f in devices
70
119
                     if block.is_valid_device(f)]
71
120
        target = sorted(available)[0]
72
 
        LOG.warn("mode is 'simple'. multiple devices given. using '%s' "
73
 
                 "(first available)", target)
 
121
        LOG.warn("mode is '%s'. multiple devices given. using '%s' "
 
122
                 "(first available)", (args.mode, target))
74
123
    else:
75
124
        target = devices[0]
76
125
 
79
128
 
80
129
    (devname, devnode) = block.get_dev_name_entry(target)
81
130
 
82
 
    LOG.info("installing in simple mode to '%s'", devname)
 
131
    LOG.info("installing in '%s' mode to '%s'", (args.mode, devname))
 
132
 
 
133
    sources = cfg.get('sources', {})
 
134
    dd_images = util.get_dd_images(sources)
 
135
 
 
136
    if len(dd_images):
 
137
        # we have at least one dd-able image
 
138
        # we will only take the first one
 
139
        rootdev = write_image_to_disk(dd_images[0], devname)
 
140
        util.subp(['mount', rootdev, state['target']])
 
141
        return 0
83
142
 
84
143
    # helper partition will forcibly set up partition there
85
144
    if util.is_uefi_bootable():
86
145
        logtime(
87
146
            "partition --format uefi %s" % devnode,
88
147
            util.subp, ("partition", "--format", "uefi", devnode))
 
148
        bootpt['enabled'] = False
 
149
    elif bootpt['enabled']:
 
150
        logtime("partition --boot %s" % devnode,
 
151
                util.subp, ("partition", "--boot", devnode))
 
152
        bootdev = devnode + "1"
 
153
        rootdev = devnode + "2"
89
154
    else:
90
155
        logtime(
91
156
            "partition %s" % devnode,
92
157
            util.subp, ("partition", devnode))
93
 
 
94
 
    rootdev = devnode + "1"
95
 
 
 
158
        rootdev = devnode + "1"
 
159
 
 
160
    # mkfs for root partition first and mount
96
161
    cmd = ['mkfs.%s' % args.fstype, '-q', '-L', 'cloudimg-rootfs', rootdev]
97
162
    logtime(' '.join(cmd), util.subp, cmd)
98
 
 
99
163
    util.subp(['mount', rootdev, state['target']])
100
164
 
 
165
    if bootpt['enabled']:
 
166
        # create 'boot' directory in state['target']
 
167
        boot_dir = os.path.join(state['target'], 'boot')
 
168
        util.subp(['mkdir', boot_dir])
 
169
        # mkfs for boot partition and mount
 
170
        cmd = ['mkfs.%s' % bootpt['fstype'],
 
171
               '-q', '-L', bootpt['label'], bootdev]
 
172
        logtime(' '.join(cmd), util.subp, cmd)
 
173
        util.subp(['mount', bootdev, boot_dir])
 
174
 
101
175
    with open(state['fstab'], "w") as fp:
102
 
        fp.write("LABEL=%s / %s defaults 0 0\n" % ('cloudimg-rootfs', 'ext4'))
 
176
        if bootpt['enabled']:
 
177
            fp.write("LABEL=%s /boot %s defaults 0 0\n" %
 
178
                     (bootpt['label'], bootpt['fstype']))
 
179
        fp.write("LABEL=%s / %s defaults 0 0\n" %
 
180
                 ('cloudimg-rootfs', args.fstype))
103
181
 
104
182
    return 0
105
183