source: fedd/federation/proxy_protogeni_segment.py @ 86a7bb8

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

Use the more general fedkit routing setup and make sure that installed tarballs have a place to go.

  • Property mode set to 100644
File size: 22.4 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        mkdir="/bin/mkdir"
337
338        for e in [ e for e in topo.elements if isinstance(e, topdl.Computer)]:
339            vname = e.name[0]
340            node = nodes.get(vname, {})
341            pname = node.get('hostname', None)
342            if pname:
343                script = open("%s/%s.startup" %(tmpdir, pname), "w")
344                # Reset the interfaces to the ones in the topo file
345                for i in [ i for i in e.interface \
346                        if not i.get_attribute('portal')]:
347                    pinf = node['interfaces'].get(i.name, None)
348                    addr = i.get_attribute('ip4_address') 
349                    netmask = i.get_attribute('ip4_netmask') or '255.255.255.0'
350                    if pinf and addr:
351                        print >>script, \
352                                "%s %s %s netmask %s"  % \
353                                (ifconfig, pinf, addr, netmask)
354                    else:
355                        self.log.error("Missing interface or address for %s" \
356                                % i.name)
357                   
358                for l, f in federation_software:
359                    base = os.path.basename(f)
360                    print >>script, "%s %s@%s:%s/%s ." % \
361                            (scp, user, host, stagingdir, base)
362                    # Make sure that there's a directory there in which to
363                    # untar.
364                    print >>script, "%s -p %s" % (mkdir, l)
365                    print >>script, \
366                            "%s -C %s -xzf %s" % (tar, l, base)
367
368                for s in e.software:
369                    # XXX: Just tarfiles for now
370                    if not (s.location and s.install):
371                        continue
372                    s_base = s.location.rpartition('/')[2]
373                    print >>script, "%s %s@%s:%s/%s ." % \
374                            (scp, user, host, stagingdir, s_base)
375                    # Make sure that there's a directory there in which to
376                    # untar.
377                    print >>script, "%s -p %s" % (mkdir, s.install)
378                    print >>script, \
379                            "%s -C %s -xzf %s" % (tar, s.install, s_base)
380                for f in ('hosts', pubkey, secretkey, 'client.conf', 
381                        'userconf'):
382                    print >>script, "%s %s@%s:%s/%s %s/etc" % \
383                            (scp, user, host, stagingdir, f, fed_dir)
384                if sshd:
385                    print >>script, "%s %s@%s:%s %s/bin" % \
386                            (scp, user, host, sshd, fed_dir)
387                if sshd_config:
388                    print >>script, "%s %s@%s:%s %s/etc" % \
389                            (scp, user, host, sshd_config, fed_dir)
390                # Look in tmpdir to get the names.  They've all been copied
391                # into the (remote) staging dir
392                if os.access("%s/%s.gw.conf" % (tmpdir, vname), os.R_OK):
393                    print >>script, "%s %s@%s:%s/%s.gw.conf %s/etc" % \
394                            (scp, user, host, stagingdir, vname, fed_dir)
395
396                # Hackery dackery dock: the ProtoGENI python is really ancient.
397                # Get a modern version (though packaged for Mandrake (remember
398                # Mandrake?  good times, good times)) and install it for SEER.
399                python_rpm="python2.4-2.4-1pydotorg.i586.rpm"
400                print >>script, "%s %s@%s:%s/%s ." % \
401                        (scp, user, host, stagingdir, python_rpm)
402                print >>script, "rpm --install ./%s" % python_rpm
403                print >>script, "rm /usr/bin/python"
404                print >>script, "ln /usr/bin/python2.4 /usr/bin/python"
405                # Back to less hacky stuff
406
407                # Start commands
408                if e.get_attribute('portal') and gate_cmd:
409                    # Install portal software
410                    for l, f in portal_software:
411                        base = os.path.basename(f)
412                        print >>script, "%s %s@%s:%s/%s ." % \
413                                (scp, user, host, stagingdir, base)
414                        print >>script, \
415                                "%s -C %s -xzf %s" % (tar, l, base)
416
417                    # Portals never have a user-specified start command
418                    print >>script, gate_cmd
419                elif node_cmd:
420                    # XXX: debug
421                    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)
422                    # XXX: debug
423                    if e.get_attribute('startup'):
424                        print >>script, "%s \\$USER '%s'" % \
425                                (node_cmd, e.get_attribute('startup'))
426                    else:
427                        print >>script, node_cmd
428                script.close()
429                if not self.scp_file("%s/%s.startup" % (tmpdir, pname), 
430                        user, pname):
431                    self.log.error("Could not copy script to %s" % pname)
432            else:
433                self.log.error("Unmapped node: %s" % vname)
434
435    def start_node(self, user, host, node):
436        # Place an identity on the node so that the copying can succeed
437        self.ssh_cmd(user, host, "scp .ssh/id_rsa %s:.ssh" % node)
438        self.ssh_cmd(user, node, "sudo /bin/sh ./%s.startup &" % node)
439
440    def start_nodes(self, user, host, nodes):
441        threads = [ ]
442        for n in nodes:
443            t = Thread(target=self.start_node, args=(user, host, n))
444            t.start()
445            threads.append(t)
446
447        done = [not t.isAlive() for t in threads]
448        while not all(done):
449            self.log.info("Waiting for threads %s" % done)
450            time.sleep(10)
451            done = [not t.isAlive() for t in threads]
452
453
454
455
456    def __call__(self, parent, aid, user, rspec, pubkey, secretkey, master,
457            ename, stagingdir, tmpdir, certfile, certpw, export_certfile, topo,
458            connInfo, services, timeout=0):
459        """
460        Start a sub-experiment on a federant.
461
462        Get the current state, modify or create as appropriate, ship data
463        and configs and start the experiment.  There are small ordering
464        differences based on the initial state of the sub-experiment.
465        """
466
467        def random_slicename(user):
468            slicename = user
469            for i in range(0,5):
470                slicename += random.choice(string.ascii_letters)
471            return slicename
472
473        host = parent.staging_host
474        ctxt = fedd_ssl_context(my_cert=certfile, password=certpw)
475        # Local software dir
476        lsoftdir = "%s/software" % tmpdir
477
478        # Open up a temporary file to contain a script for setting up the
479        # filespace for the new experiment.
480        self.log.info("[start_segment]: creating script file")
481        try:
482            sf, scriptname = tempfile.mkstemp()
483            scriptfile = os.fdopen(sf, 'w')
484        except IOError:
485            return False
486
487        scriptbase = os.path.basename(scriptname)
488
489        # Script the filesystem changes
490        print >>scriptfile, "/bin/rm -rf %s" % stagingdir
491        print >>scriptfile, 'mkdir -p %s' % stagingdir
492        print >>scriptfile, "rm -f %s" % scriptbase
493        scriptfile.close()
494
495        # Move the script to the remote machine
496        # XXX: could collide tempfile names on the remote host
497        if self.scp_file(scriptname, user, host, scriptbase):
498            os.remove(scriptname)
499        else:
500            return False
501
502        # Execute the script (and the script's last line deletes it)
503        if not self.ssh_cmd(user, host, "sh -x %s" % scriptbase):
504            return False
505
506        try:
507            gcred = self.pg_call(self.sa_url, 'GetCredential', {}, ctxt)
508        except self.ProtoGENIError, e:
509            raise service_error(service_error.federant,
510                    "ProtoGENI: %s" % e)
511        # Find a slicename not in use
512        slicename = "fabereGpgL"
513        while True:
514            slicename = random_slicename(user)
515            try:
516                param = {
517                        'credential': gcred, 
518                        'hrn': slicename,
519                        'type': 'Slice'
520                        }
521                self.pg_call(self.sa_url, 'Resolve', param, ctxt)
522            except self.ProtoGENIError, e:
523                print e
524                break
525
526        self.log.info("Creating %s" % slicename)
527        f = open("./rspec", "w")
528        print >>f, "%s" % rspec
529        f.close()
530        # Create the slice and allocate resources.  If any of this stuff fails,
531        # the allocations will time out on PG in short order, so we just raise
532        # the service_error.
533        try:
534            param = {
535                    'credential': gcred, 
536                    'hrn': slicename,
537                    'type': 'Slice'
538                    }
539            slice_cred = self.pg_call(self.sa_url, 'Register', param, ctxt)
540            f = open("./slice_cred", "w")
541            print >>f, slice_cred
542            f.close()
543            # Populate the ssh keys (let PG format them)
544            param = {
545                    'credential': gcred, 
546                    }
547            keys =  self.pg_call(self.sa_url, 'GetKeys', param, ctxt)
548            # Grab and redeem a ticket
549            param = {
550                    'credential': slice_cred, 
551                    'rspec': rspec,
552                    }
553            ticket = self.pg_call(self.cm_url, 'GetTicket', param, ctxt)
554            f = open("./ticket", "w")
555            print >>f, ticket
556            f.close()
557            param = { 
558                    'credential': slice_cred, 
559                    'keys': keys,
560                    'ticket': ticket,
561                    }
562            sliver_cred, manifest = self.pg_call(self.cm_url, 
563                    'RedeemTicket', param, ctxt)
564            f = open("./sliver_cred", "w")
565            print >>f, sliver_cred
566            f.close()
567            f = open("./manifest", "w")
568            print >>f, manifest
569            f.close()
570            # start 'em up
571            param = { 
572                    'credential': sliver_cred,
573                    }
574            self.pg_call(self.cm_url, 'StartSliver', param, ctxt)
575        except self.ProtoGENIError, e:
576            raise service_error(service_error.federant,
577                    "ProtoGENI: %s %s" % (e.code, e))
578
579        # With manifest in hand, we can export the portal node names.
580        nodes = self.manifest_to_dict(manifest)
581        self.export_store_info(export_certfile, nodes, parent.ssh_port,
582                connInfo)
583        self.generate_portal_configs(parent, topo, pubkey, secretkey, tmpdir, 
584                master, ename, connInfo, services, nodes)
585
586        # Copy software to the staging machine (done after generation to copy
587        # those, too)
588        for d in (tmpdir, lsoftdir):
589            if os.path.isdir(d):
590                for f in os.listdir(d):
591                    if not os.path.isdir("%s/%s" % (d, f)):
592                        if not self.scp_file("%s/%s" % (d, f), 
593                                user, host, "%s/%s" % (stagingdir, f)):
594                            self.log.error("Scp failed")
595                            return False
596
597
598        # Now we wait for the nodes to start on PG
599        status = 'notready'
600        try:
601            while status == 'notready':
602                param = { 
603                        'credential': slice_cred
604                        }
605                r = self.pg_call(self.cm_url, 'SliceStatus', param, ctxt)
606                print r
607                status = r.get('status', 'notready')
608                if status == 'notready':
609                    time.sleep(30)
610        except self.ProtoGENIError, e:
611            raise service_error(service_error.federant,
612                    "ProtoGENI: %s %s" % (e.code, e))
613
614        if status == 'failed':
615            self.log.error('Sliver failed to start on ProtoGENI')
616            try:
617                param = { 
618                        'credential': slice_cred
619                        }
620                self.pg_call(self.cm_url, 'DeleteSliver', param, ctxt)
621            except self.ProtoGENIError, e:
622                raise service_error(service_error.federant,
623                    "ProtoGENI: %s" % e)
624            return False
625        else:
626            parent.state_lock.acquire()
627            parent.allocation[aid]['slice_name'] = slicename
628            parent.allocation[aid]['slice_credential'] = slice_cred
629            parent.allocation[aid]['sliver_credential'] = sliver_cred
630            parent.allocation[aid]['manifest'] = manifest
631            parent.allocation[aid]['certfile'] = certfile
632            parent.allocation[aid]['certpw'] = certpw
633            parent.write_state()
634            parent.state_lock.release()
635
636        # The startcmds for portals and standard nodes (the Master Slave
637        # distinction is going away)
638        gate_cmd = parent.attrs.get('SlaveConnectorStartCmd', '/bin/true')
639        node_cmd = parent.attrs.get('SlaveNodeStartCmd', 'bin/true')
640
641        # Now we have configuration to do for ProtoGENI
642        self.configure_nodes(topo, nodes, user, parent.staging_host,
643                parent.sshd, parent.sshd_config, gate_cmd, node_cmd, 
644                pubkey, secretkey, parent.federation_software, 
645                parent.portal_software, stagingdir, tmpdir)
646
647        self.start_nodes(user, parent.staging_host, 
648                [ n['hostname'] for n in nodes.values()])
649
650        # Everything has gone OK.
651        return True
652
653class stop_segment(segment_base):
654    def __init__(self, log=None, keyfile=None, debug=False, 
655            ch_url=None, sa_url=None, cm_url=None):
656        segment_base.__init__(self, log=log, keyfile=keyfile, debug=debug,
657                ch_url=cm_url, sa_url=sa_url, cm_url=cm_url)
658
659    def __call__(self, parent, user, stagingdir, slice_cred, certfile, certpw):
660        """
661        Stop a sub experiment by calling swapexp on the federant
662        """
663        host = parent.staging_host
664        rv = False
665        try:
666            # Clean out tar files: we've gone over quota in the past
667            if stagingdir:
668                self.ssh_cmd(user, host, "rm -rf %s" % stagingdir)
669            if slice_cred:
670                self.log.error('Removing Sliver on ProtoGENI')
671                ctxt = fedd_ssl_context(my_cert=certfile, password=certpw)
672                try:
673                    param = { 
674                            'credential': slice_cred
675                            }
676                    self.pg_call(self.cm_url, 'DeleteSlice', param, ctxt)
677                except self.ProtoGENIError, e:
678                    raise service_error(service_error.federant,
679                        "ProtoGENI: %s" % e)
680            return True
681        except self.ssh_cmd_timeout:
682            rv = False
683        return rv
684
685class renew_segment(segment_base):
686    def __init__(self, log=None, debug=False, keyfile=None,
687            ch_url=None, sa_url=None, cm_url=None):
688        segment_base.__init__(self, log=log, keyfile=keyfile, debug=debug,
689                ch_url=cm_url, sa_url=sa_url, cm_url=cm_url)
690
691    def __call__(self, name, scred, interval, certfile, certpw):
692        ctxt = fedd_ssl_context(my_cert=certfile, password=certpw)
693        try:
694            expiration = time.strftime("%Y%m%dT%H:%M:%S",
695                    time.gmtime(time.time() + interval))
696            cred = self.pg_call(self.sa_url, 'GetCredential', {}, ctxt)
697
698            param = {
699                    'credential': scred,
700                    'expiration': expiration
701                    }
702            r = self.pg_call(self.sa_url, 'RenewSlice', param, ctxt)
703            param = {
704                    'credential': cred,
705                    'hrn': name,
706                    'type': 'Slice',
707                    }
708            slice = self.pg_call(self.sa_url, 'Resolve', param, ctxt)
709            uuid = slice.get('uuid', None)
710            if uuid == None:
711                sys.exit('No uuid for %s' % slicename)
712
713            print 'Calling GetCredential (uuid)'
714            param = {
715                    'credential': cred,
716                    'uuid': uuid,
717                    'type': 'Slice',
718                    }
719            new_scred = self.pg_call(self.sa_url, 'GetCredential', param, ctxt)
720            f = open('./new_slice_cred', 'w')
721            print >>f, new_scred
722            f.close()
723
724        except self.ProtoGENIError, e:
725            self.log.error("Failed to extend slice %s: %s" % (name, e))
726            return None
727        try:
728            print 'Calling RenewSlice (CM)'
729            param = {
730                    'credential': new_scred,
731                    }
732            r = self.pg_call(self.cm_url, 'RenewSlice', param, ctxt)
733        except self.ProtoGENIError, e:
734            self.log.warn("Failed to renew sliver for %s: %s" % (name, e))
735
736        return new_scred
737   
Note: See TracBrowser for help on using the repository browser.