~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/vnet/scripts/vn

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python2.4
 
2
#  -*- mode: python; -*-
 
3
#============================================================================
 
4
# Copyright (C) 2005, 2006 Mike Wray <mike.wray@hp.com>
 
5
#
 
6
# This library is free software; you can redistribute it and/or modify
 
7
# it under the terms of the GNU Lesser General Public License as published by
 
8
# the Free Software Foundation; either version 2.1 of the License, or
 
9
# (at your option) any later version.
 
10
#
 
11
# This library is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU Lesser General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU Lesser General Public License
 
17
# along with this library; if not, write to the Free Software
 
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
#============================================================================
 
20
 
 
21
# Vnet (network virtualization) control utility.
 
22
 
 
23
import os
 
24
import os.path
 
25
import re
 
26
import socket
 
27
import sys
 
28
from getopt import getopt, GetoptError
 
29
 
 
30
from xen.xend import sxp
 
31
from xen.xend.PrettyPrint import prettyprint
 
32
 
 
33
# Path of unix-domain socket to vnetd.
 
34
VNETD_PATH = "/tmp/vnetd"
 
35
 
 
36
def vnetd_running():
 
37
    return os.path.exists(VNETD_PATH)
 
38
 
 
39
def vnetd_open():
 
40
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
 
41
    sock.connect(VNETD_PATH)
 
42
    fi = sock.makefile('r', 0)
 
43
    fo = sock.makefile('w', 0)
 
44
    return (fi, fo)
 
45
 
 
46
os.defpath += ':/sbin:/usr/sbin:/usr/local/sbin'
 
47
CMD_IFCONFIG = 'ifconfig'
 
48
CMD_BRCTL    = 'brctl'
 
49
 
 
50
opts = None
 
51
 
 
52
class Opts:
 
53
 
 
54
    def __init__(self, **kwds):
 
55
        for (k, v) in kwds.items():
 
56
            setattr(self, k, v)
 
57
 
 
58
opts = Opts(verbose=False, dryrun=False)
 
59
 
 
60
def set_opts(val):
 
61
    global opts
 
62
    opts = val
 
63
    return opts
 
64
 
 
65
def cmd(prog, *args):
 
66
    """Execute command 'prog' with 'args', optionally printing the command.
 
67
    """
 
68
    global opts
 
69
    command = " ".join([ prog ] + map(str, args))
 
70
    if opts.verbose:
 
71
        print command
 
72
    if not opts.dryrun:
 
73
        os.system(command)
 
74
 
 
75
def vif_bridge_add(bridge, vif):
 
76
    """Add a network interface to a bridge.
 
77
    """
 
78
    cmd(CMD_BRCTL, 'addif', bridge, vif)
 
79
 
 
80
def vif_bridge_rem(bridge, vif):
 
81
    """Remove a network interface from a bridge.
 
82
    """
 
83
    cmd(CMD_BRCTL, 'delif', bridge, vif)
 
84
 
 
85
def bridge_create(bridge, **kwd):
 
86
    """Create a bridge.
 
87
    Defaults hello time to 0, forward delay to 0 and stp off.
 
88
    """
 
89
    cmd(CMD_BRCTL, 'addbr', bridge)
 
90
    if kwd.get('hello', None) is None:
 
91
        kwd['hello'] = 0
 
92
    if kwd.get('fd', None) is None:
 
93
        kwd['fd'] = 0
 
94
    if kwd.get('stp', None) is None:
 
95
        kwd['stp'] = 'off'
 
96
    bridge_set(bridge, **kwd)
 
97
    cmd(CMD_IFCONFIG, bridge, "up")
 
98
 
 
99
def bridge_set(bridge, hello=None, fd=None, stp=None):
 
100
    """Set bridge parameters.
 
101
    """
 
102
    if hello is not None:
 
103
        cmd(CMD_BRCTL, 'sethello', bridge, hello)
 
104
    if fd is not None:
 
105
        cmd(CMD_BRCTL, 'setfd', bridge, fd)
 
106
    if stp is not None:
 
107
        cmd(CMD_BRCTL, 'stp', bridge, stp)
 
108
 
 
109
def bridge_del(bridge):
 
110
    """Delete a bridge.
 
111
    """
 
112
    cmd(CMD_IFCONFIG, bridge, 'down')
 
113
    cmd(CMD_BRCTL, 'delbr', bridge)
 
114
 
 
115
class Bridge:
 
116
    # Network interfaces are at /sys/class/net/*.
 
