~soren/nova/iptables-security-groups

« back to all changes in this revision

Viewing changes to nova/compute/disk.py

  • Committer: Soren Hansen
  • Date: 2011-01-03 09:56:21 UTC
  • mfrom: (430.2.79 nova)
  • Revision ID: soren@linux2go.dk-20110103095621-qy398qk1uk8o7cy3
Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
import os
27
27
import tempfile
28
28
 
29
 
from twisted.internet import defer
30
 
 
31
29
from nova import exception
32
30
from nova import flags
33
31
 
39
37
                     'block_size to use for dd')
40
38
 
41
39
 
42
 
@defer.inlineCallbacks
43
40
def partition(infile, outfile, local_bytes=0, resize=True,
44
41
              local_type='ext2', execute=None):
45
42
    """
64
61
    file_size = os.path.getsize(infile)
65
62
    if resize and file_size < FLAGS.minimum_root_size:
66
63
        last_sector = FLAGS.minimum_root_size / sector_size - 1
67
 
        yield execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d'
68
 
                      % (infile, last_sector, sector_size))
69
 
        yield execute('e2fsck -fp %s' % infile, check_exit_code=False)
70
 
        yield execute('resize2fs %s' % infile)
 
64
        execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d'
 
65
                % (infile, last_sector, sector_size))
 
66
        execute('e2fsck -fp %s' % infile, check_exit_code=False)
 
67
        execute('resize2fs %s' % infile)
71
68
        file_size = FLAGS.minimum_root_size
72
69
    elif file_size % sector_size != 0:
73
 
        logging.warn("Input partition size not evenly divisible by"
74
 
                     " sector size: %d / %d", file_size, sector_size)
 
70
        logging.warn(_("Input partition size not evenly divisible by"
 
71
                       " sector size: %d / %d"), file_size, sector_size)
75
72
    primary_sectors = file_size / sector_size
76
73
    if local_bytes % sector_size != 0:
77
 
        logging.warn("Bytes for local storage not evenly divisible"
78
 
                     " by sector size: %d / %d", local_bytes, sector_size)
 
74
        logging.warn(_("Bytes for local storage not evenly divisible"
 
75
                       " by sector size: %d / %d"), local_bytes, sector_size)
79
76
    local_sectors = local_bytes / sector_size
80
77
 
81
78
    mbr_last = 62  # a
86
83
    last_sector = local_last  # e
87
84
 
88
85
    # create an empty file
89
 
    yield execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d'
90
 
                  % (outfile, mbr_last, sector_size))
 
86
    execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d'
 
87
            % (outfile, mbr_last, sector_size))
91
88
 
92
89
    # make mbr partition
93
 
    yield execute('parted --script %s mklabel msdos' % outfile)
 
90
    execute('parted --script %s mklabel msdos' % outfile)
94
91
 
95
92
    # append primary file
96
 
    yield execute('dd if=%s of=%s bs=%s conv=notrunc,fsync oflag=append'
97
 
                  % (infile, outfile, FLAGS.block_size))
 
93
    execute('dd if=%s of=%s bs=%s conv=notrunc,fsync oflag=append'
 
94
            % (infile, outfile, FLAGS.block_size))
98
95
 
99
96
    # make primary partition
100
 
    yield execute('parted --script %s mkpart primary %ds %ds'
101
 
                  % (outfile, primary_first, primary_last))
 
97
    execute('parted --script %s mkpart primary %ds %ds'
 
98
            % (outfile, primary_first, primary_last))
102
99
 
103
100
    if local_bytes > 0:
104
101
        # make the file bigger
105
 
        yield execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d'
106
 
                      % (outfile, last_sector, sector_size))
 
102
        execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d'
 
103
                % (outfile, last_sector, sector_size))
107
104
        # make and format local partition
108
 
        yield execute('parted --script %s mkpartfs primary %s %ds %ds'
109
 
                      % (outfile, local_type, local_first, local_last))
110
 
 
111
 
 
112
 
@defer.inlineCallbacks
 
105
        execute('parted --script %s mkpartfs primary %s %ds %ds'
 
106
                % (outfile, local_type, local_first, local_last))
 
107
 
 
108
 
 
109
def extend(image, size, execute):
 
110
    file_size = os.path.getsize(image)
 
111
    if file_size >= size:
 
112
        return
 
113
    return execute('truncate -s size %s' % (image,))
 
114
 
 
115
 
113
116
def inject_data(image, key=None, net=None, partition=None, execute=None):
114
117
    """Injects a ssh key and optionally net data into a disk image.
115
118
 
119
122
    If partition is not specified it mounts the image as a single partition.
120
123
 
