def __init__(self,patching,logger):
     self.mounts = []
     disk_util = DiskUtil(patching,logger)
     device_items = disk_util.get_device_items(None);
     for device_item in device_items:
         mount = Mount(device_item.name, device_item.type, device_item.file_system, device_item.mount_point)
         self.mounts.append(mount)
示例#2
0
 def __init__(self, patching, logger):
     self.mounts = []
     added_mount_point_names = []
     disk_util = DiskUtil(patching, logger)
     # Get mount points
     mount_points, fs_types = disk_util.get_mount_points(None)
     # Get lsblk devices
     device_items = disk_util.get_device_items(None)
     lsblk_mounts = []
     lsblk_mount_points = []
     lsblk_fs_types = []
     # List to hold mount-points returned from lsblk command but not reurned from mount command
     lsblk_mounts_not_in_mount = []
     for device_item in device_items:
         mount = Mount(device_item.name, device_item.type,
                       device_item.file_system, device_item.mount_point)
         lsblk_mounts.append(mount)
         logger.log(
             "lsblk mount point " + str(device_item.mount_point) +
             " added with fs type " + str(device_item.file_system), True)
         lsblk_mount_points.append(device_item.mount_point)
         lsblk_fs_types.append(device_item.file_system)
         # If lsblk mount is not found in "mount command" mount-list, add it to the lsblk_mounts_not_in_mount array
         if ((device_item.mount_point not in mount_points) and
             (device_item.mount_point not in lsblk_mounts_not_in_mount)):
             lsblk_mounts_not_in_mount.append(device_item.mount_point)
     # Sort lsblk_mounts_not_in_mount array in ascending order
     lsblk_mounts_not_in_mount.sort()
     # Add the lsblk devices in the same order as they are returned in mount command output
     for mount_point, fs_type in zip(mount_points, fs_types):
         if ((mount_point in lsblk_mount_points)
                 and (mount_point not in added_mount_point_names)):
             mountObj = lsblk_mounts[lsblk_mount_points.index(mount_point)]
             if (mountObj.fstype is None or mountObj.fstype == ""
                     or mountObj.fstype == " "):
                 logger.log(
                     "fstype empty from lsblk for mount" + str(mount_point),
                     True)
                 mountObj.fstype = fs_type
             self.mounts.append(mountObj)
             added_mount_point_names.append(mount_point)
     # Append all the lsblk devices corresponding to lsblk_mounts_not_in_mount list mount-points
     for mount_point in lsblk_mounts_not_in_mount:
         if ((mount_point in lsblk_mount_points)
                 and (mount_point not in added_mount_point_names)):
             self.mounts.append(
                 lsblk_mounts[lsblk_mount_points.index(mount_point)])
             added_mount_point_names.append(mount_point)
     added_mount_point_names.reverse()
     logger.log("added_mount_point_names :" + str(added_mount_point_names),
                True)
     # Reverse the mounts list
     self.mounts.reverse()
示例#3
0
 def __init__(self,patching,logger):
     self.mounts = []
     added_mount_point_names = [] 
     disk_util = DiskUtil(patching,logger)
     # Get mount points 
     mount_points, fs_types = disk_util.get_mount_points() 
     # Get lsblk devices 
     device_items = disk_util.get_device_items(None);
     lsblk_mounts = [] 
     lsblk_mount_points = [] 
     lsblk_fs_types = []
     # List to hold mount-points returned from lsblk command but not reurned from mount command 
     lsblk_mounts_not_in_mount = [] 
     for device_item in device_items:
         mount = Mount(device_item.name, device_item.type, device_item.file_system, device_item.mount_point)
         lsblk_mounts.append(mount)
         logger.log("lsblk mount point "+str(device_item.mount_point)+" added with fs type "+str(device_item.file_system), True)
         lsblk_mount_points.append(device_item.mount_point)
         lsblk_fs_types.append(device_item.file_system)
         # If lsblk mount is not found in "mount command" mount-list, add it to the lsblk_mounts_not_in_mount array
         if((device_item.mount_point not in mount_points) and (device_item.mount_point not in lsblk_mounts_not_in_mount)):
             lsblk_mounts_not_in_mount.append(device_item.mount_point)
     # Sort lsblk_mounts_not_in_mount array in ascending order
     lsblk_mounts_not_in_mount.sort()
     # Add the lsblk devices in the same order as they are returned in mount command output
     for mount_point, fs_type in zip(mount_points, fs_types):
         if((mount_point in lsblk_mount_points) and (mount_point not in added_mount_point_names)):
             mountObj = lsblk_mounts[lsblk_mount_points.index(mount_point)]
             if(mountObj.fstype is None or mountObj.fstype == "" or mountObj.fstype == " "):
                 logger.log("fstype empty from lsblk for mount" + str(mount_point), True)
                 mountObj.fstype = fs_type
             self.mounts.append(mountObj)
             added_mount_point_names.append(mount_point)
     # Append all the lsblk devices corresponding to lsblk_mounts_not_in_mount list mount-points
     for mount_point in lsblk_mounts_not_in_mount:
         if((mount_point in lsblk_mount_points) and (mount_point not in added_mount_point_names)):
             self.mounts.append(lsblk_mounts[lsblk_mount_points.index(mount_point)])
             added_mount_point_names.append(mount_point)
     added_mount_point_names.reverse()
     logger.log("added_mount_point_names :" + str(added_mount_point_names), True)
     # Reverse the mounts list
     self.mounts.reverse()
