Coverage for nova/virt/libvirt/storage/dmcrypt.py: 94%

29 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-04-24 11:16 +0000

1# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory 

2# All Rights Reserved 

3# 

4# Licensed under the Apache License, Version 2.0 (the "License"); you may 

5# not use this file except in compliance with the License. You may obtain 

6# a copy of the License at 

7# 

8# http://www.apache.org/licenses/LICENSE-2.0 

9# 

10# Unless required by applicable law or agreed to in writing, software 

11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

13# License for the specific language governing permissions and limitations 

14# under the License. 

15 

16import os 

17 

18from oslo_concurrency import processutils 

19from oslo_log import log as logging 

20from oslo_utils import excutils 

21 

22import nova.privsep.libvirt 

23 

24 

25LOG = logging.getLogger(__name__) 

26 

27_dmcrypt_suffix = '-dmcrypt' 

28 

29 

30def volume_name(base): 

31 """Returns the suffixed dmcrypt volume name. 

32 

33 This is to avoid collisions with similarly named device mapper names for 

34 LVM volumes 

35 """ 

36 return base + _dmcrypt_suffix 

37 

38 

39def is_encrypted(path): 

40 """Returns true if the path corresponds to an encrypted disk.""" 

41 if path.startswith('/dev/mapper'): 41 ↛ 44line 41 didn't jump to line 44 because the condition on line 41 was always true

42 return path.rpartition('/')[2].endswith(_dmcrypt_suffix) 

43 else: 

44 return False 

45 

46 

47def create_volume(target, device, cipher, key_size, key): 

48 """Sets up a dmcrypt mapping 

49 

50 :param target: device mapper logical device name 

51 :param device: underlying block device 

52 :param cipher: encryption cipher string digestible by cryptsetup 

53 :param key_size: encryption key size 

54 :param key: encoded encryption key bytestring 

55 """ 

56 try: 

57 nova.privsep.libvirt.dmcrypt_create_volume( 

58 target, device, cipher, key_size, key) 

59 except processutils.ProcessExecutionError as e: 

60 with excutils.save_and_reraise_exception(): 

61 LOG.error("Could not start encryption for disk %(device)s: " 

62 "%(exception)s", {'device': device, 'exception': e}) 

63 

64 

65def delete_volume(target): 

66 """Deletes a dmcrypt mapping 

67 

68 :param target: name of the mapped logical device 

69 """ 

70 try: 

71 nova.privsep.libvirt.dmcrypt_delete_volume(target) 

72 except processutils.ProcessExecutionError as e: 

73 # cryptsetup returns 4 when attempting to destroy a non-existent 

74 # dm-crypt device. It indicates that the device is invalid, which 

75 # means that the device is invalid (i.e., it has already been 

76 # destroyed). 

77 if e.exit_code == 4: 

78 LOG.debug("Ignoring exit code 4, volume already destroyed") 

79 else: 

80 with excutils.save_and_reraise_exception(): 

81 LOG.error("Could not disconnect encrypted volume " 

82 "%(volume)s. If dm-crypt device is still active " 

83 "it will have to be destroyed manually for " 

84 "cleanup to succeed.", {'volume': target}) 

85 

86 

87def list_volumes(): 

88 """Function enumerates encrypted volumes.""" 

89 return [dmdev for dmdev in os.listdir('/dev/mapper') 

90 if dmdev.endswith('-dmcrypt')]