Skip to content
Snippets Groups Projects
command.py 10.4 KiB
Newer Older
Seblu's avatar
Seblu committed
#!/usr/bin/env python
#coding=utf8

'''
CloudControl CLI command module
'''

Seblu's avatar
Seblu committed
import os, os.path
import sys
Seblu's avatar
Seblu committed
import re
Seblu's avatar
Seblu committed
import pprint
Seblu's avatar
Seblu committed
import ConfigParser
Seblu's avatar
Seblu committed
from optparse import OptionParser
Seblu's avatar
Seblu committed

Seblu's avatar
Seblu committed
import cccli
Seblu's avatar
Seblu committed
from cccli.exception import *
from cccli.printer import color

from sjrpc.client import SimpleRpcClient
from sjrpc.core.exceptions import *
Seblu's avatar
Seblu committed

class Command(object):

Seblu's avatar
Seblu committed
    def __init__(self, argv, cli):
Seblu's avatar
Seblu committed
        # check argv
Seblu's avatar
Seblu committed
        if len(argv) == 0:
            raise cmdBadName()
Seblu's avatar
Seblu committed
        # check valid command chars
        if not re.match("^[a-zA-Z0-9]+", argv[0]):
Seblu's avatar
Seblu committed
            raise cmdBadName()
Seblu's avatar
Seblu committed
        cmdlist = [ x[4:] for x in dir(self) if x.startswith("cmd_") ]
        matchlist = [ x for x in cmdlist if re.match("%s.+"%argv[0], x) ]
        if argv[0] in cmdlist:
            pass
        elif len(matchlist) == 1:
            argv[0] = matchlist[0]
        else:
Seblu's avatar
Seblu committed
            raise cmdBadName()
Seblu's avatar
Seblu committed
        self._cmd = getattr(self, "cmd_%s"%argv[0])
Seblu's avatar
Seblu committed
        self._argv = argv
Seblu's avatar
Seblu committed
        self.cli = cli
Seblu's avatar
Seblu committed
        self.printer = cli.printer
Seblu's avatar
Seblu committed

    @classmethod
    def usage(cls, cmdname):
        '''Return usage of a command'''
        fname = "cmd_%s"%cmdname
        if not hasattr(cls, fname):
Seblu's avatar
Seblu committed
            raise cmdBadName(cmdname)
Seblu's avatar
Seblu committed
        if hasattr(getattr(cls, fname), "usage"):
            return getattr(getattr(cls, fname), "usage")
        return ""
Seblu's avatar
Seblu committed

    def call(self):
        '''Run command'''
        if re.match("^[a-zA-Z0-9]+$", self._argv[0]):
            name = "cmd_%s"%self._argv[0]
            if hasattr(self, name):
                cmd = getattr(self, name)
                return cmd(self._argv)
Seblu's avatar
Seblu committed
        raise cmdBadName(self._argv[0])
Seblu's avatar
Seblu committed

    def cmd_exit(self, argv):
        '''Quit application with respect'''
        raise SystemExit()
Seblu's avatar
Seblu committed
    cmd_exit.usage = "exit"
    cmd_exit.desc = "Quit application with respect"

    def cmd_quit(self, argv):
        '''Quit application with respect'''
        raise SystemExit()
    cmd_quit.usage = "quit"
    cmd_quit.desc = "Quit application with respect"

    def cmd_version(self, argv):
        '''Print cli version'''
Seblu's avatar
Seblu committed
        self.printer.out(cccli.version)
Seblu's avatar
Seblu committed
    cmd_version.usage = "version"
    cmd_version.desc = "Print cli version"

    def cmd_usage(self, argv):
        '''Print usage of a command'''
        if len(argv) != 2:
Seblu's avatar
Seblu committed
            raise cmdBadArgument()
Seblu's avatar
Seblu committed
        usage = Command.usage(argv[1])
        if usage != "":
Seblu's avatar
Seblu committed
            self.printer.out("usage: %s"%usage)
Seblu's avatar
Seblu committed
        else:
Seblu's avatar
Seblu committed
            self.printer.out("No usage.")
Seblu's avatar
Seblu committed
    cmd_usage.usage = "usage [command]"
    cmd_usage.desc = "Print usage of a command"

    def cmd_help(self, argv):
        '''Print help'''
        if len(argv) == 1:
            # build command list
            cmdlist = list()
            doclist = list()
            for x in dir(self):
                m = re.match("^cmd_([a-zA-Z0-9]+)$", x)
                if m:
                    cmdlist.append(m.group(1))
                    if hasattr(getattr(self, x), "__doc__"):
                        doclist.append(getattr(getattr(self, x), "__doc__"))
            # printing commands list
            width = max(map(len, cmdlist)) + 3
Seblu's avatar
Seblu committed
            self.printer.out("%sCommands:%s"%(color["lwhite"], color["reset"]))
