From 0e8c965b880cc678f7202f07e9059bb38a78f0b9 Mon Sep 17 00:00:00 2001 From: Serg Melikyan Date: Mon, 4 Mar 2013 14:12:47 +0400 Subject: [PATCH] Updated initial version of portas-api --- api/openstack-common.conf | 0 api/setup.py | 90 -- portas/.gitignore | 2 +- portas/bin/portas-api | 15 +- portas/doc/source/conf.py | 49 +- portas/doc/source/index.rst | 67 +- portas/etc/portas-api-paste.ini | 56 +- portas/etc/portas-api.conf | 21 +- portas/openstack-common.conf | 2 +- portas/portas/api/v1/environments.py | 30 + portas/portas/api/v1/router.py | 36 +- portas/portas/common/config.py | 63 +- portas/portas/common/exception.py | 228 +-- portas/portas/db/__init__.py | 13 +- portas/portas/db/api.py | 19 +- portas/portas/db/migrate_repo/migrate.cfg | 2 +- .../versions/001_add_initial_tables.py | 37 +- .../db/migrate_repo/versions/__init__.py | 1 - portas/portas/db/models.py | 126 +- portas/portas/db/session.py | 40 +- portas/portas/locale/ru/LC_MESSAGES/portas.po | 1221 ++--------------- portas/portas/schema.py | 26 - portas/portas/tests/api/simple_test.py | 2 +- portas/portas/version.py | 4 +- portas/run_tests.sh | 4 +- portas/setup.cfg | 24 + portas/setup.py | 8 +- portas/tools/pip-requires | 29 +- portas/tools/test-requires | 19 + 29 files changed, 370 insertions(+), 1864 deletions(-) delete mode 100644 api/openstack-common.conf delete mode 100644 api/setup.py diff --git a/api/openstack-common.conf b/api/openstack-common.conf deleted file mode 100644 index e69de29..0000000 diff --git a/api/setup.py b/api/setup.py deleted file mode 100644 index 3265bca..0000000 --- a/api/setup.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import os -import subprocess - -from setuptools import setup, find_packages -from setuptools.command.sdist import sdist - -from windc import version - - -if os.path.isdir('.bzr'): - with open("windc/vcsversion.py", 'w') as version_file: - vcs_cmd = subprocess.Popen(["bzr", "version-info", "--python"], - stdout=subprocess.PIPE) - vcsversion = vcs_cmd.communicate()[0] - version_file.write(vcsversion) - - -class local_sdist(sdist): - """Customized sdist hook - builds the ChangeLog file from VC first""" - - def run(self): - if os.path.isdir('.bzr'): - # We're in a bzr branch - - log_cmd = subprocess.Popen(["bzr", "log", "--gnu"], - stdout=subprocess.PIPE) - changelog = log_cmd.communicate()[0] - with open("ChangeLog", "w") as changelog_file: - changelog_file.write(changelog) - sdist.run(self) - -cmdclass = {'sdist': local_sdist} - -# If Sphinx is installed on the box running setup.py, -# enable setup.py to build the documentation, otherwise, -# just ignore it -try: - from sphinx.setup_command import BuildDoc - - class local_BuildDoc(BuildDoc): - def run(self): - for builder in ['html', 'man']: - self.builder = builder - self.finalize_options() - BuildDoc.run(self) - cmdclass['build_sphinx'] = local_BuildDoc - -except: - pass - - -setup( - name='windc', - version=version.canonical_version_string(), - description='The WinDC project provides a simple WSGI server for Windows Environment Management', - license='Apache License (2.0)', - author='OpenStack', - author_email='openstack@lists.launchpad.net', - url='http://windc.openstack.org/', - packages=find_packages(exclude=['tests', 'bin']), - test_suite='nose.collector', - cmdclass=cmdclass, - include_package_data=True, - classifiers=[ - 'Development Status :: 4 - Beta', - 'License :: OSI Approved :: Apache Software License', - 'Operating System :: POSIX :: Linux', - 'Programming Language :: Python :: 2.6', - 'Environment :: No Input/Output (Daemon)', - ], - scripts=['bin/windc', - 'bin/windc-api']) diff --git a/portas/.gitignore b/portas/.gitignore index 7b4690b..6133130 100644 --- a/portas/.gitignore +++ b/portas/.gitignore @@ -1,4 +1,4 @@ -##IntelJ Idea +#IntelJ Idea .idea/ #virtualenv diff --git a/portas/bin/portas-api b/portas/bin/portas-api index bb7817d..103269b 100755 --- a/portas/bin/portas-api +++ b/portas/bin/portas-api @@ -19,29 +19,32 @@ import gettext import os import sys - # If ../portas/__init__.py exists, add ../ to Python search path, so that # it will override what happens to be installed in /usr/(local/)lib/python... + possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir)) if os.path.exists(os.path.join(possible_topdir, 'portas', '__init__.py')): sys.path.insert(0, possible_topdir) -gettext.install('portas', './portas/locale', unicode=1) - from portas.common import config from portas.openstack.common import log from portas.openstack.common import wsgi +from portas.openstack.common import service +gettext.install('portas', './portas/locale', unicode=1) if __name__ == '__main__': try: config.parse_args() + log.setup('portas') - server = wsgi.Server() - server.start(config.load_paste_app(), default_port=8181) - server.wait() + api_service = wsgi.Service(config.load_paste_app(), + port=config.CONF.bind_port, + host=config.CONF.bind_host) + launcher = service.Launcher() + launcher.run_service(api_service) except RuntimeError, e: sys.stderr.write("ERROR: %s\n" % e) sys.exit(1) diff --git a/portas/doc/source/conf.py b/portas/doc/source/conf.py index 8b546d6..f3f4cf5 100644 --- a/portas/doc/source/conf.py +++ b/portas/doc/source/conf.py @@ -1,3 +1,4 @@ + # -*- coding: utf-8 -*- # Copyright (c) 2010 OpenStack Foundation. # @@ -15,8 +16,8 @@ # limitations under the License. # -# Glance documentation build configuration file, created by -# sphinx-quickstart on Tue May 18 13:50:15 2010. +# Portas documentation build configuration file, created by +# sphinx-quickstart on Tue February 28 13:50:15 2013. # # This file is execfile()'d with the current directory set to its containing # dir. @@ -33,7 +34,7 @@ import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path = [os.path.abspath('../../glance'), +sys.path = [os.path.abspath('../../portas'), os.path.abspath('../..'), os.path.abspath('../../bin') ] + sys.path @@ -65,19 +66,19 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'Glance' -copyright = u'2010, OpenStack Foundation.' +project = u'Portas' +copyright = u'2013, Mirantis, Inc.' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -from glance.version import version_info as glance_version +from portas.version import version_info as portas_version # The full version, including alpha/beta/rc tags. -release = glance_version.version_string_with_vcs() +release = portas_version.version_string_with_vcs() # The short X.Y version. -version = glance_version.canonical_version_string() +version = portas_version.canonical_version_string() # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -114,7 +115,7 @@ show_authors = True pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. -modindex_common_prefix = ['glance.'] +modindex_common_prefix = ['portas.'] # -- Options for man page output -------------------------------------------- @@ -122,25 +123,7 @@ modindex_common_prefix = ['glance.'] # List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual' man_pages = [ - ('man/glance', 'glance', u'Glance CLI', - [u'OpenStack'], 1), - ('man/glanceapi', 'glance-api', u'Glance API Server', - [u'OpenStack'], 1), - ('man/glancecachecleaner', 'glance-cache-cleaner', u'Glance Cache Cleaner', - [u'OpenStack'], 1), - ('man/glancecachemanage', 'glance-cache-manage', u'Glance Cache Manager', - [u'OpenStack'], 1), - ('man/glancecacheprefetcher', 'glance-cache-prefetcher', - u'Glance Cache Pre-fetcher', [u'OpenStack'], 1), - ('man/glancecachepruner', 'glance-cache-pruner', u'Glance Cache Pruner', - [u'OpenStack'], 1), - ('man/glancecontrol', 'glance-control', u'Glance Daemon Control Helper ', - [u'OpenStack'], 1), - ('man/glancemanage', 'glance-manage', u'Glance Management Utility', - [u'OpenStack'], 1), - ('man/glanceregistry', 'glance-registry', u'Glance Registry Server', - [u'OpenStack'], 1), - ('man/glancescrubber', 'glance-scrubber', u'Glance Scrubber Service', + ('man/portasapi', 'portas-api', u'Portas API Server', [u'OpenStack'], 1) ] @@ -219,7 +202,7 @@ html_use_index = False #html_file_suffix = '' # Output file base name for HTML help builder. -htmlhelp_basename = 'glancedoc' +htmlhelp_basename = 'portasdoc' # -- Options for LaTeX output ------------------------------------------------ @@ -234,8 +217,8 @@ htmlhelp_basename = 'glancedoc' # (source start file, target name, title, author, # documentclass [howto/manual]). latex_documents = [ - ('index', 'Glance.tex', u'Glance Documentation', - u'Glance Team', 'manual'), + ('index', 'Portas.tex', u'Portas Documentation', + u'Keero Team', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -256,6 +239,4 @@ latex_documents = [ #latex_use_modindex = True # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'python': ('http://docs.python.org/', None), - 'nova': ('http://nova.openstack.org', None), - 'swift': ('http://swift.openstack.org', None)} +intersphinx_mapping = {'python': ('http://docs.python.org/', None)} diff --git a/portas/doc/source/index.rst b/portas/doc/source/index.rst index 842c91e..cff04f3 100644 --- a/portas/doc/source/index.rst +++ b/portas/doc/source/index.rst @@ -14,70 +14,7 @@ License for the specific language governing permissions and limitations under the License. -Welcome to Glance's documentation! +Welcome to Portas's documentation! ================================== -The Glance project provides services for discovering, registering, and -retrieving virtual machine images. Glance has a RESTful API that allows -querying of VM image metadata as well as retrieval of the actual image. - -VM images made available through Glance can be stored in a variety of -locations from simple filesystems to object-storage systems like the -OpenStack Swift project. - -Glance, as with all OpenStack projects, is written with the following design -guidelines in mind: - -* **Component based architecture**: Quickly add new behaviors -* **Highly available**: Scale to very serious workloads -* **Fault tolerant**: Isolated processes avoid cascading failures -* **Recoverable**: Failures should be easy to diagnose, debug, and rectify -* **Open standards**: Be a reference implementation for a community-driven api - -This documentation is generated by the Sphinx toolkit and lives in the source -tree. Additional documentation on Glance and other components of OpenStack can -be found on the `OpenStack wiki`_. - -.. _`OpenStack wiki`: http://wiki.openstack.org - -Concepts -======== - -.. toctree:: - :maxdepth: 1 - - identifiers - statuses - formats - common-image-properties - -Installing/Configuring Glance -============================= - -.. toctree:: - :maxdepth: 1 - - installing - configuring - authentication - policies - -Operating Glance -================ - -.. toctree:: - :maxdepth: 1 - - controllingservers - db - cache - notifications - -Using Glance -============ - -.. toctree:: - :maxdepth: 1 - - glanceapi - glanceclient +We rule the world! \ No newline at end of file diff --git a/portas/etc/portas-api-paste.ini b/portas/etc/portas-api-paste.ini index 8dbdc8c..9b1d990 100644 --- a/portas/etc/portas-api-paste.ini +++ b/portas/etc/portas-api-paste.ini @@ -1,57 +1,5 @@ -[DEFAULT] -# Show more verbose log output (sets INFO log level output) -verbose = True -# Show debugging output in logs (sets DEBUG log level output) -debug = True -# Address to bind the server to -bind_host = 0.0.0.0 -# Port the bind the server to -bind_port = 8082 -# Log to this file. Make sure the user running skeleton-api has -# permissions to write to this file! -log_file = /tmp/api.log -# Orchestration Adapter Section -# -#provider - Cloud provider to use (openstack, amazon, dummy) -provider = openstack - -# Heat specific parameters -#heat_url - url for the heat service -# [auto] - find in the keystone -heat_url = auto - -#heat_api_version - version of the API to use -# -heat_api_version = 1 - - -[pipeline:windc-api] +[pipeline:portas-api] pipeline = apiv1app -# NOTE: use the following pipeline for keystone -#pipeline = authtoken context apiv1app [app:apiv1app] -paste.app_factory = windc.common.wsgi:app_factory -windc.app_factory = windc.api.v1.router:API - -[filter:context] -paste.filter_factory = windc.common.wsgi:filter_factory -windc.filter_factory = windc.common.context:ContextMiddleware - -[filter:authtoken] -paste.filter_factory = keystone.middleware.auth_token:filter_factory -auth_host = 172.18.67.57 -auth_port = 35357 -auth_protocol = http -auth_uri = http://172.18.67.57:5000/v2.0/ -admin_tenant_name = service -admin_user = windc -admin_password = 000 - -[filter:auth-context] -paste.filter_factory = windc.common.wsgi:filter_factory -windc.filter_factory = keystone.middleware.balancer_auth_token:KeystoneContextMiddleware - -[rabbitmq] -host = 10.0.0.1 -vhost = keero \ No newline at end of file +paste.app_factory = portas.api.v1.router:API.factory \ No newline at end of file diff --git a/portas/etc/portas-api.conf b/portas/etc/portas-api.conf index 3f1381b..fc991f2 100644 --- a/portas/etc/portas-api.conf +++ b/portas/etc/portas-api.conf @@ -13,22 +13,7 @@ bind_port = 8082 # Log to this file. Make sure the user running skeleton-api has # permissions to write to this file! -log_file = /tmp/api.log +log_file = /tmp/portas-api.log -[pipeline:windc-api] -pipeline = versionnegotiation context apiv1app - -[pipeline:versions] -pipeline = versionsapp - -[app:versionsapp] -paste.app_factory = windc.api.versions:app_factory - -[app:apiv1app] -paste.app_factory = windc.api.v1:app_factory - -[filter:versionnegotiation] -paste.filter_factory = windc.api.middleware.version_negotiation:filter_factory - -[filter:context] -paste.filter_factory = openstack.common.middleware.context:filter_factory +#A valid SQLAlchemy connection string for the metadata database +sql_connection = sqlite:///portas.sqlite \ No newline at end of file diff --git a/portas/openstack-common.conf b/portas/openstack-common.conf index c3faaa6..6f1c598 100644 --- a/portas/openstack-common.conf +++ b/portas/openstack-common.conf @@ -1,7 +1,7 @@ [DEFAULT] # The list of modules to copy from openstack-common -modules=setup,wsgi,config,exception,gettextutilsl,jsonutils,log,xmlutils,sslutils,service,notifier,local,install_venv_common +modules=setup,wsgi,config,exception,gettextutils,importutils,jsonutils,log,xmlutils,sslutils,service,notifier,local,install_venv_common,version,timeutils,eventlet_backdoor,threadgroup,loopingcall,uuidutils # The base module to hold the copy of openstack.common base=portas \ No newline at end of file diff --git a/portas/portas/api/v1/environments.py b/portas/portas/api/v1/environments.py index e69de29..cf4500b 100644 --- a/portas/portas/api/v1/environments.py +++ b/portas/portas/api/v1/environments.py @@ -0,0 +1,30 @@ +from portas.db.api import EnvironmentRepository +from portas.openstack.common import wsgi +from portas.openstack.common import log as logging + + +log = logging.getLogger(__name__) + + +class Controller(object): + repository = EnvironmentRepository() + + def index(self, request): + log.debug(_("Display list of environments")) + return {"environments": [env.to_dict() for env in self.repository.list()]} + + def create(self, request, body): + return self.repository.add(body).to_dict() + + # def delete(self, request, datacenter_id): + # log.debug("Got delete request. Request: %s", req) + # self.repository., datacenter_id) + # + # def update(self, req, tenant_id, datacenter_id, body): + # log.debug("Got update request. Request: %s", req) + # core_api.update_dc(self.conf, tenant_id, datacenter_id, body) + # return {'datacenter': {'id': dc_id}} + + +def create_resource(): + return wsgi.Resource(Controller()) \ No newline at end of file diff --git a/portas/portas/api/v1/router.py b/portas/portas/api/v1/router.py index 5631774..018ad72 100644 --- a/portas/portas/api/v1/router.py +++ b/portas/portas/api/v1/router.py @@ -14,37 +14,17 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - - -from glance.api.v1 import images -from glance.api.v1 import members -from glance.common import wsgi +import routes +from portas.openstack.common import wsgi +from portas.api.v1 import environments class API(wsgi.Router): - - """WSGI router for Glance v1 API requests.""" + @classmethod + def factory(cls, global_conf, **local_conf): + return cls(routes.Mapper()) def __init__(self, mapper): - images_resource = images.create_resource() - - mapper.resource("image", "images", controller=images_resource, - collection={'detail': 'GET'}) - mapper.connect("/", controller=images_resource, action="index") - mapper.connect("/images/{id}", controller=images_resource, - action="meta", conditions=dict(method=["HEAD"])) - - members_resource = members.create_resource() - - mapper.resource("member", "members", controller=members_resource, - parent_resource=dict(member_name='image', - collection_name='images')) - mapper.connect("/shared-images/{id}", - controller=members_resource, - action="index_shared_images") - mapper.connect("/images/{image_id}/members", - controller=members_resource, - action="update_all", - conditions=dict(method=["PUT"])) - + environments_resource = environments.create_resource() + mapper.resource("environment", "environments", controller=environments_resource) super(API, self).__init__(mapper) diff --git a/portas/portas/common/config.py b/portas/portas/common/config.py index fb8e235..cae0d3c 100644 --- a/portas/portas/common/config.py +++ b/portas/portas/common/config.py @@ -29,71 +29,40 @@ import sys from oslo.config import cfg from paste import deploy -from glance.version import version_info as version +from portas.version import version_info as version paste_deploy_opts = [ cfg.StrOpt('flavor'), cfg.StrOpt('config_file'), ] -common_opts = [ - cfg.BoolOpt('allow_additional_image_properties', default=True, - help=_('Whether to allow users to specify image properties ' - 'beyond what the image schema provides')), - cfg.StrOpt('data_api', default='glance.db.sqlalchemy.api', - help=_('Python module path of data access API')), - cfg.IntOpt('limit_param_default', default=25, - help=_('Default value for the number of items returned by a ' - 'request if not specified explicitly in the request')), - cfg.IntOpt('api_limit_max', default=1000, - help=_('Maximum permissible number of items that could be ' - 'returned by a request')), - cfg.BoolOpt('show_image_direct_url', default=False, - help=_('Whether to include the backend image storage location ' - 'in image properties. Revealing storage location can be a ' - 'security risk, so use this setting with caution!')), - cfg.IntOpt('image_size_cap', default=1099511627776, - help=_("Maximum size of image a user can upload in bytes. " - "Defaults to 1099511627776 bytes (1 TB).")), - cfg.BoolOpt('enable_v1_api', default=True, - help=_("Deploy the v1 OpenStack Images API. ")), - cfg.BoolOpt('enable_v2_api', default=True, - help=_("Deploy the v2 OpenStack Images API. ")), - cfg.StrOpt('pydev_worker_debug_host', default=None, - help=_('The hostname/IP of the pydev process listening for ' - 'debug connections')), - cfg.IntOpt('pydev_worker_debug_port', default=5678, - help=_('The port on which a pydev process is listening for ' - 'connections.')), + +bind_opts = [ + cfg.StrOpt('bind_host', default='localhost'), + cfg.IntOpt('bind_port'), ] CONF = cfg.CONF CONF.register_opts(paste_deploy_opts, group='paste_deploy') -CONF.register_opts(common_opts) +CONF.register_opts(bind_opts) -CONF.import_opt('verbose', 'glance.openstack.common.log') -CONF.import_opt('debug', 'glance.openstack.common.log') -CONF.import_opt('log_dir', 'glance.openstack.common.log') -CONF.import_opt('log_file', 'glance.openstack.common.log') -CONF.import_opt('log_config', 'glance.openstack.common.log') -CONF.import_opt('log_format', 'glance.openstack.common.log') -CONF.import_opt('log_date_format', 'glance.openstack.common.log') -CONF.import_opt('use_syslog', 'glance.openstack.common.log') -CONF.import_opt('syslog_log_facility', 'glance.openstack.common.log') +CONF.import_opt('verbose', 'portas.openstack.common.log') +CONF.import_opt('debug', 'portas.openstack.common.log') +CONF.import_opt('log_dir', 'portas.openstack.common.log') +CONF.import_opt('log_file', 'portas.openstack.common.log') +CONF.import_opt('log_config', 'portas.openstack.common.log') +CONF.import_opt('log_format', 'portas.openstack.common.log') +CONF.import_opt('log_date_format', 'portas.openstack.common.log') +CONF.import_opt('use_syslog', 'portas.openstack.common.log') +CONF.import_opt('syslog_log_facility', 'portas.openstack.common.log') def parse_args(args=None, usage=None, default_config_files=None): CONF(args=args, - project='glance', + project='portas', version=version.cached_version_string(), usage=usage, default_config_files=default_config_files) - -def parse_cache_args(args=None): - config_files = cfg.find_config_files(project='glance', prog='glance-cache') - parse_args(args=args, default_config_files=config_files) - - def setup_logging(): """ Sets up the logging options for a log with supplied name diff --git a/portas/portas/common/exception.py b/portas/portas/common/exception.py index fb1435d..59bb0ee 100644 --- a/portas/portas/common/exception.py +++ b/portas/portas/common/exception.py @@ -16,21 +16,14 @@ # License for the specific language governing permissions and limitations # under the License. -"""Glance exception subclasses""" - -import urlparse +"""Portas exception subclasses""" _FATAL_EXCEPTION_FORMAT_ERRORS = False -class RedirectException(Exception): - def __init__(self, url): - self.url = urlparse.urlparse(url) - - -class GlanceException(Exception): +class PortasException(Exception): """ - Base Glance Exception + Base Portas Exception To correctly use this class, inherit from it and define a 'message' property. That message will get printf'd @@ -50,223 +43,14 @@ class GlanceException(Exception): # at least get the core message out if something happened pass - super(GlanceException, self).__init__(message) + super(PortasException, self).__init__(message) - -class MissingArgumentError(GlanceException): - message = _("Missing required argument.") - - -class MissingCredentialError(GlanceException): - message = _("Missing required credential: %(required)s") - - -class BadAuthStrategy(GlanceException): - message = _("Incorrect auth strategy, expected \"%(expected)s\" but " - "received \"%(received)s\"") - - -class NotFound(GlanceException): - message = _("An object with the specified identifier was not found.") - - -class UnknownScheme(GlanceException): - message = _("Unknown scheme '%(scheme)s' found in URI") - - -class BadStoreUri(GlanceException): - message = _("The Store URI was malformed.") - - -class Duplicate(GlanceException): - message = _("An object with the same identifier already exists.") - - -class StorageFull(GlanceException): - message = _("There is not enough disk space on the image storage media.") - - -class StorageWriteDenied(GlanceException): - message = _("Permission to write image storage media denied.") - - -class AuthBadRequest(GlanceException): - message = _("Connect error/bad request to Auth service at URL %(url)s.") - - -class AuthUrlNotFound(GlanceException): - message = _("Auth service at URL %(url)s not found.") - - -class AuthorizationFailure(GlanceException): - message = _("Authorization failed.") - - -class NotAuthenticated(GlanceException): - message = _("You are not authenticated.") - - -class Forbidden(GlanceException): - message = _("You are not authorized to complete this action.") - - -class ForbiddenPublicImage(Forbidden): - message = _("You are not authorized to complete this action.") - - -class ProtectedImageDelete(Forbidden): - message = _("Image %(image_id)s is protected and cannot be deleted.") - - -#NOTE(bcwaldon): here for backwards-compatability, need to deprecate. -class NotAuthorized(Forbidden): - message = _("You are not authorized to complete this action.") - - -class Invalid(GlanceException): - message = _("Data supplied was not valid.") - - -class InvalidSortKey(Invalid): - message = _("Sort key supplied was not valid.") - - -class InvalidFilterRangeValue(Invalid): - message = _("Unable to filter using the specified range.") - - -class ReadonlyProperty(Forbidden): - message = _("Attribute '%(property)s' is read-only.") - - -class ReservedProperty(Forbidden): - message = _("Attribute '%(property)s' is reserved.") - - -class AuthorizationRedirect(GlanceException): - message = _("Redirecting to %(uri)s for authorization.") - - -class DatabaseMigrationError(GlanceException): - message = _("There was an error migrating the database.") - - -class ClientConnectionError(GlanceException): - message = _("There was an error connecting to a server") - - -class ClientConfigurationError(GlanceException): - message = _("There was an error configuring the client.") - - -class MultipleChoices(GlanceException): - message = _("The request returned a 302 Multiple Choices. This generally " - "means that you have not included a version indicator in a " - "request URI.\n\nThe body of response returned:\n%(body)s") - - -class LimitExceeded(GlanceException): - message = _("The request returned a 413 Request Entity Too Large. This " - "generally means that rate limiting or a quota threshold was " - "breached.\n\nThe response body:\n%(body)s") - - def __init__(self, *args, **kwargs): - self.retry_after = (int(kwargs['retry']) if kwargs.get('retry') - else None) - super(LimitExceeded, self).__init__(*args, **kwargs) - - -class ServiceUnavailable(GlanceException): - message = _("The request returned 503 Service Unavilable. This " - "generally occurs on service overload or other transient " - "outage.") - - def __init__(self, *args, **kwargs): - self.retry_after = (int(kwargs['retry']) if kwargs.get('retry') - else None) - super(ServiceUnavailable, self).__init__(*args, **kwargs) - - -class ServerError(GlanceException): - message = _("The request returned 500 Internal Server Error.") - - -class UnexpectedStatus(GlanceException): - message = _("The request returned an unexpected status: %(status)s." - "\n\nThe response body:\n%(body)s") - - -class InvalidContentType(GlanceException): - message = _("Invalid content type %(content_type)s") - - -class BadRegistryConnectionConfiguration(GlanceException): - message = _("Registry was not configured correctly on API server. " - "Reason: %(reason)s") - - -class BadStoreConfiguration(GlanceException): - message = _("Store %(store_name)s could not be configured correctly. " - "Reason: %(reason)s") - - -class BadDriverConfiguration(GlanceException): - message = _("Driver %(driver_name)s could not be configured correctly. " - "Reason: %(reason)s") - - -class StoreDeleteNotSupported(GlanceException): - message = _("Deleting images from this store is not supported.") - - -class StoreAddDisabled(GlanceException): - message = _("Configuration for store failed. Adding images to this " - "store is disabled.") - - -class InvalidNotifierStrategy(GlanceException): - message = _("'%(strategy)s' is not an available notifier strategy.") - - -class MaxRedirectsExceeded(GlanceException): - message = _("Maximum redirects (%(redirects)s) was exceeded.") - - -class InvalidRedirect(GlanceException): - message = _("Received invalid HTTP redirect.") - - -class NoServiceEndpoint(GlanceException): - message = _("Response from Keystone does not contain a Glance endpoint.") - - -class RegionAmbiguity(GlanceException): - message = _("Multiple 'image' service matches for region %(region)s. This " - "generally means that a region is required and you have not " - "supplied one.") - - -class WorkerCreationFailure(GlanceException): - message = _("Server worker creation failed: %(reason)s.") - - -class SchemaLoadError(GlanceException): +class SchemaLoadError(PortasException): message = _("Unable to load schema: %(reason)s") -class InvalidObject(GlanceException): +class InvalidObject(PortasException): message = _("Provided object does not match schema " "'%(schema)s': %(reason)s") -class UnsupportedHeaderFeature(GlanceException): - message = _("Provided header feature is unsupported: %(feature)s") - - -class InUseByStore(GlanceException): - message = _("The image cannot be deleted because it is in use through " - "the backend store outside of Glance.") - - -class ImageSizeLimitExceeded(GlanceException): - message = _("The provided image is too large.") diff --git a/portas/portas/db/__init__.py b/portas/portas/db/__init__.py index 0a754b6..75fd934 100644 --- a/portas/portas/db/__init__.py +++ b/portas/portas/db/__init__.py @@ -1 +1,12 @@ -__author__ = 'sad' +from oslo.config import cfg + +sql_connection_opt = cfg.StrOpt('sql_connection', + default='sqlite:///portas.sqlite', + secret=True, + metavar='CONNECTION', + help='A valid SQLAlchemy connection ' + 'string for the metadata database. ' + 'Default: %(default)s') + +CONF = cfg.CONF +CONF.register_opt(sql_connection_opt) \ No newline at end of file diff --git a/portas/portas/db/api.py b/portas/portas/db/api.py index 0a754b6..4c1d0af 100644 --- a/portas/portas/db/api.py +++ b/portas/portas/db/api.py @@ -1 +1,18 @@ -__author__ = 'sad' +from portas.db.models import Environment +from portas.db.session import get_session + + +class EnvironmentRepository(object): + def list(self): + session = get_session() + return session.query(Environment).all() + + def add(self, values): + session = get_session() + with session.begin(): + env = Environment() + env.update(values) + session.add(env) + return env + + # def update(self, env): \ No newline at end of file diff --git a/portas/portas/db/migrate_repo/migrate.cfg b/portas/portas/db/migrate_repo/migrate.cfg index 6761c45..2ca05cc 100644 --- a/portas/portas/db/migrate_repo/migrate.cfg +++ b/portas/portas/db/migrate_repo/migrate.cfg @@ -1,7 +1,7 @@ [db_settings] # Used to identify which repository this database is versioned under. # You can use the name of your project. -repository_id=Glance Migrations +repository_id=Portas Migrations # The name of the database table used to track the schema version. # This name shouldn't already be used by your project. diff --git a/portas/portas/db/migrate_repo/versions/001_add_initial_tables.py b/portas/portas/db/migrate_repo/versions/001_add_initial_tables.py index 1200328..1488383 100644 --- a/portas/portas/db/migrate_repo/versions/001_add_initial_tables.py +++ b/portas/portas/db/migrate_repo/versions/001_add_initial_tables.py @@ -1,36 +1,29 @@ from sqlalchemy.schema import MetaData, Table, Column, ForeignKey -from sqlalchemy.types import Integer, String, Text, DateTime +from sqlalchemy.types import String, Text, DateTime meta = MetaData() -Table('datacenter', meta, - Column('id', String(32), primary_key=True), - Column('name', String(255)), - Column('type', String(255)), - Column('version', String(255)), - Column('tenant_id',String(100)), - Column('KMS', String(80)), - Column('WSUS', String(80)), - Column('extra', Text()), +Table('environment', meta, + Column('id', String(32), primary_key=True), + Column('name', String(255)), + Column('created', DateTime(), nullable=False), + Column('updated', DateTime(), nullable=False), + Column('tenant_id', String(36)), + Column('description', Text()), ) Table('service', meta, - Column('id', String(32), primary_key=True), - Column('datacenter_id', String(32), ForeignKey('datacenter.id')), - Column('name', String(255)), - Column('type', String(40)), - Column('status', String(255)), - Column('tenant_id', String(40)), - Column('created_at', DateTime, nullable=False), - Column('updated_at', DateTime, nullable=False), - Column('deployed', String(40)), - Column('vm_id',String(40)), - Column('extra', Text()), + Column('id', String(32), primary_key=True), + Column('name', String(255)), + Column('type', String(40)), + Column('environment_id', String(32), ForeignKey('environment.id')), + Column('created', DateTime, nullable=False), + Column('updated', DateTime, nullable=False), + Column('description', Text()), ) - def upgrade(migrate_engine): meta.bind = migrate_engine meta.create_all() diff --git a/portas/portas/db/migrate_repo/versions/__init__.py b/portas/portas/db/migrate_repo/versions/__init__.py index 507b5ff..e69de29 100644 --- a/portas/portas/db/migrate_repo/versions/__init__.py +++ b/portas/portas/db/migrate_repo/versions/__init__.py @@ -1 +0,0 @@ -# template repository default versions module diff --git a/portas/portas/db/models.py b/portas/portas/db/models.py index 7901f37..4dccda7 100644 --- a/portas/portas/db/models.py +++ b/portas/portas/db/models.py @@ -17,19 +17,20 @@ # under the License. """ -SQLAlchemy models for glance data +SQLAlchemy models for portas data """ +import anyjson -from sqlalchemy import Column, Integer, String, BigInteger +from sqlalchemy import Column, String, BigInteger, TypeDecorator, ForeignKey from sqlalchemy.ext.compiler import compiles from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy import ForeignKey, DateTime, Boolean, Text +from sqlalchemy import DateTime, Text from sqlalchemy.orm import relationship, backref, object_mapper -from sqlalchemy import UniqueConstraint -import glance.db.sqlalchemy.api -from glance.openstack.common import timeutils -from glance.openstack.common import uuidutils +from portas.openstack.common import timeutils +from portas.openstack.common import uuidutils + +from portas.db.session import get_session BASE = declarative_base() @@ -40,22 +41,16 @@ def compile_big_int_sqlite(type_, compiler, **kw): class ModelBase(object): - """Base class for Nova and Glance Models""" - __table_args__ = {'mysql_engine': 'InnoDB'} - __table_initialized__ = False - __protected_attributes__ = set([ - "created_at", "updated_at", "deleted_at", "deleted"]) + __protected_attributes__ = {"created", "updated"} - created_at = Column(DateTime, default=timeutils.utcnow, - nullable=False) - updated_at = Column(DateTime, default=timeutils.utcnow, - nullable=False, onupdate=timeutils.utcnow) - deleted_at = Column(DateTime) - deleted = Column(Boolean, nullable=False, default=False) + created = Column(DateTime, default=timeutils.utcnow, + nullable=False) + updated = Column(DateTime, default=timeutils.utcnow, + nullable=False, onupdate=timeutils.utcnow) def save(self, session=None): """Save this object""" - session = session or glance.db.sqlalchemy.api.get_session() + session = session or get_session() session.add(self) session.flush() @@ -94,80 +89,55 @@ class ModelBase(object): return self.__dict__.items() def to_dict(self): - return self.__dict__.copy() + dictionary = self.__dict__.copy() + return {k: v for k, v in dictionary.iteritems() if k != '_sa_instance_state'} -class Image(BASE, ModelBase): - """Represents an image in the datastore""" - __tablename__ = 'images' +class JsonBlob(TypeDecorator): + impl = Text + + def process_bind_param(self, value, dialect): + return anyjson.serialize(value) + + def process_result_value(self, value, dialect): + return anyjson.deserialize(value) + + +class Environment(BASE, ModelBase): + """Represents a Environment in the metadata-store""" + __tablename__ = 'environment' id = Column(String(36), primary_key=True, default=uuidutils.generate_uuid) name = Column(String(255)) - disk_format = Column(String(20)) - container_format = Column(String(20)) - size = Column(BigInteger) - status = Column(String(30), nullable=False) - is_public = Column(Boolean, nullable=False, default=False) - checksum = Column(String(32)) - min_disk = Column(Integer(), nullable=False, default=0) - min_ram = Column(Integer(), nullable=False, default=0) - owner = Column(String(255)) - protected = Column(Boolean, nullable=False, default=False) + tenant_id = Column(String(36)) + description = Column(JsonBlob()) -class ImageProperty(BASE, ModelBase): - """Represents an image properties in the datastore""" - __tablename__ = 'image_properties' - __table_args__ = (UniqueConstraint('image_id', 'name'), {}) +class Service(BASE, ModelBase): + """ + Represents an instance of service. - id = Column(Integer, primary_key=True) - image_id = Column(String(36), ForeignKey('images.id'), - nullable=False) - image = relationship(Image, backref=backref('properties')) + :var name: string + :var type: string - type of service (e.g. Active Directory) + """ + __tablename__ = 'service' + + id = Column(String(36), primary_key=True, default=uuidutils.generate_uuid) name = Column(String(255), index=True, nullable=False) - value = Column(Text) - - -class ImageTag(BASE, ModelBase): - """Represents an image tag in the datastore""" - __tablename__ = 'image_tags' - - id = Column(Integer, primary_key=True, nullable=False) - image_id = Column(String(36), ForeignKey('images.id'), nullable=False) - value = Column(String(255), nullable=False) - - -class ImageLocation(BASE, ModelBase): - """Represents an image location in the datastore""" - __tablename__ = 'image_locations' - - id = Column(Integer, primary_key=True, nullable=False) - image_id = Column(String(36), ForeignKey('images.id'), nullable=False) - image = relationship(Image, backref=backref('locations')) - value = Column(Text(), nullable=False) - - -class ImageMember(BASE, ModelBase): - """Represents an image members in the datastore""" - __tablename__ = 'image_members' - __table_args__ = (UniqueConstraint('image_id', 'member'), {}) - - id = Column(Integer, primary_key=True) - image_id = Column(String(36), ForeignKey('images.id'), - nullable=False) - image = relationship(Image, backref=backref('members')) - - member = Column(String(255), nullable=False) - can_share = Column(Boolean, nullable=False, default=False) - status = Column(String(20), nullable=False, default="pending") + type = Column(String(255), index=True, nullable=False) + environment_id = Column(String(36), ForeignKey('environment.id')) + environment = relationship(Environment, + backref=backref('service', order_by=id), + uselist=False) + description = Column(JsonBlob()) def register_models(engine): """ Creates database tables for all models with the given engine """ - models = (Image, ImageProperty, ImageMember) + models = (Environment, Service) for model in models: model.metadata.create_all(engine) @@ -176,6 +146,6 @@ def unregister_models(engine): """ Drops database tables for all models with the given engine """ - models = (Image, ImageProperty) + models = (Environment, Service) for model in models: model.metadata.drop_all(engine) diff --git a/portas/portas/db/session.py b/portas/portas/db/session.py index c8e1c1c..42d32f8 100644 --- a/portas/portas/db/session.py +++ b/portas/portas/db/session.py @@ -30,15 +30,10 @@ from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import NullPool from sqlalchemy.exc import DisconnectionError -from windc.common import cfg -from windc.db import migrate_repo +from portas.common.config import CONF as conf +from portas.db import migrate_repo -DB_GROUP_NAME = 'sql' -DB_OPTIONS = ( - cfg.IntOpt('idle_timeout', default=3600), - cfg.StrOpt('connection', default='sqlite:///windc.sqlite'), -) MAKER = None ENGINE = None @@ -73,27 +68,26 @@ class MySQLPingListener(object): raise -def get_session(conf, autocommit=True, expire_on_commit=False): +def get_session(autocommit=True, expire_on_commit=False): """Return a SQLAlchemy session.""" global MAKER if MAKER is None: MAKER = sessionmaker(autocommit=autocommit, expire_on_commit=expire_on_commit) - engine = get_engine(conf) + engine = get_engine() MAKER.configure(bind=engine) session = MAKER() return session -def get_engine(conf): +def get_engine(): """Return a SQLAlchemy engine.""" global ENGINE - register_conf_opts(conf) - connection_url = make_url(conf.sql.connection) + connection_url = make_url(conf.sql_connection) if ENGINE is None or not ENGINE.url == connection_url: - engine_args = {'pool_recycle': conf.sql.idle_timeout, + engine_args = {'pool_recycle': 3600, 'echo': False, 'convert_unicode': True } @@ -101,22 +95,16 @@ def get_engine(conf): engine_args['poolclass'] = NullPool if 'mysql' in connection_url.drivername: engine_args['listeners'] = [MySQLPingListener()] - ENGINE = create_engine(conf.sql.connection, **engine_args) + ENGINE = create_engine(conf.sql_connection, **engine_args) + + sync() return ENGINE -def register_conf_opts(conf, options=DB_OPTIONS, group=DB_GROUP_NAME): - """Register database options.""" - - conf.register_group(cfg.OptGroup(name=group)) - conf.register_opts(options, group=group) - - -def sync(conf): - register_conf_opts(conf) +def sync(): repo_path = os.path.abspath(os.path.dirname(migrate_repo.__file__)) try: - versioning_api.upgrade(conf.sql.connection, repo_path) + versioning_api.upgrade(conf.sql_connection, repo_path) except versioning_exceptions.DatabaseNotControlledError: - versioning_api.version_control(conf.sql.connection, repo_path) - versioning_api.upgrade(conf.sql.connection, repo_path) + versioning_api.version_control(conf.sql_connection, repo_path) + versioning_api.upgrade(conf.sql_connection, repo_path) diff --git a/portas/portas/locale/ru/LC_MESSAGES/portas.po b/portas/portas/locale/ru/LC_MESSAGES/portas.po index 770835b..4ff9895 100644 --- a/portas/portas/locale/ru/LC_MESSAGES/portas.po +++ b/portas/portas/locale/ru/LC_MESSAGES/portas.po @@ -3,12 +3,11 @@ # This file is distributed under the same license as the PROJECT project. # FIRST AUTHOR , 2012. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2012-02-19 17:19-0800\n" +"POT-Creation-Date: 2013-03-01 17:33+0400\n" "PO-Revision-Date: 2012-04-26 17:40+0800\n" "Last-Translator: FULL NAME \n" "Language-Team: ru \n" @@ -19,1198 +18,174 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.6\n" -#: glance/api/middleware/cache.py:50 -msgid "Initialized image cache middleware" +#: portas/exefile.py:2 +msgid "Hello" +msgstr "Привет!" + +#: portas/openstack/common/exception.py:104 +msgid "Uncaught exception" msgstr "" -#: glance/api/middleware/cache.py:77 +#: portas/openstack/common/jsonutils.py:88 #, python-format -msgid "Cache hit for image '%s'" +msgid "Max serialization depth exceeded on object: %d %s" msgstr "" -#: glance/api/middleware/cache.py:93 +#: portas/openstack/common/log.py:225 #, python-format -msgid "" -"Image cache contained image file for image '%s', however the registry did" -" not contain metadata for that image!" +msgid "Deprecated: %s" msgstr "" -#: glance/api/middleware/cache.py:121 +#: portas/openstack/common/log.py:358 #, python-format -msgid "Removing image %s from cache" +msgid "syslog facility must be one of: %s" msgstr "" -#: glance/api/middleware/cache_manage.py:70 -msgid "Initialized image cache management middleware" -msgstr "" - -#: glance/api/middleware/version_negotiation.py:53 +#: portas/openstack/common/log.py:518 #, python-format -msgid "Processing request: %(method)s %(path)s Accept: %(accept)s" +msgid "Fatal call to deprecated config: %(msg)s" msgstr "" -#: glance/api/middleware/version_negotiation.py:66 +#: portas/openstack/common/service.py:112 +#: portas/openstack/common/service.py:275 +msgid "Full set of CONF:" +msgstr "" + +#: portas/openstack/common/service.py:121 +#: portas/openstack/common/service.py:218 #, python-format -msgid "Matched versioned URI. Version: %d.%d" +msgid "Caught %s, exiting" msgstr "" -#: glance/api/middleware/version_negotiation.py:73 +#: portas/openstack/common/service.py:164 +msgid "Parent process has died unexpectedly, exiting" +msgstr "" + +#: portas/openstack/common/service.py:200 +msgid "Forking too fast, sleeping" +msgstr "" + +#: portas/openstack/common/service.py:223 +msgid "Unhandled exception" +msgstr "" + +#: portas/openstack/common/service.py:230 #, python-format -msgid "Unknown version in versioned URI: %d.%d. Returning version choices." +msgid "Started child %d" msgstr "" -#: glance/api/middleware/version_negotiation.py:87 +#: portas/openstack/common/service.py:240 #, python-format -msgid "Matched versioned media type. Version: %d.%d" +msgid "Starting %d workers" msgstr "" -#: glance/api/middleware/version_negotiation.py:93 +#: portas/openstack/common/service.py:257 #, python-format -msgid "Unknown version in accept header: %d.%d...returning version choices." +msgid "Child %(pid)d killed by signal %(sig)d" msgstr "" -#: glance/api/middleware/version_negotiation.py:100 +#: portas/openstack/common/service.py:261 #, python-format -msgid "Unknown accept header: %s...returning version choices." +msgid "Child %(pid)s exited with status %(code)d" msgstr "" -#: glance/api/v1/controller.py:43 glance/api/v1/members.py:37 +#: portas/openstack/common/service.py:265 #, python-format -msgid "Image with identifier %s not found" +msgid "pid %d not in child list" msgstr "" -#: glance/api/v1/controller.py:48 glance/api/v1/members.py:41 -msgid "Unauthorized image access" -msgstr "" - -#: glance/api/v1/controller.py:60 +#: portas/openstack/common/service.py:293 #, python-format -msgid "Image %s is not active" +msgid "Caught %s, stopping children" msgstr "" -#: glance/api/v1/images.py:292 +#: portas/openstack/common/service.py:304 #, python-format -msgid "An image with identifier %s already exists" +msgid "Waiting on %d children to exit" msgstr "" -#: glance/api/v1/images.py:297 +#: portas/openstack/common/sslutils.py:52 #, python-format -msgid "Failed to reserve image. Got error: %(e)s" +msgid "Unable to find cert_file : %s" msgstr "" -#: glance/api/v1/images.py:302 -msgid "Not authorized to reserve image." -msgstr "" - -#: glance/api/v1/images.py:324 -msgid "Content-Type must be application/octet-stream" -msgstr "" - -#: glance/api/v1/images.py:334 +#: portas/openstack/common/sslutils.py:55 #, python-format -msgid "Setting image %s to status 'saving'" +msgid "Unable to find ca_file : %s" msgstr "" -#: glance/api/v1/images.py:338 +#: portas/openstack/common/sslutils.py:58 #, python-format -msgid "Uploading image data for image %(image_id)s to %(store_name)s store" +msgid "Unable to find key_file : %s" msgstr "" -#: glance/api/v1/images.py:345 -msgid "Got request with no content-length and no x-image-meta-size header" -msgstr "" - -#: glance/api/v1/images.py:351 -#, python-format -msgid "" -"Denying attempt to upload image larger than %(max_image_size)d. Supplied " -"image size was %(image_size)d" -msgstr "" - -#: glance/api/v1/images.py:365 -#, python-format -msgid "" -"Supplied checksum (%(supplied_checksum)s) and checksum generated from " -"uploaded image (%(checksum)s) did not match. Setting image status to " -"'killed'." -msgstr "" - -#: glance/api/v1/images.py:376 -#, python-format -msgid "" -"Updating image %(image_id)s data. Checksum set to %(checksum)s, size set " -"to %(size)d" -msgstr "" - -#: glance/api/v1/images.py:387 -#, python-format -msgid "Attempt to upload duplicate image: %s" -msgstr "" - -#: glance/api/v1/images.py:394 -#, python-format -msgid "Unauthorized upload attempt: %s" -msgstr "" - -#: glance/api/v1/images.py:402 -#, python-format -msgid "Image storage media is full: %s" -msgstr "" - -#: glance/api/v1/images.py:410 -#, python-format -msgid "Insufficient permissions on image storage media: %s" -msgstr "" - -#: glance/api/v1/images.py:428 -#, python-format -msgid "Error uploading image: (%(class_name)s): %(exc)s" -msgstr "" - -#: glance/api/v1/images.py:473 -#, python-format -msgid "Unable to kill image %(id)s: %(exc)s" -msgstr "" - -#: glance/api/v1/images.py:532 glance/api/v1/images.py:564 -#: glance/api/v1/images.py:637 -msgid "Read-only access" -msgstr "" - -#: glance/api/v1/images.py:585 -msgid "Cannot upload to an unqueued image" -msgstr "" - -#: glance/api/v1/images.py:591 -msgid "Attempted to update Location field for an image not in queued status." -msgstr "" - -#: glance/api/v1/images.py:602 glance/registry/api/v1/images.py:392 -#, python-format -msgid "Failed to update image metadata. Got error: %(e)s" -msgstr "" - -#: glance/api/v1/images.py:644 -msgid "Image is protected" -msgstr "" - -#: glance/api/v1/images.py:680 -#, python-format -msgid "Requested store %s not available on this Glance server" -msgstr "" - -#: glance/api/v1/images.py:696 -#, python-format -msgid "Default store %s not available on this Glance server\n" -msgstr "" - -#: glance/api/v1/images.py:714 -#, python-format -msgid "Incoming image size of %s was not convertible to an integer." -msgstr "" - -#: glance/api/v1/images.py:723 -#, python-format -msgid "" -"Denying attempt to upload image larger than %(max_image_size)d. Supplied " -"image size was %(incoming_image_size)d" -msgstr "" - -#: glance/api/v1/images.py:800 -#, python-format -msgid "An error occurred during image.send notification: %(err)s" -msgstr "" - -#: glance/api/v1/images.py:831 -#, python-format -msgid "" -"An error occurred reading from backend storage for image %(image_id): " -"%(err)s" -msgstr "" - -#: glance/api/v1/images.py:837 -#, python-format -msgid "" -"Backend storage for image %(image_id)s disconnected after writing only " -"%(bytes_written)d bytes" -msgstr "" - -#: glance/api/v1/images.py:841 -#, python-format -msgid "Corrupt image download for image %(image_id)s" -msgstr "" - -#: glance/api/v1/members.py:53 glance/api/v1/members.py:88 -#: glance/api/v1/members.py:124 glance/registry/api/v1/members.py:70 -#: glance/registry/api/v1/members.py:173 glance/registry/api/v1/members.py:228 -msgid "No authenticated user" -msgstr "" - -#: glance/common/auth.py:168 glance/common/auth.py:213 -#, python-format -msgid "Unexpected response: %s" -msgstr "" - -#: glance/common/auth.py:235 -#, python-format -msgid "Unknown auth strategy '%s'" -msgstr "" - -#: glance/common/client.py:267 -msgid "" -"You have selected to use SSL in connecting, and you have supplied a cert," -" however you have failed to supply either a key_file parameter or set the" -" GLANCE_CLIENT_KEY_FILE environ variable" -msgstr "" - -#: glance/common/client.py:275 -msgid "" -"You have selected to use SSL in connecting, and you have supplied a key, " -"however you have failed to supply either a cert_file parameter or set the" -" GLANCE_CLIENT_CERT_FILE environ variable" -msgstr "" - -#: glance/common/client.py:283 -#, python-format -msgid "The key file you specified %s does not exist" -msgstr "" - -#: glance/common/client.py:289 -#, python-format -msgid "The cert file you specified %s does not exist" -msgstr "" - -#: glance/common/client.py:295 -#, python-format -msgid "The CA file you specified %s does not exist" -msgstr "" - -#: glance/common/config.py:90 -msgid "Invalid syslog facility" -msgstr "" - -#: glance/common/exception.py:37 -msgid "An unknown exception occurred" -msgstr "" - -#: glance/common/exception.py:59 -msgid "Missing required argument." -msgstr "" - -#: glance/common/exception.py:63 -#, python-format -msgid "Missing required credential: %(required)s" -msgstr "" - -#: glance/common/exception.py:67 -msgid "An object with the specified identifier was not found." -msgstr "" - -#: glance/common/exception.py:71 -#, python-format -msgid "Unknown scheme '%(scheme)s' found in URI" -msgstr "" - -#: glance/common/exception.py:75 -#, python-format -msgid "The Store URI %(uri)s was malformed. Reason: %(reason)s" -msgstr "" - -#: glance/common/exception.py:79 -msgid "An object with the same identifier already exists." -msgstr "" - -#: glance/common/exception.py:83 -msgid "There is not enough disk space on the image storage media." -msgstr "" - -#: glance/common/exception.py:87 -msgid "Permission to write image storage media denied." -msgstr "" - -#: glance/common/exception.py:91 -#, python-format -msgid "" -"Failed to import requested object/class: '%(import_str)s'. Reason: " -"%(reason)s" -msgstr "" - -#: glance/common/exception.py:96 -#, python-format -msgid "Connect error/bad request to Auth service at URL %(url)s." -msgstr "" - -#: glance/common/exception.py:100 -#, python-format -msgid "Auth service at URL %(url)s not found." -msgstr "" - -#: glance/common/exception.py:104 -msgid "Authorization failed." -msgstr "" - -#: glance/common/exception.py:108 glance/common/exception.py:112 -msgid "You are not authorized to complete this action." -msgstr "" - -#: glance/common/exception.py:116 -msgid "Data supplied was not valid." -msgstr "" - -#: glance/common/exception.py:120 -#, python-format -msgid "Redirecting to %(uri)s for authorization." -msgstr "" - -#: glance/common/exception.py:124 -msgid "There was an error migrating the database." -msgstr "" - -#: glance/common/exception.py:128 -msgid "There was an error connecting to a server" -msgstr "" - -#: glance/common/exception.py:132 -msgid "There was an error configuring the client." -msgstr "" - -#: glance/common/exception.py:136 -#, python-format -msgid "" -"The request returned a 302 Multiple Choices. This generally means that " -"you have not included a version indicator in a request URI.\n" -"\n" -"The body of response returned:\n" -"%(body)s" -msgstr "" - -#: glance/common/exception.py:142 -#, python-format -msgid "Invalid content type %(content_type)s" -msgstr "" - -#: glance/common/exception.py:146 -#, python-format -msgid "Registry was not configured correctly on API server. Reason: %(reason)s" -msgstr "" - -#: glance/common/exception.py:151 -#, python-format -msgid "Store %(store_name)s could not be configured correctly. Reason: %(reason)s" -msgstr "" - -#: glance/common/exception.py:156 -#, python-format -msgid "" -"Driver %(driver_name)s could not be configured correctly. Reason: " -"%(reason)s" -msgstr "" - -#: glance/common/exception.py:161 -msgid "Deleting images from this store is not supported." -msgstr "" - -#: glance/common/exception.py:165 -msgid "Configuration for store failed. Adding images to this store is disabled." -msgstr "" - -#: glance/common/exception.py:170 -#, python-format -msgid "'%(strategy)s' is not an available notifier strategy." -msgstr "" - -#: glance/common/exception.py:174 -#, python-format -msgid "Maximum redirects (%(redirects)s) was exceeded." -msgstr "" - -#: glance/common/exception.py:178 -msgid "Received invalid HTTP redirect." -msgstr "" - -#: glance/common/exception.py:182 -msgid "Response from Keystone does not contain a Glance endpoint." -msgstr "" - -#: glance/common/wsgi.py:106 +#: portas/openstack/common/sslutils.py:61 msgid "" "When running server in SSL mode, you must specify both a cert_file and " "key_file option value in your configuration file" msgstr "" -#: glance/common/wsgi.py:124 +#: portas/openstack/common/wsgi.py:110 #, python-format -msgid "Could not bind to %s:%s after trying for 30 seconds" +msgid "Could not bind to %(host)s:%(port)s after trying for 30 seconds" msgstr "" -#: glance/common/wsgi.py:155 -msgid "SIGTERM received" +#: portas/openstack/common/wsgi.py:372 +msgid "Unsupported Content-Type" msgstr "" -#: glance/common/wsgi.py:164 -msgid "SIGHUP received" +#: portas/openstack/common/wsgi.py:375 +msgid "Malformed request body" msgstr "" -#: glance/common/wsgi.py:180 +#: portas/openstack/common/wsgi.py:660 +msgid "Empty body provided in request" +msgstr "" + +#: portas/openstack/common/wsgi.py:666 +msgid "Unrecognized Content-Type provided in request" +msgstr "" + +#: portas/openstack/common/wsgi.py:670 +msgid "No Content-Type provided in request" +msgstr "" + +#: portas/openstack/common/wsgi.py:676 +msgid "Unable to deserialize body as provided Content-Type" +msgstr "" + +#: portas/openstack/common/wsgi.py:726 +msgid "cannot understand JSON" +msgstr "" + +#: portas/openstack/common/wsgi.py:750 +msgid "cannot understand XML" +msgstr "" + +#: portas/openstack/common/notifier/api.py:126 #, python-format -msgid "Starting %d workers" +msgid "%s not in valid priorities" msgstr "" -#: glance/common/wsgi.py:191 -#, python-format -msgid "Removing dead child %s" -msgstr "" - -#: glance/common/wsgi.py:199 -msgid "Caught keyboard interrupt. Exiting." -msgstr "" - -#: glance/common/wsgi.py:203 -msgid "Exited" -msgstr "" - -#: glance/common/wsgi.py:221 -#, python-format -msgid "Child %d exiting normally" -msgstr "" - -#: glance/common/wsgi.py:224 -#, python-format -msgid "Started child %s" -msgstr "" - -#: glance/common/wsgi.py:243 -msgid "Starting single process server" -msgstr "" - -#: glance/image_cache/__init__.py:57 -#, python-format -msgid "Image cache loaded driver '%s'." -msgstr "" - -#: glance/image_cache/__init__.py:60 +#: portas/openstack/common/notifier/api.py:142 #, python-format msgid "" -"Image cache driver '%(driver_name)s' failed to load. Got error: " -"'%(import_err)s." +"Problem '%(e)s' attempting to send to notification system. " +"Payload=%(payload)s" msgstr "" -#: glance/image_cache/__init__.py:65 glance/image_cache/__init__.py:82 -msgid "Defaulting to SQLite driver." -msgstr "" - -#: glance/image_cache/__init__.py:79 -#, python-format -msgid "" -"Image cache driver '%(driver_module)s' failed to configure. Got error: " -"'%(config_err)s" -msgstr "" - -#: glance/image_cache/__init__.py:164 -msgid "Image cache has free space, skipping prune..." -msgstr "" - -#: glance/image_cache/__init__.py:168 -#, python-format -msgid "" -"Image cache currently %(overage)d bytes over max size. Starting prune to " -"max size of %(max_size)d " -msgstr "" - -#: glance/image_cache/__init__.py:177 -#, python-format -msgid "Pruning '%(image_id)s' to free %(size)d bytes" -msgstr "" - -#: glance/image_cache/__init__.py:185 -#, python-format -msgid "" -"Pruning finished pruning. Pruned %(total_files_pruned)d and " -"%(total_bytes_pruned)d." -msgstr "" - -#: glance/image_cache/__init__.py:220 -#, python-format -msgid "Tee'ing image '%s' into cache" -msgstr "" - -#: glance/image_cache/__init__.py:232 -#, python-format -msgid "" -"Exception encountered while tee'ing image '%s' into cache. Continuing " -"with response." -msgstr "" - -#: glance/image_cache/prefetcher.py:55 -#, python-format -msgid "Image '%s' is not active. Not caching." -msgstr "" - -#: glance/image_cache/prefetcher.py:60 glance/image_cache/queue_image.py:52 -#, python-format -msgid "No metadata found for image '%s'" -msgstr "" - -#: glance/image_cache/prefetcher.py:64 -#, python-format -msgid "Caching image '%s'" -msgstr "" - -#: glance/image_cache/prefetcher.py:72 -msgid "Nothing to prefetch." -msgstr "" - -#: glance/image_cache/prefetcher.py:76 -#, python-format -msgid "Found %d images to prefetch" -msgstr "" - -#: glance/image_cache/prefetcher.py:82 -msgid "Failed to successfully cache all images in queue." -msgstr "" - -#: glance/image_cache/prefetcher.py:86 -#, python-format -msgid "Successfully cached all %d images" -msgstr "" - -#: glance/image_cache/queue_image.py:47 -#, python-format -msgid "Image '%s' is not active. Not queueing." -msgstr "" - -#: glance/image_cache/queue_image.py:55 -#, python-format -msgid "Queueing image '%s'" -msgstr "" - -#: glance/image_cache/queue_image.py:63 -msgid "No images to queue!" -msgstr "" - -#: glance/image_cache/queue_image.py:66 -#, python-format -msgid "Received %d images to queue" -msgstr "" - -#: glance/image_cache/queue_image.py:72 -msgid "Failed to successfully queue all images in queue." -msgstr "" - -#: glance/image_cache/queue_image.py:76 -#, python-format -msgid "Successfully queued all %d images" -msgstr "" - -#: glance/image_cache/drivers/base.py:65 -#, python-format -msgid "Failed to read %s from config" -msgstr "" - -#: glance/image_cache/drivers/sqlite.py:120 -#, python-format -msgid "Failed to initialize the image cache database. Got error: %s" -msgstr "" - -#: glance/image_cache/drivers/sqlite.py:159 -#: glance/image_cache/drivers/xattr.py:143 -msgid "Gathering cached image entries." -msgstr "" - -#: glance/image_cache/drivers/sqlite.py:294 -#: glance/image_cache/drivers/xattr.py:273 -#, python-format -msgid "Fetch finished, moving '%(incomplete_path)s' to '%(final_path)s'" -msgstr "" - -#: glance/image_cache/drivers/sqlite.py:318 -#: glance/image_cache/drivers/xattr.py:289 -#, python-format -msgid "" -"Fetch of cache file failed, rolling back by moving '%(incomplete_path)s' " -"to '%(invalid_path)s'" -msgstr "" - -#: glance/image_cache/drivers/sqlite.py:372 -#, python-format -msgid "Error executing SQLite call. Got error: %s" -msgstr "" - -#: glance/image_cache/drivers/sqlite.py:388 -#: glance/image_cache/drivers/xattr.py:327 -#, python-format -msgid "Not queueing image '%s'. Already cached." -msgstr "" - -#: glance/image_cache/drivers/sqlite.py:393 -#: glance/image_cache/drivers/xattr.py:332 -#, python-format -msgid "Not queueing image '%s'. Already being written to cache" -msgstr "" - -#: glance/image_cache/drivers/sqlite.py:399 -#: glance/image_cache/drivers/xattr.py:338 -#, python-format -msgid "Not queueing image '%s'. Already queued." -msgstr "" - -#: glance/image_cache/drivers/sqlite.py:460 -#: glance/image_cache/drivers/xattr.py:429 -#, python-format -msgid "Deleting image cache file '%s'" -msgstr "" - -#: glance/image_cache/drivers/sqlite.py:463 -#: glance/image_cache/drivers/xattr.py:432 -#, python-format -msgid "Cached image file '%s' doesn't exist, unable to delete" -msgstr "" - -#: glance/image_cache/drivers/xattr.py:104 -#, python-format -msgid "" -"The device housing the image cache directory %(image_cache_dir)s does not" -" support xattr. It is likely you need to edit your fstab and add the " -"user_xattr option to the appropriate line for the device housing the " -"cache directory." -msgstr "" - -#: glance/image_cache/drivers/xattr.py:281 -#, python-format -msgid "Removing image '%s' from queue after caching it." -msgstr "" - -#: glance/image_cache/drivers/xattr.py:343 -#, python-format -msgid "Queueing image '%s'." -msgstr "" - -#: glance/image_cache/drivers/xattr.py:375 -#, python-format -msgid "No grace period, reaping '%(path)s' immediately" -msgstr "" - -#: glance/image_cache/drivers/xattr.py:380 -#, python-format -msgid "Cache entry '%(path)s' exceeds grace period, (%(age)i s > %(grace)i s)" -msgstr "" - -#: glance/image_cache/drivers/xattr.py:385 -#, python-format -msgid "Reaped %(reaped)s %(entry_type)s cache entries" -msgstr "" - -#: glance/notifier/notify_kombu.py:88 -#, python-format -msgid "Reconnecting to AMQP server on %(hostname)s:%(port)d" -msgstr "" - -#: glance/notifier/notify_kombu.py:92 -#, python-format -msgid "Connecting to AMQP server on %(hostname)s:%(port)d" -msgstr "" - -#: glance/notifier/notify_kombu.py:121 -#, python-format -msgid "Connected to AMQP server on %(hostname)s:%(port)d" -msgstr "" - -#: glance/notifier/notify_kombu.py:150 -#, python-format -msgid "" -"Unable to connect to AMQP server on %(hostname)s:%(port)d after " -"%(max_retries)d tries: %(err_str)s" -msgstr "" - -#: glance/notifier/notify_kombu.py:162 -#, python-format -msgid "" -"AMQP server on %(hostname)s:%(port)d is unreachable: %(err_str)s. Trying " -"again in %(sleep_time)d seconds." -msgstr "" - -#: glance/notifier/notify_kombu.py:169 -#, python-format -msgid "Notification with priority %(priority)s failed; msg=%s" -msgstr "" - -#: glance/notifier/notify_kombu.py:206 -#, python-format -msgid "Unable to send notification: %s" -msgstr "" - -#: glance/notifier/notify_qpid.py:113 -#, python-format -msgid "Connected to AMQP server on %s" -msgstr "" - -#: glance/registry/__init__.py:66 -msgid "Configuration option was not valid" -msgstr "" - -#: glance/registry/__init__.py:70 -msgid "Could not find required configuration option" -msgstr "" - -#: glance/registry/__init__.py:117 -msgid "Adding image metadata..." -msgstr "" - -#: glance/registry/__init__.py:124 -#, python-format -msgid "Updating image metadata for image %s..." -msgstr "" - -#: glance/registry/__init__.py:130 +#: portas/openstack/common/notifier/api.py:172 #, python-format -msgid "Deleting image metadata for image %s..." +msgid "Failed to load notifier %s. These notifications will not be sent." msgstr "" -#: glance/registry/api/v1/images.py:70 -msgid "Invalid marker. Image could not be found." -msgstr "" - -#: glance/registry/api/v1/images.py:171 -msgid "Unrecognized changes-since value" -msgstr "" - -#: glance/registry/api/v1/images.py:176 -msgid "protected must be True, or False" -msgstr "" - -#: glance/registry/api/v1/images.py:202 -msgid "limit param must be an integer" -msgstr "" - -#: glance/registry/api/v1/images.py:205 -msgid "limit param must be positive" -msgstr "" - -#: glance/registry/api/v1/images.py:214 -msgid "Invalid marker format" -msgstr "" - -#: glance/registry/api/v1/images.py:224 -#, python-format -msgid "Unsupported sort_key. Acceptable values: %s" -msgstr "" - -#: glance/registry/api/v1/images.py:233 -#, python-format -msgid "Unsupported sort_dir. Acceptable values: %s" -msgstr "" - -#: glance/registry/api/v1/images.py:259 -msgid "is_public must be None, True, or False" -msgstr "" - -#: glance/registry/api/v1/images.py:280 glance/registry/api/v1/images.py:403 -#: glance/registry/api/v1/members.py:47 glance/registry/api/v1/members.py:81 -#: glance/registry/api/v1/members.py:183 glance/registry/api/v1/members.py:238 -#, python-format -msgid "Access by %(user)s to image %(id)s denied" -msgstr "" - -#: glance/registry/api/v1/images.py:306 -#, python-format -msgid "Access by %(user)s to delete public image %(id)s denied" -msgstr "" - -#: glance/registry/api/v1/images.py:312 -#, python-format -msgid "Access by %(user)s to delete private image %(id)s denied" -msgstr "" - -#: glance/registry/api/v1/images.py:345 -msgid "Invalid image id format" -msgstr "" - -#: glance/registry/api/v1/images.py:352 -#, python-format -msgid "Image with identifier %s already exists!" -msgstr "" - -#: glance/registry/api/v1/images.py:356 -#, python-format -msgid "Failed to add image metadata. Got error: %(e)s" -msgstr "" - -#: glance/registry/api/v1/images.py:382 -#, python-format -msgid "Updating image %(id)s with metadata: %(image_data)r" -msgstr "" - -#: glance/registry/api/v1/members.py:89 glance/registry/api/v1/members.py:191 -#: glance/registry/api/v1/members.py:246 -msgid "No permission to share that image" -msgstr "" - -#: glance/registry/api/v1/members.py:97 glance/registry/api/v1/members.py:110 -#: glance/registry/api/v1/members.py:201 -#, python-format -msgid "Invalid membership association: %s" -msgstr "" - -#: glance/registry/api/v1/members.py:275 -msgid "Invalid marker. Membership could not be found." -msgstr "" - -#: glance/registry/db/api.py:83 -#, python-format -msgid "" -"Error configuring registry database with supplied sql_connection " -"'%(sql_connection)s'. Got error:\n" -"%(err)s" -msgstr "" - -#: glance/registry/db/api.py:100 -msgid "Attempted to modify image user did not own." -msgstr "" - -#: glance/registry/db/api.py:101 -msgid "You do not own this image" -msgstr "" - -#: glance/registry/db/migration.py:47 -#, python-format -msgid "database '%(sql_connection)s' is not under migration control" -msgstr "" - -#: glance/registry/db/migration.py:64 -#, python-format -msgid "Upgrading %(sql_connection)s to version %(version_str)s" -msgstr "" - -#: glance/registry/db/migration.py:80 -#, python-format -msgid "Downgrading %(sql_connection)s to version %(version)s" -msgstr "" - -#: glance/registry/db/migration.py:95 -#, python-format -msgid "database '%(sql_connection)s' is already under migration control" -msgstr "" - -#: glance/registry/db/migrate_repo/schema.py:96 -#, python-format -msgid "creating table %(table)s" -msgstr "" - -#: glance/registry/db/migrate_repo/schema.py:102 -#, python-format -msgid "dropping table %(table)s" -msgstr "" - -#: glance/store/__init__.py:196 -#, python-format -msgid "Failed to delete image at %s from store (%s)" -msgstr "" - -#: glance/store/__init__.py:209 -#, python-format -msgid "Image id %(image_id)s already queued for delete" -msgstr "" - -#: glance/store/base.py:44 -msgid "Failed to configure store correctly. Disabling add method." -msgstr "" - -#: glance/store/filesystem.py:59 -msgid "No path specified" -msgstr "" - -#: glance/store/filesystem.py:111 -#, python-format -msgid "Could not find %s in configuration options." -msgstr "" - -#: glance/store/filesystem.py:118 -#, python-format -msgid "Directory to write image files does not exist (%s). Creating." -msgstr "" - -#: glance/store/filesystem.py:124 -#, python-format -msgid "Unable to create datadir: %s" -msgstr "" - -#: glance/store/filesystem.py:142 -#, python-format -msgid "Image file %s not found" -msgstr "" - -#: glance/store/filesystem.py:144 -#, python-format -msgid "Found image at %s. Returning in ChunkedFile." -msgstr "" - -#: glance/store/filesystem.py:163 -#, python-format -msgid "Deleting image at %(fn)s" -msgstr "" - -#: glance/store/filesystem.py:166 -#, python-format -msgid "You cannot delete file %s" -msgstr "" - -#: glance/store/filesystem.py:169 -#, python-format -msgid "Image file %s does not exist" -msgstr "" - -#: glance/store/filesystem.py:194 -#, python-format -msgid "Image file %s already exists!" -msgstr "" - -#: glance/store/filesystem.py:218 -#, python-format -msgid "" -"Wrote %(bytes_written)d bytes to %(filepath)s with checksum " -"%(checksum_hex)s" -msgstr "" - -#: glance/store/http.py:76 -#, python-format -msgid "Credentials '%s' not well-formatted." -msgstr "" - -#: glance/store/http.py:82 -msgid "No address specified in HTTP URL" -msgstr "" - -#: glance/store/location.py:123 -#, python-format -msgid "Unable to find StoreLocation class in store %s" -msgstr "" - -#: glance/store/rbd.py:63 -msgid "URI must start with rbd://" -msgstr "" - -#: glance/store/rbd.py:96 glance/store/rbd.py:202 -#, python-format -msgid "RBD image %s does not exist" -msgstr "" - -#: glance/store/rbd.py:128 -#, python-format -msgid "Error in store configuration: %s" -msgstr "" - -#: glance/store/rbd.py:172 -#, python-format -msgid "RBD image %s already exists" -msgstr "" - -#: glance/store/s3.py:90 -msgid "" -"URI cannot contain more than one occurrence of a scheme.If you have " -"specified a URI like " -"s3://accesskey:secretkey@https://s3.amazonaws.com/bucket/key-id, you need" -" to change it to use the s3+https:// scheme, like so: " -"s3+https://accesskey:secretkey@s3.amazonaws.com/bucket/key-id" -msgstr "" - -#: glance/store/s3.py:125 -#, python-format -msgid "Badly formed S3 credentials %s" -msgstr "" - -#: glance/store/s3.py:137 -msgid "Badly formed S3 URI. Missing s3 service URL." -msgstr "" - -#: glance/store/s3.py:140 -msgid "Badly formed S3 URI" -msgstr "" - -#: glance/store/s3.py:233 glance/store/swift.py:312 -#, python-format -msgid "Could not find %(param)s in configuration options." -msgstr "" - -#: glance/store/s3.py:281 -#, python-format -msgid "" -"Retrieved image object from S3 using (s3_host=%(s3_host)s, " -"access_key=%(accesskey)s, bucket=%(bucket)s, key=%(obj_name)s)" -msgstr "" - -#: glance/store/s3.py:333 -#, python-format -msgid "S3 already has an image at location %s" -msgstr "" - -#: glance/store/s3.py:336 -#, python-format -msgid "" -"Adding image object to S3 using (s3_host=%(s3_host)s, " -"access_key=%(access_key)s, bucket=%(bucket)s, key=%(obj_name)s)" -msgstr "" - -#: glance/store/s3.py:357 -#, python-format -msgid "Writing request body file to temporary file for %s" -msgstr "" - -#: glance/store/s3.py:371 -#, python-format -msgid "Uploading temporary file to S3 for %s" -msgstr "" - -#: glance/store/s3.py:379 -#, python-format -msgid "" -"Wrote %(size)d bytes to S3 key named %(obj_name)s with checksum " -"%(checksum_hex)s" -msgstr "" - -#: glance/store/s3.py:404 -#, python-format -msgid "" -"Deleting image object from S3 using (s3_host=%(s3_host)s, " -"access_key=%(accesskey)s, bucket=%(bucket)s, key=%(obj_name)s)" -msgstr "" - -#: glance/store/s3.py:425 -#, python-format -msgid "Could not find bucket with ID %(bucket_id)s" -msgstr "" - -#: glance/store/s3.py:473 -#, python-format -msgid "Could not find key %(obj)s in bucket %(bucket)s" -msgstr "" - -#: glance/store/scrubber.py:42 -#, python-format -msgid "Starting Daemon: wakeup_time=%(wakeup_time)s threads=%(threads)s" -msgstr "" - -#: glance/store/scrubber.py:55 -msgid "Daemon Shutdown on KeyboardInterrupt" -msgstr "" - -#: glance/store/scrubber.py:59 -msgid "Runing application" -msgstr "" - -#: glance/store/scrubber.py:62 -#, python-format -msgid "Next run scheduled in %s seconds" -msgstr "" - -#: glance/store/scrubber.py:83 -#, python-format -msgid "Initializing scrubber with conf: %s" -msgstr "" - -#: glance/store/scrubber.py:98 -#, python-format -msgid "%s does not exist" -msgstr "" - -#: glance/store/scrubber.py:120 glance/store/scrubber.py:175 -#, python-format -msgid "Deleting %s images" -msgstr "" - -#: glance/store/scrubber.py:129 -#, python-format -msgid "Deleting %(uri)s" -msgstr "" - -#: glance/store/scrubber.py:132 -#, python-format -msgid "Failed to delete image from store (%(uri)s)." -msgstr "" - -#: glance/store/scrubber.py:151 -#, python-format -msgid "Getting images deleted before %s" -msgstr "" - -#: glance/store/swift.py:105 -msgid "" -"URI cannot contain more than one occurrence of a scheme.If you have " -"specified a URI like " -"swift://user:pass@http://authurl.com/v1/container/obj, you need to change" -" it to use the swift+http:// scheme, like so: " -"swift+http://user:pass@authurl.com/v1/container/obj" -msgstr "" - -#: glance/store/swift.py:142 -#, python-format -msgid "Badly formed credentials '%(creds)s' in Swift URI" -msgstr "" - -#: glance/store/swift.py:163 -msgid "Badly formed Swift URI" -msgstr "" - -#: glance/store/swift.py:229 -#, python-format -msgid "Error in configuration conf: %s" -msgstr "" - -#: glance/store/swift.py:264 glance/store/swift.py:506 -#, python-format -msgid "Swift could not find image at uri %(uri)s" -msgstr "" - -#: glance/store/swift.py:303 -#, python-format -msgid "" -"Creating Swift connection with (auth_address=%(auth_url)s, user=%(user)s," -" snet=%(snet)s)" -msgstr "" - -#: glance/store/swift.py:367 -#, python-format -msgid "Adding image object '%(obj_name)s' to Swift" -msgstr "" - -#: glance/store/swift.py:387 -msgid "Cannot determine image size. Adding as a segmented object to Swift." -msgstr "" - -#: glance/store/swift.py:411 -#, python-format -msgid "" -"Wrote chunk %(chunk_id)d/%(total_chunks)s of length %(bytes_read)d to " -"Swift returning MD5 of content: %(chunk_etag)s" -msgstr "" - -#: glance/store/swift.py:420 -msgid "Deleting final zero-length chunk" -msgstr "" - -#: glance/store/swift.py:456 -#, python-format -msgid "Swift already has an image at location %s" -msgstr "" - -#: glance/store/swift.py:458 -#, python-format -msgid "" -"Failed to add object to Swift.\n" -"Got error from Swift: %(e)s" -msgstr "" - -#: glance/store/swift.py:546 -#, python-format -msgid "" -"Failed to add container to Swift.\n" -"Got error from Swift: %(e)s" +#: portas/openstack/common/notifier/rabbit_notifier.py:27 +msgid "The rabbit_notifier is now deprecated. Please use rpc_notifier instead." msgstr "" -#: glance/store/swift.py:550 +#: portas/openstack/common/notifier/rpc_notifier.py:45 +#: portas/openstack/common/notifier/rpc_notifier2.py:51 #, python-format -msgid "" -"The container %(container)s does not exist in Swift. Please set the " -"swift_store_create_container_on_put optionto add container to Swift " -"automatically." +msgid "Could not send notification to %(topic)s. Payload=%(message)s" msgstr "" diff --git a/portas/portas/schema.py b/portas/portas/schema.py index b16c33f..7051765 100644 --- a/portas/portas/schema.py +++ b/portas/portas/schema.py @@ -44,21 +44,6 @@ class Schema(object): def _filter_func(properties, key): return key in properties - def merge_properties(self, properties): - # Ensure custom props aren't attempting to override base props - original_keys = set(self.properties.keys()) - new_keys = set(properties.keys()) - intersecting_keys = original_keys.intersection(new_keys) - conflicting_keys = [k for k in intersecting_keys - if self.properties[k] != properties[k]] - if len(conflicting_keys) > 0: - props = ', '.join(conflicting_keys) - reason = _("custom properties (%(props)s) conflict " - "with base properties") - raise exception.SchemaLoadError(reason=reason % {'props': props}) - - self.properties.update(properties) - def raw(self): raw = { 'name': self.name, @@ -70,17 +55,6 @@ class Schema(object): return raw -class PermissiveSchema(Schema): - @staticmethod - def _filter_func(properties, key): - return True - - def raw(self): - raw = super(PermissiveSchema, self).raw() - raw['additionalProperties'] = {'type': 'string'} - return raw - - class CollectionSchema(object): def __init__(self, name, item_schema): diff --git a/portas/portas/tests/api/simple_test.py b/portas/portas/tests/api/simple_test.py index bad8dde..c8d86a5 100644 --- a/portas/portas/tests/api/simple_test.py +++ b/portas/portas/tests/api/simple_test.py @@ -3,4 +3,4 @@ import unittest class Test(unittest.TestCase): def test(self): - assert False + assert True diff --git a/portas/portas/version.py b/portas/portas/version.py index 5a5db6a..f740c7e 100644 --- a/portas/portas/version.py +++ b/portas/portas/version.py @@ -15,6 +15,6 @@ # under the License. -from glance.openstack.common import version as common_version +from portas.openstack.common import version as common_version -version_info = common_version.VersionInfo('glance') +version_info = common_version.VersionInfo('portas') diff --git a/portas/run_tests.sh b/portas/run_tests.sh index f99249f..31ec4e8 100755 --- a/portas/run_tests.sh +++ b/portas/run_tests.sh @@ -28,8 +28,8 @@ function process_option { -P|--no-pep8) let no_pep8=1;; -f|--force) let force=1;; -u|--update) update=1;; - --unittests-only) noseopts="$noseopts --exclude-dir=glance/tests/functional";; - -c|--coverage) noseopts="$noseopts --with-coverage --cover-package=glance";; + --unittests-only) noseopts="$noseopts --exclude-dir=portas/tests/functional";; + -c|--coverage) noseopts="$noseopts --with-coverage --cover-package=portas";; -*) noseopts="$noseopts $1";; *) noseargs="$noseargs $1" esac diff --git a/portas/setup.cfg b/portas/setup.cfg index d53addc..3e54754 100644 --- a/portas/setup.cfg +++ b/portas/setup.cfg @@ -7,3 +7,27 @@ source-dir = doc/source tag_build = tag_date = 0 tag_svn_revision = 0 + +[compile_catalog] +directory = portas/locale +domain = portas + +[update_catalog] +domain = portas +output_dir = portas/locale +input_file = portas/locale/portas.pot + +[extract_messages] +keywords = _ gettext ngettext l_ lazy_gettext +mapping_file = babel.cfg +output_file = portas/locale/portas.pot + +[nosetests] +# NOTE(jkoelker) To run the test suite under nose install the following +# coverage http://pypi.python.org/pypi/coverage +# tissue http://pypi.python.org/pypi/tissue (pep8 checker) +# openstack-nose https://github.com/jkoelker/openstack-nose +verbosity=2 +cover-package = portas +cover-html = true +cover-erase = true \ No newline at end of file diff --git a/portas/setup.py b/portas/setup.py index a0cfe4d..8cd1b76 100644 --- a/portas/setup.py +++ b/portas/setup.py @@ -25,7 +25,8 @@ project = 'portas' setuptools.setup( name=project, version=setup.get_version(project, '2013.1'), - description='The Portas project provides a simple WSGI server for Windows Environment Management', + description='The Portas project provides a simple WSGI server for Windows ' + 'Environment Management', license='Apache License (2.0)', author='OpenStack', author_email='openstack@lists.launchpad.net', @@ -43,6 +44,7 @@ setuptools.setup( 'Programming Language :: Python :: 2.7', 'Environment :: No Input/Output (Daemon)', 'Environment :: OpenStack', - ], + ], scripts=['bin/portas-api'], - py_modules=[]) \ No newline at end of file + py_modules=[] +) diff --git a/portas/tools/pip-requires b/portas/tools/pip-requires index 20109d9..c5a332f 100644 --- a/portas/tools/pip-requires +++ b/portas/tools/pip-requires @@ -1,23 +1,30 @@ -# The greenlet package must be compiled with gcc and needs -# the Python.h headers. Make sure you install the python-dev -# package to get the right headers... -greenlet>=0.3.1 - -SQLAlchemy<=0.7.9 +Babel +SQLAlchemy>=0.7,<=0.7.9 anyjson eventlet>=0.9.12 PasteDeploy -Routes -webob==1.0.8 +routes +WebOb>=1.2 wsgiref argparse -sqlalchemy-migrate>=0.7.2 +boto +sqlalchemy-migrate>=0.7 httplib2 kombu +pycrypto>=2.1.0alpha1 iso8601>=0.1.4 -PyChef + +# Note you will need gcc buildtools installed and must +# have installed libxml headers for lxml to be successfully +# installed using pip, therefore you will need to install the +# libxml2-dev and libxslt-dev Ubuntu packages. +lxml + # For paste.util.template used in keystone.common.template Paste passlib -puka +jsonschema +python-keystoneclient>=0.2.0 + +http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b4.tar.gz#egg=oslo-config diff --git a/portas/tools/test-requires b/portas/tools/test-requires index e69de29..0330b67 100644 --- a/portas/tools/test-requires +++ b/portas/tools/test-requires @@ -0,0 +1,19 @@ +# Packages needed for dev testing +distribute>=0.6.24 + +# Needed for testing +coverage +fixtures>=0.3.12 +mox +nose +nose-exclude +openstack.nose_plugin>=0.7 +nosehtmloutput>=0.0.3 +pep8==1.3.3 +sphinx>=1.1.2 +requests +testtools>=0.9.22 + +# Optional packages that should be installed when testing +xattr>=0.6.0 +pysendfile==2.0.0 \ No newline at end of file