Commit 56c91533 authored by Sébastien Luttringer's avatar Sébastien Luttringer
Browse files

Merge migrate and allocate info vm module

parent e0e56229
Loading
Loading
Loading
Loading
+0 −56
Original line number Diff line number Diff line
#coding=utf8

# This file is part of CloudControl.
#
# CloudControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# CloudControl 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with CloudControl.  If not, see <http://www.gnu.org/licenses/>.

"""
CloudControl server command
"""

import json

from cloudcontrol.cli.exception import cmdBadArgument
from cloudcontrol.cli.printer import color
from cloudcontrol.cli.command import RemoteCommand


class Command_allocate(RemoteCommand):
    """VM allocation command"""

    def __init__(self, cli, argv0):
        RemoteCommand.__init__(self, cli, argv0)
        self.set_usage("%prog [options] <path to vmspec>")
        self.add_option("-t", dest="target", default="id", help="target on which to spawn VMs")

    def __call__(self, argv):
        self.parse_args(argv)
        if len(self.args) != 1:
            raise cmdBadArgument()

        # Load vmspec
        try:
            vmspec = json.load(open(self.args[0]))
        except IOError as err:
            self.printer.error("Unable to load vmspec: %s" % err.args[1])
        else:
            job_id = self.rpc.call("allocate", vmspec, self.options.target)

            self.printer.out("\n%sA job doing this allocation has been started.%s" % (color["light"], color["reset"]))
            self.printer.out("%sWatch it%s: watch list id:%s$duration$state$status$title" % (color["light"], color["reset"], job_id))
            self.printer.out("%sGet logs:%s attachment id:%s logs" % (color["light"], color["reset"], job_id))
            self.printer.out("%sGet results:%s attachment id:%s results\n" % (color["light"], color["reset"], job_id))

    def remote_functions(self):
        return set(("allocate",))
+0 −126
Original line number Diff line number Diff line
#coding=utf8

# This file is part of CloudControl.
#
# CloudControl is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# CloudControl 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with CloudControl.  If not, see <http://www.gnu.org/licenses/>.

'''
CloudControl migrate command
'''

from cloudcontrol.cli.exception import *
from sjrpc.core.exceptions import *
from cloudcontrol.cli.printer import Printer, color
from cloudcontrol.cli.command import TqlCommand

class Command_migrate(TqlCommand):
    '''Migrate vm'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
        self.set_usage("%prog [options] <source tql> <dest tql>")
        self.remove_option("--direct")
        self.remove_option("--raw")
        self.remove_option("--print-tql")
        self.add_option("-l", "--list", action="store_true", dest="list", default=False,
                        help="List migration types and algo")
        self.add_option("-t", "--type", action="store", dest="type", default="",
                        help="Selection migration type")
        self.add_option("-a", "--algo", action="store", dest="algo", default="",
                        help="Select migration algorithm")

    def __call__(self, argv):
        # Parse argline
        self.parse_args(argv)
        # Retrieve election types
        self.etypes = self.get_electiontypes()
        # Check args and do listings
        if self.options.list:
            self.list()
            return
        elif self.options.type not in self.etypes:
            raise cmdBadArgument("No such type: %s"%self.options.type)
        elif self.options.algo not in self.etypes[self.options.type]:
            raise cmdBadArgument("No such algo: %s for type: %s"%(self.options.algo, self.options.type))
        elif len(self.args) != 2:
            raise cmdBadArgument()
        stql = self.args[0]
        dtql = self.args[1]
        # election(query_vm, query_dest, mtype='cold', algo='fair', **kwargs)
        scrutin = self.rpccall("election", stql, dtql,
                               mtype=self.options.type,
                               algo=self.options.algo,
                               _direct=True, _status=False)
        # check election result
        if len(scrutin) == 0:
            raise cmdError("No migration plan found")
        # print election
        for (i,o) in enumerate(scrutin):
            if self.options.index:
                self.printer.out("[%d] "%i, nl="")
            self.printer.out("%s%s %s-> %s%s%s (%s)"%(
                    self.tdc("id"),
                    o["sid"],
                    color["reset"],
                    self.tdc("id"),
                    o["did"],
                    color["reset"],
                    o["type"]))
        # ask confirmation
        if self.printer.ask("Do you confirm election? (Yes baby) ") != "Yes baby":
            raise cmdWarning("User resign")
        # run migration
        self.rpccall("migrate", scrutin, _direct=True)

    def remote_functions(self):
        return set(("migrate", "electiontypes", "election"))

    def get_electiontypes(self):
        '''Return a list of migration type'''
        try:
            return self.cli.rpc.call("electiontypes")
        except RpcError as e:
            raise cmdError(e)

    def list(self):
        '''Print a list of migration type'''
        for t in self.etypes.keys():
            self.printer.out("migrate -t %s -a %s"%(t, ",".join(self.etypes[t])))


class Command_migrate2(TqlCommand):
    '''New generation VM migration.'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
        self.set_usage("%prog [options] <source tql> <dest tql>")
        self.add_option("-l", "--live", action="store_true", default=False,
            help="Do a live migration")
        self.add_option("-b", "--batch", help="Name of this batch")
        self.add_option("-f", "--flag", action="append",
            help="Migration or allocation flags")

    def __call__(self, argv):
        self.parse_args(argv)
        if self.options.live:
            self.tql_filter += "&r=vm&status=running"
        else:
            self.tql_filter += "&r=vm&status=stopped"
        if len(self.args) != 2:
            raise cmdBadArgument()
        self.rpccall("migrate2", self.args[0], self.args[1],
            live=self.options.live, flags=self.options.flag)

    def remote_functions(self):
        return set(("migrate2",))
