In my quest for the perfect network setup for a VM here is a piece of
code that will allocate mac addresses from a pool.
It's not that polished yet. So far you can only allocate based on the
pool:
fe:fd:12:aa:bb:cc
where aa:bb:cc are the pool. However, that is 17 million different mac
addresses so it's quite a lot.
The code forms a REST webservice that accepts a POST to / and responds
with a Location header indicating the new mac address.
That mac address resources accept a DELETE to return the address to
the pool.
There are other options that define a client for the webservice.
So the idea is that you do this on 'someserver':
python macserv.py start
and then later, when you want to start a VM:
MACADDR=`python macserv.py clientpost someserver 8000`
./umlkernel ubda=fs eth0=tuntap,,$MACADDR ...
and when the VM stops you do:
python macserv.py clientdelete $MACADDR someserver 8000
This doesn't help you discover IP addresses (my other obsession) but
it does deletgate control over macs to a central point. Obtaining a
mac is such an infrequent operation (I have some apps where VMs are
highly disposable but I still don't create macs that often) that a
single server like this could easily handle a network of hundreds of
machines.
If anyone uses it let me know... my personal publishing systems (for
code and such) are in a little bit of flux right now but it will go
into source control eventually.
--
Nic Ferrier
http://www.tapsellferrier.co.uk for all your tapsell ferrier needs
#!/usr/bin/python
import BaseHTTPServer
import os
import os.path
import shutil
import sys
import re
import urllib
import logging
import dbhash
import time
# This should be a param
# It indicates what byte follows fe:fd in the mac address; eg: fe:fd:12:aa:bb:cc
mac_3rd_byte=12
# The map of allocated MACs; we use mac: time-allocated
allocated_map = None
freed_map = None
def init_mac_seed():
global allocated_map
keys = allocated_map.keys()
if len(keys) == 0:
return 0
else:
keys.sort(lambda a,b: cmp(allocated_map[a], allocated_map[b]))
last_mac = keys[-1]
mac_re = "fe:fd:([0-9a-fA-F]{2})((:([0-9a-fA-F]{2})){3})"
last_id = int("".join(re.split(":", re.match(mac_re, last_mac).groups()[1])), 16)
return last_id
# Default for the first mac address
id = None
def next_mac():
global id
global mac_3rd_byte
global allocated_map
global freed_map
freed_keys = freed_map.keys()
if len(freed_keys):
mac, t = freed_map.popitem()
return mac
else:
id = id + 1
mac_end = ":".join(filter(lambda x: not(x == ''), re.split("(.{2})", "%06x" % (id))))
mac = "fe:fd:%s:%s" % (mac_3rd_byte, mac_end)
allocated_map[mac] = "%f" % (time.time())
return mac
def mark_free(mac):
global allocated_map
try:
print mac
allocated_map[mac]
except KeyError:
return False
else:
global freed_map
freed_map[mac] = "%f" % (time.time())
allocated_map.pop(mac)
return True
# The HTTP server we're using
# It implements a simple REST service for acquiring and returning a MAC address
class MACSERVEHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""XRT http handler."""
def handle_one_request(self):
"""Handle a single HTTP request. Pinched from XRT and before that, python."""
self.raw_requestline = self.rfile.readline()
if not self.raw_requestline:
self.close_connection = 1
return
if not self.parse_request(): # An error code has been sent, just exit
return
if self.command == "POST":
the_mac_address = next_mac()
self.send_response(201, "Created")
self.send_header("Location", "/" + the_mac_address)
self.end_headers()
elif self.command == "DELETE":
# Needs to return the resource to be deleted... where is the resource?
the_mac_address = self.path.strip("/")
# Check that we think the mac is assigned
if mark_free(the_mac_address):
self.send_response(204, "Deleted")
self.end_headers()
else:
self.send_error(500, "Not assigned")
else:
self.send_error(500, "bad HTTP method")
return
def run(HandlerClass = MACSERVEHTTPRequestHandler,
ServerClass = BaseHTTPServer.HTTPServer):
BaseHTTPServer.test(HandlerClass, ServerClass)
return
if __name__ == '__main__':
import pdb
import sys
def runit():
global allocated_map
global freed_map
global id
allocated_map = dbhash.open("/var/run/macserve_allocated.dbm", "c")
freed_map = dbhash.open("/var/run/macserve_freed.dbm", "c")
id = init_mac_seed()
run()
if sys.argv[1] == "run":
sys.argv=[] # for some reason the stupid BaseHTTPServer reads argv by default
pdb.runcall(runit)
elif sys.argv[1] == "start":
ret = os.fork()
if ret == 0:
sys.argv=[] # for some reason the stupid BaseHTTPServer reads argv by default
runit()
else:
pidfile = open("/var/run/macserver", "w")
pidfile.write("%s" % (ret))
pidfile.close()
elif sys.argv[1] == "stop":
if os.path.exists("/var/run/macserver"):
pidfile = open("/var/run/macserver")
pid = int(pidfile.read().strip())
os.kill(pid, 3)
elif sys.argv[1] == "clientpost":
import httplib
httpcon = httplib.HTTPConnection(sys.argv[2], int(sys.argv[3]))
try:
httpcon.request("POST", "/")
resp = httpcon.getresponse()
if resp.status == 201:
print resp.getheader("Location").split("/")[-1]
else:
print >>sys.stderr, resp.reason
finally:
httpcon.close()
elif sys.argv[1] == "clientdelete":
import httplib
httpcon = httplib.HTTPConnection(sys.argv[3], int(sys.argv[4]))
try:
httpcon.request("DELETE", "/" + sys.argv[2])
resp = httpcon.getresponse()
if resp.status != 204:
print >>sys.stderr, resp.reason
finally:
httpcon.close()
# End
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
User-mode-linux-user mailing list
User-mode-linux-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-user