117
    # A bridge interface has ./bridge dir, ./brif is dir of bridged interfaces
 
118
    # (symlinks to the brport dirs).
 
119
    # If an interface is bridged ./brport is bridged port info,
 
120
    # brport/bridge is a symlink to the bridge.
 
121
 
 
122
    INTERFACE_DIR = "/sys/class/net"
 
123
 
 
124
    def isBridge(klass, dev):
 
125
        """Test if a network interface is a bridge.
 
126
        """
 
127
        devdir = os.path.join(klass.INTERFACE_DIR, dev)
 
128
        brdir = os.path.join(devdir, "bridge")
 
129
        try:
 
130
            os.stat(brdir)
 
131
            return True
 
132
        except:
 
133
            return False
 
134
 
 
135
    isBridge = classmethod(isBridge)
 
136
 
 
137
    def getInterfaces(klass):
 
138
        """Get a list of the network interfaces.
 
139
        """
 
140
        try:
 
141
            v = os.listdir(klass.INTERFACE_DIR)
 
142
            v.sort()
 
143
            return v
 
144
        except:
 
145
            return []
 
146
 
 
147
    getInterfaces = classmethod(getInterfaces)
 
148
 
 
149
    def getInterfaceAddr(klass, intf):
 
150
        intfdir = os.path.join(klass.INTERFACE_DIR, intf)
 
151
        addrfile = os.path.join(intfdir, "address")
 
152
        try:
 
153
            f = file(addrfile, "rb")
 
154
        except Exception, ex:
 
155
            #print ex
 
156
            return None
 
157
        try:
 
158
            return f.readline().strip()
 
159
        finally:
 
160
            f.close()
 
161
 
 
162
    getInterfaceAddr = classmethod(getInterfaceAddr)
 
163
 
 
164
    def getBridges(klass):
 
165
        """Get a list of the bridges.
 
166
        """
 
167
        return [ dev for dev in klass.getInterfaces() if klass.isBridge(dev) ]
 
168
 
 
169
    getBridges = classmethod(getBridges)
 
170
 
 
171
    def getBridgeInterfaces(klass, dev):
 
172
        """Get a list of the interfaces attached to a bridge.
 
173
        """
 
174
        devdir = os.path.join(klass.INTERFACE_DIR, dev)
 
175
        intfdir = os.path.join(devdir, "brif")
 
176
        try:
 
177
            v = os.listdir(intfdir)
 
178
            v.sort()
 
179
            return v
 
180
        except:
 
181
            return []
 
182
 
 
183
    getBridgeInterfaces = classmethod(getBridgeInterfaces)
 
184
 
 
185
    def getBridge(klass, dev):
 
186
        """Get the bridge an interface is attached to (if any).
 
187
        """
 
188
        devdir = os.path.join(klass.INTERFACE_DIR, dev)
 
189
        brfile = os.path.join(devdir, "brport/bridge")
 
190
        try:
 
191
            brpath = os.readlink(brfile)
 
192
            return os.path.basename(brpath)
 
193
        except:
 
194
            return None
 
195
 
 
196
    getBridge = classmethod(getBridge)
 
197
 
 
198
def vnet_cmd(expr):
 
199
    """Send a command expression to the vnet implementation.
 
200
    """
 
201
    if vnetd_running():
 
202
        (fi, fo) = vnetd_open()
 
203
    else:
 
204
        fi = None
 
205
        fo = file("/proc/vnet/policy", "wb")
 
206
    try:
 
207
        sxp.show(expr, fo)
 
208
        fo.flush()
 
209
    finally:
 
210
        if fi: fi.close()
 
211
        if fo: fo.close()
 
212
 
 
213
def varp_flush():
 
214
    """Flush the varp cache.
 
215
    """
 
216
    expr = ['varp.flush']
 
217
    return vnet_cmd(expr)
 
218
 
 
219
def vif_add(vnetid, vmac):
 
220
    """Tell the vnet implementation to add a vif to a vnet.
 
221
    """
 
222
    expr = ['vif.add', ['vnet', vnetid], ['vmac', vmac]]
 
223
    return vnet_cmd(expr)
 
224
 
 
225
def vif_del(vnetid, vmac):
 
226
    """Tell the vnet implementation to delete a vif from a vnet.
 
227
    """
 
228
    expr = ['vif.del', ['vnet', vnetid], ['vmac', vmac]]
 
229
    return vnet_cmd(expr)
 
230
 
 
231
def vnet_add(vnetid, vnetif=None, security=None):
 
