|
| 1 | +import requests |
| 2 | +import json |
| 3 | +import sys |
| 4 | + |
| 5 | + |
| 6 | +class Sandbox: |
| 7 | + """ |
| 8 | + Sandbox Python API wrapper |
| 9 | + """ |
| 10 | + |
| 11 | + def __init__(self, config_file): |
| 12 | + quali_config = json.load(open(config_file, 'r')) |
| 13 | + self.server_address = 'http://{}:{}/api'.format(quali_config['server_name'], quali_config['server_port']) |
| 14 | + self.username = quali_config['username'] |
| 15 | + self.password = quali_config['password'] |
| 16 | + self.domain = quali_config['domain'] |
| 17 | + self.auth_code = '' |
| 18 | + self.headers = '' |
| 19 | + |
| 20 | + def _request_and_parse(self, request_type, url_str, json_dict={}, data_dict={}): |
| 21 | + """ |
| 22 | +
|
| 23 | + :param request_type: |
| 24 | + :param url_str: |
| 25 | + :param json_dict: |
| 26 | + :param data_dict: |
| 27 | + :return: |
| 28 | + """ |
| 29 | + |
| 30 | + response = '' |
| 31 | + if request_type.lower() == 'put': |
| 32 | + response = requests.put(url_str, json=json_dict, headers=self.headers) |
| 33 | + |
| 34 | + elif request_type.lower() == 'get': |
| 35 | + response = requests.get(url_str, json=json_dict, headers=self.headers) |
| 36 | + |
| 37 | + elif request_type.lower() == 'post': |
| 38 | + response = requests.post(url_str, json=json_dict, headers=self.headers, data=json.dumps(data_dict)) |
| 39 | + |
| 40 | + if not response.ok: |
| 41 | + sys.exit('Error code: {}\nError text: {}\nP{} failed, exiting'.format(response.status_code, |
| 42 | + json.loads(response.text)[ |
| 43 | + 'message'], url_str)) |
| 44 | + return response |
| 45 | + |
| 46 | + def login(self): |
| 47 | + """Login and set some internal variables |
| 48 | + """ |
| 49 | + url_str = self.server_address + '/login' |
| 50 | + json_dict = {'username': self.username, 'password': self.password, 'domain': self.domain} |
| 51 | + response = self._request_and_parse('put', url_str, json_dict) |
| 52 | + self.auth_code = "Basic " + response.content[1:-1] |
| 53 | + self.headers = {"Authorization": self.auth_code, "Content-Type": "application/json"} |
| 54 | + |
| 55 | + def get_blueprints(self): |
| 56 | + """Get all blueprints details |
| 57 | + :return: <dict> Dict of blueprints and their ids |
| 58 | + """ |
| 59 | + url_str = '{}{}'.format(self.server_address, '/v1/blueprints') |
| 60 | + response = self._request_and_parse('get', url_str) |
| 61 | + |
| 62 | + # parse the output |
| 63 | + parsed_response = json.loads(response.content) |
| 64 | + blueprint_names = [blueprint['name'].encode('utf-8') for blueprint in parsed_response] |
| 65 | + blueprint_ids = [blueprint['id'].encode('utf-8') for blueprint in parsed_response] |
| 66 | + blueprint_dict = dict(zip(blueprint_names, blueprint_ids)) |
| 67 | + |
| 68 | + # return a dictionary of blueprints names and their ids |
| 69 | + return blueprint_dict |
| 70 | + |
| 71 | + def get_blueprint_id(self, blueprint_name): |
| 72 | + """Return blueprint id, given blueprint name |
| 73 | + :param blueprint_name: Name of the blueprint |
| 74 | + :return: blueprint_id |
| 75 | + """ |
| 76 | + |
| 77 | + # Get all blueprints and see if blueprint_name exists in the list |
| 78 | + blueprints = self.get_blueprints() |
| 79 | + if blueprint_name not in blueprints.iterkeys(): |
| 80 | + raise Exception( |
| 81 | + 'Blueprint "{}" not found, exiting'.format(blueprint_name)) |
| 82 | + |
| 83 | + # If exists, return name of blueprint |
| 84 | + return blueprints[blueprint_name] |
| 85 | + |
| 86 | + def get_blueprint_details(self, blueprint_id): |
| 87 | + """Returns a dict of the blueprint, given the blueprint id |
| 88 | + :param blueprint_id: blueprint_id |
| 89 | + :return: dict of name, estimated_setup_duration, description of the blueprint |
| 90 | + """ |
| 91 | + url_str = '{}{}{}'.format(self.server_address, '/v1/blueprints/', blueprint_id) |
| 92 | + response = self._request_and_parse('get', url_str) |
| 93 | + parsed_blueprint_details = json.loads(response.content) |
| 94 | + return_dict = {'name': parsed_blueprint_details['name'], |
| 95 | + 'estimated_setup_duration': parsed_blueprint_details['estimated_setup_duration'], |
| 96 | + 'description': parsed_blueprint_details['description']} |
| 97 | + return return_dict |
| 98 | + |
| 99 | + def get_blueprint_details_by_name(self, blueprint_name): |
| 100 | + """Create a sandbox from the provided blueprint name |
| 101 | + :param blueprint_name: blueprint name |
| 102 | + :return: dict of name, estimated_setup_duration, description of the blueprint |
| 103 | + """ |
| 104 | + blueprint_id = self.get_blueprint_id(blueprint_name) |
| 105 | + return self.get_blueprint_details(blueprint_id) |
| 106 | + |
| 107 | + def start_sandbox(self, blueprint_id, duration, sandbox_name=''): |
| 108 | + """Create a sandbox from the provided blueprint id |
| 109 | + :param blueprint_id: blueprint_id |
| 110 | + :param duration: duration in minutes |
| 111 | + :param sandbox_name: name of the sandbox, same as blueprint if name='' |
| 112 | + :return: if success sandbox_id, else False |
| 113 | + """ |
| 114 | + |
| 115 | + # Do some parameter validation |
| 116 | + try: |
| 117 | + int(duration) |
| 118 | + except ValueError: |
| 119 | + raise Exception('Duration "{}" has to be integer'.format(duration)) |
| 120 | + |
| 121 | + duration = 'PT{}M'.format(duration) |
| 122 | + if sandbox_name == '': |
| 123 | + sandbox_name = self.get_blueprint_details(blueprint_id)['name'] |
| 124 | + |
| 125 | + url_str = '{}{}{}/{}'.format(self.server_address, '/v1/blueprints/', blueprint_id, 'start') |
| 126 | + data_dict = {"duration": duration, "name": sandbox_name} |
| 127 | + response = self._request_and_parse('post', url_str, data_dict=data_dict) |
| 128 | + if response.ok: |
| 129 | + return json.loads(response.content)['id'] |
| 130 | + else: |
| 131 | + return response.ok |
| 132 | + |
| 133 | + def start_sandbox_by_name(self, blueprint_name, duration, sandbox_name=''): |
| 134 | + """Create a sandbox from the provided blueprint name |
| 135 | + :param blueprint_name: blueprint_name |
| 136 | + :param duration: duration in minutes |
| 137 | + :param sandbox_name: sandbox name |
| 138 | + :return: if success sandbox_id, else False |
| 139 | + """ |
| 140 | + blueprint_id = self.get_blueprint_id(blueprint_name) |
| 141 | + if sandbox_name == '': |
| 142 | + sandbox_name = blueprint_name |
| 143 | + return self.start_sandbox(blueprint_id, duration, sandbox_name) |
| 144 | + |
| 145 | + def get_sandboxes(self): |
| 146 | + """Returns a dictionary of all sandboxes name and their ids |
| 147 | + :return: A dict of sandbox ids and names |
| 148 | + """ |
| 149 | + url_str = '{}{}'.format(self.server_address, '/v1/sandboxes') |
| 150 | + response = self._request_and_parse('get', url_str) |
| 151 | + |
| 152 | + # parse the output |
| 153 | + parsed_response = json.loads(response.content) |
| 154 | + sandbox_names = [sandbox['name'].encode('utf-8') for sandbox in parsed_response] |
| 155 | + sandbox_ids = [sandbox['id'].encode('utf-8') for sandbox in parsed_response] |
| 156 | + sandbox_dict = dict(zip(sandbox_ids, sandbox_names)) |
| 157 | + |
| 158 | + # return a dictionary of sandboxes names and their ids |
| 159 | + return sandbox_dict |
| 160 | + |
| 161 | + def get_sandbox_details(self, sandbox_id): |
| 162 | + """Returns a dictionary of the sandbox, its name, type and state |
| 163 | + :param sandbox_id: <str> Sandbox id |
| 164 | + :return: dictionary of sandbox name, type and state |
| 165 | + """ |
| 166 | + |
| 167 | + # Get info from cloudshell |
| 168 | + url_str = '{}{}{}'.format(self.server_address, '/v1/sandboxes/', sandbox_id) |
| 169 | + response = self._request_and_parse('get', url_str) |
| 170 | + |
| 171 | + # parse the information |
| 172 | + parsed_blueprint_details = json.loads(response.content) |
| 173 | + |
| 174 | + # prepare a dictionary to return |
| 175 | + return_dict = {'name': parsed_blueprint_details['name'], |
| 176 | + 'type': parsed_blueprint_details['type'], |
| 177 | + 'state': parsed_blueprint_details['state']} |
| 178 | + return return_dict |
| 179 | + |
| 180 | + def get_sandboxes_details_by_name(self, sandbox_name): |
| 181 | + """ |
| 182 | + :param sandbox_name: Sandbox name |
| 183 | + :return: dictionary of sandbox name, type and state |
| 184 | + """ |
| 185 | + return_dict = {} |
| 186 | + sandbox_ids = self.get_sandbox_ids(sandbox_name) |
| 187 | + for sandbox_id in sandbox_ids: |
| 188 | + return_dict[sandbox_id] = self.get_sandbox_details(sandbox_id) |
| 189 | + return return_dict |
| 190 | + |
| 191 | + def get_sandbox_ids(self, sandbox_name): |
| 192 | + """Returns the sandbox id, given sandbox name |
| 193 | + :param sandbox_name: Sandbox name |
| 194 | + :return: Sandbox id |
| 195 | + """ |
| 196 | + sandboxes = self.get_sandboxes() |
| 197 | + if sandbox_name not in sandboxes.itervalues(): |
| 198 | + raise Exception( |
| 199 | + 'Sandbox "{}" not found, exiting'.format(sandbox_name)) |
| 200 | + |
| 201 | + sandbox_ids = [k for k, v in sandboxes.iteritems() if v == sandbox_name] |
| 202 | + return sandbox_ids |
| 203 | + |
| 204 | + def stop_sandbox(self, sandbox_id): |
| 205 | + """Stop the sandbox given sandbox id |
| 206 | + :param sandbox_id: Sandbox id |
| 207 | + :return: True if success, False if not |
| 208 | + """ |
| 209 | + |
| 210 | + url_str = '{}{}{}/{}'.format(self.server_address, '/v1/sandboxes/', sandbox_id, 'stop') |
| 211 | + response = self._request_and_parse('post', url_str) |
| 212 | + return response.ok |
| 213 | + |
| 214 | + def stop_sandboxes_by_name(self, sandbox_name): |
| 215 | + """Stop the sandbox given sandbox name |
| 216 | + :param sandbox_name: Sandbox name |
| 217 | + :return: True if success, False if not |
| 218 | + """ |
| 219 | + sandbox_ids = self.get_sandbox_ids(sandbox_name) |
| 220 | + for sandbox_id in sandbox_ids: |
| 221 | + self.stop_sandbox(sandbox_id) |
| 222 | + |
| 223 | + |
| 224 | +def main(): |
| 225 | + usage = """Usage: |
| 226 | + # Init vars |
| 227 | + blueprint_name = 'Sandbox Python API Test' |
| 228 | + sandbox_name = 'Sandbox Python API Test' |
| 229 | + config_file = 'quali_config.json' |
| 230 | +
|
| 231 | + my_sandbox = Sandbox(config_file=config_file) |
| 232 | +
|
| 233 | + my_sandbox.login() |
| 234 | +
|
| 235 | + print my_sandbox.get_blueprints() |
| 236 | + blueprint_id = my_sandbox.get_blueprint_id(blueprint_name=blueprint_name) |
| 237 | + print "Blueprint Id:", blueprint_id |
| 238 | + print my_sandbox.get_blueprint_details(blueprint_id=blueprint_id) |
| 239 | + print my_sandbox.get_blueprint_details_by_name(blueprint_name=blueprint_name) |
| 240 | +
|
| 241 | + print my_sandbox.start_sandbox(blueprint_id=blueprint_id, duration='20', sandbox_name='') |
| 242 | + print my_sandbox.start_sandbox_by_name(blueprint_name=blueprint_name, duration='20', sandbox_name='') |
| 243 | + print my_sandbox.get_sandboxes() |
| 244 | + sandbox_id = my_sandbox.get_sandbox_ids(sandbox_name=sandbox_name) |
| 245 | + print sandbox_id |
| 246 | + print my_sandbox.get_sandbox_details(sandbox_id=sandbox_id[0]) |
| 247 | + print my_sandbox.get_sandboxes_details_by_name(sandbox_name=sandbox_name) |
| 248 | + print my_sandbox.stop_sandbox(sandbox_id=sandbox_id[0]) |
| 249 | + print my_sandbox.stop_sandboxes_by_name(sandbox_name=sandbox_name) |
| 250 | + """ |
| 251 | + |
| 252 | + print usage |
| 253 | + |
| 254 | + |
| 255 | +if __name__ == '__main__': |
| 256 | + main() |
| 257 | + |
| 258 | + |
| 259 | +# # Contents of quali_config.json |
| 260 | +# { |
| 261 | +# "server_name": "localhost", |
| 262 | +# "server_port": "82", |
| 263 | +# "username": "USERNAME", |
| 264 | +# "password": "PASSWORD", |
| 265 | +# "domain": "DOMAIN" |
| 266 | +# } |
0 commit comments