Seblu's avatar
Seblu committed
            for c, d in zip(cmdlist, doclist):
                line = "%s"%c
                line = line.ljust(width,)
                line += "- %s"%d
Seblu's avatar
Seblu committed
                self.printer.out(line)
Seblu's avatar
Seblu committed
        elif len(argv) == 2:
            fname = "cmd_%s"%argv[1]
            if hasattr(self, fname):
                if hasattr(getattr(self, fname), "__doc__"):
Seblu's avatar
Seblu committed
                    self.printer.out("Description: %s"%getattr(getattr(self, fname), "__doc__"))
Seblu's avatar
Seblu committed
                if hasattr(getattr(self, fname), "usage"):
Seblu's avatar
Seblu committed
                    self.printer.out("Usage: %s"%getattr(getattr(self, fname), "usage"))
Seblu's avatar
Seblu committed
                if hasattr(getattr(self, fname), "details"):
Seblu's avatar
Seblu committed
                    Self.Printer.out("Details: %s"%getattr(getattr(self, fname), "details"))
Seblu's avatar
Seblu committed
            else:
Seblu's avatar
Seblu committed
                raise cmdBadArgument(argv[1])
Seblu's avatar
Seblu committed
        else:
Seblu's avatar
Seblu committed
            raise cmdBadArgument()
Seblu's avatar
Seblu committed
    cmd_help.usage = "help [command]"
    cmd_help.desc = "Print help about a command"

    def cmd_alias(self, argv):
        '''Show or create alias'''
        if len(argv) == 1:
            for n, v in self.cli.alias.items():
Seblu's avatar
Seblu committed
                self.printer.out("%s=%s"%(n, v))
Seblu's avatar
Seblu committed
        elif len(argv) == 2:
            if argv[1] not in self.cli.alias:
Seblu's avatar
Seblu committed
                raise cmdBadArgument(argv[1])
Seblu's avatar
Seblu committed
            self.printer.out("%s=%s"%(argv[1], self.cli.alias[argv[1]]))
Seblu's avatar
Seblu committed
        elif len(argv) == 3:
            self.cli.alias[argv[1]] = argv[2]
Seblu's avatar
Seblu committed
            self.cli.alias.save(self.cli.settings.get("alias", ""))
Seblu's avatar
Seblu committed
        else:
Seblu's avatar
Seblu committed
            raise cmdBadArgument()
Seblu's avatar
Seblu committed
    cmd_alias.usage = "alias [name] [value]"
    cmd_alias.desc = "Show or create aliases"

    def cmd_unalias(self, argv):
        '''Remove an alias'''
        if len(argv) != 2:
Seblu's avatar
Seblu committed
            raise cmdBadArgument()
Seblu's avatar
Seblu committed
        if argv[1] not in self.cli.alias:
Seblu's avatar
Seblu committed
            raise cmdBadArgument("%s: No such alias"%argv[1])
Seblu's avatar
Seblu committed
        del self.cli.alias[argv[1]]
Seblu's avatar
Seblu committed
        self.cli.alias.save(self.cli.settings.get("alias", ""))
Seblu's avatar
Seblu committed
    cmd_unalias.usage = "unalias [name]"
    cmd_unalias.desc = "Remove an aliases"
Seblu's avatar
Seblu committed

    def cmd_rcmd(self, argv):
        '''Show remote commands'''
        for cmds in self.cli.rpc.list_commands():
Seblu's avatar
Seblu committed
            self.printer.out("%s"%cmds["name"])
Seblu's avatar
Seblu committed
    cmd_rcmd.usage = "rcmd"
    cmd_rcmd.desc = "Print remote command list"
Seblu's avatar
Seblu committed
    def cmd_history(self, argv):
        '''Show history of commands'''
        if not self.printer.history:
            raise cmdError("History is not available")
        for l in self.printer.history:
Seblu's avatar
Seblu committed
            self.printer.out(l)
Seblu's avatar
Seblu committed
    cmd_history.usage = "history"
    cmd_history.desc = "Show commands history"

Seblu's avatar
Seblu committed
    def cmd_list(self, argv):
        '''List objects'''
Seblu's avatar
Seblu committed
        try:
Seblu's avatar
Seblu committed
            oparser = OptionParser(prog="list")
            oparser.add_option("-t", action="store_true", dest="table")
            (options, args) = oparser.parse_args(argv[1:])
        except SystemExit:
            return
        if len(args) == 0:
            args.append("a")
        try:
            objs = self.cli.rpc.list(str.join("", args))
Seblu's avatar
Seblu committed
        except RpcError as e:
            raise cmdError("RPCError: %s"%str(e))
        if len(objs) == 0:
            return
