From 3a3d6907c086f30f92fd0f3900e205aa78ecb65c Mon Sep 17 00:00:00 2001 From: Antoine Millet Date: Tue, 28 Dec 2010 18:52:05 +0100 Subject: [PATCH] Added "#" separator. --- ccserver/handlers.py | 92 +++++++++++++++++++++++--------------------- ccserver/tql.py | 25 +++++++++--- 2 files changed, 68 insertions(+), 49 deletions(-) diff --git a/ccserver/handlers.py b/ccserver/handlers.py index d3fc75c..722c1ee 100644 --- a/ccserver/handlers.py +++ b/ccserver/handlers.py @@ -4,7 +4,7 @@ import inspect import logging from sjrpc.utils import RpcHandler, pure -from tql import TqlQuery +from tql import TqlQuery, TqlCondition, TqlLimit from conf import CCConf from exceptions import AlreadyRegistered, AuthenticationError @@ -70,49 +70,53 @@ class ClientHandler(OnlineCCHandler): query = TqlQuery(query) for condition in query.iterconditions(): - tag_name = condition.name - - if tag_name in ('a', 'hv', 'h', 'id'): - # Append all accounts: - for login in self._server.conf.list_accounts(): - tags = self._server.resolve_tags(login, query.tags) - objects.append(tags) - - if tag_name in ('vm', 'h', 'id'): - hvs = [o for o in objects if o['role'] == 'hypervisor' - and o['status'] == 'online'] - if not hvs: - for hy in self._server.iter_connected_role('hypervisor'): - tags = self._server.resolve_tags(hy.login, query.tags) - hvs.append(tags) - - # Query the selected hypervisors: - logging.debug('Querying %d hypervisors: ' - '%s' % (len(hvs), hvs)) - async_calls = {} - tags = tuple(query.tags) - for hy_tags in hvs: - hy = self._server.get_connection(hy_tags['a']) - cid = hy.connection.async_call('list_vm', tags=tags) - async_calls[cid] = hy_tags - - logging.debug('Waiting for the response of hypervisors...') - calls = frozenset(async_calls) - responses = self._server.manager.wait(calls, timeout=5) - logging.debug('Responses received from hypervisors.') - - for resp in responses: - if resp['error'] is None: - hy = async_calls[resp['id']] - for vm_tags in resp['return']: - vm_tags['role'] = 'vm' - vm_tags['id'] = '%s.%s' % (hy['a'], vm_tags['vm']) - vm_tags.update(hy['__static_user']) - objects.append(vm_tags) - - # Filter the tag - objects = [o for o in objects if condition.check(o.get(tag_name))] - + if isinstance(condition, TqlCondition): + tag_name = condition.name + + if tag_name in ('a', 'hv', 'h', 'id'): + # Append all accounts: + for login in self._server.conf.list_accounts(): + tags = self._server.resolve_tags(login, query.tags) + objects.append(tags) + + if tag_name in ('vm', 'h', 'id'): + hvs = [o for o in objects if o['role'] == 'hypervisor' + and o['con'] != 'offline'] + if not hvs: + for hy in self._server.iter_connected_role('hypervisor'): + tags = self._server.resolve_tags(hy.login, query.tags) + hvs.append(tags) + + # Query the selected hypervisors: + logging.debug('Querying %d hypervisors: ' + '%s' % (len(hvs), hvs)) + async_calls = {} + tags = tuple(query.tags) + for hy_tags in hvs: + hy = self._server.get_connection(hy_tags['a']) + cid = hy.connection.async_call('list_vm', tags=tags) + async_calls[cid] = hy_tags + + logging.debug('Waiting for the response of hypervisors...') + calls = frozenset(async_calls) + responses = self._server.manager.wait(calls, timeout=5) + logging.debug('Responses received from hypervisors.') + + for resp in responses: + if resp['error'] is None: + hy = async_calls[resp['id']] + for vm_tags in resp['return']: + vm_tags['role'] = 'vm' + vm_tags['id'] = '%s.%s' % (hy['a'], vm_tags['vm']) + vm_tags.update(hy['__static_user']) + objects.append(vm_tags) + + # Filter the tag + objects = [o for o in objects if condition.check(o.get(tag_name))] + + elif isinstance(condition, TqlLimit): + objects = objects[:condition.number] + # Before to return, filter with the asked tags for each objects: tags = query.tags tags.add('id') diff --git a/ccserver/tql.py b/ccserver/tql.py index 319e1e6..ca173e0 100644 --- a/ccserver/tql.py +++ b/ccserver/tql.py @@ -59,6 +59,14 @@ class TqlCondition(object): def check(self, value): return self.operator(value, self.value) ^ self.invert +class TqlLimit(object): + + def __init__(self, number): + self.number = number + + def __repr__(self): + return '' % self.number + class TqlQuery(object): ''' Parse a query written with TQL (Tag Query Language) and allow to filter a @@ -75,12 +83,11 @@ class TqlQuery(object): '<=': 'lte', '~': 'regex'} - RE_COND = re.compile(r'^(?P[a-z-A-Z0-9_-]+)' - r'((?P[!$<>~:=]{1,3})' - r'(?P[^&]+))?$') + RE_COND = re.compile(r'^(?P[a-z-A-Z0-9_?*-]+)' + r'((?P[!<>~:=]{1,3})' + r'(?P[^&$#]+?))?$') RE_TAG = re.compile(r'^(?P[a-z-A-Z0-9_-]+)') - RE_SEPARATOR = re.compile(r'(&|\$)') - + RE_SEPARATOR = re.compile(r'(&|\$|#)') def __init__(self, query): self._conditions = [] @@ -151,6 +158,14 @@ class TqlQuery(object): raise TqlParsingError('Error while parsing, invalid tag ' 'name %s' % repr(tok)) + elif sep == '#': + if tok.isdigit(): + lim = TqlLimit(int(tok)) + self._conditions.append(lim) + else: + raise TqlParsingError('Error while parsing, invalid limit ' + '%s' % repr(tok)) + def has_condition(self, tag_name): ''' Return True if query has made a condition for the specified tag name. -- GitLab