~gmb/maas/backports

« back to all changes in this revision

Viewing changes to src/provisioningserver/udev.py

  • Committer: Gavin Panella
  • Date: 2014-09-29 15:26:08 UTC
  • mfrom: (3124 maas)
  • mto: This revision was merged to the branch mainline in revision 3125.
  • Revision ID: gavin.panella@canonical.com-20140929152608-73b1soyzub5dhe6w
Merge trunk, resolving conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2014 Canonical Ltd.  This software is licensed under the
 
2
# GNU Affero General Public License version 3 (see the file LICENSE).
 
3
 
 
4
"""Code to generate `udev` rules."""
 
5
 
 
6
from __future__ import (
 
7
    absolute_import,
 
8
    print_function,
 
9
    unicode_literals,
 
10
    )
 
11
 
 
12
str = None
 
13
 
 
14
__metaclass__ = type
 
15
__all__ = [
 
16
    'compose_network_interfaces_udev_rules',
 
17
    ]
 
18
 
 
19
from textwrap import dedent
 
20
 
 
21
 
 
22
def compose_udev_equality(key, value):
 
23
    """Return a udev comparison clause, like `ACTION=="add"`."""
 
24
    assert key == key.upper()
 
25
    return '%s=="%s"' % (key, value)
 
26
 
 
27
 
 
28
def compose_udev_attr_equality(attribute, value):
 
29
    """Return a udev attribute comparison clause, like `ATTR{type}=="1"`."""
 
30
    assert attribute == attribute.lower()
 
31
    return 'ATTR{%s}=="%s"' % (attribute, value)
 
32
 
 
33
 
 
34
def compose_udev_setting(key, value):
 
35
    """Return a udev assignment clause, like `NAME="eth0"`."""
 
36
    assert key == key.upper()
 
37
    return '%s="%s"' % (key, value)
 
38
 
 
39
 
 
40
def compose_udev_rule(interface, mac):
 
41
    """Return a udev rule to set the name of network interface with `mac`.
 
42
 
 
43
    The rule ends up as a single line looking something like:
 
44
 
 
45
        SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*",
 
46
        ATTR{address}="ff:ee:dd:cc:bb:aa", NAME="eth0"
 
47
 
 
48
    (Note the difference between `=` and `==`: they both occur.)
 
49
    """
 
50
    rule = ', '.join([
 
51
        compose_udev_equality('SUBSYSTEM', 'net'),
 
52
        compose_udev_equality('ACTION', 'add'),
 
53
        compose_udev_equality('DRIVERS', '?*'),
 
54
        compose_udev_attr_equality('address', mac),
 
55
        compose_udev_setting('NAME', interface),
 
56
        ])
 
57
    return '%s\n' % rule
 
58
 
 
59
 
 
60
def compose_network_interfaces_udev_rules(interfaces):
 
61
    """Return text for a udev persistent-net rules file.
 
62
 
 
63
    These rules assign fixed names to network interfaces.  They ensure that
 
64
    the same network interface cards come up with the same interface names on
 
65
    every boot.  Otherwise, the kernel may assign interface names in different
 
66
    orders on every boot, and so network interfaces can "switch identities"
 
67
    every other time the machine reboots.
 
68
 
 
69
    :param interfaces: List of tuples of interface name and MAC address.
 
70
    :return: Text to write into a udev rules file.
 
71
    """
 
72
    rules = [
 
73
        compose_udev_rule(interface, mac)
 
74
        for interface, mac in interfaces
 
75
        ]
 
76
    return dedent("""\
 
77
        # MAAS-assigned network interface names.
 
78
        %s
 
79
        # End of MAAS-assigned network interface names.
 
80
        """) % '\n\n'.join(rules)