Add support to programmably start a profile on the POWDER testbed, which can in turn...
[it/test.git] / XTesting / powder-control / powder / rpc.py
1 #!/usr/bin/env python3
2 #
3 # Copyright (c) 2004-2020 University of Utah and the Flux Group.
4 #
5 # {{{EMULAB-LICENSE
6 #
7 # This file is part of the Emulab network testbed software.
8 #
9 # This file is free software: you can redistribute it and/or modify it
10 # under the terms of the GNU Affero General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or (at
12 # your option) any later version.
13 #
14 # This file is distributed in the hope that it will be useful, but WITHOUT
15 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
17 # License for more details.
18 #
19 # You should have received a copy of the GNU Affero General Public License
20 # along with this file.  If not, see <http://www.gnu.org/licenses/>.
21 #
22 # }}}
23 #
24
25 import logging
26 import os
27 import ssl
28 import sys
29 import xmlrpc.client as xmlrpc_client
30
31
32 PACKAGE_VERSION = 0.1
33 DEBUG = 0
34
35 # rpc server
36 XMLRPC_SERVER = "boss.emulab.net"
37 XMLRPC_PORT   = 3069
38 SERVER_PATH   = "/usr/testbed"
39 URI           = "https://" + XMLRPC_SERVER + ":" + str(XMLRPC_PORT) + SERVER_PATH
40
41 RESPONSE_SUCCESS     = 0
42 RESPONSE_BADARGS     = 1
43 RESPONSE_ERROR       = 2
44 RESPONSE_FORBIDDEN   = 3
45 RESPONSE_BADVERSION  = 4
46 RESPONSE_SERVERERROR = 5
47 RESPONSE_TOOBIG      = 6
48 RESPONSE_REFUSED     = 7  # Emulab is down, try again later.
49 RESPONSE_TIMEDOUT    = 8
50
51 # User supplied login ID, password, and certificate
52 try:
53     LOGIN_ID  = os.environ['USER']
54     PEM_PWORD = os.environ['PWORD']
55     CERT_PATH = os.environ['CERT']
56 except KeyError:
57     logging.error('Missing Powder credential environment variable(s)')
58     sys.exit(1)
59
60
61 def do_method(method, params):
62     ctx = ssl.SSLContext()
63     ctx.set_ciphers('ALL:@SECLEVEL=0')
64     ctx.load_cert_chain(CERT_PATH, password=PEM_PWORD)
65     ctx.check_hostname = False
66     ctx.verify_mode = ssl.CERT_NONE
67
68     # Get a handle on the server,
69     server = xmlrpc_client.ServerProxy(URI, context=ctx, verbose=DEBUG)
70
71     # Get a pointer to the function we want to invoke.
72     meth      = getattr(server, "portal." + method)
73     meth_args = [PACKAGE_VERSION, params]
74
75     # Make the call.
76     try:
77         response = meth(*meth_args)
78     except xmlrpc_client.Fault as e:
79         print(e.faultString)
80         return -1, None
81
82     rval = response["code"]
83
84     # If the code indicates failure, look for a "value". Use that as the
85     # return value instead of the code.
86     if rval != RESPONSE_SUCCESS:
87         if response["value"]:
88             rval = response["value"]
89
90     return rval, response
91
92
93 def start_experiment(experiment_name, project_name, profile_name):
94     params = {
95         "name": experiment_name,
96         "proj": project_name,
97         "profile": ','.join([project_name, profile_name])
98     }
99     rval, response = do_method("startExperiment", params)
100     return rval, response
101
102
103 def terminate_experiment(project_name, experiment_name):
104     params = {
105         "experiment": ','.join([project_name, experiment_name])
106     }
107     rval, response = do_method("terminateExperiment", params)
108     return rval, response
109
110
111 def get_experiment_status(project_name, experiment_name):
112     params = {
113         "experiment": ','.join([project_name, experiment_name])
114     }
115     rval, response = do_method("experimentStatus", params)
116     return rval, response
117
118
119 def get_experiment_manifests(project_name, experiment_name):
120     params = {
121         "experiment": ','.join([project_name, experiment_name])
122     }
123     rval, response = do_method("experimentManifests", params)
124     return rval, response