[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]
[et-mgmt-tools] [PATCH] virt-install: Add --serial and --parallel options
- From: Cole Robinson <crobinso redhat com>
- To: Fedora/Linux Management Tools <et-mgmt-tools redhat com>
- Subject: [et-mgmt-tools] [PATCH] virt-install: Add --serial and --parallel options
- Date: Thu, 09 Jul 2009 15:26:18 -0400
The attached patch adds --serial and --parallel options to virt-install, for
attaching the respective devices to the new VM. Isn't much to say here, some
examples explain it all:
Serial PTY:
--serial pty
Parallel to a file:
--serial file,path=/tmp/foo.log
TCP net console in server mode, using telnet format:
--serial tcp,host=0.0.0.0:2222,mode=bind,protocol=telnet
UDP net console, sending output to the specified host:
--serial udp,host=192.168.10.20:4444
The man page has examples for several other types as well. --serial and
--parallel share the same option format, as they do in the libvirt xml.
Any questions or comments appreciated.
- Cole
# HG changeset patch
# User Cole Robinson <crobinso redhat com>
# Date 1247102899 14400
# Node ID 7751290d749d678e6a97a32ea5455af6e2226e78
# Parent 77b5e67be942bd75e5226612ee5fa5ab36c8a56d
virt-install: Add --serial and --parallel options.
Options take the same form of OPT1=VAL1,OPT2=VAL2,... similar to the --disk
option. The docs describe the rest.
diff -r 77b5e67be942 -r 7751290d749d man/en/virt-install.pod.in
--- a/man/en/virt-install.pod.in Wed Jul 08 21:23:32 2009 -0400
+++ b/man/en/virt-install.pod.in Wed Jul 08 21:28:19 2009 -0400
@@ -150,6 +150,82 @@
Attach a virtual audio device to the guest.
+=item --parallel=CHAROPTS
+
+=item --serial=CHAROPTS
+
+Specifies a serial device to attach to the guest, with various options. The
+general format of a serial string is
+
+ --serial type,opt1=val1,opt2=val2,...
+
+--serial and --parallel devices share all the same options, unless otherwise
+noted. Some of the types of character device redirection are:
+
+=over 4
+
+=item B<--serial pty>
+
+Psuedo TTY. The allocated pty will be listed in the running guests XML
+description.
+
+=item B<--serial dev,path=HOSTPATH>
+
+Host device. For serial devices, this could be /dev/ttyS0. For parallel
+devices, this could be /dev/parport0.
+
+=item B<--serial file,path=FILENAME>
+
+Write output to FILENAME.
+
+=item B<--serial pipe,path=PIPEPATH>
+
+Named pipe (see pipe(7))
+
+=item B<--serial tcp,host=HOST:PORT,mode=MODE,protocol=PROTOCOL>
+
+TCP net console. MODE is either 'bind' (wait for connections on HOST:PORT)
+or 'connect' (send output to HOST:PORT), default is 'connect'. HOST defaults
+to '127.0.0.1', but PORT is required. PROTOCOL can be either 'raw' or 'telnet'
+(default 'raw'). If 'telnet', the port acts like a telnet server or client.
+Some examples:
+
+Connect to localhost, port 1234:
+
+--serial tcp,host=:1234
+
+Wait for connections on any address, port 4567:
+
+--serial tcp,host=0.0.0.0:4567,mode=bind
+
+Wait for telnet connection on localhost, port 2222. The user could then
+connect interactively to this console via 'telnet localhost 2222':
+
+--serial tcp,host=:2222,mode=bind,protocol=telnet
+
+=item B<--serial udp,host=CONNECT_HOST:PORT,bind_port=BIND_HOST:BIND_PORT>
+
+UDP net console. HOST:PORT is the destination to send output to (default
+HOST is '127.0.0.1', PORT is required. BIND_HOST:PORT is the optional local
+address to bind to (default BIND_HOST is 127.0.0.1, but is only set if
+BIND_PORT is specified.) Some examples:
+
+Send output to default syslog port (may need to edit /etc/rsyslog.conf
+accordingly):
+
+--serial udp,host=:514
+
+Send output to remote host 192.168.10.20, port 4444 (this output can be
+read on the remote host using 'nc -u -l 4444':
+
+--serial udp,host=192.168.10.20:4444
+
+=item B<--serial unix,path=UNIXPATH,mode=MODE>
+
+Unix socket (see unix(7). MODE has similar behavior and defaults as 'tcp'.
+
+=back
+
=item --noapic
Override the OS type / variant to disables the APIC setting for fully
diff -r 77b5e67be942 -r 7751290d749d tests/clitest.py
--- a/tests/clitest.py Wed Jul 08 21:23:32 2009 -0400
+++ b/tests/clitest.py Wed Jul 08 21:28:19 2009 -0400
@@ -211,6 +211,36 @@
}, # category "graphics"
+ "char" : {
+ "char_args": "--hvm --nographics --noautoconsole --nodisks --pxe",
+
+ "valid": [
+ # Simple devs
+ "--serial pty --parallel null",
+ # Some with options
+ "--serial file,path=/tmp/foo --parallel unix,path=/tmp/foo --parallel null",
+ # UDP
+ "--parallel udp,host=0.0.0.0:1234,bind_host=127.0.0.1:1234",
+ # TCP
+ "--serial tcp,mode=bind,host=0.0.0.0:1234",
+ # Unix
+ "--parallel unix,path=/tmp/foo-socket",
+ # TCP w/ telnet
+ "--serial tcp,host=:1234,protocol=telnet",
+ ],
+ "invalid" : [
+ # Bogus device type
+ "--parallel foobah",
+ # Unix with no path
+ "--serial unix",
+ # Path where it doesn't belong
+ "--serial null,path=/tmp/foo",
+ # Nonexistent argument
+ "--serial udp,host=:1234,frob=baz",
+ ],
+
+ }, # category 'char'
+
"misc": {
"misc_args": "--nographics --noautoconsole",
diff -r 77b5e67be942 -r 7751290d749d virt-install
--- a/virt-install Wed Jul 08 21:23:32 2009 -0400
+++ b/virt-install Wed Jul 08 21:28:19 2009 -0400
@@ -33,6 +33,8 @@
import virtinst
import virtinst.CapabilitiesParser
import virtinst.cli as cli
+from virtinst.VirtualCharDevice import VirtualCharDevice
+from virtinst.VirtualDevice import VirtualDevice
from virtinst.cli import fail
import gettext
@@ -45,6 +47,17 @@
DEFAULT_POOL_PATH = "/var/lib/libvirt/images"
DEFAULT_POOL_NAME = "default"
+def partition(string, sep):
+ if not string:
+ return (None, None, None)
+
+ if string.count(sep):
+ splitres = string.split(sep, 1)
+ ret = (splitres[0], sep, splitres[1])
+ else:
+ ret = (string, None, None)
+ return ret
+
def build_default_pool(guest):
if not virtinst.util.is_storage_capable(guest.conn):
@@ -71,6 +84,70 @@
raise RuntimeError(_("Couldn't create default storage pool '%s': %s") %
(DEFAULT_POOL_PATH, str(e)))
+def parse_char_option(guest, char_type, optstring):
+ """
+ Helper to parse --serial/--parallel options
+ """
+ # Peel the char type off the front
+ dev_type, ignore, optstring = partition(optstring, ",")
+
+ opts = cli.parse_optstr(optstring)
+
+ dev = VirtualCharDevice.get_dev_instance(guest.conn, char_type, dev_type)
+
+ def set_param(paramname, dictname, val=None):
+ if not val:
+ if opts.has_key(dictname):
+ val = opts[dictname]
+ del(opts[dictname])
+ else:
+ return
+
+ if not hasattr(dev, paramname):
+ raise ValueError(_("%(chartype)s type %(devtype)s does not "
+ "support '%(optname)s' option.") %
+ {"chartype" : char_type, "devtype": dev_type,
+ "optname" : dictname} )
+ setattr(dev, paramname, val)
+
+ def parse_host(key):
+ host, ignore, port = partition(opts.get(key), ":")
+ if opts.has_key(key):
+ del(opts[key])
+
+ return host, port
+
+ host, port = parse_host("host")
+ bind_host, bind_port = parse_host("bind_host")
+
+ set_param("source_path", "path")
+ set_param("source_mode", "mode")
+ set_param("protocol", "protocol")
+ set_param("source_host", "host", host)
+ set_param("source_port", "host", port)
+ set_param("bind_host", "bind_host", bind_host)
+ set_param("bind_port", "bind_host", bind_port)
+
+ # If extra parameters, then user passed some garbage param
+ if opts:
+ raise ValueError(_("Unknown option(s) %s") % opts.keys())
+
+ # Try to generate dev XML to perform upfront validation
+ dev.get_xml_config()
+
+ return dev
+
+def get_chardevs(char_type, opts, guest):
+
+ for optstr in cli.listify(opts):
+ try:
+ dev = parse_char_option(guest, char_type, optstr)
+ guest.add_device(dev)
+ except Exception, e:
+ fail(_("Error in %(chartype)s device parameters: %(err)s") %
+ {"chartype": char_type, "err": str(e) })
+
+
def parse_disk_option(guest, path, size):
"""helper to properly parse --disk options"""
abspath = None
@@ -81,14 +158,6 @@
sparse = True
option_whitelist = ["perms", "cache", "bus", "device", "size", "sparse"]
- def partition(string, sep):
- if string.count(sep):
- splitres = string.split(sep, 1)
- ret = (splitres[0], sep, splitres[1])
- else:
- ret = (string, None, None)
- return ret
-
# Strip media type
path, ignore, optstr = partition(path, ",")
if path.startswith("path="):
@@ -459,6 +528,12 @@
action="callback", callback=cli.check_before_store,
help=_("The OS variant for fully virtualized guests, "
"e.g. 'fedora6', 'rhel5', 'solaris10', 'win2k'"))
+ geng.add_option("", "--serial", type="string", dest="serials",
+ action="callback", callback=cli.check_before_append,
+ help=_("Add a serial device to the domain."))
+ geng.add_option("", "--parallel", type="string", dest="parallels",
+ action="callback", callback=cli.check_before_append,
+ help=_("Add a parallel device to the domain."))
geng.add_option("", "--host-device", type="string", dest="hostdevs",
action="callback", callback=cli.check_before_append,
help=_("Physical host device to attach to the domain."))
@@ -549,7 +624,6 @@
netg.add_option("-m", "--mac", type="string", dest="mac",
action="callback", callback=cli.check_before_append,
help=optparse.SUPPRESS_HELP)
-
parser.add_option_group(netg)
vncg = cli.graphics_option_group(parser)
@@ -661,6 +735,9 @@
cli.get_cpuset(options.cpuset, guest.memory, guest, conn)
if ishvm:
cli.get_sound(options.sound, guest)
+ get_chardevs(VirtualDevice.VIRTUAL_DEV_SERIAL, options.serials, guest)
+ get_chardevs(VirtualDevice.VIRTUAL_DEV_PARALLEL, options.parallels,
+ guest)
# set up disks
get_disks(options.file_path, options.diskopts, options.disksize,
diff -r 77b5e67be942 -r 7751290d749d virtinst/cli.py
--- a/virtinst/cli.py Wed Jul 08 21:23:32 2009 -0400
+++ b/virtinst/cli.py Wed Jul 08 21:28:19 2009 -0400
@@ -452,6 +452,14 @@
# Ask for attributes
#
+def listify(l):
+ if l is None:
+ return []
+ elif type(l) != list:
+ return [ l ]
+ else:
+ return l
+
def get_name(name, guest, image_name=None):
prompt_txt = _("What is the name of your virtual machine?")
err_txt = _("A name is required for the virtual machine.")
@@ -614,14 +622,6 @@
"network" : network_name, "model" : model , "macaddr" : mac }
def digest_networks(conn, macs, bridges, networks, nics = 0):
- def listify(l):
- if l is None:
- return []
- elif type(l) != list:
- return [ l ]
- else:
- return l
-
macs = listify(macs)
bridges = listify(bridges)
networks = listify(networks)
[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]