~cerberus/nova/nova_notifications

« back to all changes in this revision

Viewing changes to nova/network/linux_net.py

  • Committer: Cerberus
  • Date: 2011-05-18 17:47:16 UTC
  • mfrom: (754.1.331 nova)
  • Revision ID: matt.dietz@rackspace.com-20110518174716-vicvbkk4t1insa9e
MergeĀ fromĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
16
#    License for the specific language governing permissions and limitations
17
17
#    under the License.
18
 
"""
19
 
Implements vlans, bridges, and iptables rules using linux utilities.
20
 
"""
21
 
 
 
18
 
 
19
"""Implements vlans, bridges, and iptables rules using linux utilities."""
 
20
 
 
21
import calendar
22
22
import inspect
23
23
import os
24
 
import calendar
25
24
 
26
25
from nova import db
27
26
from nova import exception
29
28
from nova import log as logging
30
29
from nova import utils
31
30
 
 
31
 
32
32
LOG = logging.getLogger("nova.linux_net")
33
33
 
34
34
 
35
35
def _bin_file(script):
36
 
    """Return the absolute path to scipt in the bin directory"""
37
 
    return os.path.abspath(os.path.join(__file__, "../../../bin", script))
 
36
    """Return the absolute path to scipt in the bin directory."""
 
37
    return os.path.abspath(os.path.join(__file__, '../../../bin', script))
38
38
 
39
39
 
40
40
FLAGS = flags.FLAGS
66
66
 
67
67
 
68
68
class IptablesRule(object):
69
 
    """An iptables rule
 
69
    """An iptables rule.
70
70
 
71
71
    You shouldn't need to use this class directly, it's only used by
72
 
    IptablesManager
 
72
    IptablesManager.
 
73
 
73
74
    """
 
75
 
74
76
    def __init__(self, chain, rule, wrap=True, top=False):
75
77
        self.chain = chain
76
78
        self.rule = rule
95
97
 
96
98
 
97
99
class IptablesTable(object):
98
 
    """An iptables table"""
 
100
    """An iptables table."""
99
101
 
100
102
    def __init__(self):
101
103
        self.rules = []
103
105
        self.unwrapped_chains = set()
104
106
 
105
107
    def add_chain(self, name, wrap=True):
106
 
        """Adds a named chain to the table
 
108
        """Adds a named chain to the table.
107
109
 
108
110
        The chain name is wrapped to be unique for the component creating
109
111
        it, so different components of Nova can safely create identically
110
112
        named chains without interfering with one another.
111
113
 
112
114
        At the moment, its wrapped name is <binary name>-<chain name>,
113
 
        so if nova-compute creates a chain named "OUTPUT", it'll actually
114
 
        end up named "nova-compute-OUTPUT".
 
115
        so if nova-compute creates a chain named 'OUTPUT', it'll actually
 
116
        end up named 'nova-compute-OUTPUT'.
 
117
 
115
118
        """
116
119
        if wrap:
117
120
            self.chains.add(name)
119
122
            self.unwrapped_chains.add(name)
120
123
 
121
124
    def remove_chain(self, name, wrap=True):
122
 
        """Remove named chain
 
125
        """Remove named chain.
123
126
 
124
127
        This removal "cascades". All rule in the chain are removed, as are
125
128
        all rules in other chains that jump to it.
126
129
 
127
130
        If the chain is not found, this is merely logged.
 
131
 
128
132
        """
129
133
        if wrap:
130
134
            chain_set = self.chains
132
136
            chain_set = self.unwrapped_chains
133
137
 
134
138
        if name not in chain_set:
135
 
            LOG.debug(_("Attempted to remove chain %s which doesn't exist"),
 
139
            LOG.debug(_('Attempted to remove chain %s which does not exist'),
136
140
                      name)
137
141
            return
138
142
 
147
151
        self.rules = filter(lambda r: jump_snippet not in r.rule, self.rules)
148
152
 
149
153
    def add_rule(self, chain, rule, wrap=True, top=False):
150
 
        """Add a rule to the table
 