232
    """Tell the vnet implementation to add a vnet.
 
233
    """
 
234
    expr = ['vnet.add', ['id', vnetid]]
 
235
    if vnetif:
 
236
        expr.append(['vnetif', vnetif])
 
237
    if security:
 
238
        expr.append(['security', security])
 
239
    return vnet_cmd(expr)
 
240
 
 
241
def peer_add(addr, port=None):
 
242
    expr = ['peer.add', ['addr', addr]]
 
243
    if port:
 
244
        expr.append(['port', port])
 
245
    return vnet_cmd(expr)
 
246
    
 
247
def peer_del(addr, port=None):
 
248
    expr = ['peer.del', ['addr', addr]]
 
249
    return vnet_cmd(expr)
 
250
 
 
251
def vnet_del(vnetid):
 
252
    """Tell the vnet implementation to delete a vnet.
 
253
    """
 
254
    expr = ['vnet.del', ['id', vnetid]]
 
255
    return vnet_cmd(expr)
 
256
 
 
257
def vnet_create(vnetid, vnetif=None, bridge=None, security=None):
 
258
    """Tell the vnet implementation to add a vnet.
 
259
    If 'bridge' is non-null, create the bridge and add the vnet interface
 
260
    to it.
 
261
    """
 
262
    vnet_add(vnetid, vnetif=vnetif, security=security)
 
263
    val = vnet_lookup(vnetid)
 
264
    if not vnetif:
 
265
        vnetif = sxp.child_value(val, "vnetif")
 
266
    vmac = get_mac(vnetif)
 
267
    emac = get_mac("eth0") or get_mac("eth1") or get_mac("eth2")
 
268
    if emac and vmac != emac:
 
269
        set_mac(vnetif, emac)
 
270
    cmd(CMD_IFCONFIG, vnetif, 'up')
 
271
    if bridge:
 
272
        bridge_create(bridge)
 
273
        vif_bridge_add(bridge, vnetif)
 
274
    return val
 
275
        
 
276
def vnet_delete(vnet, delbridge=False):
 
277
    """Tell the vnet implementation to delete a vnet.
 
278
    If the vnet interface is attached to a bridge,
 
279
    remove it from the bridge, and if delbridge is true
 
280
    delete the bridge.
 
281
    """
 
282
    v = vnet_lookup(vnet)    
 
283
    if not v:
 
284
        raise GetoptError("vnet not found: %s" % vnet)
 
285
    vnetid = sxp.child_value(v, "id")
 
286
    vnetif = sxp.child_value(v, "vnetif")
 
287
    bridge = Bridge.getBridge(vnetif)
 
288
    if bridge:
 
289
        vif_bridge_rem(bridge, vnetif)
 
290
        if delbridge:
 
291
            bridge_del(bridge)
 
292
    return vnet_del(vnetid)
 
293
 
 
294
def get_mac(intf):
 
295
    """Get the mac address of an interface.
 
296
    """
 
297
    try:
 
298
        return Bridge.getInterfaceAddr(intf)
 
299
    except:
 
300
        pass
 
301
 
 
302
    hwre = re.compile(".*\s+HWaddr\s+(?P<mac>\S*)\s+.*")
 
303
    fin = os.popen("%s %s" % (CMD_IFCONFIG, intf), 'r')
 
304
    try:
 
305
        for x in fin:
 
306
            m = hwre.match(x)
 
307
            if not m:
 
308
                continue
 
309
            info = m.groupdict()
 
310
            return info['mac']
 
311
        return None
 
312
    finally:
 
313
        fin.close()
 
314
 
 
315
def set_mac(intf, mac):
 
316
    cmd(CMD_IFCONFIG, intf, 'down')
 
317
    cmd(CMD_IFCONFIG, intf, 'hw', 'ether', mac)
 
318
    cmd(CMD_IFCONFIG, intf, 'up')
 
319
 
 
320
def get_addr(host):
 
321
    return socket.gethostbyname(host)
 
322
 
 
323
def get_port(srv):
 
324
    return srv
 
325
 
 
326
def vnetidof(v):
 
327
    """Normalise a vnet id. Adds leading 0 fields to make up 8 if
 
328
    there aren't enough. Pads all fields to 4 hex digits.
 
329
    """
 
330
    try:
 
331
        l = v.split(":")
 
332
        l = [ int(x or 0, 16) for x in l ]
 
333
        l = [ 0 ] * (8 - len(l)) + l
 
334
        return ":".join([ "%04x" % x for x in l ])
 
