diff options
author | Aaron LI <aaronly.me@outlook.com> | 2016-11-22 17:55:21 +0800 |
---|---|---|
committer | Aaron LI <aaronly.me@outlook.com> | 2016-11-22 17:55:21 +0800 |
commit | d1e3f6219e1325e32e94de2b0c8189647c3393cb (patch) | |
tree | 4d920777e6c5e118b2af66896d93ec3782eae1d0 /fg21sim/webui/handlers | |
parent | bc77803e4d72ec51f7c57ac09c2e131247adccaa (diff) | |
download | fg21sim-d1e3f6219e1325e32e94de2b0c8189647c3393cb.tar.bz2 |
webui: Add "ProductsAJAXHandler" to manipulate the products manifest
TODO: some actions currently not implemented yet
Diffstat (limited to 'fg21sim/webui/handlers')
-rw-r--r-- | fg21sim/webui/handlers/__init__.py | 1 | ||||
-rw-r--r-- | fg21sim/webui/handlers/products.py | 173 |
2 files changed, 174 insertions, 0 deletions
diff --git a/fg21sim/webui/handlers/__init__.py b/fg21sim/webui/handlers/__init__.py index 6fa4152..a859e6e 100644 --- a/fg21sim/webui/handlers/__init__.py +++ b/fg21sim/webui/handlers/__init__.py @@ -5,4 +5,5 @@ from .index import IndexHandler from .login import LoginHandler from .configs import ConfigsAJAXHandler from .console import ConsoleAJAXHandler +from .products import ProductsAJAXHandler from .websocket import WSHandler diff --git a/fg21sim/webui/handlers/products.py b/fg21sim/webui/handlers/products.py new file mode 100644 index 0000000..5c9e0c8 --- /dev/null +++ b/fg21sim/webui/handlers/products.py @@ -0,0 +1,173 @@ +# Copyright (c) 2016 Weitian LI <liweitianux@live.com> +# MIT license + +""" +Handle the AJAX requests from the client to manage the simulation products. +""" + + +import os +import logging + +import tornado.ioloop +from tornado.escape import json_decode, json_encode + +from .base import BaseRequestHandler + + +logger = logging.getLogger(__name__) + + +class ProductsAJAXHandler(BaseRequestHandler): + """ + Handle the AJAX requests from the client to manage the simulation products. + + Attributes + ---------- + from_localhost : bool + ``True`` if the request is from the localhost, otherwise ``False``. + """ + def initialize(self): + """Hook for subclass initialization. Called for each request.""" + self.products = self.application.products + if self.request.remote_ip == "127.0.0.1": + self.from_localhost = True + else: + self.from_localhost = False + + def get(self): + """ + Handle the READ-ONLY products manifest manipulations. + + Supported actions: + - get: Get the current products manifest + - download: TODO + - open: TODO + """ + action = self.get_argument("action", "get") + if action == "get": + response = { + "manifest": self.products.manifest, + "localhost": self.from_localhost, + } + success = True + else: + # ERROR: bad action + success = False + reason = "Bad request action: {0}".format(action) + # + if success: + logger.debug("Response: {0}".format(response)) + self.set_header("Content-Type", "application/json; charset=UTF-8") + self.write(json_encode(response)) + else: + logger.warning("Request failed: {0}".format(reason)) + self.send_error(400, reason=reason) + + @tornado.web.authenticated + def post(self): + """ + Handle the READ-WRITE products manifest manipulations. + + Supported actions: + - load: Load the products manifest from file + - save: Save the current products manifest to file + - reset: Reset existing products manifest + - convert: Convert the product from HEALPix map to HPX image + """ + request = json_decode(self.request.body) + logger.debug("Received request: {0}".format(request)) + action = request.get("action") + if action == "load": + # Load the manifest from supplied file + try: + success, reason = self._load_products(request["manifestfile"]) + except KeyError: + success = False + reason = "'manifestfile' is missing" + elif action == "save": + # Save current products manifest to file + try: + success, reason = self._save_products(request["outfile"], + request["clobber"]) + except KeyError: + success = False + reason = "'outfile' or 'clobber' is missing" + elif action == "reset": + # Reset existing products manifest + success = self._reset_products() + elif action == "convert": + # Convert the product from HEALPix map to HPX image + raise NotImplementedError("TODO") + else: + # ERROR: bad action + success = False + reason = "Bad request action: {0}".format(action) + # + if success: + response = {"action": action, "success": success} + logger.debug("Response: {0}".format(response)) + self.set_header("Content-Type", "application/json; charset=UTF-8") + self.write(json_encode(response)) + else: + logger.warning("Request failed: {0}".format(reason)) + self.send_error(400, reason=reason) + + def _reset_products(self): + """Reset the existing products manifest.""" + self.products.reset() + return True + + def _load_products(self, manifestfile): + """ + Load the products manifest from file. + + Parameters + ---------- + manifestfile: str + The path to the products manifest file, which must be + an *absolute path*. + + Returns + ------- + success : bool + ``True`` if the operation succeeded, otherwise, ``False``. + error : str + If failed, this ``error`` saves the details, otherwise, ``None``. + """ + success = False + error = None + if os.path.isabs(os.path.expanduser(manifestfile)): + self.products.load(manifestfile) + success = True + else: + error = "Not an absolute path" + return (success, error) + + def _save_products(self, outfile, clobber=False): + """ + Save current products manifest to file. + + Parameters + ---------- + outfile: str + The filepath to the output manifest file, which must be + an *absolute path*. + clobber : bool, optional + Whether overwrite the output file if already exists? + + Returns + ------- + success : bool + ``True`` if the operation succeeded, otherwise, ``False``. + error : str + If failed, this ``error`` saves the details, otherwise, ``None``. + """ + success = False + error = None + try: + self.products.dump(outfile, clobber=clobber) + success = True + except (ValueError, OSError) as e: + error = str(e) + return (success, error) |