154
        """Add a rule to the table.
151
155
 
152
156
        This is just like what you'd feed to iptables, just without
153
 
        the "-A <chain name>" bit at the start.
 
157
        the '-A <chain name>' bit at the start.
154
158
 
155
159
        However, if you need to jump to one of your wrapped chains,
156
160
        prepend its name with a '$' which will ensure the wrapping
157
161
        is applied correctly.
 
162
 
158
163
        """
159
164
        if wrap and chain not in self.chains:
160
 
            raise ValueError(_("Unknown chain: %r") % chain)
 
165
            raise ValueError(_('Unknown chain: %r') % chain)
161
166
 
162
167
        if '$' in rule:
163
168
            rule = ' '.join(map(self._wrap_target_chain, rule.split(' ')))
170
175
        return s
171
176
 
172
177
    def remove_rule(self, chain, rule, wrap=True, top=False):
173
 
        """Remove a rule from a chain
 
178
        """Remove a rule from a chain.
174
179
 
175
180
        Note: The rule must be exactly identical to the one that was added.
176
181
        You cannot switch arguments around like you can with the iptables
177
182
        CLI tool.
 
183
 
178
184
        """
179
185
        try:
180
186
            self.rules.remove(IptablesRule(chain, rule, wrap, top))
181
187
        except ValueError:
182
 
            LOG.debug(_("Tried to remove rule that wasn't there:"
183
 
                        " %(chain)r %(rule)r %(wrap)r %(top)r"),
 
188
            LOG.debug(_('Tried to remove rule that was not there:'
 
189
                        ' %(chain)r %(rule)r %(wrap)r %(top)r'),
184
190
                      {'chain': chain, 'rule': rule,
185
191
                       'top': top, 'wrap': wrap})
186
192
 
187
193
 
188
194
class IptablesManager(object):
189
 
    """Wrapper for iptables
 
195
    """Wrapper for iptables.
190
196
 
191
197
    See IptablesTable for some usage docs
192
198
 
205
211
    For ipv4, the builtin PREROUTING, OUTPUT, and POSTROUTING nat chains are
206
212
    wrapped in the same was as the builtin filter chains. Additionally, there's
207
213
    a snat chain that is applied after the POSTROUTING chain.
 
214
 
208
215
    """
 
216
 
209
217
    def __init__(self, execute=None):
210
218
        if not execute:
211
219
            self.execute = _execute
267
275
 
268
276
    @utils.synchronized('iptables', external=True)
269
277
    def apply(self):
270
 
        """Apply the current in-memory set of iptables rules
 
278
        """Apply the current in-memory set of iptables rules.
271
279
 
272
280
        This will blow away any rules left over from previous runs of the
273
281
        same component of Nova, and replace them with our current set of
274
282
        rules. This happens atomically, thanks to iptables-restore.
 
283
 