示例#4
0
class ResourceDiskUtil(object):
    """ Resource Disk Encryption Utilities """

    RD_KEY_FILE = CommonVariables.PassphraseFileNameKey
    RD_MOUNT_POINT = '/mnt/resource'
    RD_BASE_DEV_PATH = '/dev/disk/azure/resource'
    RD_DEV_PATH = '/dev/disk/azure/resource-part1'
    DM_PREFIX = '/dev/mapper/'
    # todo: consolidate this and other key file path references
    # (BekUtil.py, ExtensionParameter.py, and dracut patches)
    RD_KEY_FILE = '/mnt/azure_bek_disk/LinuxPassPhraseFileName'
    RD_KEY_FILE_MOUNT_POINT = '/mnt/azure_bek_disk'
    RD_KEY_VOLUME_LABEL = 'BEK VOLUME'

    def __init__(self, hutil, logger, distro_patcher):
        self.hutil = hutil
        self.logger = logger
        self.executor = CommandExecutor(self.logger)
        self.disk_util = DiskUtil(hutil=self.hutil,
                                  patching=distro_patcher,
                                  logger=self.logger,
                                  encryption_environment=None)
        self.mapper_name = str(uuid.uuid4())
        self.mapper_path = self.DM_PREFIX + self.mapper_name

    def is_encrypt_format_all(self):
        """ return true if current encryption operation is EncryptFormatAll """
        try:
            public_settings_str = self.hutil._context._config[
                'runtimeSettings'][0]['handlerSettings'].get('publicSettings')
            if isinstance(public_settings_str, basestring):
                public_settings = json.loads(public_settings_str)
            else:
                public_settings = public_settings_str
            encryption_operation = public_settings.get(
                CommonVariables.EncryptionEncryptionOperationKey)
            if encryption_operation in [
                    CommonVariables.EnableEncryptionFormatAll
            ]:
                return True
        except:
            self.logger.log("unable to identify current encryption operation")
        return False

    def is_luks_device(self):
        """ checks if the device is set up with a luks header """
        if not self.resource_disk_partition_exists():
            return False
        cmd = 'cryptsetup isLuks ' + self.RD_DEV_PATH
        return (int)(self.executor.Execute(
            cmd, suppress_logging=True)) == CommonVariables.process_success

    def is_luks_device_opened(self):
        """ check for presence of luks uuid to see if device was already opened """
        # suppress logging to avoid log clutter if the device is not open yet
        if not self.resource_disk_partition_exists():
            return False
        cmd = 'test -b /dev/disk/by-uuid/$(cryptsetup luksUUID ' + self.RD_DEV_PATH + ')'
        return (int)(self.executor.ExecuteInBash(
            cmd, suppress_logging=True)) == CommonVariables.process_success

    def is_valid_key(self):
        """ test if current key can be used to open current partition """
        # suppress logging to avoid log clutter if the key doesn't match
        if not self.resource_disk_partition_exists():
            return False
        cmd = 'cryptsetup luksOpen ' + self.RD_DEV_PATH + ' --test-passphrase --key-file ' + self.RD_KEY_FILE
        return (int)(self.executor.Execute(
            cmd, suppress_logging=True)) == CommonVariables.process_success

    def resource_disk_exists(self):
        """ true if the udev name for resource disk exists """
        cmd = 'test -b ' + self.RD_BASE_DEV_PATH
        return (int)(self.executor.Execute(
            cmd, suppress_logging=True)) == CommonVariables.process_success

    def resource_disk_partition_exists(self):
        """ true if udev name for resource disk partition exists """
        cmd = 'test -b ' + self.RD_DEV_PATH
        return (int)(self.executor.Execute(
            cmd, suppress_logging=True)) == CommonVariables.process_success

    def format_luks(self):
        """ set up resource disk crypt device layer using disk util """
        if not self.resource_disk_partition_exists():
            self.logger.log(
                'LUKS format operation requested, but resource disk partition does not exist'
            )
            return False
        return (int)(self.disk_util.luks_format(
            passphrase_file=self.RD_KEY_FILE,
            dev_path=self.RD_DEV_PATH,
            header_file=None)) == CommonVariables.process_success

    def encrypt(self):
        """ use disk util with the appropriate device mapper """
        self.mount_key_volume()
        return (int)(self.disk_util.encrypt_disk(
            dev_path=self.RD_DEV_PATH,
            passphrase_file=self.RD_KEY_FILE,
            mapper_name=self.mapper_name,
            header_file=None)) == CommonVariables.process_success

    def make(self):
        """ make a default file system on top of the crypt layer """
        make_result = self.disk_util.format_disk(
            dev_path=self.mapper_path,
            file_system=CommonVariables.default_file_system)
        if make_result != CommonVariables.process_success:
            self.logger.log(msg="Failed to make file system on ephemeral disk",
                            level=CommonVariables.ErrorLevel)
            return False
        # todo - drop DATALOSS_WARNING_README.txt file to disk
        return True

    def mount_key_volume(self):
        """ attempt to mount the key volume and verify existence of key file"""
        if not os.path.exists(self.RD_KEY_FILE):
            self.disk_util.make_sure_path_exists(self.RD_KEY_FILE_MOUNT_POINT)
            key_volume_device_name = os.popen('blkid -L "' +
                                              self.RD_KEY_VOLUME_LABEL +
                                              '"').read().strip()
            self.disk_util.mount_filesystem(key_volume_device_name,
                                            self.RD_KEY_FILE_MOUNT_POINT)
        return os.path.exists(self.RD_KEY_FILE)

    def mount(self):
        """ mount the file system previously made on top of the crypt layer """
        #ensure that resource disk mount point directory has been created
        cmd = 'mkdir -p ' + self.RD_MOUNT_POINT
        if self.executor.Execute(
                cmd, suppress_logging=True) != CommonVariables.process_success:
            self.logger.log(msg='Failed to precreate mount point directory: ' +
                            cmd,
                            level=CommonVariables.ErrorLevel)
            return False

        # mount to mount point directory
        mount_result = self.disk_util.mount_filesystem(
            dev_path=self.mapper_path,
            mount_point=self.RD_MOUNT_POINT,
            file_system=CommonVariables.default_file_system)
        if mount_result != CommonVariables.process_success:
            self.logger.log(msg="Failed to mount file system on resource disk",
                            level=CommonVariables.ErrorLevel)
            return False
        return True

    def configure_waagent(self):
        """ turn off waagent.conf resource disk management  """
        # set ResourceDisk.MountPoint to standard mount point
        cmd = "sed -i.rdbak1 's|ResourceDisk.MountPoint=.*|ResourceDisk.MountPoint=" + self.RD_MOUNT_POINT + "|' /etc/waagent.conf"
        # set ResourceDiskFormat=n to ensure waagent does not attempt a simultaneous format
        cmd = "sed -i.rdbak2 's|ResourceDisk.Format=y|ResourceDisk.Format=n|' /etc/waagent.conf"
        if self.executor.ExecuteInBash(cmd) != CommonVariables.process_success:
            self.logger.log(
                msg="Failed to set ResourceDiskFormat in /etc/waagent.conf",
                level=CommonVariables.WarningLevel)
            return False
        # todo: restart waagent if necessary to ensure changes are picked up?
        return True

    def configure_fstab(self):
        """ remove resource disk from /etc/fstab if present """
        cmd = "sed -i.bak '/azure_resource-part1/d' /etc/fstab"
        if self.executor.ExecuteInBash(cmd) != CommonVariables.process_success:
            self.logger.log(
                msg="Failed to configure resource disk entry of /etc/fstab",
                level=CommonVariables.WarningLevel)
            return False
        return True

    def unmount_resource_disk(self):
        """ unmount resource disk """
        # after service healing multiple unmounts of key file mount point may be required
        self.disk_util.umount(self.RD_KEY_FILE_MOUNT_POINT)
        self.disk_util.umount(self.RD_KEY_FILE_MOUNT_POINT)
        self.disk_util.umount(self.RD_MOUNT_POINT)
        self.disk_util.umount('/mnt')

    def is_crypt_mounted(self):
        """ return true if mount point is already on a crypt layer """
        mount_items = self.disk_util.get_mount_items()
        for mount_item in mount_items:
            if mount_item["dest"] == self.RD_MOUNT_POINT and mount_item[
                    "src"].startswith(self.DM_PREFIX):
                return True
        return False

    def get_rd_device_mapper(self):
        """ retrieve current device mapper path backing the encrypted resource disk mount point """
        device_items = self.disk_util.get_device_items(self.RD_DEV_PATH)
        for device_item in device_items:
            if device_item.type.lower() == 'crypt':
                self.logger.log('Found device mapper: ' +
                                device_item.name.lower(),
                                level='Info')
                return device_item.name.lower()
        return None

    def remove_device_mapper(self):
        """ use dmsetup to remove the resource disk device mapper if it exists """
        dm_name = self.get_rd_device_mapper()
        if dm_name:
            cmd = 'dmsetup remove ' + self.DM_PREFIX + dm_name
            if self.executor.Execute(cmd) == CommonVariables.process_success:
                return True
            else:
                self.logger.log('failed to remove ' + dm_name)
        else:
            self.logger.log('no resource disk device mapper found')
        return False

    def prepare_partition(self):
        """ create partition on resource disk if missing """
        if self.resource_disk_partition_exists():
            return True
        self.logger.log("resource disk partition does not exist", level='Info')
        cmd = 'parted ' + self.RD_BASE_DEV_PATH + ' mkpart primary ext4 0% 100%'
        if self.executor.ExecuteInBash(cmd) == CommonVariables.process_success:
            # wait for the corresponding udev name to become available
            for i in range(0, 10):
                time.sleep(i)
                if self.resource_disk_partition_exists():
                    return True
        self.logger.log('unable to make resource disk partition')
        return False

    def clear_luks_header(self):
        """ clear luks header by overwriting with 10MB of entropy """
        if not self.resource_disk_partition_exists():
            self.logger.log(
                "resource partition does not exist, no luks header to clear")
            return True
        cmd = 'dd if=/dev/urandom of=' + self.RD_DEV_PATH + ' bs=512 count=20480'
        return self.executor.Execute(cmd) == CommonVariables.process_success

    def try_remount(self):
        """ mount encrypted resource disk if not already mounted"""
        if self.is_crypt_mounted():
            self.logger.log("resource disk already encrypted and mounted",
                            level='Info')
            return True

        if self.resource_disk_exists() and self.resource_disk_partition_exists(
        ) and self.is_luks_device() and self.is_valid_key():
            # store the currently associated path and name
            current_mapper_name = self.get_rd_device_mapper()
            if current_mapper_name:
                self.mapper_name = current_mapper_name
                self.mapper_path = self.DM_PREFIX + self.mapper_name
                if not self.is_luks_device_opened:
                    # attempt to open
                    self.disk_util.luks_open(passphrase_file=self.RD_KEY_FILE,
                                             dev_path=self.RD_DEV_PATH,
                                             mapper_name=self.mapper_name,
                                             header_file=None,
                                             uses_cleartext_key=False)
                    if not self.is_luks_device_opened:
                        return False
                # attempt mount
                return self.mount()

        # conditions required to re-mount were not met
        return False

    def prepare(self):
        """ prepare a non-encrypted resource disk to be encrypted """
        self.configure_waagent()
        self.configure_fstab()
        if self.resource_disk_partition_exists():
            self.disk_util.swapoff()
            self.unmount_resource_disk()
            self.remove_device_mapper()
            self.clear_luks_header()
        self.prepare_partition()
        return True

    def automount(self):
        """ encrypt resource disk """
        # try to remount if the disk was previously encrypted and is still valid
        if self.try_remount():
            return True

        # unencrypted or unusable
        if self.is_encrypt_format_all():
            return self.prepare() and self.encrypt() and self.make(
            ) and self.mount()
        else:
            self.logger.log(
                'EncryptionFormatAll not in use, resource disk will not be automatically formatted and encrypted.'
            )