Seblu's avatar
Seblu committed
        if options.table:
            self._list_table(objs)
        else:
            self._list(objs)
    cmd_list.usage = "list [tql]"

    def _list(self, objs):
        for o in objs:
            id = o.pop("id")
            tags = " ".join([ "%s%s:%s%s"%(color["green"], t, color["reset"], v) for (t,v) in o.items() ])
            self.printer.out("%sid:%s%s %s"%(color["green"], color["yellow"], id, tags))

    def _list_table(self, objs):
Seblu's avatar
Seblu committed
        # get all tag list
        tags = dict()
        for o in objs:
            for t,v in o.items():
                tags[t] = max(len(str(v)), tags.get(t, len(str(t))))
        # extract id info
        idsize = tags.pop("id")
        # print titles
Seblu's avatar
Seblu committed
        self.printer.out(color["green"], nl="")
        self.printer.out("id".ljust(idsize+1), nl=" ")
Seblu's avatar
Seblu committed
        for t,v in tags.items():
            self.printer.out(t.ljust(v), nl=" ")
Seblu's avatar
Seblu committed
        self.printer.out(color["reset"])
Seblu's avatar
Seblu committed
        # print obj
        for obj in objs:
            self.printer.out("%s%s%s"%(color["yellow"], obj.pop("id").ljust(idsize+1), color["reset"]) ,nl=" ")
            for (t, v) in tags.items():
                self.printer.out(str(obj.get(t, "")).ljust(v) ,nl=" ")
            self.printer.out()
Seblu's avatar
Seblu committed

    def _startstopsdestroypauseresume(self, argv):
        # arg stuff
        if len(argv) == 1:
Seblu's avatar
Seblu committed
            raise cmdBadArgument()
Seblu's avatar
Seblu committed
        tql = str.join("", argv[1:])
        # print tql list result
        items = self.cli.rpc.list(tql)
        if len(items) == 0:
Seblu's avatar
Seblu committed
            self.printer.out("No selected object")
Seblu's avatar
Seblu committed
        self.printer.out("Your request give the following result:")
        for item in items:
Seblu's avatar
Seblu committed
            self.printer.out("%s"%item["id"])
        self.printer.out("Count: %s"%len(items))
        if self.printer.ask("Are you sure to %s? (yes/NO) "%argv[0], "yes") != "yes":
            raise cmdWarning("Aborted")
        if len(items) > 5:
            if self.printer.ask("You request is on more than 5 objets. Are you really sure to %s its? (Yes, I am) "%argv[0], "Yes, I am") != "Yes, I am":
                raise cmdWarning("Aborted")
        self.cli.rpc[argv[0]](tql)

Seblu's avatar
Seblu committed
    def cmd_start(self, argv):
        '''Start objects'''
        self._startstopsdestroypauseresume(argv)
Seblu's avatar
Seblu committed
    cmd_start.usage = "start [tql]"

    def cmd_stop(self, argv):
        '''Stop objects'''
        self._startstopsdestroypauseresume(argv)
    cmd_stop.usage = "stop [tql]"

    def cmd_pause(self, argv):
        '''Pause objects'''
        self._startstopsdestroypauseresume(argv)
    cmd_pause.usage = "pause [tql]"

    def cmd_resume(self, argv):
        '''Resume objects'''
        self._startstopsdestroypauseresume(argv)
    cmd_resume.usage = "resume [tql]"

    def cmd_destroy(self, argv):
        '''Force objects to stop'''
        self._startstopsdestroypauseresume(argv)
    cmd_destroy.usage = "destroy [tql]"

Seblu's avatar
Seblu committed
    def cmd_clear(self, argv):
        '''Clear tty'''
        self.printer.out("\033[H\033[2J", nl="")
    cmd_clear.usage = "clear"

Seblu's avatar
Seblu committed
    def cmd_uptime(self, argv):
        '''Show connection uptime'''
        if len(argv) == 1:
            argv.append(self.cli.settings["login"])
        tql = "a~(%s)$con"%"|".join(argv[1:])
        try:
            objs = self.cli.rpc.list(tql)
        except RpcError as e:
            raise cmdError("RPCError: %s"%str(e))
        for o in objs:
            self.printer.out("%s: %ss"%(o["a"],o["con"]))
    cmd_uptime.usage = "uptime [login]"

Seblu's avatar
Seblu committed

class Alias(dict):
    ''' Alias wrapper'''
    def load(self, filename):
        '''load alias from file'''
        if os.access(filename, os.R_OK):
            fparser = ConfigParser.SafeConfigParser()
            fparser.read(filename)
            if fparser.has_section("alias"):
                self.clear()
                self.update(fparser.items("alias"))

    def save(self, filename):
        '''save alias on file'''
        if os.access(filename, os.R_OK or os.W_OK):
            fparser = ConfigParser.SafeConfigParser()
            fparser.read(filename)
            fparser.remove_section("alias")
            fparser.add_section("alias")
            for n,v in self.items():
                fparser.set("alias", n, v)
            fparser.write(open(filename, "w"))