Check-in [daa18d8131]
Not logged in
Overview
Comment:Added try-finally to the vws command execution. Fixes [5a1bd05199]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: daa18d8131ea5abb48005576e2ff32d1e63dd098
User & Date: vitus on 2015-12-18 05:26:38
Other Links: manifest | tags
Context
2015-12-18
08:32
Added function list_briges which disappeared somewhere when create command was incorporated in vws script check-in: 155c39c9b5 user: vitus tags: trunk
05:26
Added try-finally to the vws command execution. Fixes [5a1bd05199] check-in: daa18d8131 user: vitus tags: trunk
2015-12-17
14:31
Incremented version number to 0.2 check-in: b07302139d user: vitus tags: trunk
Changes

Deleted start.template version [92da85b8ac].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/sh
# Get machine name from current directory name
NAME=$(basename $(pwd))
# if remote access is enabled, then there should be
# SPICE_PASSWORD=password
QEMU_AUDIO_DRV=spice
export QEMU_AUDIO_DRV
if [ -n "$SPICE_PASSWORD" ]; then
   SPICE_AUTH="password=$SPICE_PASSWORD"
else
   SPICE_AUTH="disable-ticketing,addr=127.0.0.1"
fi
SPICE_PORT=$(find_free_port 5900)
if [ "$1" = '-cdrom' ]; then
	shift
	CDROM=",file=$1"
	shift
fi

{qemubinary} -name $NAME {accel} \
-m {memory} \
{drive} \
{cdrom}$CDROM \
{net} \
{usb} \
{sound} \
-chardev socket,server,nowait,path=monitor,id=monitor \
-mon chardev=monitor,mode=readline \
-vga {vga} \
-spice port=$SPICE_PORT,$SPICE_AUTH \
-device virtio-serial -chardev spicevmc,id=vdagent,name=vdagent \
-device virtserialport,chardev=vdagent,name=com.redhat.spice.0 \
-device ich9-usb-ehci1,id=usb \
-device ich9-usb-uhci1,masterbus=usb.0,firstport=0,multifunction=on \
-chardev spicevmc,name=usbredir,id=usbredirchardev1 \
-device usb-redir,chardev=usbredirchardev1,id=usbredirdev1 \
-daemonize -pidfile pid
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































Modified vws from [efb0c40873] to [c15e09c135].

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
                    result.append(m.group(1))
    return result

def cmd_snapshot(options):
    import os.path
    if not options.stopped:
        print >>sys.stderr,"Cannot make snapshot of running VW"
        return 1
    drives=get_drives(options.dir)
    os.chdir(options.dir)
    newnames={}
    for i in drives:
        name,ext=os.path.splitext(i)
        newnames[i]=name+"."+options.snapname+"."+ext
        if os.path.exists(newnames[i]):







|







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
                    result.append(m.group(1))
    return result

def cmd_snapshot(options):
    import os.path
    if not options.stopped:
        print >>sys.stderr,"Cannot make snapshot of running VW"
        sys.exit(1)
    drives=get_drives(options.dir)
    os.chdir(options.dir)
    newnames={}
    for i in drives:
        name,ext=os.path.splitext(i)
        newnames[i]=name+"."+options.snapname+"."+ext
        if os.path.exists(newnames[i]):
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
                return m.group(1)
    return None                

def cmd_revert(options):
    # Removes latest snapshot images and creates new ones instead
    if not options.stopped:
        print >>sys.stderr,"Cannot revert running VW to snapshot"
        return 1
    os.chdir(options.dir)
    for drive in get_drives(options.dir):
        # Check if first  has backing file
        backing=get_backing(drive)
        if not backing:
            print >>sys.stderr,"Drive %s has no snapshots"%drive
            continue







|







304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
                return m.group(1)
    return None                

def cmd_revert(options):
    # Removes latest snapshot images and creates new ones instead
    if not options.stopped:
        print >>sys.stderr,"Cannot revert running VW to snapshot"
        sys.exit(1)
    os.chdir(options.dir)
    for drive in get_drives(options.dir):
        # Check if first  has backing file
        backing=get_backing(drive)
        if not backing:
            print >>sys.stderr,"Drive %s has no snapshots"%drive
            continue
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511


