~ubuntu-branches/ubuntu/quantal/virtinst/quantal-proposed

« back to all changes in this revision

Viewing changes to virtinst/cli.py

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Léonard
  • Date: 2011-01-29 21:41:21 UTC
  • mto: (1.6.3 sid)
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: james.westby@ubuntu.com-20110129214121-pjuxf2xz08l5zqew
Tags: upstream-0.500.5
Import upstream version 0.500.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
20
# MA 02110-1301 USA.
21
21
 
22
 
import os, sys
 
22
import os
 
23
import sys
23
24
import logging
24
25
import logging.handlers
25
 
import gettext, locale
 
26
import gettext
 
27
import locale
26
28
import optparse
27
 
from optparse import OptionValueError, OptionParser
 
29
from optparse import OptionValueError, OptionParser, OptionGroup
 
30
import re
 
31
import difflib
 
32
import tempfile
28
33
 
29
34
import libvirt
30
35
import _util
31
36
import virtinst
32
 
from virtinst import VirtualNetworkInterface, VirtualVideoDevice, Guest, \
 
37
from _util import listify
 
38
from virtinst import VirtualNetworkInterface, Guest, \
33
39
                     VirtualGraphics, VirtualAudio, VirtualDisk, User
34
40
from virtinst import _virtinst as _
35
41
 
36
42
MIN_RAM = 64
37
43
force = False
 
44
quiet = False
38
45
doprompt = True
39
46
 
40
 
def check_if_test_uri_remote(uri):
41
 
    magic = "__virtinst_test_remote__"
42
 
    if uri and uri.startswith(magic):
43
 
        uri = uri.replace(magic, "")
 
47
log_exception = _util.log_exception
 
48
_virtinst_uri_magic = "__virtinst_test__"
 
49
 
 
50
def _is_virtinst_test_uri(uri):
 
51
    return uri and uri.startswith(_virtinst_uri_magic)
 
52
 
 
53
def _open_test_uri(uri):
 
54
    """
 
55
    This hack allows us to fake various drivers via passing a magic
 
56
    URI string to virt-*. Helps with testing
 
57
    """
 
58
    uri = uri.replace(_virtinst_uri_magic, "")
 
59
    ret = uri.split(",", 1)
 
60
    uri = ret[0]
 
61
    ignore, opts = parse_optstr(len(ret) > 1 and ret[1] or "")
 
62
 
 
63
    conn = open_connection(uri)
 
64
 
 
65
    def sanitize_xml(xml):
 
66
        orig = xml
 
67
        xml = re.sub("arch='.*'", "arch='i686'", xml)
 
68
        xml = re.sub("domain type='.*'", "domain type='test'", xml)
 
69
        xml = re.sub("machine type='.*'", "", xml)
 
70
 
 
71
        logging.debug("virtinst test sanitizing diff\n:%s" %
 
72
                      "\n".join(difflib.unified_diff(orig.split("\n"),
 
73
                                                     xml.split("\n"))))
 
74
        return xml
 
75
 
 
76
    # Need tmpfile names to be deterministic
 
77
    if "predictable" in opts:
 
78
        def fakemkstemp(prefix, *args, **kwargs):
 
79
            ignore = args
 
80
            ignore = kwargs
 
81
            filename = os.path.join(".", prefix)
 
82
            return os.open(filename, os.O_RDWR | os.O_CREAT), filename
 
83
        tempfile.mkstemp = fakemkstemp
 
84
 
 
85
        _util.randomMAC = lambda type_: "00:11:22:33:44:55"
 
86
        _util.uuidToString = lambda r: "00000000-1111-2222-3333-444444444444"
 
87
 
 
88
    # Fake remote status
 
89
    if "remote" in opts:
44
90
        _util.is_uri_remote = lambda uri_: True
45
 
    return uri
 
91
 
 
92
    # Fake capabilities
 
93
    if "caps" in opts:
 
94
        capsxml = file(opts["caps"]).read()
 
95
        conn.getCapabilities = lambda: capsxml
 
96
 
 
97
    if "qemu" in opts or "xen" in opts:
 
98
        conn.getVersion = lambda: 10000000000
 
99
 
 
100
        origcreate = conn.createLinux
 
101
        origdefine = conn.defineXML
 
102
        def newcreate(xml, flags):
 