121
124
    """
122
 
    out, err = yield execute('sudo losetup -f --show %s' % image)
 
125
    out, err = execute('sudo losetup --find --show %s' % image)
123
126
    if err:
124
 
        raise exception.Error('Could not attach image to loopback: %s' % err)
 
127
        raise exception.Error(_('Could not attach image to loopback: %s')
 
128
                              % err)
125
129
    device = out.strip()
126
130
    try:
127
131
        if not partition is None:
128
132
            # create partition
129
 
            out, err = yield execute('sudo kpartx -a %s' % device)
 
133
            out, err = execute('sudo kpartx -a %s' % device)
130
134
            if err:
131
 
                raise exception.Error('Failed to load partition: %s' % err)
 
135
                raise exception.Error(_('Failed to load partition: %s') % err)
132
136
            mapped_device = '/dev/mapper/%sp%s' % (device.split('/')[-1],
133
137
                                                   partition)
134
138
        else:
135
139
            mapped_device = device
136
 
        out, err = yield execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device)
 
140
 
 
141
        # We can only loopback mount raw images. If the device isn't there,
 
142
        # it's normally because it's a .vmdk or a .vdi etc
 
143
        if not os.path.exists(mapped_device):
 
144
            raise exception.Error('Mapped device was not found (we can'
 
145
                                  ' only inject raw disk images): %s' %
 
146
                                  mapped_device)
 
147
 
 
148
        # Configure ext2fs so that it doesn't auto-check every N boots
 
149
        out, err = execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device)
137
150
 
138
151
        tmpdir = tempfile.mkdtemp()
139
152
        try:
140
153
            # mount loopback to dir
141
 
            out, err = yield execute(
 
154
            out, err = execute(
142
155
                    'sudo mount %s %s' % (mapped_device, tmpdir))
143
156
            if err:
144
 
                raise exception.Error('Failed to mount filesystem: %s' % err)
 
157
                raise exception.Error(_('Failed to mount filesystem: %s')
 
158
                                      % err)
145
159
 
146
160
            try:
147
161
                if key:
148
162
                    # inject key file
149
 
                    yield _inject_key_into_fs(key, tmpdir, execute=execute)
 
163
                    _inject_key_into_fs(key, tmpdir, execute=execute)
150
164
                if net:
151
 
                    yield _inject_net_into_fs(net, tmpdir, execute=execute)
 
165
                    _inject_net_into_fs(net, tmpdir, execute=execute)
152
166
            finally:
153
167
                # unmount device
154
 
                yield execute('sudo umount %s' % mapped_device)
 
168
                execute('sudo umount %s' % mapped_device)
155
169
        finally:
156
170
            # remove temporary directory
157
 
            yield execute('rmdir %s' % tmpdir)
 
171
            execute('rmdir %s' % tmpdir)
158
172
            if not partition is None:
159
173
                # remove partitions
160
 
                yield execute('sudo kpartx -d %s' % device)
 
174
                execute('sudo kpartx -d %s' % device)
161
175
    finally:
162
176
        # remove loopback
163
 
        yield execute('sudo losetup -d %s' % device)
164
 
 
165
 
 
166
 
@defer.inlineCallbacks
 
177
        execute('sudo losetup --detach %s' % device)
 
178
 
 
179
 
167
180
def _inject_key_into_fs(key, fs, execute=None):
168
181
    """Add the given public ssh key to root's authorized_keys.
169
182
 
170
183
    key is an ssh key string.
171
184
    fs is the path to the base of the filesystem into which to inject the key.
172
185
    """
173
 
    sshdir = os.path.join(os.path.join(fs, 'root'), '.ssh')
174
 
    yield execute('sudo mkdir -p %s' % sshdir)  # existing dir doesn't matter
175
 
    yield execute('sudo chown root %s' % sshdir)
176
 
    yield execute('sudo chmod 700 %s' % sshdir)
 
186
    sshdir = os.path.join(fs, 'root', '.ssh')
 
187
    execute('sudo mkdir -p %s' % sshdir)  # existing dir doesn't matter
 
188
    execute('sudo chown root %s' % sshdir)
 
189
    execute('sudo chmod 700 %s' % sshdir)
177
190
    keyfile = os.path.join(sshdir, 'authorized_keys')
178
 
    yield execute('sudo tee -a %s' % keyfile, '\n' + key.strip() + '\n')
179
 
 
180
 
 
181
 
@defer.inlineCallbacks
 
191
    execute('sudo tee -a %s' % keyfile, '\n' + key.strip() + '\n')
 
192
 
 
193
 
182
194
def _inject_net_into_fs(net, fs, execute=None):
183
195
    """Inject /etc/network/interfaces into the filesystem rooted at fs.
184
196
 
185
197
    net is the contents of /etc/network/interfaces.
186
198
    """
187
199
    netdir = os.path.join(os.path.join(fs, 'etc'), 'network')
188
 
    yield execute('sudo mkdir -p %s' % netdir)  # existing dir doesn't matter
189
 
    yield execute('sudo chown root:root %s' % netdir)
190
 
    yield execute('sudo chmod 755 %s' % netdir)
 
200
    execute('sudo mkdir -p %s' % netdir)  # existing dir doesn't matter
 
201
    execute('sudo chown root:root %s' % netdir)
 
202
    execute('sudo chmod 755 %s' % netdir)
191
203
    netfile = os.path.join(netdir, 'interfaces')
192
 
    yield execute('sudo tee %s' % netfile, net)
 
204
    execute('sudo tee %s' % netfile, net)