parent
39e1a3cc44
commit
f11c8c4c07
@ -39,8 +39,8 @@ flags.DEFINE_integer('api_port', 9292, 'API server listens on this port')
|
|||||||
|
|
||||||
|
|
||||||
def main(_args):
|
def main(_args):
|
||||||
# NOTE(sirp): importing in main so that eventlet is imported AFTER daemonization
|
# NOTE(sirp): importing in main so that eventlet is imported AFTER
|
||||||
# see https://bugs.launchpad.net/bugs/687661
|
# daemonization. See https://bugs.launchpad.net/bugs/687661
|
||||||
from glance.common import wsgi
|
from glance.common import wsgi
|
||||||
from glance.server import API
|
from glance.server import API
|
||||||
server = wsgi.Server()
|
server = wsgi.Server()
|
||||||
|
@ -38,9 +38,10 @@ flags.DEFINE_string('registry_host', '0.0.0.0',
|
|||||||
flags.DEFINE_integer('registry_port', 9191,
|
flags.DEFINE_integer('registry_port', 9191,
|
||||||
'Registry server listens on this port')
|
'Registry server listens on this port')
|
||||||
|
|
||||||
|
|
||||||
def main(_args):
|
def main(_args):
|
||||||
# NOTE(sirp): importing in main so that eventlet is imported AFTER daemonization
|
# NOTE(sirp): importing in main so that eventlet is imported AFTER
|
||||||
# see https://bugs.launchpad.net/bugs/687661
|
# daemonization. See https://bugs.launchpad.net/bugs/687661
|
||||||
from glance.common import wsgi
|
from glance.common import wsgi
|
||||||
from glance.registry.server import API
|
from glance.registry.server import API
|
||||||
server = wsgi.Server()
|
server = wsgi.Server()
|
||||||
|
@ -239,7 +239,7 @@ class Client(BaseClient):
|
|||||||
image_meta['size'] = len(body)
|
image_meta['size'] = len(body)
|
||||||
|
|
||||||
headers = util.image_meta_to_http_headers(image_meta)
|
headers = util.image_meta_to_http_headers(image_meta)
|
||||||
|
|
||||||
if image_data:
|
if image_data:
|
||||||
headers['content-type'] = 'application/octet-stream'
|
headers['content-type'] = 'application/octet-stream'
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class ApiError(Error):
|
|||||||
def __init__(self, message='Unknown', code='Unknown'):
|
def __init__(self, message='Unknown', code='Unknown'):
|
||||||
self.message = message
|
self.message = message
|
||||||
self.code = code
|
self.code = code
|
||||||
super(ApiError, self).__init__('%s: %s'% (code, message))
|
super(ApiError, self).__init__('%s: %s' % (code, message))
|
||||||
|
|
||||||
|
|
||||||
class NotFound(Error):
|
class NotFound(Error):
|
||||||
|
@ -39,6 +39,7 @@ from glance.common.exception import ProcessExecutionError
|
|||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
|
TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
|
||||||
|
|
||||||
|
|
||||||
def import_class(import_str):
|
def import_class(import_str):
|
||||||
"""Returns a class from a string including module and class"""
|
"""Returns a class from a string including module and class"""
|
||||||
mod_str, _sep, class_str = import_str.rpartition('.')
|
mod_str, _sep, class_str = import_str.rpartition('.')
|
||||||
@ -48,6 +49,7 @@ def import_class(import_str):
|
|||||||
except (ImportError, ValueError, AttributeError):
|
except (ImportError, ValueError, AttributeError):
|
||||||
raise exception.NotFound('Class %s cannot be found' % class_str)
|
raise exception.NotFound('Class %s cannot be found' % class_str)
|
||||||
|
|
||||||
|
|
||||||
def import_object(import_str):
|
def import_object(import_str):
|
||||||
"""Returns an object including a module or module and class"""
|
"""Returns an object including a module or module and class"""
|
||||||
try:
|
try:
|
||||||
@ -57,6 +59,7 @@ def import_object(import_str):
|
|||||||
cls = import_class(import_str)
|
cls = import_class(import_str)
|
||||||
return cls()
|
return cls()
|
||||||
|
|
||||||
|
|
||||||
def fetchfile(url, target):
|
def fetchfile(url, target):
|
||||||
logging.debug("Fetching %s" % url)
|
logging.debug("Fetching %s" % url)
|
||||||
# c = pycurl.Curl()
|
# c = pycurl.Curl()
|
||||||
@ -68,6 +71,7 @@ def fetchfile(url, target):
|
|||||||
# fp.close()
|
# fp.close()
|
||||||
execute("curl --fail %s -o %s" % (url, target))
|
execute("curl --fail %s -o %s" % (url, target))
|
||||||
|
|
||||||
|
|
||||||
def execute(cmd, process_input=None, addl_env=None, check_exit_code=True):
|
def execute(cmd, process_input=None, addl_env=None, check_exit_code=True):
|
||||||
logging.debug("Running cmd: %s", cmd)
|
logging.debug("Running cmd: %s", cmd)
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
@ -83,7 +87,7 @@ def execute(cmd, process_input=None, addl_env=None, check_exit_code=True):
|
|||||||
obj.stdin.close()
|
obj.stdin.close()
|
||||||
if obj.returncode:
|
if obj.returncode:
|
||||||
logging.debug("Result was %s" % (obj.returncode))
|
logging.debug("Result was %s" % (obj.returncode))
|
||||||
if check_exit_code and obj.returncode <> 0:
|
if check_exit_code and obj.returncode != 0:
|
||||||
(stdout, stderr) = result
|
(stdout, stderr) = result
|
||||||
raise ProcessExecutionError(exit_code=obj.returncode,
|
raise ProcessExecutionError(exit_code=obj.returncode,
|
||||||
stdout=stdout,
|
stdout=stdout,
|
||||||
@ -109,7 +113,8 @@ def default_flagfile(filename='glance.conf'):
|
|||||||
script_dir = os.path.dirname(inspect.stack()[-1][1])
|
script_dir = os.path.dirname(inspect.stack()[-1][1])
|
||||||
filename = os.path.abspath(os.path.join(script_dir, filename))
|
filename = os.path.abspath(os.path.join(script_dir, filename))
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
sys.argv = sys.argv[:1] + ['--flagfile=%s' % filename] + sys.argv[1:]
|
sys.argv = \
|
||||||
|
sys.argv[:1] + ['--flagfile=%s' % filename] + sys.argv[1:]
|
||||||
|
|
||||||
|
|
||||||
def debug(arg):
|
def debug(arg):
|
||||||
@ -117,11 +122,11 @@ def debug(arg):
|
|||||||
return arg
|
return arg
|
||||||
|
|
||||||
|
|
||||||
def runthis(prompt, cmd, check_exit_code = True):
|
def runthis(prompt, cmd, check_exit_code=True):
|
||||||
logging.debug("Running %s" % (cmd))
|
logging.debug("Running %s" % (cmd))
|
||||||
exit_code = subprocess.call(cmd.split(" "))
|
exit_code = subprocess.call(cmd.split(" "))
|
||||||
logging.debug(prompt % (exit_code))
|
logging.debug(prompt % (exit_code))
|
||||||
if check_exit_code and exit_code <> 0:
|
if check_exit_code and exit_code != 0:
|
||||||
raise ProcessExecutionError(exit_code=exit_code,
|
raise ProcessExecutionError(exit_code=exit_code,
|
||||||
stdout=None,
|
stdout=None,
|
||||||
stderr=None,
|
stderr=None,
|
||||||
@ -129,7 +134,9 @@ def runthis(prompt, cmd, check_exit_code = True):
|
|||||||
|
|
||||||
|
|
||||||
def generate_uid(topic, size=8):
|
def generate_uid(topic, size=8):
|
||||||
return '%s-%s' % (topic, ''.join([random.choice('01234567890abcdefghijklmnopqrstuvwxyz') for x in xrange(size)]))
|
return '%s-%s' % (topic, ''.join(
|
||||||
|
[random.choice('01234567890abcdefghijklmnopqrstuvwxyz')
|
||||||
|
for x in xrange(size)]))
|
||||||
|
|
||||||
|
|
||||||
def generate_mac():
|
def generate_mac():
|
||||||
@ -198,6 +205,7 @@ class LazyPluggable(object):
|
|||||||
backend = self.__get_backend()
|
backend = self.__get_backend()
|
||||||
return getattr(backend, key)
|
return getattr(backend, key)
|
||||||
|
|
||||||
|
|
||||||
def deferredToThread(f):
|
def deferredToThread(f):
|
||||||
def g(*args, **kwargs):
|
def g(*args, **kwargs):
|
||||||
return deferToThread(f, *args, **kwargs)
|
return deferToThread(f, *args, **kwargs)
|
||||||
|
@ -142,7 +142,9 @@ def _image_update(_context, values, image_id):
|
|||||||
image_ref.save(session=session)
|
image_ref.save(session=session)
|
||||||
|
|
||||||
for key, value in properties.iteritems():
|
for key, value in properties.iteritems():
|
||||||
prop_values = {'image_id': image_ref.id, 'key': key, 'value': value}
|
prop_values = {'image_id': image_ref.id,
|
||||||
|
'key': key,
|
||||||
|
'value': value}
|
||||||
image_property_create(_context, prop_values)
|
image_property_create(_context, prop_values)
|
||||||
|
|
||||||
return image_get(_context, image_ref.id)
|
return image_get(_context, image_ref.id)
|
||||||
|
@ -137,11 +137,12 @@ class ModelBase(object):
|
|||||||
def items(self):
|
def items(self):
|
||||||
return self.__dict__.items()
|
return self.__dict__.items()
|
||||||
|
|
||||||
|
|
||||||
class Image(BASE, ModelBase):
|
class Image(BASE, ModelBase):
|
||||||
"""Represents an image in the datastore"""
|
"""Represents an image in the datastore"""
|
||||||
__tablename__ = 'images'
|
__tablename__ = 'images'
|
||||||
__prefix__ = 'img'
|
__prefix__ = 'img'
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
name = Column(String(255))
|
name = Column(String(255))
|
||||||
type = Column(String(30))
|
type = Column(String(30))
|
||||||
@ -156,13 +157,13 @@ class Image(BASE, ModelBase):
|
|||||||
raise exception.Invalid(
|
raise exception.Invalid(
|
||||||
"Invalid image type '%s' for image." % type)
|
"Invalid image type '%s' for image." % type)
|
||||||
return type
|
return type
|
||||||
|
|
||||||
@validates('status')
|
@validates('status')
|
||||||
def validate_status(self, key, status):
|
def validate_status(self, key, status):
|
||||||
if not status in ('available', 'pending', 'disabled'):
|
if not status in ('available', 'pending', 'disabled'):
|
||||||
raise exception.Invalid("Invalid status '%s' for image." % status)
|
raise exception.Invalid("Invalid status '%s' for image." % status)
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
|
||||||
class ImageProperty(BASE, ModelBase):
|
class ImageProperty(BASE, ModelBase):
|
||||||
"""Represents an image properties in the datastore"""
|
"""Represents an image properties in the datastore"""
|
||||||
@ -173,7 +174,7 @@ class ImageProperty(BASE, ModelBase):
|
|||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
image_id = Column(Integer, ForeignKey('images.id'), nullable=False)
|
image_id = Column(Integer, ForeignKey('images.id'), nullable=False)
|
||||||
image = relationship(Image, backref=backref('properties'))
|
image = relationship(Image, backref=backref('properties'))
|
||||||
|
|
||||||
key = Column(String(255), index=True)
|
key = Column(String(255), index=True)
|
||||||
value = Column(Text)
|
value = Column(Text)
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ class FilesystemBackend(Backend):
|
|||||||
except OSError:
|
except OSError:
|
||||||
raise exception.NotAuthorized("You cannot delete file %s" % fn)
|
raise exception.NotAuthorized("You cannot delete file %s" % fn)
|
||||||
else:
|
else:
|
||||||
raise exception.NotFound("File %s does not exist" % fn)
|
raise exception.NotFound("File %s does not exist" % fn)
|
||||||
|
|
||||||
|
|
||||||
def get_backend_class(backend):
|
def get_backend_class(backend):
|
||||||
|
@ -114,12 +114,12 @@ class FilesystemBackend(glance.store.Backend):
|
|||||||
|
|
||||||
:retval The location that was written, with file:// scheme prepended
|
:retval The location that was written, with file:// scheme prepended
|
||||||
"""
|
"""
|
||||||
|
|
||||||
datadir = FLAGS.filesystem_store_datadir
|
datadir = FLAGS.filesystem_store_datadir
|
||||||
|
|
||||||
if not os.path.exists(datadir):
|
if not os.path.exists(datadir):
|
||||||
os.makedirs(datadir)
|
os.makedirs(datadir)
|
||||||
|
|
||||||
filepath = os.path.join(datadir, str(id))
|
filepath = os.path.join(datadir, str(id))
|
||||||
|
|
||||||
if os.path.exists(filepath):
|
if os.path.exists(filepath):
|
||||||
|
@ -19,6 +19,7 @@ import httplib
|
|||||||
|
|
||||||
import glance.store
|
import glance.store
|
||||||
|
|
||||||
|
|
||||||
class HTTPBackend(glance.store.Backend):
|
class HTTPBackend(glance.store.Backend):
|
||||||
""" An implementation of the HTTP Backend Adapter """
|
""" An implementation of the HTTP Backend Adapter """
|
||||||
|
|
||||||
@ -35,11 +36,12 @@ class HTTPBackend(glance.store.Backend):
|
|||||||
elif parsed_uri.scheme == "https":
|
elif parsed_uri.scheme == "https":
|
||||||
conn_class = httplib.HTTPSConnection
|
conn_class = httplib.HTTPSConnection
|
||||||
else:
|
else:
|
||||||
raise glance.store.BackendException("scheme '%s' not supported for HTTPBackend")
|
raise glance.store.BackendException(
|
||||||
|
"scheme '%s' not supported for HTTPBackend")
|
||||||
|
|
||||||
conn = conn_class(parsed_uri.netloc)
|
conn = conn_class(parsed_uri.netloc)
|
||||||
conn.request("GET", parsed_uri.path, "", {})
|
conn.request("GET", parsed_uri.path, "", {})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return glance.store._file_iter(conn.getresponse(), cls.CHUNKSIZE)
|
return glance.store._file_iter(conn.getresponse(), cls.CHUNKSIZE)
|
||||||
finally:
|
finally:
|
||||||
|
@ -29,14 +29,14 @@ class SwiftBackend(glance.store.Backend):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, parsed_uri, expected_size, conn_class=None):
|
def get(cls, parsed_uri, expected_size, conn_class=None):
|
||||||
"""
|
"""
|
||||||
Takes a parsed_uri in the format of:
|
Takes a parsed_uri in the format of:
|
||||||
swift://user:password@auth_url/container/file.gz.0, connects to the
|
swift://user:password@auth_url/container/file.gz.0, connects to the
|
||||||
swift instance at auth_url and downloads the file. Returns the generator
|
swift instance at auth_url and downloads the file. Returns the
|
||||||
resp_body provided by get_object.
|
generator resp_body provided by get_object.
|
||||||
"""
|
"""
|
||||||
(user, key, authurl, container, obj) = \
|
(user, key, authurl, container, obj) = \
|
||||||
cls._parse_swift_tokens(parsed_uri)
|
cls._parse_swift_tokens(parsed_uri)
|
||||||
|
|
||||||
# TODO(sirp): snet=False for now, however, if the instance of
|
# TODO(sirp): snet=False for now, however, if the instance of
|
||||||
# swift we're talking to is within our same region, we should set
|
# swift we're talking to is within our same region, we should set
|
||||||
# snet=True
|
# snet=True
|
||||||
@ -50,9 +50,10 @@ class SwiftBackend(glance.store.Backend):
|
|||||||
|
|
||||||
obj_size = int(resp_headers['content-length'])
|
obj_size = int(resp_headers['content-length'])
|
||||||
if obj_size != expected_size:
|
if obj_size != expected_size:
|
||||||
raise glance.store.BackendException("Expected %s byte file, Swift has %s bytes"
|
raise glance.store.BackendException(
|
||||||
% (expected_size, obj_size))
|
"Expected %s byte file, Swift has %s bytes" %
|
||||||
|
(expected_size, obj_size))
|
||||||
|
|
||||||
return resp_body
|
return resp_body
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -62,7 +63,7 @@ class SwiftBackend(glance.store.Backend):
|
|||||||
"""
|
"""
|
||||||
(user, key, authurl, container, obj) = \
|
(user, key, authurl, container, obj) = \
|
||||||
cls._parse_swift_tokens(parsed_uri)
|
cls._parse_swift_tokens(parsed_uri)
|
||||||
|
|
||||||
# TODO(sirp): snet=False for now, however, if the instance of
|
# TODO(sirp): snet=False for now, however, if the instance of
|
||||||
# swift we're talking to is within our same region, we should set
|
# swift we're talking to is within our same region, we should set
|
||||||
# snet=True
|
# snet=True
|
||||||
@ -76,7 +77,7 @@ class SwiftBackend(glance.store.Backend):
|
|||||||
|
|
||||||
# TODO(jaypipes): What to return here? After reading the docs
|
# TODO(jaypipes): What to return here? After reading the docs
|
||||||
# at swift.common.client, I'm not sure what to check for...
|
# at swift.common.client, I'm not sure what to check for...
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _parse_swift_tokens(cls, parsed_uri):
|
def _parse_swift_tokens(cls, parsed_uri):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user