103
            xml = sanitize_xml(xml)
 
104
            origcreate(xml, flags)
 
105
        def newdefine(xml):
 
106
            xml = sanitize_xml(xml)
 
107
            origdefine(xml)
 
108
        conn.createLinux = newcreate
 
109
        conn.defineXML = newdefine
 
110
 
 
111
        if "qemu" in opts:
 
112
            conn.getURI = lambda: "qemu+abc:///system"
 
113
        if "xen" in opts:
 
114
            conn.getURI = lambda: "xen+abc:///"
 
115
 
 
116
    return conn
46
117
 
47
118
class VirtStreamHandler(logging.StreamHandler):
48
119
 
74
145
        encoding = getattr(f, "encoding", None)
75
146
        if not encoding:
76
147
            (dummy, encoding) = locale.getlocale()
 
148
        if not encoding:
 
149
            encoding = "UTF-8"
77
150
        return encoding
78
151
 
79
152
    def print_help(self, file=None):
133
206
    gettext.bindtextdomain(virtinst.gettext_app, virtinst.gettext_dir)
134
207
    gettext.install(virtinst.gettext_app, virtinst.gettext_dir)
135
208
 
136
 
def setupLogging(appname, debug=False):
137
 
    # set up logging
 
209
def earlyLogging():
 
210
    logging.basicConfig(level=logging.DEBUG, format='%(message)s')
 
211
 
 
212
def setupLogging(appname, debug=False, do_quiet=False):
 
213
    global quiet
 
214
    quiet = do_quiet
 
215
 
138
216
    vi_dir = os.path.expanduser("~/.virtinst")
139
217
    if not os.access(vi_dir, os.W_OK):
140
218
        if os.path.exists(vi_dir):
148
226
 
149
227
 
150
228
    dateFormat = "%a, %d %b %Y %H:%M:%S"
151
 
    fileFormat = "[%(asctime)s " + appname + " %(process)d] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
 
229
    fileFormat = ("[%(asctime)s " + appname + " %(process)d] "
 
230
                  "%(levelname)s (%(module)s:%(lineno)d) %(message)s")
152
231
    streamDebugFormat = "%(asctime)s %(levelname)-8s %(message)s"
153
232
    streamErrorFormat = "%(levelname)-8s %(message)s"
154
233
    filename = os.path.join(vi_dir, appname + ".log")
155
234
 
156
235
    rootLogger = logging.getLogger()
 
236
 
 
237
    # Undo early logging
 
238
    for handler in rootLogger.handlers:
 
239
        rootLogger.removeHandler(handler)
 
240
 
157
241
    rootLogger.setLevel(logging.DEBUG)
158
 
    fileHandler = logging.handlers.RotatingFileHandler(filename, "a",
159
 
                                                       1024*1024, 5)
 
242
    fileHandler = logging.handlers.RotatingFileHandler(filename, "ae",
 
243
                                                       1024 * 1024, 5)
160
244
 
161
245
    fileHandler.setFormatter(logging.Formatter(fileFormat,
162
246
                                               dateFormat))
168
252
        streamHandler.setFormatter(logging.Formatter(streamDebugFormat,
169
253
                                                     dateFormat))
170
254
    else:
171
 
        streamHandler.setLevel(logging.ERROR)
 
255
        if quiet:
 
256
            level = logging.ERROR
 
257
        else:
 
258
            level = logging.WARN
 
259
        streamHandler.setLevel(level)
172
260
        streamHandler.setFormatter(logging.Formatter(streamErrorFormat))
173
261
    rootLogger.addHandler(streamHandler)
174
262
 
193
281
def fail(msg, do_exit=True):
194
282
    """Convenience function when failing in cli app"""
195
283
    logging.error(msg)
196
 
    _util.log_exception()
 
284
    log_exception()
197
285
    if do_exit:
198
286
        _fail_exit()
199
287
 
 
288
def print_stdout(msg, do_force=False):
 
289
    if do_force or not quiet:
 
290
        print msg
 
291
 
 
292
def print_stderr(msg):
 
293
    logging.debug(msg)
 
294
    print >> sys.stderr, msg
 
295
 
200
296
def _fail_exit():
201
297
    sys.exit(1)
202
298
 
203
299
def nice_exit():
204
 
    print _("Exiting at user request.")
 