335
    except:
 
336
        return None
 
337
 
 
338
def vnet_lookup(vnet, vnets=None):
 
339
    """Find the vnet with the given vnet id or vnet interface.
 
340
 
 
341
    @param vnet id or interface
 
342
    @param vnets list of vnet info to use (get from implementation if None)
 
343
    @return vnet info or None if not found
 
344
    """
 
345
    vnetid = vnetidof(vnet)
 
346
    if vnets is None:
 
347
        vnets = vnet_list()
 
348
    for v in vnets:
 
349
        vid = sxp.child_value(v, "id")
 
350
        if vid == vnet or vid == vnetid:
 
351
            return v
 
352
        if sxp.child_value(v, "vnetif") == vnet:
 
353
            return v
 
354
    return None
 
355
 
 
356
def get_vnetid(vnet):
 
357
    """Get the normalised vnet id of the given vnet id or vnet interface.
 
358
    Raises an error if the vnet cannot be found.
 
359
    """
 
360
    v = vnet_lookup(vnet)
 
361
    if not v:
 
362
        raise GetoptError("vnet not found: %s" % vnet)
 
363
    vnetid = sxp.child_value(v, "id")
 
364
    return vnetid
 
365
 
 
366
def vif_list():
 
367
    """Get the list of vif info from the vnet implementation.
 
368
    """
 
369
    if vnetd_running():
 
370
        (fi, fo) = vnetd_open()
 
371
        sxp.show(['vif.list'], fo)
 
372
        fo.flush()
 
373
    else:
 
374
        fi = file("/proc/vnet/vifs")
 
375
        fo = None
 
376
    try:
 
377
        return sxp.parse(fi) or []
 
378
    finally:
 
379
        if fi: fi.close()
 
380
        if fo: fo.close()
 
381
 
 
382
def vnets_filter(vnetlist, vnets):
 
383
    """Filter a list of vnet info by a list of vnet ids or interfaces.
 
384
    """
 
385
    if vnets is None:
 
386
        val = vnetlist
 
387
    else:
 
388
        val = []
 
389
        for x in vnets:
 
390
            v = vnet_lookup(x, vnets=vnetlist)
 
391
            if not v:
 
392
                continue
 
393
            val.append(v)
 
394
    return val
 
395
 
 
396
def vnet_list(vnets=None):
 
397
    """Get the list of vnet info from the vnet implementation,
 
398
    sorted by vnet id.
 
399
 
 
400
    @param vnets list of vnet ids or interfaces to filter the results by
 
401
    """
 
402
    if vnetd_running():
 
403
        (fi, fo) = vnetd_open()
 
404
        sxp.show(['vnet.list'], fo)
 
405
        fo.flush()
 
406
    else:
 
407
        fi = file("/proc/vnet/vnets")
 
408
        fo = None
 
409
    try:
 
410
        val = vnets_filter(sxp.parse(fi) or [], vnets)
 
411
        val.sort(lambda x, y:
 
412
                   cmp(sxp.child_value(x, "id"),
 
413
                       sxp.child_value(y, "id")))
 
414
        return val
 
415
    finally:
 
416
        if fi: fi.close()
 
417
        if fo: fo.close()
 
418
        
 
419
def vnif_list(vnets=None):
 
420
    """Get the list of vnet interface names from the vnet implementation.
 
421
 
 
422
    @param vnets list of vnet ids or interfaces to filter the results by
 
423
    """
 
424
    vnifs = []
 
425
    for v in vnet_list(vnets=vnets):
 
426
        vnetif = sxp.child_value(v, "vnetif")
 
427
        if vnetif:
 
428
            vnifs.append(vnetif)
 
429
    return vnifs
 
430
        
 
431
def varp_list():
 
432
    """Get the list of varp info from the vnet implementation.
 
433
    """
 
434
    if vnetd_running():
 
435
        (fi, fo) = vnetd_open()
 
436
        sxp.show(['varp.list'], fo)
 
437
        fo.flush()
 
438
    else:
 
439
        fi = file("/proc/vnet/varp")
 
440
        fo = None
 
441
    try:
 
442
        return sxp.parse(fi) or []
 
443
    finally:
 
444
        if fi: fi.close()
 
445
        if fo: fo.close()
 
446
 
 
447
def peer_list():
 
448
    if vnetd_running():
 
449
        (fi, fo) = vnetd_open()
 
450
        sxp.show(['peer.list'], fo)
 
451
        fo.flush()
 
452
    else:
 
