Check-in [7d648e5be3]
Not logged in
Overview
Comment:Fix quoting of arguments of start command. Support per user configuration in .config/vws/vws.conf as well as .vwsrc Fix some pylint warnings
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7d648e5be3cc98ccc00e286915c4ff7ee4428799
User & Date: vitus on 2022-02-08 17:27:14
Other Links: manifest | tags
Context
2022-07-28
15:22
Version 0.8.1 - support new info network format check-in: e5904254e7 user: vitus tags: trunk
2022-02-08
17:27
Fix quoting of arguments of start command. Support per user configuration in .config/vws/vws.conf as well as .vwsrc Fix some pylint warnings check-in: 7d648e5be3 user: vitus tags: trunk
2020-01-16
18:18
Fix moninor command for python3 check-in: 9be36c3e65 user: vitus tags: trunk
Changes

Modified vws from [0a5a51e7d3] to [c5b995c8c3].

1
2
3
4
5
6
7
8
9
10
11
12
13



14
15
16

17
18
19
20
21
22
23
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













+
+
+



+







#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
""" vws - script to control QEMU/KVM virtual workstations """
# pylint: disable=too-many-lines
from configparser import ConfigParser
from argparse import ArgumentParser, Namespace
import fcntl
import socket
import select
import errno
import re
import os
import os.path
import fnmatch
import shlex
import shutil
import sys
import time
import pwd
import grp

VERSION = 0.8
def find_vm(name):
    """ Search and return VM directory """
    search_path = [os.path.join(pwd.getpwuid(os.getuid()).pw_dir, "VWs"),
                   config.get("directories", "SharedVMs"),
                   config.get("directories", "AutostartVMs")]
39
40
41
42
43
44
45
46

47
48

49
50
51
52
53
54
55
43
44
45
46
47
48
49

50
51

52
53
54
55
56
57
58
59







-
+

-
+







    try:
        sock.connect(monitor_path)
    except IOError as ex:
        if ex.errno == errno.ECONNREFUSED:
            # virtal machine is not running
            return None
        raise ex
    readfd, dummy_w, dummy_x = select.select([sock], [], [], 0.1)
    readfd, _, _ = select.select([sock], [], [], 0.1)
    if sock in readfd:
        dummy_greeting = sock.recv(1024)
        _ = sock.recv(1024)
    return sock

def send_command(sock, command):
    """ Sends monitor command to given socket and returns answer """
    if sock is None:
        raise RuntimeError("None socket is passed to send_command")
    fcntl.flock(sock, fcntl.LOCK_EX)
226
227
228
229
230
231
232
233

234

235

236
237

238
239

240
241


242

243
244
245
246
247
248
249
250
251
252
253
254
255

256
257
258
259
260
261
262
230
231
232
233
234
235
236

237
238
239

240
241

242
243

244
245
246
247
248

249
250
251
252
253
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269







-
+

+
-
+

-
+

-
+


+
+
-
+












-
+







    return None

def make_start_cmdline(options):
    """
    Append options passed from vws commandline to start script
    commandline
    """
    arg = ""
    arg = []
    if options.cdrom:
        arg.append("-cdrom")
        arg = " -cdrom " + os.path.abspath(options.cdrom[0])
        arg.append(os.path.abspath(options.cdrom[0]))
    if options.snapshot:
        arg = arg+" -snapshot"
        arg.append("-snapshot")
    if options.args:
        arg = arg + " " + "".join(options.args)
        arg.append( "".join(options.args))
    if options.password:
        os.environ["SPICE_PASSWORD"] = options.password[0]
    if arg:
        return shlex.join(arg)
    return arg
    return ""
def cmd_start(options):
    """ vws start """
    if not "DISPLAY" in os.environ:
        # If cannot start GUI just don't do it.
        options.gui = False
    if options.stopped:
        arg = make_start_cmdline(options)
        cwd = os.getcwd()
        os.chdir(options.dir)
        # Check for snapshot
        snapshot_id = check_for_snapshot(options.dir)
        if snapshot_id is not None:
            arg = arg + " -loadvm " + snapshot_id
            arg = arg + " " + shlex.join(["-loadvm", snapshot_id])
        # Check for correct brige name
        try:
            os.stat("monitor")
        except FileNotFoundError:
            # We cannot find monitor socket. So this machine might be
            # never run on this host
            fix_bridge_name("start")
314
315
316
317
318
319
320
321

322
323
324
325
326
327
328
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335







-
+







                idx = answer.index('\n')
                print(answer[idx+1:], end="")
                eol = answer.endswith("\n")
                sys.stdout.flush()
            elif options.sock in readfd:
                print("UNSOLICITED MESSAGE %" +
                      options.sock.recv(1000).decode("utf-8").rstrip())
                eol = True      
                eol = True
    except KeyboardInterrupt:
        if not eol:
            print("")
        eol = True
        print("Keyboard interrupt")
    if not eol:
        print("")
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492
493
494
495
483
484
485
486
487
488
489

490
491
492
493
494

495
496
497
498
499
500
501







-
+




