import mg.tasks from mg import error from flask import request, Response from flask.ext import restful from flask.ext.restful import reqparse, abort from werkzeug import secure_filename import tempfile import shutil import os import zipfile import cStringIO class api(restful.Api): def __init__(self, *args, **kwargs): restful.Api.__init__(self, *args, **kwargs) self.add_resource(Stores, '/stores') self.add_resource(Store, '/stores/') self.add_resource(StoreFiles, '/stores//files') self.add_resource(StoreExtensions, '/stores//extensions') self.add_resource(StoreCmd, '/stores//cmd') class Stores(restful.Resource): def get(self): return {'stores': list(mg.tasks.list_stores())} def post(self): """ Install store """ parser = reqparse.RequestParser() parser.add_argument('store_name', type=str, dest='store_names', required=True) parser.add_argument('store_version', type=str, required=True) parser.add_argument('fast', type=str) parser.add_argument('base_url', type=str) parser.add_argument('secure_base_url', type=str) try: args = parser.parse_args() args = dict([(k, args[k]) for k in ['store_names', 'store_version', 'fast', 'base_url', 'secure_base_url'] if (hasattr(args, k) and args[k])]) mg.tasks.install_store(**args) return {'status': True, 'info': mg.tasks.store_info(args['store_names'])} except error.generalError as e: abort(400, message=e.message, status=False) class Store(restful.Resource): def delete(self, store_id): try: mg.tasks.delete_store(store_id) except error.generalError as e: abort(400, message=e.message, status=False) return {'status': True} def get(self, store_id): try: return mg.tasks.store_info(store_id) except error.generalError as e: abort(400, message=e.message, status=False) def put(self, store_id): """ Backup/restore store """ try: parser = reqparse.RequestParser() parser.add_argument('backup', type=str, required=True) parser.add_argument('mode', type=lambda x: x if x in ['save_state', 'restore_state'] else [].index(x), required=True, help="Use save_state or restore_state for mode") args = parser.parse_args() op = getattr(mg.tasks, args['mode']) op(store_id, args['backup']) except error.generalError as e: abort(400, message=e.message, status=False) return {'status': True} class StoreFiles(restful.Resource): @staticmethod def prepare_path(): parser = reqparse.RequestParser() parser.add_argument('path', type=str, required=True) args = parser.parse_args() if 'path' not in args: return "" path = args['path'].split("/") path = "/".join([el for el in path if el not in ("..", "/", "")]) return path def delete(self, store_id): path = StoreFiles.prepare_path() try: if not os.path.isfile(path): raise ValueError("Can delete only files") os.unlink(os.path.join(mg.tasks.store_info(store_id)['root'], path)) except BaseException as e: abort(400, message=str(e), status=False) return {'status': True} def get(self, store_id): try: path = os.path.join(mg.tasks.store_info(store_id)['root'], StoreFiles.prepare_path()) if not os.path.isdir(path): return { 'status': True, 'data': (open(path)).read() } fd = cStringIO.StringIO() zf = zipfile.ZipFile(fd, 'w') def zipdir(path, zip): for root, dirs, files in os.walk(path): for file in files: p = os.path.join(root, file) if p.startswith(path): alias = p[len(path):] zip.write(p, alias) zipdir(path, zf) zf.close() return Response(fd.getvalue(), mimetype='application/x-zip', headers={"Content-Disposition": "attachment;filename=%s" % 'folder.zip'}) except (error.generalError, IOError) as e: abort(400, message=str(e), status=False) def post(self, store_id): path = StoreFiles.prepare_path() for fl in request.files.getlist('file'): filename = secure_filename(fl.filename) try: os.makedirs(os.path.join(mg.tasks.store_info(store_id)['root'], path)) except os.error: pass fl.save(os.path.join(mg.tasks.store_info(store_id)['root'], path, filename)) return {'success': True} class StoreExtensions(restful.Resource): def post(self, store_id): parser = reqparse.RequestParser() parser.add_argument('extension', type=str) tempdir = tempfile.mkdtemp() try: args = parser.parse_args() if args['extension']: ext = parser.parse_args()['extension'] else: fl=request.files['file'] filename = secure_filename(fl.filename) ext = os.path.join(tempdir, filename) fl.save(ext) mg.tasks.install_extension(ext, store_id) except error.generalError as e: abort(400, message=e.message, status=False) finally: shutil.rmtree(tempdir) return {'status': True} class StoreCmd(restful.Resource): def post(self, store_id): parser = reqparse.RequestParser() parser.add_argument('cmd', type=str) try: args = parser.parse_args() mg.tasks.run_shell_script(store_id, args['cmd']) except (error.generalError, AssertionError) as e: abort(400, message=e.message, status=False) return {'status': True}