453
        fi = file("/proc/vnet/peers")
 
454
        fo = None
 
455
    try:
 
456
        return sxp.parse(fi) or []
 
457
    finally:
 
458
        if fi: fi.close()
 
459
        if fo: fo.close()
 
460
 
 
461
class Opt:
 
462
    """Declares command-line options for a command.
 
463
    """
 
464
 
 
465
    def getopt(klass, argv, opts, args):
 
466
        """Get options and args from argv.
 
467
        The value opts in the return value has an attribute for
 
468
        eacho option or arg. The value args in the return value
 
469
        is the remaining arguments.
 
470
 
 
471
        @param argv arguments
 
472
        @param opts option specifiers (list of Opt objects)
 
473
        @param args arg specififiers (list of Arg objects)
 
474
        @return (opts, args)
 
475
        """
 
476
        shortopts = "".join([ x.optShort() for x in opts ])
 
477
        longopts  = [ x.optLong() for x in opts ]
 
478
        (ovals, oargs) = getopt(argv[1:], shortopts, longopts)
 
479
        odir = Opts()
 
480
        for x in opts:
 
481
            x.setDefault(odir)
 
482
        for (k, v) in ovals:
 
483
            for x in opts:
 
484
                x.setOpt(k, v, odir)
 
485
        argc = len(oargs)
 
486
        if len(oargs) < len(args):
 
487
            raise GetoptError("insufficient arguments for %s" % argv[0])
 
488
        for (x, v) in zip(args, oargs):
 
489
            x.setArg(v, odir)
 
490
        return (odir, oargs[len(args): ])
 
491
 
 
492
    getopt = classmethod(getopt)
 
493
 
 
494
    def gethelp(klass, opts, args):
 
495
        l = []
 
496
        for x in opts:
 
497
            l.append(x.help())
 
498
        for x in args:
 
499
            l.append(x.help())
 
500
        return " ".join(l)
 
501
 
 
502
    gethelp = classmethod(gethelp)
 
503
 
 
504
    """A command=-line option.
 
505
 
 
506
    @param name option name (this attribute is set to value in opts)
 
507
    @param short short option flag (single-character string)
 
508
    @param long long option name (defaults to option name, pass "" to suppress)
 
509
    @param arg argument name (option has no arg if not specified)
 
510
    """
 
511
    def __init__(self, name, short=None, long=None, arg=False):
 
512
        self.name = name
 
513
        self.short = short
 
514
        if long is None:
 
515
            long = name
 
516
        elif not long:
 
517
            long = None
 
518
        self.long = long
 
519
        self.arg = arg
 
520
 
 
521
    def help(self):
 
522
        s = self.keyShort()
 
523
        l = self.keyLong()
 
524
        if s and l:
 
525
            return "[%s | %s]" % (s, l)
 
526
        else:
 
527
            return s or l
 
528
 
 
529
    def keyShort(self):
 
530
        if self.short:
 
531
            return "-%s" % self.short
 
532
        else:
 
533
            return None
 
534
 
 
535
    def keyLong(self):
 
536
        if self.long:
 
537
            return "--%s" % self.long
 
538
        else:
 
539
            return None
 
540
 
 
541
    def optLong(self):
 
542
        if not self.long:
 
543
            return None
 
544
        if self.arg:
 
545
            return "%s=" % self.long
 
546
        else:
 
547
            return self.long
 
548
 
 
549
    def optShort(self):
 
550
        if not self.short:
 
551
            return None
 
552
        if self.arg:
 
553
            return "%s:" % self.short
 
554
        else:
 
555
            return self.short
 
556
 
 
557
    def setDefault(self, vals):
 
558
        if self.arg:
 
559
            setattr(vals, self.name, None)
 
560
        else:
 
561
            setattr(vals, self.name, False)
 
562
 
 
563
    def setOpt(self, k, v, vals):
 
564
        if k in [ self.keyShort(), self.keyLong() ]:
 
565
            if self.arg:
 
566
                setattr(vals, self.name, v)
 
567
            else:
 
568
                if v not in [ None, '' ]:
 
569
                    raise GetoptError("option %s does not take an argument" % k)
 
570
                setattr(vals, self.name, True)
 
571
 
 
572
class Arg:
 
573
 
 
574
    """A command-line parameter. Args get their values from arguments
 
575
    left over after option processing and are assigned in order.
 
576
    The value is accessible as the attribute called 'name' in opts.
 
577
 
 
578
    @param name argument name
 
579
    """
 
580
    def __init__(self, name):
 