+144 −13
Original line number Diff line number Diff line
@@ -22,10 +22,40 @@ CloudControl VM related commands
from cloudcontrol.cli.exception import *
from sjrpc.core.exceptions import *
from cloudcontrol.cli.printer import Printer, color
from cloudcontrol.cli.command import TqlCommand
from cloudcontrol.cli.command import RemoteCommand, TqlCommand

import json


class Command_allocate(RemoteCommand):
    """Create VMs"""

    def __init__(self, cli, argv0):
        RemoteCommand.__init__(self, cli, argv0)
        self.set_usage("%prog [options] <path to vmspec>")
        self.add_option("-t", dest="target", default="id",
            help="target on which to spawn VMs")

    def __call__(self, argv):
        self.parse_args(argv)
        if len(self.args) != 1:
            raise cmdBadArgument()
        try:
            allocation_plan = json.load(open(self.args[0]))
        except IOError as err:
            raise cmdError("Unable to load allocation plan: %s" % err)
        job_id = self.rpc.call("allocate", allocation_plan, self.options.target)
        self.printer.out("\n%sA job doing this allocation has been started.%s" % (color["light"], color["reset"]))
        self.printer.out("%sWatch it%s: watch list id:%s$duration$state$status$title" % (color["light"], color["reset"], job_id))
        self.printer.out("%sGet logs:%s attachment id:%s logs" % (color["light"], color["reset"], job_id))
        self.printer.out("%sGet results:%s attachment id:%s results\n" % (color["light"], color["reset"], job_id))

    def remote_functions(self):
        return set(("allocate",))


class Command_start(TqlCommand):
    '''Start a stopped vm'''
    '''Start stopped VMs'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -46,7 +76,7 @@ class Command_start(TqlCommand):


class Command_stop(TqlCommand):
    '''Stop a running vm'''
    '''Stop running VMs'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -65,7 +95,7 @@ class Command_stop(TqlCommand):


class Command_destroy(TqlCommand):
    '''Force a vm to stop'''
    '''Force VMs to stop'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -84,7 +114,7 @@ class Command_destroy(TqlCommand):


class Command_pause(TqlCommand):
    '''Pause a running vm'''
    '''Pause running VMs'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -103,7 +133,7 @@ class Command_pause(TqlCommand):


class Command_resume(TqlCommand):
    '''Resume a paused vm'''
    '''Resume paused VMs'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -121,7 +151,7 @@ class Command_resume(TqlCommand):
        return set(("resume",))

class Command_reset(TqlCommand):
    '''Reset a running vm'''
    '''Reset running VMs'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -139,7 +169,7 @@ class Command_reset(TqlCommand):
        return set(("reset",))

class Command_cycle(TqlCommand):
    '''Destroy and start a running vm'''
    '''Destroy and start again running VMs'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -197,7 +227,7 @@ class Command_autostart(TqlCommand):
        return set(("autostart",))

class Command_undefine(TqlCommand):
    '''Undefine a stopped vm'''
    '''Remove stopped VMs'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -217,7 +247,7 @@ class Command_undefine(TqlCommand):
        return set(("undefine",))

