[1d73342] | 1 | #!/usr/local/bin/python |
---|
| 2 | |
---|
| 3 | import os,sys |
---|
| 4 | |
---|
| 5 | import re |
---|
| 6 | import random |
---|
| 7 | import string |
---|
| 8 | import subprocess |
---|
| 9 | import tempfile |
---|
| 10 | import copy |
---|
| 11 | import pickle |
---|
| 12 | import logging |
---|
| 13 | import signal |
---|
| 14 | import time |
---|
| 15 | |
---|
| 16 | import traceback |
---|
| 17 | # For parsing visualization output and splitter output |
---|
| 18 | import xml.parsers.expat |
---|
| 19 | |
---|
| 20 | from threading import Lock, Thread, Condition |
---|
| 21 | from subprocess import call, Popen, PIPE |
---|
| 22 | from string import join |
---|
| 23 | |
---|
| 24 | from urlparse import urlparse |
---|
| 25 | from urllib2 import urlopen |
---|
| 26 | |
---|
| 27 | from util import * |
---|
[6bedbdba] | 28 | from deter import fedid, generate_fedid |
---|
[1d73342] | 29 | from remote_service import xmlrpc_handler, soap_handler, service_caller |
---|
| 30 | from service_error import service_error |
---|
| 31 | from synch_store import synch_store |
---|
| 32 | from experiment_partition import experiment_partition |
---|
| 33 | from authorizer import abac_authorizer |
---|
| 34 | from thread_pool import thread_pool, pooled_thread |
---|
| 35 | |
---|
[6bedbdba] | 36 | from deter import topdl |
---|
[044dd20] | 37 | from deter import ip_allocator |
---|
| 38 | from deter import ip_addr |
---|
[1d73342] | 39 | import list_log |
---|
| 40 | |
---|
| 41 | |
---|
| 42 | class experiment_control_legacy: |
---|
| 43 | """ |
---|
| 44 | This contains the legacy access control requests that can be included in |
---|
| 45 | the experiment control component. This will eventually be completely |
---|
| 46 | removed. It is also only functional in the context of an experiment |
---|
| 47 | control object. |
---|
| 48 | """ |
---|
| 49 | |
---|
[5ecb9a3] | 50 | def get_legacy_access(self, tb, tbparam, fid, masters, tbmap, expid=None, |
---|
| 51 | expcert=None): |
---|
[1d73342] | 52 | """ |
---|
| 53 | Get access to testbed through fedd and set the parameters for that tb |
---|
| 54 | """ |
---|
| 55 | def get_export_project(svcs): |
---|
| 56 | """ |
---|
| 57 | Look through for the list of federated_service for this testbed |
---|
| 58 | objects for a project_export service, and extract the project |
---|
| 59 | parameter. |
---|
| 60 | """ |
---|
| 61 | |
---|
| 62 | pe = [s for s in svcs if s.name=='project_export'] |
---|
| 63 | if len(pe) == 1: |
---|
| 64 | return pe[0].params.get('project', None) |
---|
| 65 | elif len(pe) == 0: |
---|
| 66 | return None |
---|
| 67 | else: |
---|
| 68 | raise service_error(service_error.req, |
---|
| 69 | "More than one project export is not supported") |
---|
| 70 | |
---|
[5ecb9a3] | 71 | try: |
---|
| 72 | access_user = self.accessdb[fid] |
---|
| 73 | except KeyError: |
---|
| 74 | raise service_error(service_error.internal, |
---|
| 75 | "Access map and authorizer out of sync in " + \ |
---|
| 76 | "create_experiment for fedid %s" % fid) |
---|
| 77 | |
---|
[1d73342] | 78 | uri = tbmap.get(testbed_base(tb), None) |
---|
| 79 | if not uri: |
---|
| 80 | raise service_error(service_error.server_config, |
---|
| 81 | "Unknown testbed: %s" % tb) |
---|
| 82 | |
---|
| 83 | export_svcs = masters.get(tb,[]) |
---|
| 84 | import_svcs = [ s for m in masters.values() \ |
---|
| 85 | for s in m \ |
---|
| 86 | if tb in s.importers ] |
---|
| 87 | |
---|
| 88 | export_project = get_export_project(export_svcs) |
---|
| 89 | |
---|
| 90 | # Tweak search order so that if there are entries in access_user that |
---|
| 91 | # have a project matching the export project, we try them first |
---|
| 92 | if export_project: |
---|
| 93 | access_sequence = [ (p, u) for p, u in access_user \ |
---|
| 94 | if p == export_project] |
---|
| 95 | access_sequence.extend([(p, u) for p, u in access_user \ |
---|
| 96 | if p != export_project]) |
---|
| 97 | else: |
---|
| 98 | access_sequence = access_user |
---|
| 99 | |
---|
| 100 | for p, u in access_sequence: |
---|
| 101 | self.log.debug(("[get_access] Attempting access from (%s, %s) " + \ |
---|
| 102 | "to %s") % ((p or "None"), u, uri)) |
---|
| 103 | |
---|
| 104 | if p: |
---|
| 105 | # Request with user and project specified |
---|
| 106 | req = {\ |
---|
| 107 | 'credential': [ "project: %s" % p, "user: %s" % u], |
---|
| 108 | } |
---|
| 109 | else: |
---|
| 110 | # Request with only user specified |
---|
| 111 | req = {\ |
---|
| 112 | 'credential': [ 'user: %s' % u ], |
---|
| 113 | } |
---|
| 114 | |
---|
| 115 | # Make the service request from the services we're importing and |
---|
| 116 | # exporting. Keep track of the export request ids so we can |
---|
| 117 | # collect the resulting info from the access response. |
---|
| 118 | e_keys = { } |
---|
| 119 | if import_svcs or export_svcs: |
---|
| 120 | req['service'] = [ ] |
---|
| 121 | |
---|
| 122 | for i, s in enumerate(import_svcs): |
---|
| 123 | idx = 'import%d' % i |
---|
| 124 | sr = {'id': idx, 'name': s.name, 'visibility': 'import' } |
---|
| 125 | if s.params: |
---|
| 126 | sr['fedAttr'] = [ { 'attribute': k, 'value': v } \ |
---|
| 127 | for k, v in s.params.items()] |
---|
| 128 | req['service'].append(sr) |
---|
| 129 | |
---|
| 130 | for i, s in enumerate(export_svcs): |
---|
| 131 | idx = 'export%d' % i |
---|
| 132 | e_keys[idx] = s |
---|
| 133 | sr = {'id': idx, 'name': s.name, 'visibility': 'export' } |
---|
| 134 | if s.params: |
---|
| 135 | sr['fedAttr'] = [ { 'attribute': k, 'value': v } |
---|
| 136 | for k, v in s.params.items()] |
---|
| 137 | req['service'].append(sr) |
---|
| 138 | try: |
---|
| 139 | if self.local_access.has_key(uri): |
---|
| 140 | # Local access call |
---|
| 141 | req = { 'RequestAccessRequestBody' : req } |
---|
| 142 | r = self.local_access[uri].RequestAccess(req, |
---|
| 143 | fedid(file=self.cert_file)) |
---|
| 144 | r = { 'RequestAccessResponseBody' : r } |
---|
| 145 | else: |
---|
| 146 | r = self.call_RequestAccess(uri, req, |
---|
| 147 | self.cert_file, self.cert_pwd, self.trusted_certs) |
---|
| 148 | except service_error, e: |
---|
| 149 | if e.code == service_error.access: |
---|
| 150 | self.log.debug("[get_access] Access denied") |
---|
| 151 | r = None |
---|
| 152 | continue |
---|
| 153 | else: |
---|
| 154 | raise e |
---|
| 155 | |
---|
| 156 | if r.has_key('RequestAccessResponseBody'): |
---|
| 157 | # Through to here we have a valid response, not a fault. |
---|
| 158 | # Access denied is a fault, so something better or worse than |
---|
| 159 | # access denied has happened. |
---|
| 160 | r = r['RequestAccessResponseBody'] |
---|
| 161 | self.log.debug("[get_access] Access granted") |
---|
| 162 | break |
---|
| 163 | else: |
---|
| 164 | raise service_error(service_error.protocol, |
---|
| 165 | "Bad proxy response") |
---|
| 166 | |
---|
| 167 | if not r: |
---|
| 168 | raise service_error(service_error.access, |
---|
| 169 | "Access denied by %s (%s)" % (tb, uri)) |
---|
| 170 | |
---|
| 171 | tbparam[tb] = { |
---|
| 172 | "allocID" : r['allocID'], |
---|
| 173 | "uri": uri, |
---|
| 174 | } |
---|
| 175 | |
---|
| 176 | # Collect the responses corresponding to the services this testbed |
---|
| 177 | # exports. These will be the service requests that we will include in |
---|
| 178 | # the start segment requests (with appropriate visibility values) to |
---|
| 179 | # import and export the segments. |
---|
| 180 | for s in r.get('service', []): |
---|
| 181 | id = s.get('id', None) |
---|
| 182 | if id and id in e_keys: |
---|
| 183 | e_keys[id].reqs.append(s) |
---|
| 184 | |
---|
| 185 | # Add attributes to parameter space. We don't allow attributes to |
---|
| 186 | # overlay any parameters already installed. |
---|
| 187 | for a in r.get('fedAttr', []): |
---|
| 188 | try: |
---|
| 189 | if a['attribute'] and \ |
---|
| 190 | isinstance(a['attribute'], basestring)\ |
---|
| 191 | and not tbparam[tb].has_key(a['attribute'].lower()): |
---|
| 192 | tbparam[tb][a['attribute'].lower()] = a['value'] |
---|
| 193 | except KeyError: |
---|
| 194 | self.log.error("Bad attribute in response: %s" % a) |
---|
| 195 | |
---|
| 196 | |
---|