Created
September 9, 2019 11:14
-
-
Save EnriqCG/1cb7ed00889c69fdd07f0b5312cba681 to your computer and use it in GitHub Desktop.
Openstack client for creating and destroying instances
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Openstack client API for creating and destroying instances with the Nova API | |
Date: 04/09/2019 | |
Author: Enrique Carpintero | |
""" | |
import requests | |
import json | |
class OpenStackAPI: | |
def __init__(self, api_host): | |
self.host = api_host | |
def authenticate(self, user_id, password, project_id): | |
"""Authenticates with the password method on Keystone | |
and saves the token on the object for later use. | |
""" | |
r = requests.post("{}:5000/v3/auth/tokens".format(self.host), json= { | |
"auth": { | |
"identity": { | |
"methods": [ | |
"password" | |
], | |
"password": { | |
"user": { | |
"id": user_id, | |
"password": password | |
} | |
} | |
}, | |
"scope": { | |
"project": { | |
"id": project_id | |
} | |
} | |
} | |
}) | |
# | |
try: | |
self.headers = { | |
'X-Auth-Token': r.headers['X-Subject-Token'], | |
'Content-Type': 'application/json' | |
} | |
except KeyError: | |
print("Could not get token from Keystone") | |
raise SystemExit | |
def get_instances(self): | |
"""Returns a list of all available instances | |
Reference: https://docs.openstack.org/api-ref/compute/?expanded=show-server-details-detail#list-servers | |
""" | |
r = requests.get("{}:8774/v2.1/servers".format(self.host), headers=self.headers) | |
return r.json() | |
def get_instance_data_by_id(self, instance_id): | |
"""Returns instance data provided by Openstack | |
Reference: https://docs.openstack.org/api-ref/compute/?expanded=show-server-details-detail#show-server-details | |
""" | |
r = requests.get("{}:8774/v2.1/servers/{}".format(self.host, instance_id), headers=self.headers) | |
return r.json() | |
def get_instance_ip(self, instance_id): | |
"""Return the instance IP as a string. Returns False after 100 failed attempts. | |
Hammers the API on a loop until Neutron (network) allocates an IP. | |
""" | |
for _ in range(100): | |
try: | |
instance = self.get_instance_data_by_id(instance_id) | |
return instance['server']['addresses']['sharednet1'][0]['addr'] | |
except KeyError: | |
continue | |
return False | |
def create_instance(self, instance_name, image_id, flavor_id, network_id, security_group_name = None, user_data = None): | |
"""Nova API reference: https://docs.openstack.org/api-ref/compute/?expanded=create-server-detail#create-server | |
image_id, flavor_id and network_id can be obtained through Horizon | |
config_drive should always be True | |
user_data is a base64 encoded string for the cloud-init | |
""" | |
payload = { | |
"server": { | |
"name": instance_name, | |
"imageRef": image_id, | |
"flavorRef": flavor_id, | |
"networks": [{ | |
"uuid": network_id | |
}], | |
"config_drive": True | |
} | |
} | |
if security_group_name is not None: | |
payload['server']['security_groups'] = [{ "name": security_group_name }] | |
if user_data is not None: | |
payload['server']['user_data'] = user_data | |
r = requests.post("{}:8774/v2.1/servers".format(self.host), headers=self.headers, json= payload) | |
# Status code for resource creation is 202 Accepted | |
if r.status_code is not 202: | |
print("Could not create Nova instance", r.json()) | |
return r.json() | |
def delete_instance_by_id(self, instance_id): | |
"""Returns True if instance deletion is successful. False if unsuccessful | |
""" | |
r = requests.delete("{}:8774/v2.1/servers/{}".format(self.host, instance_id), headers=self.headers) | |
# 204 No Content - request was successful | |
return True if r.status_code is 204 else False | |
def delete_all_instances(self): | |
"""Iterates over created instances and executes a delete for each one of them | |
Once that is completed it checks if all instances were in fact deleted. | |
""" | |
instances = self.get_instances() | |
for instance in instances['servers']: | |
if self.delete_instance_by_id(instance['id']) is not True: | |
print("Could not delete instance with name: {}".format(instance['name'])) | |
instances = self.get_instances() | |
return True | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment