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
2016-06-12 17:11:11 +03:00
import collections
2013-03-18 01:06:52 +04:00
import logging
import logging . handlers
2013-04-12 16:26:21 +04:00
import os
2016-06-15 00:29:54 +03:00
import re
2013-03-18 01:06:52 +04:00
import shlex
2015-03-23 16:39:14 +03:00
import subprocess
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
2015-04-06 22:42:40 +03:00
from virtcli import CLIConfig
2013-03-18 02:18:22 +04:00
2014-09-12 23:59:22 +04:00
from . import util
from . clock import Clock
2015-09-05 00:03:31 +03:00
from . cpu import CPU
2014-09-12 23:59:22 +04:00
from . deviceaudio import VirtualAudio
from . devicechar import ( VirtualChannelDevice , VirtualConsoleDevice ,
VirtualSerialDevice , VirtualParallelDevice )
from . devicecontroller import VirtualController
from . devicedisk import VirtualDisk
from . devicefilesystem import VirtualFilesystem
from . devicegraphics import VirtualGraphics
from . devicehostdev import VirtualHostDevice
2015-04-09 20:22:40 +03:00
from . deviceinput import VirtualInputDevice
2014-09-12 23:59:22 +04:00
from . deviceinterface import VirtualNetworkInterface
from . devicememballoon import VirtualMemballoon
from . devicepanic import VirtualPanicDevice
from . deviceredirdev import VirtualRedirDevice
from . devicerng import VirtualRNGDevice
from . devicesmartcard import VirtualSmartCardDevice
from . devicetpm import VirtualTPMDevice
from . devicevideo import VirtualVideoDevice
from . devicewatchdog import VirtualWatchdog
2015-09-05 00:03:31 +03:00
from . domainblkiotune import DomainBlkiotune
from . domainfeatures import DomainFeatures
from . domainmemorybacking import DomainMemorybacking
from . domainmemorytune import DomainMemorytune
2014-09-12 23:59:22 +04:00
from . domainnumatune import DomainNumatune
2015-09-05 00:03:31 +03:00
from . domainresource import DomainResource
from . idmap import IdMap
2014-09-12 23:59:22 +04:00
from . nodedev import NodeDevice
from . osxml import OSXML
2015-09-05 00:03:31 +03:00
from . pm import PM
from . seclabel import Seclabel
2014-09-12 23:59:22 +04:00
from . storage import StoragePool , StorageVolume
2016-09-07 01:12:20 +03:00
from . sysinfo import SYSInfo
2017-03-06 04:45:33 +03:00
from . xmlnsqemu import XMLNSQemu
2013-03-18 01:06:52 +04:00
2013-03-18 02:18:22 +04:00
2015-04-12 02:25:46 +03:00
##########################
# Global option handling #
##########################
class _GlobalState ( object ) :
def __init__ ( self ) :
self . quiet = False
self . all_checks = None
self . _validation_checks = { }
def set_validation_check ( self , checkname , val ) :
self . _validation_checks [ checkname ] = val
def get_validation_check ( self , checkname ) :
if self . all_checks is not None :
return self . all_checks
# Default to True for all checks
return self . _validation_checks . get ( checkname , True )
_globalstate = None
def get_global_state ( ) :
return _globalstate
def _reset_global_state ( ) :
global _globalstate
_globalstate = _GlobalState ( )
2013-03-18 01:06:52 +04:00
####################
# CLI init helpers #
####################
class VirtStreamHandler ( logging . StreamHandler ) :
def emit ( self , record ) :
"""
Based on the StreamHandler code from python 2.6 : ripping out all
2015-07-30 09:06:49 +03:00
the unicode handling and just unconditionally logging seems to fix
2013-03-18 01:06:52 +04:00
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 ' ,
2015-04-06 22:42:40 +03:00
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 ) :
2015-04-12 02:25:46 +03:00
_reset_global_state ( )
get_global_state ( ) . quiet = do_quiet
2013-03-18 01:06:52 +04:00
2013-10-01 18:12:56 +04:00
vi_dir = None
2014-09-08 18:51:34 +04:00
logfile = None
2016-07-20 16:31:28 +03:00
if not _in_testsuite ( ) :
2013-10-01 18:12:56 +04:00
vi_dir = util . get_cache_dir ( )
2014-09-08 18:51:34 +04:00
logfile = os . path . join ( vi_dir , appname + " .log " )
2013-10-01 18:12:56 +04:00
2014-09-08 18:51:34 +04:00
try :
if vi_dir and not os . access ( vi_dir , os . W_OK ) :
if os . path . exists ( vi_dir ) :
raise RuntimeError ( " No write access to directory %s " % vi_dir )
2013-03-18 01:06:52 +04:00
2014-09-08 18:51:34 +04:00
try :
os . makedirs ( vi_dir , 0751 )
except IOError , e :
raise RuntimeError ( " Could not create directory %s : %s " %
( vi_dir , e ) )
if ( logfile and
os . path . exists ( logfile ) and
not os . access ( logfile , os . W_OK ) ) :
raise RuntimeError ( " No write access to logfile %s " % logfile )
except Exception , e :
logging . warning ( " Error setting up logfile: %s " , e )
logfile = None
2013-03-18 01:06:52 +04:00
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 )
2014-09-08 18:51:34 +04:00
if logfile :
fileHandler = logging . handlers . RotatingFileHandler (
logfile , " ae " , 1024 * 1024 , 5 )
fileHandler . setFormatter (
logging . Formatter ( fileFormat , dateFormat ) )
2013-10-01 18:12:56 +04:00
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 ) )
2015-09-07 01:36:37 +03:00
elif cli_app or not logfile :
2015-04-12 02:25:46 +03:00
if get_global_state ( ) . quiet :
2013-03-18 01:06:52 +04:00
level = logging . ERROR
else :
level = logging . WARN
streamHandler . setLevel ( level )
streamHandler . setFormatter ( logging . Formatter ( streamErrorFormat ) )
2015-09-07 01:36:37 +03:00
else :
streamHandler = None
2013-07-05 23:14:11 +04:00
if streamHandler :
rootLogger . addHandler ( streamHandler )
2013-03-18 01:06:52 +04:00
2014-09-20 19:37:23 +04:00
util . register_libvirt_error_handler ( )
2013-03-18 01:06:52 +04:00
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
2015-09-19 01:31:56 +03:00
logging . getLogger ( " requests " ) . setLevel ( logging . ERROR )
2013-03-18 01:06:52 +04:00
# 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
2016-07-20 16:31:28 +03:00
def _in_testsuite ( ) :
return " VIRTINST_TEST_SUITE " in os . environ
2014-02-18 18:40:39 +04:00
##############################
# Libvirt connection helpers #
##############################
2013-03-18 01:06:52 +04:00
def getConnection ( uri ) :
2014-09-12 23:59:22 +04:00
from . connection import VirtualConnection
2013-03-18 01:06:52 +04:00
logging . debug ( " Requesting libvirt URI %s " , ( uri or " default " ) )
2014-09-12 23:59:22 +04:00
conn = VirtualConnection ( uri )
2013-07-05 16:59:58 +04:00
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 ) :
2015-04-12 02:25:46 +03:00
if do_force or not get_global_state ( ) . quiet :
2013-03-18 01:06:52 +04:00
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-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
def validate_disk ( dev , warn_overwrite = False ) :
2015-04-12 02:25:46 +03:00
def _optional_fail ( msg , checkname ) :
do_check = get_global_state ( ) . get_validation_check ( checkname )
if do_check :
fail ( msg + ( _ ( " (Use --check %s =off or "
" --check all=off to override) " ) % checkname ) )
logging . debug ( " Skipping --check %s error condition ' %s ' " ,
checkname , msg )
logging . warn ( msg )
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
2015-04-12 02:25:46 +03:00
if not VirtualDisk . path_definitely_exists ( dev . conn , dev . path ) :
return
_optional_fail (
2015-06-02 15:21:58 +03:00
_ ( " This will overwrite the existing path ' %s ' " ) % dev . path ,
2015-04-12 02:25:46 +03:00
" path_exists " )
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 . " %
2015-04-12 02:25:46 +03:00
( dev . path , names ) ) ,
" path_in_use " )
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 :
2015-04-12 02:25:46 +03:00
_optional_fail ( errmsg , " disk_size " )
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
2016-06-17 15:57:30 +03:00
def _run_console ( guest , args ) :
2014-02-06 04:09:26 +04:00
logging . debug ( " Running: %s " , " " . join ( args ) )
2016-07-20 16:31:28 +03:00
if _in_testsuite ( ) :
2016-06-17 15:57:30 +03:00
# Add this destroy() in here to trigger more virt-install code
# for the test suite
guest . domain . destroy ( )
return None
2014-02-06 04:09:26 +04:00
child = os . fork ( )
if child :
return child
os . execvp ( args [ 0 ] , args )
2014-04-03 02:39:43 +04:00
os . _exit ( 1 ) # pylint: disable=protected-access
2014-02-06 04:09:26 +04:00
def _gfx_console ( guest ) :
2015-03-23 16:39:14 +03:00
args = [ " virt-viewer " ,
2014-02-06 04:09:26 +04:00
" --connect " , guest . conn . uri ,
" --wait " , guest . name ]
2016-05-04 12:33:26 +03:00
# Currently virt-viewer needs attaching to the local display while
# spice gl is enabled.
if guest . has_gl ( ) :
args . append ( " --attach " )
2014-09-21 02:20:41 +04:00
logging . debug ( " Launching virt-viewer for graphics type ' %s ' " ,
guest . get_devices ( " graphics " ) [ 0 ] . type )
2016-06-17 15:57:30 +03:00
return _run_console ( guest , args )
2014-02-06 04:09:26 +04:00
def _txt_console ( guest ) :
2015-03-23 16:39:14 +03:00
args = [ " virsh " ,
2014-02-06 04:09:26 +04:00
" --connect " , guest . conn . uri ,
" console " , guest . name ]
2014-09-21 02:20:41 +04:00
logging . debug ( " Connecting to text console " )
2016-06-17 15:57:30 +03:00
return _run_console ( guest , args )
2014-02-06 04:09:26 +04:00
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 )
2014-09-21 02:20:41 +04:00
def get_console_cb ( guest ) :
gdevs = guest . get_devices ( " graphics " )
if not gdevs :
return _txt_console
2014-02-06 04:09:26 +04:00
2014-09-21 02:20:41 +04:00
gtype = gdevs [ 0 ] . type
if gtype not in [ " default " ,
VirtualGraphics . TYPE_VNC ,
VirtualGraphics . TYPE_SPICE ] :
2014-02-06 04:09:26 +04:00
logging . debug ( " No viewer to launch for graphics type ' %s ' " , gtype )
2014-09-21 02:20:41 +04:00
return
2016-07-20 16:37:59 +03:00
if not _in_testsuite ( ) :
try :
subprocess . check_output ( [ " virt-viewer " , " --version " ] )
except OSError :
logging . warn ( _ ( " Unable to connect to graphical console: "
" virt-viewer not installed. Please install "
" the ' virt-viewer ' package. " ) )
return None
if not os . environ . get ( " DISPLAY " , " " ) :
logging . warn ( _ ( " Graphics requested but DISPLAY is not set. "
" Not running virt-viewer. " ) )
return None
2014-09-21 02:20:41 +04:00
return _gfx_console
2014-02-06 04:09:26 +04:00
2015-04-12 02:25:46 +03:00
def get_meter ( ) :
2016-07-20 16:31:28 +03:00
quiet = ( get_global_state ( ) . quiet or _in_testsuite ( ) )
2015-09-06 21:26:50 +03:00
return util . make_meter ( quiet = quiet )
2015-04-12 02:25:46 +03:00
2014-02-18 18:40:39 +04:00
###########################
# Common CLI option/group #
###########################
2013-03-18 01:06:52 +04:00
2014-02-12 18:57:40 +04:00
def add_connect_option ( parser , invoker = None ) :
if invoker == " virt-xml " :
parser . add_argument ( " -c " , " --connect " , metavar = " URI " ,
help = _ ( " Connect to hypervisor with libvirt URI " ) )
else :
parser . add_argument ( " --connect " , metavar = " URI " ,
help = _ ( " Connect to hypervisor with libvirt URI " ) )
2013-03-18 01:06:52 +04:00
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 :
2015-04-08 02:58:28 +03:00
print_kwargs = {
" dest " : " xmlonly " ,
" default " : False ,
" help " : _ ( " Print the generated domain XML rather than create "
" the guest. " ) ,
}
if printstep :
print_kwargs [ " nargs " ] = " ? "
print_kwargs [ " const " ] = " all "
else :
print_kwargs [ " action " ] = " store_true "
grp . add_argument ( " --print-xml " , * * print_kwargs )
2013-09-28 19:27:26 +04:00
if printstep :
2015-04-05 00:10:45 +03:00
# Back compat, argparse allows us to use --print-xml
# for everything.
2014-01-19 02:01:43 +04:00
grp . add_argument ( " --print-step " , dest = " xmlstep " ,
2015-04-05 00:10:45 +03:00
help = argparse . SUPPRESS )
2013-09-28 19:27:26 +04:00
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. " ) )
2015-04-12 02:25:46 +03:00
if prompt :
grp . add_argument ( " --check " ,
help = _ ( " Enable or disable validation checks. Example: \n "
" --check path_in_use=off \n "
" --check all=off " ) )
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 "
2014-07-05 00:42:24 +04:00
" --memory 1024 (in MiB) \n "
2014-03-22 20:19:44 +04:00
" --memory 512,maxmemory=1024 " ) )
2014-01-25 03:56:59 +04:00
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 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-09-21 02:56:39 +04:00
" --network none \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 " ) )
2015-04-09 20:22:40 +03:00
devg . add_argument ( " --input " , action = " append " ,
help = _ ( " Configure a guest input device. Ex: \n "
" --input tablet \n "
" --input keyboard,bus=usb " ) )
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-09-20 22:29:34 +04:00
devg . add_argument ( " --hostdev " , action = " append " ,
help = _ ( " Configure physical USB/PCI/etc host devices "
" to be shared with the guest " ) )
2014-09-21 03:30:16 +04:00
devg . add_argument ( " --filesystem " , action = " append " ,
help = _ ( " Pass host directory to the guest. Ex: \n "
" --filesystem /my/source/dir,/dir/in/guest \n "
" --filesystem template_name,/,type=template " ) )
2014-09-20 22:29:34 +04:00
# Back compat name
devg . add_argument ( " --host-device " , action = " append " , dest = " hostdev " ,
help = argparse . SUPPRESS )
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
2014-01-22 01:26:35 +04:00
def add_guest_xml_options ( geng ) :
2015-05-04 01:08:10 +03:00
geng . add_argument ( " --security " , action = " append " ,
2014-07-15 17:25:20 +04:00
help = _ ( " Set domain security driver configuration. " ) )
2014-01-22 01:26:35 +04:00
geng . add_argument ( " --numatune " ,
2014-07-15 17:25:20 +04:00
help = _ ( " Tune NUMA policy for the domain process. " ) )
2014-02-25 06:02:31 +04:00
geng . add_argument ( " --memtune " , action = " append " ,
2014-07-15 17:25:20 +04:00
help = _ ( " Tune memory policy for the domain process. " ) )
2014-02-06 18:41:00 +04:00
geng . add_argument ( " --blkiotune " , action = " append " ,
2014-07-15 17:25:20 +04:00
help = _ ( " Tune blkio policy for the domain process. " ) )
2014-03-22 20:28:23 +04:00
geng . add_argument ( " --memorybacking " , action = " append " ,
2014-07-15 17:25:20 +04:00
help = _ ( " Set memory backing policy for the domain process. Ex: \n "
" --memorybacking hugepages=on " ) )
2014-01-22 01:26:35 +04:00
geng . add_argument ( " --features " ,
2014-07-15 17:25:20 +04:00
help = _ ( " Set domain <features> XML. Ex: \n "
" --features acpi=off \n "
" --features apic=on,eoi=on " ) )
2014-01-22 01:26:35 +04:00
geng . add_argument ( " --clock " ,
2014-07-15 17:25:20 +04:00
help = _ ( " Set domain <clock> XML. Ex: \n "
" --clock offset=localtime,rtc_tickpolicy=catchup " ) )
geng . add_argument ( " --pm " ,
help = _ ( " Configure VM power management features " ) )
2014-05-29 13:03:24 +04:00
geng . add_argument ( " --events " ,
2014-07-15 17:25:20 +04:00
help = _ ( " Configure VM lifecycle management policy " ) )
2014-06-04 06:08:05 +04:00
geng . add_argument ( " --resource " , action = " append " ,
2014-07-15 17:25:20 +04:00
help = _ ( " Configure VM resource partitioning (cgroups) " ) )
2016-09-07 01:12:20 +03:00
geng . add_argument ( " --sysinfo " , action = " append " ,
help = _ ( " Configure SMBIOS System Information. Ex: \n "
" --sysinfo emulate \n "
" --sysinfo host \n "
" --sysinfo bios_vendor=Vendor_Inc.,bios_version=1.2.3-abc,... \n "
" --sysinfo system_manufacturer=System_Corp.,system_product=Computer,... \n "
" --sysinfo baseBoard_manufacturer=Baseboard_Corp.,baseBoard_product=Motherboard,... \n " ) )
2017-03-06 04:45:33 +03:00
geng . add_argument ( " --qemu-commandline " , action = " append " ,
help = _ ( " Pass arguments directly to the qemu emulator. Ex: \n "
" --qemu-commandline= ' -display gtk,gl=on ' \n "
" --qemu-commandline env=DISPLAY=:0.1 " ) )
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 " ,
2014-02-11 18:08:55 +04:00
help = _ ( " Enable user namespace for LXC container. Ex: \n "
2014-02-11 03:13:42 +04:00
" --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 "
2014-06-17 05:33:14 +04:00
" --disk size=10 (new 10GiB image in default location) \n "
2014-12-10 21:19:19 +03:00
" --disk /my/existing/disk,cache=none \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. #
#############################################
2015-11-18 21:59:15 +03:00
def _raw_on_off_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
2014-02-05 01:16:39 +04:00
2015-11-18 21:59:15 +03:00
def _on_off_convert ( key , val ) :
if val is None :
2014-02-05 01:16:39 +04:00
return None
2015-11-18 21:59:15 +03:00
val = _raw_on_off_convert ( val )
2014-02-05 01:16:39 +04:00
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 ) :
2016-06-14 21:37:21 +03: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
@cb : Rather than set an attribute directly on the virtinst
object , ( self , inst , val , virtarg ) 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
the value of this option , ' = ' included . Should be used sparingly .
@aliases : List of cli aliases . Useful if we want to change a property
name on the cli but maintain back compat .
@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 .
@lookup_cb : If specified , use this function for performing match
lookups .
@is_novalue : If specified , the parameter is not expected in the
form FOO = BAR , but just FOO .
@find_inst_cb : If specified , this can be used to return a different
' inst ' to check and set attributes against . For example ,
VirtualDisk has multiple seclabel children , this provides a hook
to lookup the specified child object .
"""
attrname = None
cliname = None
cb = None
can_comma = None
ignore_default = False
aliases = None
is_list = False
is_onoff = False
lookup_cb = None
is_novalue = False
2016-06-15 00:29:54 +03:00
find_inst_cb = None
2016-06-14 21:37:21 +03:00
@staticmethod
def make_arg ( attrname , cliname , * * kwargs ) :
2014-01-19 22:56:06 +04:00
"""
2016-06-14 21:37:21 +03:00
Generates a new VirtCLIArgument class with the passed static
values . Initialize it later with the actual command line and value .
kwargs can be any of the
2014-01-19 22:56:06 +04:00
"""
2016-06-14 21:37:21 +03:00
class VirtAddArg ( _VirtCLIArgument ) :
pass
VirtAddArg . attrname = attrname
VirtAddArg . cliname = cliname
for key , val in kwargs . items ( ) :
# getattr for validation
getattr ( VirtAddArg , key )
setattr ( VirtAddArg , key , val )
return VirtAddArg
@classmethod
def match_name ( cls , cliname ) :
2016-06-14 02:35:21 +03:00
"""
2016-06-14 21:37:21 +03:00
Return True if the passed argument name matches this
VirtCLIArgument . So for an option like - - foo bar = X , this
checks if we are the parser for ' bar '
2016-06-14 14:37:21 +03:00
"""
2016-06-14 21:37:21 +03:00
for argname in [ cls . cliname ] + util . listify ( cls . aliases ) :
2016-06-15 00:29:54 +03:00
if re . match ( " ^ %s $ " % argname , cliname ) :
2016-06-14 21:37:21 +03:00
return True
return False
2016-06-14 14:37:21 +03:00
2016-06-14 21:37:21 +03:00
def __init__ ( self , key , val ) :
2016-06-14 14:37:21 +03:00
"""
2016-06-14 21:37:21 +03:00
Instantiate a VirtCLIArgument with the actual key = val pair
from the command line .
2016-06-14 02:35:21 +03:00
"""
2016-06-14 21:37:21 +03:00
# Sanitize the value
2014-01-19 22:56:06 +04:00
if val is None :
2016-06-14 21:37:21 +03:00
if not self . is_novalue :
raise RuntimeError ( " Option ' %s ' had no value set. " % key )
val = " "
2014-01-19 19:37:14 +04:00
if val == " " :
val = None
2014-01-19 22:56:06 +04:00
if self . is_onoff :
2016-06-14 21:37:21 +03:00
val = _on_off_convert ( key , val )
2016-06-14 18:38:53 +03:00
2016-06-14 21:37:21 +03:00
self . val = val
self . key = key
2014-01-19 22:56:06 +04:00
2016-06-14 21:37:21 +03:00
def parse_param ( self , parser , inst , support_cb ) :
2016-06-13 21:16:36 +03:00
"""
2016-06-14 02:35:21 +03:00
Process the cli param against the pass inst .
So if we are VirtCLIArgument for - - disk device = , and the user
2016-06-14 21:37:21 +03:00
specified - - disk device = foo , we were instanciated with
key = device val = foo , so set inst . device = foo
2016-06-13 21:16:36 +03:00
"""
2016-06-14 18:38:53 +03:00
if support_cb :
support_cb ( inst , self )
2016-06-14 21:37:21 +03:00
if self . val == " default " and self . ignore_default :
2016-06-14 18:38:53 +03:00
return
2014-01-19 19:37:14 +04:00
2016-06-15 00:29:54 +03:00
if self . find_inst_cb :
inst = self . find_inst_cb ( parser , # pylint: disable=not-callable
inst , self . val , self , True )
2014-01-19 22:56:06 +04:00
try :
2014-01-19 19:37:14 +04:00
if self . attrname :
2014-09-06 21:44:01 +04:00
eval ( " inst. " + self . attrname ) # pylint: disable=eval-used
2014-01-19 22:56:06 +04:00
except AttributeError :
raise RuntimeError ( " programming error: obj= %s does not have "
" member= %s " % ( inst , self . attrname ) )
2016-06-13 23:30:29 +03:00
if self . cb :
2016-06-14 21:37:21 +03:00
self . cb ( parser , inst , # pylint: disable=not-callable
self . val , self )
2014-01-19 22:56:06 +04:00
else :
2014-04-03 02:39:43 +04:00
exec ( # pylint: disable=exec-used
2016-06-14 21:37:21 +03:00
" inst. " + self . attrname + " = self.val " )
2013-03-18 01:06:52 +04:00
2016-06-14 21:37:21 +03:00
def lookup_param ( self , parser , inst ) :
2016-06-13 02:48:16 +03:00
"""
2016-06-14 02:35:21 +03:00
See if the passed value matches our Argument , like via virt - xml
So if this Argument is for - - disk device = , and the user
2016-06-14 21:37:21 +03:00
specified virt - xml - - edit device = floppy - - disk . . . , we were
instantiated with key = device val = floppy , so return
' inst.device == floppy '
2016-06-13 02:48:16 +03:00
"""
if not self . attrname and not self . lookup_cb :
raise RuntimeError (
_ ( " Don ' t know how to match device type ' %(device_type)s ' "
" property ' %(property_name)s ' " ) %
{ " device_type " : getattr ( inst , " virtual_device_type " , " " ) ,
2016-06-14 21:37:21 +03:00
" property_name " : self . key } )
2016-06-13 02:48:16 +03:00
2016-06-15 00:29:54 +03:00
if self . find_inst_cb :
inst = self . find_inst_cb ( parser , # pylint: disable=not-callable
inst , self . val , self , False )
if not inst :
return False
2016-06-13 02:48:16 +03:00
if self . lookup_cb :
2016-06-14 21:37:21 +03:00
return self . lookup_cb ( parser , # pylint: disable=not-callable
inst , self . val , self )
2016-06-13 02:48:16 +03:00
else :
return eval ( # pylint: disable=eval-used
2016-06-14 21:37:21 +03:00
" inst. " + self . attrname ) == self . val
2016-06-13 21:16:36 +03:00
def parse_optstr_tuples ( optstr ) :
"""
Parse the command string into an ordered list of tuples . So
a string like - - disk path = foo , size = 5 , path = bar will end up like
[ ( " path " , " foo " ) , ( " size " , " 5 " ) , ( " path " , " bar " ) ]
"""
argsplitter = shlex . shlex ( optstr or " " , posix = True )
argsplitter . commenters = " "
argsplitter . whitespace = " , "
argsplitter . whitespace_split = True
ret = [ ]
for opt in list ( argsplitter ) :
if not opt :
continue
if opt . count ( " = " ) :
cliname , val = opt . split ( " = " , 1 )
else :
cliname = opt
val = None
ret . append ( ( cliname , val ) )
return ret
2013-03-18 01:06:52 +04:00
2016-06-13 21:16:36 +03:00
2016-06-14 14:37:21 +03:00
def _parse_optstr_to_dict ( optstr , virtargs , remove_first ) :
"""
Parse the passed argument string into an OrderedDict WRT
the passed list of VirtCLIArguments and their special handling .
2013-04-13 22:34:52 +04:00
2016-06-14 14:37:21 +03:00
So for - - disk path = foo , size = 5 , optstr is ' path=foo,size=5 ' , and
we return { " path " : " foo " , " size " : " 5 " }
"""
2016-06-14 20:54:37 +03:00
optdict = collections . OrderedDict ( )
2016-06-14 14:37:21 +03:00
opttuples = parse_optstr_tuples ( optstr )
2014-01-19 22:56:06 +04:00
2016-06-14 14:37:21 +03:00
def _add_opt ( virtarg , cliname , val ) :
2016-06-14 20:54:37 +03:00
if ( cliname not in optdict and
2016-06-14 14:37:21 +03:00
virtarg . is_list ) :
2016-06-14 20:54:37 +03:00
optdict [ cliname ] = [ ]
2014-01-19 22:56:06 +04:00
2016-06-14 20:54:37 +03:00
if type ( optdict . get ( cliname ) ) is list :
optdict [ cliname ] . append ( val )
2016-06-14 14:37:21 +03:00
else :
2016-06-14 20:54:37 +03:00
optdict [ cliname ] = val
2016-06-14 14:37:21 +03:00
def _lookup_virtarg ( cliname ) :
for virtarg in virtargs :
if virtarg . match_name ( cliname ) :
return virtarg
2016-06-14 20:54:37 +03:00
def _consume_comma_arg ( commaopt ) :
while opttuples :
cliname , val = opttuples [ 0 ]
if _lookup_virtarg ( cliname ) :
# Next tuple is for an actual virtarg
break
# Next tuple is a continuation of the comma argument,
# sum it up
opttuples . pop ( 0 )
commaopt [ 1 ] + = " , " + cliname
if val :
commaopt [ 1 ] + = " = " + val
return commaopt
2016-06-14 14:37:21 +03:00
# Splice in remove_first names upfront
for idx , ( cliname , val ) in enumerate ( opttuples ) :
if val is not None or not remove_first :
break
opttuples [ idx ] = ( remove_first . pop ( 0 ) , cliname )
2016-06-14 20:54:37 +03:00
while opttuples :
cliname , val = opttuples . pop ( 0 )
2016-06-14 14:37:21 +03:00
virtarg = _lookup_virtarg ( cliname )
2016-06-14 20:54:37 +03:00
if not virtarg :
optdict [ cliname ] = val
2016-06-14 14:37:21 +03:00
continue
2013-09-28 04:16:35 +04:00
2016-06-14 20:54:37 +03:00
if virtarg . can_comma :
commaopt = _consume_comma_arg ( [ cliname , val ] )
_add_opt ( virtarg , commaopt [ 0 ] , commaopt [ 1 ] )
else :
_add_opt ( virtarg , cliname , val )
2013-03-18 01:06:52 +04:00
2016-06-14 20:54:37 +03:00
return optdict
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 .
2016-06-13 23:30:29 +03:00
A command line argument like - - disk just extends this interface
and calls add_arg a bunch to register subarguments like path = ,
size = , etc . See existing impls examples of how to do all sorts of
crazy stuff .
Class parameters :
2016-06-14 14:37:21 +03:00
@remove_first : List of parameters to peel off the front of the
option string , and store in the optdict . So :
remove_first = [ " char_type " ] for - - serial pty , foo = bar
maps to { " char_type " , " pty " , " foo " : " bar " }
2017-03-09 01:03:01 +03:00
@stub_none : If the parsed option string is just ' none ' , make it a no - op .
This helps us be backwards compatible : for example , - - rng none is
a no - op , but one day we decide to add an rng device by default to
certain VMs , and - - rng none is extended to handle that . - - rng none
can be added to users command lines and it will give the expected
results regardless of the virt - install version .
2016-06-13 23:30:29 +03:00
@support_cb : An extra support check function for further validation .
Called before the virtinst object is altered . Take arguments
( inst , attrname , cliname )
@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 )
2016-06-14 01:50:31 +03:00
@cli_arg_name : The command line argument this maps to , so
" hostdev " for - - hostdev
2013-03-18 01:06:52 +04:00
"""
2015-09-04 23:07:01 +03:00
objclass = None
2016-06-13 23:30:29 +03:00
remove_first = None
2017-03-09 01:03:01 +03:00
stub_none = True
2016-06-13 23:30:29 +03:00
support_cb = None
clear_attr = None
2016-06-14 01:50:31 +03:00
cli_arg_name = None
2016-06-14 14:37:21 +03:00
_virtargs = [ ]
2016-06-13 23:30:29 +03:00
@classmethod
def add_arg ( cls , * args , * * kwargs ) :
"""
Add a VirtCLIArgument for this class .
"""
2016-06-14 14:37:21 +03:00
if not cls . _virtargs :
2016-06-14 21:37:21 +03:00
cls . _virtargs = [ _VirtCLIArgument . make_arg (
None , " clearxml " , cb = cls . _clearxml_cb , is_onoff = True ) ]
cls . _virtargs . append ( _VirtCLIArgument . make_arg ( * args , * * kwargs ) )
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
@classmethod
2016-06-14 18:38:53 +03:00
def print_introspection ( cls ) :
"""
Print out all _param names , triggered via ex . - - disk help
"""
print " -- %s options: " % cls . cli_arg_name
for arg in sorted ( cls . _virtargs , key = lambda p : p . cliname ) :
print " %s " % arg . cliname
print
def __init__ ( self , guest , optstr ) :
self . guest = guest
self . optstr = optstr
self . optdict = _parse_optstr_to_dict ( self . optstr ,
2016-06-14 20:54:37 +03:00
self . _virtargs , util . listify ( self . remove_first ) [ : ] )
2016-06-14 18:38:53 +03:00
def _clearxml_cb ( self , inst , val , virtarg ) :
2016-06-13 23:05:56 +03:00
"""
Callback that handles virt - xml clearxml = yes | no magic
"""
2016-06-14 18:38:53 +03:00
if not self . objclass and not self . clear_attr :
2016-06-13 23:05:56 +03:00
raise RuntimeError ( " Don ' t know how to clearxml -- %s " %
2016-06-14 18:38:53 +03:00
self . cli_arg_name )
2016-06-13 23:05:56 +03:00
if val is not True :
return
2014-01-26 00:44:14 +04:00
2016-06-13 23:05:56 +03:00
clear_inst = inst
2016-06-14 18:38:53 +03:00
if self . clear_attr :
clear_inst = getattr ( inst , self . clear_attr )
2016-06-13 23:05:56 +03:00
# If there's any opts remaining, leave the root stub element
2016-06-14 14:37:21 +03:00
# in place with leave_stub=True, so virt-xml updates are done
# in place.
2016-06-13 23:05:56 +03:00
#
2016-06-14 14:37:21 +03:00
# Example: --edit --cpu clearxml=yes should remove the <cpu>
2016-06-13 23:05:56 +03:00
# block. But --edit --cpu clearxml=yes,model=foo should leave
# a <cpu> stub in place, so that it gets model=foo in place,
2016-10-25 18:35:47 +03:00
# otherwise the newly created cpu block gets appended to the
2016-06-13 23:05:56 +03:00
# end of the domain XML, which gives an ugly diff
2016-06-14 21:37:21 +03:00
clear_inst . clear ( leave_stub = " , " in self . optstr )
def _optdict_to_param_list ( self , optdict ) :
"""
Convert the passed optdict to a list of instantiated
VirtCLIArguments to actually interact with
"""
ret = [ ]
for param in self . _virtargs :
for key in optdict . keys ( ) :
if param . match_name ( key ) :
ret . append ( param ( key , optdict . pop ( key ) ) )
return ret
def _check_leftover_opts ( self , optdict ) :
"""
Used to check if there were any unprocessed entries in the
optdict after we should have emptied it . Like if the user
passed an invalid argument such as - - disk idontexist = foo
"""
if optdict :
fail ( _ ( " Unknown options %s " ) % optdict . keys ( ) )
2014-01-21 17:48:22 +04:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
"""
Subclasses can hook into this to do any pre / post processing
of the inst , or self . optdict
"""
2016-06-14 21:37:21 +03:00
optdict = self . optdict . copy ( )
for param in self . _optdict_to_param_list ( optdict ) :
param . parse_param ( self , inst , self . support_cb )
2014-01-21 17:48:22 +04:00
2016-06-14 21:37:21 +03:00
self . _check_leftover_opts ( optdict )
2016-06-14 14:37:21 +03:00
return inst
2014-01-21 17:48:22 +04:00
2016-06-14 14:37:21 +03:00
def parse ( self , inst , validate = True ) :
"""
Main entry point . Iterate over self . _virtargs , and serialize
self . optdict into ' inst ' .
For virt - xml , ' inst ' is the virtinst object we are editing ,
ex . a VirtualDisk from a parsed Guest object .
For virt - install , ' inst ' is None , and we will create a new
inst from self . objclass , or edit a singleton object in place
like Guest . features / DomainFeatures
"""
if not self . optstr :
2014-01-21 17:48:22 +04:00
return None
2017-03-09 01:03:01 +03:00
if self . stub_none and self . optstr == " none " :
2016-06-14 14:37:21 +03:00
return None
new_object = False
if self . objclass and not inst :
if self . guest . child_class_is_singleton ( self . objclass ) :
inst = self . guest . list_children_for_class ( self . objclass ) [ 0 ]
else :
new_object = True
inst = self . objclass ( # pylint: disable=not-callable
self . guest . conn )
ret = [ ]
try :
objs = self . _parse ( inst or self . guest )
for obj in util . listify ( objs ) :
if not new_object :
break
if validate :
obj . validate ( )
self . guest . add_child ( obj )
ret + = util . listify ( objs )
except Exception , e :
logging . debug ( " Exception parsing inst= %s optstr= %s " ,
inst , self . optstr , exc_info = True )
fail ( _ ( " Error: -- %(cli_arg_name)s %(options)s : %(err)s " ) %
{ " cli_arg_name " : self . cli_arg_name ,
" options " : self . optstr , " err " : str ( e ) } )
2014-01-21 17:48:22 +04:00
return ret
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
def lookup_child_from_option_string ( self ) :
2014-01-19 19:37:14 +04:00
"""
2015-09-04 23:07:01 +03:00
Given a passed option string , search the guests ' child list
for all objects which match the passed options .
2015-09-05 00:03:31 +03:00
Used only by virt - xml - - edit lookups
2014-01-19 19:37:14 +04:00
"""
ret = [ ]
2016-06-14 14:37:21 +03:00
objlist = self . guest . list_children_for_class ( self . objclass )
2014-01-19 19:37:14 +04:00
2016-06-14 21:37:21 +03:00
try :
for inst in objlist :
2016-06-14 14:37:21 +03:00
optdict = self . optdict . copy ( )
2016-06-15 00:29:54 +03:00
valid = True
2016-06-14 21:37:21 +03:00
for param in self . _optdict_to_param_list ( optdict ) :
paramret = param . lookup_param ( self , inst )
2016-06-15 00:29:54 +03:00
if paramret is False :
valid = False
2014-09-20 21:22:52 +04:00
break
if valid :
ret . append ( inst )
2016-06-14 21:37:21 +03:00
self . _check_leftover_opts ( optdict )
except Exception , e :
logging . debug ( " Exception parsing inst= %s optstr= %s " ,
inst , self . optstr , exc_info = True )
fail ( _ ( " Error: -- %(cli_arg_name)s %(options)s : %(err)s " ) %
{ " cli_arg_name " : self . cli_arg_name ,
" options " : self . optstr , " err " : str ( e ) } )
2014-01-19 19:37:14 +04:00
return ret
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
VIRT_PARSERS = [ ]
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
def _register_virt_parser ( parserclass ) :
VIRT_PARSERS . append ( parserclass )
2014-01-19 22:56:06 +04:00
2016-06-13 23:00:58 +03:00
2015-04-12 02:25:46 +03:00
###################
# --check parsing #
###################
def convert_old_force ( options ) :
if options . force :
if not options . check :
options . check = " all=off "
del ( options . force )
class ParseCLICheck ( VirtCLIParser ) :
2016-06-14 01:50:31 +03:00
cli_arg_name = " check "
2016-06-14 18:38:53 +03:00
def set_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
# This sets properties on the _GlobalState objects
2016-06-14 18:38:53 +03:00
inst . set_validation_check ( virtarg . cliname , val )
2015-04-12 02:25:46 +03:00
2016-06-13 23:30:29 +03:00
ParseCLICheck . add_arg ( None , " path_in_use " , is_onoff = True ,
cb = ParseCLICheck . set_cb )
ParseCLICheck . add_arg ( None , " disk_size " , is_onoff = True ,
cb = ParseCLICheck . set_cb )
ParseCLICheck . add_arg ( None , " path_exists " , is_onoff = True ,
cb = ParseCLICheck . set_cb )
ParseCLICheck . add_arg ( " all_checks " , " all " , is_onoff = True )
2015-04-12 02:25:46 +03:00
def parse_check ( checkstr ) :
2016-06-14 01:50:31 +03:00
# Overwrite this for each parse
2016-06-14 14:37:21 +03:00
parser = ParseCLICheck ( None , checkstr )
parser . parse ( get_global_state ( ) )
2015-04-12 02:25:46 +03:00
2014-01-25 05:03:30 +04:00
######################
# --metadata parsing #
######################
class ParserMetadata ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " metadata "
2016-06-13 23:30:29 +03:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserMetadata )
2016-06-13 23:30:29 +03:00
ParserMetadata . add_arg ( " name " , " name " , can_comma = True )
ParserMetadata . add_arg ( " title " , " title " , can_comma = True )
ParserMetadata . add_arg ( " uuid " , " uuid " )
ParserMetadata . add_arg ( " description " , " description " , can_comma = True )
2013-03-18 01:06:52 +04:00
2014-05-29 13:03:24 +04:00
####################
# --events parsing #
####################
2014-05-29 05:46:24 +04:00
class ParserEvents ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " events "
2016-06-13 23:30:29 +03:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserEvents )
2016-06-13 23:30:29 +03:00
ParserEvents . add_arg ( " on_poweroff " , " on_poweroff " )
ParserEvents . add_arg ( " on_reboot " , " on_reboot " )
ParserEvents . add_arg ( " on_crash " , " on_crash " )
ParserEvents . add_arg ( " on_lockfailure " , " on_lockfailure " )
2014-05-29 05:46:24 +04:00
2014-06-04 06:08:05 +04:00
######################
# --resource parsing #
######################
class ParserResource ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " resource "
2016-06-13 23:30:29 +03:00
objclass = DomainResource
remove_first = " partition "
2014-06-04 06:08:05 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserResource )
2016-06-13 23:30:29 +03:00
ParserResource . add_arg ( " partition " , " partition " )
2014-06-04 06:08:05 +04:00
2013-03-18 01:06:52 +04:00
######################
# --numatune parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserNumatune ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " numatune "
2016-06-13 23:30:29 +03:00
objclass = DomainNumatune
remove_first = " nodeset "
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserNumatune )
2016-06-13 23:30:29 +03:00
ParserNumatune . add_arg ( " memory_nodeset " , " nodeset " , can_comma = True )
ParserNumatune . add_arg ( " 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 ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " memory "
2016-06-13 23:30:29 +03:00
remove_first = " memory "
2016-06-14 18:38:53 +03:00
def set_memory_cb ( self , inst , val , virtarg ) :
setattr ( inst , virtarg . cliname , int ( val ) * 1024 )
2014-01-25 03:56:59 +04:00
2016-06-13 23:30:29 +03:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserMemory )
2016-06-13 23:30:29 +03:00
ParserMemory . add_arg ( " memory " , " memory " , cb = ParserMemory . set_memory_cb )
ParserMemory . add_arg ( " maxmemory " , " maxmemory " , cb = ParserMemory . set_memory_cb )
ParserMemory . add_arg ( " memoryBacking.hugepages " , " hugepages " , is_onoff = True )
2014-01-25 03:56:59 +04:00
2014-02-25 06:02:31 +04:00
#####################
# --memtune parsing #
#####################
class ParserMemorytune ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " memtune "
2016-06-13 23:30:29 +03:00
objclass = DomainMemorytune
remove_first = " soft_limit "
2014-02-25 06:02:31 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserMemorytune )
2016-06-13 23:30:29 +03:00
ParserMemorytune . add_arg ( " hard_limit " , " hard_limit " )
ParserMemorytune . add_arg ( " soft_limit " , " soft_limit " )
ParserMemorytune . add_arg ( " swap_hard_limit " , " swap_hard_limit " )
ParserMemorytune . add_arg ( " min_guarantee " , " min_guarantee " )
2014-02-25 06:02:31 +04:00
2016-06-11 20:45:05 +03:00
#######################
# --blkiotune parsing #
#######################
class ParserBlkiotune ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " blkiotune "
2016-06-13 23:30:29 +03:00
objclass = DomainBlkiotune
remove_first = " weight "
2016-06-11 20:45:05 +03:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserBlkiotune )
2016-06-13 23:30:29 +03:00
ParserBlkiotune . add_arg ( " weight " , " weight " )
ParserBlkiotune . add_arg ( " device_path " , " device_path " )
ParserBlkiotune . add_arg ( " device_weight " , " device_weight " )
2016-06-11 20:45:05 +03:00
###########################
# --memorybacking parsing #
###########################
class ParserMemorybacking ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " memorybacking "
2016-06-13 23:30:29 +03:00
objclass = DomainMemorybacking
2016-06-11 20:45:05 +03:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserMemorybacking )
2016-06-13 23:30:29 +03:00
ParserMemorybacking . add_arg ( " hugepages " , " hugepages " , is_onoff = True )
ParserMemorybacking . add_arg ( " page_size " , " size " )
ParserMemorybacking . add_arg ( " page_unit " , " unit " )
ParserMemorybacking . add_arg ( " page_nodeset " , " nodeset " , can_comma = True )
ParserMemorybacking . add_arg ( " nosharepages " , " nosharepages " , is_onoff = True )
ParserMemorybacking . add_arg ( " locked " , " locked " , is_onoff = True )
2016-06-11 20:45:05 +03:00
2013-03-18 01:06:52 +04:00
#################
# --cpu parsing #
#################
2014-01-19 22:56:06 +04:00
class ParserCPU ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " cpu "
2016-06-13 23:30:29 +03:00
objclass = CPU
remove_first = " model "
2017-03-09 01:03:01 +03:00
stub_none = False
2014-01-19 22:56:06 +04:00
2016-06-15 01:19:09 +03:00
def cell_find_inst_cb ( self , inst , val , virtarg , can_edit ) :
cpu = inst
num = 0
if re . search ( " \ d+ " , virtarg . key ) :
num = int ( re . search ( " \ d+ " , virtarg . key ) . group ( ) )
if can_edit :
while len ( cpu . cells ) < ( num + 1 ) :
cpu . add_cell ( )
try :
return cpu . cells [ num ]
except IndexError :
if not can_edit :
return None
raise
2016-06-14 18:38:53 +03:00
def set_model_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
if val == " host " :
val = inst . SPECIAL_MODE_HOST_MODEL
if val == " none " :
val = inst . SPECIAL_MODE_CLEAR
2014-01-19 19:37:14 +04:00
2016-06-13 23:30:29 +03:00
if val in inst . SPECIAL_MODES :
inst . set_special_mode ( val )
else :
inst . model = val
2014-01-19 19:37:14 +04:00
2016-06-14 18:38:53 +03:00
def set_feature_cb ( self , inst , val , virtarg ) :
policy = virtarg . cliname
2016-06-13 23:30:29 +03:00
for feature_name in util . listify ( val ) :
featureobj = None
2014-01-19 22:56:06 +04:00
2016-06-13 23:30:29 +03:00
for f in inst . features :
if f . name == feature_name :
featureobj = f
break
2014-01-19 22:56:06 +04:00
2016-06-13 23:30:29 +03:00
if featureobj :
featureobj . policy = policy
else :
inst . add_feature ( feature_name , policy )
2014-01-19 22:56:06 +04:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
2014-01-19 22:56:06 +04:00
# Convert +feature, -feature into expected format
2016-06-14 14:37:21 +03:00
for key , value in self . optdict . items ( ) :
2014-01-19 22:56:06 +04:00
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 :
2016-06-14 14:37:21 +03:00
del ( self . optdict [ key ] )
if self . optdict . get ( policy ) is None :
self . optdict [ policy ] = [ ]
self . optdict [ policy ] . append ( key [ 1 : ] )
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
return VirtCLIParser . _parse ( self , inst )
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserCPU )
2016-06-13 23:30:29 +03:00
ParserCPU . add_arg ( None , " model " , cb = ParserCPU . set_model_cb )
ParserCPU . add_arg ( " mode " , " mode " )
ParserCPU . add_arg ( " match " , " match " )
ParserCPU . add_arg ( " vendor " , " vendor " )
ParserCPU . add_arg ( None , " force " , is_list = True , cb = ParserCPU . set_feature_cb )
ParserCPU . add_arg ( None , " require " , is_list = True , cb = ParserCPU . set_feature_cb )
ParserCPU . add_arg ( None , " optional " , is_list = True , cb = ParserCPU . set_feature_cb )
ParserCPU . add_arg ( None , " disable " , is_list = True , cb = ParserCPU . set_feature_cb )
ParserCPU . add_arg ( None , " forbid " , is_list = True , cb = ParserCPU . set_feature_cb )
2016-06-15 01:19:09 +03:00
# Options for CPU.cells config
ParserCPU . add_arg ( " id " , " cell[0-9]*.id " ,
find_inst_cb = ParserCPU . cell_find_inst_cb )
ParserCPU . add_arg ( " cpus " , " cell[0-9]*.cpus " , can_comma = True ,
find_inst_cb = ParserCPU . cell_find_inst_cb )
ParserCPU . add_arg ( " memory " , " cell[0-9]*.memory " ,
find_inst_cb = ParserCPU . cell_find_inst_cb )
2016-06-13 23:30:29 +03:00
2016-06-14 14:37:21 +03:00
###################
# --vcpus parsing #
###################
class ParserVCPU ( VirtCLIParser ) :
cli_arg_name = " vcpus "
remove_first = " vcpus "
2016-06-14 18:38:53 +03:00
def set_vcpus_cb ( self , inst , val , virtarg ) :
attrname = ( ( " maxvcpus " in self . optdict ) and
2016-06-14 14:37:21 +03:00
" curvcpus " or " vcpus " )
setattr ( inst , attrname , val )
2016-06-14 18:38:53 +03:00
def set_cpuset_cb ( self , inst , val , virtarg ) :
2016-06-14 14:37:21 +03:00
if not val :
return
if val != " auto " :
inst . cpuset = val
return
# Previously we did our own one-time cpuset placement
# based on current NUMA memory availability, but that's
# pretty dumb unless the conditions on the host never change.
# So instead use newer vcpu placement=, but only if it's
# supported.
if not inst . conn . check_support (
inst . conn . SUPPORT_CONN_VCPU_PLACEMENT ) :
logging . warning ( " vcpu placement=auto not supported, skipping. " )
return
inst . vcpu_placement = " auto "
def _parse ( self , inst ) :
set_from_top = ( " maxvcpus " not in self . optdict and
" vcpus " not in self . optdict )
ret = VirtCLIParser . _parse ( self , inst )
if set_from_top :
inst . vcpus = inst . cpu . vcpus_from_topology ( )
return ret
_register_virt_parser ( ParserVCPU )
ParserVCPU . add_arg ( " cpu.sockets " , " sockets " )
ParserVCPU . add_arg ( " cpu.cores " , " cores " )
ParserVCPU . add_arg ( " cpu.threads " , " threads " )
ParserVCPU . add_arg ( None , " vcpus " , cb = ParserVCPU . set_vcpus_cb )
ParserVCPU . add_arg ( " vcpus " , " maxvcpus " )
ParserVCPU . add_arg ( None , " cpuset " , can_comma = True , cb = ParserVCPU . set_cpuset_cb )
ParserVCPU . add_arg ( " vcpu_placement " , " placement " )
2013-03-18 01:06:52 +04:00
##################
# --boot parsing #
##################
2014-01-19 22:56:06 +04:00
class ParserBoot ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " boot "
2016-06-13 23:30:29 +03:00
clear_attr = " os "
2016-06-14 18:38:53 +03:00
def set_uefi ( self , inst , val , virtarg ) :
ignore = virtarg
2016-06-13 23:30:29 +03:00
ignore = val
inst . set_uefi_default ( )
2016-06-14 18:38:53 +03:00
def set_initargs_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
inst . os . set_initargs_string ( val )
2016-09-07 01:12:20 +03:00
def set_smbios_mode_cb ( self , inst , val , virtarg ) :
if not val . startswith ( " emulate " ) and not val . startswith ( " host " ) :
inst . sysinfo . parse ( val )
val = " sysinfo "
inst . os . smbios_mode = val
self . optdict [ " smbios_mode " ] = val
2016-06-14 18:38:53 +03:00
def noset_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
pass
2014-01-19 22:56:06 +04:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
2014-01-19 22:56:06 +04:00
# Build boot order
2013-03-18 01:06:52 +04:00
boot_order = [ ]
2016-06-14 14:37:21 +03:00
for cliname in self . optdict . keys ( ) :
2014-05-02 18:20:59 +04:00
if cliname not in inst . os . BOOT_DEVICES :
2013-03-18 01:06:52 +04:00
continue
2016-06-14 14:37:21 +03:00
del ( self . optdict [ cliname ] )
2014-01-19 22:56:06 +04:00
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
2016-06-14 14:37:21 +03:00
VirtCLIParser . _parse ( self , inst )
2014-01-19 22:56:06 +04:00
2013-07-30 22:26:53 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserBoot )
2016-06-13 23:30:29 +03:00
# UEFI depends on these bits, so set them first
ParserBoot . add_arg ( " os.arch " , " arch " )
ParserBoot . add_arg ( " type " , " domain_type " )
ParserBoot . add_arg ( " os.os_type " , " os_type " )
ParserBoot . add_arg ( " emulator " , " emulator " )
ParserBoot . add_arg ( None , " uefi " , cb = ParserBoot . set_uefi , is_novalue = True )
ParserBoot . add_arg ( " os.useserial " , " useserial " , is_onoff = True )
ParserBoot . add_arg ( " os.enable_bootmenu " , " menu " , is_onoff = True )
ParserBoot . add_arg ( " os.kernel " , " kernel " )
ParserBoot . add_arg ( " os.initrd " , " initrd " )
ParserBoot . add_arg ( " os.dtb " , " dtb " )
ParserBoot . add_arg ( " os.loader " , " loader " )
ParserBoot . add_arg ( " os.loader_ro " , " loader_ro " , is_onoff = True )
ParserBoot . add_arg ( " os.loader_type " , " loader_type " )
ParserBoot . add_arg ( " os.nvram " , " nvram " )
ParserBoot . add_arg ( " os.nvram_template " , " nvram_template " )
ParserBoot . add_arg ( " os.kernel_args " , " kernel_args " ,
aliases = [ " extra_args " ] , can_comma = True )
ParserBoot . add_arg ( " os.init " , " init " )
ParserBoot . add_arg ( " os.machine " , " machine " )
ParserBoot . add_arg ( " os.initargs " , " initargs " , cb = ParserBoot . set_initargs_cb )
2016-09-07 01:12:20 +03:00
ParserBoot . add_arg ( " os.smbios_mode " , " smbios_mode " ,
can_comma = True , cb = ParserBoot . set_smbios_mode_cb )
2016-06-13 23:30:29 +03:00
# This is simply so the boot options are advertised with --boot help,
# actual processing is handled by _parse
for _bootdev in OSXML . BOOT_DEVICES :
ParserBoot . add_arg ( None , _bootdev , is_novalue = True , cb = ParserBoot . noset_cb )
2014-02-18 18:40:39 +04:00
###################
# --idmap parsing #
###################
2014-02-09 19:25:25 +04:00
class ParserIdmap ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " idmap "
2016-06-13 23:30:29 +03:00
objclass = IdMap
2014-02-09 19:25:25 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserIdmap )
2016-06-13 23:30:29 +03:00
ParserIdmap . add_arg ( " uid_start " , " uid_start " )
ParserIdmap . add_arg ( " uid_target " , " uid_target " )
ParserIdmap . add_arg ( " uid_count " , " uid_count " )
ParserIdmap . add_arg ( " gid_start " , " gid_start " )
ParserIdmap . add_arg ( " gid_target " , " gid_target " )
ParserIdmap . add_arg ( " gid_count " , " gid_count " )
2014-02-09 19:25:25 +04:00
2013-03-18 01:06:52 +04:00
######################
# --security parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserSecurity ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " security "
2016-06-13 23:30:29 +03:00
objclass = Seclabel
2014-01-26 00:44:14 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserSecurity )
2016-06-13 23:30:29 +03:00
ParserSecurity . add_arg ( " type " , " type " )
ParserSecurity . add_arg ( " model " , " model " )
ParserSecurity . add_arg ( " relabel " , " relabel " , is_onoff = True )
ParserSecurity . add_arg ( " label " , " label " , can_comma = True )
ParserSecurity . add_arg ( " baselabel " , " label " , can_comma = 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 ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " features "
2016-06-13 23:30:29 +03:00
objclass = DomainFeatures
2014-01-26 00:44:14 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserFeatures )
2016-06-13 23:30:29 +03:00
ParserFeatures . add_arg ( " acpi " , " acpi " , is_onoff = True )
ParserFeatures . add_arg ( " apic " , " apic " , is_onoff = True )
ParserFeatures . add_arg ( " pae " , " pae " , is_onoff = True )
ParserFeatures . add_arg ( " privnet " , " privnet " , is_onoff = True )
ParserFeatures . add_arg ( " hap " , " hap " , is_onoff = True )
ParserFeatures . add_arg ( " viridian " , " viridian " , is_onoff = True )
ParserFeatures . add_arg ( " eoi " , " eoi " , is_onoff = True )
ParserFeatures . add_arg ( " pmu " , " pmu " , is_onoff = True )
2014-01-19 22:56:06 +04:00
2017-03-27 16:55:42 +03:00
ParserFeatures . add_arg ( " hyperv_reset " , " hyperv_reset " , is_onoff = True )
2016-06-13 23:30:29 +03:00
ParserFeatures . add_arg ( " hyperv_vapic " , " hyperv_vapic " , is_onoff = True )
ParserFeatures . add_arg ( " hyperv_relaxed " , " hyperv_relaxed " , is_onoff = True )
ParserFeatures . add_arg ( " hyperv_spinlocks " , " hyperv_spinlocks " , is_onoff = True )
ParserFeatures . add_arg ( " hyperv_spinlocks_retries " ,
" hyperv_spinlocks_retries " )
2017-03-30 21:17:15 +03:00
ParserFeatures . add_arg ( " hyperv_synic " , " hyperv_synic " , is_onoff = True )
2014-01-19 22:56:06 +04:00
2016-06-13 23:30:29 +03:00
ParserFeatures . add_arg ( " vmport " , " vmport " , is_onoff = True )
ParserFeatures . add_arg ( " kvm_hidden " , " kvm_hidden " , is_onoff = True )
ParserFeatures . add_arg ( " pvspinlock " , " pvspinlock " , is_onoff = True )
2015-04-03 01:04:05 +03:00
2016-06-13 23:30:29 +03:00
ParserFeatures . add_arg ( " gic_version " , " gic_version " )
2016-06-10 18:42:56 +03:00
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 ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " clock "
2016-06-13 23:30:29 +03:00
objclass = Clock
2014-01-26 00:44:14 +04:00
2016-06-14 18:38:53 +03:00
def set_timer ( self , inst , val , virtarg ) :
tname , attrname = virtarg . cliname . split ( " _ " )
2013-10-06 00:45:15 +04:00
2016-06-13 23:30:29 +03:00
timerobj = None
for t in inst . timers :
if t . name == tname :
timerobj = t
break
2013-10-06 00:45:15 +04:00
2016-06-13 23:30:29 +03:00
if not timerobj :
timerobj = inst . add_timer ( )
timerobj . name = tname
setattr ( timerobj , attrname , val )
2013-10-06 00:45:15 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserClock )
2016-06-13 23:30:29 +03:00
ParserClock . add_arg ( " offset " , " offset " )
2013-10-06 00:45:15 +04:00
2016-06-13 23:30:29 +03:00
for _tname in Clock . TIMER_NAMES :
ParserClock . add_arg ( None , _tname + " _present " ,
is_onoff = True ,
cb = ParserClock . set_timer )
ParserClock . add_arg ( None , _tname + " _tickpolicy " , cb = ParserClock . set_timer )
2014-01-19 22:56:06 +04:00
2014-02-03 01:12:29 +04:00
################
# --pm parsing #
################
class ParserPM ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " pm "
2016-06-13 23:30:29 +03:00
objclass = PM
2014-02-03 01:12:29 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserPM )
2016-06-13 23:30:29 +03:00
ParserPM . add_arg ( " suspend_to_mem " , " suspend_to_mem " , is_onoff = True )
ParserPM . add_arg ( " suspend_to_disk " , " suspend_to_disk " , is_onoff = True )
2014-02-03 01:12:29 +04:00
2016-09-07 01:12:20 +03:00
#####################
# --sysinfo parsing #
#####################
class ParserSYSInfo ( VirtCLIParser ) :
cli_arg_name = " sysinfo "
objclass = SYSInfo
remove_first = " type "
def set_type_cb ( self , inst , val , virtarg ) :
if val == " host " or val == " emulate " :
self . guest . os . smbios_mode = val
elif val == " smbios " :
self . guest . os . smbios_mode = " sysinfo "
inst . type = val
else :
fail ( _ ( " Unknown sysinfo flag ' %s ' " ) % val )
2017-03-06 04:55:21 +03:00
def set_uuid_cb ( self , inst , val , virtarg ) :
2016-09-07 01:12:20 +03:00
# If a uuid is supplied it must match the guest UUID. This would be
# impossible to guess if the guest uuid is autogenerated so just
# overwrite the guest uuid with what is passed in assuming it passes
# the sanity checking below.
inst . system_uuid = val
2017-03-06 04:55:21 +03:00
self . guest . uuid = val
2016-09-07 01:12:20 +03:00
def _parse ( self , inst ) :
if self . optstr == " host " or self . optstr == " emulate " :
self . optdict [ ' type ' ] = self . optstr
2017-03-06 05:18:26 +03:00
elif self . optstr :
# If any string specified, default to type=smbios otherwise
# libvirt errors. User args can still override this though
self . optdict [ ' type ' ] = ' smbios '
2016-09-07 01:12:20 +03:00
return VirtCLIParser . _parse ( self , inst )
_register_virt_parser ( ParserSYSInfo )
# <sysinfo type='smbios'>
ParserSYSInfo . add_arg ( " type " , " type " ,
cb = ParserSYSInfo . set_type_cb , can_comma = True )
# <bios> type 0 BIOS Information
ParserSYSInfo . add_arg ( " bios_vendor " , " bios_vendor " )
ParserSYSInfo . add_arg ( " bios_version " , " bios_version " )
2017-03-06 04:55:21 +03:00
ParserSYSInfo . add_arg ( " bios_date " , " bios_date " )
2016-09-07 01:12:20 +03:00
ParserSYSInfo . add_arg ( " bios_release " , " bios_release " )
# <system> type 1 System Information
ParserSYSInfo . add_arg ( " system_manufacturer " , " system_manufacturer " )
ParserSYSInfo . add_arg ( " system_product " , " system_product " )
ParserSYSInfo . add_arg ( " system_version " , " system_version " )
ParserSYSInfo . add_arg ( " system_serial " , " system_serial " )
ParserSYSInfo . add_arg ( " system_uuid " , " system_uuid " ,
2017-03-06 04:55:21 +03:00
cb = ParserSYSInfo . set_uuid_cb )
2016-09-07 01:12:20 +03:00
ParserSYSInfo . add_arg ( " system_sku " , " system_sku " )
ParserSYSInfo . add_arg ( " system_family " , " system_family " )
# <baseBoard> type 2 Baseboard (or Module) Information
ParserSYSInfo . add_arg ( " baseBoard_manufacturer " , " baseBoard_manufacturer " )
ParserSYSInfo . add_arg ( " baseBoard_product " , " baseBoard_product " )
ParserSYSInfo . add_arg ( " baseBoard_version " , " baseBoard_version " )
ParserSYSInfo . add_arg ( " baseBoard_serial " , " baseBoard_serial " )
ParserSYSInfo . add_arg ( " baseBoard_asset " , " baseBoard_asset " )
ParserSYSInfo . add_arg ( " baseBoard_location " , " baseBoard_location " )
2017-03-06 04:45:33 +03:00
##############################
# --qemu-commandline parsing #
##############################
class ParserQemuCLI ( VirtCLIParser ) :
cli_arg_name = " qemu_commandline "
objclass = XMLNSQemu
def args_cb ( self , inst , val , virtarg ) :
for opt in shlex . split ( val ) :
inst . add_arg ( opt )
def env_cb ( self , inst , val , virtarg ) :
name , envval = val . split ( " = " , 1 )
inst . add_env ( name , envval )
def _parse ( self , inst ) :
self . optdict . clear ( )
if self . optstr . startswith ( " env= " ) :
self . optdict [ " env " ] = self . optstr . split ( " = " , 1 ) [ 1 ]
elif self . optstr . startswith ( " args= " ) :
self . optdict [ " args " ] = self . optstr . split ( " = " , 1 ) [ 1 ]
elif self . optstr . startswith ( " clearxml= " ) :
self . optdict [ " clearxml " ] = self . optstr . split ( " = " , 1 ) [ 1 ]
else :
self . optdict [ " args " ] = self . optstr
return VirtCLIParser . _parse ( self , inst )
_register_virt_parser ( ParserQemuCLI )
ParserQemuCLI . add_arg ( None , " args " , cb = ParserQemuCLI . args_cb , can_comma = True )
ParserQemuCLI . add_arg ( None , " env " , cb = ParserQemuCLI . env_cb , can_comma = True )
2013-03-18 01:06:52 +04:00
##########################
# Guest <device> parsing #
##########################
2016-06-13 23:30:29 +03:00
def _add_device_address_args ( cls ) :
"""
Add VirtualDeviceAddress parameters if we are parsing for a device
"""
cls . add_arg ( " address.type " , " address.type " )
cls . add_arg ( " address.domain " , " address.domain " )
cls . add_arg ( " address.bus " , " address.bus " )
cls . add_arg ( " address.slot " , " address.slot " )
cls . add_arg ( " address.multifunction " , " address.multifunction " ,
is_onoff = True )
cls . add_arg ( " address.function " , " address.function " )
cls . add_arg ( " address.controller " , " address.controller " )
cls . add_arg ( " address.unit " , " address.unit " )
cls . add_arg ( " address.port " , " address.port " )
cls . add_arg ( " address.target " , " address.target " )
cls . add_arg ( " address.reg " , " address.reg " )
cls . add_arg ( " address.cssid " , " address.cssid " )
cls . add_arg ( " address.ssid " , " address.ssid " )
cls . add_arg ( " address.devno " , " address.devno " )
cls . add_arg ( " address.iobase " , " address.iobase " )
cls . add_arg ( " address.irq " , " address.irq " )
cls . add_arg ( " address.base " , " address.base " )
2013-03-18 01:06:52 +04:00
##################
# --disk parsing #
##################
2014-02-11 03:47:58 +04:00
def _default_image_file_format ( conn ) :
if conn . check_support ( conn . SUPPORT_CONN_DEFAULT_QCOW2 ) :
return " qcow2 "
return " raw "
2014-12-06 02:17:39 +03:00
def _get_default_image_format ( conn , poolobj ) :
tmpvol = StorageVolume ( conn )
tmpvol . pool = poolobj
if tmpvol . file_type != StorageVolume . TYPE_FILE :
return None
return _default_image_file_format ( conn )
def _generate_new_volume_name ( guest , poolobj , fmt ) :
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 ) )
ext = StorageVolume . get_file_extension_for_format ( fmt )
return StorageVolume . find_free_name (
poolobj , guest . name , suffix = ext , collidelist = collidelist )
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 ParserDisk ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " disk "
2016-06-13 23:30:29 +03:00
objclass = VirtualDisk
remove_first = " path "
2017-03-09 01:03:01 +03:00
stub_none = False
2016-06-13 23:30:29 +03:00
2016-06-14 18:38:53 +03:00
def noset_cb ( self , inst , val , virtarg ) :
ignore = self , inst , val , virtarg
2014-02-01 00:38:39 +04:00
2016-06-15 00:29:54 +03:00
def seclabel_find_inst_cb ( self , inst , val , virtarg , can_edit ) :
disk = inst
num = 0
if re . search ( " \ d+ " , virtarg . key ) :
num = int ( re . search ( " \ d+ " , virtarg . key ) . group ( ) )
if can_edit :
while len ( disk . seclabels ) < ( num + 1 ) :
disk . add_seclabel ( )
try :
return disk . seclabels [ num ]
except IndexError :
if not can_edit :
return None
raise
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
if self . optstr == " none " :
2014-09-21 03:16:13 +04:00
return
2014-01-19 22:56:06 +04:00
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 :
2015-06-02 15:21:58 +03:00
fail ( _ ( " Improper value for ' size ' : %s " ) % str ( e ) )
2013-03-18 01:06:52 +04:00
2014-01-25 04:05:04 +04:00
def convert_perms ( val ) :
if val is None :
return
if val == " ro " :
2016-06-14 14:37:21 +03:00
self . optdict [ " readonly " ] = " on "
2014-01-25 04:05:04 +04:00
elif val == " sh " :
2016-06-14 14:37:21 +03:00
self . optdict [ " shareable " ] = " on "
2014-01-25 04:05:04 +04:00
elif val == " rw " :
# It's default. Nothing to do.
pass
else :
2015-06-02 15:21:58 +03:00
fail ( _ ( " Unknown ' %s ' value ' %s ' " ) % ( " perms " , val ) )
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
has_path = " path " in self . optdict
backing_store = self . optdict . pop ( " backing_store " , None )
2016-06-17 03:08:53 +03:00
backing_format = self . optdict . pop ( " backing_format " , None )
2016-06-14 14:37:21 +03:00
poolname = self . optdict . pop ( " pool " , None )
volname = self . optdict . pop ( " vol " , None )
size = parse_size ( self . optdict . pop ( " size " , None ) )
fmt = self . optdict . pop ( " format " , None )
2017-01-16 19:08:28 +03:00
sparse = _on_off_convert ( " sparse " , self . optdict . pop ( " sparse " , " yes " ) )
2016-06-14 14:37:21 +03:00
convert_perms ( self . optdict . pop ( " perms " , None ) )
has_type_volume = ( " source_pool " in self . optdict or
" source_volume " in self . optdict )
has_type_network = ( " source_protocol " in self . optdict )
2013-03-18 01:06:52 +04:00
2014-12-10 20:31:56 +03:00
optcount = sum ( [ bool ( p ) for p in [ has_path , poolname , volname ,
has_type_volume , has_type_network ] ] )
2014-12-06 02:17:39 +03:00
if optcount > 1 :
fail ( _ ( " Cannot specify more than 1 storage path " ) )
if optcount == 0 and size :
# Saw something like --disk size=X, have it imply pool=default
poolname = " default "
if volname :
if volname . count ( " / " ) != 1 :
raise ValueError ( _ ( " Storage volume must be specified as "
" vol=poolname/volname " ) )
poolname , volname = volname . split ( " / " )
2015-01-29 18:03:35 +03:00
logging . debug ( " Parsed --disk volume as: pool= %s vol= %s " ,
2014-12-06 02:17:39 +03:00
poolname , volname )
2016-06-14 14:37:21 +03:00
VirtCLIParser . _parse ( self , inst )
2014-12-06 03:52:25 +03:00
# Generate and fill in the disk source info
newvolname = None
poolobj = None
2014-12-06 02:17:39 +03:00
if poolname :
if poolname == " default " :
StoragePool . build_default_pool ( self . guest . conn )
poolobj = self . guest . conn . storagePoolLookupByName ( poolname )
2014-12-06 21:04:59 +03:00
if volname :
2014-12-06 02:17:39 +03:00
vol_object = poolobj . storageVolLookupByName ( volname )
2014-12-10 01:03:48 +03:00
inst . set_vol_object ( vol_object , poolobj )
2014-12-06 03:52:25 +03:00
poolobj = None
2014-12-06 21:04:59 +03:00
if ( ( poolobj or inst . wants_storage_creation ( ) ) and
( fmt or size or sparse or backing_store ) ) :
if not poolobj :
poolobj = inst . get_parent_pool ( )
newvolname = os . path . basename ( inst . path )
if poolobj and not fmt :
2014-12-06 02:17:39 +03:00
fmt = _get_default_image_format ( self . guest . conn , poolobj )
2014-12-06 03:52:25 +03:00
if newvolname is None :
newvolname = _generate_new_volume_name ( self . guest , poolobj ,
fmt )
2014-12-06 02:17:39 +03:00
vol_install = VirtualDisk . build_vol_install (
2014-12-06 03:52:25 +03:00
self . guest . conn , newvolname , poolobj , size , sparse ,
2016-06-17 03:08:53 +03:00
fmt = fmt , backing_store = backing_store ,
backing_format = backing_format )
2014-12-06 04:12:35 +03:00
inst . set_vol_install ( vol_install )
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 )
2015-04-07 23:38:52 +03:00
inst . cli_generated_target = True
2014-01-26 06:08:11 +04:00
2014-01-19 22:56:06 +04:00
return inst
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserDisk )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserDisk )
# These are all handled specially in _parse
ParserDisk . add_arg ( None , " backing_store " , cb = ParserDisk . noset_cb )
2016-06-17 03:08:53 +03:00
ParserDisk . add_arg ( None , " backing_format " , cb = ParserDisk . noset_cb )
2016-06-13 23:30:29 +03:00
ParserDisk . add_arg ( None , " pool " , cb = ParserDisk . noset_cb )
ParserDisk . add_arg ( None , " vol " , cb = ParserDisk . noset_cb )
ParserDisk . add_arg ( None , " size " , cb = ParserDisk . noset_cb )
ParserDisk . add_arg ( None , " format " , cb = ParserDisk . noset_cb )
ParserDisk . add_arg ( None , " sparse " , cb = ParserDisk . noset_cb )
ParserDisk . add_arg ( " source_pool " , " source_pool " )
ParserDisk . add_arg ( " source_volume " , " source_volume " )
ParserDisk . add_arg ( " source_name " , " source_name " )
ParserDisk . add_arg ( " source_protocol " , " source_protocol " )
ParserDisk . add_arg ( " source_host_name " , " source_host_name " )
ParserDisk . add_arg ( " source_host_port " , " source_host_port " )
ParserDisk . add_arg ( " source_host_socket " , " source_host_socket " )
ParserDisk . add_arg ( " source_host_transport " , " source_host_transport " )
ParserDisk . add_arg ( " path " , " path " )
ParserDisk . add_arg ( " device " , " device " )
ParserDisk . add_arg ( " bus " , " bus " )
ParserDisk . add_arg ( " removable " , " removable " , is_onoff = True )
ParserDisk . add_arg ( " driver_cache " , " cache " )
ParserDisk . add_arg ( " driver_discard " , " discard " )
ParserDisk . add_arg ( " driver_name " , " driver_name " )
ParserDisk . add_arg ( " driver_type " , " driver_type " )
ParserDisk . add_arg ( " driver_io " , " io " )
ParserDisk . add_arg ( " error_policy " , " error_policy " )
ParserDisk . add_arg ( " serial " , " serial " )
ParserDisk . add_arg ( " target " , " target " )
ParserDisk . add_arg ( " startup_policy " , " startup_policy " )
ParserDisk . add_arg ( " read_only " , " readonly " , is_onoff = True )
ParserDisk . add_arg ( " shareable " , " shareable " , is_onoff = True )
ParserDisk . add_arg ( " boot.order " , " boot_order " )
ParserDisk . add_arg ( " iotune_rbs " , " read_bytes_sec " )
ParserDisk . add_arg ( " iotune_wbs " , " write_bytes_sec " )
ParserDisk . add_arg ( " iotune_tbs " , " total_bytes_sec " )
ParserDisk . add_arg ( " iotune_ris " , " read_iops_sec " )
ParserDisk . add_arg ( " iotune_wis " , " write_iops_sec " )
ParserDisk . add_arg ( " iotune_tis " , " total_iops_sec " )
ParserDisk . add_arg ( " sgio " , " sgio " )
2016-06-15 00:29:54 +03:00
# VirtualDisk.seclabels properties
ParserDisk . add_arg ( " model " , " seclabel[0-9]*.model " ,
find_inst_cb = ParserDisk . seclabel_find_inst_cb )
ParserDisk . add_arg ( " relabel " , " seclabel[0-9]*.relabel " , is_onoff = True ,
find_inst_cb = ParserDisk . seclabel_find_inst_cb )
ParserDisk . add_arg ( " label " , " seclabel[0-9]*.label " , can_comma = True ,
find_inst_cb = ParserDisk . seclabel_find_inst_cb )
2016-06-13 23:30:29 +03:00
2013-03-18 01:06:52 +04:00
#####################
# --network parsing #
#####################
2014-01-19 22:56:06 +04:00
class ParserNetwork ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " network "
2016-06-13 23:30:29 +03:00
objclass = VirtualNetworkInterface
remove_first = " type "
2017-03-09 01:03:01 +03:00
stub_none = False
2013-03-18 01:06:52 +04:00
2016-06-14 18:38:53 +03:00
def set_mac_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
if val == " RANDOM " :
return None
inst . macaddr = val
return val
2014-02-06 02:45:46 +04:00
2016-06-14 18:38:53 +03:00
def set_type_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
if val == " default " :
inst . set_default_source ( )
else :
inst . type = val
2015-11-18 21:59:15 +03:00
2016-06-14 18:38:53 +03:00
def set_link_state ( self , inst , val , virtarg ) :
ignore = virtarg
2016-06-13 23:30:29 +03:00
if val in [ " up " , " down " ] :
2015-11-18 21:59:15 +03:00
inst . link_state = val
2016-06-13 23:30:29 +03:00
return
2015-11-18 21:59:15 +03:00
2016-06-13 23:30:29 +03:00
ret = _raw_on_off_convert ( val )
if ret is True :
val = " up "
elif ret is False :
val = " down "
inst . link_state = val
2015-08-28 14:12:49 +03:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
if self . optstr == " none " :
2014-09-21 02:56:39 +04:00
return
2016-06-14 14:37:21 +03:00
if " type " not in self . optdict :
if " network " in self . optdict :
self . optdict [ " type " ] = VirtualNetworkInterface . TYPE_VIRTUAL
self . optdict [ " source " ] = self . optdict . pop ( " network " )
elif " bridge " in self . optdict :
self . optdict [ " type " ] = VirtualNetworkInterface . TYPE_BRIDGE
self . optdict [ " source " ] = self . optdict . pop ( " bridge " )
2014-01-19 22:56:06 +04:00
2016-06-14 14:37:21 +03:00
return VirtCLIParser . _parse ( self , inst )
2014-01-19 22:56:06 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserNetwork )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserNetwork )
ParserNetwork . add_arg ( " type " , " type " , cb = ParserNetwork . set_type_cb )
2017-03-05 22:43:31 +03:00
ParserNetwork . add_arg ( " trustGuestRxFilters " , " trustGuestRxFilters " ,
is_onoff = True )
2016-06-13 23:30:29 +03:00
ParserNetwork . add_arg ( " source " , " source " )
ParserNetwork . add_arg ( " source_mode " , " source_mode " )
2016-08-27 08:41:38 +03:00
ParserNetwork . add_arg ( " source_type " , " source_type " )
ParserNetwork . add_arg ( " source_path " , " source_path " )
2016-06-13 23:30:29 +03:00
ParserNetwork . add_arg ( " portgroup " , " portgroup " )
ParserNetwork . add_arg ( " target_dev " , " target " )
ParserNetwork . add_arg ( " model " , " model " )
ParserNetwork . add_arg ( " macaddr " , " mac " , cb = ParserNetwork . set_mac_cb )
ParserNetwork . add_arg ( " filterref " , " filterref " )
ParserNetwork . add_arg ( " boot.order " , " boot_order " )
ParserNetwork . add_arg ( " link_state " , " link_state " ,
cb = ParserNetwork . set_link_state )
ParserNetwork . add_arg ( " driver_name " , " driver_name " )
ParserNetwork . add_arg ( " driver_queues " , " driver_queues " )
ParserNetwork . add_arg ( " rom_file " , " rom_file " )
ParserNetwork . add_arg ( " rom_bar " , " rom_bar " , is_onoff = True )
# For 802.1Qbg
ParserNetwork . add_arg ( " virtualport.type " , " virtualport_type " )
ParserNetwork . add_arg ( " virtualport.managerid " , " virtualport_managerid " )
ParserNetwork . add_arg ( " virtualport.typeid " , " virtualport_typeid " )
ParserNetwork . add_arg ( " virtualport.typeidversion " ,
" virtualport_typeidversion " )
ParserNetwork . add_arg ( " virtualport.instanceid " , " virtualport_instanceid " )
# For openvswitch & 802.1Qbh
ParserNetwork . add_arg ( " virtualport.profileid " , " virtualport_profileid " )
# For openvswitch & midonet
ParserNetwork . add_arg ( " virtualport.interfaceid " , " virtualport_interfaceid " )
2013-03-18 01:06:52 +04:00
######################
# --graphics parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserGraphics ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " graphics "
2016-06-13 23:30:29 +03:00
objclass = VirtualGraphics
remove_first = " type "
2017-03-09 01:03:01 +03:00
stub_none = False
2013-03-18 01:06:52 +04:00
2016-06-14 18:38:53 +03:00
def set_keymap_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
from . import hostkeymap
if not val :
val = None
elif val . lower ( ) == " local " :
val = 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
2016-06-14 18:38:53 +03:00
def set_type_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
if val == " default " :
return
inst . type = val
2016-06-14 18:38:53 +03:00
def set_listen_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
if val == " none " :
inst . set_listen_none ( )
elif val == " socket " :
inst . remove_all_listens ( )
obj = inst . add_listen ( )
obj . type = " socket "
else :
inst . listen = val
2015-04-11 23:56:27 +03:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
if self . optstr == " none " :
2014-02-08 01:07:32 +04:00
self . guest . skip_default_graphics = True
return
2016-05-20 19:44:13 +03:00
2016-06-14 14:37:21 +03:00
ret = VirtCLIParser . _parse ( self , inst )
2016-05-20 19:44:13 +03:00
if inst . conn . is_qemu ( ) and inst . gl :
if inst . type != " spice " :
logging . warn ( " graphics type= %s does not support GL " , inst . type )
elif not inst . conn . check_support (
inst . conn . SUPPORT_CONN_SPICE_GL ) :
logging . warn ( " qemu/libvirt version may not support spice GL " )
2017-02-21 16:01:00 +03:00
if inst . conn . is_qemu ( ) and inst . rendernode :
if inst . type != " spice " :
logging . warn ( " graphics type= %s does not support rendernode " , inst . type )
elif not inst . conn . check_support (
inst . conn . SUPPORT_CONN_SPICE_RENDERNODE ) :
logging . warn ( " qemu/libvirt version may not support rendernode " )
2016-05-20 19:44:13 +03:00
return ret
2014-02-08 01:07:32 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserGraphics )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserGraphics )
ParserGraphics . add_arg ( None , " type " , cb = ParserGraphics . set_type_cb )
ParserGraphics . add_arg ( " port " , " port " )
ParserGraphics . add_arg ( " tlsPort " , " tlsport " )
ParserGraphics . add_arg ( " listen " , " listen " , cb = ParserGraphics . set_listen_cb )
ParserGraphics . add_arg ( None , " keymap " , cb = ParserGraphics . set_keymap_cb )
ParserGraphics . add_arg ( " passwd " , " password " )
ParserGraphics . add_arg ( " passwdValidTo " , " passwordvalidto " )
ParserGraphics . add_arg ( " connected " , " connected " )
ParserGraphics . add_arg ( " defaultMode " , " defaultMode " )
ParserGraphics . add_arg ( " image_compression " , " image_compression " )
ParserGraphics . add_arg ( " streaming_mode " , " streaming_mode " )
ParserGraphics . add_arg ( " clipboard_copypaste " , " clipboard_copypaste " ,
is_onoff = True )
ParserGraphics . add_arg ( " mouse_mode " , " mouse_mode " )
ParserGraphics . add_arg ( " filetransfer_enable " , " filetransfer_enable " ,
is_onoff = True )
ParserGraphics . add_arg ( " gl " , " gl " , is_onoff = True )
2017-02-21 16:01:00 +03:00
ParserGraphics . add_arg ( " rendernode " , " rendernode " )
2016-06-13 23:30:29 +03:00
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 ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " controller "
2016-06-13 23:30:29 +03:00
objclass = VirtualController
remove_first = " type "
2014-01-19 19:37:14 +04:00
2016-06-14 18:38:53 +03:00
def set_server_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
inst . address . set_addrstr ( val )
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
if self . optstr == " usb2 " :
2014-09-12 23:59:22 +04:00
return VirtualController . get_usb2_controllers ( inst . conn )
2016-06-14 14:37:21 +03:00
elif self . optstr == " usb3 " :
2014-01-19 22:56:06 +04:00
inst . type = " usb "
inst . model = " nec-xhci "
return inst
2016-06-14 14:37:21 +03:00
return VirtCLIParser . _parse ( self , inst )
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserController )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserController )
ParserController . add_arg ( " type " , " type " )
ParserController . add_arg ( " model " , " model " )
ParserController . add_arg ( " index " , " index " )
ParserController . add_arg ( " master_startport " , " master " )
ParserController . add_arg ( None , " address " , cb = ParserController . set_server_cb )
2015-04-09 20:22:40 +03:00
###################
# --input parsing #
###################
class ParserInput ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " input "
2016-06-13 23:30:29 +03:00
objclass = VirtualInputDevice
remove_first = " type "
2015-04-09 20:22:40 +03:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserInput )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserInput )
ParserInput . add_arg ( " type " , " type " )
ParserInput . add_arg ( " bus " , " bus " )
2015-04-09 20:22:40 +03:00
2013-03-18 01:06:52 +04:00
#######################
# --smartcard parsing #
#######################
2014-01-19 22:56:06 +04:00
class ParserSmartcard ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " smartcard "
2016-06-13 23:30:29 +03:00
objclass = VirtualSmartCardDevice
remove_first = " mode "
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserSmartcard )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserSmartcard )
ParserSmartcard . add_arg ( " mode " , " mode " )
ParserSmartcard . add_arg ( " type " , " type " )
2013-03-18 01:06:52 +04:00
######################
# --redirdev parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserRedir ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " redirdev "
2016-06-13 23:30:29 +03:00
objclass = VirtualRedirDevice
remove_first = " bus "
2017-03-09 01:03:01 +03:00
stub_none = False
2014-01-19 19:37:14 +04:00
2016-06-14 18:38:53 +03:00
def set_server_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
inst . parse_friendly_server ( val )
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
if self . optstr == " none " :
2014-02-05 21:58:53 +04:00
self . guest . skip_default_usbredir = True
return
2016-06-14 14:37:21 +03:00
return VirtCLIParser . _parse ( self , inst )
2014-02-05 21:58:53 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserRedir )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserRedir )
ParserRedir . add_arg ( " bus " , " bus " )
ParserRedir . add_arg ( " type " , " type " )
ParserRedir . add_arg ( " boot.order " , " boot_order " )
ParserRedir . add_arg ( None , " server " , cb = ParserRedir . set_server_cb )
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 ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " tpm "
2016-06-13 23:30:29 +03:00
objclass = VirtualTPMDevice
remove_first = " type "
2013-06-26 05:45:07 +04:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
if ( self . optdict . get ( " type " , " " ) . startswith ( " / " ) ) :
self . optdict [ " path " ] = self . optdict . pop ( " type " )
return VirtCLIParser . _parse ( self , inst )
2013-09-28 18:28:04 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserTPM )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserTPM )
ParserTPM . add_arg ( " type " , " type " )
ParserTPM . add_arg ( " model " , " model " )
ParserTPM . add_arg ( " device_path " , " path " )
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 ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " rng "
2016-06-13 23:30:29 +03:00
objclass = VirtualRNGDevice
remove_first = " type "
2017-03-09 00:54:16 +03:00
stub_none = False
2016-06-13 23:30:29 +03:00
2016-06-14 18:38:53 +03:00
def set_hosts_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
namemap = { }
inst . backend_type = inst . cli_backend_type
if inst . cli_backend_mode == " connect " :
namemap [ " backend_host " ] = " connect_host "
namemap [ " backend_service " ] = " connect_service "
if inst . cli_backend_mode == " bind " :
namemap [ " backend_host " ] = " bind_host "
namemap [ " backend_service " ] = " bind_service "
if inst . cli_backend_type == " udp " :
namemap [ " backend_connect_host " ] = " connect_host "
namemap [ " backend_connect_service " ] = " connect_service "
2016-06-14 18:38:53 +03:00
if virtarg . cliname in namemap :
setattr ( inst , namemap [ virtarg . cliname ] , val )
2016-06-13 23:30:29 +03:00
2016-06-14 18:38:53 +03:00
def set_backend_cb ( self , inst , val , virtarg ) :
if virtarg . cliname == " backend_mode " :
2016-06-13 23:30:29 +03:00
inst . cli_backend_mode = val
2016-06-14 18:38:53 +03:00
elif virtarg . cliname == " backend_type " :
2016-06-13 23:30:29 +03:00
inst . cli_backend_type = val
2013-09-18 17:29:29 +04:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
2017-03-09 00:54:16 +03:00
if self . optstr == " none " :
self . guest . skip_default_rng = True
return
2016-06-13 23:30:29 +03:00
inst . cli_backend_mode = " connect "
inst . cli_backend_type = " udp "
2014-01-19 22:56:06 +04:00
2016-06-14 14:37:21 +03:00
if self . optdict . get ( " type " , " " ) . startswith ( " / " ) :
2014-01-19 22:56:06 +04:00
# Allow --rng /dev/random
2016-06-14 14:37:21 +03:00
self . optdict [ " device " ] = self . optdict . pop ( " type " )
self . optdict [ " type " ] = " random "
2014-01-19 22:56:06 +04:00
2016-06-14 14:37:21 +03:00
return VirtCLIParser . _parse ( self , inst )
2014-01-19 22:56:06 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserRNG )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserRNG )
ParserRNG . add_arg ( " type " , " type " )
ParserRNG . add_arg ( None , " backend_mode " , cb = ParserRNG . set_backend_cb )
ParserRNG . add_arg ( None , " backend_type " , cb = ParserRNG . set_backend_cb )
ParserRNG . add_arg ( None , " backend_host " , cb = ParserRNG . set_hosts_cb )
ParserRNG . add_arg ( None , " backend_service " , cb = ParserRNG . set_hosts_cb )
ParserRNG . add_arg ( None , " backend_connect_host " , cb = ParserRNG . set_hosts_cb )
ParserRNG . add_arg ( None , " backend_connect_service " , cb = ParserRNG . set_hosts_cb )
ParserRNG . add_arg ( " device " , " device " )
ParserRNG . add_arg ( " model " , " model " )
ParserRNG . add_arg ( " rate_bytes " , " rate_bytes " )
ParserRNG . add_arg ( " rate_period " , " rate_period " )
2013-03-18 01:06:52 +04:00
######################
# --watchdog parsing #
######################
2014-01-19 22:56:06 +04:00
class ParserWatchdog ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " watchdog "
2016-06-13 23:30:29 +03:00
objclass = VirtualWatchdog
remove_first = " model "
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserWatchdog )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserWatchdog )
ParserWatchdog . add_arg ( " model " , " model " )
ParserWatchdog . add_arg ( " action " , " action " )
2013-03-18 01:06:52 +04:00
########################
# --memballoon parsing #
########################
2014-01-19 22:56:06 +04:00
class ParserMemballoon ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " memballoon "
2016-06-13 23:30:29 +03:00
objclass = VirtualMemballoon
remove_first = " model "
2017-03-09 01:03:01 +03:00
stub_none = False
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserMemballoon )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserMemballoon )
ParserMemballoon . add_arg ( " 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 ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " panic "
2016-06-13 23:30:29 +03:00
objclass = VirtualPanicDevice
remove_first = " iobase "
2016-06-14 18:38:53 +03:00
def set_iobase_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
if val == " default " :
return
inst . iobase = val
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserPanic )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserPanic )
ParserPanic . add_arg ( None , " iobase " , cb = ParserPanic . set_iobase_cb )
2014-01-22 13:44:38 +04:00
2013-03-18 01:06:52 +04:00
######################################################
# --serial, --parallel, --channel, --console parsing #
######################################################
2014-01-19 22:56:06 +04:00
class _ParserChar ( VirtCLIParser ) :
2016-06-13 23:30:29 +03:00
remove_first = " char_type "
2017-03-09 01:03:01 +03:00
stub_none = False
2014-01-19 22:56:06 +04:00
2016-06-14 18:38:53 +03:00
def support_check ( self , inst , virtarg ) :
if type ( virtarg . attrname ) is not str :
2016-06-13 23:30:29 +03:00
return
2016-06-14 18:38:53 +03:00
if not inst . supports_property ( virtarg . attrname ) :
2016-06-13 23:30:29 +03:00
raise ValueError ( _ ( " %(devtype)s type ' %(chartype)s ' does not "
" support ' %(optname)s ' option. " ) %
{ " devtype " : inst . virtual_device_type ,
" chartype " : inst . type ,
2016-06-14 18:38:53 +03:00
" optname " : virtarg . cliname } )
2016-06-13 23:30:29 +03:00
support_cb = support_check
2016-06-14 18:38:53 +03:00
def set_host_cb ( self , inst , val , virtarg ) :
if ( " bind_host " not in self . optdict and
self . optdict . get ( " mode " , None ) == " bind " ) :
2014-01-19 19:37:14 +04:00
inst . set_friendly_bind ( val )
2016-06-13 23:30:29 +03:00
else :
inst . set_friendly_source ( val )
2014-01-19 19:37:14 +04:00
2016-06-14 18:38:53 +03:00
def set_bind_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
inst . set_friendly_bind ( val )
2014-01-19 22:56:06 +04:00
2016-06-14 18:38:53 +03:00
def set_target_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
inst . set_friendly_target ( val )
2015-09-05 23:27:27 +03:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
if self . optstr == " none " and inst . virtual_device_type == " console " :
2014-01-19 22:56:06 +04:00
self . guest . skip_default_console = True
return
2016-06-14 14:37:21 +03:00
if self . optstr == " none " and inst . virtual_device_type == " channel " :
2014-01-19 22:56:06 +04:00
self . guest . skip_default_channel = True
return
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
return VirtCLIParser . _parse ( self , inst )
2013-10-06 17:41:37 +04:00
2014-01-19 22:56:06 +04:00
2016-06-13 23:30:29 +03:00
_add_device_address_args ( _ParserChar )
_ParserChar . add_arg ( " type " , " char_type " )
_ParserChar . add_arg ( " source_path " , " path " )
_ParserChar . add_arg ( " protocol " , " protocol " )
_ParserChar . add_arg ( " target_type " , " target_type " )
_ParserChar . add_arg ( " target_name " , " name " )
_ParserChar . add_arg ( None , " host " , cb = _ParserChar . set_host_cb )
_ParserChar . add_arg ( None , " bind_host " , cb = _ParserChar . set_bind_cb )
_ParserChar . add_arg ( None , " target_address " , cb = _ParserChar . set_target_cb )
_ParserChar . add_arg ( " source_mode " , " mode " )
2016-08-24 23:37:36 +03:00
_ParserChar . add_arg ( " source_master " , " source.master " )
_ParserChar . add_arg ( " source_slave " , " source.slave " )
2016-07-18 22:03:06 +03:00
_ParserChar . add_arg ( " log_file " , " log.file " )
_ParserChar . add_arg ( " log_append " , " log.append " , is_onoff = True )
2016-06-13 23:30:29 +03:00
2014-01-19 22:56:06 +04:00
class ParserSerial ( _ParserChar ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " serial "
2015-09-04 23:07:01 +03:00
objclass = VirtualSerialDevice
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserSerial )
2014-01-19 22:56:06 +04:00
class ParserParallel ( _ParserChar ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " parallel "
2015-09-04 23:07:01 +03:00
objclass = VirtualParallelDevice
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserParallel )
2014-01-19 22:56:06 +04:00
class ParserChannel ( _ParserChar ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " channel "
2015-09-04 23:07:01 +03:00
objclass = VirtualChannelDevice
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserChannel )
2014-01-19 22:56:06 +04:00
class ParserConsole ( _ParserChar ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " console "
2015-09-04 23:07:01 +03:00
objclass = VirtualConsoleDevice
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserConsole )
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 ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " filesystem "
2016-06-13 23:30:29 +03:00
objclass = VirtualFilesystem
remove_first = [ " source " , " target " ]
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserFilesystem )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserFilesystem )
ParserFilesystem . add_arg ( " type " , " type " )
ParserFilesystem . add_arg ( " accessmode " , " accessmode " , aliases = [ " mode " ] )
ParserFilesystem . add_arg ( " source " , " source " )
ParserFilesystem . add_arg ( " target " , " target " )
2013-03-18 01:06:52 +04:00
###################
# --video parsing #
###################
2014-01-19 22:56:06 +04:00
class ParserVideo ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " video "
2016-06-13 23:30:29 +03:00
objclass = VirtualVideoDevice
remove_first = " model "
2013-09-28 04:16:35 +04:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
ret = VirtCLIParser . _parse ( self , inst )
2016-05-20 19:44:13 +03:00
if inst . conn . is_qemu ( ) and inst . accel3d :
if inst . model != " virtio " :
logging . warn ( " video model= %s does not support accel3d " ,
inst . model )
elif not inst . conn . check_support (
inst . conn . SUPPORT_CONN_VIDEO_VIRTIO_ACCEL3D ) :
logging . warn ( " qemu/libvirt version may not support "
" virtio accel3d " )
return ret
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserVideo )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserVideo )
ParserVideo . add_arg ( " model " , " model " , ignore_default = True )
ParserVideo . add_arg ( " accel3d " , " accel3d " , is_onoff = True )
ParserVideo . add_arg ( " heads " , " heads " )
ParserVideo . add_arg ( " ram " , " ram " )
ParserVideo . add_arg ( " vram " , " vram " )
2017-03-05 22:51:25 +03:00
ParserVideo . add_arg ( " vram64 " , " vram64 " )
2016-06-13 23:30:29 +03:00
ParserVideo . add_arg ( " vgamem " , " vgamem " )
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 ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " sound "
2016-06-13 23:30:29 +03:00
objclass = VirtualAudio
remove_first = " model "
2017-03-09 01:03:01 +03:00
stub_none = False
2013-03-18 01:06:52 +04:00
2016-06-14 14:37:21 +03:00
def _parse ( self , inst ) :
if self . optstr == " none " :
2014-02-05 21:49:16 +04:00
self . guest . skip_default_sound = True
return
2016-06-14 14:37:21 +03:00
return VirtCLIParser . _parse ( self , inst )
2014-02-05 21:49:16 +04:00
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserSound )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserSound )
ParserSound . add_arg ( " model " , " model " , ignore_default = True )
2013-03-18 01:06:52 +04:00
2016-06-13 23:30:29 +03:00
#####################
2014-09-20 22:29:34 +04:00
# --hostdev parsing #
2016-06-13 23:30:29 +03:00
#####################
2013-03-18 01:06:52 +04:00
2014-01-19 22:56:06 +04:00
class ParserHostdev ( VirtCLIParser ) :
2016-06-14 14:37:21 +03:00
cli_arg_name = " hostdev "
2016-06-13 23:30:29 +03:00
objclass = VirtualHostDevice
remove_first = " name "
2016-06-14 18:38:53 +03:00
def set_name_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
val = NodeDevice . lookupNodedevFromString ( inst . conn , val )
inst . set_from_nodedev ( val )
2016-06-14 18:38:53 +03:00
def name_lookup_cb ( self , inst , val , virtarg ) :
2016-06-13 23:30:29 +03:00
nodedev = NodeDevice . lookupNodedevFromString ( inst . conn , val )
return nodedev . compare_to_hostdev ( inst )
2016-06-14 14:37:21 +03:00
_register_virt_parser ( ParserHostdev )
2016-06-13 23:30:29 +03:00
_add_device_address_args ( ParserHostdev )
ParserHostdev . add_arg ( None , " name " ,
cb = ParserHostdev . set_name_cb ,
lookup_cb = ParserHostdev . name_lookup_cb )
ParserHostdev . add_arg ( " driver_name " , " driver_name " )
ParserHostdev . add_arg ( " boot.order " , " boot_order " )
ParserHostdev . add_arg ( " 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
###########################
2016-06-14 14:37:21 +03:00
# Public virt parser APIs #
2014-01-21 23:28:47 +04:00
###########################
2016-06-14 14:37:21 +03:00
def parse_option_strings ( options , guest , instlist , update = False ) :
2014-01-21 23:28:47 +04:00
"""
2016-06-14 14:37:21 +03:00
Iterate over VIRT_PARSERS , and launch the associated parser
2014-01-21 23:28:47 +04:00
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 = [ ]
2016-06-14 14:37:21 +03:00
for parserclass in VIRT_PARSERS :
optlist = util . listify ( getattr ( options , parserclass . cli_arg_name ) )
if not optlist :
2016-06-14 01:50:31 +03:00
continue
2016-06-14 14:37:21 +03:00
for inst in instlist :
if inst and optlist :
# If an object is passed in, we are updating it in place, and
# only use the last command line occurrence, eg. from virt-xml
optlist = [ optlist [ - 1 ] ]
2014-01-19 19:37:14 +04:00
2016-06-14 14:37:21 +03:00
for optstr in optlist :
parserobj = parserclass ( guest , optstr )
parseret = parserobj . parse ( inst , validate = not update )
ret + = util . listify ( parseret )
2014-01-26 04:51:56 +04:00
return ret
2014-01-22 18:06:35 +04:00
2016-06-14 14:37:21 +03:00
def check_option_introspection ( options ) :
2014-01-22 18:06:35 +04:00
"""
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
2016-06-14 14:37:21 +03:00
for parserclass in VIRT_PARSERS :
optlist = util . listify ( getattr ( options , parserclass . cli_arg_name ) )
if not optlist :
2014-01-22 18:06:35 +04:00
continue
2016-06-14 01:36:12 +03:00
2016-06-14 14:37:21 +03:00
for optstr in optlist :
2016-06-14 01:36:12 +03:00
if optstr == " ? " or optstr == " help " :
2016-06-14 14:37:21 +03:00
parserclass . print_introspection ( )
2016-06-14 01:36:12 +03:00
ret = True
2014-01-22 18:06:35 +04:00
return ret