def delete(self, key): """Delete key/value from environment's userdata. Args: key (str): The name of key to delete, along with value Returns: str: The response from Skytap, or "{}". """ new_content = "" del_key = False lines = self.contents.split("\n") for i in lines: if i != "": j = i.split() if len(j) > 0 and j[0] == (key + ":"): del_key = True else: new_content += (i.strip() + "\n") if del_key: Utils.info('Deleting key \"' + key + '\".') api = ApiClient() data = {"contents": "" + new_content} response = api.rest(self.url, data, 'POST') self.refresh() return response else: Utils.info('Key \"' + key + '\" already exists.') return "{}"
def add(self, key, value): """Add value to environment's userdata. Args: key (str): The name of the value's key. value (str): The value to add. Returns: str: The response from Skytap, or "{}". """ add_key = True lines = self.contents.split("\n") for i in lines: if i != "": j = i.split() if len(j) > 0 and j[0] == (key + ":"): add_key = False if add_key: Utils.info('Adding key \"' + key + '\" with value \"' '' + value + '\"') api = ApiClient() new_content = "" + key + ": " + value + "\n" + self.contents data = {"contents": new_content} response = api.rest(self.url, data, 'POST') self.data[key] = value self.refresh() return response else: Utils.info('Key \"' + key + '\" with value \"' + value + '\"' 'already exists.') return "{}"
def remove_user(self, user): """Remove a :class:`user` from the group. Args: user (int): id of the user to remove. Raises: TypeError: If user is not an :class:`int`. KeyError: If user is not in :class:`Users` list. Returns: bool: True if the user was removed. Example: >>> groups = skytap.Groups() >>> groups[1234].remove_user(12345) """ if type(user) is not int: raise TypeError('User must be an int.') Utils.info('Removing user ' + str(user) + ' from group: ' + self.name) api = ApiClient() api.rest(self.url + '/users/' + str(user), {}, 'DELETE') self.refresh() return user not in self.users
def remove_user(self, user): """Remove a :class:`user` from the group. Args: user (int): id of the user to remove. Raises: TypeError: If user is not an :class:`int`. KeyError: If user is not in :class:`Users` list. Returns: bool: True if the user was removed. Example: >>> groups = skytap.Groups() >>> groups[1234].remove_user(12345) """ if (type(user) is not int): raise TypeError('User must be an int.') Utils.info('Removing user ' + str(user) + ' from group: ' + self.name) api = ApiClient() user_json = api.rest(self.url + '/users/' + str(user), {}, 'DELETE') self.refresh() return user not in self.users
def add_user(self, user): """Add a :class:`User` to the group. Args: user (int): id of the user to add. Raises: TypeError: If user is not an :class:`int`. KeyError: If user is not in :class:`Users` list. Returns: bool: True if the user was added. Example: >>> groups = skytap.Groups() >>> users = skytap.Users() >>> for u in users: ... groups[12345].add(u.id) """ if (type(user) is not int): raise TypeError('User must be an int.') Utils.info('Adding user ' + str(user) + ' to group: ' + self.name) api = ApiClient() user_json = api.rest(self.url + '/users/' + str(user) + '.json', {}, 'PUT') self.refresh() return user in self.users
def add(self, login_name, email=None): """Add one user. Args: login_name (str): The login id of the account, usually an email. email (str): The email of the account. If blank, will use login_name. Returns: int: The new user id from Skytap. Example: .. code-block:: python users = skytap.Users() new_user = users.add('*****@*****.**') print(users[new_user].login_name) """ Utils.info('Adding user: '******'.json' response = api.rest(url, data, 'POST') new_user = json.loads(response) self.refresh() if 'id' in new_user: return int(new_user['id']) Utils.warning('Trying to create user (' + login_name + '), but ' + 'got an unexpected return from Skytap. Response:\n' + response) return 0
def delete_line(self, line): """Delete line from environment's userdata. Args: line (int): line number to delete. Returns: str: The response from Skytap. """ line = str(line) lines = self.contents.split("\n") new_content = "" for i in lines: if i != "": if i.strip() != line.strip(): new_content += (i.strip() + "\n") Utils.info('Removing line: \"' + str(line) + '\"') api = ApiClient() data = {"contents": new_content.lstrip()} response = api.rest(self.url, data, 'POST') self.refresh() return response
def add_user(self, user): """Add a :class:`User` to the group. Args: user (int): id of the user to add. Raises: TypeError: If user is not an :class:`int`. KeyError: If user is not in :class:`Users` list. Returns: bool: True if the user was added. Example: >>> groups = skytap.Groups() >>> users = skytap.Users() >>> for u in users: ... groups[12345].add(u.id) """ if type(user) is not int: raise TypeError('User must be an int.') Utils.info('Adding user ' + str(user) + ' to group: ' + self.name) api = ApiClient() api.rest(self.url + '/users/' + str(user) + '.json', {}, 'PUT') self.refresh() return user in self.users
def add(self, group, description=''): """Add one group. Args: group (str): The group name to add. description (str): The group description to add. Returns: int: The new group id from Skytap. Example: .. code-block:: python groups = skytap.Groups() new_group = groups.add('muppets', 'felt covered friends') print(groups[new_group].name) """ Utils.info('Adding group: ' + group) api = ApiClient() data = {"name": group, "description": description} url = self.url + '.json' response = api.rest(url, data, 'POST') new_group = json.loads(response) self.refresh() if 'id' in new_group: return int(new_group['id']) Utils.warning('Trying to create group (' + group + '), but ' + 'got an unexpected return from Skytap. Response:\n' + response) return 0
def delete(self): """Delete this export job.""" Utils.info('Deleting job ' + str(self.id) + ' from queue.') api = ApiClient() response = api.rest(self.url, {}, 'DELETE') return response
def delete(self): """Delete a VM. In general, it'd seem wise not to do this very often. """ Utils.info('Deleting VM: ' + str(self.id) + '(' + self.name + ')') api = ApiClient() response = api.rest(self.url, {}, 'DELETE') return response
def delete(self): """Delete the group.""" Utils.info('Deleting group: ' + str(self.id) + ' (' + self.name + ')') api = ApiClient() response = api.rest(self.url_v1, {}, 'DELETE') return response
def enable(self, label_id): """Enable a label category.""" if not self.url.endswith("label_categories"): return "Can only enable label categories." Utils.info("Enabling label category of id " + str(label_id) + ".") api = ApiClient() data = {"enabled": "True"} response = api.rest(self.url + "/" + str(label_id), data, "PUT") self.refresh() return response
def disable(self, label_id): """Disable a label category (the closest thing to deleting).""" if not self.url.endswith("label_categories"): return "Can only disable label categories." Utils.info("Disabling label category of id " + str(label_id) + ".") api = ApiClient() data = {"enabled": "False"} response = api.rest(self.url + "/" + str(label_id), data, "PUT") self.refresh() return response
def create(self, name, single_value): """Create label that is single or multi-valued.""" if not self.url.endswith("label_categories"): return "Cannot create label. Did you mean to use \"add()\"?" Utils.info("Creating Label: " + name + "" ". Single-value: " + str(single_value)) api = ApiClient() data = [{"name": name, "single-value": single_value}] response = api.rest(self.url, data, "POST") self.refresh() return response
def add(self, value, category): """Add label to environment or VM.""" if self.url.endswith("label_categories"): return "Cannot add label. Did you mean to use \"create()\"?" Utils.info("Adding Label to " + category + " with value " + value + ".") api = ApiClient() data = [{"label_category": category, "value": value}] response = api.rest(self.url, data, "PUT") self.refresh() return response
def add(self, note): """Add one note. Args: note (str): The note text to add. Returns: str: The response from Skytap, typically the new note. """ Utils.info('Adding note: ' + note) api = ApiClient() data = {"text": note} response = api.rest(self.url, data, 'POST') self.refresh() return response
def delete(self, transfer_user): """Delete the user.""" if isinstance(transfer_user, User): transfer_user = transfer_user.id if not isinstance(transfer_user, int): raise TypeError('transfer_user must be a User or int.') Utils.info('Deleting user: '******' (' + self.name + ') and transferring ' + 'resources to user id: ' + str(transfer_user)) api = ApiClient() transfer = {"transfer_user_id": str(transfer_user)} response = api.rest(self.url, transfer, 'DELETE') return response
def _check_response(self, resp, attempts=1): """Return true if the rseponse a good/reasonable one. If the HTTP status code is in the 200s, return True, otherwise try to determine what happened. If we're asked to retry, politely wait the appropraite amount of time and retry, otherwise, wait the retry_wait amount of time. Fail (return False) if we've exceeded our retry amount. """ if resp is None: raise ValueError('A response wasn\'t received') if 200 <= resp.status_code < 300: return True # If we made it this far, we need to handle an exception if attempts >= Config.max_http_attempts or (resp.status_code != 429 and resp.status_code != 423): Utils.error('Error recieved in API return. Response code: ' + str(resp.status_code) + '. Reponse text: ' + resp.text) # print(resp.headers) error_response = json.loads(resp.text) error_response['status_code'] = resp.status_code raise Exception(error_response) if resp.status_code == 423: # "Busy" if 'Retry-After' in resp.headers: Utils.info('Received HTTP 423. Retry-After set to ' + resp.headers['Retry-After'] + ' sec. Waiting to retry.') # noqa time.sleep(int(resp.headers['Retry-After']) + 1) else: Utils.info( 'Received HTTP 429. Too many requests. Waiting to retry.' ) # noqa time.sleep(Config.retry_wait) return False # Assume we're going to retry with exponential backoff # Should only get here on a 429 "too many requests" but it's # not clear from Skytap what their limits are on when we should retry. time.sleep(2**(attempts - 1)) return False
def create(self, vmid): """Create an export job from a vm in a template.""" if type(vmid) is not int: raise TypeError('vmid must be an int') Utils.info('creating export job for VM ' + str(vmid)) api = ApiClient() data = {"vm_id": vmid} url = self.url + '.json' response = api.rest(url, data, "POST") exports = json.loads(response) self.refresh() if 'id' in exports: return int(exports['id']) Utils.warning('Trying to create new export job from VM ' + vmid + ', but got an unexpected response from Skytap. ' + 'Response:\n' + response) return 0
def add_line(self, text, line=-1): """Add line to environment's userdata. Args: text (str): line of text to be added. (Required) line (int): line number to add to. If too large, default to last. Returns: str: The response from Skytap. """ try: line = int(line) except ValueError: return "{}" # Not an integer lines = self.contents.split("\n") new_content = "" line_found = False count = 0 for i in lines: if i != "": if line == count: new_content += (text.strip() + "\n") new_content += (i.strip() + "\n") line_found = True else: new_content += (i.strip() + "\n") count += 1 if not line_found: new_content += (text.strip() + "\n") Utils.info('Adding line: \"' + text + '\"') api = ApiClient() data = {"contents": new_content} response = api.rest(self.url, data, 'POST') self.refresh() return response
def _check_response(self, resp, attempts=1): """Return true if the rseponse a good/reasonable one. If the HTTP status code is in the 200s, return True, otherwise try to determine what happened. If we're asked to retry, politely wait the appropraite amount of time and retry, otherwise, wait the retry_wait amount of time. Fail (return False) if we've exceeded our retry amount. """ if resp is None: raise ValueError('A response wasn\'t received') if 200 <= resp.status_code < 300: return True # If we made it this far, we need to handle an exception if attempts >= Config.max_http_attempts or (resp.status_code != 429 and resp.status_code != 423): Utils.error('Error recieved in API return. Response code: ' + str(resp.status_code) + '. Reponse text: ' + resp.text) # print(resp.headers) error_response = json.loads(resp.text) error_response['status_code'] = resp.status_code raise Exception(error_response) if resp.status_code == 423: # "Busy" if 'Retry-After' in resp.headers: Utils.info('Received HTTP 423. Retry-After set to ' + resp.headers['Retry-After'] + ' sec. Waiting to retry.') # noqa time.sleep(int(resp.headers['Retry-After']) + 1) else: Utils.info('Received HTTP 429. Too many requests. Waiting to retry.') # noqa time.sleep(Config.retry_wait) return False # Assume we're going to retry with exponential backoff # Should only get here on a 429 "too many requests" but it's # not clear from Skytap what their limits are on when we should retry. time.sleep(2 ** (attempts - 1)) return False
def delete(self, note): """Delete one note. Args: note: The :class:`~skytap.models.Note` to delete. Returns: str: The response from Skytap. Raises: TypeError: If note is not a Note object. """ if note is None: return False if not isinstance(note, Note): raise TypeError Utils.info('Deleting note ID: ' + str(note.id)) api = ApiClient() url = self.url.replace('.json', '/' + str(note.id)) response = api.rest(url, {}, 'DELETE') self.refresh() return response
def delete(self): """Delete a service. Warning: Cannot be undone.""" Utils.info('Deleting published service: ' + str(self.id)) api = ApiClient() response = api.rest(self.url, {}, 'DELETE') return response
def delete(self): """Delete a service. Cannot be undone!""" Utils.info('Deleting published service: ' + str(self.id)) api = ApiClient() response = api.rest(self.url, {}, 'DELETE') return response