class Command_clone(TqlCommand):
    '''Clone vm'''
    '''Clone a VM'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -266,7 +296,7 @@ class Command_clone(TqlCommand):
        return set(("clone",))

class Command_rescue(TqlCommand):
    '''Switch a vm to rescue mode'''
    '''Switch VMs to rescue mode'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -284,7 +314,7 @@ class Command_rescue(TqlCommand):
        return set(("rescue",))

class Command_unrescue(TqlCommand):
    '''Switch a vm back from rescue mode'''
    '''Switch VMs back from rescue mode'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -302,7 +332,7 @@ class Command_unrescue(TqlCommand):
        return set(("unrescue",))

class Command_title(TqlCommand):
    '''Set a vm title'''
    '''Set a VM title'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
@@ -320,3 +350,104 @@ class Command_title(TqlCommand):

    def remote_functions(self):
        return set(("title",))

class Command_migrate(TqlCommand):
    '''Migrate VMs'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
        self.set_usage("%prog [options] <source tql> <dest tql>")
        self.remove_option("--direct")
        self.remove_option("--raw")
        self.remove_option("--print-tql")
        self.add_option("-l", "--list", action="store_true", dest="list", default=False,
                        help="List migration types and algo")
        self.add_option("-t", "--type", action="store", dest="type", default="",
                        help="Selection migration type")
        self.add_option("-a", "--algo", action="store", dest="algo", default="",
                        help="Select migration algorithm")

    def __call__(self, argv):
        # Parse argline
        self.parse_args(argv)
        # Retrieve election types
        self.etypes = self.get_electiontypes()
        # Check args and do listings
        if self.options.list:
            self.list()
            return
        elif self.options.type not in self.etypes:
            raise cmdBadArgument("No such type: %s"%self.options.type)
        elif self.options.algo not in self.etypes[self.options.type]:
            raise cmdBadArgument("No such algo: %s for type: %s"%(self.options.algo, self.options.type))
        elif len(self.args) != 2:
            raise cmdBadArgument()
        stql = self.args[0]
        dtql = self.args[1]
        # election(query_vm, query_dest, mtype='cold', algo='fair', **kwargs)
        scrutin = self.rpccall("election", stql, dtql,
                               mtype=self.options.type,
                               algo=self.options.algo,
                               _direct=True, _status=False)
        # check election result
        if len(scrutin) == 0:
            raise cmdError("No migration plan found")
        # print election
        for (i,o) in enumerate(scrutin):
            if self.options.index:
                self.printer.out("[%d] "%i, nl="")
            self.printer.out("%s%s %s-> %s%s%s (%s)"%(
                    self.tdc("id"),
                    o["sid"],
                    color["reset"],
                    self.tdc("id"),
                    o["did"],
                    color["reset"],
                    o["type"]))
        # ask confirmation
        if self.printer.ask("Do you confirm election? (Yes baby) ") != "Yes baby":
            raise cmdWarning("User resign")
        # run migration
        self.rpccall("migrate", scrutin, _direct=True)

    def remote_functions(self):
        return set(("migrate", "electiontypes", "election"))

    def get_electiontypes(self):
        '''Return a list of migration type'''
        try:
            return self.cli.rpc.call("electiontypes")
        except RpcError as e:
            raise cmdError(e)

    def list(self):
        '''Print a list of migration type'''
        for t in self.etypes.keys():
            self.printer.out("migrate -t %s -a %s"%(t, ",".join(self.etypes[t])))


class Command_migrate2(TqlCommand):
    '''Migrate VMs, version 2'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
        self.set_usage("%prog [options] <source tql> <dest tql>")
        self.add_option("-l", "--live", action="store_true", default=False,
            help="Do a live migration")
        self.add_option("-b", "--batch", help="Name of this batch")
        self.add_option("-f", "--flag", action="append",
            help="Migration or allocation flags")

    def __call__(self, argv):
        self.parse_args(argv)
        if self.options.live:
            self.tql_filter += "&r=vm&status=running"
        else:
            self.tql_filter += "&r=vm&status=stopped"
        if len(self.args) != 2:
            raise cmdBadArgument()
        self.rpccall("migrate2", self.args[0], self.args[1],
            live=self.options.live, flags=self.options.flag)

    def remote_functions(self):
        return set(("migrate2",))