
This patchset adds one new method to the partitions API - PATCH /v1/partitions/{partition} The partitions storage layer is also updated to support a simpler update interface: - update(self, name, **kwargs) [with kwargs in ('hosts', 'weight')] The partitions transport layer is cleared of cruft and reuses JSON handling utilities from the queues transport layer. This patch implementation uses jsonschema to achieve self-documenting, strict format validation of the incoming input. The partition storage controllers are modified accordingly, as are the tests. More tests are added for the partitions transport layer to verify the correctness and to ease future refactorings. Change-Id: Ifa92b1225421196f95131c2b74e3c07b07c4cfd4 Implements: blueprint placement-service Closes-Bug: 1230841
104 lines
3.0 KiB
Python
104 lines
3.0 KiB
Python
# Copyright (c) 2013 Rackspace Hosting, 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.
|
|
|
|
"""MongoDB storage controller for proxy partitions.
|
|
|
|
Schema:
|
|
|
|
{
|
|
'n': Name :: str
|
|
'h': [Host_url :: str],
|
|
'w': Weight :: int,
|
|
}
|
|
"""
|
|
|
|
from marconi.proxy.storage import base
|
|
from marconi.proxy.storage import exceptions
|
|
from marconi.queues.storage.mongodb import utils
|
|
|
|
PARTITIONS_INDEX = [
|
|
('n', 1)
|
|
]
|
|
|
|
|
|
class PartitionsController(base.PartitionsBase):
|
|
def __init__(self, *args, **kwargs):
|
|
super(PartitionsController, self).__init__(*args, **kwargs)
|
|
|
|
self._col = self.driver.db['partitions']
|
|
self._col.ensure_index(PARTITIONS_INDEX, unique=True)
|
|
|
|
@utils.raises_conn_error
|
|
def list(self):
|
|
cursor = self._col.find(fields={'n': 1, 'h': 1, 'w': 1, '_id': 0})
|
|
|
|
for entry in cursor:
|
|
yield _normalize(entry)
|
|
|
|
@utils.raises_conn_error
|
|
def get(self, name):
|
|
fields = {'n': 1, 'w': 1, 'h': 1, '_id': 0}
|
|
partition = self._col.find_one({'n': name},
|
|
fields=fields)
|
|
|
|
if partition is None:
|
|
raise exceptions.PartitionNotFound(name)
|
|
|
|
return _normalize(partition)
|
|
|
|
@utils.raises_conn_error
|
|
def exists(self, name):
|
|
try:
|
|
next(self._col.find({'n': name}))
|
|
except StopIteration:
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
@utils.raises_conn_error
|
|
def create(self, name, weight, hosts):
|
|
# NOTE(cpp-cabrera): overwriting behavior should be okay for
|
|
# managing partitions
|
|
self._col.update({'n': name},
|
|
{'$set': {'n': name, 'w': weight, 'h': hosts}},
|
|
upsert=True)
|
|
|
|
@utils.raises_conn_error
|
|
def delete(self, name):
|
|
self._col.remove({'n': name}, w=0)
|
|
|
|
@utils.raises_conn_error
|
|
def drop_all(self):
|
|
self._col.drop()
|
|
self._col.ensure_index(PARTITIONS_INDEX, unique=True)
|
|
|
|
@utils.raises_conn_error
|
|
def update(self, name, **kwargs):
|
|
key, value = kwargs.popitem()
|
|
assert key in ('hosts', 'weight'), "kwargs (hosts, weight)"
|
|
res = self._col.update({'n': name},
|
|
{'$set': {key[0]: value}},
|
|
upsert=False)
|
|
if not res['updatedExisting']:
|
|
raise exceptions.PartitionNotFound(name)
|
|
|
|
|
|
def _normalize(entry):
|
|
return {
|
|
'name': entry['n'],
|
|
'hosts': entry['h'],
|
|
'weight': entry['w']
|
|
}
|