source: fedd/federation/emulab_segment.py @ f3898f7

compt_changesinfo-ops
Last change on this file since f3898f7 was f3898f7, checked in by Ted Faber <faber@…>, 13 years ago

Simple support for experiments in groups. Closes #32

  • Property mode set to 100644
File size: 5.3 KB
Line 
1#!/usr/local/bin/python
2
3import logging 
4import util
5
6from M2Crypto import SSL
7from M2Crypto.m2xmlrpclib import SSL_Transport
8from xmlrpclib import ServerProxy, dumps, loads, Fault, Error, Binary
9from M2Crypto.SSL import SSLError
10from M2Crypto.BIO import BIOError
11from socket import error as socket_error
12from socket import sslerror
13import httplib
14from federation.util import fedd_ssl_context
15from federation import service_error
16
17class emulab_segment:
18    def __init__(self, boss, cert):
19        self.ctxt = fedd_ssl_context(my_cert=cert)
20        self.ctxt.set_verify(SSL.verify_none, 10)
21        self.boss = boss
22        self.null = """
23set ns [new Simulator]
24source tb_compat.tcl
25
26set a [$ns node]
27
28$ns rtproto Session
29$ns run
30"""
31        self.log =  getattr(self, 'log', None) 
32        self.debug = getattr(self, 'debug', False)
33
34    def emulab_call(self, method, params):
35        VERSION = 0.1
36        try:
37            transport = SSL_Transport(self.ctxt)
38            port = ServerProxy(self.boss, transport=transport)
39            remote_method = getattr(port, method, None)
40            if remote_method is not None:
41                resp = remote_method(VERSION, params)
42            else:
43                raise service_error(service_error.internal, 
44                        "Bad method: %s" % method)
45        except socket_error, e:
46            raise service_error(service_error.connect, 
47                    "Cannot connect" % e)
48            raise e
49        except BIOError, e:
50            if self.log:
51                self.log.warn("BIO error: %s" % e)
52            raise e
53        except sslerror, e:
54            if self.log:
55                self.log.warn("SSL (socket) error: %s" %  e)
56            raise e
57        except SSLError, e:
58            if self.log:
59                self.log.warn("SSL error: %s" % e)
60            raise e
61        except httplib.HTTPException, e:
62            if self.log:
63                self.log.warn("HTTP error: %s" % e)
64            raise e
65        except Fault, f:
66            raise service_error(service_error.protocol, 
67                    "Remote XMLRPC Fault: %s" % f)
68        except Error, e:
69            raise service_error(service_error.protocol, 
70                    "Remote XMLRPC Fault: %s" % e)
71
72        code = resp.get('code', -1)
73        if code ==0:
74            return (code, resp.get('value', None))
75        else:
76            return (code, resp.get('output', None))
77
78    def get_state(self, pid, eid):
79        """
80        Return the state of the experiment as reported by emulab
81        """
82
83        if self.debug:
84            state = 'swapped'
85        else:
86            params =  { 'proj': pid, 'exp': eid }
87            code, state = self.emulab_call('experiment.state', params)
88            if code != 0:
89                state = 'none'
90
91        if self.log:
92            self.log.debug("State is %s" % state)
93        return state
94
95    def make_null_experiment(self, pid, eid, tmpdir, gid=None):
96        """
97        Create a null copy of the experiment so that we capture any logs there
98        if the modify fails.  Emulab software discards the logs from a failed
99        startexp.
100        """
101
102        if self.debug:
103            if self.log:
104                self.log.debug("[make_null_experiment]: (debug) Creating experiment")
105            return True
106        else:
107            params = {
108                    'proj': pid,
109                    'exp': eid, 
110                    'nsfilestr': self.null,
111                    'batch': False,
112                    'idleswap': 0,
113                    'noidleswap_reason': 'Federated experiment',
114                    'noswapin': True,
115                    'wait': True
116                    }
117            if gid is not None:
118                params['group'] = gid
119            if self.log:
120                self.log.info("[make_null_experiment]: Creating experiment")
121            code, value = self.emulab_call('experiment.startexp', params)
122
123            if self.log:
124                if code == 0: 
125                    self.log.info('[make_null_experiment]: Create succeeded')
126                else: 
127                    self.log.error('[make_null_experiment]: Create failed: %s' \
128                            % value)
129
130            return code == 0
131
132    def swap_exp(self, pid, eid, direction='out', wait=True):
133        """
134        Swap experiment in.
135        """
136        if self.debug:
137            if self.log:
138                self.log.info("[swap_exp]: (debug) Swapping %s %s" % \
139                        (eid, direction))
140            return True
141        else:
142            if self.log:
143                self.log.info("[swap_exp]: Swapping %s %s" % (eid, direction))
144            params = {
145                    'proj': pid,
146                    'exp': eid,
147                    'direction': direction,
148                    'wait': wait,
149                    }
150            code, value = self.emulab_call('experiment.swapexp', params)
151
152            if self.log:
153                if code == 0: self.log.info('[swap_exp]: Swap succeeded')
154                else: self.log.error('[swap_exp]: Swap failed: %s' % value)
155
156        return code == 0
157
158    def modify_exp(self, pid, eid, tcl, wait=True):
159        if self.debug:
160            self.log.info("[modify_exp]: (debug) Modifying %s" % eid)
161            return True
162        else:
163            self.log.info("[modify_exp]: Modifying %s" % eid)
164            params = {
165                    'proj': pid,
166                    'exp': eid,
167                    'nsfilestr': tcl,
168                    'wait': wait,
169                    'reboot': True,
170                    'restart_eventsys': True,
171                    }
172            code, value = self.emulab_call('experiment.modify', params)
173            if self.log:
174                if code == 0: 
175                    self.log.info('[modify_exp]: Modify succeeded')
176                else: 
177                    self.log.error('[modify_exp]: Modify failed: %s' \
178                            % value)
179            return code == 0
180
181
182    def get_mapping(self, pid, eid):
183        """
184        Get the physical to virtual mapping from the expinfo command and save
185        it in the self.map member.
186        """
187
188        if self.debug:
189            if self.log:
190                self.log.info("[get_mapping] (debug) Generating mapping")
191                return True
192        else:
193            if self.log:
194                self.log.info("[get_mapping] Generating mapping")
195
196            params = {
197                    'proj': pid,
198                    'exp': eid,
199                    'aspect': 'mapping'
200                    }
201            code, nodes = self.emulab_call('experiment.info', params)
202            if code ==0:
203                for k, v in nodes.items():
204                    if v.get('erole', False) and 'pnode' in v:
205                        self.node[k] = v['pnode']
206                if self.log:
207                    self.log.info("Mapping complete")
208                return True
209            else:
210                raise service_error(service_error.internal,
211                        "Cannot get node mapping of segment:%s/%s" % (pid, eid))
212
Note: See TracBrowser for help on using the repository browser.