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.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.queue.resources import QueueResource, StartCSRMessage
from barbican.common import config
LOG = logging.getLogger(__name__)
@ -54,9 +55,11 @@ class TenantsResource(ApiResource):
if tenant:
abort(falcon.HTTP_400, 'Tenant with username {0} '
'already exists'.format(username))
# TBD: Encrypte fields
new_tenant = Tenant()
new_tenant.username = username
new_tenant.status = States.ACTIVE
self.repo.create_from(new_tenant)
print '...post create from'
@ -91,9 +94,10 @@ class TenantResource(ApiResource):
class CSRsResource(ApiResource):
"""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')
self.repo = csr_repo or CSRRepo()
self.queue = queue_resource or QueueResource()
def on_post(self, req, resp, tenent_id):
body = load_body(req)
@ -110,6 +114,8 @@ class CSRsResource(ApiResource):
# abort(falcon.HTTP_400, 'Tenant with username {0} '
# 'already exists'.format(username))
# TBD: Encrypt fields
new_csr = CSR()
new_csr.requestor = requestor
self.repo.create_from(new_csr)
@ -117,10 +123,13 @@ class CSRsResource(ApiResource):
# TBD: Remove:
print '...post create from'
resp.status = falcon.HTTP_201
resp.set_header('Location', '/{0}'.format(new_csr.id))
# 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(tenent_id, new_csr.id))
# 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})
@ -134,6 +143,7 @@ class CSRResource(ApiResource):
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, tenent_id, csr_id):

View File

@ -30,6 +30,10 @@ from barbican.openstack.common import uuidutils
BASE = declarative_base()
# Allowed entity states
class States(object):
PENDING = 'PENDING'
ACTIVE = 'ACTIVE'
@compiles(BigInteger, 'sqlite')
def compile_big_int_sqlite(type_, compiler, **kw):
@ -52,6 +56,8 @@ class ModelBase(object):
deleted_at = Column(DateTime)
deleted = Column(Boolean, nullable=False, default=False)
status = Column(String(20), nullable=False, default=States.PENDING)
def save(self, session=None):
"""Save this object"""
# 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."""
dict_fields = {'id':self.id,
'created':self.created_at,
'updated':self.updated_at}
'updated':self.updated_at,
'status':self.status}
if self.deleted_at:
dict_fields['deleted'] = self.deleted_at
if self.deleted:
@ -146,11 +153,15 @@ class CSR(BASE, ModelBase):
__tablename__ = 'csrs'
tenant_id = Column(String(36), ForeignKey('tenants.id'),
nullable=False)
tenant = relationship(Tenant, backref=backref('csrs'))
requestor = Column(String(255))
def _do_extra_dict_fields(self):
"""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):
@ -161,12 +172,23 @@ class Certificate(BASE, ModelBase):
__tablename__ = 'certificates'
private_key = Column(String(255))
public_key = Column(String(255))
tenant_id = Column(String(36), ForeignKey('tenants.id'),
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):
"""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

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)