Commit d1304043 authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Copy quotaholder client files into clients

parent 18555878
......@@ -32,6 +32,12 @@
# or implied, of GRNET S.A.
def str_or_utf8(s):
if isinstance(s, unicode):
return s.encode('utf8')
return str(s)
class CallError(Exception):
exceptions = {}
......@@ -46,15 +52,16 @@ class CallError(Exception):
return self
def __init__(self, *args, **kw):
self.call_error = kw.get('call_error', self.__class__.__name__)
self.call_error = kw.pop('call_error', self.__class__.__name__)
self.args = args
self.kwargs = kw
def __str__(self):
return '\n--------\n'.join(str(x) for x in self.args)
return '\n--------\n'.join(str_or_utf8(x) for x in self.args)
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__,
','.join(str(x) for x in self.args))
','.join(str_or_utf8(x) for x in self.args))
@classmethod
def from_exception(cls, exc):
......@@ -71,7 +78,7 @@ class CallError(Exception):
def to_dict(self):
return {'call_error': self.call_error,
'error_args': self.args}
'error_args': (self.args, self.kwargs)}
@classmethod
def from_dict(cls, dictobj):
......@@ -86,8 +93,11 @@ class CallError(Exception):
if args is None:
args = (str(dictobj),)
call_error = 'UnknownError'
kw = {}
else:
args, kw = args
self = cls(*args, call_error=call_error)
self = cls(*args, call_error=call_error, **kw)
return self
def register_exceptions(*exceptions):
......
......@@ -31,13 +31,12 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from kamaki.clients.commissioning import Callpoint, CallError
from kamaki.clients.commissioning.utils.debug import debug
from kamaki.clients import Client
from synnefo.lib.commissioning import Callpoint, CallError
from synnefo.lib.commissioning.utils.debug import debug
from . import Client
from json import loads as json_loads, dumps as json_dumps
class CommissioningClient(Callpoint):
def __init__(self, base_url, token):
......
# Copyright 2012 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from synnefo.lib.quotaholder.api import QuotaholderAPI, QH_PRACTICALLY_INFINITE
from .commissioning_client import CommissioningClient
class QuotaholderClient(CommissioningClient):
api_spec = QuotaholderAPI()
appname = 'quotaholder'
def __init__(self, base_url=None, token=None):
default_url = 'http://127.0.0.1:8008/quotaholder/v'
base_url = base_url if base_url else default_url
super(self.__class__, self).__init__(base_url, token)
......@@ -31,14 +31,45 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from kamaki.clients.quotaholder.api import QuotaholderAPI
from kamaki.clients.commissioning.client import CommissioningClient
from kamaki.clients.commissioning import Callpoint, CallError
from kamaki.clients.commissioning.utils.debug import debug
from kamaki.clients import Client
from json import loads as json_loads, dumps as json_dumps
class QuotaholderClient(CommissioningClient):
api_spec = QuotaholderAPI()
appname = 'quotaholder'
class CommissioningClient(Callpoint):
def __init__(self, base_url=None, token=None):
super(self.__class__, self).__init__(base_url, token)
def __init__(self, base_url, token):
super(CommissioningClient, self).__init__()
self._kc = Client(base_url, token)
def do_make_call(self, api_call, data):
_kc = self._kc
gettable = ['list', 'get', 'read']
method = (_kc.get if any(api_call.startswith(x) for x in gettable)
else _kc.post)
path = api_call
json_data = json_dumps(data)
debug("%s %s\n%s\n<<<\n", method.func_name, path, json_data)
resp = method(path, data=json_data, success=(200, 450, 500))
debug(">>>\nStatus: %s", resp.status_code)
body = resp.text
debug("\n%s\n<<<\n", body[:128] if body else None)
status = int(resp.status_code)
if status == 200:
return json_loads(body)
else:
try:
error = json_loads(body)
except ValueError:
exc = CallError(body, call_error='ValueError')
else:
exc = CallError.from_dict(error)
raise exc
......@@ -31,12 +31,17 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from kamaki.clients.quotaholder.api.quotaholder import QuotaholderAPI
from kamaki.clients.quotaholder.api.exception import\
(InvalidKeyError, NoEntityError,
NoQuantityError, NoCapacityError,
ExportLimitError, ImportLimitError,
CorruptedError, InvalidDataError,
from kamaki.clients.quotaholder.api import QuotaholderAPI
from kamaki.clients.quotaholder.api import QH_PRACTICALLY_INFINITE
from kamaki.clients.quotaholder.exception import (
InvalidKeyError,
NoEntityError,
NoQuantityError,
NoCapacityError,
ExportLimitError,
ImportLimitError,
CorruptedError,
InvalidDataError,
DuplicateError)
API_Spec = QuotaholderAPI
......@@ -31,37 +31,62 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from kamaki.clients.commissioning import (CallError, register_exception,
InvalidDataError, CorruptedError)
from kamaki.clients.commissioning import (
CallError,
register_exception,
InvalidDataError,
CorruptedError)
@register_exception
class CommissionException(CallError):
pass
@register_exception
class InvalidKeyError(CommissionException):
pass
@register_exception
class NoEntityError(CommissionException):
pass
@register_exception
class CommissionValueException(CommissionException):
def __init__(self, *args, **kw):
super(CommissionValueException, self).__init__(*args, **kw)
kwargs = self.kwargs
self.source = kwargs['source']
self.target = kwargs['target']
self.resource = kwargs['resource']
self.requested = kwargs['requested']
self.current = kwargs['current']
self.limit = kwargs['limit']
@register_exception
class NoQuantityError(CommissionException):
class NoQuantityError(CommissionValueException):
pass
@register_exception
class NoCapacityError(CommissionException):
class NoCapacityError(CommissionValueException):
pass
@register_exception
class ExportLimitError(CommissionException):
class ExportLimitError(CommissionValueException):
pass
@register_exception
class ImportLimitError(CommissionException):
class ImportLimitError(CommissionValueException):
pass
@register_exception
class DuplicateError(CommissionException):
pass
......@@ -34,16 +34,25 @@
# or implied, of GRNET S.A.
from kamaki.clients.commissioning import (CanonifyException, SpecifyException,
Specificator, Null, Integer, Text,
Tuple, ListOf, Dict, Args)
from kamaki.clients.commissioning import (
CanonifyException,
SpecifyException,
Specificator,
Null,
Integer,
Text,
Tuple,
ListOf,
Dict,
Args)
from random import choice, randint
Context = Dict(classname='Context', null=True, show=False)
Context = Dict(classname='Context', null=True, show=False)
class Name(Text):
def init(self):
self.opts.update({'regex': "[\w.:@+/-]+", 'maxlen':512})
self.opts.update({'regex': "[\w.:@+/-]+", 'maxlen': 512})
Text.init(self)
def _random_choice(self, kw):
......@@ -51,167 +60,187 @@ class Name(Text):
length = randint(1, 48)
return ''.join(choice(alphabet) for _ in xrange(length))
class Nonnegative(Integer):
def init(self):
self.opts.update({'minimum': 0})
class Positive(Integer):
def init(self):
self.opts.update({'minimum': 1})
Serial = Positive(classname='Serial')
ClientKey = Name(classname='ClientKey')
Nothing = Null(classname='Nothing')
Entity = Name(classname='Entity')
Owner = Name(classname='Owner')
Key = Text(classname='Key')
NewKey = Text(classname='Newkey')
OwnerKey = Text(classname='OwnerKey')
Resource = Name(classname='Resource')
Policy = Name(classname='Policy')
Quantity = Integer(classname='Quantity', null=True)
Capacity = Nonnegative(classname='Capacity', null=True)
ImportLimit = Nonnegative(classname='ImportLimit', null=True)
ExportLimit = Nonnegative(classname='ExportLimit', null=True)
Imported = Nonnegative(classname='Imported')
Exported = Nonnegative(classname='Exported')
Returned = Nonnegative(classname='Returned')
Released = Nonnegative(classname='Released')
Flags = Nonnegative(classname='Flags')
Index = Nonnegative(classname='Index')
Timepoint = Text(classname='Timepoint', maxlen=24)
Reason = Text( classname = 'Reason',
regex = '(ACCEPT|REJECT):.*',
maxlen = 128 )
QH_PRACTICALLY_INFINITE = 10**32
Serial = Positive(classname='Serial')
ClientKey = Name(classname='ClientKey')
Nothing = Null(classname='Nothing')
Entity = Name(classname='Entity')
Owner = Name(classname='Owner')
Key = Text(classname='Key')
NewKey = Text(classname='Newkey')
OwnerKey = Text(classname='OwnerKey')
Resource = Name(classname='Resource')
Policy = Name(classname='Policy')
Quantity = Integer(classname='Quantity')
Capacity = Nonnegative(classname='Capacity')
ImportLimit = Nonnegative(classname='ImportLimit')
ExportLimit = Nonnegative(classname='ExportLimit')
QuantityDelta = Integer(classname='QuantityDelta')
CapacityDelta = Integer(classname='CapacityDelta')
ImportLimitDelta = Integer(classname='ImportLimitDelta')
ExportLimitDelta = Integer(classname='ExportLimitDelta')
Imported = Nonnegative(classname='Imported')
Exported = Nonnegative(classname='Exported')
Returned = Nonnegative(classname='Returned')
Released = Nonnegative(classname='Released')
Flags = Nonnegative(classname='Flags')
Index = Nonnegative(classname='Index')
Timepoint = Text(classname='Timepoint', maxlen=24)
Reason = Text(classname='Reason', regex='(ACCEPT|REJECT):.*', maxlen=128)
class QuotaholderAPI(Specificator):
def create_entity (
self,
context = Context,
create_entity = ListOf(Entity, Owner, Key, OwnerKey, nonempty=1)
):
def create_entity(
self,
context=Context,
create_entity=ListOf(Entity, Owner, Key, OwnerKey,
nonempty=1)
):
rejected = ListOf(Index)
return rejected
def set_entity_key (
self,
context = Context,
set_entity_key = ListOf(Entity, Key, NewKey)
):
def set_entity_key(
self,
context=Context,
set_entity_key=ListOf(Entity, Key, NewKey)
):
rejected = ListOf(Entity)
return rejected
def list_entities (
self,
context = Context,
entity = Entity,
key = Key
):
def list_entities(
self,
context=Context,
entity=Entity,
key=Key
):
entities = ListOf(Entity)
return entities
def get_entity (
self,
context = Context,
get_entity = ListOf(Entity, Key, nonempty=1)
):
def get_entity(
self,
context=Context,
get_entity=ListOf(Entity, Key, nonempty=1)
):
entities = ListOf(Entity, Owner)
return entities
def get_limits (
self,
context = Context,
get_limits = ListOf(Policy, nonempty=1)
):
def get_limits(
self,
context=Context,
get_limits=ListOf(Policy, nonempty=1)
):
limits = ListOf(Policy, Quantity, Capacity,
ImportLimit, ExportLimit)
return limits
def set_limits (
self,
context = Context,
set_limits = ListOf( Policy, Quantity, Capacity,
ImportLimit, ExportLimit,
nonempty=1 )
):
def set_limits(
self,
context=Context,
set_limits=ListOf(
Policy,
Quantity,
Capacity,
ImportLimit,
ExportLimit,
nonempty=1)
):
rejected = ListOf(Policy)
return rejected
def get_holding (
self,
context = Context,
get_holding = ListOf(Entity, Resource, Key)
):
def get_holding(
self,
context=Context,
get_holding=ListOf(Entity, Resource, Key)
):
holdings = ListOf( Entity, Resource, Policy,
Imported, Exported, Returned, Released, Flags )
return holdings
def set_holding (
self,
context = Context,
set_holding = ListOf(Entity, Resource, Key, Policy, Flags)
):
def set_holding(
self,
context=Context,
set_holding=ListOf(Entity, Resource, Key, Policy, Flags)
):
rejected = ListOf(Entity, Resource, Policy)
return rejected
def init_holding (
self,
context = Context,
init_holding = ListOf(Entity, Resource, Key, Policy,
Imported, Exported, Returned, Released,
Flags)
):
def init_holding(
self,
context=Context,
init_holding=ListOf(
Entity,
Resource,
Key,
Policy,
Imported,
Exported,
Returned,
Released,
Flags)
):
rejected = ListOf(Index)
return rejected
def reset_holding (
self,
context = Context,
reset_holding = ListOf(Entity, Resource, Key,
Imported, Exported, Returned, Released)
):
def reset_holding(
self,
context=Context,
reset_holding=ListOf(
Entity,
Resource,
Key,
Imported,
Exported,
Returned,
Released)
):
rejected = ListOf(Index)
return rejected
def release_holding (
self,
context = Context,
release_holding = ListOf(Entity, Resource, Key)
):
def release_holding(
self,
context=Context,
release_holding=ListOf(Entity, Resource, Key)
):
rejected = ListOf(Index)
return rejected
def list_resources (
self,
context = Context,
entity = Entity,
key = Key
):
def list_resources(self, context=Context, entity=Entity, key=Key):
resources = ListOf(Resource)
return resources
def list_holdings (
self,
context = Context,
list_holdings = ListOf(Entity, Key)
):
def list_holdings(
self,
context=Context,
list_holdings=ListOf(Entity, Key)
):
rejected = ListOf(Entity)
holdings_list = ListOf(ListOf(Entity, Resource,
Imported, Exported,
Returned, Released))
return Tuple(holdings_list, rejected)
def get_quota (
self,
context = Context,
get_quota = ListOf(Entity, Resource, Key)
):
def get_quota(
self,
context=Context,
get_quota=ListOf(Entity, Resource, Key)
):
quotas = ListOf(Entity, Resource,
Quantity, Capacity,
ImportLimit, ExportLimit,
......@@ -220,100 +249,145 @@ class QuotaholderAPI(Specificator):
Flags)
return quotas
def set_quota (
self,
context = Context,
set_quota = ListOf( Entity, Resource, Key,
Quantity, Capacity,
ImportLimit, ExportLimit, Flags )
):
def set_quota(
self,
context=Context,