source: fedd/federation/proxy_protogeni_segment.py @ 4e9719b

axis_examplecompt_changesinfo-opsversion-3.01version-3.02
Last change on this file since 4e9719b was 4e9719b, checked in by Ted Faber <faber@…>, 14 years ago

SEER stuff

  • Property mode set to 100644
File size: 22.2 KB
Line 
1#!/usr/local/bin/python
2
3import sys, os
4import re
5
6import tempfile
7import subprocess
8import logging 
9import time
10import random
11import string
12import signal
13
14import xml.parsers.expat
15from threading import Thread
16
17from proxy_segment import proxy_segment
18from service_error import service_error
19from remote_service import service_caller
20from util import fedd_ssl_context
21
22import topdl
23
24class segment_base(proxy_segment):
25    class ProtoGENIError(Exception): 
26        def __init__(self, op, code, output):
27            Exception.__init__(self, output)
28            self.op = op
29            self.code = code
30            self.output = output
31
32    def __init__(self, log=None, keyfile=None, debug=False, 
33            ch_url=None, sa_url=None, cm_url=None):
34        proxy_segment.__init__(self, log=log, keyfile=keyfile, debug=debug)
35
36        self.ProtoGENIError = start_segment.ProtoGENIError
37        self.ch_url = ch_url
38        self.sa_url = sa_url
39        self.cm_url = cm_url
40
41        self.call_SetValue = service_caller('SetValue')
42
43        self.debug_fail = ['Resolve']
44        self.debug_response = {
45                'RedeemTicket': ("XML blob1", "XML blob2"),
46                'SliceStatus': { 'status': 'ready' },
47            }
48
49
50    def pg_call(self, url, method, params, context):
51        max_retries = 5
52        retries = 0
53
54        s = service_caller(method, request_body_name="", strict=False)
55        self.log.debug("Calling %s %s" % (url, method))
56        if not self.debug:
57            while retries < max_retries:
58                r = s.call_xmlrpc_service(url, params, context=context)
59                code = r.get('code', -1)
60                if code == 0:
61                    # Success leaves the loop here
62                    return r.get('value', None)
63                elif code == 14 and retries +1 < max_retries:
64                    # Busy resource
65                    retries+= 1
66                    self.log.info("Resource busy, retrying in 30 secs")
67                    time.sleep(30)
68                else:
69                    # NB: out of retries falls through to here
70                    raise self.ProtoGENIError(op=method, 
71                            code=r.get('code', 'unknown'), 
72                            output=r.get('output', 'No output'))
73        else:
74            if method in self.debug_fail:
75                raise self.ProtoGENIError(op=method, code='unknown',
76                        output='No output')
77            elif self.debug_response.has_key(method):
78                return self.debug_response[method]
79            else:
80                return "%s XML blob" % method
81
82
83class start_segment(segment_base):
84    def __init__(self, log=None, keyfile=None, debug=False, 
85            ch_url=None, sa_url=None, cm_url=None):
86        segment_base.__init__(self, log=log, keyfile=keyfile, debug=debug,
87                ch_url=cm_url, sa_url=sa_url, cm_url=cm_url)
88
89
90    # Turn the manifest into a dict were each virtual nodename (i.e. the topdl
91    # name) has an entry with the allocated machine in hostname and the
92    # interfaces in 'interfaces'.  I love having XML parser code lying around.
93    def manifest_to_dict(self, manifest, ignore_debug=False):
94        if self.debug and not ignore_debug: 
95            self.log.debug("Returning null manifest dict")
96            return { }
97
98        # The class allows us to keep a little state - the dict under
99        # consteruction and the current entry in that dict for the interface
100        # element code.
101        class manifest_parser:
102            def __init__(self):
103                self.d = { }
104                self.current_key=None
105
106            # If the element is a node, create a dict entry for it.  If it's an
107            # interface inside a node, add an entry in the interfaces list with
108            # the virtual name and component id.
109            def start_element(self, name, attrs):
110                if name == 'node':
111                    self.current_key = attrs.get('virtual_id',"")
112                    if self.current_key:
113                        self.d[self.current_key] = {
114                                'hostname': attrs.get('hostname', None),
115                                'interfaces': { }
116                                }
117                elif name == 'interface' and self.current_key:
118                    self.d[self.current_key]['interfaces']\
119                            [attrs.get('virtual_id','')] = \
120                            attrs.get('component_id', None)
121            #  When a node is finished, clear current_key
122            def end_element(self, name):
123                if name == 'node': self.current_key = None
124
125
126        mp = manifest_parser()
127        p = xml.parsers.expat.ParserCreate()
128        # These are bound to the class we just created
129        p.StartElementHandler = mp.start_element
130        p.EndElementHandler = mp.end_element
131
132        p.Parse(manifest)
133        return mp.d
134
135
136    def generate_portal_configs(self, parent, topo, pubkey_base, 
137            secretkey_base, tmpdir, master, leid, connInfo, services, nodes):
138
139        def conninfo_to_dict(key, info):
140            """
141            Make a cpoy of the connection information about key, and flatten it
142            into a single dict by parsing out any feddAttrs.
143            """
144
145            rv = None
146            for i in info:
147                if key == i.get('portal', "") or \
148                        key in [e.get('element', "") \
149                        for e in i.get('member', [])]:
150                    rv = i.copy()
151                    break
152
153            else:
154                return rv
155
156            if 'fedAttr' in rv:
157                for a in rv['fedAttr']:
158                    attr = a.get('attribute', "")
159                    val = a.get('value', "")
160                    if attr and attr not in rv:
161                        rv[attr] = val
162                del rv['fedAttr']
163            return rv
164
165        # XXX: un hardcode this
166        def client_null(f, s):
167            print >>f, "Service: %s" % s['name']
168
169        def client_smb(f, s):
170            print >>f, "Service: %s" % s['name']
171            smbshare = None
172            smbuser = None
173            smbproj = None
174            for a in s.get('fedAttr', []):
175                if a.get('attribute', '') == 'SMBSHARE':
176                    smbshare = a.get('value', None)
177                elif a.get('attribute', '') == 'SMBUSER':
178                    smbuser = a.get('value', None)
179                elif a.get('attribute', '') == 'SMBPROJ':
180                    smbproj = a.get('value', None)
181
182            if all((smbshare, smbuser, smbproj)):
183                print >>f, "SMBshare: %s" % smbshare
184                print >>f, "ProjectUser: %s" % smbuser
185                print >>f, "ProjectName: %s" % smbproj
186
187        client_service_out = {
188                'SMB': client_smb,
189                'tmcd': client_null,
190                'seer': client_null,
191                'userconfig': client_null,
192            }
193
194        def server_port(f, s):
195            p = urlparse(s.get('server', 'http://localhost'))
196            print >>f, 'port: remote:%s:%s:%s' % (p.port, p.hostname, p.port) 
197
198        def server_null(f,s): pass
199
200        def server_seer(f, s):
201            print >>f, 'seer: true'
202
203        server_service_out = {
204                'SMB': server_port,
205                'tmcd': server_port,
206                'userconfig': server_null,
207                'seer': server_seer,
208            }
209        # XXX: end un hardcode this
210
211
212        seer_out = False
213        client_out = False
214        for e in [ e for e in topo.elements \
215                if isinstance(e, topdl.Computer) and e.get_attribute('portal')]:
216            myname = e.name[0]
217            type = e.get_attribute('portal_type')
218            testbed = e.get_attribute('testbed')
219
220            info = conninfo_to_dict(myname, connInfo)
221
222            if not info:
223                raise service_error(service_error.req,
224                        "No connectivity info for %s" % myname)
225
226            # Translate to physical name (ProtoGENI doesn't have DNS)
227            physname = nodes.get(myname, {'hostname': myname})['hostname']
228            peer = info.get('peer', "")
229            ldomain = parent.domain;
230
231            mexp = info.get('masterexperiment',"")
232            mproj, meid = mexp.split("/", 1)
233            mdomain = info.get('masterdomain',"")
234            muser = info.get('masteruser','root')
235            smbshare = info.get('smbshare', 'USERS')
236            ssh_port = info.get('ssh_port', '22')
237
238            active = info.get('active', 'False')
239
240            cfn = "%s/%s.gw.conf" % (tmpdir, myname.lower())
241            tunnelconfig = parent.attrs.has_key('TunnelCfg')
242            try:
243                f = open(cfn, "w")
244                if active == 'True':
245                    print >>f, "active: True"
246                    print >>f, "ssh_port: %s" % ssh_port
247                    if type in ('control', 'both'):
248                        for s in [s for s in services \
249                                if s.get('name', "") in parent.imports]:
250                            server_service_out[s['name']](f, s)
251
252                if tunnelconfig:
253                    print >>f, "tunnelip: %s" % tunnelconfig
254                print >>f, "peer: %s" % peer.lower()
255                print >>f, "ssh_pubkey: /usr/local/federation/etc/%s" % \
256                        pubkey_base
257                print >>f, "ssh_privkey: /usr/local/federation/etc/%s" % \
258                        secretkey_base
259                f.close()
260            except IOError, e:
261                raise service_error(service_error.internal,
262                        "Can't write protal config %s: %s" % (cfn, e))
263
264            if not client_out and type in ('control', 'both'):
265                try:
266                    f = open("%s/client.conf" % tmpdir, "w")
267                    print >>f, "ControlGateway: %s" % physname.lower()
268                    for s in services:
269                        if s.get('name',"") in parent.imports and \
270                                s.get('visibility','') == 'import':
271                            client_service_out[s['name']](f, s)
272                    # Seer uses this to find credentials in the shared project
273                    # dir.
274                    print >>f, "ExperimentID: %s/%s" % (mproj, meid)
275                    if testbed == master:
276                        print >>f, "SEERBase: True"
277                    f.close()
278                except IOError, e:
279                    raise service_error(service_error.internal,
280                            "Cannot write client.conf: %s" %s)
281                client_out = True
282
283
284
285    def export_store_info(self, cf, nodes, ssh_port, connInfo):
286        """
287        For the export requests in the connection info, install the peer names
288        at the experiment controller via SetValue calls.
289        """
290
291        for c in connInfo:
292            for p in [ p for p in c.get('parameter', []) \
293                    if p.get('type', '') == 'output']:
294
295                if p.get('name', '') == 'peer':
296                    k = p.get('key', None)
297                    surl = p.get('store', None)
298                    if surl and k and k.index('/') != -1:
299                        if self.debug:
300                            req = { 'name': k, 'value': 'debug' }
301                            self.call_SetValue(surl, req, cf)
302                        else:
303                            value = nodes.get(k[k.index('/')+1:], 
304                                    {}).get('hostname',"")
305                            if value:
306                                req = { 'name': k, 'value': value }
307                                self.call_SetValue(surl, req, cf)
308                            else:
309                                self.log.error("No hostname for %s" % \
310                                        k[k.index('/'):])
311                    else:
312                        self.log.error("Bad export request: %s" % p)
313                elif p.get('name', '') == 'ssh_port':
314                    k = p.get('key', None)
315                    surl = p.get('store', None)
316                    if surl and k:
317                        req = { 'name': k, 'value': ssh_port }
318                        self.call_SetValue(surl, req, cf)
319                    else:
320                        self.log.error("Bad export request: %s" % p)
321                else:
322
323                    self.log.error("Unknown export parameter: %s" % \
324                            p.get('name'))
325                    continue
326
327    def configure_nodes(self, topo, nodes, user, host, sshd, sshd_config,
328            gate_cmd, node_cmd, pubkey, secretkey, federation_software, 
329            portal_software, stagingdir, tmpdir):
330
331        fed_dir = "/usr/local/federation"
332        ssh = "/usr/bin/ssh -n -i .ssh/id_rsa -o 'ForwardX11 no' -o 'StrictHostKeyChecking no' "
333        scp = "/usr/bin/scp -i .ssh/id_rsa -o 'ForwardX11 no' -o 'StrictHostKeyChecking no' "
334        ifconfig = "/sbin/ifconfig"
335        tar = "/bin/tar"
336
337        for e in [ e for e in topo.elements if isinstance(e, topdl.Computer)]:
338            vname = e.name[0]
339            node = nodes.get(vname, {})
340            pname = node.get('hostname', None)
341            if pname:
342                script = open("%s/%s.startup" %(tmpdir, pname), "w")
343                # Reset the interfaces to the ones in the topo file
344                for i in [ i for i in e.interface \
345                        if not i.get_attribute('portal')]:
346                    pinf = node['interfaces'].get(i.name, None)
347                    addr = i.get_attribute('ip4_address') 
348                    netmask = i.get_attribute('ip4_netmask') or '255.255.255.0'
349                    if pinf and addr:
350                        print >>script, \
351                                "%s %s %s netmask %s"  % \
352                                (ifconfig, pinf, addr, netmask)
353                    else:
354                        self.log.error("Missing interface or address for %s" \
355                                % i.name)
356                   
357                for l, f in federation_software:
358                    base = os.path.basename(f)
359                    print >>script, "%s %s@%s:%s/%s ." % \
360                            (scp, user, host, stagingdir, base)
361                    print >>script, \
362                            "%s -C %s -xzf %s" % (tar, l, base)
363
364                for s in e.software:
365                    # XXX: Just tarfiles for now
366                    if not (s.location and s.install):
367                        continue
368                    s_base = s.location.rpartition('/')[2]
369                    print >>script, "%s %s@%s:%s/%s ." % \
370                            (scp, user, host, stagingdir, s_base)
371                    print >>script, \
372                            "%s -C %s -xzf %s" % (tar, s.install, s_base)
373                for f in ('hosts', pubkey, secretkey, 'client.conf', 
374                        'userconf'):
375                    print >>script, "%s %s@%s:%s/%s %s/etc" % \
376                            (scp, user, host, stagingdir, f, fed_dir)
377                if sshd:
378                    print >>script, "%s %s@%s:%s %s/bin" % \
379                            (scp, user, host, sshd, fed_dir)
380                if sshd_config:
381                    print >>script, "%s %s@%s:%s %s/etc" % \
382                            (scp, user, host, sshd_config, fed_dir)
383                # Look in tmpdir to get the names.  They've all been copied
384                # into the (remote) staging dir
385                if os.access("%s/%s.gw.conf" % (tmpdir, vname), os.R_OK):
386                    print >>script, "%s %s@%s:%s/%s.gw.conf %s/etc" % \
387                            (scp, user, host, stagingdir, vname, fed_dir)
388
389                # Hackery dackery dock: the ProtoGENI python is really ancient.
390                # Get a modern version (though packaged for Mandrake (remember
391                # Mandrake?  good times, good times)) and install it for SEER.
392                python_rpm="python2.4-2.4-1pydotorg.i586.rpm"
393                print >>script, "%s %s@%s:%s/%s ." % \
394                        (scp, user, host, stagingdir, python_rpm)
395                print >>script, "rpm --install ./%s" % python_rpm
396                print >>script, "rm /usr/bin/python"
397                print >>script, "ln /usr/bin/python2.4 /usr/bin/python"
398                # Back to less hacky stuff
399
400                # Start commands
401                if e.get_attribute('portal') and gate_cmd:
402                    # Install portal software
403                    for l, f in portal_software:
404                        base = os.path.basename(f)
405                        print >>script, "%s %s@%s:%s/%s ." % \
406                                (scp, user, host, stagingdir, base)
407                        print >>script, \
408                                "%s -C %s -xzf %s" % (tar, l, base)
409
410                    # Portals never have a user-specified start command
411                    print >>script, gate_cmd
412                elif node_cmd:
413                    # XXX: debug
414                    print >>script, "sudo perl -I%s/lib %s/bin/import_key.pl /users/%s/.ssh/authorized_keys /root/.ssh/authorized_keys" % (fed_dir, fed_dir, user)
415                    # XXX: debug
416                    # start routing on nodes
417                    print >>script, "sudo perl %s/bin/protogeni_routing.pl" % \
418                            fed_dir
419                    if e.get_attribute('startup'):
420                        print >>script, "%s \\$USER '%s'" % \
421                                (node_cmd, e.get_attribute('startup'))
422                    else:
423                        print >>script, node_cmd
424                script.close()
425                if not self.scp_file("%s/%s.startup" % (tmpdir, pname), 
426                        user, pname):
427                    self.log.error("Could not copy script to %s" % pname)
428            else:
429                self.log.error("Unmapped node: %s" % vname)
430
431    def start_node(self, user, host, node):
432        # Place an identity on the node so that the copying can succeed
433        self.ssh_cmd(user, host, "scp .ssh/id_rsa %s:.ssh" % node)
434        self.ssh_cmd(user, node, "sudo /bin/sh ./%s.startup &" % node)
435
436    def start_nodes(self, user, host, nodes):
437        threads = [ ]
438        for n in nodes:
439            t = Thread(target=self.start_node, args=(user, host, n))
440            t.start()
441            threads.append(t)
442
443        done = [not t.isAlive() for t in threads]
444        while not all(done):
445            self.log.info("Waiting for threads %s" % done)
446            time.sleep(10)
447            done = [not t.isAlive() for t in threads]
448
449
450
451
452    def __call__(self, parent, aid, user, rspec, pubkey, secretkey, master,
453            ename, stagingdir, tmpdir, certfile, certpw, export_certfile, topo,
454            connInfo, services, timeout=0):
455        """
456        Start a sub-experiment on a federant.
457
458        Get the current state, modify or create as appropriate, ship data
459        and configs and start the experiment.  There are small ordering
460        differences based on the initial state of the sub-experiment.
461        """
462
463        def random_slicename(user):
464            slicename = user
465            for i in range(0,5):
466                slicename += random.choice(string.ascii_letters)
467            return slicename
468
469        host = parent.staging_host
470        ctxt = fedd_ssl_context(my_cert=certfile, password=certpw)
471        # Local software dir
472        lsoftdir = "%s/software" % tmpdir
473
474        # Open up a temporary file to contain a script for setting up the
475        # filespace for the new experiment.
476        self.log.info("[start_segment]: creating script file")
477        try:
478            sf, scriptname = tempfile.mkstemp()
479            scriptfile = os.fdopen(sf, 'w')
480        except IOError:
481            return False
482
483        scriptbase = os.path.basename(scriptname)
484
485        # Script the filesystem changes
486        print >>scriptfile, "/bin/rm -rf %s" % stagingdir
487        print >>scriptfile, 'mkdir -p %s' % stagingdir
488        print >>scriptfile, "rm -f %s" % scriptbase
489        scriptfile.close()
490
491        # Move the script to the remote machine
492        # XXX: could collide tempfile names on the remote host
493        if self.scp_file(scriptname, user, host, scriptbase):
494            os.remove(scriptname)
495        else:
496            return False
497
498        # Execute the script (and the script's last line deletes it)
499        if not self.ssh_cmd(user, host, "sh -x %s" % scriptbase):
500            return False
501
502        try:
503            gcred = self.pg_call(self.sa_url, 'GetCredential', {}, ctxt)
504        except self.ProtoGENIError, e:
505            raise service_error(service_error.federant,
506                    "ProtoGENI: %s" % e)
507        # Find a slicename not in use
508        slicename = "fabereGpgL"
509        while True:
510            slicename = random_slicename(user)
511            try:
512                param = {
513                        'credential': gcred, 
514                        'hrn': slicename,
515                        'type': 'Slice'
516                        }
517                self.pg_call(self.sa_url, 'Resolve', param, ctxt)
518            except self.ProtoGENIError, e:
519                print e
520                break
521
522        self.log.info("Creating %s" % slicename)
523        f = open("./rspec", "w")
524        print >>f, "%s" % rspec
525        f.close()
526        # Create the slice and allocate resources.  If any of this stuff fails,
527        # the allocations will time out on PG in short order, so we just raise
528        # the service_error.
529        try:
530            param = {
531                    'credential': gcred, 
532                    'hrn': slicename,
533                    'type': 'Slice'
534                    }
535            slice_cred = self.pg_call(self.sa_url, 'Register', param, ctxt)
536            f = open("./slice_cred", "w")
537            print >>f, slice_cred
538            f.close()
539            # Populate the ssh keys (let PG format them)
540            param = {
541                    'credential': gcred, 
542                    }
543            keys =  self.pg_call(self.sa_url, 'GetKeys', param, ctxt)
544            # Grab and redeem a ticket
545            param = {
546                    'credential': slice_cred, 
547                    'rspec': rspec,
548                    }
549            ticket = self.pg_call(self.cm_url, 'GetTicket', param, ctxt)
550            f = open("./ticket", "w")
551            print >>f, ticket
552            f.close()
553            param = { 
554                    'credential': slice_cred, 
555                    'keys': keys,
556                    'ticket': ticket,
557                    }
558            sliver_cred, manifest = self.pg_call(self.cm_url, 
559                    'RedeemTicket', param, ctxt)
560            f = open("./sliver_cred", "w")
561            print >>f, sliver_cred
562            f.close()
563            f = open("./manifest", "w")
564            print >>f, manifest
565            f.close()
566            # start 'em up
567            param = { 
568                    'credential': sliver_cred,
569                    }
570            self.pg_call(self.cm_url, 'StartSliver', param, ctxt)
571        except self.ProtoGENIError, e:
572            raise service_error(service_error.federant,
573                    "ProtoGENI: %s %s" % (e.code, e))
574
575        # With manifest in hand, we can export the portal node names.
576        nodes = self.manifest_to_dict(manifest)
577        self.export_store_info(export_certfile, nodes, parent.ssh_port,
578                connInfo)
579        self.generate_portal_configs(parent, topo, pubkey, secretkey, tmpdir, 
580                master, ename, connInfo, services, nodes)
581
582        # Copy software to the staging machine (done after generation to copy
583        # those, too)
584        for d in (tmpdir, lsoftdir):
585            if os.path.isdir(d):
586                for f in os.listdir(d):
587                    if not os.path.isdir("%s/%s" % (d, f)):
588                        if not self.scp_file("%s/%s" % (d, f), 
589                                user, host, "%s/%s" % (stagingdir, f)):
590                            self.log.error("Scp failed")
591                            return False
592
593
594        # Now we wait for the nodes to start on PG
595        status = 'notready'
596        try:
597            while status == 'notready':
598                param = { 
599                        'credential': slice_cred
600                        }
601                r = self.pg_call(self.cm_url, 'SliceStatus', param, ctxt)
602                print r
603                status = r.get('status', 'notready')
604                if status == 'notready':
605                    time.sleep(30)
606        except self.ProtoGENIError, e:
607            raise service_error(service_error.federant,
608                    "ProtoGENI: %s %s" % (e.code, e))
609
610        if status == 'failed':
611            self.log.error('Sliver failed to start on ProtoGENI')
612            try:
613                param = { 
614                        'credential': slice_cred
615                        }
616                self.pg_call(self.cm_url, 'DeleteSliver', param, ctxt)
617            except self.ProtoGENIError, e:
618                raise service_error(service_error.federant,
619                    "ProtoGENI: %s" % e)
620            return False
621        else:
622            parent.state_lock.acquire()
623            parent.allocation[aid]['slice_name'] = slicename
624            parent.allocation[aid]['slice_credential'] = slice_cred
625            parent.allocation[aid]['sliver_credential'] = sliver_cred
626            parent.allocation[aid]['manifest'] = manifest
627            parent.allocation[aid]['certfile'] = certfile
628            parent.allocation[aid]['certpw'] = certpw
629            parent.write_state()
630            parent.state_lock.release()
631
632        # The startcmds for portals and standard nodes (the Master Slave
633        # distinction is going away)
634        gate_cmd = parent.attrs.get('SlaveConnectorStartCmd', '/bin/true')
635        node_cmd = parent.attrs.get('SlaveNodeStartCmd', 'bin/true')
636
637        # Now we have configuration to do for ProtoGENI
638        self.configure_nodes(topo, nodes, user, parent.staging_host,
639                parent.sshd, parent.sshd_config, gate_cmd, node_cmd, 
640                pubkey, secretkey, parent.federation_software, 
641                parent.portal_software, stagingdir, tmpdir)
642
643        self.start_nodes(user, parent.staging_host, 
644                [ n['hostname'] for n in nodes.values()])
645
646        # Everything has gone OK.
647        return True
648
649class stop_segment(segment_base):
650    def __init__(self, log=None, keyfile=None, debug=False, 
651            ch_url=None, sa_url=None, cm_url=None):
652        segment_base.__init__(self, log=log, keyfile=keyfile, debug=debug,
653                ch_url=cm_url, sa_url=sa_url, cm_url=cm_url)
654
655    def __call__(self, parent, user, stagingdir, slice_cred, certfile, certpw):
656        """
657        Stop a sub experiment by calling swapexp on the federant
658        """
659        host = parent.staging_host
660        rv = False
661        try:
662            # Clean out tar files: we've gone over quota in the past
663            if stagingdir:
664                self.ssh_cmd(user, host, "rm -rf %s" % stagingdir)
665            if slice_cred:
666                self.log.error('Removing Sliver on ProtoGENI')
667                ctxt = fedd_ssl_context(my_cert=certfile, password=certpw)
668                try:
669                    param = { 
670                            'credential': slice_cred
671                            }
672                    self.pg_call(self.cm_url, 'DeleteSlice', param, ctxt)
673                except self.ProtoGENIError, e:
674                    raise service_error(service_error.federant,
675                        "ProtoGENI: %s" % e)
676            return True
677        except self.ssh_cmd_timeout:
678            rv = False
679        return rv
680
681class renew_segment(segment_base):
682    def __init__(self, log=None, debug=False, keyfile=None,
683            ch_url=None, sa_url=None, cm_url=None):
684        segment_base.__init__(self, log=log, keyfile=keyfile, debug=debug,
685                ch_url=cm_url, sa_url=sa_url, cm_url=cm_url)
686
687    def __call__(self, name, scred, interval, certfile, certpw):
688        ctxt = fedd_ssl_context(my_cert=certfile, password=certpw)
689        try:
690            expiration = time.strftime("%Y%m%dT%H:%M:%S",
691                    time.gmtime(time.time() + interval))
692            cred = self.pg_call(self.sa_url, 'GetCredential', {}, ctxt)
693
694            param = {
695                    'credential': scred,
696                    'expiration': expiration
697                    }
698            r = self.pg_call(self.sa_url, 'RenewSlice', param, ctxt)
699            param = {
700                    'credential': cred,
701                    'hrn': name,
702                    'type': 'Slice',
703                    }
704            slice = self.pg_call(self.sa_url, 'Resolve', param, ctxt)
705            uuid = slice.get('uuid', None)
706            if uuid == None:
707                sys.exit('No uuid for %s' % slicename)
708
709            print 'Calling GetCredential (uuid)'
710            param = {
711                    'credential': cred,
712                    'uuid': uuid,
713                    'type': 'Slice',
714                    }
715            new_scred = self.pg_call(self.sa_url, 'GetCredential', param, ctxt)
716            f = open('./new_slice_cred', 'w')
717            print >>f, new_scred
718            f.close()
719
720        except self.ProtoGENIError, e:
721            self.log.error("Failed to extend slice %s: %s" % (name, e))
722            return None
723        try:
724            print 'Calling RenewSlice (CM)'
725            param = {
726                    'credential': new_scred,
727                    }
728            r = self.pg_call(self.cm_url, 'RenewSlice', param, ctxt)
729        except self.ProtoGENIError, e:
730            self.log.warn("Failed to renew sliver for %s: %s" % (name, e))
731
732        return new_scred
733   
Note: See TracBrowser for help on using the repository browser.