Skip to content

Commit

Permalink
scripts: qmp-shell: add transaction subshell
Browse files Browse the repository at this point in the history
Add a special processing mode to craft transactions.

By entering "transaction(" the shell will enter a special
mode where each subsequent command will be saved as a transaction
instead of executed as an individual command.

The transaction can be submitted by entering ")" on a line by itself.

Examples:

Separate lines:

(QEMU) transaction(
TRANS> block-dirty-bitmap-add node=drive0 name=bitmap1
TRANS> block-dirty-bitmap-clear node=drive0 name=bitmap0
TRANS> )

With a transaction action included on the first line:

(QEMU) transaction( block-dirty-bitmap-add node=drive0 name=bitmap2
TRANS> block-dirty-bitmap-add node=drive0 name=bitmap3
TRANS> )

As a one-liner, with just one transaction action:

(QEMU) transaction( block-dirty-bitmap-add node=drive0 name=bitmap0 )

As a side-effect of this patch, blank lines are now parsed as no-ops,
regardless of which shell mode you are in.

Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Tested-by: Kashyap Chamarthy <kchamart@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
  • Loading branch information
jnsnow authored and Luiz Capitulino committed May 11, 2015
1 parent 6092c3e commit 30bd681
Showing 1 changed file with 41 additions and 1 deletion.
42 changes: 41 additions & 1 deletion scripts/qmp/qmp-shell
Expand Up @@ -73,6 +73,8 @@ class QMPShell(qmp.QEMUMonitorProtocol):
self._greeting = None
self._completer = None
self._pp = pp
self._transmode = False
self._actions = list()

def __get_address(self, arg):
"""
Expand Down Expand Up @@ -159,6 +161,36 @@ class QMPShell(qmp.QEMUMonitorProtocol):
< command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
"""
cmdargs = cmdline.split()

# Transactional CLI entry/exit:
if cmdargs[0] == 'transaction(':
self._transmode = True
cmdargs.pop(0)
elif cmdargs[0] == ')' and self._transmode:
self._transmode = False
if len(cmdargs) > 1:
raise QMPShellError("Unexpected input after close of Transaction sub-shell")
qmpcmd = { 'execute': 'transaction',
'arguments': { 'actions': self._actions } }
self._actions = list()
return qmpcmd

# Nothing to process?
if not cmdargs:
return None

# Parse and then cache this Transactional Action
if self._transmode:
finalize = False
action = { 'type': cmdargs[0], 'data': {} }
if cmdargs[-1] == ')':
cmdargs.pop(-1)
finalize = True
self.__cli_expr(cmdargs[1:], action['data'])
self._actions.append(action)
return self.__build_cmd(')') if finalize else None

# Standard command: parse and return it to be executed.
qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
self.__cli_expr(cmdargs[1:], qmpcmd['arguments'])
return qmpcmd
Expand All @@ -171,6 +203,9 @@ class QMPShell(qmp.QEMUMonitorProtocol):
print 'command format: <command-name> ',
print '[arg-name1=arg1] ... [arg-nameN=argN]'
return True
# For transaction mode, we may have just cached the action:
if qmpcmd is None:
return True
resp = self.cmd_obj(qmpcmd)
if resp is None:
print 'Disconnected'
Expand All @@ -191,6 +226,11 @@ class QMPShell(qmp.QEMUMonitorProtocol):
version = self._greeting['QMP']['version']['qemu']
print 'Connected to QEMU %d.%d.%d\n' % (version['major'],version['minor'],version['micro'])

def get_prompt(self):
if self._transmode:
return "TRANS> "
return "(QEMU) "

def read_exec_command(self, prompt):
"""
Read and execute a command.
Expand Down Expand Up @@ -330,7 +370,7 @@ def main():
die('Could not connect to %s' % addr)

qemu.show_banner()
while qemu.read_exec_command('(QEMU) '):
while qemu.read_exec_command(qemu.get_prompt()):
pass
qemu.close()

Expand Down

0 comments on commit 30bd681

Please sign in to comment.