#
#    id:
#        An opaque string.  In order for this module to know that the remote
#        FS is the same one that is mounted locally it must share information
#        with the glance deployment.  Both glance and nova-compute must be
#        configured with a unique matching string.  This ensures that the
#        file:// advertised URL is describing a file system that is known
#        to nova-compute
#    mountpoint:
#        The location at which the file system is locally mounted.  Glance
#        may mount a shared file system on a different path than nova-compute.
#        This value will be compared against the metadata advertised with
#        glance and paths will be adjusted to ensure that the correct file
#        file is copied.
#
#  If these values are not added to nova.conf and the file module is in the
#  allowed_direct_url_schemes list, then the legacy behavior will occur such
#  that a copy will be attempted assuming that the glance and nova file systems
#  are the same.
**** CubicPower OpenStack Study ****
class FileTransfer(xfer_base.TransferBase):
    desc_required_keys = ['id', 'mountpoint']
    #NOTE(jbresnah) because the group under which these options are added is
    # dyncamically determined these options need to stay out of global space
    # or they will confuse generate_sample.sh
    filesystem_opts = [
         cfg.StrOpt('id',
                    help=_('A unique ID given to each file system.  This is '
                           'value is set in Glance and agreed upon here so '
                           'that the operator knowns they are dealing with '
                           'the same file system.')),
         cfg.StrOpt('mountpoint',
                    help=_('The path at which the file system is mounted.')),
    ]
    
**** CubicPower OpenStack Study ****
    def _get_options(self):
        fs_dict = {}
        for fs in CONF.image_file_url.filesystems:
            group_name = 'image_file_url:' + fs
            conf_group = CONF[group_name]
            if conf_group.id is None:
                msg = _('The group %s(group_name) must be configured with '
                        'an id.')
                raise exception.ImageDownloadModuleConfigurationError(
                    module=str(self), reason=msg)
            fs_dict[CONF[group_name].id] = CONF[group_name]
        return fs_dict
**** CubicPower OpenStack Study ****
    def __init__(self):
        # create the needed options
        for fs in CONF.image_file_url.filesystems:
            group_name = 'image_file_url:' + fs
            CONF.register_opts(self.filesystem_opts, group=group_name)
**** CubicPower OpenStack Study ****
    def _verify_config(self):
        for fs_key in self.filesystems:
            for r in self.desc_required_keys:
                fs_ent = self.filesystems[fs_key]
                if fs_ent[r] is None:
                    msg = _('The key %s is required in all file system '
                            'descriptions.')
                    LOG.error(msg)
                    raise exception.ImageDownloadModuleConfigurationError(
                        module=str(self), reason=msg)
**** CubicPower OpenStack Study ****
    def _file_system_lookup(self, metadata, url_parts):
        for r in self.desc_required_keys:
            if r not in metadata:
                url = url_parts.geturl()
                msg = _('The key %(r)s is required in the location metadata '
                        'to access the url %(url)s.') % {'r': r, 'url': url}
                LOG.info(msg)
                raise exception.ImageDownloadModuleMetaDataError(
                    module=str(self), reason=msg)
        id = metadata['id']
        if id not in self.filesystems:
            msg = _('The ID %(id)s is unknown.') % {'id': id}
            LOG.info(msg)
            return
        fs_descriptor = self.filesystems[id]
        return fs_descriptor
**** CubicPower OpenStack Study ****
    def _normalize_destination(self, nova_mount, glance_mount, path):
        if not path.startswith(glance_mount):
            msg = (_('The mount point advertised by glance: %(glance_mount)s, '
                     'does not match the URL path: %(path)s') %
                     {'glance_mount': glance_mount, 'path': path})
            raise exception.ImageDownloadModuleMetaDataError(
                module=str(self), reason=msg)
        new_path = path.replace(glance_mount, nova_mount, 1)
        return new_path
**** CubicPower OpenStack Study ****
    def download(self, context, url_parts, dst_file, metadata, **kwargs):
        self.filesystems = self._get_options()
        if not self.filesystems:
            #NOTE(jbresnah) when nothing is configured assume legacy behavior
            nova_mountpoint = '/'
            glance_mountpoint = '/'
        else:
            self._verify_config()
            fs_descriptor = self._file_system_lookup(metadata, url_parts)
            if fs_descriptor is None:
                msg = (_('No matching ID for the URL %s was found.') %
                        url_parts.geturl())
                raise exception.ImageDownloadModuleError(reason=msg,
                                                    module=str(self))
            nova_mountpoint = fs_descriptor['mountpoint']
            glance_mountpoint = metadata['mountpoint']
        source_file = self._normalize_destination(nova_mountpoint,
                                                  glance_mountpoint,
                                                  url_parts.path)
        lv_utils.copy_image(source_file, dst_file)
        LOG.info(_('Copied %(source_file)s using %(module_str)s') %
                 {'source_file': source_file, 'module_str': str(self)})
def get_download_handler(**kwargs):
    return FileTransfer()
def get_schemes():
    return ['file', 'filesystem']
**** CubicPower OpenStack Study ****
def get_download_handler(**kwargs):
    return FileTransfer()
**** CubicPower OpenStack Study ****
def get_schemes():
    return ['file', 'filesystem']