275
284
        """
276
285
        s = [('iptables', self.ipv4)]
277
286
        if FLAGS.use_ipv6:
348
357
 
349
358
 
350
359
def metadata_forward():
351
 
    """Create forwarding rule for metadata"""
352
 
    iptables_manager.ipv4['nat'].add_rule("PREROUTING",
353
 
                                          "-s 0.0.0.0/0 -d 169.254.169.254/32 "
354
 
                                          "-p tcp -m tcp --dport 80 -j DNAT "
355
 
                                          "--to-destination %s:%s" % \
 
360
    """Create forwarding rule for metadata."""
 
361
    iptables_manager.ipv4['nat'].add_rule('PREROUTING',
 
362
                                          '-s 0.0.0.0/0 -d 169.254.169.254/32 '
 
363
                                          '-p tcp -m tcp --dport 80 -j DNAT '
 
364
                                          '--to-destination %s:%s' % \
356
365
                                          (FLAGS.ec2_dmz_host, FLAGS.ec2_port))
357
366
    iptables_manager.apply()
358
367
 
359
368
 
360
369
def init_host():
361
 
    """Basic networking setup goes here"""
 
370
    """Basic networking setup goes here."""
362
371
    # NOTE(devcamcar): Cloud public SNAT entries and the default
363
372
    # SNAT rule for outbound traffic.
364
 
    iptables_manager.ipv4['nat'].add_rule("snat",
365
 
                                          "-s %s -j SNAT --to-source %s" % \
 
373
    iptables_manager.ipv4['nat'].add_rule('snat',
 
374
                                          '-s %s -j SNAT --to-source %s' % \
366
375
                                           (FLAGS.fixed_range,
367
376
                                            FLAGS.routing_source_ip))
368
377
 
369
 
    iptables_manager.ipv4['nat'].add_rule("POSTROUTING",
370
 
                                          "-s %s -d %s -j ACCEPT" % \
 
378
    iptables_manager.ipv4['nat'].add_rule('POSTROUTING',
 
379
                                          '-s %s -d %s -j ACCEPT' % \
371
380
                                          (FLAGS.fixed_range, FLAGS.dmz_cidr))
372
381
 
373
 
    iptables_manager.ipv4['nat'].add_rule("POSTROUTING",
374
 
                                          "-s %(range)s -d %(range)s "
375
 
                                          "-j ACCEPT" % \
 
382
    iptables_manager.ipv4['nat'].add_rule('POSTROUTING',
 
383
                                          '-s %(range)s -d %(range)s '
 
384
                                          '-j ACCEPT' % \
376
385
                                          {'range': FLAGS.fixed_range})
377
386
    iptables_manager.apply()
378
387
 
379
388
 
380
389
def bind_floating_ip(floating_ip, check_exit_code=True):
381
 
    """Bind ip to public interface"""
 
390
    """Bind ip to public interface."""
382
391
    _execute('sudo', 'ip', 'addr', 'add', floating_ip,
383
392
             'dev', FLAGS.public_interface,
384
393
             check_exit_code=check_exit_code)
385
394
 
386
395
 
387
396
def unbind_floating_ip(floating_ip):
388
 
    """Unbind a public ip from public interface"""
 
397
    """Unbind a public ip from public interface."""
389
398
    _execute('sudo', 'ip', 'addr', 'del', floating_ip,
390
399
             'dev', FLAGS.public_interface)
391
400
 
392
401
 
393
402
def ensure_metadata_ip():
394
 
    """Sets up local metadata ip"""
 
403
    """Sets up local metadata ip."""
395
404
    _execute('sudo', 'ip', 'addr', 'add', '169.254.169.254/32',
396
405
             'scope', 'link', 'dev', 'lo', check_exit_code=False)
397
406
 
398
407
 
399
408
def ensure_vlan_forward(public_ip, port, private_ip):
400
 
    """Sets up forwarding rules for vlan"""
401
 
    iptables_manager.ipv4['filter'].add_rule("FORWARD",
402
 
                                             "-d %s -p udp "
403
 
                                             "--dport 1194 "
404
 
                                             "-j ACCEPT" % private_ip)
405
 
    iptables_manager.ipv4['nat'].add_rule("PREROUTING",
406
 
                                          "-d %s -p udp "
407
 
                                          "--dport %s -j DNAT --to %s:1194" %
 
409
    """Sets up forwarding rules for vlan."""
 
410
    iptables_manager.ipv4['filter'].add_rule('FORWARD',
 
411
                                             '-d %s -p udp '
 
412
                                             '--dport 1194 '
 
413
                                             '-j ACCEPT' % private_ip)
 
414
    iptables_manager.ipv4['nat'].add_rule('PREROUTING',
 
415
                                          '-d %s -p udp '
 
416
                                          '--dport %s -j DNAT --to %s:1194' %
408
417
                                          (public_ip, port, private_ip))
409
418
    iptables_manager.ipv4['nat'].add_rule("OUTPUT",
410
419
                                          "-d %s -p udp "
414
423
 
415
424
 
416
425
def ensure_floating_forward(floating_ip, fixed_ip):
417
 
    """Ensure floating ip forwarding rule"""
 
426
    """Ensure floating ip forwarding rule."""
418
427
    for chain, rule in floating_forward_rules(floating_ip, fixed_ip):
419
428
        iptables_manager.ipv4['nat'].add_rule(chain, rule)
420
429
    iptables_manager.apply()
421
430
 
422
431
 
423
432
def remove_floating_forward(floating_ip, fixed_ip):
424
 
    """Remove forwarding for floating ip"""
 
433
    """Remove forwarding for floating ip."""
425
434
    for chain, rule in floating_forward_rules(floating_ip, fixed_ip):
426
435
        iptables_manager.ipv4['nat'].remove_rule(chain, rule)
427
436
    iptables_manager.apply()
428
437
 
429
438
 
430
439
def floating_forward_rules(floating_ip, fixed_ip):
431
 
    return [("PREROUTING", "-d %s -j DNAT --to %s" % (floating_ip, fixed_ip)),
432
 
            ("OUTPUT", "-d %s -j DNAT --to %s" % (floating_ip, fixed_ip)),
433
 
            ("floating-snat",
434
 
             "-s %s -j SNAT --to %s" % (fixed_ip, floating_ip))]
 
440
    return [('PREROUTING', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip)),
 
441
            ('OUTPUT', '-d %s -j DNAT --to %s' % (floating_ip, fixed_ip)),
 
442
            ('floating-snat',
 
443
             '-s %s -j SNAT --to %s' % (fixed_ip, floating_ip))]
435
444
 
436
445
 
437
446
def ensure_vlan_bridge(vlan_num, bridge, net_attrs=None):
438
 
    """Create a vlan and bridge unless they already exist"""
 
447
    """Create a vlan and bridge unless they already exist."""
439
448
    interface = ensure_vlan(vlan_num)
440
449
    ensure_bridge(bridge, interface, net_attrs)
441
450
 
442
451
 
443
452
def ensure_vlan(vlan_num):
444
 
    """Create a vlan unless it already exists"""
445
 
    interface = "vlan%s" % vlan_num
 
453
    """Create a vlan unless it already exists."""
 
454
    interface = 'vlan%s' % vlan_num
446
455
    if not _device_exists(interface):
447
 
        LOG.debug(_("Starting VLAN inteface %s"), interface)
 
456
        LOG.debug(_('Starting VLAN inteface %s'), interface)
448
457
        _execute('sudo', 'vconfig', 'set_name_type', 'VLAN_PLUS_VID_NO_PAD')
449
458
        _execute('sudo', 'vconfig', 'add', FLAGS.vlan_interface, vlan_num)
450
459
        _execute('sudo', 'ip', 'link', 'set', interface, 'up')
464
473
 
465
474
    The code will attempt to move any ips that already exist on the interface
466
475
    onto the bridge and reset the default gateway if necessary.
 
476
 
467
477
    """
