Adds dmcrypt utility module
Patch adds a module for manipulating dmcrypt devices. Implements: blueprint encrypt-ephemeral-storage Change-Id: I308b9f26c382b332c02f13aa1d5f0a830e9ef277
This commit is contained in:
parent
50c9055c8e
commit
b15b197b6f
|
@ -202,9 +202,12 @@ systool: CommandFilter, systool, root
|
|||
# nova/virt/libvirt/volume.py:
|
||||
sginfo: CommandFilter, sginfo, root
|
||||
sg_scan: CommandFilter, sg_scan, root
|
||||
cryptsetup: CommandFilter, cryptsetup, root
|
||||
ln: RegExpFilter, ln, root, ln, --symbolic, --force, /dev/mapper/ip-.*-iscsi-iqn.2010-10.org.openstack:volume-.*, /dev/disk/by-path/ip-.*-iscsi-iqn.2010-10.org.openstack:volume-.*
|
||||
|
||||
# nova/volume/encryptors.py:
|
||||
# nova/virt/libvirt/dmcrypt.py:
|
||||
cryptsetup: CommandFilter, cryptsetup, root
|
||||
|
||||
# nova/virt/xenapi/vm_utils.py:
|
||||
xenstore-read: CommandFilter, xenstore-read, root
|
||||
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from nova import test
|
||||
from nova import utils
|
||||
from nova.virt.libvirt import dmcrypt
|
||||
|
||||
|
||||
class LibvirtDmcryptTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(LibvirtDmcryptTestCase, self).setUp()
|
||||
|
||||
self.CIPHER = 'cipher'
|
||||
self.KEY_SIZE = 256
|
||||
self.NAME = 'disk'
|
||||
self.TARGET = dmcrypt.volume_name(self.NAME)
|
||||
self.PATH = '/dev/nova-lvm/instance_disk'
|
||||
self.KEY = range(0, self.KEY_SIZE)
|
||||
self.KEY_STR = ''.join(["%02x" % x for x in range(0, self.KEY_SIZE)])
|
||||
|
||||
self.executes = []
|
||||
self.kwargs = {}
|
||||
|
||||
def fake_execute(*cmd, **kwargs):
|
||||
self.executes.append(cmd)
|
||||
self.kwargs = kwargs
|
||||
return None, None
|
||||
|
||||
def fake_listdir(path):
|
||||
return [self.TARGET, '/dev/mapper/disk']
|
||||
|
||||
self.stubs.Set(utils, 'execute', fake_execute)
|
||||
self.stubs.Set(os, 'listdir', fake_listdir)
|
||||
|
||||
def test_create_volume(self):
|
||||
expected_commands = [('cryptsetup',
|
||||
'create',
|
||||
self.TARGET,
|
||||
self.PATH,
|
||||
'--cipher=' + self.CIPHER,
|
||||
'--key-size=' + str(self.KEY_SIZE),
|
||||
'--key-file=-')]
|
||||
dmcrypt.create_volume(self.TARGET, self.PATH, self.CIPHER,
|
||||
self.KEY_SIZE, self.KEY)
|
||||
|
||||
self.assertEqual(expected_commands, self.executes)
|
||||
self.assertEqual(self.KEY_STR, self.kwargs['process_input'])
|
||||
|
||||
def test_delete_volume(self):
|
||||
expected_commands = [('cryptsetup', 'remove', self.TARGET)]
|
||||
dmcrypt.delete_volume(self.TARGET)
|
||||
|
||||
self.assertEqual(expected_commands, self.executes)
|
||||
|
||||
def test_list_volumes(self):
|
||||
encrypted_volumes = dmcrypt.list_volumes()
|
||||
|
||||
self.assertEqual([self.TARGET], encrypted_volumes)
|
|
@ -0,0 +1,63 @@
|
|||
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
|
||||
# All Rights Reserved
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from nova.virt.libvirt import utils
|
||||
|
||||
_dmcrypt_suffix = '-dmcrypt'
|
||||
|
||||
|
||||
def volume_name(base):
|
||||
"""Returns the suffixed dmcrypt volume name.
|
||||
|
||||
This is to avoid collisions with similarly named device mapper names for
|
||||
LVM volumes
|
||||
"""
|
||||
return base + _dmcrypt_suffix
|
||||
|
||||
|
||||
def create_volume(target, device, cipher, key_size, key):
|
||||
"""Sets up a dmcrypt mapping
|
||||
|
||||
:param target: device mapper logical device name
|
||||
:param device: underlying block device
|
||||
:param cipher: encryption cipher string digestible by cryptsetup
|
||||
:param cipher: encryption key size
|
||||
:param key: encryption key as an array of unsigned bytes
|
||||
"""
|
||||
cmd = ('cryptsetup',
|
||||
'create',
|
||||
target,
|
||||
device,
|
||||
'--cipher=' + cipher,
|
||||
'--key-size=' + str(key_size),
|
||||
'--key-file=-')
|
||||
key = ''.join(map(lambda byte: "%02x" % byte, key))
|
||||
utils.execute(*cmd, process_input=key, run_as_root=True)
|
||||
|
||||
|
||||
def delete_volume(target):
|
||||
"""Deletes a dmcrypt mapping
|
||||
|
||||
:param target: name of the mapped logical device
|
||||
"""
|
||||
utils.execute('cryptsetup', 'remove', target, run_as_root=True)
|
||||
|
||||
|
||||
def list_volumes():
|
||||
"""Function enumerates encrypted volumes."""
|
||||
return [dmdev for dmdev in os.listdir('/dev/mapper')
|
||||
if dmdev.endswith('-dmcrypt')]
|
Loading…
Reference in New Issue