41b32aa48f85bf9c5f6290af1d6d5688d4315e79
[nepi.git] / src / nepi / testbeds / planetlab / util.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 from constants import TESTBED_ID, TESTBED_VERSION
5 from nepi.core import testbed_impl
6 from nepi.core.metadata import Parallel
7 from nepi.util.constants import TIME_NOW
8 from nepi.util.graphtools import mst
9 from nepi.util import ipaddr2
10 from nepi.util import environ
11 from nepi.util.parallel import ParallelRun
12 import sys
13 import os
14 import os.path
15 import time
16 import resourcealloc
17 import collections
18 import operator
19 import functools
20 import socket
21 import struct
22 import tempfile
23 import subprocess
24 import random
25 import shutil
26 import logging
27 import metadata
28 import weakref
29
30 def getAPI(user, pass_, **kw):
31     import plcapi
32     return plcapi.PLCAPI(username=user, password=pass_, **kw)
33
34 def filterBlacklist(candidates):
35     blpath = environ.homepath('plblacklist')
36     
37     try:
38         bl = open(blpath, "r")
39     except:
40         return candidates
41         
42     try:
43         blacklist = set(
44             map(int,
45                 map(str.strip, bl.readlines())
46             )
47         )
48         return [ x for x in candidates if x not in blacklist ]
49     finally:
50         bl.close()
51
52 def appendBlacklist(node_ids):
53     if not isinstance(node_ids, list):
54         node_ids = [ node_ids ]
55     
56     blpath = environ.homepath('plblacklist')
57     bl = open(blpath, "a")
58     
59     try:
60         for node_id in node_ids:
61             bl.write("%s\n" % (node_id,))
62     finally:
63         bl.close()
64
65 def getVnet(api, slicename):
66     slicetags = api.GetSliceTags(
67         name = slicename,
68         tagname = 'vsys_vnet',
69         fields=('value',))
70     if slicetags:
71         return slicetags[0]['value']
72     else:
73         return None
74
75 def getNodes(api, num, **constraints):
76     # Now do the backtracking search for a suitable solution
77     # First with existing slice nodes
78     reqs = []
79     nodes = []
80     
81     import node as Node
82         
83     for i in xrange(num):
84         node = Node.Node(api)
85         node.min_num_external_interface = 1
86         nodes.append(node)
87     
88     node = nodes[0]
89     candidates = filterBlacklist(node.find_candidates())
90     reqs = [candidates] * num
91
92     def pickbest(fullset, nreq, node=nodes[0]):
93         if len(fullset) > nreq:
94             fullset = zip(node.rate_nodes(fullset),fullset)
95             fullset.sort(reverse=True)
96             del fullset[nreq:]
97             return set(map(operator.itemgetter(1),fullset))
98         else:
99             return fullset
100     
101     solution = resourcealloc.alloc(reqs, sample=pickbest)
102     
103     # Do assign nodes
104     runner = ParallelRun(maxthreads=4)
105     for node, node_id in zip(nodes, solution):
106         runner.put(node.assign_node_id, node_id)
107     runner.join()
108     
109     return nodes
110
111 def getSpanningTree(nodes, root = None, maxbranching = 2, hostgetter = operator.attrgetter('hostname')):
112     if not root:
113         # Pick root (deterministically)
114         root = min(nodes, key=hostgetter)
115     
116     # Obtain all IPs in numeric format
117     # (which means faster distance computations)
118     for node in nodes:
119         node._ip = socket.gethostbyname(hostgetter(node))
120         node._ip_n = struct.unpack('!L', socket.inet_aton(node._ip))[0]
121     
122     # Compute plan
123     # NOTE: the plan is an iterator
124     plan = mst.mst(
125         nodes,
126         lambda a,b : ipaddr2.ipdistn(a._ip_n, b._ip_n),
127         root = root,
128         maxbranching = maxbranching)
129
130     return plan
131