Several execution fixes:
[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.ipaddr2 as ipaddr2
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.netmask = None
22         self.broadcast = True
23         self._interface_id = None
24
25         # These get initialized when the iface is connected to its node
26         self.node = None
27
28         # These get initialized when the iface is connected to the internet
29         self.has_internet = False
30
31     def __str__(self):
32         return "%s<ip:%s/%s up mac:%s>" % (
33             self.__class__.__name__,
34             self.address, self.netmask,
35             self.lladdr,
36         )
37
38     def add_address(self, address, netprefix, broadcast):
39         raise RuntimeError, "Cannot add explicit addresses to public interface"
40     
41     def pick_iface(self, siblings):
42         """
43         Picks an interface using the PLCAPI to query information about the node.
44         
45         Needs an assigned node.
46         
47         Params:
48             siblings: other NodeIface elements attached to the same node
49         """
50         
51         if self.node is None or self.node._node_id is None:
52             raise RuntimeError, "Cannot pick interface without an assigned node"
53         
54         avail = self._api.GetInterfaces(
55             node_id=self.node._node_id, 
56             is_primary=self.primary,
57             fields=('interface_id','mac','netmask','ip') )
58         
59         used = set([sibling._interface_id for sibling in siblings
60                     if sibling._interface_id is not None])
61         
62         for candidate in avail:
63             candidate_id = candidate['interface_id']
64             if candidate_id not in used:
65                 # pick it!
66                 self._interface_id = candidate_id
67                 self.address = candidate['ip']
68                 self.lladdr = candidate['mac']
69                 self.netprefix = candidate['netmask']
70                 self.netmask = ipaddr2.ipv4_dot2mask(self.netprefix) if self.netprefix else None
71                 return
72         else:
73             raise RuntimeError, "Cannot configure interface: cannot find suitable interface in PlanetLab node"
74
75     def validate(self):
76         if not self.has_internet:
77             raise RuntimeError, "All external interface devices must be connected to the Internet"
78     
79
80 class TunIface(object):
81     def __init__(self, api=None):
82         if not api:
83             api = plcapi.PLCAPI()
84         self._api = api
85         
86         # Attributes
87         self.address = None
88         self.netprefix = None
89         self.netmask = None
90         
91         self.up = None
92         self.device_name = None
93         self.mtu = None
94         self.snat = False
95
96         # These get initialized when the iface is connected to its node
97         self.node = None
98
99     def __str__(self):
100         return "%s<ip:%s/%s %s%s>" % (
101             self.__class__.__name__,
102             self.address, self.netmask,
103             " up" if self.up else " down",
104             " snat" if self.snat else "",
105         )
106
107     def add_address(self, address, netprefix, broadcast):
108         if (self.address or self.netprefix or self.netmask) is not None:
109             raise RuntimeError, "Cannot add more than one address to TUN interfaces"
110         if broadcast:
111             raise ValueError, "TUN interfaces cannot broadcast in PlanetLab"
112         
113         self.address = address
114         self.netprefix = netprefix
115         self.netmask = ipaddr2.ipv4_dot2mask(netprefix)
116
117     def validate(self):
118         pass
119     
120
121 # Yep, it does nothing - yet
122 class Internet(object):
123     def __init__(self, api=None):
124         if not api:
125             api = plcapi.PLCAPI()
126         self._api = api
127
128