300
    print_stdout(_("Exiting at user request."))
205
301
    sys.exit(0)
206
302
 
 
303
def virsh_start_cmd(guest):
 
304
    return ("virsh --connect %s start %s" % (guest.conn.getURI(), guest.name))
 
305
 
 
306
def install_fail(guest):
 
307
    virshcmd = virsh_start_cmd(guest)
 
308
 
 
309
    print_stderr(
 
310
        _("Domain installation does not appear to have been successful.\n"
 
311
          "If it was, you can restart your domain by running:\n"
 
312
          "  %s\n"
 
313
          "otherwise, please restart your installation.") % virshcmd)
 
314
    sys.exit(1)
 
315
 
207
316
# Connection opening helper functions
208
 
def getConnection(connect):
209
 
    if (connect and
210
 
        not User.current().has_priv(User.PRIV_CREATE_DOMAIN, connect)):
 
317
def getConnection(uri):
 
318
    if (uri and not User.current().has_priv(User.PRIV_CREATE_DOMAIN, uri)):
211
319
        fail(_("Must be root to create Xen guests"))
212
320
 
213
 
    # Hack to facilitate remote unit testing
214
 
    connect = check_if_test_uri_remote(connect)
 
321
    # Hack to facilitate virtinst unit testing
 
322
    if _is_virtinst_test_uri(uri):
 
323
        return _open_test_uri(uri)
215
324
 
216
 
    logging.debug("Requesting libvirt URI %s" % (connect or "default"))
217
 
    conn = open_connection(connect)
 
325
    logging.debug("Requesting libvirt URI %s" % (uri or "default"))
 
326
    conn = open_connection(uri)
218
327
    logging.debug("Received libvirt URI %s" % conn.getURI())
219
328
 
220
329
    return conn
235
344
    try:
236
345
        return _do_creds(creds, cbdata)
237
346
    except:
238
 
        _util.log_exception("Error in creds callback.")
 
347
        log_exception("Error in creds callback.")
239
348
        raise
240
349
 
241
350
def _do_creds(creds, cbdata_ignore):
334
443
def is_prompt():
335
444
    return doprompt
336
445
 
337
 
def prompt_for_input(noprompt_err, prompt = "", val = None, failed=False):
 
446
def prompt_for_input(noprompt_err, prompt="", val=None, failed=False):
338
447
    if val is not None:
339
448
        return val
340
449
 
343
452
            # We already failed validation in a previous function, just exit
344
453
            _fail_exit()
345
454
 
346
 
        msg = noprompt_err
347
 
        if not force and not msg.count("--prompt"):
348
 
            # msg wasn't already appended to from yes_or_no
349
 
            msg = noprompt_err + " " + _("(use --prompt to run interactively)")
350
 
        fail(msg)
 
455
        fail(noprompt_err)
351
456
 
352
 
    print prompt + " ",
 
457
    print_stdout(prompt + " ", do_force=True)
353
458
    return sys.stdin.readline().strip()
354
459
 
355
460
def yes_or_no_convert(s):
363
468
def yes_or_no(s):
364
469
    ret = yes_or_no_convert(s)
365
470
    if ret == None:
366
 
        raise ValueError, "A yes or no response is required"
 
471
        raise ValueError(_("A yes or no response is required"))
367
472
    return ret
368
473
 
369
474
def prompt_for_yes_or_no(warning, question):
407
512
            passed_val = None
408
513
            failed = True
409
514
 
 
515
def vcpu_cli_options(grp):
 
516
    grp.add_option("", "--vcpus", type="string", dest="vcpus",
 
517
        help=_("Number of vcpus to configure for your guest. Ex:\n"
 
518
               "--vcpus 5\n"
 
519
               "--vcpus 5,maxcpus=10\n"
 
520
               "--vcpus sockets=2,cores=4,threads=2"))
 
521
    grp.add_option("", "--cpuset", type="string", dest="cpuset",
 
522
                   action="callback", callback=check_before_store,
 
523
                   help=_("Set which physical CPUs Domain can use."))
 
524
    grp.add_option("", "--cpu", type="string", dest="cpu",
 
525
        action="callback", callback=check_before_store,
 
526
        help=_("CPU model and features. Ex: --cpu coreduo,+x2apic"))
 
527
    grp.add_option("", "--check-cpu", action="store_true", dest="check_cpu",
 
528
                   help=optparse.SUPPRESS_HELP)
 
529
 
410
530
# Register vnc + sdl options for virt-install and virt-image
411
531
def graphics_option_group(parser):
412
 
    from optparse import OptionGroup
413
532
 
414
533
    vncg = OptionGroup(parser, _("Graphics Configuration"))
 
534
    vncg.add_option("", "--graphics", type="string", dest="graphics",
 
535
                    action="callback", callback=check_before_store,
 
536
      help=_("Specify display configuration. Ex:\n"
 
537
             "--graphics vnc\n"
 
538
             "--graphics spice,port=1,tlsport=2\n"
 
539
             "--graphics none\n"
 
540
             "--graphics vnc,password=foobar,port=5910,keymap=ja"))
415
541
    vncg.add_option("", "--vnc", action="store_true", dest="vnc",
416
 
                    help=_("Use VNC for graphics support"))
 
542
                    help=optparse.SUPPRESS_HELP)
417
543
    vncg.add_option("", "--vncport", type="int", dest="vncport",
418
 
                    help=_("Port to use for VNC"))
 
544
                    help=optparse.SUPPRESS_HELP)
419
545
    vncg.add_option("", "--vnclisten", type="string", dest="vnclisten",
420
 
                    help=_("Address to listen on for VNC connections."))
 
546
                    help=optparse.SUPPRESS_HELP)
421
547
    vncg.add_option("-k", "--keymap", type="string", dest="keymap",
422
548
                    action="callback", callback=check_before_store,
423
 
                    help=_("set up keymap for the VNC console"))
 
549
                    help=optparse.SUPPRESS_HELP)
424
550
    vncg.add_option("", "--sdl", action="store_true", dest="sdl",
425
 
                    help=_("Use SDL for graphics support"))
 
551
                    help=optparse.SUPPRESS_HELP)
426
552
    vncg.add_option("", "--nographics", action="store_true",
427
 
                    help=_("Don't set up a graphical console for the guest."))
 
553
                    help=optparse.SUPPRESS_HELP)
428
554
    return vncg
429
555
 
430
556
# Specific function for disk prompting. Returns a validated VirtualDisk
457
583
            msg = _("What would you like to use as the disk (file path)?")
458
584
            if not size is None:
459
585
                msg = _("Please enter the path to the file you would like to "
460
 
                        "use for storage. It will have size %sGB.") %(size,)
 
586
                        "use for storage. It will have size %sGB.") % size
461
587
 
462
588
        if not no_path_needed:
463
589
            path = prompt_for_input(patherr, prompt_txt or msg, passed_path)
494
620
        askmsg = _("Do you really want to use this disk (yes or no)")
495
621
 
496
622
        # Prompt if disk file already exists and preserve mode is not used
497
 
        if ((path_exists and dev.type == dev.TYPE_FILE and warn_overwrite) or
498
 
            is_prompt()):
 
623
        does_collide = (path_exists and
 
624
                        dev.type == dev.TYPE_FILE and
 
625
                        dev.device == dev.DEVICE_DISK)
 
626
        if (does_collide and (warn_overwrite or is_prompt())):
499
627
            msg = (_("This will overwrite the existing path '%s'" %
500
628
                   dev.path))
501
629
            if not prompt_for_yes_or_no(msg, askmsg):
521
649
# Ask for attributes
522
650
#
523
651
 
524
 
def listify(l):
525
 
    if l is None:
526
 
        return []
527
 
    elif type(l) != list:
528
 
        return [ l ]
529
 
    else:
530
 
        return l
 
652
name_missing    = _("--name is required")
 
653
ram_missing     = _("--ram amount in MB is required")
531
654
 
532
655
def get_name(name, guest, image_name=None):
533
656
    prompt_txt = _("What is the name of your virtual machine?")
534
 
    err_txt = _("A name is required for the virtual machine.")
 
657
    err_txt = name_missing
535
658
 
536
659
    if name is None:
537
660
        name = image_name
539
662
 
540
663
def get_memory(memory, guest, image_memory=None):
541
664
    prompt_txt = _("How much RAM should be allocated (in megabytes)?")
542
 
    err_txt = _("Memory amount is required for the virtual machine.")
 
