From 8744eb15ce9afe71899e4ca9918129b60adbcfda Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Sat, 22 Sep 2012 12:41:12 +0000 Subject: Provide /packages route to support packagekit-backend-presolve --- diff --git a/sugar-network-server b/sugar-network-server index 847f716..b5feb0e 100755 --- a/sugar-network-server +++ b/sugar-network-server @@ -28,11 +28,11 @@ from sugar_network import node, local from sugar_network.local.mounts import LocalMount from sugar_network.local.mountset import Mountset from sugar_network.local.mounts import LocalMount -from sugar_network.node import stats +from sugar_network.node import stats, obs from sugar_network.node.commands import MasterCommands +from sugar_network.node.router import Router from sugar_network.resources.volume import Volume from sugar_network.toolkit import sugar, sneakernet -from sugar_network.toolkit.router import Router class Application(application.Daemon): @@ -91,6 +91,7 @@ Option.seek('main', application) Option.seek('webui', webui) Option.seek('node', node) Option.seek('stats', stats) +Option.seek('obs', obs) Option.seek('active-document', ad) app = Application( diff --git a/sugar_network/local/mountset.py b/sugar_network/local/mountset.py index 7cba34b..5625ecb 100644 --- a/sugar_network/local/mountset.py +++ b/sugar_network/local/mountset.py @@ -21,9 +21,9 @@ import active_document as ad from sugar_network import local, node from sugar_network.toolkit import zeroconf, netlink, network, mounts_monitor -from sugar_network.toolkit.router import Router from sugar_network.local.mounts import LocalMount, NodeMount from sugar_network.node.commands import NodeCommands +from sugar_network.node.router import Router from sugar_network.node.sync_node import SyncCommands from sugar_network.resources.volume import Volume, Commands, Request from active_toolkit import util, coroutine, enforce diff --git a/sugar_network/node/commands.py b/sugar_network/node/commands.py index bcd8fe2..6b4c64f 100644 --- a/sugar_network/node/commands.py +++ b/sugar_network/node/commands.py @@ -57,6 +57,10 @@ class NodeCommands(ad.VolumeCommands, Commands): with file(master_path, 'w') as f: f.write(_DEFAULT_MASTER_GUID) + @property + def is_master(self): + return self._is_master + def connect(self, callback, condition=None, **kwargs): self.volume.connect(callback, condition) diff --git a/sugar_network/node/obs.py b/sugar_network/node/obs.py new file mode 100644 index 0000000..db85997 --- /dev/null +++ b/sugar_network/node/obs.py @@ -0,0 +1,56 @@ +# Copyright (C) 2012 Aleksey Lim +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import logging +from xml.etree import cElementTree as ElementTree + +from sugar_network.toolkit import http +from active_toolkit.options import Option +from active_toolkit import enforce + + +obs_url = Option( + 'OBS API url; the entire OBS related functionality makes sense only ' + 'for master server', + default='https://obs.sugarlabs.org') + +obs_presolve_project = Option( + 'OBS project to use with packagekit-backend-presolve', + default='resolve') + + +_logger = logging.getLogger('node.obs') +_client = None + + +def get_presolve_repos(): + result = [] + reply = _request('GET', ['build', obs_presolve_project.value]) + for i in reply.findall('entry'): + result.append(i.get('name')) + return result + + +def _request(*args, **kwargs): + global _client + + if _client is None: + _client = http.Client(obs_url.value) + + response = _client.request(*args, **kwargs) + enforce(response.headers.get('Content-Type') == 'text/xml', + 'Irregular OBS response') + # pylint: disable-msg=E1103 + return ElementTree.parse(response.raw).getroot() diff --git a/sugar_network/node/router.py b/sugar_network/node/router.py new file mode 100644 index 0000000..da6f131 --- /dev/null +++ b/sugar_network/node/router.py @@ -0,0 +1,77 @@ +# Copyright (C) 2012 Aleksey Lim +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import json +import logging + +import active_document as ad +from sugar_network.node import obs +from sugar_network.toolkit import router +from active_toolkit import enforce + + +_logger = logging.getLogger('node.router') + + +class Router(router.Router): + + def __init__(self, commands): + router.Router.__init__(self, commands) + self._repos = None + + @router.route('GET', '/packages') + def packages(self, request, response): + response.content_type = 'application/json' + if len(request.path) == 1: + return self._list_repos() + elif len(request.path) == 2: + return self._list_packages(request) + elif len(request.path) == 3: + return self._get_package(request.path[1], request.path[2]) + else: + raise RuntimeError('Incorrect path') + + @router.route('HEADER', '/packages') + def try_packages(self, request, response): + enforce(len(request.path) == 3, 'Incorrect path') + self._get_package(request.path[1], request.path[2]) + + def _list_repos(self): + if self._repos is None: + if self.commands.is_master: + # Node should not depend on OBS + self._repos = obs.get_presolve_repos() + else: + self._repos = [] + return {'total': len(self._repos), 'result': self._repos} + + def _list_packages(self, request): + directory = self.commands.volume['context'] + documents, total = directory.find(type='package', + offset=request.get('offset'), limit=request.get('limit')) + return {'total': total.value, 'result': [i.guid for i in documents]} + + def _get_package(self, repo, package): + directory = self.commands.volume['context'] + context = directory.get(package) + meta = context.meta('feed') + enforce(meta is not None and 'path' in meta, ad.NotFound, 'No feed') + + with file(meta['path']) as f: + feed = json.load(f) + enforce('presolve' in feed and repo in feed['presolve'], ad.NotFound, + 'No presolve info') + + return feed['presolve'][repo] diff --git a/sugar_network/toolkit/router.py b/sugar_network/toolkit/router.py index f659a68..23890ed 100644 --- a/sugar_network/toolkit/router.py +++ b/sugar_network/toolkit/router.py @@ -64,8 +64,8 @@ def route(method, path): class Router(object): - def __init__(self, cp): - self._cp = cp + def __init__(self, commands): + self.commands = commands self._authenticated = set() self._valid_origins = set() self._invalid_origins = set() @@ -95,7 +95,7 @@ class Router(object): _logger.debug('Logging %r user', user) request = Request(method='GET', cmd='exists', document='user', guid=user) - enforce(self._cp.call(request, ad.Response()), Unauthorized, + enforce(self.commands.call(request, ad.Response()), Unauthorized, 'Principal user does not exist') self._authenticated.add(user) @@ -133,7 +133,7 @@ class Router(object): if rout: result = rout(request, response) else: - result = self._cp.call(request, response) + result = self.commands.call(request, response) if hasattr(result, 'read'): # pylint: disable-msg=E1103 -- cgit v0.9.1