config=ConfigParser({'SharedVMs':'/var/cache/vws/shared',
    'AutoStartVMs':'/var/cache/vws/autostart'})
config.add_section('directories')
config.read(['/etc/vws.conf',os.environ['HOME']+'/.vwsrc'])

args=ArgumentParser()
cmds=args.add_subparsers(dest='command',help="sub-command help")
p=cmds.add_parser("list",help="List existing VWs",description="List existing VWs")
p.add_argument("--state",action='store_const',const=True,default=False,
                dest='state',help='Show state of the machine')
p.add_argument("--addr",action='store_const',const=True,default=False,
                dest='addr',help='Show mac address and spice port')
p.add_argument("--usb",action='store_const',const=True,default=False,







|







497
498
499
500
501
502
503
504
505
506
507
508
509
510
511


config=ConfigParser({'SharedVMs':'/var/cache/vws/shared',
    'AutoStartVMs':'/var/cache/vws/autostart'})
config.add_section('directories')
config.read(['/etc/vws.conf',os.environ['HOME']+'/.vwsrc'])

args=ArgumentParser(description="Manage Virtual Workstations")
cmds=args.add_subparsers(dest='command',help="sub-command help")
p=cmds.add_parser("list",help="List existing VWs",description="List existing VWs")
p.add_argument("--state",action='store_const',const=True,default=False,
                dest='state',help='Show state of the machine')
p.add_argument("--addr",action='store_const',const=True,default=False,
                dest='addr',help='Show mac address and spice port')
p.add_argument("--usb",action='store_const',const=True,default=False,
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
# Screenshoits and recording
p=new_command(cmds,'screenshot',help='take a screenshot')
p.add_argument('filename',help='PPM image filename to write screenshot to')
p=new_command(cmds,'record',help='Record audio output from VM')
p.add_argument('filename',help='wav file to record autdio to')
new_command(cmds,'stoprecord',help='stop recording audio')
# Create new VM
p=new_command(cmds,'create',help="Create new VM")
p.add_argument("--no-usb",help="Disable USB controller",action='store_const', const = False, default=True, dest="usb")
p.add_argument("--size",metavar='size',help="Size of primary disk images",dest="size",default="20G");
p.add_argument("--arch",metavar='cputype',help="Emulated architecture",dest="arch",default='x86_64');
p.add_argument("--no-sound",help="Disable sound card",action='store_const',const = None,default='hda',  dest="sound")
p.add_argument("--sound",metavar='cardtype',help="Specify sound card type",dest='sound',default='hda')
p.add_argument("--vga",metavar='cardtype',help="specify video card type (cirrus,std,vmwae,qxl) default qxl",dest="vga",default="qxl")
p.add_argument("--net",help="Network - 'user' or bridge name",dest='net',default="user")
p.add_argument("--mem",metavar='size',help="Size of memory",dest="mem",default="1024M")
p.add_argument("--diskif",metavar='interface-type',help="Disk interface (virtio, scsi, ide)",choices=['virtio','scsi','ide'],dest="diskif",default="virtio")
p.add_argument('--shared',help='Create shared VM instead of private one',action='store_const',const= True,dest='shared',default=False)
p.add_argument('--image',metavar='filename',help='Existing disk image to import',dest='image',default=None)
p.add_argument('--install',metavar='filename.iso',help='ISO image to install OS from',dest='install',default=None)
# Miscellenia
p=new_command(cmds,'monitor',help='connect stdin/stdout to monitor of VM')
p=new_command(cmds,'spiceuri',help='Output spice URI of machine')

parsed_args=args.parse_args(sys.argv[1:])







|









|







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
# Screenshoits and recording
p=new_command(cmds,'screenshot',help='take a screenshot')
p.add_argument('filename',help='PPM image filename to write screenshot to')
p=new_command(cmds,'record',help='Record audio output from VM')
p.add_argument('filename',help='wav file to record autdio to')
new_command(cmds,'stoprecord',help='stop recording audio')
# Create new VM
p=new_command(cmds,'create',help="Create new VW")
p.add_argument("--no-usb",help="Disable USB controller",action='store_const', const = False, default=True, dest="usb")
p.add_argument("--size",metavar='size',help="Size of primary disk images",dest="size",default="20G");
p.add_argument("--arch",metavar='cputype',help="Emulated architecture",dest="arch",default='x86_64');
p.add_argument("--no-sound",help="Disable sound card",action='store_const',const = None,default='hda',  dest="sound")
p.add_argument("--sound",metavar='cardtype',help="Specify sound card type",dest='sound',default='hda')
p.add_argument("--vga",metavar='cardtype',help="specify video card type (cirrus,std,vmwae,qxl) default qxl",dest="vga",default="qxl")
p.add_argument("--net",help="Network - 'user' or bridge name",dest='net',default="user")
p.add_argument("--mem",metavar='size',help="Size of memory",dest="mem",default="1024M")
p.add_argument("--diskif",metavar='interface-type',help="Disk interface (virtio, scsi, ide)",choices=['virtio','scsi','ide'],dest="diskif",default="virtio")
p.add_argument('--shared',help='Create shared VW instead of private one',action='store_const',const= True,dest='shared',default=False)
p.add_argument('--image',metavar='filename',help='Existing disk image to import',dest='image',default=None)
p.add_argument('--install',metavar='filename.iso',help='ISO image to install OS from',dest='install',default=None)
# Miscellenia
p=new_command(cmds,'monitor',help='connect stdin/stdout to monitor of VM')
p=new_command(cmds,'spiceuri',help='Output spice URI of machine')

parsed_args=args.parse_args(sys.argv[1:])
595
596
597
598
599
600
601

602
603
604
605
606
607
608
609

610
611
612
613
            print >>sys.stderr, "Virtual machine %s is not running."%parsed_args.machine
            sys.exit(1)
        else:
            parsed_args.stopped = True

funcname="cmd_"+parsed_args.command


if hasattr(parsed_args,"subcommand"):
    funcname+="_"+parsed_args.subcommand
try:
   func=globals()[funcname]
except KeyError:
    print >>sys.stderr,"Operation %s is not implemented"%funcname
    sys.exit(3)
func(parsed_args)

if hasattr(parsed_args,'sock') and parsed_args.sock is not None:
    parsed_args.sock.shutdown(socket.SHUT_RDWR)
    parsed_args.sock.close()








>
|
|
|
|
|
|
|
|
>
|
|
|

595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
            print >>sys.stderr, "Virtual machine %s is not running."%parsed_args.machine
            sys.exit(1)
        else:
            parsed_args.stopped = True

funcname="cmd_"+parsed_args.command

try:
    if hasattr(parsed_args,"subcommand"):
        funcname+="_"+parsed_args.subcommand
    try:
        func=globals()[funcname]
    except KeyError:
        print >>sys.stderr,"Operation %s is not implemented"%funcname
        sys.exit(3)
    func(parsed_args)
finally:    
    if hasattr(parsed_args,'sock') and parsed_args.sock is not None:
        parsed_args.sock.shutdown(socket.SHUT_RDWR)
        parsed_args.sock.close()

Added vws.mkd version [83850157de].

















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
NAME
====

*vws* - manage Virtual Workstations

SYNOPSIS
========

**vws create** *name* [ **--install** *isoimage* ]

**vws list**  [**--state**] [**--usb** ]

**vws start** *name* [**--no-gui**] [**--cdrom** *iso-image*]

**vws stop** *name* [**--hard**]

**vws save** *name*

**vws reset** *name*

**vws cdrom** [ **--id** *id* ] [ *iso-image* | **--eject *]

**vws usb attach** *name*  *pattern*

**vws usb detach** *name*  *pattern*

**vws usb attached** *name* 

**vws usb list** 

**vws snapshot** *name* [ *id* ]

**vws revert** *name* [ *id* ]

**vws commit** *name*

**vws snapshots**  *name*

**vws screenshot** *name* *filename.ppm*

**vws record** *name* *filename.wav*

**vws stoprecord**  *name*

**vws monitor** *name*

**vws spiceuri** *name*

**vws version** 

DESCRIPTION
===========

**vws** is thin scripting layer around **qemu-system**(1), which aims to
simplify common tasks for some usage scenarios. Note that **qemu** command
line is so complicated for good purpose, so any attempt to simplify it
would make some functionality unavailable.

**vws** is intended for software developers, who need to manually test
software on various systems, read documentation on them and experiment.
So, it is Virtual WorkStation system, not virtual servers or application
container.

It aims to allow user play with virtual machines directly, bypassing
vws. User is allowed to alter **qemu** parameters directly in the
**vws**-generated startup scripts and connect to monitor typing monitor
commands by hand. Copying virtual workstation from one host to another
is just a matter of transferring several files. 

VW CREATION
-----------

**vws create** command creates basic layout of the virtual machine -
virtual disk image and startup script and optionally starts installation
process connecting specified ISO-image to virtual CD-ROM drive.

It is also possible to create new machine with copy of existing virtual
drive.

Options of **create** commands allow to alter hardware configuration
(memory and disk size, disk interface, sound hardware, video card
disable sound and usb altogether).

What is hardcoded into **vws** system is that

1. Use unix domain socket in the same directory as startup script for
monitor. vws script rely of the existence of this script.
2. Use of **qcow2** image format. Without it, snapshots and saving VM
state would not work
3. Use spice as GUI protocol. It is only protocol which allows to share
clipboard of quest with clipboard of host, and redirect USB devices via
network.

Shared or personal VWs
----------------------

**vws** support creation of personal and shared VWs. Personal VWs is
created in the user home directory and accessible only for owner. Shared
VWs are created in some system wide directory and accessible for the
members of some group. By default it use **kvm** group, since only
members of this group have read-write access use kernel virtualisation 
module, and it greatly improves performance of qemu for compatible
architectures.

VWs networking
--------------

**qemu** support various ways to connect virtual machine to network.
**vws** support only two of them - user mode network stack or bridged
network. By default VW is created with user mode network stack, which
basically means that it can establish outgoing TCP connections, but
there is no way to connect to it from outside world. (There is ways to
forward host ports to virtual machine in QEMU, but you'll have to hack
startup script manually to use it in the **vws** created machine).

Other way is bridged networking. I.e. each virtual machine would create
tun interface which would be connected to some bridge.

To use this mode, you have to perform following setup tasks

1. Make qemu-bridge-helper utility setuid root. (it is designed to run
setuid root, but Debian doesn't install it such way). It is required to
allow qemu, started from non-root user to add interface to bridge.
2. Create bridge interface to use. You can have several bridges and
specify which one would be used on VW creation. Really, by manual
editing of the startup script, you can add several network interfaces to
VW and connect them to the different bridges.
3. Setup you host system to forward packets from bridge network to
outside internet. You can either use NAT, or include your ethernet
interface into bridge.
4. Make sure DHCP server is running in the bridge network. If your
ethernet interface is part of the bridge, VWs would get their dynamic IP
from your network router. If you use NAT, you'll need to run DHCP
server, for instance **dnsmasq**(8) on your host and make it serve your bridge
interface. You can live without DHCP on bridge, but it would be your
problem to configure IP address on each VW manually. If you are planning
to deploy many VWs with different operating systems, it is better to
have DHCP running.


STARTING AND STOPPING
---------------------

REMOVABLE DEVICE MANAGEMENT
---------------------------

SNAPSHOTS
---------

MISCELLANEA
-----------

**vws** allows to take virtual machine screenshot or record sound,
produced by virtual machine. One don't need to have GUI window open to
take screenshots.


OPTIONS
=======

INTERNALS
=========

CONFIGURATION FILE
------------------

LAYOUT OF VIRTUAL MACHINES
--------------------------