class ResourceDiskUtil(object):
    """ Resource Disk Encryption Utilities """

    RD_KEY_FILE = CommonVariables.PassphraseFileNameKey
    RD_MOUNT_POINT = '/mnt/resource'
    RD_BASE_DEV_PATH = '/dev/disk/azure/resource'
    RD_DEV_PATH = '/dev/disk/azure/resource-part1'
    DM_PREFIX = '/dev/mapper/'
    # todo: consolidate this and other key file path references
    # (BekUtil.py, ExtensionParameter.py, and dracut patches)
    RD_KEY_FILE = '/mnt/azure_bek_disk/LinuxPassPhraseFileName'
    RD_KEY_FILE_MOUNT_POINT = '/mnt/azure_bek_disk'
    RD_KEY_VOLUME_LABEL = 'BEK VOLUME'

    def __init__(self, hutil, logger, distro_patcher):
        self.hutil = hutil
        self.logger = logger
        self.executor = CommandExecutor(self.logger)
        self.disk_util = DiskUtil(hutil=self.hutil, patching=distro_patcher, logger=self.logger, encryption_environment=None)
        self.mapper_name = str(uuid.uuid4())
        self.mapper_path = self.DM_PREFIX + self.mapper_name

    def is_encrypt_format_all(self):
        """ return true if current encryption operation is EncryptFormatAll """
        try:                
            public_settings_str = self.hutil._context._config['runtimeSettings'][0]['handlerSettings'].get('publicSettings')
            if isinstance(public_settings_str, basestring):
                public_settings = json.loads(public_settings_str)
            else:
                public_settings = public_settings_str
            encryption_operation = public_settings.get(CommonVariables.EncryptionEncryptionOperationKey)
            if encryption_operation in [CommonVariables.EnableEncryptionFormatAll]:
                return True
        except:
            self.logger.log("unable to identify current encryption operation")
        return False

    def is_luks_device(self):
        """ checks if the device is set up with a luks header """
        if not self.resource_disk_partition_exists():
            return False
        cmd = 'cryptsetup isLuks ' + self.RD_DEV_PATH
        return (int)(self.executor.Execute(cmd, suppress_logging=True)) == CommonVariables.process_success

    def is_luks_device_opened(self):
        """ check for presence of luks uuid to see if device was already opened """
        # suppress logging to avoid log clutter if the device is not open yet
        if not self.resource_disk_partition_exists():
            return False
        cmd = 'test -b /dev/disk/by-uuid/$(cryptsetup luksUUID ' + self.RD_DEV_PATH + ')'
        return (int)(self.executor.ExecuteInBash(cmd, suppress_logging=True)) == CommonVariables.process_success

    def is_valid_key(self):
        """ test if current key can be used to open current partition """
        # suppress logging to avoid log clutter if the key doesn't match
        if not self.resource_disk_partition_exists():
            return False
        cmd = 'cryptsetup luksOpen ' + self.RD_DEV_PATH + ' --test-passphrase --key-file ' + self.RD_KEY_FILE
        return (int)(self.executor.Execute(cmd, suppress_logging=True)) == CommonVariables.process_success

    def resource_disk_exists(self):
        """ true if the udev name for resource disk exists """
        cmd = 'test -b ' + self.RD_BASE_DEV_PATH
        return (int)(self.executor.Execute(cmd, suppress_logging=True)) == CommonVariables.process_success

    def resource_disk_partition_exists(self):
        """ true if udev name for resource disk partition exists """
        cmd = 'test -b ' + self.RD_DEV_PATH
        return (int)(self.executor.Execute(cmd, suppress_logging=True)) == CommonVariables.process_success

    def format_luks(self):
        """ set up resource disk crypt device layer using disk util """
        if not self.resource_disk_partition_exists():
            self.logger.log('LUKS format operation requested, but resource disk partition does not exist')
            return False
        return (int)(self.disk_util.luks_format(passphrase_file=self.RD_KEY_FILE, dev_path=self.RD_DEV_PATH, header_file=None)) == CommonVariables.process_success

    def encrypt(self):
        """ use disk util with the appropriate device mapper """
        self.mount_key_volume()
        return (int)(self.disk_util.encrypt_disk(dev_path=self.RD_DEV_PATH, passphrase_file=self.RD_KEY_FILE, mapper_name=self.mapper_name, header_file=None)) == CommonVariables.process_success

    def make(self):
        """ make a default file system on top of the crypt layer """
        make_result = self.disk_util.format_disk(dev_path=self.mapper_path, file_system=CommonVariables.default_file_system)
        if make_result != CommonVariables.process_success:
            self.logger.log(msg="Failed to make file system on ephemeral disk", level=CommonVariables.ErrorLevel)
            return False
        # todo - drop DATALOSS_WARNING_README.txt file to disk
        return True

    def mount_key_volume(self):
        """ attempt to mount the key volume and verify existence of key file"""
        if not os.path.exists(self.RD_KEY_FILE):
            self.disk_util.make_sure_path_exists(self.RD_KEY_FILE_MOUNT_POINT)
            key_volume_device_name = os.popen('blkid -L "' + self.RD_KEY_VOLUME_LABEL + '"').read().strip()
            self.disk_util.mount_filesystem(key_volume_device_name, self.RD_KEY_FILE_MOUNT_POINT)
        return os.path.exists(self.RD_KEY_FILE)
        
    def mount(self):
        """ mount the file system previously made on top of the crypt layer """
        #ensure that resource disk mount point directory has been created
        cmd = 'mkdir -p ' + self.RD_MOUNT_POINT
        if self.executor.Execute(cmd, suppress_logging=True) != CommonVariables.process_success:
            self.logger.log(msg='Failed to precreate mount point directory: ' + cmd, level=CommonVariables.ErrorLevel)
            return False

        # mount to mount point directory
        mount_result = self.disk_util.mount_filesystem(dev_path=self.mapper_path, mount_point=self.RD_MOUNT_POINT, file_system=CommonVariables.default_file_system)
        if mount_result != CommonVariables.process_success:
            self.logger.log(msg="Failed to mount file system on resource disk", level=CommonVariables.ErrorLevel)
            return False
        return True

    def configure_waagent(self):
        """ turn off waagent.conf resource disk management  """
        # set ResourceDisk.MountPoint to standard mount point
        cmd = "sed -i.rdbak1 's|ResourceDisk.MountPoint=.*|ResourceDisk.MountPoint=" + self.RD_MOUNT_POINT + "|' /etc/waagent.conf"
        # set ResourceDiskFormat=n to ensure waagent does not attempt a simultaneous format
        cmd = "sed -i.rdbak2 's|ResourceDisk.Format=y|ResourceDisk.Format=n|' /etc/waagent.conf"
        if self.executor.ExecuteInBash(cmd) != CommonVariables.process_success:
            self.logger.log(msg="Failed to set ResourceDiskFormat in /etc/waagent.conf", level=CommonVariables.WarningLevel)
            return False
        # todo: restart waagent if necessary to ensure changes are picked up?
        return True

    def configure_fstab(self):
        """ remove resource disk from /etc/fstab if present """
        cmd = "sed -i.bak '/azure_resource-part1/d' /etc/fstab"
        if self.executor.ExecuteInBash(cmd) != CommonVariables.process_success:
            self.logger.log(msg="Failed to configure resource disk entry of /etc/fstab", level=CommonVariables.WarningLevel)
            return False        
        return True

    def unmount_resource_disk(self):
        """ unmount resource disk """
        # after service healing multiple unmounts of key file mount point may be required
        self.disk_util.umount(self.RD_KEY_FILE_MOUNT_POINT)
        self.disk_util.umount(self.RD_KEY_FILE_MOUNT_POINT)
        self.disk_util.umount(self.RD_MOUNT_POINT)
        self.disk_util.umount('/mnt')

    def is_crypt_mounted(self):
        """ return true if mount point is already on a crypt layer """
        mount_items = self.disk_util.get_mount_items()
        for mount_item in mount_items:
            if mount_item["dest"] == self.RD_MOUNT_POINT and mount_item["src"].startswith(self.DM_PREFIX):
                return True
        return False

    def get_rd_device_mapper(self):
        """ retrieve current device mapper path backing the encrypted resource disk mount point """
        device_items = self.disk_util.get_device_items(self.RD_DEV_PATH)
        for device_item in device_items:
            if device_item.type.lower() == 'crypt':
                self.logger.log('Found device mapper: ' + device_item.name.lower(), level='Info')
                return device_item.name.lower()
        return None

    def remove_device_mapper(self):
        """ use dmsetup to remove the resource disk device mapper if it exists """
        dm_name = self.get_rd_device_mapper()
        if dm_name:
            cmd = 'dmsetup remove ' + self.DM_PREFIX + dm_name
            if self.executor.Execute(cmd) == CommonVariables.process_success:
                return True
            else:
                self.logger.log('failed to remove ' + dm_name)
        else:
            self.logger.log('no resource disk device mapper found')
        return False

    def prepare_partition(self):
        """ create partition on resource disk if missing """
        if self.resource_disk_partition_exists():
            return True
        self.logger.log("resource disk partition does not exist", level='Info')
        cmd = 'parted ' + self.RD_BASE_DEV_PATH + ' mkpart primary ext4 0% 100%'
        if self.executor.ExecuteInBash(cmd) == CommonVariables.process_success:
            # wait for the corresponding udev name to become available
            for i in range(0, 10):
                time.sleep(i)
                if self.resource_disk_partition_exists():
                    return True
        self.logger.log('unable to make resource disk partition')
        return False


    def clear_luks_header(self):
        """ clear luks header by overwriting with 10MB of entropy """
        if not self.resource_disk_partition_exists():
            self.logger.log("resource partition does not exist, no luks header to clear")
            return True
        cmd = 'dd if=/dev/urandom of=' + self.RD_DEV_PATH + ' bs=512 count=20480'
        return self.executor.Execute(cmd) == CommonVariables.process_success
            
    def try_remount(self):
        """ mount encrypted resource disk if not already mounted"""
        if self.is_crypt_mounted():
            self.logger.log("resource disk already encrypted and mounted", level='Info')
            return True

        if self.resource_disk_exists() and self.resource_disk_partition_exists() and self.is_luks_device() and self.is_valid_key():
            # store the currently associated path and name
            current_mapper_name = self.get_rd_device_mapper()
            if current_mapper_name:
                self.mapper_name = current_mapper_name
                self.mapper_path = self.DM_PREFIX + self.mapper_name
                if not self.is_luks_device_opened:
                    # attempt to open
                    self.disk_util.luks_open(passphrase_file=self.RD_KEY_FILE, dev_path=self.RD_DEV_PATH, mapper_name=self.mapper_name, header_file=None, uses_cleartext_key=False)
                    if not self.is_luks_device_opened:
                        return False
                # attempt mount
                return self.mount()

        # conditions required to re-mount were not met
        return False

    def prepare(self):
        """ prepare a non-encrypted resource disk to be encrypted """
        self.configure_waagent()
        self.configure_fstab()
        if self.resource_disk_partition_exists():
            self.disk_util.swapoff()
            self.unmount_resource_disk()
            self.remove_device_mapper()
            self.clear_luks_header()
        self.prepare_partition()
        return True

    def automount(self):
        """ encrypt resource disk """
        # try to remount if the disk was previously encrypted and is still valid
        if self.try_remount():
            return True

        # unencrypted or unusable
        if self.is_encrypt_format_all():
            return self.prepare() and self.encrypt() and self.make() and self.mount()
        else:
            self.logger.log('EncryptionFormatAll not in use, resource disk will not be automatically formatted and encrypted.')