2013-03-18 01:06:52 +04:00
#
# Utility functions for the command line drivers
#
2014-01-20 16:58:17 +04:00
# Copyright 2006-2007, 2013, 2014 Red Hat, Inc.
2013-03-18 01:06:52 +04:00
# Jeremy Katz <katzj@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
2013-10-28 00:59:47 +04:00
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
2013-03-18 01:06:52 +04:00
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
2014-01-19 02:01:43 +04:00
import argparse
2013-03-18 01:06:52 +04:00
import logging
import logging . handlers
2013-04-12 16:26:21 +04:00
import os
2013-03-18 01:06:52 +04:00
import shlex
2013-04-12 16:26:21 +04:00
import sys
2013-07-05 23:14:11 +04:00
import traceback
2013-03-18 01:06:52 +04:00
import libvirt
2013-03-18 02:18:22 +04:00
from virtcli import cliconfig
2013-03-18 01:06:52 +04:00
import virtinst
2013-04-11 18:27:02 +04:00
from virtinst import util
2013-03-18 01:06:52 +04:00
2013-03-18 02:18:22 +04:00
2013-03-18 01:06:52 +04:00
force = False
quiet = False
####################
# CLI init helpers #
####################
class VirtStreamHandler ( logging . StreamHandler ) :
def emit ( self , record ) :
"""
Based on the StreamHandler code from python 2.6 : ripping out all
the unicode handling and just uncoditionally logging seems to fix
logging backtraces with unicode locales ( for me at least ) .
No doubt this is atrocious , but it WORKSFORME !
"""
try :
msg = self . format ( record )
stream = self . stream
fs = " %s \n "
stream . write ( fs % msg )
self . flush ( )
except ( KeyboardInterrupt , SystemExit ) :
raise
except :
self . handleError ( record )
2013-04-13 22:34:52 +04:00
2014-01-22 18:06:35 +04:00
class VirtHelpFormatter ( argparse . RawDescriptionHelpFormatter ) :
2014-01-19 02:01:43 +04:00
'''
2013-03-18 01:06:52 +04:00
Subclass the default help formatter to allow printing newline characters
in - - help output . The way we do this is a huge hack : (
Inspiration : http : / / groups . google . com / group / comp . lang . python / browse_thread / thread / 6 df6e6b541a15bc2 / 09 f28e26af0699b1
2014-01-19 02:01:43 +04:00
'''
2013-03-18 01:06:52 +04:00
oldwrap = None
2014-01-19 02:01:43 +04:00
def _split_lines ( self , * args , * * kwargs ) :
def return_default ( ) :
2014-01-22 18:06:35 +04:00
return argparse . RawDescriptionHelpFormatter . _split_lines (
self , * args , * * kwargs )
2013-03-18 01:06:52 +04:00
2014-01-19 02:01:43 +04:00
if len ( kwargs ) != 0 and len ( args ) != 2 :
return return_default ( )
2013-03-18 01:06:52 +04:00
2014-01-19 02:01:43 +04:00
try :
text = args [ 0 ]
if " \n " in text :
return text . splitlines ( )
return return_default ( )
except :
return return_default ( )
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
2014-01-22 18:06:35 +04:00
def setupParser ( usage , description , introspection_epilog = False ) :
2014-01-19 02:01:43 +04:00
epilog = _ ( " See man page for examples and full option syntax. " )
2014-01-22 18:06:35 +04:00
if introspection_epilog :
2014-01-27 23:48:23 +04:00
epilog = _ ( " Use ' --option=? ' or ' --option help ' to see "
" available suboptions " ) + " \n " + epilog
2013-06-30 23:03:53 +04:00
2014-01-19 02:01:43 +04:00
parser = argparse . ArgumentParser (
usage = usage , description = description ,
formatter_class = VirtHelpFormatter ,
epilog = epilog )
parser . add_argument ( ' --version ' , action = ' version ' ,
version = cliconfig . __version__ )
2013-06-30 23:03:53 +04:00
2013-03-18 01:06:52 +04:00
return parser
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def earlyLogging ( ) :
logging . basicConfig ( level = logging . DEBUG , format = ' %(message)s ' )
2013-04-13 22:34:52 +04:00
2013-07-05 23:14:11 +04:00
def setupLogging ( appname , debug_stdout , do_quiet , cli_app = True ) :
2013-03-18 01:06:52 +04:00
global quiet
quiet = do_quiet
2013-10-01 18:12:56 +04:00
vi_dir = None
if not " VIRTINST_TEST_SUITE " in os . environ :
vi_dir = util . get_cache_dir ( )
if vi_dir and not os . access ( vi_dir , os . W_OK ) :
2013-03-18 01:06:52 +04:00
if os . path . exists ( vi_dir ) :
raise RuntimeError ( " No write access to directory %s " % vi_dir )
try :
2013-11-01 16:26:24 +04:00
os . makedirs ( vi_dir , 0751 )
2013-03-18 01:06:52 +04:00
except IOError , e :
raise RuntimeError ( " Could not create directory %s : %s " %
( vi_dir , e ) )
dateFormat = " %a , %d % b % Y % H: % M: % S "
fileFormat = ( " [ %(asctime)s " + appname + " %(process)d ] "
" %(levelname)s ( %(module)s : %(lineno)d ) %(message)s " )
streamErrorFormat = " %(levelname)-8s %(message)s "
rootLogger = logging . getLogger ( )
# Undo early logging
for handler in rootLogger . handlers :
rootLogger . removeHandler ( handler )
rootLogger . setLevel ( logging . DEBUG )
2013-10-01 18:12:56 +04:00
if vi_dir :
filename = os . path . join ( vi_dir , appname + " .log " )
fileHandler = logging . handlers . RotatingFileHandler ( filename , " ae " ,
1024 * 1024 , 5 )
fileHandler . setFormatter ( logging . Formatter ( fileFormat ,
dateFormat ) )
rootLogger . addHandler ( fileHandler )
2013-03-18 01:06:52 +04:00
streamHandler = VirtStreamHandler ( sys . stderr )
2013-07-05 23:14:11 +04:00
if debug_stdout :
2013-03-18 01:06:52 +04:00
streamHandler . setLevel ( logging . DEBUG )
streamHandler . setFormatter ( logging . Formatter ( fileFormat ,
dateFormat ) )
2013-07-05 23:14:11 +04:00
elif not cli_app :
streamHandler = None
2013-03-18 01:06:52 +04:00
else :
if quiet :
level = logging . ERROR
else :
level = logging . WARN
streamHandler . setLevel ( level )
streamHandler . setFormatter ( logging . Formatter ( streamErrorFormat ) )
2013-07-05 23:14:11 +04:00
if streamHandler :
rootLogger . addHandler ( streamHandler )
2013-03-18 01:06:52 +04:00
# Register libvirt handler
def libvirt_callback ( ignore , err ) :
if err [ 3 ] != libvirt . VIR_ERR_ERROR :
# Don't log libvirt errors: global error handler will do that
logging . warn ( " Non-error from libvirt: ' %s ' " , err [ 2 ] )
libvirt . registerErrorHandler ( f = libvirt_callback , ctx = None )
2013-07-05 23:14:11 +04:00
# Log uncaught exceptions
2013-04-12 16:26:21 +04:00
def exception_log ( typ , val , tb ) :
2013-07-05 23:14:11 +04:00
logging . debug ( " Uncaught exception: \n %s " ,
" " . join ( traceback . format_exception ( typ , val , tb ) ) )
2013-04-12 16:26:21 +04:00
sys . __excepthook__ ( typ , val , tb )
2013-03-18 01:06:52 +04:00
sys . excepthook = exception_log
# Log the app command string
2013-07-05 23:14:11 +04:00
logging . debug ( " Launched with command line: %s " , " " . join ( sys . argv ) )
2013-03-18 01:06:52 +04:00
#######################################
# Libvirt connection helpers #
#######################################
def getConnection ( uri ) :
logging . debug ( " Requesting libvirt URI %s " , ( uri or " default " ) )
2013-07-05 16:59:58 +04:00
conn = virtinst . VirtualConnection ( uri )
conn . open ( _do_creds_authname )
2013-07-08 00:38:11 +04:00
conn . cache_object_fetch = True
2013-07-06 04:36:28 +04:00
logging . debug ( " Received libvirt URI %s " , conn . uri )
2013-03-18 01:06:52 +04:00
return conn
# SASL username/pass auth
def _do_creds_authname ( creds ) :
retindex = 4
for cred in creds :
credtype , prompt , ignore , ignore , ignore = cred
prompt + = " : "
res = cred [ retindex ]
if credtype == libvirt . VIR_CRED_AUTHNAME :
res = raw_input ( prompt )
elif credtype == libvirt . VIR_CRED_PASSPHRASE :
import getpass
res = getpass . getpass ( prompt )
else :
2013-07-05 16:59:58 +04:00
raise RuntimeError ( " Unknown auth type in creds callback: %d " %
credtype )
2013-03-18 01:06:52 +04:00
cred [ retindex ] = res
return 0
##############################
# Misc CLI utility functions #
##############################
def fail ( msg , do_exit = True ) :
"""
Convenience function when failing in cli app
"""
2014-01-25 04:05:04 +04:00
logging . debug ( " " . join ( traceback . format_stack ( ) ) )
2013-03-18 01:06:52 +04:00
logging . error ( msg )
if traceback . format_exc ( ) . strip ( ) != " None " :
logging . debug ( " " , exc_info = True )
if do_exit :
_fail_exit ( )
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def print_stdout ( msg , do_force = False ) :
if do_force or not quiet :
print msg
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def print_stderr ( msg ) :
logging . debug ( msg )
print >> sys . stderr , msg
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def _fail_exit ( ) :
sys . exit ( 1 )
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def nice_exit ( ) :
print_stdout ( _ ( " Exiting at user request. " ) )
sys . exit ( 0 )
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def virsh_start_cmd ( guest ) :
2013-07-06 04:36:28 +04:00
return ( " virsh --connect %s start %s " % ( guest . conn . uri , guest . name ) )
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def install_fail ( guest ) :
virshcmd = virsh_start_cmd ( guest )
print_stderr (
_ ( " Domain installation does not appear to have been successful. \n "
" If it was, you can restart your domain by running: \n "
" %s \n "
" otherwise, please restart your installation. " ) % virshcmd )
sys . exit ( 1 )
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def set_force ( val = True ) :
global force
force = val
2013-04-13 22:34:52 +04:00
2013-09-28 19:34:03 +04:00
def set_prompt ( prompt ) :
2013-03-18 01:06:52 +04:00
# Set whether we allow prompts, or fail if a prompt pops up
2013-09-28 19:34:03 +04:00
if prompt :
2014-02-05 01:16:39 +04:00
logging . warning ( " --prompt mode is no longer supported. " )
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
2014-02-05 01:16:39 +04:00
name_missing = _ ( " --name is required " )
2013-03-18 01:06:52 +04:00
2014-02-05 01:16:39 +04:00
def validate_disk ( dev , warn_overwrite = False ) :
def _optional_fail ( msg ) :
if force :
logging . debug ( " --force skipping error condition ' %s ' " , msg )
logging . warn ( msg )
2013-03-18 01:06:52 +04:00
else :
2014-02-05 01:16:39 +04:00
fail ( msg + _ ( " (Use --force to override) " ) )
2013-03-18 01:06:52 +04:00
2014-02-05 01:16:39 +04:00
def check_path_exists ( dev ) :
2013-03-18 01:06:52 +04:00
"""
Prompt if disk file already exists and preserve mode is not used
"""
2014-02-05 01:16:39 +04:00
if not warn_overwrite :
return
if virtinst . VirtualDisk . path_exists ( dev . conn , dev . path ) :
_optional_fail (
_ ( " This will overwrite the existing path ' %s ' " % dev . path ) )
2013-03-18 01:06:52 +04:00
2014-02-05 01:16:39 +04:00
def check_inuse_conflict ( dev ) :
2013-03-18 01:06:52 +04:00
"""
Check if disk is inuse by another guest
"""
2014-01-15 02:11:51 +04:00
names = dev . is_conflict_disk ( )
2013-07-08 00:34:46 +04:00
if not names :
2014-02-05 01:16:39 +04:00
return
2013-03-18 01:06:52 +04:00
2014-02-05 01:16:39 +04:00
_optional_fail ( _ ( " Disk %s is already in use by other guests %s . " %
( dev . path , names ) ) )
2013-03-18 01:06:52 +04:00
2014-02-05 01:16:39 +04:00
def check_size_conflict ( dev ) :
2013-03-18 01:06:52 +04:00
"""
Check if specified size exceeds available storage
"""
isfatal , errmsg = dev . is_size_conflict ( )
2014-02-05 01:16:39 +04:00
# The isfatal case should have already caused us to fail
if not isfatal and errmsg :
_optional_fail ( errmsg )
2013-03-18 01:06:52 +04:00
2014-02-11 03:08:59 +04:00
def check_path_search ( dev ) :
user , broken_paths = dev . check_path_search ( dev . conn , dev . path )
if not broken_paths :
return
logging . warning ( _ ( " %s may not be accessible by the hypervisor. "
" You will need to grant the ' %s ' user search permissions for "
" the following directories: %s " ) , dev . path , user , broken_paths )
2014-02-05 01:16:39 +04:00
check_path_exists ( dev )
check_inuse_conflict ( dev )
check_size_conflict ( dev )
2014-02-11 03:08:59 +04:00
check_path_search ( dev )
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
2014-02-06 04:09:26 +04:00
def _run_console ( args ) :
logging . debug ( " Running: %s " , " " . join ( args ) )
child = os . fork ( )
if child :
return child
os . execvp ( args [ 0 ] , args )
os . _exit ( 1 ) # pylint: disable=W0212
def _gfx_console ( guest ) :
args = [ " /usr/bin/virt-viewer " ,
" --connect " , guest . conn . uri ,
" --wait " , guest . name ]
if not os . path . exists ( args [ 0 ] ) :
logging . warn ( _ ( " Unable to connect to graphical console: "
" virt-viewer not installed. Please install "
" the ' virt-viewer ' package. " ) )
return None
return _run_console ( args )
def _txt_console ( guest ) :
args = [ " /usr/bin/virsh " ,
" --connect " , guest . conn . uri ,
" console " , guest . name ]
return _run_console ( args )
def connect_console ( guest , consolecb , wait ) :
"""
Launched the passed console callback for the already defined
domain . If domain isn ' t running, return an error.
"""
child = None
if consolecb :
child = consolecb ( guest )
if not child or not wait :
return
# If we connected the console, wait for it to finish
try :
os . waitpid ( child , 0 )
except OSError , e :
logging . debug ( " waitpid: %s : %s " , e . errno , e . message )
def show_console_for_guest ( guest ) :
gdev = guest . get_devices ( " graphics " )
if not gdev :
logging . debug ( " Connecting to text console " )
return _txt_console ( guest )
gtype = gdev [ 0 ] . type
if gtype in [ " default " ,
virtinst . VirtualGraphics . TYPE_VNC ,
virtinst . VirtualGraphics . TYPE_SPICE ] :
logging . debug ( " Launching virt-viewer for graphics type ' %s ' " , gtype )
return _gfx_console ( guest )
else :
logging . debug ( " No viewer to launch for graphics type ' %s ' " , gtype )
return None
2014-02-05 01:16:39 +04:00
###########################
# CLI back compat helpers #
###########################
2013-04-13 22:34:52 +04:00
2014-01-25 03:56:59 +04:00
def convert_old_memory ( options ) :
if options . memory :
return
if not options . oldmemory :
return
options . memory = str ( options . oldmemory )
2014-01-22 00:24:46 +04:00
def convert_old_cpuset ( options ) :
if not options . cpuset :
return
if not options . vcpus :
options . vcpus = " "
options . vcpus + = " ,cpuset= %s " % options . cpuset
logging . debug ( " Generated compat cpuset: --vcpus %s " , options . vcpus )
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2014-02-06 18:33:00 +04:00
def convert_old_networks ( options , number_of_default_nics ) :
2013-09-28 04:16:35 +04:00
macs = util . listify ( options . mac )
networks = util . listify ( options . network )
bridges = util . listify ( options . bridge )
2013-03-18 01:06:52 +04:00
if bridges and networks :
fail ( _ ( " Cannot mix both --bridge and --network arguments " ) )
if bridges :
# Convert old --bridges to --networks
2013-04-12 00:32:00 +04:00
networks = [ " bridge: " + b for b in bridges ]
2013-03-18 01:06:52 +04:00
def padlist ( l , padsize ) :
2013-09-28 04:16:35 +04:00
l = util . listify ( l )
2013-03-18 01:06:52 +04:00
l . extend ( ( padsize - len ( l ) ) * [ None ] )
return l
# If a plain mac is specified, have it imply a default network
2013-09-28 04:16:35 +04:00
networks = padlist ( networks , max ( len ( macs ) , number_of_default_nics ) )
2013-03-18 01:06:52 +04:00
macs = padlist ( macs , len ( networks ) )
for idx in range ( len ( networks ) ) :
if networks [ idx ] is None :
2014-02-06 02:45:46 +04:00
networks [ idx ] = " default "
2013-09-28 04:16:35 +04:00
if macs [ idx ] :
networks [ idx ] + = " ,mac= %s " % macs [ idx ]
2013-03-18 01:06:52 +04:00
2013-09-28 04:16:35 +04:00
# Handle old format of bridge:foo instead of bridge=foo
for prefix in [ " network " , " bridge " ] :
if networks [ idx ] . startswith ( prefix + " : " ) :
networks [ idx ] = networks [ idx ] . replace ( prefix + " : " ,
prefix + " = " )
2013-03-18 01:06:52 +04:00
2013-09-28 04:16:35 +04:00
options . network = networks
2013-04-13 22:34:52 +04:00
2013-09-28 00:52:41 +04:00
2013-09-28 04:16:35 +04:00
def _determine_default_graphics ( guest , default_override ) :
if default_override is True :
2014-02-08 01:07:32 +04:00
return
2013-10-03 02:06:52 +04:00
elif default_override is False :
2014-02-08 01:07:32 +04:00
guest . skip_default_graphics = True
return
2013-04-13 22:34:52 +04:00
2013-09-28 04:16:35 +04:00
if " DISPLAY " not in os . environ . keys ( ) :
logging . debug ( " DISPLAY is not set: defaulting to nographics. " )
2014-02-08 01:07:32 +04:00
guest . skip_default_graphics = True
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2013-09-28 04:16:35 +04:00
def convert_old_graphics ( guest , options , default_override = None ) :
2013-03-18 01:06:52 +04:00
vnc = options . vnc
vncport = options . vncport
vnclisten = options . vnclisten
nographics = options . nographics
sdl = options . sdl
keymap = options . keymap
graphics = options . graphics
if graphics and ( vnc or sdl or keymap or vncport or vnclisten ) :
fail ( _ ( " Cannot mix --graphics and old style graphical options " ) )
2013-04-12 00:32:00 +04:00
optnum = sum ( [ bool ( g ) for g in [ vnc , nographics , sdl , graphics ] ] )
2013-03-18 01:06:52 +04:00
if optnum > 1 :
raise ValueError ( _ ( " Can ' t specify more than one of VNC, SDL, "
" --graphics or --nographics " ) )
2013-09-28 04:16:35 +04:00
if options . graphics :
return
2013-03-18 01:06:52 +04:00
if optnum == 0 :
2014-02-08 01:07:32 +04:00
_determine_default_graphics ( guest , default_override )
2013-09-28 04:16:35 +04:00
return
2013-03-18 01:06:52 +04:00
# Build a --graphics command line from old style opts
optstr = ( ( vnc and " vnc " ) or
( sdl and " sdl " ) or
( nographics and ( " none " ) ) )
if vnclisten :
optstr + = " ,listen= %s " % vnclisten
if vncport :
optstr + = " ,port= %s " % vncport
if keymap :
optstr + = " ,keymap= %s " % keymap
logging . debug ( " --graphics compat generated: %s " , optstr )
2013-09-28 04:16:35 +04:00
options . graphics = [ optstr ]
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
2013-09-28 17:36:11 +04:00
def convert_old_features ( options ) :
if getattr ( options , " features " , None ) :
return
opts = " "
if options . noacpi :
opts + = " acpi=off "
if options . noapic :
if opts :
opts + = " , "
opts + = " apic=off "
options . features = opts or None
2013-09-28 04:16:35 +04:00
def set_os_variant ( obj , distro_type , distro_variant ) :
# This is used for both Guest and virtconv VM, so be careful
if ( not distro_type and
not distro_variant and
hasattr ( obj , " os_autodetect " ) ) :
# Default to distro autodetection
obj . os_autodetect = True
return
2013-04-13 22:34:52 +04:00
2013-09-28 04:16:35 +04:00
distro_variant = distro_variant and str ( distro_variant ) . lower ( ) or None
distro_type = distro_type and str ( distro_type ) . lower ( ) or None
distkey = distro_variant or distro_type
if not distkey or distkey == " none " :
2013-03-18 01:06:52 +04:00
return
2013-09-28 04:16:35 +04:00
obj . os_variant = distkey
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
#############################
# Common CLI option/group #
#############################
def add_connect_option ( parser ) :
2014-01-21 03:04:23 +04:00
parser . add_argument ( " --connect " , metavar = " URI " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Connect to hypervisor with libvirt URI " ) )
2013-04-13 22:34:52 +04:00
2013-09-28 19:27:26 +04:00
def add_misc_options ( grp , prompt = False , replace = False ,
printxml = False , printstep = False ,
2014-02-06 04:09:26 +04:00
noreboot = False , dryrun = False ,
noautoconsole = False ) :
2013-09-28 19:27:26 +04:00
if prompt :
2014-01-21 03:04:23 +04:00
grp . add_argument ( " --prompt " , action = " store_true " ,
2014-01-19 02:01:43 +04:00
default = False , help = argparse . SUPPRESS )
2014-01-21 03:04:23 +04:00
grp . add_argument ( " --force " , action = " store_true " ,
2014-01-19 02:01:43 +04:00
default = False , help = argparse . SUPPRESS )
2013-09-28 19:27:26 +04:00
2014-02-06 04:09:26 +04:00
if noautoconsole :
grp . add_argument ( " --noautoconsole " , action = " store_false " ,
dest = " autoconsole " , default = True ,
help = _ ( " Don ' t automatically try to connect to the guest console " ) )
2013-09-28 19:27:26 +04:00
if noreboot :
2014-01-21 03:04:23 +04:00
grp . add_argument ( " --noreboot " , action = " store_true " ,
2013-09-28 19:27:26 +04:00
help = _ ( " Don ' t boot guest after completing install. " ) )
if replace :
2014-01-21 03:04:23 +04:00
grp . add_argument ( " --replace " , action = " store_true " ,
2013-09-28 19:27:26 +04:00
help = _ ( " Don ' t check name collision, overwrite any guest "
" with the same name. " ) )
if printxml :
2014-01-19 02:01:43 +04:00
grp . add_argument ( " --print-xml " , action = " store_true " , dest = " xmlonly " ,
2014-02-06 04:09:26 +04:00
help = _ ( " Print the generated domain XML rather than create "
" the guest. " ) )
2013-09-28 19:27:26 +04:00
if printstep :
2014-01-19 02:01:43 +04:00
grp . add_argument ( " --print-step " , dest = " xmlstep " ,
2013-09-28 19:27:26 +04:00
help = _ ( " Print XML of a specific install step "
" (1, 2, 3, all) rather than define the guest. " ) )
if dryrun :
2014-01-19 02:01:43 +04:00
grp . add_argument ( " --dry-run " , action = " store_true " , dest = " dry " ,
2013-09-28 19:27:26 +04:00
help = _ ( " Run through install process, but do not "
" create devices or define the guest. " ) )
2014-01-21 03:04:23 +04:00
grp . add_argument ( " -q " , " --quiet " , action = " store_true " ,
2013-09-28 19:27:26 +04:00
help = _ ( " Suppress non-error output " ) )
2014-01-21 03:04:23 +04:00
grp . add_argument ( " -d " , " --debug " , action = " store_true " ,
2013-09-28 19:27:26 +04:00
help = _ ( " Print debugging information " ) )
2014-01-25 05:03:30 +04:00
def add_metadata_option ( grp ) :
grp . add_argument ( " --metadata " ,
help = _ ( " Configure guest metadata. Ex: \n "
" --metadata name=foo,title= \" My pretty title \" ,uuid=... \n "
" --metadata description= \" My nice long description \" " ) )
2014-01-25 03:56:59 +04:00
def add_memory_option ( grp , backcompat = False ) :
grp . add_argument ( " --memory " ,
help = _ ( " Configure guest memory allocation. Ex: \n "
" --memory 1024 (in megabytes) \n "
" --memory 512,maxmemory=1024,hugepages=on " ) )
if backcompat :
grp . add_argument ( " -r " , " --ram " , type = int , dest = " oldmemory " ,
help = argparse . SUPPRESS )
2014-01-26 05:20:55 +04:00
def vcpu_cli_options ( grp , backcompat = True , editexample = False ) :
2014-01-21 03:04:23 +04:00
grp . add_argument ( " --vcpus " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Number of vcpus to configure for your guest. Ex: \n "
" --vcpus 5 \n "
2014-01-22 00:24:46 +04:00
" --vcpus 5,maxcpus=10,cpuset=1-4,6,8 \n "
" --vcpus sockets=2,cores=4,threads=2, " ) )
2014-01-26 05:20:55 +04:00
extramsg = " --cpu host "
if editexample :
extramsg = " --cpu host-model,clearxml=yes "
2014-01-21 03:04:23 +04:00
grp . add_argument ( " --cpu " ,
2014-01-22 01:28:07 +04:00
help = _ ( " CPU model and features. Ex: \n "
2014-01-26 05:20:55 +04:00
" --cpu coreduo,+x2apic \n " ) + extramsg )
2013-03-18 01:06:52 +04:00
if backcompat :
2014-01-19 02:01:43 +04:00
grp . add_argument ( " --check-cpu " , action = " store_true " ,
2014-01-21 03:04:23 +04:00
help = argparse . SUPPRESS )
2014-01-22 00:24:46 +04:00
grp . add_argument ( " --cpuset " , help = argparse . SUPPRESS )
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2014-01-22 01:26:35 +04:00
def add_gfx_option ( devg ) :
devg . add_argument ( " --graphics " , action = " append " ,
help = _ ( " Configure guest display settings. Ex: \n "
" --graphics vnc \n "
" --graphics spice,port=5901,tlsport=5902 \n "
" --graphics none \n "
" --graphics vnc,password=foobar,port=5910,keymap=ja " ) )
2013-03-18 01:06:52 +04:00
def graphics_option_group ( parser ) :
"""
Register vnc + sdl options for virt - install and virt - image
"""
2014-01-19 02:01:43 +04:00
vncg = parser . add_argument_group ( _ ( " Graphics Configuration " ) )
2013-03-18 01:06:52 +04:00
add_gfx_option ( vncg )
2014-01-21 03:04:23 +04:00
vncg . add_argument ( " --vnc " , action = " store_true " ,
2014-01-19 02:01:43 +04:00
help = argparse . SUPPRESS )
2014-01-21 03:04:23 +04:00
vncg . add_argument ( " --vncport " , type = int ,
2014-01-19 02:01:43 +04:00
help = argparse . SUPPRESS )
2014-01-21 03:04:23 +04:00
vncg . add_argument ( " --vnclisten " ,
2014-01-19 02:01:43 +04:00
help = argparse . SUPPRESS )
2014-01-21 03:04:23 +04:00
vncg . add_argument ( " -k " , " --keymap " ,
2014-01-19 02:01:43 +04:00
help = argparse . SUPPRESS )
2014-01-21 03:04:23 +04:00
vncg . add_argument ( " --sdl " , action = " store_true " ,
2014-01-19 02:01:43 +04:00
help = argparse . SUPPRESS )
vncg . add_argument ( " --nographics " , action = " store_true " ,
help = argparse . SUPPRESS )
2013-03-18 01:06:52 +04:00
return vncg
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def network_option_group ( parser ) :
"""
Register common network options for virt - install and virt - image
"""
2014-01-19 02:01:43 +04:00
netg = parser . add_argument_group ( _ ( " Networking Configuration " ) )
2013-03-18 01:06:52 +04:00
add_net_option ( netg )
# Deprecated net options
2014-01-21 03:04:23 +04:00
netg . add_argument ( " -b " , " --bridge " , action = " append " ,
2014-01-19 02:01:43 +04:00
help = argparse . SUPPRESS )
2014-01-21 03:04:23 +04:00
netg . add_argument ( " -m " , " --mac " , action = " append " ,
2014-01-19 02:01:43 +04:00
help = argparse . SUPPRESS )
2013-03-18 01:06:52 +04:00
return netg
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def add_net_option ( devg ) :
2014-01-21 03:04:23 +04:00
devg . add_argument ( " -w " , " --network " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure a guest network interface. Ex: \n "
" --network bridge=mybr0 \n "
" --network network=my_libvirt_virtual_net \n "
2013-08-28 19:36:25 +04:00
" --network network=mynet,model=virtio,mac=00:11... \n "
2014-01-22 18:06:35 +04:00
" --network network=mynet,filterref=clean-traffic \n "
2014-01-27 23:48:23 +04:00
" --network help " ) )
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2014-02-05 21:32:53 +04:00
def add_device_options ( devg , sound_back_compat = False ) :
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --controller " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure a guest controller device. Ex: \n "
" --controller type=usb,model=ich9-ehci1 " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --serial " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure a guest serial device " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --parallel " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure a guest parallel device " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --channel " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure a guest communication channel " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --console " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure a text console connection between "
" the guest and host " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --host-device " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure physical host devices attached to the "
" guest " ) )
2014-02-05 21:32:53 +04:00
# --sound used to be a boolean option, hence the nargs handling
sound_kwargs = {
" action " : " append " ,
" help " : _ ( " Configure guest sound device emulation " ) ,
}
if sound_back_compat :
sound_kwargs [ " nargs " ] = ' ? '
devg . add_argument ( " --sound " , * * sound_kwargs )
if sound_back_compat :
devg . add_argument ( " --soundhw " , action = " append " , dest = " sound " ,
help = argparse . SUPPRESS )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --watchdog " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure a guest watchdog device " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --video " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure guest video hardware. " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --smartcard " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure a guest smartcard device. Ex: \n "
" --smartcard mode=passthrough " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --redirdev " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure a guest redirection device. Ex: \n "
" --redirdev usb,type=tcp,server=192.168.1.1:4000 " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --memballoon " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Configure a guest memballoon device. Ex: \n "
" --memballoon model=virtio " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --tpm " , action = " append " ,
2013-06-26 05:45:07 +04:00
help = _ ( " Configure a guest TPM device. Ex: \n "
2013-09-28 18:28:04 +04:00
" --tpm /dev/tpm " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --rng " , action = " append " ,
2013-09-18 17:29:29 +04:00
help = _ ( " Configure a guest RNG device. Ex: \n "
2014-02-11 03:13:42 +04:00
" --rng /dev/random " ) )
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --panic " , action = " append " ,
2014-01-22 13:44:38 +04:00
help = _ ( " Configure a guest panic device. Ex: \n "
" --panic default " ) )
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2013-03-18 01:06:52 +04:00
def add_fs_option ( devg ) :
2014-01-21 03:04:23 +04:00
devg . add_argument ( " --filesystem " , action = " append " ,
2013-03-18 01:06:52 +04:00
help = _ ( " Pass host directory to the guest. Ex: \n "
" --filesystem /my/source/dir,/dir/in/guest \n "
" --filesystem template_name,/,type=template " ) )
2013-07-30 22:26:53 +04:00
2013-08-11 02:17:37 +04:00
def add_distro_options ( g ) :
# Way back when, we required specifying both --os-type and --os-variant
# Nowadays the distinction is pointless, so hide the less useful
# --os-type option.
2014-01-19 02:01:43 +04:00
g . add_argument ( " --os-type " , dest = " distro_type " ,
help = argparse . SUPPRESS )
g . add_argument ( " --os-variant " , dest = " distro_variant " ,
2013-08-11 02:17:37 +04:00
help = _ ( " The OS variant being installed guests, "
" e.g. ' fedora18 ' , ' rhel6 ' , ' winxp ' , etc. " ) )
2013-09-28 17:36:11 +04:00
def add_old_feature_options ( optg ) :
2014-01-21 03:04:23 +04:00
optg . add_argument ( " --noapic " , action = " store_true " ,
2014-01-19 02:01:43 +04:00
default = False , help = argparse . SUPPRESS )
2014-01-21 03:04:23 +04:00
optg . add_argument ( " --noacpi " , action = " store_true " ,
2014-01-19 02:01:43 +04:00
default = False , help = argparse . SUPPRESS )
2013-09-28 17:36:11 +04:00
2014-01-22 01:26:35 +04:00
def add_guest_xml_options ( geng ) :
geng . add_argument ( " --security " ,
help = _ ( " Set domain security driver configuration. " ) )
geng . add_argument ( " --numatune " ,
help = _ ( " Tune NUMA policy for the domain process. " ) )
2014-02-06 18:41:00 +04:00
geng . add_argument ( " --blkiotune " , action = " append " ,
help = _ ( " Tune blkio policy for the domain process. " ) )
2014-01-22 01:26:35 +04:00
geng . add_argument ( " --features " ,
help = _ ( " Set domain <features> XML. Ex: \n "
" --features acpi=off \n "
" --features apic=on,eoi=on " ) )
geng . add_argument ( " --clock " ,
help = _ ( " Set domain <clock> XML. Ex: \n "
" --clock offset=localtime,rtc_tickpolicy=catchup " ) )
2014-02-03 01:12:29 +04:00
geng . add_argument ( " --pm " , help = _ ( " Config power management features " ) )
2014-01-22 01:26:35 +04:00
2014-02-11 03:13:42 +04:00
def add_boot_options ( insg ) :
2014-01-22 01:26:35 +04:00
insg . add_argument ( " --boot " ,
2014-02-11 03:13:42 +04:00
help = _ ( " Configure guest boot settings. Ex: \n "
" --boot hd,cdrom,menu=on \n "
" --boot init=/sbin/init (for containers) " ) )
insg . add_argument ( " --idmap " ,
help = _ ( " Enable user namespace for LXC container. Ex. \n "
" --idmap uid_start=0,uid_target=1000,uid_count=10 " ) )
2014-01-22 01:26:35 +04:00
2014-01-26 21:25:18 +04:00
def add_disk_option ( stog , editexample = False ) :
editmsg = " "
if editexample :
editmsg + = " \n --disk cache= (unset cache) "
2014-01-22 01:26:35 +04:00
stog . add_argument ( " --disk " , action = " append " ,
help = _ ( " Specify storage with various options. Ex. \n "
" --disk path=/my/existing/disk \n "
" --disk path=/my/new/disk,size=5 (in gigabytes) \n "
2014-01-22 18:06:35 +04:00
" --disk device=cdrom,bus=scsi \n "
2014-01-26 21:25:18 +04:00
" --disk=? " ) + editmsg )
2014-01-22 01:26:35 +04:00
2014-01-19 22:56:06 +04:00
2013-03-18 01:06:52 +04:00
#############################################
# CLI complex parsing helpers #
# (for options like --disk, --network, etc. #
#############################################
2014-02-05 01:16:39 +04:00
def _on_off_convert ( key , val ) :
if val is None :
return None
def _yes_no_convert ( s ) :
tvalues = [ " y " , " yes " , " 1 " , " true " , " t " , " on " ]
fvalues = [ " n " , " no " , " 0 " , " false " , " f " , " off " ]
s = ( s or " " ) . lower ( )
if s in tvalues :
return True
elif s in fvalues :
return False
return None
val = _yes_no_convert ( val )
if val is not None :
return val
raise fail ( _ ( " %(key)s must be ' yes ' or ' no ' " ) % { " key " : key } )
2014-01-19 22:56:06 +04:00
class _VirtCLIArgument ( object ) :
def __init__ ( self , attrname , cliname ,
setter_cb = None , ignore_default = False ,
2014-01-26 00:44:14 +04:00
can_comma = False , aliases = None ,
2014-01-26 05:20:55 +04:00
is_list = False , is_onoff = False ) :
2014-01-19 22:56:06 +04:00
"""
A single subargument passed to compound command lines like - - disk ,
- - network , etc .
@attrname : The virtinst API attribute name the cliargument maps to .
If this is a virtinst object method , it will be called .
@cliname : The command line option name , ' path ' for path = FOO
@setter_cb : Rather than set an attribute directly on the virtinst
object , ( opts , inst , cliname , val ) to this callback to handle it .
@ignore_default : If the value passed on the cli is ' default ' , don ' t
do anything .
@can_comma : If True , this option is expected to have embedded commas .
After the parser sees this option , it will iterate over the
option string until it finds another known argument name :
everything prior to that argument name is considered part of
2014-01-25 03:07:45 +04:00
the value of this option , ' = ' included . Should be used sparingly .
2014-01-26 00:44:14 +04:00
@aliases : List of cli aliases . Useful if we want to change a property
name on the cli but maintain back compat .
2014-01-19 22:56:06 +04:00
@is_list : This value should be stored as a list , so multiple instances
are appended .
@is_onoff : The value expected on the cli is on / off or yes / no , convert
it to true / false .
"""
self . attrname = attrname
self . cliname = cliname
2013-09-28 00:52:41 +04:00
2014-01-19 22:56:06 +04:00
self . setter_cb = setter_cb
self . can_comma = can_comma
self . ignore_default = ignore_default
2014-01-25 02:58:12 +04:00
self . aliases = util . listify ( aliases )
2014-01-26 00:44:14 +04:00
self . is_list = is_list
self . is_onoff = is_onoff
2013-09-28 00:52:41 +04:00
2014-01-19 19:37:14 +04:00
def parse ( self , opts , inst , support_cb = None , lookup = False ) :
2014-01-25 02:58:12 +04:00
val = None
for cliname in self . aliases + [ self . cliname ] :
# We iterate over all values unconditionally, so they are
# removed from opts
2014-01-26 05:20:55 +04:00
foundval = opts . get_opt_param ( cliname )
2014-01-25 02:58:12 +04:00
if foundval is not None :
val = foundval
2014-01-19 22:56:06 +04:00
if val is None :
return
2014-01-19 19:37:14 +04:00
if val == " " :
val = None
2013-09-28 00:52:41 +04:00
2014-01-19 22:56:06 +04:00
if support_cb :
support_cb ( inst , self . attrname , self . cliname )
if self . is_onoff :
val = _on_off_convert ( self . cliname , val )
2014-01-19 19:37:14 +04:00
if val == " default " and self . ignore_default and not lookup :
2014-01-19 22:56:06 +04:00
return
2014-01-19 19:37:14 +04:00
if lookup and not self . attrname :
2014-02-03 20:21:16 +04:00
raise RuntimeError (
_ ( " Don ' t know how to match %(device_type)s "
" property %(property_name)s " ) %
{ " device_type " : getattr ( inst , " virtual_device_type " , " " ) ,
" property_name " : self . cliname } )
2014-01-19 19:37:14 +04:00
2014-01-19 22:56:06 +04:00
try :
2014-01-19 19:37:14 +04:00
if self . attrname :
eval ( " inst. " + self . attrname )
2014-01-19 22:56:06 +04:00
except AttributeError :
raise RuntimeError ( " programming error: obj= %s does not have "
" member= %s " % ( inst , self . attrname ) )
2014-01-19 19:37:14 +04:00
if lookup :
return eval ( " inst. " + self . attrname ) == val
elif self . setter_cb :
2014-01-19 22:56:06 +04:00
self . setter_cb ( opts , inst , self . cliname , val )
else :
exec ( " inst. " + self . attrname + " = val " ) # pylint: disable=W0122
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
class VirtOptionString ( object ) :
2014-01-26 00:44:14 +04:00
def __init__ ( self , optstr , virtargs , remove_first ) :
2014-01-19 22:56:06 +04:00
"""
Helper class for parsing opt strings of the form
opt1 = val1 , opt2 = val2 , . . .
@optstr : The full option string
@virtargs : A list of VirtCLIArguments
@remove_first : List or parameters to peel off the front of
option string , and store in the returned dict .
remove_first = [ " char_type " ] for - - serial pty , foo = bar
maps to { " char_type " , " pty " , " foo " : " bar " }
"""
self . fullopts = optstr
2013-09-28 04:16:35 +04:00
2014-01-19 22:56:06 +04:00
virtargmap = dict ( ( arg . cliname , arg ) for arg in virtargs )
2013-09-28 04:16:35 +04:00
2014-01-19 22:56:06 +04:00
# @opts: A dictionary of the mapping {cliname: val}
# @orderedopts: A list of tuples (cliname: val), in the order
# they appeared on the CLI.
self . opts , self . orderedopts = self . _parse_optstr (
virtargmap , remove_first )
2013-03-18 01:06:52 +04:00
2014-01-26 05:20:55 +04:00
def get_opt_param ( self , key ) :
2014-01-26 05:27:49 +04:00
if key not in self . opts :
return None
ret = self . opts . pop ( key )
if ret is None :
raise RuntimeError ( " Option ' %s ' had no value set. " % key )
return ret
2013-09-28 04:16:35 +04:00
2014-01-19 22:56:06 +04:00
def check_leftover_opts ( self ) :
if not self . opts :
2013-10-03 02:06:52 +04:00
return
2014-01-19 22:56:06 +04:00
raise fail ( _ ( " Unknown options %s " ) % self . opts . keys ( ) )
2013-09-28 04:16:35 +04:00
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
###########################
# Actual parsing routines #
###########################
2013-04-13 22:34:52 +04:00
2014-01-19 22:56:06 +04:00
def _parse_optstr_tuples ( self , virtargmap , remove_first ) :
"""
Parse the command string into an ordered list of tuples ( see
docs for orderedopts
"""
optstr = str ( self . fullopts or " " )
optlist = [ ]
argsplitter = shlex . shlex ( optstr , posix = True )
argsplitter . commenters = " "
argsplitter . whitespace = " , "
argsplitter . whitespace_split = True
remove_first = util . listify ( remove_first ) [ : ]
commaopt = None
for opt in list ( argsplitter ) :
if not opt :
continue
2013-09-28 04:16:35 +04:00
2014-01-19 22:56:06 +04:00
cliname = opt
val = None
if opt . count ( " = " ) :
cliname , val = opt . split ( " = " , 1 )
remove_first = [ ]
elif remove_first :
val = cliname
cliname = remove_first . pop ( 0 )
if commaopt :
if cliname in virtargmap :
optlist . append ( tuple ( commaopt ) )
commaopt = None
else :
2014-01-25 03:07:45 +04:00
commaopt [ 1 ] + = " , " + cliname
if val :
commaopt [ 1 ] + = " = " + val
2014-01-19 22:56:06 +04:00
continue
if ( cliname in virtargmap and virtargmap [ cliname ] . can_comma ) :
commaopt = [ cliname , val ]
continue
2013-09-28 04:16:35 +04:00
2014-01-19 22:56:06 +04:00
optlist . append ( ( cliname , val ) )
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
if commaopt :
optlist . append ( tuple ( commaopt ) )
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
return optlist
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
def _parse_optstr ( self , virtargmap , remove_first ) :
orderedopts = self . _parse_optstr_tuples ( virtargmap , remove_first )
optdict = { }
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
for cliname , val in orderedopts :
if ( cliname not in optdict and
cliname in virtargmap and
virtargmap [ cliname ] . is_list ) :
optdict [ cliname ] = [ ]
if type ( optdict . get ( cliname ) ) is list :
optdict [ cliname ] . append ( val )
else :
optdict [ cliname ] = val
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
return optdict , orderedopts
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2014-01-19 22:56:06 +04:00
class VirtCLIParser ( object ) :
2013-03-18 01:06:52 +04:00
"""
2014-01-19 22:56:06 +04:00
Parse a compound arg string like - - option foo = bar , baz = 12. This is
the desired interface to VirtCLIArgument and VirtCLIOptionString .
A command line argument just extends this interface , implements
_init_params , and calls set_param in the order it wants the options
parsed on the command line . See existing impls examples of how to
2014-01-19 19:37:14 +04:00
do all sorts of crazy stuff .
set_param must be set unconditionally ( ex from _init_params and not
from overriding _parse ) , so that we can show all options when the
user requests command line introspection like - - disk = ?
2013-03-18 01:06:52 +04:00
"""
2014-01-19 22:56:06 +04:00
devclass = None
2013-03-18 01:06:52 +04:00
2014-01-21 23:28:47 +04:00
def __init__ ( self , cli_arg_name ) :
2014-01-19 22:56:06 +04:00
"""
These values should be set by subclasses in _init_params
2014-01-21 23:28:47 +04:00
@cli_arg_name : The command line argument this maps to , so
" host-device " for - - host - device
2014-01-19 22:56:06 +04:00
@guest : Will be set parse ( ) , the toplevel virtinst . Guest object
@remove_first : Passed to VirtOptionString
@check_none : If the parsed option string is just ' none ' , return None
@support_cb : An extra support check function for further validation .
Called before the virtinst object is altered . Take arguments
( inst , attrname , cliname )
2014-01-26 00:44:14 +04:00
@clear_attr : If the user requests to clear the XML ( - - disk clearxml ) ,
this is the property name we grab from inst to actually clear
( so ' security ' to get guest . security ) . If it ' s True, then
clear inst ( in the case of devices )
2014-01-19 22:56:06 +04:00
"""
2014-01-21 23:28:47 +04:00
self . cli_arg_name = cli_arg_name
# This is the name of the variable that argparse will set in
# the result of parse_args()
self . option_variable_name = cli_arg_name . replace ( " - " , " _ " )
2014-01-19 22:56:06 +04:00
self . guest = None
self . remove_first = None
self . check_none = False
self . support_cb = None
2014-01-26 00:44:14 +04:00
self . clear_attr = None
2014-01-19 22:56:06 +04:00
self . _params = [ ]
self . _inparse = False
2014-01-26 00:44:14 +04:00
self . __init_global_params ( )
2014-01-19 22:56:06 +04:00
self . _init_params ( )
2014-01-26 00:44:14 +04:00
def __init_global_params ( self ) :
def set_clearxml_cb ( opts , inst , cliname , val ) :
ignore = opts = cliname
if not self . clear_attr and not self . devclass :
raise RuntimeError ( " Don ' t know how to clearxml -- %s " %
self . cli_arg_name )
clearobj = inst
if self . clear_attr :
clearobj = getattr ( inst , self . clear_attr )
if val is not True :
return
clearobj . clear ( )
self . set_param ( None , " clearxml " ,
2014-01-26 05:20:55 +04:00
setter_cb = set_clearxml_cb , is_onoff = True )
2014-01-26 00:44:14 +04:00
2014-01-22 18:06:35 +04:00
def check_introspection ( self , option ) :
for optstr in util . listify ( option ) :
2014-01-27 23:48:23 +04:00
if optstr == " ? " or optstr == " help " :
2014-01-22 18:06:35 +04:00
print " -- %s options: " % self . cli_arg_name
for arg in sorted ( self . _params , key = lambda p : p . cliname ) :
print " %s " % arg . cliname
print
return True
return False
2014-01-19 22:56:06 +04:00
def set_param ( self , * args , * * kwargs ) :
if self . _inparse :
# Otherwise we might break command line introspection
raise RuntimeError ( " programming error: Can not call set_param "
" from parse handler. " )
self . _params . append ( _VirtCLIArgument ( * args , * * kwargs ) )
2014-01-25 04:05:04 +04:00
def parse ( self , guest , optlist , inst , validate = True ) :
2014-01-21 17:48:22 +04:00
optlist = util . listify ( optlist )
editting = bool ( inst )
if editting and optlist :
# If an object is passed in, we are updating it in place, and
2014-01-21 23:28:47 +04:00
# only use the last command line occurence, eg. from virt-xml
2014-01-21 17:48:22 +04:00
optlist = [ optlist [ - 1 ] ]
ret = [ ]
for optstr in optlist :
optinst = inst
if self . devclass and not inst :
optinst = self . devclass ( guest . conn ) # pylint: disable=E1102
2014-01-19 22:56:06 +04:00
try :
2014-01-21 17:48:22 +04:00
devs = self . _parse_single_optstr ( guest , optstr , optinst )
2014-01-19 22:56:06 +04:00
for dev in util . listify ( devs ) :
2014-01-21 17:48:22 +04:00
if not hasattr ( dev , " virtual_device_type " ) :
continue
if validate :
dev . validate ( )
if editting :
continue
2014-01-19 22:56:06 +04:00
guest . add_device ( dev )
2014-01-21 17:48:22 +04:00
ret + = util . listify ( devs )
2014-01-19 22:56:06 +04:00
except Exception , e :
2014-01-21 17:48:22 +04:00
logging . debug ( " Exception parsing inst= %s optstr= %s " ,
inst , optstr , exc_info = True )
2014-01-21 23:28:47 +04:00
fail ( _ ( " Error: -- %(cli_arg_name)s %(options)s : %(err)s " ) %
{ " cli_arg_name " : self . cli_arg_name ,
" options " : optstr , " err " : str ( e ) } )
2014-01-21 17:48:22 +04:00
if not ret :
return None
if len ( ret ) == 1 :
return ret [ 0 ]
return ret
2013-03-18 01:06:52 +04:00
2014-01-19 19:37:14 +04:00
def lookup_device_from_option_string ( self , guest , optstr ) :
"""
Given a passed option string , search the guests ' device list
for all devices which match the passed options .
"""
devlist = guest . get_devices ( self . devclass . virtual_device_type ) [ : ]
ret = [ ]
for inst in devlist :
2014-01-26 00:44:14 +04:00
opts = VirtOptionString ( optstr , self . _params , self . remove_first )
2014-01-19 19:37:14 +04:00
valid = True
for param in self . _params :
if param . parse ( opts , inst ,
support_cb = None , lookup = True ) is False :
valid = False
break
if valid :
ret . append ( inst )
return ret
2014-01-21 17:48:22 +04:00
def _parse_single_optstr ( self , guest , optstr , inst ) :
2014-01-19 22:56:06 +04:00
if not optstr :
return None
if self . check_none and optstr == " none " :
return None
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
if not inst :
inst = guest
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
try :
self . guest = guest
self . _inparse = True
2014-01-26 00:44:14 +04:00
opts = VirtOptionString ( optstr , self . _params , self . remove_first )
2014-01-19 22:56:06 +04:00
return self . _parse ( opts , inst )
finally :
self . guest = None
self . _inparse = False
def _parse ( self , opts , inst ) :
for param in self . _params :
param . parse ( opts , inst , self . support_cb )
opts . check_leftover_opts ( )
return inst
def _init_params ( self ) :
raise NotImplementedError ( )
2013-03-18 01:06:52 +04:00
2014-01-25 05:03:30 +04:00
######################
# --metadata parsing #
######################
class ParserMetadata ( VirtCLIParser ) :
def _init_params ( self ) :
self . set_param ( " name " , " name " , can_comma = True )
self . set_param ( " title " , " title " , can_comma = True )
self . set_param ( " uuid " , " uuid " )
self . set_param ( " description " , " description " , can_comma = True )
2013-03-18 01:06:52 +04:00
######################
# --numatune parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserNumatune ( VirtCLIParser ) :
def _init_params ( self ) :
2014-01-26 00:44:14 +04:00
self . clear_attr = " numatune "
2014-01-19 22:56:06 +04:00
self . remove_first = " nodeset "
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " numatune.memory_nodeset " , " nodeset " , can_comma = True )
self . set_param ( " numatune.memory_mode " , " mode " )
2013-03-18 01:06:52 +04:00
2013-07-30 22:26:53 +04:00
2014-01-25 03:56:59 +04:00
####################
# --memory parsing #
####################
class ParserMemory ( VirtCLIParser ) :
def _init_params ( self ) :
self . remove_first = " memory "
def set_memory_cb ( opts , inst , cliname , val ) :
ignore = opts
setattr ( inst , cliname , int ( val ) * 1024 )
self . set_param ( " memory " , " memory " , setter_cb = set_memory_cb )
self . set_param ( " maxmemory " , " maxmemory " , setter_cb = set_memory_cb )
self . set_param ( " hugepage " , " hugepages " , is_onoff = True )
2014-01-19 19:37:14 +04:00
###################
# --vcpus parsing #
###################
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
class ParserVCPU ( VirtCLIParser ) :
def _init_params ( self ) :
self . remove_first = " vcpus "
self . set_param ( " cpu.sockets " , " sockets " )
self . set_param ( " cpu.cores " , " cores " )
self . set_param ( " cpu.threads " , " threads " )
def set_vcpus_cb ( opts , inst , cliname , val ) :
ignore = cliname
attrname = ( " maxvcpus " in opts . opts ) and " curvcpus " or " vcpus "
setattr ( inst , attrname , val )
self . set_param ( None , " vcpus " , setter_cb = set_vcpus_cb )
self . set_param ( " vcpus " , " maxvcpus " )
2013-03-18 01:06:52 +04:00
2014-01-22 00:24:46 +04:00
def set_cpuset_cb ( opts , inst , cliname , val ) :
if val == " auto " :
try :
val = virtinst . DomainNumatune . generate_cpuset (
inst . conn , inst . memory )
logging . debug ( " Auto cpuset is: %s " , val )
except Exception , e :
logging . error ( " Not setting cpuset: %s " , str ( e ) )
val = None
if val :
inst . cpuset = val
self . set_param ( None , " cpuset " , can_comma = True ,
setter_cb = set_cpuset_cb )
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
def _parse ( self , opts , inst ) :
set_from_top = ( " maxvcpus " not in opts . opts and
" vcpus " not in opts . opts )
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
ret = VirtCLIParser . _parse ( self , opts , inst )
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
if set_from_top :
inst . vcpus = inst . cpu . vcpus_from_topology ( )
return ret
2013-03-18 01:06:52 +04:00
2013-07-30 22:26:53 +04:00
2013-03-18 01:06:52 +04:00
#################
# --cpu parsing #
#################
2014-01-19 22:56:06 +04:00
class ParserCPU ( VirtCLIParser ) :
def _init_params ( self ) :
2014-01-26 00:44:14 +04:00
self . clear_attr = " cpu "
2014-01-19 22:56:06 +04:00
self . remove_first = " model "
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
def set_model_cb ( opts , inst , cliname , val ) :
ignore = opts
ignore = cliname
if val == " host " :
2014-02-05 22:51:53 +04:00
val = inst . cpu . SPECIAL_MODE_HOST_COPY
if val == " none " :
val = inst . cpu . SPECIAL_MODE_CLEAR
if val in inst . cpu . SPECIAL_MODES :
inst . cpu . set_special_mode ( val )
2014-01-19 22:56:06 +04:00
else :
inst . cpu . model = val
def set_feature_cb ( opts , inst , cliname , val ) :
ignore = opts
policy = cliname
for feature_name in util . listify ( val ) :
2014-01-19 19:37:14 +04:00
featureobj = None
for f in inst . cpu . features :
if f . name == feature_name :
featureobj = f
break
if featureobj :
featureobj . policy = policy
else :
inst . cpu . add_feature ( feature_name , policy )
2014-01-19 22:56:06 +04:00
self . set_param ( None , " model " , setter_cb = set_model_cb )
2014-02-03 00:49:42 +04:00
self . set_param ( " cpu.mode " , " mode " )
2014-01-19 22:56:06 +04:00
self . set_param ( " cpu.match " , " match " )
self . set_param ( " cpu.vendor " , " vendor " )
self . set_param ( None , " force " , is_list = True , setter_cb = set_feature_cb )
self . set_param ( None , " require " , is_list = True , setter_cb = set_feature_cb )
self . set_param ( None , " optional " , is_list = True , setter_cb = set_feature_cb )
self . set_param ( None , " disable " , is_list = True , setter_cb = set_feature_cb )
self . set_param ( None , " forbid " , is_list = True , setter_cb = set_feature_cb )
def _parse ( self , optsobj , inst ) :
opts = optsobj . opts
# Convert +feature, -feature into expected format
for key , value in opts . items ( ) :
policy = None
if value or len ( key ) == 1 :
continue
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
if key . startswith ( " + " ) :
policy = " force "
elif key . startswith ( " - " ) :
policy = " disable "
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
if policy :
del ( opts [ key ] )
if opts . get ( policy ) is None :
opts [ policy ] = [ ]
opts [ policy ] . append ( key [ 1 : ] )
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
return VirtCLIParser . _parse ( self , optsobj , inst )
2013-03-18 01:06:52 +04:00
##################
# --boot parsing #
##################
2014-01-19 22:56:06 +04:00
class ParserBoot ( VirtCLIParser ) :
def _init_params ( self ) :
2014-01-26 00:44:14 +04:00
self . clear_attr = " os "
2014-01-19 22:56:06 +04:00
self . set_param ( " os.useserial " , " useserial " , is_onoff = True )
self . set_param ( " os.enable_bootmenu " , " menu " , is_onoff = True )
self . set_param ( " os.kernel " , " kernel " )
self . set_param ( " os.initrd " , " initrd " )
self . set_param ( " os.dtb " , " dtb " )
self . set_param ( " os.loader " , " loader " )
2014-01-25 02:58:12 +04:00
self . set_param ( " os.kernel_args " , " kernel_args " , aliases = [ " extra_args " ] )
2014-01-22 00:36:34 +04:00
self . set_param ( " os.init " , " init " )
2014-01-25 02:47:09 +04:00
self . set_param ( " os.arch " , " arch " )
self . set_param ( " type " , " domain_type " )
self . set_param ( " os.machine " , " machine " )
self . set_param ( " os.os_type " , " os_type " )
self . set_param ( " emulator " , " emulator " )
2014-01-19 22:56:06 +04:00
# Order matters for boot devices, we handle it specially in parse
def noset_cb ( val ) :
ignore = val
for b in virtinst . OSXML . BOOT_DEVICES :
self . set_param ( noset_cb , b )
def _parse ( self , opts , inst ) :
# Build boot order
2013-03-18 01:06:52 +04:00
boot_order = [ ]
2014-01-19 22:56:06 +04:00
for cliname , ignore in opts . orderedopts :
if not cliname in inst . os . BOOT_DEVICES :
2013-03-18 01:06:52 +04:00
continue
2014-01-19 22:56:06 +04:00
del ( opts . opts [ cliname ] )
if cliname not in boot_order :
boot_order . append ( cliname )
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
if boot_order :
inst . os . bootorder = boot_order
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
VirtCLIParser . _parse ( self , opts , inst )
2013-07-30 22:26:53 +04:00
2014-02-09 19:25:25 +04:00
######################
# --idmap parsing #
######################
class ParserIdmap ( VirtCLIParser ) :
def _init_params ( self ) :
self . clear_attr = " idmap "
self . set_param ( " idmap.uid_start " , " uid_start " )
self . set_param ( " idmap.uid_target " , " uid_target " )
self . set_param ( " idmap.uid_count " , " uid_count " )
self . set_param ( " idmap.gid_start " , " gid_start " )
self . set_param ( " idmap.gid_target " , " gid_target " )
self . set_param ( " idmap.gid_count " , " gid_count " )
2013-03-18 01:06:52 +04:00
######################
# --security parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserSecurity ( VirtCLIParser ) :
def _init_params ( self ) :
2014-01-26 00:44:14 +04:00
self . clear_attr = " seclabel "
2014-01-19 22:56:06 +04:00
self . set_param ( " seclabel.type " , " type " )
self . set_param ( " seclabel.label " , " label " , can_comma = True )
self . set_param ( " seclabel.relabel " , " relabel " ,
is_onoff = True )
2013-03-18 01:06:52 +04:00
2013-09-28 17:36:11 +04:00
######################
# --features parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserFeatures ( VirtCLIParser ) :
def _init_params ( self ) :
2014-01-26 00:44:14 +04:00
self . clear_attr = " features "
2014-01-19 22:56:06 +04:00
self . set_param ( " features.acpi " , " acpi " , is_onoff = True )
self . set_param ( " features.apic " , " apic " , is_onoff = True )
self . set_param ( " features.pae " , " pae " , is_onoff = True )
self . set_param ( " features.privnet " , " privnet " ,
is_onoff = True )
self . set_param ( " features.hap " , " hap " ,
is_onoff = True )
self . set_param ( " features.viridian " , " viridian " ,
is_onoff = True )
self . set_param ( " features.eoi " , " eoi " , is_onoff = True )
self . set_param ( " features.hyperv_vapic " , " hyperv_vapic " ,
is_onoff = True )
self . set_param ( " features.hyperv_relaxed " , " hyperv_relaxed " ,
is_onoff = True )
self . set_param ( " features.hyperv_spinlocks " , " hyperv_spinlocks " ,
is_onoff = True )
self . set_param ( " features.hyperv_spinlocks_retries " ,
" hyperv_spinlocks_retries " )
2013-03-18 01:06:52 +04:00
2013-10-06 00:45:15 +04:00
###################
# --clock parsing #
###################
2014-01-19 22:56:06 +04:00
class ParserClock ( VirtCLIParser ) :
def _init_params ( self ) :
2014-01-26 00:44:14 +04:00
self . clear_attr = " clock "
2014-01-19 22:56:06 +04:00
self . set_param ( " clock.offset " , " offset " )
2013-10-06 00:45:15 +04:00
2014-01-19 22:56:06 +04:00
def set_timer ( opts , inst , cliname , val ) :
ignore = opts
tname , attrname = cliname . split ( " _ " )
2013-10-06 00:45:15 +04:00
2014-01-19 22:56:06 +04:00
timerobj = None
for t in inst . clock . timers :
if t . name == tname :
timerobj = t
break
2013-10-06 00:45:15 +04:00
2014-01-19 22:56:06 +04:00
if not timerobj :
timerobj = inst . clock . add_timer ( )
timerobj . name = tname
2013-10-06 00:45:15 +04:00
2014-01-19 22:56:06 +04:00
setattr ( timerobj , attrname , val )
2013-10-06 00:45:15 +04:00
2014-01-19 22:56:06 +04:00
for tname in virtinst . Clock . TIMER_NAMES :
self . set_param ( None , tname + " _present " ,
is_onoff = True ,
setter_cb = set_timer )
self . set_param ( None , tname + " _tickpolicy " , setter_cb = set_timer )
2014-02-03 01:12:29 +04:00
################
# --pm parsing #
################
class ParserPM ( VirtCLIParser ) :
def _init_params ( self ) :
self . clear_attr = " pm "
self . set_param ( " pm.suspend_to_mem " , " suspend_to_mem " , is_onoff = True )
self . set_param ( " pm.suspend_to_disk " , " suspend_to_disk " , is_onoff = True )
2013-03-18 01:06:52 +04:00
##########################
# Guest <device> parsing #
##########################
##################
# --disk parsing #
##################
def _parse_disk_source ( guest , path , pool , vol , size , fmt , sparse ) :
abspath = None
volinst = None
volobj = None
# Strip media type
2013-04-12 00:32:00 +04:00
if sum ( [ bool ( p ) for p in [ path , pool , vol ] ] ) > 1 :
2013-03-18 01:06:52 +04:00
fail ( _ ( " Cannot specify more than 1 storage path " ) )
if path :
abspath = os . path . abspath ( path )
2013-09-20 04:18:12 +04:00
if os . path . dirname ( abspath ) == " /var/lib/libvirt/images " :
virtinst . StoragePool . build_default_pool ( guest . conn )
2013-03-18 01:06:52 +04:00
elif pool :
if not size :
raise ValueError ( _ ( " Size must be specified with all ' pool= ' " ) )
2013-09-20 04:18:12 +04:00
if pool == " default " :
virtinst . StoragePool . build_default_pool ( guest . conn )
2013-07-26 00:21:30 +04:00
poolobj = guest . conn . storagePoolLookupByName ( pool )
2013-10-02 20:49:42 +04:00
collidelist = [ ]
for disk in guest . get_devices ( " disk " ) :
if ( disk . get_vol_install ( ) and
disk . get_vol_install ( ) . pool . name ( ) == poolobj . name ( ) ) :
collidelist . append ( os . path . basename ( disk . path ) )
2014-02-11 03:27:06 +04:00
tmpvol = virtinst . StorageVolume ( guest . conn )
tmpvol . pool = poolobj
if fmt is None and tmpvol . file_type == tmpvol . TYPE_FILE :
fmt = " raw "
2014-02-05 02:30:24 +04:00
ext = virtinst . StorageVolume . get_file_extension_for_format ( fmt )
2013-10-01 00:21:23 +04:00
vname = virtinst . StorageVolume . find_free_name (
2014-02-05 02:30:24 +04:00
poolobj , guest . name , suffix = ext , collidelist = collidelist )
2013-07-26 00:21:30 +04:00
volinst = virtinst . VirtualDisk . build_vol_install (
guest . conn , vname , poolobj , size , sparse )
2013-03-18 01:06:52 +04:00
if fmt :
2013-09-20 04:18:12 +04:00
if not volinst . supports_property ( " format " ) :
2013-03-18 01:06:52 +04:00
raise ValueError ( _ ( " Format attribute not supported for this "
" volume type " ) )
2013-09-20 04:18:12 +04:00
volinst . format = fmt
2013-03-18 01:06:52 +04:00
elif vol :
if not vol . count ( " / " ) :
raise ValueError ( _ ( " Storage volume must be specified as "
" vol=poolname/volname " ) )
vollist = vol . split ( " / " )
voltuple = ( vollist [ 0 ] , vollist [ 1 ] )
logging . debug ( " Parsed volume: as pool= ' %s ' vol= ' %s ' " ,
voltuple [ 0 ] , voltuple [ 1 ] )
2013-09-20 04:18:12 +04:00
if voltuple [ 0 ] == " default " :
virtinst . StoragePool . build_default_pool ( guest . conn )
2013-03-18 01:06:52 +04:00
volobj = virtinst . VirtualDisk . lookup_vol_object ( guest . conn , voltuple )
return abspath , volinst , volobj
2013-04-13 22:34:52 +04:00
2014-01-19 22:56:06 +04:00
class ParserDisk ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualDisk
self . remove_first = " path "
2014-01-25 04:05:04 +04:00
def noset_cb ( opts , inst , cliname , val ) :
ignore = opts , inst , cliname , val
2014-01-19 22:56:06 +04:00
# These are all handled specially in _parse
2014-01-25 04:05:04 +04:00
self . set_param ( None , " backing_store " , setter_cb = noset_cb )
self . set_param ( None , " pool " , setter_cb = noset_cb )
self . set_param ( None , " vol " , setter_cb = noset_cb )
self . set_param ( None , " size " , setter_cb = noset_cb )
self . set_param ( None , " format " , setter_cb = noset_cb )
self . set_param ( None , " sparse " , setter_cb = noset_cb )
self . set_param ( " path " , " path " )
2014-01-19 22:56:06 +04:00
self . set_param ( " device " , " device " )
self . set_param ( " bus " , " bus " )
self . set_param ( " removable " , " removable " , is_onoff = True )
self . set_param ( " driver_cache " , " cache " )
self . set_param ( " driver_name " , " driver_name " )
self . set_param ( " driver_type " , " driver_type " )
self . set_param ( " driver_io " , " io " )
self . set_param ( " error_policy " , " error_policy " )
self . set_param ( " serial " , " serial " )
self . set_param ( " target " , " target " )
self . set_param ( " sourceStartupPolicy " , " startup_policy " )
2014-01-25 04:05:04 +04:00
self . set_param ( " read_only " , " readonly " , is_onoff = True )
self . set_param ( " shareable " , " shareable " , is_onoff = True )
2014-02-09 22:36:12 +04:00
self . set_param ( " boot.order " , " boot_order " )
2014-01-19 22:56:06 +04:00
2014-02-01 00:38:39 +04:00
self . set_param ( " iotune_rbs " , " read_bytes_sec " )
self . set_param ( " iotune_wbs " , " write_bytes_sec " )
self . set_param ( " iotune_tbs " , " total_bytes_sec " )
self . set_param ( " iotune_ris " , " read_iops_sec " )
self . set_param ( " iotune_wis " , " write_iops_sec " )
self . set_param ( " iotune_tis " , " total_iops_sec " )
2014-01-19 22:56:06 +04:00
def _parse ( self , opts , inst ) :
def parse_size ( val ) :
if val is None :
return None
2013-03-18 01:06:52 +04:00
try :
2014-01-19 22:56:06 +04:00
return float ( val )
2013-03-18 01:06:52 +04:00
except Exception , e :
fail ( _ ( " Improper value for ' size ' : %s " % str ( e ) ) )
2014-01-25 04:05:04 +04:00
def convert_perms ( val ) :
if val is None :
return
if val == " ro " :
opts . opts [ " readonly " ] = " on "
elif val == " sh " :
opts . opts [ " shareable " ] = " on "
elif val == " rw " :
# It's default. Nothing to do.
pass
else :
fail ( _ ( " Unknown ' %s ' value ' %s ' " % ( " perms " , val ) ) )
convert_perms ( opts . get_opt_param ( " perms " ) )
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
path = opts . get_opt_param ( " path " )
2014-01-26 21:24:52 +04:00
had_path = path is not None
2014-01-19 22:56:06 +04:00
backing_store = opts . get_opt_param ( " backing_store " )
pool = opts . get_opt_param ( " pool " )
vol = opts . get_opt_param ( " vol " )
size = parse_size ( opts . get_opt_param ( " size " ) )
fmt = opts . get_opt_param ( " format " )
sparse = _on_off_convert ( " sparse " , opts . get_opt_param ( " sparse " ) )
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
abspath , volinst , volobj = _parse_disk_source (
self . guest , path , pool , vol , size , fmt , sparse )
2014-01-25 04:05:04 +04:00
path = volobj and volobj . path ( ) or abspath
2014-01-26 21:24:52 +04:00
if had_path or path :
opts . opts [ " path " ] = path or " "
2014-01-19 22:56:06 +04:00
inst = VirtCLIParser . _parse ( self , opts , inst )
2014-01-25 04:05:04 +04:00
create_kwargs = { " size " : size , " fmt " : fmt , " sparse " : sparse ,
" vol_install " : volinst , " backing_store " : backing_store }
if any ( create_kwargs . values ( ) ) :
inst . set_create_storage ( * * create_kwargs )
2014-01-19 22:56:06 +04:00
inst . cli_size = size
2014-01-26 06:08:11 +04:00
if not inst . target :
skip_targets = [ d . target for d in self . guest . get_devices ( " disk " ) ]
inst . generate_target ( skip_targets )
inst . cli_set_target = True
2014-01-19 22:56:06 +04:00
return inst
2013-03-18 01:06:52 +04:00
2014-01-21 23:28:47 +04:00
parse_disk = ParserDisk ( " disk " ) . parse
2013-03-18 01:06:52 +04:00
2013-07-13 18:09:00 +04:00
2013-03-18 01:06:52 +04:00
#####################
# --network parsing #
#####################
2014-01-19 22:56:06 +04:00
class ParserNetwork ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualNetworkInterface
self . remove_first = " type "
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
def set_mac_cb ( opts , inst , cliname , val ) :
ignore = opts
ignore = cliname
if val == " RANDOM " :
val = None
inst . macaddr = val
return val
2013-03-18 01:06:52 +04:00
2014-02-06 02:45:46 +04:00
def set_type_cb ( opts , inst , cliname , val ) :
ignore = opts
ignore = cliname
if val == " default " :
inst . set_default_source ( )
else :
inst . type = val
self . set_param ( " type " , " type " , setter_cb = set_type_cb )
2014-01-19 22:56:06 +04:00
self . set_param ( " source " , " source " )
self . set_param ( " source_mode " , " source_mode " )
self . set_param ( " target_dev " , " target " )
self . set_param ( " model " , " model " )
2014-01-19 19:37:14 +04:00
self . set_param ( " macaddr " , " mac " , setter_cb = set_mac_cb )
2014-01-19 22:56:06 +04:00
self . set_param ( " filterref " , " filterref " )
2014-02-09 22:36:12 +04:00
self . set_param ( " boot.order " , " boot_order " )
2013-03-18 01:06:52 +04:00
2014-02-01 16:48:04 +04:00
self . set_param ( " driver_name " , " driver_name " )
self . set_param ( " driver_queues " , " driver_queues " )
2014-02-01 01:51:02 +04:00
self . set_param ( " virtualport.type " , " virtualport_type " )
self . set_param ( " virtualport.managerid " , " virtualport_managerid " )
self . set_param ( " virtualport.typeid " , " virtualport_typeid " )
self . set_param ( " virtualport.typeidversion " ,
" virtualport_typeidversion " )
self . set_param ( " virtualport.instanceid " , " virtualport_instanceid " )
2014-01-19 22:56:06 +04:00
def _parse ( self , optsobj , inst ) :
opts = optsobj . opts
if " type " not in opts :
if " network " in opts :
opts [ " type " ] = virtinst . VirtualNetworkInterface . TYPE_VIRTUAL
opts [ " source " ] = opts . pop ( " network " )
elif " bridge " in opts :
opts [ " type " ] = virtinst . VirtualNetworkInterface . TYPE_BRIDGE
opts [ " source " ] = opts . pop ( " bridge " )
return VirtCLIParser . _parse ( self , optsobj , inst )
2013-03-18 01:06:52 +04:00
######################
# --graphics parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserGraphics ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualGraphics
self . remove_first = " type "
def set_keymap_cb ( opts , inst , cliname , val ) :
ignore = opts
ignore = cliname
from virtinst import hostkeymap
if not val :
val = None
elif val . lower ( ) == " local " :
val = virtinst . VirtualGraphics . KEYMAP_LOCAL
elif val . lower ( ) == " none " :
val = None
else :
use_keymap = hostkeymap . sanitize_keymap ( val )
if not use_keymap :
raise ValueError (
_ ( " Didn ' t match keymap ' %s ' in keytable! " ) % val )
val = use_keymap
inst . keymap = val
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
def set_type_cb ( opts , inst , cliname , val ) :
ignore = opts
if val == " default " :
return
inst . type = val
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( None , " type " , setter_cb = set_type_cb )
self . set_param ( " port " , " port " )
self . set_param ( " tlsPort " , " tlsport " )
self . set_param ( " listen " , " listen " )
self . set_param ( None , " keymap " , setter_cb = set_keymap_cb )
self . set_param ( " passwd " , " password " )
self . set_param ( " passwdValidTo " , " passwordvalidto " )
2014-01-29 18:52:49 +04:00
self . set_param ( " connected " , " connected " )
2013-03-18 01:06:52 +04:00
2014-02-08 01:07:32 +04:00
def _parse ( self , opts , inst ) :
if opts . fullopts == " none " :
self . guest . skip_default_graphics = True
return
return VirtCLIParser . _parse ( self , opts , inst )
2013-03-18 01:06:52 +04:00
2013-07-15 20:36:57 +04:00
########################
# --controller parsing #
########################
2013-04-13 22:34:52 +04:00
2014-01-19 22:56:06 +04:00
class ParserController ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualController
self . remove_first = " type "
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " type " , " type " )
self . set_param ( " model " , " model " )
self . set_param ( " index " , " index " )
self . set_param ( " master_startport " , " master " )
2014-01-19 19:37:14 +04:00
def set_server_cb ( opts , inst , cliname , val ) :
ignore = opts = cliname
inst . address . set_addrstr ( val )
self . set_param ( None , " address " , setter_cb = set_server_cb )
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
def _parse ( self , opts , inst ) :
if opts . fullopts == " usb2 " :
return virtinst . VirtualController . get_usb2_controllers ( inst . conn )
elif opts . fullopts == " usb3 " :
inst . type = " usb "
inst . model = " nec-xhci "
return inst
return VirtCLIParser . _parse ( self , opts , inst )
2013-03-18 01:06:52 +04:00
#######################
# --smartcard parsing #
#######################
2014-01-19 22:56:06 +04:00
class ParserSmartcard ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualSmartCardDevice
self . remove_first = " mode "
self . check_none = True
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " mode " , " mode " )
self . set_param ( " type " , " type " )
2013-03-18 01:06:52 +04:00
######################
# --redirdev parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserRedir ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualRedirDevice
self . remove_first = " bus "
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " bus " , " bus " )
self . set_param ( " type " , " type " )
2014-02-09 22:36:12 +04:00
self . set_param ( " boot.order " , " boot_order " )
2014-01-19 19:37:14 +04:00
def set_server_cb ( opts , inst , cliname , val ) :
ignore = opts = cliname
inst . parse_friendly_server ( val )
self . set_param ( None , " server " , setter_cb = set_server_cb )
2013-03-18 01:06:52 +04:00
2014-02-05 21:58:53 +04:00
def _parse ( self , opts , inst ) :
if opts . fullopts == " none " :
self . guest . skip_default_usbredir = True
return
return VirtCLIParser . _parse ( self , opts , inst )
2013-06-26 05:45:07 +04:00
2013-07-15 20:36:57 +04:00
#################
# --tpm parsing #
#################
2013-06-26 05:45:07 +04:00
2014-01-19 22:56:06 +04:00
class ParserTPM ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualTPMDevice
self . remove_first = " type "
self . check_none = True
2013-06-26 05:45:07 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " type " , " type " )
self . set_param ( " model " , " model " )
self . set_param ( " device_path " , " path " )
2013-06-26 05:45:07 +04:00
2014-01-19 22:56:06 +04:00
def _parse ( self , opts , inst ) :
if ( opts . opts . get ( " type " , " " ) . startswith ( " / " ) ) :
opts . opts [ " path " ] = opts . opts . pop ( " type " )
return VirtCLIParser . _parse ( self , opts , inst )
2013-09-28 18:28:04 +04:00
2013-06-26 05:45:07 +04:00
2013-09-28 00:52:41 +04:00
#################
# --rng parsing #
#################
2014-01-19 22:56:06 +04:00
class ParserRNG ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualRNGDevice
self . remove_first = " type "
self . check_none = True
2013-09-18 17:29:29 +04:00
2014-01-19 22:56:06 +04:00
def set_hosts_cb ( opts , inst , cliname , val ) :
namemap = { }
inst . backend_type = self . _cli_backend_type
2013-09-18 17:29:29 +04:00
2014-01-19 22:56:06 +04:00
if self . _cli_backend_mode == " connect " :
namemap [ " backend_host " ] = " connect_host "
namemap [ " backend_service " ] = " connect_service "
if self . _cli_backend_mode == " bind " :
namemap [ " backend_host " ] = " bind_host "
namemap [ " backend_service " ] = " bind_service "
if self . _cli_backend_type == " udp " :
namemap [ " backend_connect_host " ] = " connect_host "
namemap [ " backend_connect_service " ] = " connect_service "
if cliname in namemap :
setattr ( inst , namemap [ cliname ] , val )
2013-09-28 04:16:35 +04:00
2014-01-19 22:56:06 +04:00
def set_backend_cb ( opts , inst , cliname , val ) :
ignore = opts
ignore = inst
if cliname == " backend_mode " :
self . _cli_backend_mode = val
elif cliname == " backend_type " :
self . _cli_backend_type = val
2013-10-25 19:13:27 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " type " , " type " )
2013-10-25 19:13:27 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( None , " backend_mode " , setter_cb = set_backend_cb )
self . set_param ( None , " backend_type " , setter_cb = set_backend_cb )
2013-10-25 19:13:27 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( None , " backend_host " , setter_cb = set_hosts_cb )
self . set_param ( None , " backend_service " , setter_cb = set_hosts_cb )
self . set_param ( None , " backend_connect_host " , setter_cb = set_hosts_cb )
self . set_param ( None , " backend_connect_service " , setter_cb = set_hosts_cb )
2013-10-25 19:13:27 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " device " , " device " )
self . set_param ( " model " , " model " )
self . set_param ( " rate_bytes " , " rate_bytes " )
self . set_param ( " rate_period " , " rate_period " )
2013-09-18 17:29:29 +04:00
2014-01-19 22:56:06 +04:00
def _parse ( self , optsobj , inst ) :
opts = optsobj . opts
2013-09-18 17:29:29 +04:00
2014-01-19 22:56:06 +04:00
# pylint: disable=W0201
# Defined outside init, but its easier this way
self . _cli_backend_mode = " connect "
self . _cli_backend_type = " udp "
# pylint: enable=W0201
if opts . get ( " type " , " " ) . startswith ( " / " ) :
# Allow --rng /dev/random
opts [ " device " ] = opts . pop ( " type " )
opts [ " type " ] = " random "
return VirtCLIParser . _parse ( self , optsobj , inst )
2013-03-18 01:06:52 +04:00
######################
# --watchdog parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserWatchdog ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualWatchdog
self . remove_first = " model "
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " model " , " model " )
self . set_param ( " action " , " action " )
2013-03-18 01:06:52 +04:00
########################
# --memballoon parsing #
########################
2014-01-19 22:56:06 +04:00
class ParserMemballoon ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualMemballoon
self . remove_first = " model "
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " model " , " model " )
2013-03-18 01:06:52 +04:00
2014-01-22 13:44:38 +04:00
###################
# --panic parsing #
###################
2014-01-19 22:56:06 +04:00
class ParserPanic ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualPanicDevice
self . remove_first = " iobase "
2014-01-22 13:44:38 +04:00
2014-01-19 22:56:06 +04:00
def set_iobase_cb ( opts , inst , cliname , val ) :
ignore = opts
ignore = cliname
if val == " default " :
return
inst . iobase = val
self . set_param ( None , " iobase " , setter_cb = set_iobase_cb )
2014-01-22 13:44:38 +04:00
2014-02-06 18:41:00 +04:00
#######################
# --blkiotune parsing #
#######################
class ParserBlkiotune ( VirtCLIParser ) :
def _init_params ( self ) :
2014-02-07 19:12:54 +04:00
self . clear_attr = " blkiotune "
2014-02-06 18:41:00 +04:00
self . set_param ( " blkiotune.weight " , " weight " )
self . set_param ( " blkiotune.device_path " , " device_path " )
self . set_param ( " blkiotune.device_weight " , " device_weight " )
2013-03-18 01:06:52 +04:00
######################################################
# --serial, --parallel, --channel, --console parsing #
######################################################
2014-01-19 22:56:06 +04:00
class _ParserChar ( VirtCLIParser ) :
def _init_params ( self ) :
self . remove_first = " char_type "
def support_check ( inst , attrname , cliname ) :
if type ( attrname ) is not str :
return
if not inst . supports_property ( attrname ) :
raise ValueError ( _ ( " %(devtype)s type ' %(chartype)s ' does not "
" support ' %(optname)s ' option. " ) %
{ " devtype " : inst . virtual_device_type ,
" chartype " : inst . type ,
" optname " : cliname } )
self . support_cb = support_check
2014-01-19 19:37:14 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " type " , " char_type " )
self . set_param ( " source_path " , " path " )
self . set_param ( " source_mode " , " mode " )
self . set_param ( " protocol " , " protocol " )
self . set_param ( " target_type " , " target_type " )
self . set_param ( " target_name " , " name " )
2014-01-19 19:37:14 +04:00
def set_host_cb ( opts , inst , cliname , val ) :
ignore = opts = cliname
inst . set_friendly_source ( val )
self . set_param ( None , " host " , setter_cb = set_host_cb )
def set_bind_cb ( opts , inst , cliname , val ) :
ignore = opts = cliname
inst . set_friendly_bind ( val )
self . set_param ( None , " bind_host " , setter_cb = set_bind_cb )
def set_target_cb ( opts , inst , cliname , val ) :
ignore = opts = cliname
inst . set_friendly_target ( val )
self . set_param ( None , " target_address " , setter_cb = set_target_cb )
2014-01-19 22:56:06 +04:00
def _parse ( self , opts , inst ) :
if opts . fullopts == " none " and inst . virtual_device_type == " console " :
self . guest . skip_default_console = True
return
if opts . fullopts == " none " and inst . virtual_device_type == " channel " :
self . guest . skip_default_channel = True
return
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
return VirtCLIParser . _parse ( self , opts , inst )
2013-10-06 17:41:37 +04:00
2014-01-19 22:56:06 +04:00
class ParserSerial ( _ParserChar ) :
devclass = virtinst . VirtualSerialDevice
class ParserParallel ( _ParserChar ) :
devclass = virtinst . VirtualParallelDevice
class ParserChannel ( _ParserChar ) :
devclass = virtinst . VirtualChannelDevice
class ParserConsole ( _ParserChar ) :
devclass = virtinst . VirtualConsoleDevice
2013-09-28 00:52:41 +04:00
2013-03-18 01:06:52 +04:00
########################
# --filesystem parsing #
########################
2014-01-19 22:56:06 +04:00
class ParserFilesystem ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualFilesystem
self . remove_first = [ " source " , " target " ]
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " type " , " type " )
self . set_param ( " mode " , " mode " )
self . set_param ( " source " , " source " )
self . set_param ( " target " , " target " )
2013-03-18 01:06:52 +04:00
###################
# --video parsing #
###################
2014-01-19 22:56:06 +04:00
class ParserVideo ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualVideoDevice
self . remove_first = " model "
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " model " , " model " , ignore_default = True )
2013-09-28 04:16:35 +04:00
2013-03-18 01:06:52 +04:00
2014-02-05 21:49:16 +04:00
###################
2014-02-05 21:32:53 +04:00
# --sound parsing #
2014-02-05 21:49:16 +04:00
###################
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
class ParserSound ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualAudio
self . remove_first = " model "
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( " model " , " model " , ignore_default = True )
2013-03-18 01:06:52 +04:00
2014-02-05 21:49:16 +04:00
def _parse ( self , opts , inst ) :
if opts . fullopts == " none " :
self . guest . skip_default_sound = True
return
return VirtCLIParser . _parse ( self , opts , inst )
2013-03-18 01:06:52 +04:00
#####################
2014-02-10 23:24:22 +04:00
# --host-device parsing #
2013-03-18 01:06:52 +04:00
#####################
2014-01-19 22:56:06 +04:00
class ParserHostdev ( VirtCLIParser ) :
def _init_params ( self ) :
self . devclass = virtinst . VirtualHostDevice
self . remove_first = " name "
2013-09-28 04:16:35 +04:00
2014-01-19 22:56:06 +04:00
def set_name_cb ( opts , inst , cliname , val ) :
ignore = opts
ignore = cliname
val = virtinst . NodeDevice . lookupNodeName ( inst . conn , val )
inst . set_from_nodedev ( val )
2013-09-28 04:16:35 +04:00
2014-01-19 22:56:06 +04:00
self . set_param ( None , " name " , setter_cb = set_name_cb )
self . set_param ( " driver_name " , " driver_name " )
2014-02-09 22:36:12 +04:00
self . set_param ( " boot.order " , " boot_order " )
2014-02-10 23:24:22 +04:00
self . set_param ( " rom_bar " , " rom_bar " , is_onoff = True )
2013-09-28 02:06:39 +04:00
2013-09-28 00:52:41 +04:00
2014-01-21 23:28:47 +04:00
###########################
# Register parser classes #
###########################
def build_parser_map ( options , skip = None , only = None ) :
"""
Build a dictionary with mapping of cli - name - > parserinstance , so
- - vcpus - > ParserVCPU object .
"""
parsermap = { }
def register_parser ( cli_arg_name , parserclass ) :
if cli_arg_name in util . listify ( skip ) :
return
if only and cli_arg_name not in util . listify ( only ) :
return
parserobj = parserclass ( cli_arg_name )
if not hasattr ( options , parserobj . option_variable_name ) :
raise RuntimeError ( " programming error: unknown option= %s "
" cliname= %s class= %s " %
( parserobj . option_variable_name ,
parserobj . cli_arg_name , parserclass ) )
parsermap [ parserobj . option_variable_name ] = parserobj
2014-01-25 05:03:30 +04:00
register_parser ( " metadata " , ParserMetadata )
2014-01-25 03:56:59 +04:00
register_parser ( " memory " , ParserMemory )
2014-01-21 23:28:47 +04:00
register_parser ( " vcpus " , ParserVCPU )
register_parser ( " cpu " , ParserCPU )
register_parser ( " numatune " , ParserNumatune )
2014-02-06 18:41:00 +04:00
register_parser ( " blkiotune " , ParserBlkiotune )
2014-02-09 19:25:25 +04:00
register_parser ( " idmap " , ParserIdmap )
2014-01-21 23:28:47 +04:00
register_parser ( " boot " , ParserBoot )
register_parser ( " security " , ParserSecurity )
register_parser ( " features " , ParserFeatures )
register_parser ( " clock " , ParserClock )
2014-02-03 01:12:29 +04:00
register_parser ( " pm " , ParserPM )
register_parser ( " features " , ParserFeatures )
2014-01-21 23:28:47 +04:00
register_parser ( " disk " , ParserDisk )
register_parser ( " network " , ParserNetwork )
register_parser ( " graphics " , ParserGraphics )
register_parser ( " controller " , ParserController )
register_parser ( " smartcard " , ParserSmartcard )
register_parser ( " redirdev " , ParserRedir )
register_parser ( " tpm " , ParserTPM )
register_parser ( " rng " , ParserRNG )
register_parser ( " watchdog " , ParserWatchdog )
register_parser ( " memballoon " , ParserMemballoon )
register_parser ( " serial " , ParserSerial )
register_parser ( " parallel " , ParserParallel )
register_parser ( " channel " , ParserChannel )
register_parser ( " console " , ParserConsole )
register_parser ( " filesystem " , ParserFilesystem )
register_parser ( " video " , ParserVideo )
2014-02-05 21:32:53 +04:00
register_parser ( " sound " , ParserSound )
2014-01-21 23:28:47 +04:00
register_parser ( " host-device " , ParserHostdev )
register_parser ( " panic " , ParserPanic )
return parsermap
2014-01-25 04:05:04 +04:00
def parse_option_strings ( parsermap , options , guest , instlist , update = False ) :
2014-01-21 23:28:47 +04:00
"""
Iterate over the parsermap , and launch the associated parser
function for every value that was filled in on ' options ' , which
came from argparse / the command line .
2014-01-25 04:05:04 +04:00
@update : If we are updating an existing guest , like from virt - xml
2014-01-21 23:28:47 +04:00
"""
2014-01-19 19:37:14 +04:00
instlist = util . listify ( instlist )
if not instlist :
instlist = [ None ]
2014-01-26 04:51:56 +04:00
ret = [ ]
2014-01-21 23:28:47 +04:00
for option_variable_name in dir ( options ) :
if option_variable_name not in parsermap :
continue
2014-01-19 19:37:14 +04:00
for inst in util . listify ( instlist ) :
2014-01-26 04:51:56 +04:00
parseret = parsermap [ option_variable_name ] . parse (
2014-01-25 04:05:04 +04:00
guest , getattr ( options , option_variable_name ) , inst ,
validate = not update )
2014-01-26 04:51:56 +04:00
ret + = util . listify ( parseret )
return ret
2014-01-22 18:06:35 +04:00
def check_option_introspection ( options , parsermap ) :
"""
2014-01-25 04:05:04 +04:00
Check if the user requested option introspection with ex : ' --disk=? '
2014-01-22 18:06:35 +04:00
"""
ret = False
for option_variable_name in dir ( options ) :
if option_variable_name not in parsermap :
continue
if parsermap [ option_variable_name ] . check_introspection (
getattr ( options , option_variable_name ) ) :
ret = True
return ret