581
        self.name = name
 
582
 
 
583
    def setArg(self, v, vals):
 
584
        setattr(vals, self.name, v)
 
585
 
 
586
    def help(self):
 
587
        return "<%s>" % self.name
 
588
            
 
589
class VnMain:
 
590
 
 
591
    """Methods beginning with this prefix are commands.
 
592
    They must all have arguments like this:
 
593
 
 
594
    op_foo(self, argv, args, opts)
 
595
 
 
596
    argv: original command-line arguments
 
597
    args: arguments left after option processing
 
598
    opts: option and arg values (accessible as attributes)
 
599
 
 
600
    Method options are specified by setting attribute
 
601
    .opts on the method to a list of Option objects.
 
602
    For args set .args to a list of Arg objects.
 
603
    Use .use for short usage string, .help for long help.
 
604
 
 
605
    Each option or arg defines an attribute in opts. For example
 
606
    an option with name 'foo' is accessible as 'opts.foo'.
 
607
    """
 
608
    opPrefix = "op_"
 
609
 
 
610
    def __init__(self, argv):
 
611
        if argv:
 
612
            self.name = argv[0]
 
613
        else:
 
614
            self.name = "vn"
 
615
        self.argv = argv
 
616
        self.argc = len(argv)
 
617
 
 
618
    def error(self, v):
 
619
        print >>sys.stderr, "%s: %s" % (self.name, v)
 
620
        sys.exit(1)
 
621
        
 
622
    def getFunction(self, opname):
 
623
        key = self.opPrefix + opname.replace("-", "_")
 
624
        fn = getattr(self, key, None)
 
625
        if not fn:
 
626
            raise ValueError("unknown command: %s" % opname)
 
627
        return fn
 
628
    
 
629
    def main(self):
 
630
        if self.argc < 2:
 
631
            args = ["help"]
 
632
        else:
 
633
            args = self.argv[1:]
 
634
        try:
 
635
            fn = self.getFunction(args[0])
 
636
        except ValueError, ex:
 
637
            self.error(ex)
 
638
        try:
 
639
            fnopts = self.getOpts(fn)
 
640
            fnargs = self.getArgs(fn)
 
641
            (opts, parms) = Opt.getopt(args, fnopts, fnargs)
 
642
            return fn(args, parms, opts)
 
643
        except GetoptError, ex:
 
644
            self.error(ex)
 
645
        except ValueError, ex:
 
646
            self.error(ex)
 
647
        except Exception, ex:
 
648
            import traceback; traceback.print_exc()
 
649
            self.error(ex)
 
650
 
 
651
    def getOpts(self, meth):
 
652
        return getattr(meth, "opts", [])
 
653
    
 
654
    def getArgs(self, meth):
 
655
        return getattr(meth, "args", [])
 
656
    
 
657
    def getUse(self, meth):
 
658
        return getattr(meth, "use", "")
 
659
    
 
660
    def getHelp(self, meth):
 
661
        return getattr(meth, "help", "") or self.getUse(meth)
 
662
 
 
663
    def fnHelp(self, meth):
 
664
        return Opt.gethelp(self.getOpts(meth), self.getArgs(meth))
 
665
 
 
666
    def printHelp(self, fn, opt_long):
 
667
        meth = getattr(self, fn)
 
668
        opname = fn[len(self.opPrefix):].replace("_", "-")
 
669
        if opt_long:
 
670
            help = self.getHelp(meth)
 
671
            print "\n  %s" % opname
 
672
            if help:
 
673
                print "%s" % help
 
674
        else:
 
675
            use = self.getUse(meth)
 
676
            print "  %s %s" % (opname, self.fnHelp(meth))
 
677
            if use:
 
678
                print "\t\t%s" % use
 
679
 
 
680
    def show_vnif(self, dev):
 
681
        cmd(CMD_IFCONFIG, dev)
 
682
        bridge = Bridge.getBridge(dev)
 
683
        if bridge:
 
684
            print "          Bridge:", bridge
 
685
            interfaces = Bridge.getBridgeInterfaces(bridge)
 
686
            if dev in interfaces:
 
687
                interfaces.remove(dev)
 
688
            if interfaces:
 
689
                print "          Interfaces:", ", ".join(interfaces)
 
690
            print
 
691
 
 
692
    def op_help(self, argv, args, opts):
 
693
        if opts.long:
 
694
            print '%s <command> <options>' % self.name
 
695
            print self.long_help
 
696
        else:
 
