Added initial worker and queue modules, more work to go...

This commit is contained in:
John Wood 2013-04-13 15:28:13 -05:00
parent dd69458b72
commit 1dd058eb4c
8 changed files with 231 additions and 10 deletions

View File

@ -4,8 +4,9 @@ import logging
from barbican.version import __version__ from barbican.version import __version__
from barbican.api import ApiResource, load_body, abort from barbican.api import ApiResource, load_body, abort
from barbican.model.models import Tenant from barbican.model.models import Tenant, States
from barbican.model.repositories import TenantRepo from barbican.model.repositories import TenantRepo
from barbican.queue.resources import QueueResource, StartCSRMessage
from barbican.common import config from barbican.common import config
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -54,9 +55,11 @@ class TenantsResource(ApiResource):
if tenant: if tenant:
abort(falcon.HTTP_400, 'Tenant with username {0} ' abort(falcon.HTTP_400, 'Tenant with username {0} '
'already exists'.format(username)) 'already exists'.format(username))
# TBD: Encrypte fields
new_tenant = Tenant() new_tenant = Tenant()
new_tenant.username = username new_tenant.username = username
new_tenant.status = States.ACTIVE
self.repo.create_from(new_tenant) self.repo.create_from(new_tenant)
print '...post create from' print '...post create from'
@ -91,9 +94,10 @@ class TenantResource(ApiResource):
class CSRsResource(ApiResource): class CSRsResource(ApiResource):
"""Handles CSR (SSL certificate request) creation and lists requests""" """Handles CSR (SSL certificate request) creation and lists requests"""
def __init__(self, csr_repo=None): def __init__(self, csr_repo=None, queue_resource=None):
LOG.debug('Creating CSRsResource') LOG.debug('Creating CSRsResource')
self.repo = csr_repo or CSRRepo() self.repo = csr_repo or CSRRepo()
self.queue = queue_resource or QueueResource()
def on_post(self, req, resp, tenent_id): def on_post(self, req, resp, tenent_id):
body = load_body(req) body = load_body(req)
@ -110,6 +114,8 @@ class CSRsResource(ApiResource):
# abort(falcon.HTTP_400, 'Tenant with username {0} ' # abort(falcon.HTTP_400, 'Tenant with username {0} '
# 'already exists'.format(username)) # 'already exists'.format(username))
# TBD: Encrypt fields
new_csr = CSR() new_csr = CSR()
new_csr.requestor = requestor new_csr.requestor = requestor
self.repo.create_from(new_csr) self.repo.create_from(new_csr)
@ -117,10 +123,13 @@ class CSRsResource(ApiResource):
# TBD: Remove: # TBD: Remove:
print '...post create from' print '...post create from'
resp.status = falcon.HTTP_201 # Send to workers to process.
resp.set_header('Location', '/{0}'.format(new_csr.id)) self.queue.send(StartCSRMessage(new_csr.id))
resp.status = falcon.HTTP_202
resp.set_header('Location', '/{0}/csrs/{1}'.format(tenent_id, new_csr.id))
# TBD: Generate URL... # TBD: Generate URL...
url = 'http://localhost:8080:/csrs/%s' % new_csr.id url = 'http://localhost:8080:/%s/csrs/%s' % (tenent_id, new_csr.id)
resp.body = json.dumps({'ref': url}) resp.body = json.dumps({'ref': url})
@ -134,6 +143,7 @@ class CSRResource(ApiResource):
csr = self.repo.get(entity_id=csr_id) csr = self.repo.get(entity_id=csr_id)
resp.status = falcon.HTTP_200 resp.status = falcon.HTTP_200
resp.body = json.dumps(csr.to_dict_fields(), default=json_handler) resp.body = json.dumps(csr.to_dict_fields(), default=json_handler)
def on_delete(self, req, resp, tenent_id, csr_id): def on_delete(self, req, resp, tenent_id, csr_id):

View File

