~wgrant/ubuntu/natty/landscape-client/natty-updates-broken

« back to all changes in this revision

Viewing changes to landscape/lib/network.py

  • Committer: Bazaar Package Importer
  • Author(s): Free Ekanayaka
  • Date: 2010-04-21 19:58:10 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20100421195810-s30uv3s6i27lue38
Tags: 1.5.2-0ubuntu0.10.10.0
* New upstream version (LP: #594594):
  - A new includes information about active network devices and their
    IP address in sysinfo output (LP: #272344).
  - A new plugin collects information about network traffic (#LP :284662).
  - Report information about which packages requested a reboot (LP: #538253).
  - Fix breakage on Lucid AMIs having no ramdisk (LP: #574810).
  - Migrate the inter-process communication system from DBus to Twisted AMP.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
Network introspection utilities using ioctl and the /proc filesystem.
 
3
"""
 
4
import array
 
5
import fcntl
 
6
import socket
 
7
import struct
 
8
 
 
9
__all__ = ["get_active_device_info", "get_network_traffic"]
 
10
 
 
11
# from header /usr/include/bits/ioctls.h
 
12
SIOCGIFCONF = 0x8912
 
13
SIOCGIFFLAGS = 0x8913
 
14
SIOCGIFNETMASK = 0x891b
 
15
SIOCGIFBRDADDR = 0x8919
 
16
SIOCGIFADDR = 0x8915
 
17
SIOCGIFHWADDR = 0x8927
 
18
 
 
19
 
 
20
# struct definition from header /usr/include/net/if.h
 
21
# the struct size varies according to the platform arch size
 
22
# a minimal c program was used to determine the size of the
 
23
# struct, standard headers removed for brevity.
 
24
"""
 
25
#include <linux/if.h>
 
26
int main() {
 
27
  printf("Size of struct %lu\n", sizeof(struct ifreq));
 
28
}
 
29
"""
 
30
 
 
31
IF_STRUCT_SIZE_32 = 32
 
32
IF_STRUCT_SIZE_64 = 40
 
33
 
 
34
 
 
35
def is_64():
 
36
    """Returns C{True} if the platform is 64-bit, otherwise C{False}."""
 
37
    return struct.calcsize("l") == 8
 
38
 
 
39
 
 
40
# initialize the struct size as per the machine's archictecture
 
41
IF_STRUCT_SIZE = is_64() and IF_STRUCT_SIZE_64 or IF_STRUCT_SIZE_32
 
42
 
 
43
 
 
44
def get_active_interfaces(sock):
 
45
    """Generator yields active network interface names.
 
46
 
 
47
    @param sock: a socket instance.
 
48
    """
 
49
    max_interfaces = 128
 
50
 
 
51
    # setup an an array to hold our response, and initialized to null strings.
 
52
    interfaces = array.array("B", "\0" * max_interfaces * IF_STRUCT_SIZE)
 
53
    buffer_size = interfaces.buffer_info()[0]
 
54
    packed_bytes = struct.pack(
 
55
        "iL", max_interfaces * IF_STRUCT_SIZE, buffer_size)
 
56
 
 
57
    byte_length = struct.unpack(
 
58
        "iL", fcntl.ioctl(sock.fileno(), SIOCGIFCONF, packed_bytes))[0]
 
59
 
 
60
    result = interfaces.tostring()
 
61
 
 
62
    # generator over the interface names
 
63
    for index in range(0, byte_length, IF_STRUCT_SIZE):
 
64
        ifreq_struct = result[index:index+IF_STRUCT_SIZE]
 
65
        interface_name = ifreq_struct[:ifreq_struct.index("\0")]
 
66
        yield interface_name
 
67
 
 
68
 
 
69
def get_broadcast_address(sock, interface):
 
70
    """Return the broadcast address associated to an interface.
 
71
 
 
72
    @param sock: a socket instance.
 
73
    @param interface: The name of the interface.
 
74
    """
 
75
    return socket.inet_ntoa(fcntl.ioctl(
 
76
        sock.fileno(),
 
77
        SIOCGIFBRDADDR,
 
78
        struct.pack("256s", interface[:15]))[20:24])
 
79
 
 
80
 
 
81
def get_netmask(sock, interface):
 
82
    """Return the network mask associated to an interface.
 
83
 
 
84
    @param sock: a socket instance.
 
85
    @param interface: The name of the interface.
 
86
    """
 
87
    return socket.inet_ntoa(fcntl.ioctl(
 
88
        sock.fileno(),
 
89
        SIOCGIFNETMASK,
 
90
        struct.pack("256s", interface[:15]))[20:24])
 
91
 
 
92
 
 
93
def get_ip_address(sock, interface):
 
94
    """Return the IP address associated to the interface.
 
95
 
 
96
    @param sock: a socket instance.
 
97
    @param interface: The name of the interface.
 
98
    """
 
99
    return socket.inet_ntoa(fcntl.ioctl(
 
100
        sock.fileno(),
 
101
        SIOCGIFADDR,
 
102
        struct.pack("256s", interface[:15]))[20:24])
 
103
 
 
104
 
 
105
def get_mac_address(sock, interface):
 
106
    """
 
107
    Return the hardware MAC address for an interface in human friendly form,
 
108
    ie. six colon separated groups of two hexadecimal digits.
 
109
 
 
110
    @param sock: a socket instance.
 
111
    @param interface: The name of the interface.
 
112
    """
 
113
    mac_address = fcntl.ioctl(
 
114
        sock.fileno(), SIOCGIFHWADDR, struct.pack("256s", interface[:15]))
 
115
    return "".join(["%02x:" % ord(char) for char in mac_address[18:24]])[:-1]
 
116
 
 
117
 
 
118
def get_flags(sock, interface):
 
119
    """Return the integer value of the interface flags for the given interface.
 
120
 
 
121
    @param sock: a socket instance.
 
122
    @param interface: The name of the interface.
 
123
    @see /usr/include/linux/if.h for the meaning of the flags.
 
124
    """
 
125
    data = fcntl.ioctl(
 
126
        sock.fileno(), SIOCGIFFLAGS, struct.pack("256s", interface[:15]))
 
127
    return struct.unpack("H", data[16:18])[0]
 
128
 
 
129
 
 
130
def get_active_device_info():
 
131
    """
 
132
    Returns a dictionary containing information on each active network
 
133
    interface present on a machine.
 
134
    """
 
135
    results = []
 
136
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_IP)
 
137
    for interface in get_active_interfaces(sock):
 
138
        interface_info = {"interface": interface}
 
139
        interface_info["ip_address"] = get_ip_address(sock, interface)
 
140
        interface_info["mac_address"] = get_mac_address(sock, interface)
 
141
        interface_info["broadcast_address"] = get_broadcast_address(sock,
 
142
                                                                    interface)
 
143
        interface_info["netmask"] = get_netmask(sock, interface)
 
144
        interface_info["flags"] = get_flags(sock, interface)
 
145
        results.append(interface_info)
 
146
    del sock
 
147
    return results
 
148
 
 
149
 
 
150
def get_network_traffic(source_file="/proc/net/dev"):
 
151
    """
 
152
    Retrieves an array of information regarding the network activity per
 
153
    network interface.
 
154
    """
 
155
    netdev = open(source_file, "r")
 
156
    lines = netdev.readlines()
 
157
    netdev.close()
 
158
 
 
159
    # Parse out the column headers as keys.
 
160
    _, receive_columns, transmit_columns = lines[1].split("|")
 
161
    columns = ["recv_%s" % column for column in receive_columns.split()]
 
162
    columns.extend(["send_%s" % column for column in transmit_columns.split()])
 
163
 
 
164
    # Parse out the network devices.
 
165
    devices = {}
 
166
    for line in lines[2:]:
 
167
        if not ":" in line:
 
168
            continue
 
169
        device, data = line.split(":")
 
170
        device = device.strip()
 
171
        devices[device] = dict(zip(columns, map(long, data.split())))
 
172
    return devices
 
173
 
 
174
 
 
175
if __name__ == "__main__":
 
176
    import pprint
 
177
    pprint.pprint(get_active_device_info())