665
    err_txt = ram_missing
 
666
 
543
667
    def check_memory(mem):
544
668
        mem = int(mem)
545
669
        if mem < MIN_RAM:
548
672
        guest.memory = mem
549
673
 
550
674
    if memory is None and image_memory is not None:
551
 
        memory = int(image_memory)/1024
 
675
        memory = int(image_memory) / 1024
552
676
    prompt_loop(prompt_txt, err_txt, memory, guest, "memory",
553
677
                func=check_memory)
554
678
 
559
683
        except ValueError, e:
560
684
            fail(e)
561
685
 
562
 
def get_vcpus(vcpus, check_cpu, guest, conn, image_vcpus=None):
 
686
def _build_set_param(inst, opts):
 
687
    def _set_param(paramname, keyname, val=None):
 
688
        val = get_opt_param(opts, keyname, val)
 
689
        if val == None:
 
690
            return
 
691
        setattr(inst, paramname, val)
 
692
 
 
693
    return _set_param
 
694
 
 
695
def parse_vcpu_option(guest, optstring, default_vcpus):
 
696
    """
 
697
    Helper to parse --vcpu string
 
698
    """
 
699
    vcpus, opts = parse_optstr(optstring, remove_first=True)
 
700
    vcpus = vcpus or default_vcpus
 
701
 
 
702
    set_param = _build_set_param(guest, opts)
 
703
    set_cpu_param = _build_set_param(guest.cpu, opts)
 
704
    has_vcpus = ("vcpus" in opts or vcpus)
 
705
 
 
706
    set_param("vcpus", "vcpus", vcpus)
 
707
    set_param("maxvcpus", "maxvcpus")
 
708
 
 
709
    set_cpu_param("sockets", "sockets")
 
710
    set_cpu_param("cores", "cores")
 
711
    set_cpu_param("threads", "threads")
 
712
 
 
713
    if not has_vcpus:
 
714
        guest.vcpus = guest.cpu.vcpus_from_topology()
 
715
 
 
716
    if opts:
 
717
        raise ValueError(_("Unknown options %s") % opts.keys())
 
718
 
 
719
 
 
720
def get_vcpus(vcpus, check_cpu, guest, image_vcpus=None):
 
721
    if vcpus is None and image_vcpus is not None:
 
722
        vcpus = int(image_vcpus)
 
723
 
 
724
    parse_vcpu_option(guest, vcpus, image_vcpus)
 
725
 
 
726
    conn = guest.conn
563
727
    if check_cpu:
564
728
        hostinfo = conn.getInfo()
565
729
        cpu_num = hostinfo[4] * hostinfo[5] * hostinfo[6] * hostinfo[7]
572
736
            if not prompt_for_yes_or_no(msg, askmsg):
573
737
                nice_exit()
574
738
 
575
 
    if vcpus is None and image_vcpus is not None:
576
 
        vcpus = int(image_vcpus)
577
 
    if vcpus is not None:
578
 
        try:
579
 
            guest.vcpus = vcpus
580
 
        except ValueError, e:
581
 
            fail(e)
582
739
 
583
 
def get_cpuset(cpuset, mem, guest, conn):
 
740
def get_cpuset(cpuset, mem, guest):
 
741
    conn = guest.conn
584
742
    if cpuset and cpuset != "auto":
585
743
        guest.cpuset = cpuset
586
744
 
597
755
 
598
756
    return
599
757
 
 
758
def parse_cpu(guest, optstring):
 
759
    default_dict = {
 
760
        "force": [],
 
761
        "require": [],
 
762
        "optional": [],
 
763
        "disable": [],
 
764
        "forbid": [],
 
765
    }
 
766
    model, opts = parse_optstr(optstring,
 
767
                               basedict=default_dict,
 
768
                               remove_first=True)
 
769
 
 
770
    # Convert +feature, -feature into expected format
 
771
    for key, value in opts.items():
 
772
        policy = None
 
773
        if value or len(key) == 1:
 
774
            continue
 
775
 
 
776
        if key.startswith("+"):
 
777
            policy = "force"
 
778
        elif key.startswith("-"):
 
779
            policy = "disable"
 
780
 
 
781
        if policy:
 
782
            del(opts[key])
 
783
            opts[policy].append(key[1:])
 
