Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@sugarlabs.org>2012-09-22 12:41:12 (GMT)
committer Aleksey Lim <alsroot@sugarlabs.org>2012-09-22 12:41:12 (GMT)
commit8744eb15ce9afe71899e4ca9918129b60adbcfda (patch)
tree1623fb30859d460f31785cef34140cae5727754a
parentcc196252eedfc175c4e77ee2d98e4d410351961a (diff)
Provide /packages route to support packagekit-backend-presolve
-rwxr-xr-xsugar-network-server5
-rw-r--r--sugar_network/local/mountset.py2
-rw-r--r--sugar_network/node/commands.py4
-rw-r--r--sugar_network/node/obs.py56
-rw-r--r--sugar_network/node/router.py77
-rw-r--r--sugar_network/toolkit/router.py8
6 files changed, 145 insertions, 7 deletions
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 <http://www.gnu.org/licenses/>.
+
+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 <http://www.gnu.org/licenses/>.
+
+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