root/pxe/common.py

Revision 17c79627d5d4c95f2428c5e361f8f06b64257983, 4.3 KB (checked in by Frederic Lepied <frederic.lepied@…>, 21 months ago)

added docstrings and a few unit tests

  • Property mode set to 100644
Line 
1#---------------------------------------------------------------
2# Project         : pxemngr
3# File            : common.py
4# Copyright       : 2009-2010 Splitted-Desktop Systems
5# Author          : Frederic Lepied
6# Created On      : Sun Feb  1 19:03:58 2009
7#---------------------------------------------------------------
8
9"""Common functions used by scripts and web logic."""
10
11import sys
12import os
13import re
14import settings
15from pxe.models import *
16
17_MAC_REGEXP = re.compile('^.*\s([0-9a-f:]+)\s.*', re.I)
18_IP_REGEXP = re.compile('^([0-9.]+).*\s[0-9a-f:]+\s.*', re.I)
19
20def ip_to_mac(ip):
21    """Lookup a MAC address from an IPV4 address on a live Linux system."""
22    for line in open('/proc/net/arp').readlines():
23        if line.find(ip) != -1:
24            res = _MAC_REGEXP.search(line)
25            if res:
26                return res.group(1)
27    return None
28
29def mac_to_ip(mac):
30    """Lookup an IPV4 address from a MAC address on a live Linux system."""
31    mac = mac.upper()
32    for line in open('/proc/net/arp').readlines():
33        if line.find(mac) != -1:
34            res = _IP_REGEXP.search(line)
35            if res:
36                return res.group(1)
37    return None
38
39def get_mac(request):
40    """Returns a MAC address corresponding to the IPV4 address of the remote host of the request."""
41    mac = ip_to_mac(request.META['REMOTE_ADDR'])
42    if not mac:
43        print 'no mac for', request.META['REMOTE_ADDR']
44        raise Http404
45    return mac
46   
47def error(str):
48    """Print an error and exit with a return code of 1."""
49    sys.stderr.write(str + '\n')
50    sys.exit(1)
51
52def simplify_mac(s):
53    """Remove : or - between hexa numbers for a MAC address. Always returns the address in lowercase"""
54    ss = s.replace('-', '')
55    sss = ss.replace(':', '')
56    if len(sss) != 12:
57        print 'simplify_mac: invalid length (not 12)', sss, len(sss)
58        raise ValueError
59    return sss.lower()
60
61def mac2filename(m):
62    """Returns a filename using the naming convention used by PXE: 01-<mac address separated by - >."""
63    s = '01-'
64    for i in range(0, 10, 2):
65        s = s + '%s-' % m[i:i+2]
66    s = s + '%s' % m[10:12]
67    return s
68
69def mac2path(mac):
70    """Returns the path of the MAC or IPV4 mask in the file system."""
71    if len(mac) == 12:
72        return '%s/%s' % (settings.PXE_ROOT, mac2filename(mac))
73    else:
74        return '%s/%s' % (settings.PXE_ROOT, mac)
75   
76def create_symlink(src, dst):
77    """Creates a symlink removing the destination if it exists before."""
78    if os.path.exists(dst):
79        os.unlink(dst)
80    os.symlink(src, dst)
81   
82def set_next_boot(system, name, abort=True):
83    """Sets next boot symlinks in the PXE and stores the value in the database."""
84    try:
85        boot_name = BootName.objects.get(name=name)
86    except BootName.DoesNotExist:
87        if abort:
88            error('Boot name %s not defined' % name)
89        else:
90            raise BootName.DoesNotExist
91
92    prof = '%s/%s%s' % (settings.PXE_PROFILES, boot_name.name, settings.PXE_SUFFIX)
93   
94    name_dst = '%s/%s' % (settings.PXE_ROOT, system.name)
95    create_symlink(prof, name_dst)
96    for m in MacAddress.objects.filter(system=system):
97        dst = mac2path(m.mac)
98        create_symlink(system.name, dst)
99       
100    if system.name == 'default':
101        create_symlink(prof, '%s/default' % (settings.PXE_ROOT))
102
103    log = Log(system=system, boot_name=boot_name)
104    log.save()
105
106def simplify_ip(ip):
107    """Returns a string containing the hexadecimal representation of an IPV4 address or a sub-part."""
108    l = ip.split('.')
109    s = ''
110    for e in l:
111        s = s + '%02X' % int(e)
112    return s
113
114if __name__ == "__main__":
115    import unittest
116   
117    class commonTest(unittest.TestCase):
118   
119        def test1(self):
120            """simplify_ip test."""
121            return self.assertEqual(simplify_ip('10.34'), '0A22')
122
123        def test2(self):
124            """mac2filename test."""
125            return self.assertEqual(mac2filename('001b38710ab6'), '01-00-1b-38-71-0a-b6')
126
127        def test3(self):
128            """simplify_mac test."""
129            return self.assertEqual(simplify_mac('00:1b:38:71:0a:b6'), '001b38710ab6')
130
131        def test4(self):
132            """simplify_mac test."""
133            return self.assertRaises(ValueError, lambda: simplify_mac('00:1b:38:71:0a'))
134
135    unittest.main()
136
137# common.py ends here
Note: See TracBrowser for help on using the browser.