784
 
 
785
    set_param = _build_set_param(guest.cpu, opts)
 
786
    def set_features(policy):
 
787
        for name in opts.get(policy):
 
788
            guest.cpu.add_feature(name, policy)
 
789
        del(opts[policy])
 
790
 
 
791
    if model == "host":
 
792
        guest.cpu.copy_host_cpu()
 
793
        model = None
 
794
 
 
795
    set_param("model", "model", model)
 
796
    set_param("match", "match")
 
797
    set_param("vendor", "vendor")
 
798
 
 
799
    set_features("force")
 
800
    set_features("require")
 
801
    set_features("optional")
 
802
    set_features("disable")
 
803
    set_features("forbid")
 
804
 
 
805
    if opts:
 
806
        raise ValueError(_("Unknown options %s") % opts.keys())
 
807
 
600
808
def get_network(net_kwargs, guest):
601
809
    n = VirtualNetworkInterface(**net_kwargs)
602
810
    guest.nics.append(n)
613
821
            guest.set_os_variant(distro_variant)
614
822
 
615
823
def parse_optstr_tuples(optstr):
 
824
    """
 
825
    Parse optstr into a list of ordered tuples
 
826
    """
616
827
    optstr = str(optstr or "")
617
828
    optlist = []
618
829
 
625
836
        opt_val = None
626
837
        if opt.count("="):
627
838
            opt_type, opt_val = opt.split("=", 1)
628
 
            optlist.append((opt_type.lower(), opt_val.lower()))
 
839
            optlist.append((opt_type.lower(), opt_val))
629
840
        else:
630
841
            optlist.append((opt.lower(), None))
631
842
 
632
843
    return optlist
633
844
 
634
 
def parse_optstr(optstr, basedict=None):
 
845
def parse_optstr(optstr, basedict=None, remove_first=False):
635
846
    """
636
847
    Helper function for parsing opt strings of the form
637
848
    opt1=val1,opt2=val2,...
638
 
    'basedict' is a starting dictionary, so the caller can easily set
639
 
    default values, etc.
 
849
 
 
850
    @param basedict: starting dictionary, so the caller can easily set
 
851
                     default values, etc.
 
852
    @param remove_first: If true, remove the first options off the string
 
853
                         and return it seperately. For example,
 
854
                         --serial pty,foo=bar returns ("pty", {"foo" : "bar"})
640
855
 
641
856
    Returns a dictionary of {'opt1': 'val1', 'opt2': 'val2'}
642
857
    """
643
858
    optlist = parse_optstr_tuples(optstr)
644
859
    optdict = basedict or {}
 
860
    first = None
 
861
 
 
862
    if remove_first and optlist:
 
863
        first_tuple = optlist[0]
 
864
        if first_tuple[1] == None:
 
865
            first = first_tuple[0]
 
866
            optlist.remove(first_tuple)
645
867
 
646
868
    for opt, val in optlist:
647
 
        optdict[opt] = val
 
869
        if type(optdict.get(opt)) is list:
 
870
            optdict[opt].append(val)
 
871
        else:
 
872
            optdict[opt] = val
648
873
 
649
 
    return optdict
 
874
    return (first, optdict)
650
875
 
651
876
def parse_network_opts(conn, mac, network):
652
877
    net_type = None
675
900
        bridge_name = netdata
676
901
 
677
902
    # Pass the remaining arg=value pairs
678
 
    opts = parse_optstr(",".join(args))
 
903
    ignore, opts = parse_optstr(",".join(args))
679
904
    for opt_type, ignore_val in opts.items():
680
905
        if opt_type not in option_whitelist:
681
906
            fail(_("Unknown network option '%s'") % opt_type)
687
912
    # __init__
688
913
    if mac == "RANDOM":
689
914
        mac = None
690
 
    return { "conn" : conn, "type" : net_type, "bridge": bridge_name,
691
 
             "network" : network_name, "model" : model , "macaddr" : mac }
 
915
    return {"conn" : conn, "type" : net_type, "bridge": bridge_name,
 
916
            "network" : network_name, "model" : model , "macaddr" : mac}
692
917
 
693
 
def digest_networks(conn, macs, bridges, networks, nics = 0):
 
918
def digest_networks(conn, macs, bridges, networks, nics=0):
694
919
    macs     = listify(macs)
695
920
    bridges  = listify(bridges)
696
921
    networks = listify(networks)
713
938
    if len(macs) > len(networks):
714
939
        fail(_("Cannot pass more mac addresses than networks."))
715
940
    else:
716
 
        for dummy in range (len(macs),len(networks)):
 
941
        for dummy in range(len(macs), len(networks)):
717
942
            macs.append(None)
718
943
 
719
944
    # Create extra networks up to the number of nics requested
720
945
    if len(macs) < nics:
721
 
        for dummy in range(len(macs),nics):
 
946
        for dummy in range(len(macs), nics):
722
947
            if User.current().has_priv(User.PRIV_CREATE_NETWORK, conn.getURI()):
723
948
                net = _util.default_network(conn)
724
949
                networks.append(net[0] + ":" + net[1])
734
959
 
735
960
    return net_init_dicts
736
961
 
 
962
def sanitize_keymap(keymap):
 
963
    if not keymap:
 
964
        return None
 
965
 
 
966
    use_keymap = None
 
967
 
 
968
    if keymap.lower() == "local":
 
969
        use_keymap = virtinst.VirtualGraphics.KEYMAP_LOCAL
 
970
 
 
971
    elif keymap.lower() != "none":
 
972
        use_keymap = _util.check_keytable(keymap)
 
973
        if not use_keymap:
 
974
            raise ValueError(_("Didn't match keymap '%s' in keytable!") %
 
975
                             keymap)
 
976
 
 
977
    return use_keymap
 
978
 
 
979
def parse_graphics(guest, optstring, basedict):
 
980
    if optstring is None and not basedict:
 
981
        return None
 
982
 
 
983
    # Peel the model type off the front
 
984
    gtype, opts = parse_optstr(optstring, basedict, remove_first=True)
 
985
    if gtype == "none" or basedict.get("type") == "none":
 
986
        return None
 
987
    dev = VirtualGraphics(conn=guest.conn)
 
988
 
 
989
    def set_param(paramname, dictname, val=None):
 
990
        val = get_opt_param(opts, dictname, val)
 
991
        if val == None:
 
992
            return
 
993
 
 
994
        if paramname == "keymap":
 
995
            val = sanitize_keymap(val)
 
996
        setattr(dev, paramname, val)
 
997
 
 
998
    set_param("type", "type", gtype)
 
999
    set_param("port", "port")
 
1000
    set_param("tlsPort", "tlsport")
 
1001
    set_param("listen", "listen")
 
1002
    set_param("keymap", "keymap")
 
1003
    set_param("passwd", "password")
 
1004
    set_param("passwdValidTo", "passwordvalidto")
 
1005
 
 
1006
    if opts:
 
1007
        raise ValueError(_("Unknown options %s") % opts.keys())
 
1008
 
 
1009
    return dev
 
1010
 
737
1011
def get_graphics(vnc, vncport, vnclisten, nographics, sdl, keymap,
738
 
                 video_models, guest):
 
1012
                 video_models, graphics, guest):
739
1013
    video_models = video_models or []
740
1014
 
741
 
    if ((vnc and nographics) or
742
 
        (vnc and sdl) or
743
 
        (sdl and nographics)):
744
 
        raise ValueError, _("Can't specify more than one of VNC, SDL, "
745
 
                            "or --nographics")
746
 
 
747
 
    for model in video_models:
748
 
        dev = virtinst.VirtualVideoDevice(guest.conn)
749
 
        dev.model_type = model
750
 
        guest.add_device(dev)
751
 
 
752
 
    if not (vnc or nographics or sdl):
 
1015
    if graphics and (vnc or sdl or keymap or vncport or vnclisten):
 
1016
        fail(_("Cannot mix --graphics and old style graphical options"))
 
1017
 
 
1018
    # If not graphics specified, choose a default
 
1019
    if not (vnc or nographics or sdl or graphics):
753
1020
        if "DISPLAY" in os.environ.keys():
754
1021
            logging.debug("DISPLAY is set: graphics defaulting to VNC.")
755
1022
            vnc = True
757
1024
            logging.debug("DISPLAY is not set: defaulting to nographics.")
758
1025
            nographics = True
759
1026
 
760
 
    if nographics is not None:
761
 
        guest.graphics_dev = None
 
