Skip to content
Snippets Groups Projects
cli.py 4.66 KiB
Newer Older
#!/usr/bin/env python
#coding=utf8

'''
Seblu's avatar
Seblu committed
CloudControl CLI main module
'''

import os, os.path
import sys
Seblu's avatar
Seblu committed
import re
Seblu's avatar
Seblu committed
import subprocess
Seblu's avatar
Seblu committed
import shlex
import StringIO
Seblu's avatar
Seblu committed

from cccli import version, debug
from cccli.command import Command, Alias
from cccli.printer import Printer
from cccli.exception import *
Seblu's avatar
Seblu committed

from sjrpc.client import SimpleRpcClient
from sjrpc.utils import RpcHandler, ConnectionProxy, pure
Seblu's avatar
Seblu committed
from sjrpc.core.exceptions import *
Seblu's avatar
Seblu committed
    def __init__(self, settings):
        self.settings = settings
Seblu's avatar
Seblu committed
        self.prompt = ""
Seblu's avatar
Seblu committed
        self.rpc = None
Seblu's avatar
Seblu committed
        self.printer = None
Seblu's avatar
Seblu committed
        self.alias = Alias()
Seblu's avatar
Seblu committed
    def start(self, line=""):
Seblu's avatar
Seblu committed
        '''Start a CLI'''
Seblu's avatar
Seblu committed
        # line stuff
Seblu's avatar
Seblu committed
        if line:
Seblu's avatar
Seblu committed
            sys.stdin = StringIO.StringIO(line)
        # set interactive mode
        self.interactive = sys.stderr.isatty() and sys.stdin.isatty()
Seblu's avatar
Seblu committed
        # start printer and load history
Seblu's avatar
Seblu committed
        self.printer = Printer(self.interactive)
Seblu's avatar
Seblu committed
        self.printer.history.load(self.settings.get("history", ""))
        self.printer.history.maxsize(self.settings.get("hsize", None))
Seblu's avatar
Seblu committed
        # load alias
        self.alias.load(self.settings.get("alias", ""))
Seblu's avatar
Seblu committed
        # print debug
        self.printer.debug("Interactive: %s"%self.interactive)
Seblu's avatar
Seblu committed
        self.printer.debug("Alias: %s"%self.alias)
Seblu's avatar
Seblu committed
        self.printer.debug("Loaded history: %s"%len(self.printer.history))
Seblu's avatar
Seblu committed
        # Connecting
        self._connect()
        # authentifications
        self._auth()
Seblu's avatar
Seblu committed
        # Parsing
        self._parse()
        # save history
Seblu's avatar
Seblu committed
        self.printer.history.save(self.settings.get("history", ""))
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
    def _connect(self):
Seblu's avatar
Seblu committed
        self.printer.debug("Connecting...")
Seblu's avatar
Seblu committed
        rpcc = SimpleRpcClient.from_addr(self.settings["server"],
                                         self.settings["port"],
Seblu's avatar
Seblu committed
                                         enable_ssl=True,
                                         default_handler=CliHandler(),
Seblu's avatar
Seblu committed
                                         timeout=self.settings["timeout"]
Seblu's avatar
Seblu committed
                                        )
        rpcc.start(daemonize=True)
Seblu's avatar
Seblu committed
        self.rpc = ConnectionProxy(rpcc)

Seblu's avatar
Seblu committed
    def _auth(self):
Seblu's avatar
Seblu committed
        '''Handle server authentification'''
Seblu's avatar
Seblu committed
        self.printer.debug("Authenticating...")
Seblu's avatar
Seblu committed
        if self.rpc.authentify(self.settings["login"], self.settings["pass"]):
Seblu's avatar
Seblu committed
            self.printer.debug("Authenticated.")
Seblu's avatar
Seblu committed
        else:
Seblu's avatar
Seblu committed
            self.printer.fatal("Autentification failed!")
Seblu's avatar
Seblu committed
    def _parse(self):
        '''Parse a line'''
        prompt = "> " if self.interactive else ""
Seblu's avatar
Seblu committed
        while True:
            try:
Seblu's avatar
Seblu committed
                argv = shlex.split(self.printer.getline(prompt), comments=True)
                # alias subsitution
                if argv[0] in self.alias:
                    argv[0] = self.alias[argv[0]]
            except ValueError, e:
                self.printer.error("Lexer: %s"%str(e))
                continue
Seblu's avatar
Seblu committed
            except EOFError:
                break
            except SystemExit:
                break
            except KeyboardInterrupt:
Seblu's avatar
Seblu committed
                self.printer.out("")
Seblu's avatar
Seblu committed
            self._exec_command(argv)
        if self.interactive:
            self.printer.out("tcho!")
Seblu's avatar
Seblu committed
    def _exec_command(self, argv):
        '''Execute command'''
        try:
            if (argv[0] == "!"):
                p = subprocess.Popen(argv[1:], close_fds=True, shell=True)
Seblu's avatar
Seblu committed
                p.wait()
                ret = p.returncode
Seblu's avatar
Seblu committed
            elif (argv[0] == "?"):
Seblu's avatar
Seblu committed
                Command(["help"], self).call()
Seblu's avatar
Seblu committed
            else:
Seblu's avatar
Seblu committed
                Command(argv, self).call()
Seblu's avatar
Seblu committed
        except BadArgument, e:
Seblu's avatar
Seblu committed
            if str(e):
Seblu's avatar
Seblu committed
                self.printer.error("Bad argument: %s."%str(e))
Seblu's avatar
Seblu committed
            else:
Seblu's avatar
Seblu committed
                self.printer.error("Bad argument.")
Seblu's avatar
Seblu committed
            usage = Command.usage(argv[0])
            if usage != "":
Seblu's avatar
Seblu committed
                self.printer.out("usage: %s."%usage)
Seblu's avatar
Seblu committed
        except BadCommand, e:
            if str(e):
Seblu's avatar
Seblu committed
                self.printer.error("command: %s."%str(e))
Seblu's avatar
Seblu committed
            else:
Seblu's avatar
Seblu committed
                self.printer.error("No command: %s."%argv[0])
Seblu's avatar
Seblu committed
        except RpcError, e:
            if debug: raise
Seblu's avatar
Seblu committed
            self.printer.error("sjRPC: %s"%str(e))
Seblu's avatar
Seblu committed
        except Exception, e:
Seblu's avatar
Seblu committed
            if debug: raise
Seblu's avatar
Seblu committed
            self.printer.error("%s: %s."%(argv[0], str(e)))
class CliHandler(RpcHandler):
    '''Handle RPC incoming request'''

    @pure
    def get_tags(self, tags=()):
        if "version" in tags:
Seblu's avatar
Seblu committed
            return { "version": version }
Seblu's avatar
Seblu committed
        self.printer.fatal("Disconnected from server!")
Seblu's avatar
Seblu committed

class CliLexer(object):

    def __init__(self, fd):
        self.fd = fd

    def get_next_token(self):
        pass