Change OMF attributes during runtime
[nepi.git] / src / nepi / testbeds / omf / omf_api.py
1 import datetime
2 import logging
3 import ssl
4 import sys
5 import time
6
7 from nepi.testbeds.omf.omf_client import OMFClient
8 from nepi.testbeds.omf.omf_messages import MessageHandler
9
10 class OmfAPI(object):
11     def __init__(self, slice, host, port, password, debug):
12         date = datetime.datetime.now().strftime("%Y-%m-%dt%H.%M.%S")
13         tz = -time.altzone if time.daylight != 0 else -time.timezone
14         date += "%+06.2f" % (tz / 3600) # timezone difference is in seconds
15         self._user = "%s-%s" % (slice, date)
16         self._slice = slice
17         self._host = host
18         self._port = port
19         self._password = password
20         self._hostnames = []
21
22         self._logger = logging.getLogger('nepi.testbeds.omfapi')
23         if debug:
24             self._logger.setLevel(logging.DEBUG)
25
26         # OMF xmpp client
27         self._client = None
28         # message handler
29         self._message = None
30
31         if sys.version_info < (3, 0):
32             reload(sys)
33             sys.setdefaultencoding('utf8')
34
35         # instantiate the xmpp client
36         self._init_client()
37
38         # register xmpp nodes for the experiment
39         self._enroll_experiment()
40
41         # register xmpp logger for the experiment
42         self._enroll_logger()
43
44     def _init_client(self):
45         jid = "%s@%s" % (self._user, self._host)
46         xmpp = OMFClient(jid, self._password)
47         # PROTOCOL_SSLv3 required for compatibility with OpenFire
48         xmpp.ssl_version = ssl.PROTOCOL_SSLv3
49
50         if xmpp.connect((self._host, self._port)):
51             xmpp.process(threaded=True)
52             while not xmpp.ready:
53                 time.sleep(1)
54             self._client = xmpp
55             self._message = MessageHandler(self._slice, self._user)
56         else:
57             msg = "Unable to connect to the XMPP server."
58             self._logger.error(msg)
59             raise RuntimeError(msg)
60
61     def _enroll_experiment(self):
62         xmpp_node = self._exp_session_id
63         self._client.create(xmpp_node)
64         self._client.subscribe(xmpp_node)
65
66         address = "/%s/OMF/%s/%s" % (self._host, self._slice, self._user)
67         payload = self._message.newexpfunction(self._user, address)
68         slice_sid = "/OMF/%s" % (self._slice)
69         self._client.publish(payload, slice_sid)
70
71     def _enroll_logger(self):
72         xmpp_node = self._logger_session_id
73         self._client.create(xmpp_node)
74         self._client.subscribe(xmpp_node)
75
76         payload = self._message.logfunction("2", 
77                 "nodeHandler::NodeHandler", 
78                 "INFO", 
79                 "OMF Experiment Controller 5.4 (git 529a626)")
80         self._client.publish(payload, xmpp_node)
81
82     def _host_session_id(self, hostname):
83         return "/OMF/%s/%s/%s" % (self._slice, self._user, hostname)
84
85     def _host_resource_id(self, hostname):
86         return "/OMF/%s/resources/%s" % (self._slice, hostname)
87
88     @property
89     def _exp_session_id(self):
90         return "/OMF/%s/%s" % (self._slice, self._user)
91
92     @property
93     def _logger_session_id(self):
94         return "/OMF/%s/%s/LOGGER" % (self._slice, self._user)
95
96     def delete(self, hostname):
97         if not hostname in self._hostnames:
98             return
99
100         self._hostnames.remove(hostname)
101
102         xmpp_node = self._host_session_id(hostname)
103         self._client.delete(xmpp_node)
104
105     def enroll_host(self, hostname):
106         if hostname in self._hostnames:
107             return 
108
109         self._hostnames.append(hostname)
110
111         xmpp_node =  self._host_session_id(hostname)
112         self._client.create(xmpp_node)
113         self._client.subscribe(xmpp_node)
114
115         xmpp_node =  self._host_resource_id(hostname)
116         self._client.subscribe(xmpp_node)
117
118         payload = self._message.enrollfunction("1", "*", "1", hostname)
119         self._client.publish(payload, xmpp_node)
120
121     def configure(self, hostname, attribute, value): 
122         payload = self._message.configurefunction(hostname, value, attribute)
123         xmpp_node =  self._host_session_id(hostname)
124         self._client.publish(payload, xmpp_node)
125
126     def execute(self, hostname, app_id, arguments, path):
127         payload = self._message.executefunction(hostname, app_id, arguments, path)
128         xmpp_node =  self._host_session_id(hostname)
129         self._client.publish(payload, xmpp_node)
130
131     def disconnect(self):
132         self._client.delete(self._exp_session_id)
133         self._client.delete(self._logger_session_id)
134
135         for hostname in self._hostnames[:]:
136             self.delete(hostname)
137
138         time.sleep(5)
139         self._client.disconnect()
140