468
478
    if not _device_exists(bridge):
469
 
        LOG.debug(_("Starting Bridge interface for %s"), interface)
 
479
        LOG.debug(_('Starting Bridge interface for %s'), interface)
470
480
        _execute('sudo', 'brctl', 'addbr', bridge)
471
481
        _execute('sudo', 'brctl', 'setfd', bridge, 0)
472
 
        # _execute("sudo brctl setageing %s 10" % bridge)
 
482
        # _execute('sudo brctl setageing %s 10' % bridge)
473
483
        _execute('sudo', 'brctl', 'stp', bridge, 'off')
474
484
        _execute('sudo', 'ip', 'link', 'set', bridge, 'up')
475
485
    if net_attrs:
477
487
        #             bridge for it to respond to reqests properly
478
488
        suffix = net_attrs['cidr'].rpartition('/')[2]
479
489
        out, err = _execute('sudo', 'ip', 'addr', 'add',
480
 
                            "%s/%s" %
 
490
                            '%s/%s' %
481
491
                            (net_attrs['gateway'], suffix),
482
492
                            'brd',
483
493
                            net_attrs['broadcast'],
484
494
                            'dev',
485
495
                            bridge,
486
496
                            check_exit_code=False)
487
 
        if err and err != "RTNETLINK answers: File exists\n":
488
 
            raise exception.Error("Failed to add ip: %s" % err)
 
497
        if err and err != 'RTNETLINK answers: File exists\n':
 
498
            raise exception.Error('Failed to add ip: %s' % err)
489
499
        if(FLAGS.use_ipv6):
