Fix a minor bug
[snf-network] / snf-network-mac-prefix
1 #!/usr/bin/python
2
3 import fcntl
4 import errno
5 import os
6 import logging
7 import sys
8 import simplejson
9 import fcntl
10
11 starting_mac_prefix='aa:00:00'
12
13 class FileLock(object):
14   def __init__(self, fd, filename):
15     self.fd = fd
16     self.filename = filename
17
18   @classmethod
19   def Open(cls, filename):
20     # Using "os.open" is necessary to allow both opening existing file
21     # read/write and creating if not existing. Vanilla "open" will truncate an
22     # existing file -or- allow creating if not existing.
23     return cls(os.fdopen(os.open(filename, os.O_RDWR | os.O_CREAT), "w+"),
24                filename)
25
26   def __del__(self):
27     self.Close()
28
29   def Close(self):
30     if hasattr(self, "fd") and self.fd:
31       self.fd.close()
32       self.fd = None
33
34   def _flock(self, flag):
35     self._Lock(self.fd, flag)
36
37   @staticmethod
38   def _Lock(fd, flag):
39     fcntl.flock(fd, flag)
40
41   def Exclusive(self):
42     self._flock(fcntl.LOCK_EX)
43
44   def Unlock(self):
45     self._flock(fcntl.LOCK_UN)
46     
47
48 def get_data():
49   f = open('test', 'r')
50   data = simplejson.load(f)
51   f.close()
52   high = data['high']
53   pool = set(data['pool'])
54   return high, pool
55
56 def update_data(high, pool):
57   data = dict()
58   data['pool'] = list(pool)
59   data['high'] = high
60   f = open('test', 'w')
61   f.write(simplejson.dumps(data, indent=2))
62   f.close()
63
64 def init(prefix):
65   pool=set()
66   high=prefix
67   update_data(high, pool)
68
69 def find_prefix(high, pool):
70   try:
71     prefix = pool.pop()
72     new_high = high
73   except KeyError:
74     a = hex(int(high.replace(":",""),16) + 1).replace("0x",'')
75     prefix = ":".join([a[x:x+2] for x in xrange(0,len(a),2)])
76     new_high = prefix    
77
78   return prefix, new_high, pool
79
80   
81
82   
83
84
85 def main(argv):
86   if len(argv) < 2:
87     print "Usage: " + argv[0] + "init/get/put"
88     return 1
89
90   action=argv[1]
91
92   lock = FileLock.Open('prefix.lock')
93   lock.Exclusive()
94
95
96   if action == "get":
97     (high, pool) = get_data()
98     (prefix, new_high, new_pool) = find_prefix(high, pool)
99     update_data(new_high, new_pool)
100     print prefix
101
102   elif action == "put":
103     if len(argv) < 3 :
104       lock.Unlock()
105       print "Usage: " + argv[0] + "put prefix"
106       return 1
107
108     (high, pool) = get_data()
109     prefix = argv[2]
110     pool.add(prefix)
111     update_data(high, pool)
112
113   elif action == "init":
114     if len(argv) < 3:
115       lock.Unlock()
116       print "Usage: " + argv[0] + "init prefix"
117       return 1
118
119     prefix = argv[2]
120     init(prefix)
121     
122   lock.Unlock()
123   return 0
124
125 if __name__ == '__main__':
126   sys.exit(main(sys.argv))
127