697
            print '%s:' % self.name
 
698
        l = dir(self)
 
699
        l.sort()
 
700
        for fn in l:
 
701
            if fn.startswith(self.opPrefix):
 
702
                self.printHelp(fn, opts.long)
 
703
        print
 
704
 
 
705
    op_help.opts = [ Opt('long', short='l') ]
 
706
 
 
707
    def op_vnets(self, argv, args, opts):
 
708
        vnets = vnet_list(vnets=args or None)
 
709
        for v in vnets:
 
710
            prettyprint(v, width=50)
 
711
            print
 
712
            if not opts.long:
 
713
                continue
 
714
            vnif = sxp.child_value(v, "vnetif")
 
715
            if not vnif:
 
716
                continue
 
717
            self.show_vnif(vnif)
 
718
        if opts.all:
 
719
            vnetids = {}
 
720
            for v in vnets:
 
721
                vnetids[sxp.child_value(v, "id")] = v
 
722
            for v in vif_list():
 
723
                vnet = sxp.child_value(v, "vnet")
 
724
                if vnet not in vnetids:
 
725
                    continue
 
726
                prettyprint(v)
 
727
                print
 
728
            for v in varp_list():
 
729
                prettyprint(v)
 
730
                print
 
731
 
 
732
    op_vnets.opts = [ Opt('all', short='a'), Opt('long', short='l') ]
 
733
 
 
734
    def op_vnifs(self, argv, args, opts):
 
735
        vnifs = vnif_list(vnets=args or None)
 
736
        for vnif in vnifs:
 
737
            self.show_vnif(vnif)
 
738
 
 
739
    def op_vifs(self, argv, args, opts):
 
740
        for v in vif_list():
 
741
            prettyprint(v)
 
742
            print
 
743
 
 
744
    def op_varp(self, argv, args, opts):
 
745
        for v in varp_list():
 
746
            prettyprint(v)
 
747
            print
 
748
 
 
749
    def op_varp_flush(self, argv, args, opts):
 
750
        varp_flush()
 
751
 
 
752
    def op_vnet_create(self, argv, args, opts):
 
753
        return vnet_create(opts.vnet,
 
754
                           vnetif=opts.vnetif,
 
755
                           bridge=opts.bridge,
 
756
                           security=opts.security)
 
757
 
 
758
    op_vnet_create.args = [ Arg('vnet') ]
 
759
    op_vnet_create.opts = [ Opt('security', short='s', arg="SECURITY"),
 
760
                            Opt('bridge', short='b', arg="BRIDGE"),
 
761
                            Opt('vnetif', short='v', arg="VNETIF") ]
 
762
 
 
763
    def op_vnet_delete(self, argv, args, opts):
 
764
        vnetid = get_vnetid(opts.vnet)
 
765
        return vnet_delete(vnetid, delbridge=opts.bridge)
 
766
 
 
767
    op_vnet_delete.args = [ Arg('vnet') ]
 
768
    op_vnet_delete.opts = [ Opt('bridge', short='b') ]
 
769
 
 
770
    def op_vif_add(self, argv, args, opts):
 
771
        vnetid = get_vnetid(opts.vnet)
 
772
        if opts.interface:
 
773
            vmac = get_mac(opts.vmac)
 
774
            if not vmac:
 
775
                raise ValueError("interface not found: %s" % opts.vmac)
 
776
        else:
 
777
            vmac = opts.vmac
 
778
        return vif_add(vnetid, vmac)
 
779
 
 
780
    op_vif_add.args = [ Arg('vnet'), Arg('vmac') ]
 
781
    op_vif_add.opts = [ Opt('interface', short='i') ]
 
782
 
 
783
    def op_vif_delete(self, argv, args, opts):
 
784
        vnetid = get_vnetid(opts.vnet)
 
785
        if opts.interface:
 
786
            vmac = get_mac(opts.vmac)
 
787
        else:
 
788
            vmac = opts.vmac
 
789
        return vif_del(vnetid, vmac)
 
790
 
 
791
    op_vif_delete.args = [ Arg('vnet'), Arg('vmac') ]
 
792
    op_vif_delete.opts = [ Opt('interface', short='i') ]
 
793
 
 
794
    def op_peer_add(self, argv, args, opts):
 
795
        addr = get_addr(opts.addr)
 
796
        if(opts.port):
 
797
            port = get_port(opts.port)
 
798
        else:
 
799
            port = None
 
800
        return peer_add(addr, port)
 
801
        
 
802
    op_peer_add.args = [ Arg('addr') ]
 
