PEP8 cleanup
This commit is contained in:
@@ -47,4 +47,4 @@ api.add_route('/{tenant_id}/secrets/{secret_id}', SECRET)
|
||||
api.add_route('/{tenant_id}/csrs', CSRS)
|
||||
api.add_route('/{tenant_id}/csrs/{csr_id}', CSR)
|
||||
api.add_route('/{tenant_id}/certificates', CERTS)
|
||||
api.add_route('/{tenant_id}/certificates/{cert_id}', CERT)
|
||||
api.add_route('/{tenant_id}/certificates/{cert_id}', CERT)
|
||||
|
||||
@@ -20,18 +20,21 @@ API-facing resource controllers.
|
||||
|
||||
import json
|
||||
import falcon
|
||||
import logging
|
||||
|
||||
from barbican.version import __version__
|
||||
from barbican.api import ApiResource, load_body, abort
|
||||
from barbican.model.models import Tenant, Secret, States, CSR, Certificate
|
||||
from barbican.model.repositories import TenantRepo, SecretRepo, CSRRepo, CertificateRepo
|
||||
from barbican.model.repositories import TenantRepo, SecretRepo
|
||||
from barbican.model.repositories import CSRRepo, CertificateRepo
|
||||
from barbican.queue.resources import QueueResource, StartCSRMessage
|
||||
from barbican.crypto.fields import encrypt, decrypt
|
||||
from barbican.common import config
|
||||
from barbican.openstack.common.gettextutils import _
|
||||
import barbican.openstack.common.log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _tenant_not_found():
|
||||
abort(falcon.HTTP_404, 'Unable to locate tenant.')
|
||||
|
||||
@@ -42,7 +45,8 @@ def _tenant_already_exists():
|
||||
|
||||
def _secret_not_found():
|
||||
abort(falcon.HTTP_400, 'Unable to locate secret profile.')
|
||||
|
||||
|
||||
|
||||
def json_handler(obj):
|
||||
"""Convert objects into json-friendly equivalents."""
|
||||
return obj.isoformat() if hasattr(obj, 'isoformat') else obj
|
||||
@@ -50,7 +54,7 @@ def json_handler(obj):
|
||||
|
||||
class VersionResource(ApiResource):
|
||||
"""Returns service and build version information"""
|
||||
|
||||
|
||||
def on_get(self, req, resp):
|
||||
resp.status = falcon.HTTP_200
|
||||
resp.body = json.dumps({'v1': 'current',
|
||||
@@ -66,10 +70,10 @@ class TenantsResource(ApiResource):
|
||||
|
||||
def on_post(self, req, resp):
|
||||
body = load_body(req)
|
||||
print 'Start on_post...%s' % body
|
||||
LOG.debug('Start on_post...%s' % body)
|
||||
username = body['username']
|
||||
# LOG.debug('Username is {0}'.format(username))
|
||||
print 'Username is %s' % username
|
||||
LOG.debug('Tenant username is %s' % username)
|
||||
|
||||
tenant = self.repo.find_by_name(name=username, suppress_exception=True)
|
||||
|
||||
@@ -82,7 +86,7 @@ class TenantsResource(ApiResource):
|
||||
new_tenant.status = States.ACTIVE
|
||||
self.repo.create_from(new_tenant)
|
||||
|
||||
print '...post create from'
|
||||
LOG.debug('...post create from')
|
||||
|
||||
resp.status = falcon.HTTP_201
|
||||
resp.set_header('Location', '/{0}'.format(new_tenant.id))
|
||||
@@ -95,7 +99,7 @@ class TenantResource(ApiResource):
|
||||
"""Handles Tenant retrieval and deletion requests"""
|
||||
|
||||
def __init__(self, tenant_repo=None):
|
||||
self.repo = tenant_repo or TenantRepo()
|
||||
self.repo = tenant_repo or TenantRepo()
|
||||
|
||||
def on_get(self, req, resp, tenant_id):
|
||||
tenant = self.repo.get(entity_id=tenant_id)
|
||||
@@ -124,14 +128,13 @@ class SecretsResource(ApiResource):
|
||||
|
||||
body = load_body(req)
|
||||
|
||||
# TBD: Remove:
|
||||
print 'Start on_post...%s' % body
|
||||
LOG.debug('Start on_post...%s' % body)
|
||||
|
||||
name = body['name']
|
||||
# LOG.debug('Username is {0}'.format(username))
|
||||
print 'name is %s' % name
|
||||
LOG.debug('Secret name is %s' % name)
|
||||
|
||||
secret = self.secret_repo.find_by_name(name=name, suppress_exception=True)
|
||||
secret = self.secret_repo.find_by_name(name=name,
|
||||
suppress_exception=True)
|
||||
if secret:
|
||||
abort(falcon.HTTP_400, 'Secret with name {0} '
|
||||
'already exists'.format(name))
|
||||
@@ -139,21 +142,21 @@ class SecretsResource(ApiResource):
|
||||
# Encrypt fields
|
||||
encrypt(body)
|
||||
secret_value = body['secret']
|
||||
print 'encrypted secret is %s' % secret_value
|
||||
LOG.debug('Encrypted secret is %s' % secret_value)
|
||||
|
||||
new_secret = Secret()
|
||||
new_secret.name = name
|
||||
new_secret.secret = secret_value
|
||||
new_secret.tenant_id = tenant.id
|
||||
new_secret.status = States.ACTIVE
|
||||
self.secret_repo.create_from(new_secret)
|
||||
|
||||
# TBD: Remove:
|
||||
print '...post create from'
|
||||
|
||||
resp.status = falcon.HTTP_202
|
||||
resp.set_header('Location', '/{0}/secrets/{1}'.format(tenant_id, new_secret.id))
|
||||
resp.set_header('Location', '/{0}/secrets/{1}'.format(tenant_id,
|
||||
new_secret.id))
|
||||
# TBD: Generate URL...
|
||||
url = 'http://localhost:8080/%s/secrets/%s' % (tenant_id, new_secret.id)
|
||||
url = 'http://localhost:8080/%s/secrets/%s' % (tenant_id,
|
||||
new_secret.id)
|
||||
resp.body = json.dumps({'ref': url})
|
||||
|
||||
|
||||
@@ -161,17 +164,16 @@ class SecretResource(ApiResource):
|
||||
"""Handles Secret retrieval and deletion requests"""
|
||||
|
||||
def __init__(self, secret_repo=None):
|
||||
self.repo = secret_repo or SecretRepo()
|
||||
self.repo = secret_repo or SecretRepo()
|
||||
|
||||
def on_get(self, req, resp, tenant_id, secret_id):
|
||||
secret = self.repo.get(entity_id=secret_id)
|
||||
fields = secret.to_dict_fields()
|
||||
print 'read encrypted secret as %s' % fields['secret']
|
||||
LOG.debug('Read encrypted secret as %s' % fields['secret'])
|
||||
|
||||
# Decrypt fields
|
||||
decrypt(fields)
|
||||
secret_value = fields['secret']
|
||||
print 'decrypted secret is %s' % secret_value
|
||||
|
||||
resp.status = falcon.HTTP_200
|
||||
resp.body = json.dumps(fields, default=json_handler)
|
||||
@@ -182,7 +184,7 @@ class SecretResource(ApiResource):
|
||||
self.repo.delete_entity(secret)
|
||||
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
|
||||
class CSRsResource(ApiResource):
|
||||
"""Handles CSR (SSL certificate request) creation and lists requests"""
|
||||
@@ -197,16 +199,15 @@ class CSRsResource(ApiResource):
|
||||
tenant = self.tenant_repo.get(tenant_id)
|
||||
|
||||
body = load_body(req)
|
||||
# TBD: Remove:
|
||||
print 'Start on_post...%s' % body
|
||||
LOG.debug('Start on_post...%s' % body)
|
||||
requestor = body['requestor']
|
||||
# LOG.debug('Username is {0}'.format(username))
|
||||
print 'requestor is %s' % requestor
|
||||
LOG.debug('CSR requestor is %s' % requestor)
|
||||
|
||||
# TBD: What criteria to restrict multiple concurrent SSL requests per tenant?
|
||||
# csr = self.csr_repo.find_by_name(name=requestor, suppress_exception=True)
|
||||
#
|
||||
#if csr:
|
||||
# TBD: What criteria to restrict multiple concurrent SSL
|
||||
# requests per tenant?
|
||||
# csr = self.csr_repo.find_by_name(name=requestor,
|
||||
# suppress_exception=True)
|
||||
# if csr:
|
||||
# abort(falcon.HTTP_400, 'Tenant with username {0} '
|
||||
# 'already exists'.format(username))
|
||||
|
||||
@@ -217,14 +218,12 @@ class CSRsResource(ApiResource):
|
||||
new_csr.tenant_id = tenant.id
|
||||
self.csr_repo.create_from(new_csr)
|
||||
|
||||
# TBD: Remove:
|
||||
print '...post create from'
|
||||
|
||||
# Send to workers to process.
|
||||
self.queue.send(StartCSRMessage(new_csr.id))
|
||||
|
||||
resp.status = falcon.HTTP_202
|
||||
resp.set_header('Location', '/{0}/csrs/{1}'.format(tenant_id, new_csr.id))
|
||||
resp.set_header('Location', '/{0}/csrs/{1}'.format(tenant_id,
|
||||
new_csr.id))
|
||||
# TBD: Generate URL...
|
||||
url = 'http://localhost:8080/%s/csrs/%s' % (tenant_id, new_csr.id)
|
||||
resp.body = json.dumps({'ref': url})
|
||||
@@ -234,13 +233,13 @@ class CSRResource(ApiResource):
|
||||
"""Handles CSR retrieval and deletion requests"""
|
||||
|
||||
def __init__(self, csr_repo=None):
|
||||
self.repo = csr_repo or CSRRepo()
|
||||
self.repo = csr_repo or CSRRepo()
|
||||
|
||||
def on_get(self, req, resp, tenant_id, csr_id):
|
||||
csr = self.repo.get(entity_id=csr_id)
|
||||
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
resp.body = json.dumps(csr.to_dict_fields(), default=json_handler)
|
||||
|
||||
def on_delete(self, req, resp, tenant_id, csr_id):
|
||||
@@ -249,7 +248,7 @@ class CSRResource(ApiResource):
|
||||
self.repo.delete_entity(csr)
|
||||
|
||||
resp.status = falcon.HTTP_200
|
||||
|
||||
|
||||
|
||||
class CertificatesResource(ApiResource):
|
||||
"""Handles Certs (SSL certificates) lists per Tenant requests"""
|
||||
@@ -260,22 +259,22 @@ class CertificatesResource(ApiResource):
|
||||
|
||||
def on_post(self, req, resp, tenant_id):
|
||||
resp.status = falcon.HTTP_405
|
||||
# TBD: I18n this!
|
||||
msg = u"To create SSL certificates, you must first issue a CSR."
|
||||
msg = _("To create SSL certificates, you must first issue a CSR.")
|
||||
abort(falcon.HTTP_405, msg)
|
||||
|
||||
|
||||
class CertificateResource(ApiResource):
|
||||
"""Handles Cert (SSL certificates) retrieval and deletion requests"""
|
||||
|
||||
def __init__(self, cert_repo=None):
|
||||
self.repo = cert_repo or CertificateRepo()
|
||||
self.repo = cert_repo or CertificateRepo()
|
||||
|
||||
def on_get(self, req, resp, tenant_id, cert_id):
|
||||
cert = self.repo.get(entity_id=cert_id)
|
||||
|
||||
resp.status = falcon.HTTP_200
|
||||
resp.body = json.dumps(cert.to_dict_fields(), default=json_handler)
|
||||
|
||||
resp.body = json.dumps(cert.to_dict_fields(), default=json_handler)
|
||||
|
||||
def on_delete(self, req, resp, tenant_id, cert_id):
|
||||
cert = self.repo.get(entity_id=cert_id)
|
||||
|
||||
|
||||
@@ -15,4 +15,4 @@
|
||||
|
||||
"""
|
||||
Modules shared across other Barbican modules.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -20,12 +20,10 @@ Configuration setup for Barbican.
|
||||
|
||||
import os
|
||||
from oslo.config import cfg
|
||||
from barbican.openstack.common import log
|
||||
|
||||
# Ensure the local python config path is on the list to pull config info from
|
||||
CONF_FILES = cfg.find_config_files(prog='barbican-api')
|
||||
print ">>>>>>> "
|
||||
print CONF_FILES
|
||||
|
||||
#CONF_FILES = cfg.find_config_files(project='barbican', prog='barbican-api')
|
||||
CONF_FILES.append('./etc/barbican-api.conf')
|
||||
CONF_FILES.append('../etc/barbican-api.conf')
|
||||
@@ -34,4 +32,3 @@ CONF_FILES = [cfile for cfile in CONF_FILES if os.path.isfile(cfile)]
|
||||
# Set configuration files
|
||||
CONF = cfg.CONF
|
||||
CONF(prog='barbican-api', default_config_files=CONF_FILES)
|
||||
#CONF(project='barbican', prog='barbican-api', default_config_files=CONF_FILES)
|
||||
|
||||
@@ -15,4 +15,4 @@
|
||||
|
||||
"""
|
||||
Encryption/decryption services for Barbican.
|
||||
"""
|
||||
"""
|
||||
|
||||
@@ -18,21 +18,24 @@ Field-level encryption/decryption.
|
||||
|
||||
These utilities are intended to be applied onto a dictionary of field
|
||||
value, independent of the entity type, as long as these fields match
|
||||
a list of protection-fields below.
|
||||
a list of protection-fields below.
|
||||
"""
|
||||
|
||||
|
||||
FIELDS_TO_PROTECT = ['secret','private_key','public_key']
|
||||
FIELDS_TO_PROTECT = ['secret', 'private_key', 'public_key']
|
||||
|
||||
|
||||
def encrypt_value(value):
|
||||
"""Encrypt the supplied value"""
|
||||
# TBD: Supply algorithm
|
||||
return value if value is None else '[encrypt-this]%s' % value
|
||||
|
||||
|
||||
def encrypt(fields):
|
||||
"""Encrypt in-place the data of any fields found in FIELDS_TO_PROTECT"""
|
||||
for key in (key for key in FIELDS_TO_PROTECT if key in fields):
|
||||
fields[key] = encrypt_value(fields[key])
|
||||
fields[key] = encrypt_value(fields[key])
|
||||
|
||||
|
||||
def decrypt_value(value):
|
||||
"""Decrypt the supplied value"""
|
||||
@@ -42,7 +45,8 @@ def decrypt_value(value):
|
||||
prefix = '[encrypt-this]'
|
||||
return value[len(prefix):] if value.startswith(prefix) else value
|
||||
|
||||
|
||||
def decrypt(fields):
|
||||
"""Decrypt in-place the data of any fields found in FIELDS_TO_PROTECT"""
|
||||
for key in (key for key in FIELDS_TO_PROTECT if key in fields):
|
||||
fields[key] = decrypt_value(fields[key])
|
||||
fields[key] = decrypt_value(fields[key])
|
||||
|
||||
@@ -11,4 +11,4 @@
|
||||
# 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.
|
||||
# limitations under the License.
|
||||
|
||||
@@ -27,14 +27,18 @@ from sqlalchemy import Index, UniqueConstraint
|
||||
|
||||
from barbican.openstack.common import timeutils
|
||||
from barbican.openstack.common import uuidutils
|
||||
import barbican.openstack.common.log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
BASE = declarative_base()
|
||||
|
||||
|
||||
# Allowed entity states
|
||||
class States(object):
|
||||
PENDING = 'PENDING'
|
||||
ACTIVE = 'ACTIVE'
|
||||
|
||||
|
||||
@compiles(BigInteger, 'sqlite')
|
||||
def compile_big_int_sqlite(type_, compiler, **kw):
|
||||
return 'INTEGER'
|
||||
@@ -71,7 +75,7 @@ class ModelBase(object):
|
||||
import barbican.model.repositories
|
||||
session = session or barbican.model.repositories.get_session()
|
||||
session.delete(self)
|
||||
|
||||
|
||||
# TBD: Soft delete instead?
|
||||
# self.deleted = True
|
||||
# self.deleted_at = timeutils.utcnow()
|
||||
@@ -110,109 +114,109 @@ class ModelBase(object):
|
||||
|
||||
def to_dict_fields(self):
|
||||
"""Returns a dictionary of just the db fields of this entity."""
|
||||
dict_fields = {'id':self.id,
|
||||
'created':self.created_at,
|
||||
'updated':self.updated_at,
|
||||
'status':self.status}
|
||||
dict_fields = {'id': self.id,
|
||||
'created': self.created_at,
|
||||
'updated': self.updated_at,
|
||||
'status': self.status}
|
||||
if self.deleted_at:
|
||||
dict_fields['deleted'] = self.deleted_at
|
||||
if self.deleted:
|
||||
dict_fields['is_deleted'] = True
|
||||
dict_fields.update(self._do_extra_dict_fields())
|
||||
return dict_fields
|
||||
|
||||
|
||||
def _do_extra_dict_fields(self):
|
||||
"""Sub-class hook method: return dict of fields."""
|
||||
return {}
|
||||
|
||||
|
||||
|
||||
class Tenant(BASE, ModelBase):
|
||||
"""
|
||||
Represents a Tenant in the datastore
|
||||
|
||||
|
||||
Tenants are users that wish to store secret information within
|
||||
Cloudkeep's Barbican.
|
||||
"""
|
||||
|
||||
|
||||
__tablename__ = 'tenants'
|
||||
|
||||
username = Column(String(255))
|
||||
|
||||
|
||||
csrs = relationship("CSR")
|
||||
certificates = relationship("Certificate")
|
||||
|
||||
|
||||
def _do_extra_dict_fields(self):
|
||||
"""Sub-class hook method: return dict of fields."""
|
||||
return {'username':self.username}
|
||||
|
||||
return {'username': self.username}
|
||||
|
||||
|
||||
class Secret(BASE, ModelBase):
|
||||
"""
|
||||
Represents a Secret in the datastore
|
||||
|
||||
|
||||
Secrets are any information Tenants wish to store within
|
||||
Cloudkeep's Barbican.
|
||||
"""
|
||||
|
||||
|
||||
__tablename__ = 'secrets'
|
||||
|
||||
name = Column(String(255))
|
||||
secret = Column(Text)
|
||||
|
||||
|
||||
def _do_extra_dict_fields(self):
|
||||
"""Sub-class hook method: return dict of fields."""
|
||||
return {'name':self.name,
|
||||
'secret':self.secret}
|
||||
return {'name': self.name,
|
||||
'secret': self.secret}
|
||||
|
||||
|
||||
class CSR(BASE, ModelBase):
|
||||
"""
|
||||
Represents a CSR in the datastore
|
||||
|
||||
CSRs are requests to create SSL certificates, eventually sent to Certificate
|
||||
Authorities who generate these certificates.
|
||||
|
||||
CSRs are requests to create SSL certificates, eventually sent to
|
||||
Certificate Authorities who generate these certificates.
|
||||
"""
|
||||
|
||||
|
||||
__tablename__ = 'csrs'
|
||||
|
||||
tenant_id = Column(String(36), ForeignKey('tenants.id'),
|
||||
nullable=False)
|
||||
nullable=False)
|
||||
# tenant = relationship(Tenant, backref=backref('csr_assocs'))
|
||||
|
||||
requestor = Column(String(255))
|
||||
|
||||
|
||||
certificates = relationship("Certificate")
|
||||
|
||||
|
||||
def _do_extra_dict_fields(self):
|
||||
"""Sub-class hook method: return dict of fields."""
|
||||
return {'requestor':self.requestor, 'tenant_id':self.tenant_id}
|
||||
|
||||
return {'requestor': self.requestor, 'tenant_id': self.tenant_id}
|
||||
|
||||
|
||||
class Certificate(BASE, ModelBase):
|
||||
"""
|
||||
Represents an SSL Certificate in the datastore, generated by a CA on
|
||||
behalf of a Tenant.
|
||||
"""
|
||||
|
||||
|
||||
__tablename__ = 'certificates'
|
||||
|
||||
tenant_id = Column(String(36), ForeignKey('tenants.id'),
|
||||
nullable=False)
|
||||
nullable=False)
|
||||
# tenant = relationship(Tenant, backref=backref('certificate_assocs'))
|
||||
|
||||
csr_id = Column(String(36), ForeignKey('csrs.id'),
|
||||
nullable=False)
|
||||
nullable=False)
|
||||
# csr = relationship(CSR, backref=backref('certificates'))
|
||||
|
||||
private_key = Column(Text)
|
||||
public_key = Column(Text)
|
||||
|
||||
|
||||
def _do_extra_dict_fields(self):
|
||||
"""Sub-class hook method: return dict of fields."""
|
||||
return {'private_key':self.private_key,
|
||||
'public_key':self.public_key,
|
||||
'tenant_id':self.tenant_id,
|
||||
'csr_id':self.tenant_id}
|
||||
return {'private_key': self.private_key,
|
||||
'public_key': self.public_key,
|
||||
'tenant_id': self.tenant_id,
|
||||
'csr_id': self.tenant_id}
|
||||
|
||||
|
||||
# Keep this tuple synchronized with the models in the file
|
||||
@@ -223,8 +227,7 @@ def register_models(engine):
|
||||
"""
|
||||
Creates database tables for all models with the given engine
|
||||
"""
|
||||
# TBD: Remove this:
|
||||
print "models: %s" % `MODELS`
|
||||
LOG.debug("models: %s" % repr(MODELS))
|
||||
for model in MODELS:
|
||||
model.metadata.create_all(engine)
|
||||
|
||||
|
||||
@@ -19,8 +19,9 @@ TBD: The top part of this file was 'borrowed' from Glance, but seems
|
||||
quite intense for sqlalchemy, and maybe could be simplified.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
import time
|
||||
import logging
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
@@ -32,10 +33,11 @@ from barbican.common import exception
|
||||
from barbican.common import config
|
||||
# TBD: from barbican.db.sqlalchemy import migration
|
||||
from barbican.model import models
|
||||
import barbican.openstack.common.log as os_logging
|
||||
from barbican.openstack.common import timeutils
|
||||
from barbican.openstack.common.gettextutils import _
|
||||
import barbican.openstack.common.log as os_logging
|
||||
|
||||
LOG = os_logging.getLogger(__name__)
|
||||
|
||||
_ENGINE = None
|
||||
_MAKER = None
|
||||
@@ -43,7 +45,6 @@ _MAX_RETRIES = None
|
||||
_RETRY_INTERVAL = None
|
||||
BASE = models.BASE
|
||||
sa_logger = None
|
||||
LOG = os_logging.getLogger(__name__)
|
||||
|
||||
|
||||
STATUSES = ['active', 'saving', 'queued', 'killed', 'pending_delete',
|
||||
@@ -72,8 +73,7 @@ def setup_db_env():
|
||||
_MAX_RETRIES = CONF.sql_max_retries
|
||||
_RETRY_INTERVAL = CONF.sql_retry_interval
|
||||
_CONNECTION = CONF.sql_connection
|
||||
# TBD: Remove:
|
||||
print "Conn = %s" % _CONNECTION
|
||||
LOG.debug("Sql connection = %s" % _CONNECTION)
|
||||
sa_logger = logging.getLogger('sqlalchemy.engine')
|
||||
if CONF.debug:
|
||||
sa_logger.setLevel(logging.DEBUG)
|
||||
@@ -102,7 +102,7 @@ def get_session(autocommit=True, expire_on_commit=False):
|
||||
def get_engine():
|
||||
"""Return a SQLAlchemy engine."""
|
||||
"""May assign _ENGINE if not already assigned"""
|
||||
global _ENGINE, sa_logger, _CONNECTION, _IDLE_TIMEOUT, _MAX_RETRIES,\
|
||||
global _ENGINE, sa_logger, _CONNECTION, _IDLE_TIMEOUT, _MAX_RETRIES, \
|
||||
_RETRY_INTERVAL
|
||||
|
||||
if not _ENGINE:
|
||||
@@ -117,8 +117,8 @@ def get_engine():
|
||||
'convert_unicode': True}
|
||||
|
||||
try:
|
||||
# TBD: Remove
|
||||
print "Conn: %s; Args: %s" % (_CONNECTION, engine_args)
|
||||
LOG.debug("Sql connection: %s; Args: %s" % (_CONNECTION,
|
||||
engine_args))
|
||||
_ENGINE = sqlalchemy.create_engine(_CONNECTION, **engine_args)
|
||||
|
||||
# TBD: if 'mysql' in connection_dict.drivername:
|
||||
@@ -191,8 +191,8 @@ def wrap_db_error(f):
|
||||
try:
|
||||
return f(*args, **kwargs)
|
||||
except sqlalchemy.exc.OperationalError as e:
|
||||
if (remaining_attempts == 0 or
|
||||
not is_db_connection_error(e.args[0])):
|
||||
if (remaining_attempts == 0 or not
|
||||
is_db_connection_error(e.args[0])):
|
||||
raise
|
||||
except sqlalchemy.exc.DBAPIError:
|
||||
raise
|
||||
@@ -205,57 +205,57 @@ def wrap_db_error(f):
|
||||
class BaseRepo(object):
|
||||
"""
|
||||
Base repository for the barbican entities.
|
||||
|
||||
|
||||
This class provides template methods that allow sub-classes to hook
|
||||
specific functionality as needed.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
print "BaseRepo"
|
||||
LOG.debug("BaseRepo init...")
|
||||
configure_db()
|
||||
|
||||
configure_db()
|
||||
|
||||
def get_session(self, session=None):
|
||||
print "Getting session..."
|
||||
LOG.debug("Getting session...")
|
||||
return session or get_session()
|
||||
|
||||
|
||||
def find_by_name(self, name, suppress_exception=False, session=None):
|
||||
session = self.get_session(session)
|
||||
|
||||
|
||||
try:
|
||||
print "Starting find by name steps..."
|
||||
LOG.debug("Starting find by name steps...")
|
||||
query = self._do_build_query_by_name(name, session)
|
||||
print "...query = %s" % `query`
|
||||
LOG.debug("...query = %s" % repr(query))
|
||||
entity = query.one()
|
||||
print "...post query.one()"
|
||||
|
||||
LOG.debug("...post query.one()")
|
||||
|
||||
except sa_orm.exc.NoResultFound:
|
||||
entity = None
|
||||
if not suppress_exception:
|
||||
raise exception.NotFound("No %s found with name %s"
|
||||
% (self._do_entity_name(), name))
|
||||
|
||||
|
||||
return entity
|
||||
|
||||
def get(self, entity_id, force_show_deleted=False, suppress_exception=False, session=None):
|
||||
|
||||
def get(self, entity_id, force_show_deleted=False,
|
||||
suppress_exception=False, session=None):
|
||||
"""Get an entity or raise if it does not exist."""
|
||||
session = self.get_session(session)
|
||||
|
||||
|
||||
try:
|
||||
query = self._do_build_get_query(entity_id, session)
|
||||
|
||||
|
||||
# filter out deleted entities if requested
|
||||
if not force_show_deleted:
|
||||
query = query.filter_by(deleted=False)
|
||||
|
||||
|
||||
entity = query.one()
|
||||
|
||||
|
||||
except sa_orm.exc.NoResultFound:
|
||||
entity = None
|
||||
if not suppress_exception:
|
||||
raise exception.NotFound("No %s found with ID %s"
|
||||
% (self._do_entity_name(), entity_id))
|
||||
|
||||
|
||||
return entity
|
||||
|
||||
def create(self, values):
|
||||
@@ -264,57 +264,59 @@ class BaseRepo(object):
|
||||
|
||||
def create_from(self, entity):
|
||||
"""Sub-class hook: create from Tenant entity."""
|
||||
|
||||
|
||||
if not entity:
|
||||
msg = "Must supply non-None %s." % self._do_entity_name
|
||||
raise exception.Invalid(msg)
|
||||
|
||||
raise exception.Invalid(msg)
|
||||
|
||||
if entity.id:
|
||||
msg = "Must supply %s with id=None(i.e. new entity)." % self._do_entity_name
|
||||
raise exception.Invalid(msg)
|
||||
|
||||
print "Begin create from..."
|
||||
|
||||
LOG.debug("Begin create from...")
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
|
||||
|
||||
# Validate the attributes before we go any further. From my
|
||||
# (unknown Glance developer) investigation, the @validates
|
||||
# decorator does not validate
|
||||
# on new records, only on existing records, which is, well,
|
||||
# idiotic.
|
||||
values = self._do_validate(entity.to_dict())
|
||||
|
||||
|
||||
try:
|
||||
print "Saving entity..."
|
||||
LOG.debug("Saving entity...")
|
||||
entity.save(session=session)
|
||||
except sqlalchemy.exc.IntegrityError:
|
||||
raise exception.Duplicate("Entity ID %s already exists!"
|
||||
% values['id'])
|
||||
|
||||
|
||||
return self.get(entity.id)
|
||||
|
||||
def update(self, entity_id, values, purge_props=False):
|
||||
"""
|
||||
Set the given properties on an entity and update it.
|
||||
|
||||
|
||||
:raises NotFound if entity does not exist.
|
||||
"""
|
||||
return self._update(values, entity_id, purge_props)
|
||||
|
||||
def delete_entity(self, entity):
|
||||
"""Remove the entity"""
|
||||
|
||||
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
entity.delete(session=session)
|
||||
|
||||
def _do_entity_name(self):
|
||||
"""Sub-class hook: return entity name, such as for debugging."""
|
||||
return "Entity"
|
||||
return "Entity"
|
||||
|
||||
def _do_create_instance(self):
|
||||
"""Sub-class hook: return new entity instance (in Python, not in db)."""
|
||||
return None
|
||||
"""
|
||||
Sub-class hook: return new entity instance (in Python, not in db).
|
||||
"""
|
||||
return None
|
||||
|
||||
def _do_build_query_by_name(self, name, session):
|
||||
"""Sub-class hook: find entity by name."""
|
||||
@@ -325,16 +327,19 @@ class BaseRepo(object):
|
||||
return None
|
||||
|
||||
def _do_convert_values(self, values):
|
||||
"""Sub-class hook: convert text-based values to target types for the database."""
|
||||
"""
|
||||
Sub-class hook: convert text-based values to
|
||||
target types for the database.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _do_validate(self, values):
|
||||
"""
|
||||
Sub-class hook: validate values.
|
||||
|
||||
|
||||
Validates the incoming data and raises a Invalid exception
|
||||
if anything is out of order.
|
||||
|
||||
|
||||
:param values: Mapping of entity metadata to check
|
||||
"""
|
||||
status = values.get('status', None)
|
||||
@@ -342,37 +347,38 @@ class BaseRepo(object):
|
||||
# TBD: I18n this!
|
||||
msg = "%s status is required." % self._do_entity_name()
|
||||
raise exception.Invalid(msg)
|
||||
|
||||
|
||||
if status not in STATUSES:
|
||||
msg = "Invalid status '%s' for %s." % (status, self._do_entity_name())
|
||||
msg = "Invalid status '%s' for %s." % (status,
|
||||
self._do_entity_name())
|
||||
raise exception.Invalid(msg)
|
||||
|
||||
|
||||
return values
|
||||
|
||||
def _update(values, entity_id, purge_props=False):
|
||||
"""
|
||||
Used internally by create() and update()
|
||||
|
||||
|
||||
:param values: A dict of attributes to set
|
||||
:param entity_id: If None, create the entity, otherwise,
|
||||
find and update it
|
||||
"""
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
|
||||
|
||||
if entity_id:
|
||||
entity_ref = self._do_get(entity_id, session=session)
|
||||
values['updated_at'] = timeutils.utcnow()
|
||||
else:
|
||||
self._do_convert_values(values)
|
||||
entity_ref = self._do_create_instance()
|
||||
|
||||
|
||||
# Need to canonicalize ownership
|
||||
if 'owner' in values and not values['owner']:
|
||||
values['owner'] = None
|
||||
|
||||
|
||||
entity_ref.update(values)
|
||||
|
||||
|
||||
# Validate the attributes before we go any further. From my
|
||||
# (unknown Glance developer) investigation, the @validates
|
||||
# decorator does not validate
|
||||
@@ -380,13 +386,13 @@ class BaseRepo(object):
|
||||
# idiotic.
|
||||
values = self._do_validate(entity_ref.to_dict())
|
||||
self._update_values(entity_ref, values)
|
||||
|
||||
|
||||
try:
|
||||
entity_ref.save(session=session)
|
||||
except sqlalchemy.exc.IntegrityError:
|
||||
raise exception.Duplicate("Entity ID %s already exists!"
|
||||
% values['id'])
|
||||
|
||||
|
||||
return self.get(entity_ref.id)
|
||||
|
||||
def _update_values(entity_ref, values):
|
||||
@@ -400,20 +406,18 @@ class TenantRepo(BaseRepo):
|
||||
|
||||
def _do_entity_name(self):
|
||||
"""Sub-class hook: return entity name, such as for debugging."""
|
||||
return "Tenant"
|
||||
return "Tenant"
|
||||
|
||||
def _do_create_instance(self):
|
||||
return models.Tenant()
|
||||
|
||||
def _do_build_query_by_name(self, name, session):
|
||||
"""Sub-class hook: find entity by name."""
|
||||
return session.query(models.Tenant)\
|
||||
.filter_by(username=name)
|
||||
return session.query(models.Tenant).filter_by(username=name)
|
||||
|
||||
def _do_build_get_query(self, entity_id, session):
|
||||
"""Sub-class hook: build a retrieve query."""
|
||||
return session.query(models.Tenant)\
|
||||
.filter_by(id=entity_id)
|
||||
return session.query(models.Tenant).filter_by(id=entity_id)
|
||||
|
||||
def _do_validate(self, values):
|
||||
"""Sub-class hook: validate values."""
|
||||
@@ -425,20 +429,18 @@ class SecretRepo(BaseRepo):
|
||||
|
||||
def _do_entity_name(self):
|
||||
"""Sub-class hook: return entity name, such as for debugging."""
|
||||
return "Secret"
|
||||
return "Secret"
|
||||
|
||||
def _do_create_instance(self):
|
||||
return models.Secret()
|
||||
|
||||
def _do_build_query_by_name(self, name, session):
|
||||
"""Sub-class hook: find entity by name."""
|
||||
return session.query(models.Secret)\
|
||||
.filter_by(name=name)
|
||||
return session.query(models.Secret).filter_by(name=name)
|
||||
|
||||
def _do_build_get_query(self, entity_id, session):
|
||||
"""Sub-class hook: build a retrieve query."""
|
||||
return session.query(models.Secret)\
|
||||
.filter_by(id=entity_id)
|
||||
return session.query(models.Secret).filter_by(id=entity_id)
|
||||
|
||||
def _do_validate(self, values):
|
||||
"""Sub-class hook: validate values."""
|
||||
@@ -450,7 +452,7 @@ class CSRRepo(BaseRepo):
|
||||
|
||||
def _do_entity_name(self):
|
||||
"""Sub-class hook: return entity name, such as for debugging."""
|
||||
return "CSR"
|
||||
return "CSR"
|
||||
|
||||
def _do_create_instance(self):
|
||||
return models.CSR()
|
||||
@@ -461,8 +463,7 @@ class CSRRepo(BaseRepo):
|
||||
|
||||
def _do_build_get_query(self, entity_id, session):
|
||||
"""Sub-class hook: build a retrieve query."""
|
||||
return session.query(models.CSR)\
|
||||
.filter_by(id=entity_id)
|
||||
return session.query(models.CSR).filter_by(id=entity_id)
|
||||
|
||||
def _do_validate(self, values):
|
||||
"""Sub-class hook: validate values."""
|
||||
@@ -474,19 +475,19 @@ class CertificateRepo(BaseRepo):
|
||||
|
||||
def _do_entity_name(self):
|
||||
"""Sub-class hook: return entity name, such as for debugging."""
|
||||
return "Certificate"
|
||||
return "Certificate"
|
||||
|
||||
def _do_create_instance(self):
|
||||
return models.Certificate()
|
||||
|
||||
def _do_build_query_by_name(self, name, session):
|
||||
"""Sub-class hook: find entity by name."""
|
||||
raise TypeError(_("No support for retrieving by 'name' a Certificate record."))
|
||||
raise TypeError(_("No support for retrieving by "
|
||||
"'name' a Certificate record."))
|
||||
|
||||
def _do_build_get_query(self, entity_id, session):
|
||||
"""Sub-class hook: build a retrieve query."""
|
||||
return session.query(models.Certificate)\
|
||||
.filter_by(id=entity_id)
|
||||
return session.query(models.Certificate).filter_by(id=entity_id)
|
||||
|
||||
def _do_validate(self, values):
|
||||
"""Sub-class hook: validate values."""
|
||||
|
||||
@@ -27,4 +27,4 @@ queue_opts = [
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(queue_opts, group='queue')
|
||||
CONF.register_opts(queue_opts, group='queue')
|
||||
|
||||
@@ -22,6 +22,7 @@ from barbican.openstack.common import importutils
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def get_queue_api():
|
||||
return importutils.import_module(CONF.queue.queue_api)
|
||||
|
||||
@@ -35,10 +36,9 @@ class StartCSRMessage(object):
|
||||
|
||||
class QueueResource(object):
|
||||
"""Handles Queue related requests"""
|
||||
|
||||
|
||||
def __init__(self, queue_api=None):
|
||||
self.api = queue_api or get_queue_api()
|
||||
|
||||
def send(self, message):
|
||||
self.api.send(message)
|
||||
|
||||
@@ -18,7 +18,11 @@ Simple Queue API implementation.
|
||||
"""
|
||||
from barbican.worker.resources import WorkerResource
|
||||
|
||||
|
||||
def send(message):
|
||||
"""Handle the specified message by simply passing through to the Worker Resource."""
|
||||
"""
|
||||
Handle the specified message by simply passing through to the
|
||||
Worker Resource.
|
||||
"""
|
||||
worker = WorkerResource()
|
||||
worker.receive(message)
|
||||
worker.receive(message)
|
||||
|
||||
@@ -1 +1,16 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
__author__ = 'john.wood'
|
||||
|
||||
@@ -1 +1,16 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
__author__ = 'john.wood'
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from datetime import datetime
|
||||
from barbican.api.resources import *
|
||||
from barbican.model.models import *
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
__author__ = 'john.wood'
|
||||
@@ -1,3 +1,19 @@
|
||||
# Copyright (c) 2013 Rackspace, Inc.
|
||||
#
|
||||
# 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 unittest
|
||||
|
||||
@@ -21,6 +37,7 @@ CONF = cfg.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def suite():
|
||||
suite = unittest.TestSuite()
|
||||
suite.addTest(WhenConfiguring())
|
||||
|
||||
@@ -22,15 +22,16 @@ from barbican.openstack.common import importutils
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def get_worker_api():
|
||||
return importutils.import_module(CONF.worker.worker_api)
|
||||
|
||||
|
||||
class WorkerResource(object):
|
||||
"""Handles Queue related requests"""
|
||||
|
||||
|
||||
def __init__(self, worker_api=None):
|
||||
self.api = worker_api or get_worker_api()
|
||||
self.api = worker_api or get_worker_api()
|
||||
|
||||
def receive(self, message):
|
||||
self.api.process(message)
|
||||
|
||||
|
||||
@@ -17,18 +17,25 @@
|
||||
Simple Worker API implementation.
|
||||
"""
|
||||
from barbican.queue.resources import StartCSRMessage
|
||||
import barbican.openstack.common.log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StartCSRProcessor(object):
|
||||
"""Process the start of CSR processing."""
|
||||
|
||||
|
||||
def process(self, message):
|
||||
print "Processing CSR with ID = ", message.csr_id
|
||||
LOG.debug("Processing CSR with ID = ", message.csr_id)
|
||||
|
||||
|
||||
PROCESSES = {StartCSRMessage : StartCSRProcessor()}
|
||||
PROCESSES = {StartCSRMessage: StartCSRProcessor()}
|
||||
|
||||
|
||||
def process(message):
|
||||
"""Handle the specified message but simply passing through to the Worker Resource."""
|
||||
"""
|
||||
Handle the specified message but simply passing
|
||||
through to the Worker Resource.
|
||||
"""
|
||||
processor = PROCESSES[message.__class__]
|
||||
processor.process(message)
|
||||
processor.process(message)
|
||||
|
||||
Reference in New Issue
Block a user