490
500
            _execute('sudo', 'ip', '-f', 'inet6', 'addr',
491
501
                     'change', net_attrs['cidr_v6'],
501
511
        #             interface, so we move any ips to the bridge
502
512
        gateway = None
503
513
        out, err = _execute('sudo', 'route', '-n')
504
 
        for line in out.split("\n"):
 
514
        for line in out.split('\n'):
505
515
            fields = line.split()
506
 
            if fields and fields[0] == "0.0.0.0" and fields[-1] == interface:
 
516
            if fields and fields[0] == '0.0.0.0' and fields[-1] == interface:
507
517
                gateway = fields[1]
508
518
                _execute('sudo', 'route', 'del', 'default', 'gw', gateway,
509
519
                         'dev', interface, check_exit_code=False)
510
520
        out, err = _execute('sudo', 'ip', 'addr', 'show', 'dev', interface,
511
521
                            'scope', 'global')
512
 
        for line in out.split("\n"):
 
522
        for line in out.split('\n'):
513
523
            fields = line.split()
514
 
            if fields and fields[0] == "inet":
 
524
            if fields and fields[0] == 'inet':
515
525
                params = fields[1:-1]
516
526
                _execute(*_ip_bridge_cmd('del', params, fields[-1]))
517
527
                _execute(*_ip_bridge_cmd('add', params, bridge))
522
532
 
523
533
        if (err and err != "device %s is already a member of a bridge; can't "
524
534
                           "enslave it to bridge %s.\n" % (interface, bridge)):
525
 
            raise exception.Error("Failed to add interface: %s" % err)
 
535
            raise exception.Error('Failed to add interface: %s' % err)
526
536
 
527
 
    iptables_manager.ipv4['filter'].add_rule("FORWARD",
528
 
                                             "--in-interface %s -j ACCEPT" % \
 
537
    iptables_manager.ipv4['filter'].add_rule('FORWARD',
 
538
                                             '--in-interface %s -j ACCEPT' % \
529
539
                                             bridge)
530
 
    iptables_manager.ipv4['filter'].add_rule("FORWARD",
531
 
                                             "--out-interface %s -j ACCEPT" % \
 
540
    iptables_manager.ipv4['filter'].add_rule('FORWARD',
 
541
                                             '--out-interface %s -j ACCEPT' % \
532
542
                                             bridge)
533
543
 
534
544
 
535
545
def get_dhcp_leases(context, network_id):
536
 
    """Return a network's hosts config in dnsmasq leasefile format"""
 
546
    """Return a network's hosts config in dnsmasq leasefile format."""
537
547
    hosts = []
538
548
    for fixed_ip_ref in db.network_get_associated_fixed_ips(context,
539
549
                                                            network_id):
542
552
 
543
553
 
544
554
def get_dhcp_hosts(context, network_id):
545
 
    """Get a string containing a network's hosts config in dhcp-host format"""
 
555
    """Get network's hosts config in dhcp-host format."""
546
556
    hosts = []
547
557
    for fixed_ip_ref in db.network_get_associated_fixed_ips(context,
548
558
                                                            network_id):
555
565
#           aren't reloaded.
556
566
@utils.synchronized('dnsmasq_start')
557
567
def update_dhcp(context, network_id):
558
 
    """(Re)starts a dnsmasq server for a given network
559
 
 
560
 
    if a dnsmasq instance is already running then send a HUP
561
 
    signal causing it to reload, otherwise spawn a new instance
 
568
    """(Re)starts a dnsmasq server for a given network.
 
569
 
 
570
    If a dnsmasq instance is already running then send a HUP
 
571
    signal causing it to reload, otherwise spawn a new instance.
 
572
 
562
573
    """
563
574
    network_ref = db.network_get(context, network_id)
564
575
 
573
584
 
574
585
    # if dnsmasq is already running, then tell it to reload
575
586
    if pid:
576
 
        out, _err = _execute('cat', "/proc/%d/cmdline" % pid,
 
587
        out, _err = _execute('cat', '/proc/%d/cmdline' % pid,
577
588
                             check_exit_code=False)
578
589
        if conffile in out:
579
590
            try:
580
591
                _execute('sudo', 'kill', '-HUP', pid)
581
592
                return
582
593
            except Exception as exc:  # pylint: disable=W0703
583
 
                LOG.debug(_("Hupping dnsmasq threw %s"), exc)
 
594
                LOG.debug(_('Hupping dnsmasq threw %s'), exc)
584
595
        else:
585
 
            LOG.debug(_("Pid %d is stale, relaunching dnsmasq"), pid)
 
596
            LOG.debug(_('Pid %d is stale, relaunching dnsmasq'), pid)
586
597
 
587
598
    # FLAGFILE and DNSMASQ_INTERFACE in env
588
599
    env = {'FLAGFILE': FLAGS.dhcpbridge_flagfile,
625
636
            try:
626
637
                _execute('sudo', 'kill', pid)
627
638
            except Exception as exc:  # pylint: disable=W0703
628
 
                LOG.debug(_("killing radvd threw %s"), exc)
 
639
                LOG.debug(_('killing radvd threw %s'), exc)
629
640
        else:
630
 
            LOG.debug(_("Pid %d is stale, relaunching radvd"), pid)
 
641
            LOG.debug(_('Pid %d is stale, relaunching radvd'), pid)
631
642
    command = _ra_cmd(network_ref)
632
643
    _execute(*command)
633
644
    db.network_update(context, network_id,
634
 
                      {"gateway_v6":
 
645
                      {'gateway_v6':
635
646
                       utils.get_my_linklocal(network_ref['bridge'])})
636
647
 
637
648
 
638
649
def _host_lease(fixed_ip_ref):
639
 
    """Return a host string for an address in leasefile format"""
 
650
    """Return a host string for an address in leasefile format."""
640
651
    instance_ref = fixed_ip_ref['instance']
641
652
    if instance_ref['updated_at']:
642
653
        timestamp = instance_ref['updated_at']
645
656
 
646
657
    seconds_since_epoch = calendar.timegm(timestamp.utctimetuple())
647
658
 
648
 
    return "%d %s %s %s *" % (seconds_since_epoch + FLAGS.dhcp_lease_time,
 
659
    return '%d %s %s %s *' % (seconds_since_epoch + FLAGS.dhcp_lease_time,
649
660
                              instance_ref['mac_address'],
650
661
                              fixed_ip_ref['address'],
651
662
                              instance_ref['hostname'] or '*')
652
663
 
653
664
 
654
665
def _host_dhcp(fixed_ip_ref):
655
 
    """Return a host string for an address in dhcp-host format"""
 
666
    """Return a host string for an address in dhcp-host format."""
656
667
    instance_ref = fixed_ip_ref['instance']
657
 
    return "%s,%s.%s,%s" % (instance_ref['mac_address'],
 
668
    return '%s,%s.%s,%s' % (instance_ref['mac_address'],
658
669
                                   instance_ref['hostname'],
659
670
                                   FLAGS.dhcp_domain,
660
671
                                   fixed_ip_ref['address'])
661
672
 
662
673
 
663
674
def _execute(*cmd, **kwargs):
664
 
    """Wrapper around utils._execute for fake_network"""
 
675
    """Wrapper around utils._execute for fake_network."""
665
676
    if FLAGS.fake_network:
666
 
        LOG.debug("FAKE NET: %s", " ".join(map(str, cmd)))
667
 
        return "fake", 0
 
677
        LOG.debug('FAKE NET: %s', ' '.join(map(str, cmd)))
 
678
        return 'fake', 0
668
679
    else:
669
680
        return utils.execute(*cmd, **kwargs)
670
681
 
671
682
 
672
683
def _device_exists(device):
673
 
    """Check if ethernet device exists"""
 
684
    """Check if ethernet device exists."""
674
685
    (_out, err) = _execute('ip', 'link', 'show', 'dev', device,
675
686
                           check_exit_code=False)
676
687
    return not err
677
688
 
678
689
 
679
690
def _dnsmasq_cmd(net):
680
 
    """Builds dnsmasq command"""
 
691
    """Builds dnsmasq command."""
681
692
    cmd = ['sudo', '-E', 'dnsmasq',
682
693
           '--strict-order',
683
694
           '--bind-interfaces',
696
707
 
697
708
 
698
709
def _ra_cmd(net):
699
 
    """Builds radvd command"""
 
710
    """Builds radvd command."""
700
711
    cmd = ['sudo', '-E', 'radvd',
701
712
#           '-u', 'nobody',
702
713
           '-C', '%s' % _ra_file(net['bridge'], 'conf'),
705
716
 
706
717
 
707
718
def _stop_dnsmasq(network):
708
 
    """Stops the dnsmasq instance for a given network"""
 
719
    """Stops the dnsmasq instance for a given network."""
709
720
    pid = _dnsmasq_pid_for(network)
710
721
 
711
722
    if pid:
712
723
        try:
713
724
            _execute('sudo', 'kill', '-TERM', pid)
714
725
        except Exception as exc:  # pylint: disable=W0703
715
 
            LOG.debug(_("Killing dnsmasq threw %s"), exc)
 
726
            LOG.debug(_('Killing dnsmasq threw %s'), exc)
716
727
 
717
728
 
718
729
def _dhcp_file(bridge, kind):
719
 
    """Return path to a pid, leases or conf file for a bridge"""
720
 
 
 
730
    """Return path to a pid, leases or conf file for a bridge."""
721
731
    if not os.path.exists(FLAGS.networks_path):
722
732
        os.makedirs(FLAGS.networks_path)
723
 
    return os.path.abspath("%s/nova-%s.%s" % (FLAGS.networks_path,
 
733
    return os.path.abspath('%s/nova-%s.%s' % (FLAGS.networks_path,
724
734
                                              bridge,
725
735
                                              kind))
726
736
 
727
737
 
728
738
def _ra_file(bridge, kind):
729
 
    """Return path to a pid or conf file for a bridge"""
 
739
    """Return path to a pid or conf file for a bridge."""
730
740
 
731
741
    if not os.path.exists(FLAGS.networks_path):
732
742
        os.makedirs(FLAGS.networks_path)
733
 
    return os.path.abspath("%s/nova-ra-%s.%s" % (FLAGS.networks_path,
 
743
    return os.path.abspath('%s/nova-ra-%s.%s' % (FLAGS.networks_path,
734
744
                                              bridge,
735
745
                                              kind))
736
746
 
737
747
 
738
748
def _dnsmasq_pid_for(bridge):
739
 
    """Returns the pid for prior dnsmasq instance for a bridge
740
 
 
741
 
    Returns None if no pid file exists
742
 
 
743
 
    If machine has rebooted pid might be incorrect (caller should check)
 
749
    """Returns the pid for prior dnsmasq instance for a bridge.
 
750
 
 
751
    Returns None if no pid file exists.
 
752
 
 
753
    If machine has rebooted pid might be incorrect (caller should check).
 
754
 
744
755
    """
745
 
 
746
756
    pid_file = _dhcp_file(bridge, 'pid')
747
757
 
748
758
    if os.path.exists(pid_file):
751
761
 
752
762
 
753
763
def _ra_pid_for(bridge):
754
 
    """Returns the pid for prior radvd instance for a bridge
755
 
 
756
 
    Returns None if no pid file exists
757
 
 
758
 
    If machine has rebooted pid might be incorrect (caller should check)
 
764
    """Returns the pid for prior radvd instance for a bridge.
 
765
 
 
766
    Returns None if no pid file exists.
 
767
 
 
768
    If machine has rebooted pid might be incorrect (caller should check).
 
769
 
759
770
    """
760
 
 
761
771
    pid_file = _ra_file(bridge, 'pid')
762
772
 
763
773
    if os.path.exists(pid_file):
766
776
 
767
777
 
768
778
def _ip_bridge_cmd(action, params, device):
769
 
    """Build commands to add/del ips to bridges/devices"""
770
 
 
 
779
    """Build commands to add/del ips to bridges/devices."""
771
780
    cmd = ['sudo', 'ip', 'addr', action]
772
781
    cmd.extend(params)
773
782
    cmd.extend(['dev', device])