-







        arp_data.update(parse_arp(bridge))
    for vminfo in listing:
        if "mac" in vminfo and not "ip" in vminfo:
            if vminfo["mac"] in arp_data:
                vminfo["ip"] = arp_data[vminfo["mac"]]
            else:
                vminfo["ip"] = "-"
def all_vms(patterns=["*"]):
def all_vms(patterns=("*",)):
    """
    Returns list of tuples  vmname, vmtype, directory
    for all vms
    """
    import fnmatch
    search_path = [("private", os.path.join(pwd.getpwuid(os.getuid()).pw_dir,
                                            "VWs")),
                   ("shared", config.get("directories", "SharedVMs")),
                   ("autostart", config.get("directories", "AutostartVMs"))]
    vmlist = []
    for (vmtype, dirname) in search_path:
        if not os.access(dirname, os.X_OK):
528
529
530
531
532
533
534
535
536

537
538
539
540
541
542

543
544
545
546
547
548
549
534
535
536
537
538
539
540


541
542
543
544
545


546
547
548
549
550
551
552
553







-
-
+




-
-
+







        else:
            print(f["name"])
    if not count:
        sys.exit(1)

def cmd_screenshot(options):
    """ vws screenshot """
    from os.path import abspath
    filename = abspath(options.filename)
    filename = os.path.abspath(options.filename)
    print(send_command(options.sock, "screendump " + filename))

def cmd_record(options):
    """ vws record """
    from os.path import abspath
    filename = abspath(options.filename)
    filename = os.path.abspath(options.filename)
    print(send_command(options.sock, "wavcapture " + filename))

def cmd_stoprecord(options):
    """ vws stoprecord """
    answer = send_command(options.sock, "info capture")
    match = re.search('\\[(\\d+)\\]: ', answer)
    if not match:
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
712
713
714
715
716
717
718

719
720
721
722
723
724
725







-







    print("")

def cmd_shutdown(options):
    """ Search for all running machines and stops all of them """
    dirlist = [config.get("directories", "AutostartVMs"),
               config.get("directories", "SharedVms")]
    if os.getresuid()[1] == 0:
        import grp
        dirlist += map(lambda x: os.path.expanduser("~"+x)+"/VWs",
                       grp.getgrnam(config.get("permissions",
                                               "vm_group")).gr_mem)
    else:
        dirlist.append(os.path.expanduser("~")+"/VWs")
    count = 1 #Fake positive values for there is not postcondition loop in the python
    forced_finish = time.time() + options.timeout
843
844
845
846
847
848
849
850

851
852
853

854

855
856
857
858
859
860
861
862
863
864
865
866
846
847
848
849
850
851
852

853
854
855

856
857
858
859
860
861
862

863
864
865
866
867
868
869







-
+


-
+

+




-








    options["memory"] = parsed_args.mem
    if parsed_args.localtime:
        options["rtc"] = "-rtc base=localtime,clock=host \\\n"

    if os.path.exists(machinedir):
        if os.path.exists(os.path.join(machinedir, "start")):
            raise OSError("Virtual Worstation %s already exists" %
            exc = OSError("Virtual Worstation %s already exists" %
                          parsed_args.machine)
        else:
            raise OSError("Cannot create VW directory, " +
            exc = OSError("Cannot create VW directory, " +
                          "something on the way")
        raise exc
    #  Creating directory for VM
    os.makedirs(machinedir, dirmode)
    parsed_args.dir = machinedir
    if parsed_args.shared:
        import grp
        gid = grp.getgrnam(config.get("permissions", "vm_group")).gr_gid
        uid = os.getuid()
        os.chown(machinedir, uid, gid)
        if config.getboolean("permissions", "setgid_vm"):
            os.chmod(machinedir, 0o2775)
    driveopts = {"interface":parsed_args.diskif, "image":drivename}
    if parsed_args.install:
938
939
940
941
942
943
944

945

946

947
948
949
950
951
952
953
941
942
943
944
945
946
947
948
949
950

951
952
953
954
955
956
957
958







+

+
-
+







                    'permissions':{'vm_group':'kvm',
                                   'autostart_user':'root',
                                   'setgid_vm':'yes'}})

def read_config(conf):
    """ Read configration files """
    if os.getuid() != 0:
        home = pwd.getpwuid(os.getuid()).pw_dir
        conf.read(['/etc/vws.conf',
                   os.path.join(home, ".config", "vws", "vws.conf"),
                   os.path.join(pwd.getpwuid(os.getuid()).pw_dir, '.vwsrc')])
                   os.path.join(home, '.vwsrc')])
    else:
        conf.read(['/etc/vws.conf'])
def main():
    """ Parse an arguments and execute everything """
    global config
    config_defaults(config)
    read_config(config)
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1093
1094
1095
1096
1097
1098
1099

1100
1101
1102
1103
1104
1105
1106







-







    # Create command is totally different, so it is handled separately
    if parsed_args.command == 'create':
        try:
            cmd_create(parsed_args)
        except Exception as ex: # pylint: disable=broad-except
            print(str(ex), file=sys.stderr)
            if hasattr(parsed_args, "dir"):
                import shutil
                shutil.rmtree(parsed_args.dir)
                sys.exit(1)
        sys.exit(0)

    if parsed_args.command is None:
        args.print_help()
        sys.exit(0)