7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
1 |
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
114
by Devin Carlen
Updated licenses |
2 |
|
3 |
# Copyright 2010 United States Government as represented by the
|
|
3.1.9
by Vishvananda Ishaya
Removed trailing whitespace from header |
4 |
# Administrator of the National Aeronautics and Space Administration.
|
114
by Devin Carlen
Updated licenses |
5 |
# All Rights Reserved.
|
6 |
#
|
|
7 |
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
8 |
# not use this file except in compliance with the License. You may obtain
|
|
9 |
# a copy of the License at
|
|
10 |
#
|
|
11 |
# http://www.apache.org/licenses/LICENSE-2.0
|
|
1
by Jesse Andrews
initial commit |
12 |
#
|
13 |
# Unless required by applicable law or agreed to in writing, software
|
|
114
by Devin Carlen
Updated licenses |
14 |
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
15 |
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
16 |
# License for the specific language governing permissions and limitations
|
|
17 |
# under the License.
|
|
1
by Jesse Andrews
initial commit |
18 |
|
19 |
"""
|
|
20 |
Utility methods to resize, repartition, and modify disk images.
|
|
21 |
Includes injection of SSH PGP keys into authorized_keys file.
|
|
22 |
"""
|
|
23 |
||
24 |
import logging |
|
25 |
import os |
|
26 |
import tempfile |
|
150.77.1
by andy
rather comprehensive style fixes |
27 |
|
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
28 |
from nova import exception |
29 |
||
139.2.2
by Jesse Andrews
reorder imports spacing |
30 |
|
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
31 |
def partition(infile, outfile, local_bytes=0, local_type='ext2', execute=None): |
32 |
"""Takes a single partition represented by infile and writes a bootable
|
|
33 |
drive image into outfile.
|
|
118.4.1
by Vishvananda Ishaya
fix key injection script |
34 |
|
1
by Jesse Andrews
initial commit |
35 |
The first 63 sectors (0-62) of the resulting image is a master boot record.
|
36 |
Infile becomes the first primary partition.
|
|
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
37 |
If local bytes is specified, a second primary partition is created and
|
38 |
formatted as ext2.
|
|
39 |
||
1
by Jesse Andrews
initial commit |
40 |
In the diagram below, dashes represent drive sectors.
|
150.15.1
by Monty Taylor
Updated sphinx layout to a two-dir layout like swift. |
41 |
+-----+------. . .-------+------. . .------+
|
42 |
| 0 a| b c|d e|
|
|
1
by Jesse Andrews
initial commit |
43 |
+-----+------. . .-------+------. . .------+
|
44 |
| mbr | primary partiton | local partition |
|
|
45 |
+-----+------. . .-------+------. . .------+
|
|
46 |
"""
|
|
47 |
sector_size = 512 |
|
48 |
file_size = os.path.getsize(infile) |
|
49 |
if file_size % sector_size != 0: |
|
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
50 |
logging.warn("Input partition size not evenly divisible by" |
51 |
" sector size: %d / %d", file_size, sector_size) |
|
1
by Jesse Andrews
initial commit |
52 |
primary_sectors = file_size / sector_size |
53 |
if local_bytes % sector_size != 0: |
|
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
54 |
logging.warn("Bytes for local storage not evenly divisible" |
55 |
" by sector size: %d / %d", local_bytes, sector_size) |
|
1
by Jesse Andrews
initial commit |
56 |
local_sectors = local_bytes / sector_size |
57 |
||
58 |
mbr_last = 62 # a |
|
59 |
primary_first = mbr_last + 1 # b |
|
67
by Vishvananda Ishaya
fix sectors off by one |
60 |
primary_last = primary_first + primary_sectors - 1 # c |
1
by Jesse Andrews
initial commit |
61 |
local_first = primary_last + 1 # d |
67
by Vishvananda Ishaya
fix sectors off by one |
62 |
local_last = local_first + local_sectors - 1 # e |
1
by Jesse Andrews
initial commit |
63 |
last_sector = local_last # e |
64 |
||
65 |
# create an empty file
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
66 |
execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d' |
150.10.1
by Vishvananda Ishaya
fixed bug where partition code was sometimes failing due to initial dd not being yielded properly |
67 |
% (outfile, last_sector, sector_size)) |
1
by Jesse Andrews
initial commit |
68 |
|
69 |
# make mbr partition
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
70 |
execute('parted --script %s mklabel msdos' % outfile) |
1
by Jesse Andrews
initial commit |
71 |
|
72 |
# make primary partition
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
73 |
execute('parted --script %s mkpart primary %ds %ds' |
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
74 |
% (outfile, primary_first, primary_last)) |
1
by Jesse Andrews
initial commit |
75 |
|
76 |
# make local partition
|
|
77 |
if local_bytes > 0: |
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
78 |
execute('parted --script %s mkpartfs primary %s %ds %ds' |
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
79 |
% (outfile, local_type, local_first, local_last)) |
1
by Jesse Andrews
initial commit |
80 |
|
81 |
# copy file into partition
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
82 |
execute('dd if=%s of=%s bs=%d seek=%d conv=notrunc,fsync' |
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
83 |
% (infile, outfile, sector_size, primary_first)) |
84 |
||
150.77.1
by andy
rather comprehensive style fixes |
85 |
|
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
86 |
@defer.inlineCallbacks |
158.1.4
by Justin Santa Barbara
Clarified what the 'Mapped device not found' exception really means. |
87 |
def inject_data( image, key=None, net=None, dns=None, |
88 |
remove_network_udev=False, |
|
89 |
partition=None, execute=None): |
|
116.1.17
by Vishvananda Ishaya
Simple network injection |
90 |
"""Injects a ssh key and optionally net data into a disk image.
|
91 |
||
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
92 |
it will mount the image as a fully partitioned disk and attempt to inject
|
93 |
into the specified partition number.
|
|
116.1.17
by Vishvananda Ishaya
Simple network injection |
94 |
|
1
by Jesse Andrews
initial commit |
95 |
If partition is not specified it mounts the image as a single partition.
|
116.1.17
by Vishvananda Ishaya
Simple network injection |
96 |
|
1
by Jesse Andrews
initial commit |
97 |
"""
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
98 |
out, err = execute('sudo losetup --find --show %s' % image) |
1
by Jesse Andrews
initial commit |
99 |
if err: |
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
100 |
raise exception.Error('Could not attach image to loopback: %s' % err) |
1
by Jesse Andrews
initial commit |
101 |
device = out.strip() |
102 |
try: |
|
103 |
if not partition is None: |
|
104 |
# create partition
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
105 |
out, err = execute('sudo kpartx -a %s' % device) |
1
by Jesse Andrews
initial commit |
106 |
if err: |
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
107 |
raise exception.Error('Failed to load partition: %s' % err) |
108 |
mapped_device = '/dev/mapper/%sp%s' % (device.split('/')[-1], |
|
109 |
partition) |
|
1
by Jesse Andrews
initial commit |
110 |
else: |
111 |
mapped_device = device |
|
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
112 |
|
158.1.4
by Justin Santa Barbara
Clarified what the 'Mapped device not found' exception really means. |
113 |
# We can only loopback mount raw images. If the device isn't there,
|
114 |
# it's normally because it's a .vmdk or a .vdi etc
|
|
161
by Justin Santa Barbara
Fixed up some of the raw disk stuff that broke in the abstraction out of libvirt |
115 |
if not os.path.exists(mapped_device): |
158.1.4
by Justin Santa Barbara
Clarified what the 'Mapped device not found' exception really means. |
116 |
raise exception.Error( |
117 |
'Mapped device was not found (we can only inject raw disk images): %s' |
|
118 |
% mapped_device) |
|
161
by Justin Santa Barbara
Fixed up some of the raw disk stuff that broke in the abstraction out of libvirt |
119 |
|
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
120 |
# Configure ext2fs so that it doesn't auto-check every N boots
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
121 |
out, err = execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device) |
1
by Jesse Andrews
initial commit |
122 |
|
123 |
tmpdir = tempfile.mkdtemp() |
|
124 |
try: |
|
125 |
# mount loopback to dir
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
126 |
out, err = execute( |
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
127 |
'sudo mount %s %s' % (mapped_device, tmpdir)) |
1
by Jesse Andrews
initial commit |
128 |
if err: |
7.2.1
by Vishvananda Ishaya
patch from issue 4001 |
129 |
raise exception.Error('Failed to mount filesystem: %s' % err) |
1
by Jesse Andrews
initial commit |
130 |
|
131 |
try: |
|
116.1.17
by Vishvananda Ishaya
Simple network injection |
132 |
if key: |
133 |
# inject key file
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
134 |
_inject_key_into_fs(key, tmpdir, execute=execute) |
116.1.17
by Vishvananda Ishaya
Simple network injection |
135 |
if net: |
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
136 |
_inject_net_into_fs(net, tmpdir, execute=execute) |
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
137 |
if dns: |
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
138 |
_inject_dns_into_fs(dns, tmpdir, execute=execute) |
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
139 |
if remove_network_udev: |
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
140 |
_remove_network_udev(tmpdir, execute=execute) |
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
141 |
|
1
by Jesse Andrews
initial commit |
142 |
finally: |
143 |
# unmount device
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
144 |
execute('sudo umount %s' % mapped_device) |
1
by Jesse Andrews
initial commit |
145 |
finally: |
146 |
# remove temporary directory
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
147 |
execute('rmdir %s' % tmpdir) |
1
by Jesse Andrews
initial commit |
148 |
if not partition is None: |
149 |
# remove partitions
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
150 |
execute('sudo kpartx -d %s' % device) |
1
by Jesse Andrews
initial commit |
151 |
finally: |
152 |
# remove loopback
|
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
153 |
execute('sudo losetup --detach %s' % device) |
1
by Jesse Andrews
initial commit |
154 |
|
116.1.17
by Vishvananda Ishaya
Simple network injection |
155 |
def _inject_key_into_fs(key, fs, execute=None): |
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
156 |
sshdir = os.path.join(fs, 'root', '.ssh') |
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
157 |
execute('sudo mkdir -p %s' % sshdir) # existing dir doesn't matter |
158 |
execute('sudo chown root %s' % sshdir) |
|
159 |
execute('sudo chmod 700 %s' % sshdir) |
|
1
by Jesse Andrews
initial commit |
160 |
keyfile = os.path.join(sshdir, 'authorized_keys') |
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
161 |
execute('sudo tee -a %s' % keyfile, '\n' + key.strip() + '\n') |
1
by Jesse Andrews
initial commit |
162 |
|
150.85.8
by Justin Santa Barbara
Merged with trunk (via virtualbox-support) |
163 |
|
116.1.17
by Vishvananda Ishaya
Simple network injection |
164 |
def _inject_net_into_fs(net, fs, execute=None): |
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
165 |
netfile = os.path.join(fs, 'etc', 'network', 'interfaces') |
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
166 |
execute('sudo tee %s' % netfile, net) |
116.1.17
by Vishvananda Ishaya
Simple network injection |
167 |
|
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
168 |
def _inject_dns_into_fs(dns, fs, execute=None): |
169 |
dnsfile = os.path.join(fs, 'etc', 'resolv.conf') |
|
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
170 |
execute('sudo tee %s' % dnsfile, dns) |
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
171 |
|
172 |
def _remove_network_udev(fs, execute=None): |
|
158.1.4
by Justin Santa Barbara
Clarified what the 'Mapped device not found' exception really means. |
173 |
# TODO(justinsb): This is correct for Ubuntu, but might not be right for
|
174 |
# other distros. There is a much bigger discussion to be had about what
|
|
175 |
# we inject and how we inject it.
|
|
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
176 |
rulesfile = os.path.join(fs, 'etc', 'udev', 'rules.d', '70-persistent-net.rules') |
150.85.6
by Justin Santa Barbara
Removed twisted from the compute service |
177 |
execute('rm -f %s' % rulesfile) |
154
by Justin Santa Barbara
Able to set up DNS, and remove udev network rules |
178 |