1027
    if (sum(map(int, map(bool, [vnc, nographics, sdl, graphics])))) > 1:
 
1028
        raise ValueError(_("Can't specify more than one of VNC, SDL, "
 
1029
                           "--graphics or --nographics"))
 
1030
 
 
1031
    # Build an initial graphics argument dict
 
1032
    basedict = {
 
1033
        "type"      : ((vnc and "vnc") or
 
1034
                       (sdl and "sdl") or
 
1035
                       (nographics and "none")),
 
1036
        "listen"    : vnclisten,
 
1037
        "port"      : vncport,
 
1038
        "keymap"    : keymap,
 
1039
    }
 
1040
 
 
1041
    try:
 
1042
        dev = parse_graphics(guest, graphics, basedict)
 
1043
    except Exception, e:
 
1044
        fail(_("Error in graphics device parameters: %s") % str(e))
 
1045
 
 
1046
    if not dev:
762
1047
        return
 
1048
    guest.graphics_dev = dev
763
1049
 
764
 
    # After this point, we are using graphics, so add a video device
765
 
    # if one wasn't passed
 
1050
    # At this point we are definitely using graphics, so setup a default
 
1051
    # video card if necc.
766
1052
    if not video_models:
767
 
        guest.add_device(VirtualVideoDevice(conn=guest.conn))
768
 
 
769
 
    if sdl is not None:
770
 
        guest.graphics_dev = VirtualGraphics(type=VirtualGraphics.TYPE_SDL)
771
 
        return
772
 
 
773
 
    if vnc is not None:
774
 
        guest.graphics_dev = VirtualGraphics(type=VirtualGraphics.TYPE_VNC)
775
 
        if vncport:
776
 
            guest.graphics_dev.port = vncport
777
 
        if vnclisten:
778
 
            guest.graphics_dev.listen = vnclisten
779
 
 
780
 
    if keymap:
781
 
        use_keymap = None
782
 
 
783
 
        if keymap.lower() == "local":
784
 
            use_keymap = virtinst.VirtualGraphics.KEYMAP_LOCAL
785
 
 
786
 
        elif keymap.lower() != "none":
787
 
            use_keymap = _util.check_keytable(keymap)
788
 
            if not use_keymap:
789
 
                raise ValueError(_("Didn't match keymap '%s' in keytable!") %
790
 
                                 keymap)
791
 
 
792
 
        guest.graphics_dev.keymap = use_keymap
 
1053
        video_models.append(None)
 
1054
    for model in video_models:
 
1055
        vdev = virtinst.VirtualVideoDevice(guest.conn)
 
1056
        if model:
 
1057
            vdev.model_type = model
 
1058
        guest.add_device(vdev)
793
1059
 
794
1060
def get_sound(old_sound_bool, sound_opts, guest):
795
1061
    if not sound_opts:
816
1082
### Option parsing
817
1083
def check_before_store(option, opt_str, value, parser):
818
1084
    if len(value) == 0:
819
 
        raise OptionValueError, _("%s option requires an argument") %opt_str
 
1085
        raise OptionValueError(_("%s option requires an argument") % opt_str)
820
1086
    setattr(parser.values, option.dest, value)
821
1087
 
822
1088
def check_before_append(option, opt_str, value, parser):
823
1089
    if len(value) == 0:
824
 
        raise OptionValueError, _("%s option requires an argument") %opt_str
 
1090
        raise OptionValueError(_("%s option requires an argument") % opt_str)
825
1091
    parser.values.ensure_value(option.dest, []).append(value)
826
1092
 
 
1093
def get_opt_param(opts, dictnames, val=None):
 
1094
    if type(dictnames) is not list:
 
1095
        dictnames = [dictnames]
 
1096
 
 
1097
    for key in dictnames:
 
1098
        if key in opts:
 
1099
            if val == None:
 
1100
                val = opts[key]
 
1101
            del(opts[key])
 
1102
 
 
1103
    return val
 
1104
 
 
1105
def partition(string, sep):
 
1106
    if not string:
 
1107
        return (None, None, None)
 
1108
 
 
1109
    if string.count(sep):
 
1110
        splitres = string.split(sep, 1)
 
1111
        ret = (splitres[0], sep, splitres[1])
 
1112
    else:
 
1113
        ret = (string, None, None)
 
1114
    return ret