Changeset 987aaa1 for fedd/fedd_create.py
- Timestamp:
- Sep 9, 2008 2:07:18 PM (16 years ago)
- Branches:
- axis_example, compt_changes, info-ops, master, version-1.30, version-2.00, version-3.01, version-3.02
- Children:
- 45ebc4d
- Parents:
- 4fc2250
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
fedd/fedd_create.py
r4fc2250 r987aaa1 20 20 21 21 from fedd_util import fedid, fedd_ssl_context, pack_soap, unpack_soap, \ 22 pack_id, unpack_id 22 pack_id, unpack_id, encapsulate_binaries, decapsulate_binaries 23 23 24 24 from optparse import OptionParser, OptionValueError … … 76 76 version="0.1") 77 77 78 self.set_defaults(url="https://localhost:23235", anonymous=False,79 serialize_only=False, transport="soap", use_fedid=False,80 debug=0, file=None, master=None)81 82 78 self.add_option("-c","--cert", action="store", dest="cert", 83 79 type="string", help="my certificate file") 84 80 self.add_option("-d", "--debug", action="count", dest="debug", 85 help="Set debug. Repeat for more information") 86 self.add_option("-f", "--file", dest="file", 87 help="experiment description file") 88 self.add_option("-F","--useFedid", action="store_true", 89 dest="use_fedid", 90 help="Use a fedid derived from my certificate as user identity") 91 self.add_option("-k", "--sshKey", action="callback", type="string", 92 callback=add_ssh_key, callback_args=(access_keys,), 93 help="ssh key for access (can be supplied more than once") 94 self.add_option("-K", "--x509Key", action="callback", type="string", 95 callback=add_x509_cert, callback_args=(access_keys,), 96 help="X509 certificate for access " + \ 97 "(can be supplied more than once") 98 self.add_option("-m", "--master", dest="master", 99 help="Master testbed in the federation") 81 default=0, help="Set debug. Repeat for more information") 100 82 self.add_option("-s", "--serializeOnly", action="store_true", 101 dest="serialize_only", 83 dest="serialize_only", default=False, 102 84 help="Print the SOAP request that would be sent and exit") 103 85 self.add_option("-T","--trusted", action="store", dest="trusted", 104 86 type="string", help="Trusted certificates (required)") 105 87 self.add_option("-u", "--url", action="store", dest="url", 106 type="string", 88 type="string",default="https://localhost:23235", 107 89 help="URL to connect to (default %default)") 108 self.add_option("-U", "--username", action="store", dest="user",109 type="string", help="Use this username instead of the uid")110 90 self.add_option("-x","--transport", action="store", type="choice", 111 choices=("xmlrpc", "soap"), 91 choices=("xmlrpc", "soap"), default="soap", 112 92 help="Transport for request (xmlrpc|soap) (Default: %default)") 113 93 self.add_option("--trace", action="store_const", dest="tracefile", 114 94 const=sys.stderr, help="Print SOAP exchange to stderr") 115 95 96 class fedd_create_opts(fedd_client_opts): 97 def __init__(self, access_keys, add_key_callback=None, 98 add_cert_callback=None): 99 fedd_client_opts.__init__(self) 100 self.add_option("-e", "--experiment_cert", dest="out_certfile", 101 type="string", help="output certificate file") 102 self.add_option("-F","--useFedid", action="store_true", 103 dest="use_fedid", default=False, 104 help="Use a fedid derived from my certificate as user identity") 105 self.add_option("-f", "--file", dest="file", 106 help="experiment description file") 107 if add_key_callback: 108 self.add_option("-k", "--sshKey", action="callback", type="string", 109 callback=add_key_callback, callback_args=(access_keys,), 110 help="ssh key for access (can be supplied more than once") 111 if add_cert_callback: 112 self.add_option("-K", "--x509Key", action="callback", 113 type="string", callback=add_cert_callback, 114 callback_args=(access_keys,), 115 help="X509 certificate for access " + \ 116 "(can be supplied more than once") 117 self.add_option("-m", "--master", dest="master", 118 help="Master testbed in the federation") 119 self.add_option("-U", "--username", action="store", dest="user", 120 type="string", help="Use this username instead of the uid") 121 116 122 def exit_with_fault(dict, out=sys.stderr): 117 123 """ Print an error message and exit. … … 133 139 sys.exit(dict.get('code', 20)) 134 140 135 def add_ssh_key(option, opt_str, value, parser, access_keys): 136 try: 137 access_keys.append(access_method(file=value, 138 type=access_method.type_ssh)) 139 except IOError, (errno, strerror): 140 raise OptionValueError("Cannot generate sshPubkey from %s: %s (%d)" % 141 (value,strerror,errno)) 142 143 def add_x509_cert(option, opt_str, value, parser, access_keys): 144 try: 145 access_keys.append(access_method(file=value, 146 type=access_method.type_x509)) 147 except IOError, (errno, strerror): 148 raise OptionValueError("Cannot read x509 cert from %s: %s (%d)" % 149 (value,strerror,errno)) 150 151 def get_user_info(access_keys): 152 pw = pwd.getpwuid(os.getuid()); 153 try_cert=None 154 user = None 155 156 if pw != None: 157 user = pw[0] 158 try_cert = "%s/.ssl/emulab.pem" % pw[5]; 159 if not os.access(try_cert, os.R_OK): 160 try_cert = None 161 if len(access_keys) == 0: 162 for k in ["%s/.ssh/id_rsa.pub", "%s/.ssh/id_dsa.pub", 163 "%s/.ssh/identity.pub"]: 164 try_key = k % pw[5]; 165 if os.access(try_key, os.R_OK): 166 access_keys.append(access_method(file=try_key, 167 type=access_method.type_ssh)) 168 break 169 return (user, try_cert) 170 171 access_keys = [] 172 173 # Process the options using the customized option parser defined above 174 parser = fedd_client_opts() 175 176 (opts, args) = parser.parse_args() 177 178 if opts.trusted != None: 179 if ( not os.access(opts.trusted, os.R_OK) ) : 180 sys.exit("Cannot read trusted certificates (%s)" % opts.trusted) 141 class fedd_exp_data_opts(fedd_client_opts): 142 def __init__(self): 143 fedd_client_opts.__init__(self) 144 self.add_option("-e", "--experiment_cert", dest="exp_certfile", 145 type="string", help="output certificate file") 146 147 # Querying experiment data follows the same control flow regardless of the 148 # specific data retrieved. This class encapsulates that control flow. 149 class exp_data: 150 def __init__(self, op): 151 """ 152 Specialize the class for the type of data requested (op) 153 """ 154 if op =='vtopo': 155 self.RequestMessage = VtopoRequestMessage; 156 self.ResponseMessage = VtopoResponseMessage; 157 self.RequestBody="VtopoRequestBody" 158 self.ResponseBody="VtopoResponseBody" 159 self.method = "Vtopo" 160 self.key="vtopo" 161 self.xml='experiment' 162 elif op == 'vis': 163 self.RequestMessage = VisRequestMessage; 164 self.ResponseMessage = VisResponseMessage; 165 self.RequestBody="VisRequestBody" 166 self.ResponseBody="VisResponseBody" 167 self.method = "Vis" 168 self.key="vis" 169 self.xml='vis' 170 else: 171 raise TypeError("Bad op: %s" % op) 172 173 def print_xml(self, d, out=sys.stdout): 174 """ 175 Print the retrieved data is a simple xml representation of the dict. 176 """ 177 str = "<%s>\n" % self.xml 178 for t in ('node', 'lan'): 179 if d.has_key(t): 180 for x in d[t]: 181 str += "<%s>" % t 182 for k in x.keys(): 183 str += "<%s>%s</%s>" % (k, x[k],k) 184 str += "</%s>\n" % t 185 str+= "</%s>" % self.xml 186 print >>out, str 187 188 def __call__(self): 189 """ 190 The control flow. Compose the request and print the response. 191 """ 192 # Process the options using the customized option parser defined above 193 parser = fedd_exp_data_opts() 194 195 (opts, args) = parser.parse_args() 196 197 if opts.trusted != None: 198 if ( not os.access(opts.trusted, os.R_OK) ) : 199 sys.exit("Cannot read trusted certificates (%s)" % opts.trusted) 200 else: 201 parser.error("--trusted is required") 202 203 if opts.debug > 0: opts.tracefile=sys.stderr 204 205 if opts.cert != None: cert = opts.cert 206 207 if cert == None: 208 sys.exit("No certificate given (--cert) or found") 209 210 if os.access(cert, os.R_OK): 211 fid = fedid(file=cert) 212 else: 213 sys.exit("Cannot read certificate (%s)" % cert) 214 215 if opts.exp_certfile: 216 exp_fedid = fedid(file=opts.exp_certfile) 217 else: 218 sys.exit("Experiment certfile required") 219 220 context = None 221 while context == None: 222 try: 223 context = fedd_ssl_context(cert, opts.trusted) 224 except SSL.SSLError, e: 225 # Yes, doing this on message type is not ideal. The string 226 # comes from OpenSSL, so check there is this stops working. 227 if str(e) == "bad decrypt": 228 print >>sys.stderr, "Bad Passphrase given." 229 else: raise 230 231 msg = { 'experiment': { 'fedid': exp_fedid } } 232 233 if opts.debug > 1: print >>sys.stderr, msg 234 235 if opts.transport == "soap": 236 loc = feddServiceLocator(); 237 port = loc.getfeddPortType(opts.url, 238 transport=M2Crypto.httpslib.HTTPSConnection, 239 transdict={ 'ssl_context' : context }, 240 tracefile=opts.tracefile) 241 242 req = self.RequestMessage() 243 244 set_req = getattr(req, "set_element_%s" % self.RequestBody, None) 245 246 set_req(pack_soap(req, self.RequestBody, msg)) 247 248 if opts.serialize_only: 249 sw = SoapWriter() 250 sw.serialize(req) 251 print str(sw) 252 sys.exit(0) 253 254 try: 255 method_call = getattr(port, self.method, None) 256 resp = method_call(req) 257 except ZSI.ParseException, e: 258 sys.exit("Malformed response (XMLPRC?): %s" % e) 259 except ZSI.FaultException, e: 260 resp = e.fault.detail[0] 261 262 if resp: 263 resp_call = getattr(resp, "get_element_%s" %self.ResponseBody, 264 None) 265 if resp_call: 266 resp_body = resp_call() 267 if ( resp_body != None): 268 try: 269 resp_dict = unpack_soap(resp_body) 270 if opts.debug > 1: print >>sys.stderr, resp_dict 271 if resp_dict.has_key(self.key): 272 self.print_xml(resp_dict[self.key]) 273 except RuntimeError, e: 274 sys.exit("Bad response. %s" % e.message) 275 elif 'get_element_FeddFaultBody' in dir(resp): 276 resp_body = resp.get_element_FeddFaultBody() 277 if resp_body != None: 278 exit_with_fault(unpack_soap(resp_body)) 279 else: sys.exit("No body in response!?") 280 else: sys.exit("No response?!?") 281 elif opts.transport == "xmlrpc": 282 if opts.serialize_only: 283 ser = dumps((msg,)) 284 print ser 285 sys.exit(0) 286 287 transport = SSL_Transport(context) 288 port = ServerProxy(opts.url, transport=transport) 289 290 try: 291 method_call = getattr(port, self.method, None) 292 resp = method_call( 293 encapsulate_binaries({ self.RequestBody: msg},\ 294 ('fedid',))) 295 except Error, e: 296 resp = { 'FeddFaultBody': \ 297 { 'errstr' : e.faultCode, 'desc' : e.faultString } } 298 if resp: 299 if resp.has_key(self.ResponseBody): 300 try: 301 resp_dict = resp[self.ResponseBody] 302 if opts.debug > 1: print >>sys.stderr, resp_dict 303 if resp_dict.has_key(self.key): 304 self.print_xml(resp_dict[self.key]) 305 except RuntimeError, e: 306 sys.exit("Bad response. %s" % e.messgae) 307 elif resp.has_key('FeddFaultBody'): 308 exit_with_fault(resp['FeddFaultBody']) 309 else: sys.exit("No body in response!?") 310 else: sys.exit("No response?!?") 311 312 class create: 313 def __init__(self): pass 314 315 def add_ssh_key(self, option, opt_str, value, parser, access_keys): 316 try: 317 access_keys.append(access_method(file=value, 318 type=access_method.type_ssh)) 319 except IOError, (errno, strerror): 320 raise OptionValueError("Cannot generate sshPubkey from %s: "\ 321 "%s (%d)" % (value,strerror,errno)) 322 323 def add_x509_cert(self, option, opt_str, value, parser, access_keys): 324 try: 325 access_keys.append(access_method(file=value, 326 type=access_method.type_x509)) 327 except IOError, (errno, strerror): 328 raise OptionValueError("Cannot read x509 cert from %s: %s (%d)" % 329 (value,strerror,errno)) 330 331 def get_user_info(self, access_keys): 332 pw = pwd.getpwuid(os.getuid()); 333 try_cert=None 334 user = None 335 336 if pw != None: 337 user = pw[0] 338 try_cert = "%s/.ssl/emulab.pem" % pw[5]; 339 if not os.access(try_cert, os.R_OK): 340 try_cert = None 341 if len(access_keys) == 0: 342 for k in ["%s/.ssh/id_rsa.pub", "%s/.ssh/id_dsa.pub", 343 "%s/.ssh/identity.pub"]: 344 try_key = k % pw[5]; 345 if os.access(try_key, os.R_OK): 346 access_keys.append(access_method(file=try_key, 347 type=access_method.type_ssh)) 348 break 349 return (user, try_cert) 350 351 def __call__(self): 352 access_keys = [] 353 # Process the options using the customized option parser defined above 354 parser = fedd_create_opts(access_keys, self.add_ssh_key, 355 self.add_x509_cert) 356 357 (opts, args) = parser.parse_args() 358 359 if opts.trusted != None: 360 if ( not os.access(opts.trusted, os.R_OK) ) : 361 sys.exit("Cannot read trusted certificates (%s)" % opts.trusted) 362 else: 363 parser.error("--trusted is required") 364 365 if opts.debug > 0: opts.tracefile=sys.stderr 366 367 (user, cert) = self.get_user_info(access_keys) 368 369 if opts.user: user = opts.user 370 371 if opts.cert != None: cert = opts.cert 372 373 if cert == None: 374 sys.exit("No certificate given (--cert) or found") 375 376 if os.access(cert, os.R_OK): 377 fid = fedid(file=cert) 378 if opts.use_fedid == True: 379 user = fid 380 else: 381 sys.exit("Cannot read certificate (%s)" % cert) 382 383 if opts.file: 384 exp_desc = "" 385 try: 386 f = open(opts.file, 'r') 387 for line in f: 388 exp_desc += line 389 f.close() 390 except IOError: 391 sys.exit("Cannot read description file (%s)" %opts.file) 392 else: 393 sys.exit("Must specify an experiment description (--file)") 394 395 if not opts.master: 396 sys.exit("Must specify a master testbed (--master)") 397 398 out_certfile = opts.out_certfile 399 400 context = None 401 while context == None: 402 try: 403 context = fedd_ssl_context(cert, opts.trusted) 404 except SSL.SSLError, e: 405 # Yes, doing this on message type is not ideal. The string comes 406 # from OpenSSL, so check there is this stops working. 407 if str(e) == "bad decrypt": 408 print >>sys.stderr, "Bad Passphrase given." 409 else: raise 410 411 msg = { 412 'experimentdescription': exp_desc, 413 'master': opts.master, 414 'user' : [ {\ 415 'userID': pack_id(user), \ 416 'access': [ { a.type: a.buf } for a in access_keys]\ 417 } ] 418 } 419 420 if opts.debug > 1: print >>sys.stderr, msg 421 422 if opts.transport == "soap": 423 loc = feddServiceLocator(); 424 port = loc.getfeddPortType(opts.url, 425 transport=M2Crypto.httpslib.HTTPSConnection, 426 transdict={ 'ssl_context' : context }, 427 tracefile=opts.tracefile) 428 429 req = CreateRequestMessage() 430 431 req.set_element_CreateRequestBody( 432 pack_soap(req, "CreateRequestBody", msg)) 433 434 if opts.serialize_only: 435 sw = SoapWriter() 436 sw.serialize(req) 437 print str(sw) 438 sys.exit(0) 439 440 try: 441 resp = port.Create(req) 442 except ZSI.ParseException, e: 443 sys.exit("Malformed response (XMLPRC?): %s" % e) 444 except ZSI.FaultException, e: 445 resp = e.fault.detail[0] 446 447 if resp: 448 if 'get_element_CreateResponseBody' in dir(resp): 449 resp_body = resp.get_element_CreateResponseBody() 450 if ( resp_body != None): 451 try: 452 resp_dict = unpack_soap(resp_body) 453 if opts.debug > 1: print >>sys.stderr, resp_dict 454 ea = resp_dict.get('experimentAccess', None) 455 if out_certfile and ea and ea.has_key('X509'): 456 try: 457 f = open(out_certfile, "w") 458 print >>f, ea['X509'] 459 f.close() 460 except IOError: 461 sys.exit('Could not write to %s' % \ 462 out_certfile) 463 except RuntimeError, e: 464 sys.exit("Bad response. %s" % e.message) 465 elif 'get_element_FeddFaultBody' in dir(resp): 466 resp_body = resp.get_element_FeddFaultBody() 467 if resp_body != None: 468 exit_with_fault(unpack_soap(resp_body)) 469 else: sys.exit("No body in response!?") 470 else: sys.exit("No response?!?") 471 elif opts.transport == "xmlrpc": 472 if opts.serialize_only: 473 ser = dumps((msg,)) 474 print ser 475 sys.exit(0) 476 477 transport = SSL_Transport(context) 478 port = ServerProxy(opts.url, transport=transport) 479 480 try: 481 resp = port.Create({ 'CreateRequestBody': msg}) 482 except Error, e: 483 resp = { 'FeddFaultBody': \ 484 { 'errstr' : e.faultCode, 'desc' : e.faultString } } 485 if resp: 486 if resp.has_key('CreateResponseBody'): 487 try: 488 resp_dict = resp['CreateResponseBody'] 489 decapsulate_binaries(resp_dict, ('fedid',)) 490 if opts.debug > 1: print >>sys.stderr, resp_dict 491 ea = resp_dict.get('experimentAccess', None) 492 if out_certfile and ea and ea.has_key('X509'): 493 try: 494 f = open(out_certfile, "w") 495 print >>f, ea['X509'] 496 f.close() 497 except IOError: 498 sys.exit('Could not write to %s' % out_certfile) 499 except RuntimeError, e: 500 sys.exit("Bad response. %s" % e.messgae) 501 elif resp.has_key('FeddFaultBody'): 502 exit_with_fault(resp['FeddFaultBody']) 503 else: sys.exit("No body in response!?") 504 505 else: sys.exit("No response?!?") 506 507 valid_cmds = ['create'] 508 509 f = None 510 if sys.argv[1] == 'create': 511 del sys.argv[1] 512 f = create() 513 elif sys.argv[1] == 'vtopo': 514 del sys.argv[1] 515 f = exp_data('vtopo') 516 elif sys.argv[1] == 'vis': 517 del sys.argv[1] 518 f = exp_data('vis') 181 519 else: 182 parser.error("--trusted is required") 183 184 if opts.debug > 0: opts.tracefile=sys.stderr 185 186 (user, cert) = get_user_info(access_keys) 187 188 if opts.user: user = opts.user 189 190 if opts.cert != None: cert = opts.cert 191 192 if cert == None: 193 sys.exit("No certificate given (--cert) or found") 194 195 if os.access(cert, os.R_OK): 196 fid = fedid(file=cert) 197 if opts.use_fedid == True: 198 user = fid 199 else: 200 sys.exit("Cannot read certificate (%s)" % cert) 201 202 if opts.file: 203 exp_desc = "" 204 try: 205 f = open(opts.file, 'r') 206 for line in f: 207 exp_desc += line 208 f.close() 209 except IOError: 210 sys.exit("Cannot read description file (%s)" %opts.file) 211 else: 212 sys.exit("Must specify an experiment description (--file)") 213 214 if not opts.master: 215 sys.exit("Must specify a master testbed (--master)") 216 217 218 context = None 219 while context == None: 220 try: 221 context = fedd_ssl_context(cert, opts.trusted) 222 except SSL.SSLError, e: 223 # Yes, doing this on message type is not ideal. The string comes from 224 # OpenSSL, so check there is this stops working. 225 if str(e) == "bad decrypt": 226 print >>sys.stderr, "Bad Passphrase given." 227 else: raise 228 229 msg = { 230 'experimentdescription': exp_desc, 231 'master': opts.master, 232 'user' : [ {\ 233 'userID': pack_id(user), \ 234 'access': [ { a.type: a.buf } for a in access_keys]\ 235 } ] 236 } 237 238 if opts.debug > 1: print >>sys.stderr, msg 239 240 if opts.transport == "soap": 241 loc = feddServiceLocator(); 242 port = loc.getfeddPortType(opts.url, 243 transport=M2Crypto.httpslib.HTTPSConnection, 244 transdict={ 'ssl_context' : context }, 245 tracefile=opts.tracefile) 246 247 req = CreateRequestMessage() 248 249 req.set_element_CreateRequestBody( 250 pack_soap(req, "CreateRequestBody", msg)) 251 252 if opts.serialize_only: 253 sw = SoapWriter() 254 sw.serialize(req) 255 print str(sw) 256 sys.exit(0) 257 258 try: 259 resp = port.Create(req) 260 except ZSI.ParseException, e: 261 sys.exit("Malformed response (XMLPRC?): %s" % e) 262 except ZSI.FaultException, e: 263 resp = e.fault.detail[0] 264 265 if resp: 266 if 'get_element_CreateResponseBody' in dir(resp): 267 resp_body = resp.get_element_CreateResponseBody() 268 if ( resp_body != None): 269 try: 270 resp_dict = unpack_soap(resp_body) 271 if opts.debug > 1: print >>sys.stderr, resp_dict 272 except RuntimeError, e: 273 sys.exit("Bad response. %s" % e.message) 274 elif 'get_element_FeddFaultBody' in dir(resp): 275 resp_body = resp.get_element_FeddFaultBody() 276 if resp_body != None: 277 exit_with_fault(unpack_soap(resp_body)) 278 else: sys.exit("No body in response!?") 279 else: sys.exit("No response?!?") 280 elif opts.transport == "xmlrpc": 281 if opts.serialize_only: 282 ser = dumps((msg,)) 283 print ser 284 sys.exit(0) 285 286 transport = SSL_Transport(context) 287 port = ServerProxy(opts.url, transport=transport) 288 289 try: 290 resp = port.Create({ 'CreateRequestBody': msg}) 291 except Error, e: 292 resp = { 'FeddFaultBody': \ 293 { 'errstr' : e.faultCode, 'desc' : e.faultString } } 294 if resp: 295 if resp.has_key('CreateResponseBody'): 296 try: 297 resp_dict = resp['CreateResponseBody'] 298 if opts.debug > 1: print >>sys.stderr, resp_dict 299 except RuntimeError, e: 300 sys.exit("Bad response. %s" % e.messgae) 301 elif resp.has_key('FeddFaultBody'): 302 exit_with_fault(resp['FeddFaultBody']) 303 else: sys.exit("No body in response!?") 304 305 else: sys.exit("No response?!?") 520 sys.exit("Bad command: %s. Valid ones are: %s" % \ 521 (sys.argv[1], ", ".join(valid_cmds))) 522 523 if f: f() 524 else: sys.exit("Null function?!?")
Note: See TracChangeset
for help on using the changeset viewer.