803
    op_peer_add.opts = [ Opt('port', short='p') ]
 
804
    
 
805
    def op_peer_delete(self, argv, args, opts):
 
806
        addr = get_addr(opts.addr)
 
807
        return peer_del(addr)
 
808
 
 
809
    op_peer_delete.args = [ Arg('addr') ]
 
810
    
 
811
    def op_peers(self, argv, args, opts):
 
812
        for v in peer_list():
 
813
            prettyprint(v)
 
814
            print
 
815
 
 
816
    def op_bridges(self, argv, args, opts):
 
817
        if opts.long:
 
818
            for bridge in Bridge.getBridges():
 
819
                cmd(CMD_IFCONFIG, bridge)
 
820
                interfaces = Bridge.getBridgeInterfaces(bridge)
 
821
                if interfaces:
 
822
                    print "          Interfaces:", ", ".join(interfaces)
 
823
                    print
 
824
        else:
 
825
            for bridge in Bridge.getBridges():
 
826
                print bridge,
 
827
                interfaces = Bridge.getBridgeInterfaces(bridge)
 
828
                if interfaces:
 
829
                    print ":", ", ".join(interfaces)
 
830
                else:
 
831
                    print
 
832
            
 
833
    op_bridges.opts = [ Opt('long', short='l') ]
 
834
 
 
835
    def op_insmod(self, argv, args, opts):
 
836
        """Insert the vnet kernel module."""
 
837
        cmd("/etc/xen/scripts/vnet-insert", *args)
 
838
 
 
839
    long_help          = """Control utility for vnets (virtual networking).
 
840
Report bugs to Mike Wray <mike.wray@hp.com>.
 
841
"""
 
842
 
 
843
    op_help.use        = "Print help."
 
844
    op_help.help       = "Print help, long help if the option -l or --long is given."
 
845
 
 
846
    op_vnets.use       = """Print vnets."""
 
847
    op_vnets.help      = """Print vnet information, where options are:
 
848
    -a, -all           Print vnets, vifs and varp info.
 
849
    -l, --long         Print ifconfigs for vnet interfaces."""
 
850
 
 
851
    op_vifs.use        = "Print vifs."
 
852
 
 
853
    op_vnifs.use       = "Print ifconfigs for vnet network interfaces."
 
854
 
 
855
    op_varp.use        = "Print varp info and entries in the varp cache."
 
856
 
 
857
    op_varp_flush.use  = "Flush the varp cache."
 
858
    
 
859
    op_vnet_create.use = "Create a vnet."
 
860
 
 
861
    op_vnet_delete.use = "Delete a vnet."
 
862
    op_vnet_delete.help = """Delete a vnet.
 
863
    -b, --bridge       Delete the bridge the vnet interface is attached to.
 
864
    """
 
865
 
 
866
    op_vif_add.use     = "Add a vif to a vnet."
 
867
    op_vif_add.help    = """Add a vif to a vnet. Not usually needed as vifs
 
868
are added automatically.
 
869
    -i, --interface    The vmac is the name of an interface to get the mac from."""
 
870
 
 
871
    op_vif_delete.use  = "Delete a vif from a vnet."
 
872
    op_vif_delete.help = """Delete a vif from a vnet. Not usually needed as vifs
 
873
are removed periodically.
 
874
    -i, --interface    The vmac is the name of an interface to get the mac from."""
 
875
 
 
876
    op_peer_add.use    = "Add a peer."
 
877
    op_peer_add.help   = """Add a peer: <addr> <port>
 
878
Vnets use multicast to discover interfaces, but networks are often configured
 
879
not to forward multicast. Vnets forward multicasts to peers using UDP.
 
880
Only add peers if multicasts are not working, check with
 
881
 
 
882
ping -b 224.10.0.1
 
883
 
 
884
Only add peers at one machine in a subnet, otherwise you may cause forwarding
 
885
loops.
 
886
"""
 
887
 
 
888
    op_peer_delete.use = "Delete a peer."
 
889
    op_peer_delete.help= "Delete a peer: <addr>"
 
890
 
 
891
    op_peers.use       = "List peers."
 
892
    op_peers.help      = "List peers."
 
893
 
 
894
    op_bridges.use     = "Print bridges."
 
895
 
 
896
    op_insmod.use      = "Insert the vnet kernel module, optionally with parameters."
 
897
 
 
898
if __name__ == "__main__":
 
899
    vn = VnMain(sys.argv)
 
900
    vn.main()
 
901