Remove code for image syncing which is not used now
Change-Id: I088977739394448e9ad8038480c1da52df2a8c24
This commit is contained in:
@@ -1,185 +0,0 @@
|
|||||||
"""Implementation of an cascading image service that uses to sync the image
|
|
||||||
from cascading glance to the special cascaded glance.
|
|
||||||
"""
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from oslo.config import cfg
|
|
||||||
|
|
||||||
from nova.image import glance
|
|
||||||
from nova.image.sync import drivers as drivermgr
|
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
glance_cascading_opt = [
|
|
||||||
cfg.StrOpt('image_copy_dest_location_url',
|
|
||||||
default='file:///var/lib/glance/images',
|
|
||||||
help=("The path cascaded image_data copy to."),
|
|
||||||
deprecated_opts=[cfg.DeprecatedOpt('dest_location_url',
|
|
||||||
group='DEFAULT')]),
|
|
||||||
cfg.StrOpt('image_copy_dest_host',
|
|
||||||
default='127.0.0.1',
|
|
||||||
help=("The host name where image_data copy to."),
|
|
||||||
deprecated_opts=[cfg.DeprecatedOpt('dest_host',
|
|
||||||
group='DEFAULT')]),
|
|
||||||
cfg.StrOpt('image_copy_dest_user',
|
|
||||||
default='glance',
|
|
||||||
help=("The user name of cascaded glance for copy."),
|
|
||||||
deprecated_opts=[cfg.DeprecatedOpt('dest_user',
|
|
||||||
group='DEFAULT')]),
|
|
||||||
cfg.StrOpt('image_copy_dest_password',
|
|
||||||
default='openstack',
|
|
||||||
help=("The passowrd of cascaded glance for copy."),
|
|
||||||
deprecated_opts=[cfg.DeprecatedOpt('dest_password',
|
|
||||||
group='DEFAULT')]),
|
|
||||||
cfg.StrOpt('image_copy_source_location_url',
|
|
||||||
default='file:///var/lib/glance/images',
|
|
||||||
help=("where the cascaded image data from"),
|
|
||||||
deprecated_opts=[cfg.DeprecatedOpt('source_location_url',
|
|
||||||
group='DEFAULT')]),
|
|
||||||
cfg.StrOpt('image_copy_source_host',
|
|
||||||
default='0.0.0.1',
|
|
||||||
help=("The host name where image_data copy from."),
|
|
||||||
deprecated_opts=[cfg.DeprecatedOpt('source_host',
|
|
||||||
group='DEFAULT')]),
|
|
||||||
cfg.StrOpt('image_copy_source_user',
|
|
||||||
default='glance',
|
|
||||||
help=("The user name of glance for copy."),
|
|
||||||
deprecated_opts=[cfg.DeprecatedOpt('source_user',
|
|
||||||
group='DEFAULT')]),
|
|
||||||
cfg.StrOpt('image_copy_source_password',
|
|
||||||
default='openstack',
|
|
||||||
help=("The passowrd of glance for copy."),
|
|
||||||
deprecated_opts=[cfg.DeprecatedOpt('source_password',
|
|
||||||
group='DEFAULT')]),
|
|
||||||
]
|
|
||||||
|
|
||||||
CONF.register_opts(glance_cascading_opt)
|
|
||||||
|
|
||||||
_V2_IMAGE_CREATE_PROPERTIES = ['container_format', 'disk_format', 'min_disk',
|
|
||||||
'min_ram', 'name', 'protected']
|
|
||||||
|
|
||||||
|
|
||||||
def get_adding_image_properties(image):
|
|
||||||
_tags = list(image.tags) or []
|
|
||||||
kwargs = {}
|
|
||||||
for key in _V2_IMAGE_CREATE_PROPERTIES:
|
|
||||||
try:
|
|
||||||
value = getattr(image, key, None)
|
|
||||||
if value and value != 'None':
|
|
||||||
kwargs[key] = value
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
if _tags:
|
|
||||||
kwargs['tags'] = _tags
|
|
||||||
return kwargs
|
|
||||||
|
|
||||||
|
|
||||||
def get_candidate_path(image, scheme='file'):
|
|
||||||
locations = image.locations or []
|
|
||||||
for loc in locations:
|
|
||||||
if loc['url'].startswith(scheme):
|
|
||||||
return loc['url'] if scheme != 'file' \
|
|
||||||
else loc['url'][len('file://'):]
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_copy_driver(scheme_key):
|
|
||||||
return drivermgr.get_store_driver(scheme_key)
|
|
||||||
|
|
||||||
|
|
||||||
def get_host_port(url):
|
|
||||||
if not url:
|
|
||||||
return None, None
|
|
||||||
pieces = urlparse.urlparse(url)
|
|
||||||
return pieces.netloc.split(":")[0], pieces.netloc.split(":")[1]
|
|
||||||
|
|
||||||
|
|
||||||
class GlanceCascadingService(object):
|
|
||||||
|
|
||||||
def __init__(self, cascading_client=None):
|
|
||||||
self._client = cascading_client or glance.GlanceClientWrapper()
|
|
||||||
|
|
||||||
def sync_image(self, context, cascaded_url, cascading_image):
|
|
||||||
cascaded_glance_url = cascaded_url
|
|
||||||
_host, _port = get_host_port(cascaded_glance_url)
|
|
||||||
_cascaded_client = glance.GlanceClientWrapper(context=context,
|
|
||||||
host=_host,
|
|
||||||
port=_port,
|
|
||||||
version=2)
|
|
||||||
|
|
||||||
image_meta = get_adding_image_properties(cascading_image)
|
|
||||||
cascaded_image = _cascaded_client.call(context, 2, 'create',
|
|
||||||
**image_meta)
|
|
||||||
image_id = cascading_image.id
|
|
||||||
cascaded_id = cascaded_image.id
|
|
||||||
candidate_path = get_candidate_path(cascading_image)
|
|
||||||
LOG.debug("the candidate path is %s." % (candidate_path))
|
|
||||||
# copy image
|
|
||||||
try:
|
|
||||||
image_loc = self._copy_data(image_id, cascaded_id, candidate_path)
|
|
||||||
except Exception as e:
|
|
||||||
LOG.exception(("copy image failed, reason=%s") % e)
|
|
||||||
raise
|
|
||||||
else:
|
|
||||||
if not image_loc:
|
|
||||||
LOG.exception(("copy image Exception, no cascaded_loc"))
|
|
||||||
try:
|
|
||||||
# patch loc to the cascaded image
|
|
||||||
csd_locs = [{'url': image_loc,
|
|
||||||
'metadata': {}
|
|
||||||
}]
|
|
||||||
_cascaded_client.call(context, 2, 'update', cascaded_id,
|
|
||||||
remove_props=None,
|
|
||||||
locations=csd_locs)
|
|
||||||
except Exception as e:
|
|
||||||
LOG.exception(("patch loc to cascaded image Exception, reason: %s"
|
|
||||||
% e))
|
|
||||||
raise
|
|
||||||
|
|
||||||
try:
|
|
||||||
# patch glance-loc to cascading image
|
|
||||||
csg_locs = cascading_image.locations
|
|
||||||
glance_loc = '%s/v2/images/%s' % (cascaded_glance_url,
|
|
||||||
cascaded_id)
|
|
||||||
csg_locs.append({'url': glance_loc,
|
|
||||||
'metadata': {'image_id': str(cascaded_id),
|
|
||||||
'action': 'upload'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
self._client.call(context, 2, 'update', image_id,
|
|
||||||
remove_props=None, locations=csg_locs)
|
|
||||||
except Exception as e:
|
|
||||||
LOG.exception(("patch loc to cascading image Exception, reason: %s"
|
|
||||||
% e))
|
|
||||||
raise
|
|
||||||
|
|
||||||
return cascaded_id
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _copy_data(cascading_id, cascaded_id, candidate_path):
|
|
||||||
source_pieces = urlparse.urlparse(CONF.image_copy_source_location_url)
|
|
||||||
dest_pieces = urlparse.urlparse(CONF.image_copy_dest_location_url)
|
|
||||||
source_scheme = source_pieces.scheme
|
|
||||||
dest_scheme = dest_pieces.scheme
|
|
||||||
_key = ('%s:%s' % (source_scheme, dest_scheme))
|
|
||||||
copy_driver = get_copy_driver(_key)
|
|
||||||
source_path = os.path.join(source_pieces.path, cascading_id)
|
|
||||||
dest_path = os.path.join(dest_pieces.path, cascaded_id)
|
|
||||||
|
|
||||||
source_location = {'host': CONF.image_copy_source_host,
|
|
||||||
'login_user': CONF.image_copy_source_user,
|
|
||||||
'login_password': CONF.image_copy_source_password,
|
|
||||||
'path': source_path
|
|
||||||
}
|
|
||||||
dest_location = {'host': CONF.image_copy_dest_host,
|
|
||||||
'login_user': CONF.image_copy_dest_user,
|
|
||||||
'login_password': CONF.image_copy_dest_password,
|
|
||||||
'path': dest_path
|
|
||||||
}
|
|
||||||
return copy_driver.copy_to(source_location,
|
|
||||||
dest_location,
|
|
||||||
candidate_path=candidate_path)
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
from nova.exception import NovaException
|
|
||||||
from nova.i18n import _
|
|
||||||
|
|
||||||
|
|
||||||
class GlanceSyncException(NovaException):
|
|
||||||
msg_fmt = _("Sync image failed: %(reason)s")
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import nova.image.sync.drivers.filesystem
|
|
||||||
|
|
||||||
|
|
||||||
_store_drivers_map = {
|
|
||||||
'file:file':filesystem.Store
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_store_driver(scheme_key):
|
|
||||||
cls = _store_drivers_map.get(scheme_key)
|
|
||||||
return cls()
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
import logging
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from oslo.config import cfg
|
|
||||||
import pxssh
|
|
||||||
import pexpect
|
|
||||||
|
|
||||||
from nova.i18n import _
|
|
||||||
from nova.image import exception
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
|
||||||
|
|
||||||
sync_opt = [
|
|
||||||
cfg.IntOpt('scp_copy_timeout', default=3600,
|
|
||||||
help=_('when snapshot, max wait (second)time for snapshot '
|
|
||||||
'status become active.'),
|
|
||||||
deprecated_opts=[cfg.DeprecatedOpt('scp_copy_timeout',
|
|
||||||
group='DEFAULT')]),
|
|
||||||
]
|
|
||||||
CONF.register_opts(sync_opt, group='sync')
|
|
||||||
|
|
||||||
|
|
||||||
def _get_ssh(hostname, username, password):
|
|
||||||
s = pxssh.pxssh()
|
|
||||||
s.login(hostname, username, password, original_prompt='[#$>]')
|
|
||||||
s.logfile = sys.stdout
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
class Store(object):
|
|
||||||
|
|
||||||
def copy_to(self, from_location, to_location, candidate_path=None):
|
|
||||||
|
|
||||||
from_store_loc = from_location
|
|
||||||
to_store_loc = to_location
|
|
||||||
LOG.debug(_('from_store_loc is: %s'), from_store_loc)
|
|
||||||
|
|
||||||
if from_store_loc['host'] == to_store_loc['host'] and \
|
|
||||||
from_store_loc['path'] == to_store_loc['path']:
|
|
||||||
|
|
||||||
LOG.info(_('The from_loc is same to to_loc, no need to copy. the '
|
|
||||||
'host:path is %s:%s') % (from_store_loc['host'],
|
|
||||||
from_store_loc['path']))
|
|
||||||
return 'file://%s' % to_store_loc['path']
|
|
||||||
|
|
||||||
to_host = r"""{username}@{host}""".format(
|
|
||||||
username=to_store_loc['login_user'],
|
|
||||||
host=to_store_loc['host'])
|
|
||||||
|
|
||||||
to_path = r"""{to_host}:{path}""".format(to_host=to_host,
|
|
||||||
path=to_store_loc['path'])
|
|
||||||
|
|
||||||
copy_path = from_store_loc['path']
|
|
||||||
|
|
||||||
try:
|
|
||||||
from_ssh = _get_ssh(from_store_loc['host'],
|
|
||||||
from_store_loc['login_user'],
|
|
||||||
from_store_loc['login_password'])
|
|
||||||
except Exception:
|
|
||||||
msg = _('ssh login failed to %(user)s:%(passwd)s %(host)s' %
|
|
||||||
{'user': from_store_loc['login_user'],
|
|
||||||
'passwd': from_store_loc['login_password'],
|
|
||||||
'host': from_store_loc['host']
|
|
||||||
})
|
|
||||||
LOG.exception(msg)
|
|
||||||
raise exception.GlanceSyncException(reason=msg)
|
|
||||||
|
|
||||||
from_ssh.sendline('ls %s' % copy_path)
|
|
||||||
from_ssh.prompt()
|
|
||||||
if 'cannot access' in from_ssh.before or \
|
|
||||||
'No such file' in from_ssh.before:
|
|
||||||
if candidate_path:
|
|
||||||
from_ssh.sendline('ls %s' % candidate_path)
|
|
||||||
from_ssh.prompt()
|
|
||||||
if 'cannot access' not in from_ssh.before and \
|
|
||||||
'No such file' not in from_ssh.before:
|
|
||||||
copy_path = candidate_path
|
|
||||||
else:
|
|
||||||
msg = _("the image path for copy to is not exists, file copy"
|
|
||||||
"failed: path is %s" % copy_path)
|
|
||||||
LOG.exception(msg)
|
|
||||||
raise exception.GlanceSyncException(reason=msg)
|
|
||||||
|
|
||||||
from_ssh.sendline('scp -P 22 %s %s' % (copy_path, to_path))
|
|
||||||
while True:
|
|
||||||
scp_index = from_ssh.expect(['.yes/no.', '.assword:.',
|
|
||||||
pexpect.TIMEOUT])
|
|
||||||
if scp_index == 0:
|
|
||||||
from_ssh.sendline('yes')
|
|
||||||
from_ssh.prompt()
|
|
||||||
elif scp_index == 1:
|
|
||||||
from_ssh.sendline(to_store_loc['login_password'])
|
|
||||||
from_ssh.prompt(timeout=CONF.sync.scp_copy_timeout)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
msg = _("scp commond execute failed, with copy_path %s and "
|
|
||||||
"to_path %s" % (copy_path, to_path))
|
|
||||||
LOG.exception(msg)
|
|
||||||
raise exception.GlanceSyncException(reason=msg)
|
|
||||||
|
|
||||||
if from_ssh:
|
|
||||||
from_ssh.logout()
|
|
||||||
|
|
||||||
return 'file://%s' % to_store_loc['path']
|
|
||||||
Reference in New Issue
Block a user