@ -30,6 +30,10 @@ from barbican.openstack.common import uuidutils
BASE = declarative_base() BASE = declarative_base()
# Allowed entity states
class States(object):
PENDING = 'PENDING'
ACTIVE = 'ACTIVE'
@compiles(BigInteger, 'sqlite') @compiles(BigInteger, 'sqlite')
def compile_big_int_sqlite(type_, compiler, **kw): def compile_big_int_sqlite(type_, compiler, **kw):
@ -52,6 +56,8 @@ class ModelBase(object):
deleted_at = Column(DateTime) deleted_at = Column(DateTime)
deleted = Column(Boolean, nullable=False, default=False) deleted = Column(Boolean, nullable=False, default=False)
status = Column(String(20), nullable=False, default=States.PENDING)
def save(self, session=None): def save(self, session=None):
"""Save this object""" """Save this object"""
# import api here to prevent circular dependency problem # import api here to prevent circular dependency problem
@ -106,7 +112,8 @@ class ModelBase(object):
"""Returns a dictionary of just the db fields of this entity.""" """Returns a dictionary of just the db fields of this entity."""
dict_fields = {'id':self.id, dict_fields = {'id':self.id,
'created':self.created_at, 'created':self.created_at,
'updated':self.updated_at} 'updated':self.updated_at,
'status':self.status}
if self.deleted_at: if self.deleted_at:
dict_fields['deleted'] = self.deleted_at dict_fields['deleted'] = self.deleted_at
if self.deleted: if self.deleted:
@ -146,11 +153,15 @@ class CSR(BASE, ModelBase):
__tablename__ = 'csrs' __tablename__ = 'csrs'
tenant_id = Column(String(36), ForeignKey('tenants.id'),
nullable=False)
tenant = relationship(Tenant, backref=backref('csrs'))
requestor = Column(String(255)) requestor = Column(String(255))
def _do_extra_dict_fields(self): def _do_extra_dict_fields(self):
"""Sub-class hook method: return dict of fields.""" """Sub-class hook method: return dict of fields."""
return {'requestor':self.requestor} return {'requestor':self.requestor, 'tenant_id':self.tenant_id}
class Certificate(BASE, ModelBase): class Certificate(BASE, ModelBase):
@ -161,12 +172,23 @@ class Certificate(BASE, ModelBase):
__tablename__ = 'certificates' __tablename__ = 'certificates'
private_key = Column(String(255)) tenant_id = Column(String(36), ForeignKey('tenants.id'),
public_key = Column(String(255)) nullable=False)
tenant = relationship(Tenant, backref=backref('certificates'))
csr_id = Column(String(36), ForeignKey('csrs.id'),
nullable=False)
csr= relationship(CSR, backref=backref('certificates'))
private_key = Column(Text)
public_key = Column(Text)
def _do_extra_dict_fields(self): def _do_extra_dict_fields(self):
"""Sub-class hook method: return dict of fields.""" """Sub-class hook method: return dict of fields."""
return {'private_key':self.private_key, 'public_key':self.public_key} 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 # Keep this tuple synchronized with the models in the file

View File

@ -0,0 +1,29 @@
# 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.
"""
Queue objects for Cloudkeep's Barbican
"""
from oslo.config import cfg
from barbican.common import config
queue_opts = [
cfg.StrOpt('queue_api', default='barbican.queue.simple',
help=_('Python module path of queue implementation API')),
]
CONF = cfg.CONF
CONF.register_opts(queue_opts, group='queue')

View File

@ -0,0 +1,43 @@
# 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.
"""
Queue Resources related objects and functions.
"""
from oslo.config import cfg
CONF = cfg.CONF
def get_queue_api():
return importutils.import_module(CONF.queue_api)
class StartCSRMessage(object):
"""Message to start the CSR process"""
def __init__(self, csr_id):
self.csr_id = csr_id
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)

24
barbican/queue/simple.py Normal file
View File

@ -0,0 +1,24 @@
# 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.
"""
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."""
worker = WorkerResource()
worker.receive(message)

View File

@ -0,0 +1,29 @@
# 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.
"""
Worker objects for Cloudkeep's Barbican
"""
from oslo.config import cfg
from barbican.common import config
worker_opts = [
cfg.StrOpt('worker_api', default='barbican.worker.simple',
help=_('Python module path of worker implementation API')),
]
CONF = cfg.CONF
CONF.register_opts(worker_opts, group='worker')

View File

@ -0,0 +1,35 @@
# 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.
"""
Queue Resources related objects and functions.
"""
from oslo.config import cfg
CONF = cfg.CONF
def get_worker_api():
return importutils.import_module(CONF.worker_api)
class WorkerResource(object):
"""Handles Queue related requests"""
def __init__(self, worker_api=None):
self.api = worker_api or get_worker_api()
def receive(self, message):
self.api.process(message)

29
barbican/worker/simple.py Normal file
View File

@ -0,0 +1,29 @@
# 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.
"""
Simple Worker API implementation.
"""
from barbican.queue.resources import StartCSRMessage
class StartCSRProcessor(object):
print "Processing CSR with ID = ", csr_id
PROCESSES = {StartCSRMessage : StartCSRProcessor()}
def process(message):
"""Handle the specified message but simply passing through to the Worker Resource."""
processor = PROCESSES[message.__class__]
processor.process(message)