Implementing PlanetLab testbed
[nepi.git] / src / nepi / testbeds / planetlab / interfaces.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 from constants import TESTBED_ID
5 import nepi.util.ipaddr
6 import plcapi
7
8 class NodeIface(object):
9     def __init__(self, api=None):
10         if not api:
11             api = plcapi.PLCAPI()
12         self._api = api
13         
14         # Attributes
15         self.primary = True
16
17         # These get initialized at configuration time
18         self.address = None
19         self.lladdr = None
20         self.netprefix = None
21         self.broadcast = True
22         self._interface_id = None
23
24         # These get initialized when the iface is connected to its node
25         self.node = None
26
27         # These get initialized when the iface is connected to the internet
28         self.has_internet = False
29
30     def add_address(self, address, netprefix, broadcast):
31         raise RuntimeError, "Cannot add explicit addresses to public interface"
32     
33     def pick_iface(self, siblings):
34         """
35         Picks an interface using the PLCAPI to query information about the node.
36         
37         Needs an assigned node.
38         
39         Params:
40             siblings: other NodeIface elements attached to the same node
41         """
42         
43         if (self.node or self.node._node_id) is None:
44             raise RuntimeError, "Cannot pick interface without an assigned node"
45         
46         avail = self._api.GetInterfaces(
47             node_id=self.node._node_id, 
48             is_primary=self.primary,
49             fields=('interface_id','mac','netmask','ip') ))
50         
51         used = set([sibling._interface_id for sibling in siblings
52                     if sibling._interface_id is not None])
53         
54         for candidate in avail:
55             candidate_id = candidate['interface_id']
56             if candidate_id not in used:
57                 # pick it!
58                 self._interface_id = candidate_id
59                 self.address = candidate['ip']
60                 self.lladdr = candidate['mac']
61                 self.netprefix = candidate['netmask']
62                 return
63         else:
64             raise RuntimeError, "Cannot configure interface: cannot find suitable interface in PlanetLab node"
65
66     def validate(self):
67         if not element.has_internet:
68             raise RuntimeError, "All external interface devices must be connected to the Internet"
69     
70
71 class TunIface(object):
72     def __init__(self, api=None):
73         if not api:
74             api = plcapi.PLCAPI()
75         self._api = api
76         
77         # Attributes
78         self.address = None
79         self.netprefix = None
80         self.netmask = None
81         
82         self.up = None
83         self.device_name = None
84         self.mtu = None
85         self.snat = False
86
87         # These get initialized when the iface is connected to its node
88         self.node = None
89
90     def add_address(self, address, netprefix, broadcast):
91         if (self.address or self.netprefix or self.netmask) is not None:
92             raise RuntimeError, "Cannot add more than one address to TUN interfaces"
93         if broadcast:
94             raise ValueError, "TUN interfaces cannot broadcast in PlanetLab"
95         
96         self.address = address
97         self.netprefix = netprefix
98         self.netmask = nepi.util.ipaddr.ipv4_dot2mask(netprefix)
99
100     def validate(self):
101         pass
102     
103
104 # Yep, it does nothing - yet
105 class Internet(object):
106     def __init__(self, api=None):
107         if not api:
108             api = plcapi.PLCAPI()
109         self._api = api
110
111