1050 lines
38 KiB
Python
1050 lines
38 KiB
Python
import httplib2
|
|
import json
|
|
import os
|
|
import re
|
|
import six
|
|
import sys
|
|
import time
|
|
from urlparse import urlparse
|
|
import xml.dom.minidom
|
|
|
|
from proboscis import before_class
|
|
from proboscis import test
|
|
from proboscis import TestProgram
|
|
from proboscis.asserts import *
|
|
from proboscis.asserts import Check
|
|
|
|
from troveclient.compat import Dbaas
|
|
from troveclient.compat import TroveHTTPClient
|
|
|
|
|
|
from client import ConfigFile
|
|
from client import SnippetWriter
|
|
from client import JsonClient
|
|
from client import XmlClient
|
|
|
|
|
|
print_req = True
|
|
|
|
|
|
class ExampleClient(object):
|
|
|
|
def __init__(self, config_file):
|
|
if not os.path.exists(config_file):
|
|
raise RuntimeError("Could not find Example CONF at %s." %
|
|
config_file)
|
|
file_contents = open(config_file, "r").read()
|
|
try:
|
|
config = json.loads(file_contents)
|
|
except Exception as exception:
|
|
msg = 'Error loading config file "%s".' % config_file
|
|
raise RuntimeError(msg, exception)
|
|
|
|
self.directory = config.get("directory", None)
|
|
if not self.directory.endswith('/'):
|
|
self.directory += '/'
|
|
print "directory = %s" % self.directory
|
|
self.api_url = config.get("api_url", None)
|
|
print "api_url = %s" % self.api_url
|
|
#auth
|
|
auth_url = config.get("auth_url", None)
|
|
print "auth_url = %s" % auth_url
|
|
username = config.get("username", None)
|
|
print "username = %s" % username
|
|
password = config.get("password", None)
|
|
print "password = %s" % password
|
|
self.tenant = config.get("tenant", None)
|
|
self.replace_host = config.get("replace_host", None)
|
|
print "tenant = %s" % self.tenant
|
|
self.replace_dns_hostname = config.get("replace_dns_hostname", None)
|
|
if auth_url:
|
|
auth_id, tenant_id = self.get_auth_token_id_tenant_id(auth_url,
|
|
username,
|
|
password)
|
|
else:
|
|
auth_id = self.tenant
|
|
tenant_id = self.tenant
|
|
|
|
print "id = %s" % auth_id
|
|
self.headers = {
|
|
'X-Auth-Token': str(auth_id)
|
|
}
|
|
print "tenantID = %s" % tenant_id
|
|
self.tenantID = tenant_id
|
|
self.dbaas_url = "%s/v1.0/%s" % (self.api_url, self.tenantID)
|
|
|
|
def write_request_file(self, name, content_type, url, method,
|
|
req_headers, request_body):
|
|
def write_request():
|
|
return self.output_request(url, req_headers, request_body,
|
|
content_type, method)
|
|
if print_req:
|
|
print("\t%s req url:%s" % (content_type, url))
|
|
print("\t%s req method:%s" % (content_type, method))
|
|
print("\t%s req headers:%s" % (content_type, req_headers))
|
|
print("\t%s req body:%s" % (content_type, request_body))
|
|
self.write_file(name, content_type, url, method, write_request)
|
|
|
|
def write_response_file(self, name, content_type, url, method,
|
|
resp, resp_content):
|
|
def write_response():
|
|
return self.output_response(resp, resp_content, content_type)
|
|
self.write_file(name, content_type, url, method, write_response)
|
|
if print_req:
|
|
print("\t%s resp:%s" % (content_type, resp))
|
|
print("\t%s resp content:%s" % (content_type, resp_content))
|
|
|
|
def write_file(self, name, content_type, url, method, func):
|
|
filename = "%sdb-%s-request.%s" % (self.directory, name, content_type)
|
|
with open(filename, "w") as file:
|
|
output = func()
|
|
output = output.replace(self.tenantID, '1234')
|
|
if self.replace_host:
|
|
output = output.replace(self.api_url, self.replace_host)
|
|
pre_host_port = urlparse(self.api_url).netloc
|
|
post_host = urlparse(self.replace_host).netloc
|
|
output = output.replace(pre_host_port, post_host)
|
|
|
|
file.write(output)
|
|
|
|
def version_http_call(self, name, method, json, xml,
|
|
output=True, print_resp=False):
|
|
json['url'] = "%s/%s" % (self.api_url, json['url'])
|
|
xml['url'] = "%s/%s" % (self.api_url, xml['url'])
|
|
return self.make_request(name, method, json, xml, output, print_resp)
|
|
|
|
def http_call(self, name, method, url, json, xml,
|
|
output=True, print_resp=False):
|
|
json['url'] = "%s/%s" % (self.dbaas_url, json['url'])
|
|
xml['url'] = "%s/%s" % (self.dbaas_url, xml['url'])
|
|
return self.make_request(name, method, json, xml, output, print_resp)
|
|
|
|
# print_req and print_resp for debugging purposes
|
|
def make_request(self, name, method, json, xml,
|
|
output=True, print_resp=False):
|
|
name = name.replace('_', '-')
|
|
print "http call for %s" % name
|
|
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
|
req_headers = {'User-Agent': "python-example-client",
|
|
'Content-Type': "application/json",
|
|
'Accept': "application/json"
|
|
}
|
|
req_headers.update(self.headers)
|
|
|
|
|
|
content_type = 'json'
|
|
request_body = json.get('body', None)
|
|
url = json.get('url')
|
|
if output:
|
|
self.write_request_file(name, 'json', url, method, req_headers,
|
|
request_body)
|
|
|
|
resp, resp_content = http.request(url, method, body=request_body,
|
|
headers=req_headers)
|
|
json_resp = resp, resp_content
|
|
if output:
|
|
filename = "%sdb-%s-response.%s" % (self.directory, name,
|
|
content_type)
|
|
self.write_response_file(name, 'json', url, method, resp,
|
|
resp_content)
|
|
|
|
|
|
content_type = 'xml'
|
|
req_headers['Accept'] = 'application/xml'
|
|
req_headers['Content-Type'] = 'application/xml'
|
|
request_body = xml.get('body', None)
|
|
url = xml.get('url')
|
|
if output:
|
|
filename = "%sdb-%s-request.%s" % (self.directory, name,
|
|
content_type)
|
|
output = self.write_request_file(name, 'xml', url, method,
|
|
req_headers, request_body)
|
|
resp, resp_content = http.request(url, method, body=request_body,
|
|
headers=req_headers)
|
|
xml_resp = resp, resp_content
|
|
if output:
|
|
filename = "%sdb-%s-response.%s" % (self.directory, name,
|
|
content_type)
|
|
self.write_response_file(name, 'xml', url, method, resp,
|
|
resp_content)
|
|
|
|
|
|
return json_resp, xml_resp
|
|
|
|
def _indent_xml(self, my_string):
|
|
my_string = my_string.encode("utf-8")
|
|
# convert to plain string without indents and spaces
|
|
my_re = re.compile(r'>\s+([^\s])', re.DOTALL)
|
|
my_string = myre.sub(r'>\g<1>', my_string)
|
|
my_string = xml.dom.minidom.parseString(my_string).toprettyxml()
|
|
# remove line breaks
|
|
my_re = re.compile(r'>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL)
|
|
my_string = my_re.sub(r'>\g<1></', my_string)
|
|
return my_string
|
|
|
|
def output_request(self, url, output_headers, body, content_type, method,
|
|
static_auth_token=True):
|
|
output_list = []
|
|
parsed = urlparse(url)
|
|
if parsed.query:
|
|
method_url = parsed.path + '?' + parsed.query
|
|
else:
|
|
method_url = parsed.path
|
|
output_list.append("%s %s HTTP/1.1" % (method, method_url))
|
|
output_list.append("User-Agent: %s" % output_headers['User-Agent'])
|
|
output_list.append("Host: %s" % parsed.netloc)
|
|
# static_auth_token option for documentation purposes
|
|
if static_auth_token:
|
|
output_token = '87c6033c-9ff6-405f-943e-2deb73f278b7'
|
|
else:
|
|
output_token = output_headers['X-Auth-Token']
|
|
output_list.append("X-Auth-Token: %s" % output_token)
|
|
output_list.append("Accept: %s" % output_headers['Accept'])
|
|
output_list.append("Content-Type: %s" % output_headers['Content-Type'])
|
|
output_list.append("")
|
|
pretty_body = self.format_body(body, content_type)
|
|
output_list.append("%s" % pretty_body)
|
|
output_list.append("")
|
|
return '\n'.join(output_list)
|
|
|
|
def output_response(self, resp, body, content_type):
|
|
output_list = []
|
|
version = "1.1" if resp.version == 11 else "1.0"
|
|
lines = [
|
|
["HTTP/%s %s %s" % (version, resp.status, resp.reason)],
|
|
["Content-Type: %s" % resp['content-type']],
|
|
["Content-Length: %s" % resp['content-length']],
|
|
["Date: %s" % resp['date']]]
|
|
new_lines = [x[0] for x in lines]
|
|
joined_lines = '\n'.join(new_lines)
|
|
output_list.append(joined_lines)
|
|
if body:
|
|
output_list.append("")
|
|
pretty_body = self.format_body(body, content_type)
|
|
output_list.append("%s" % pretty_body)
|
|
output_list.append("")
|
|
return '\n'.join(output_list)
|
|
|
|
def format_body(self, body, content_type):
|
|
if content_type == 'json':
|
|
try:
|
|
if self.replace_dns_hostname:
|
|
before = r'\"hostname\": \"[a-zA-Z0-9-_\.]*\"'
|
|
after = '\"hostname\": \"%s\"' % self.replace_dns_hostname
|
|
body = re.sub(before, after, body)
|
|
return json.dumps(json.loads(body), sort_keys=True, indent=4)
|
|
except Exception:
|
|
return body if body else ''
|
|
else:
|
|
# expected type of body is xml
|
|
try:
|
|
if self.replace_dns_hostname:
|
|
hostname = 'hostname=\"%s\"' % self.replace_dns_hostname,
|
|
body = re.sub(r'hostname=\"[a-zA-Z0-9-_\.]*\"',
|
|
hostname, body)
|
|
return self._indent_xml(body)
|
|
except Exception as ex:
|
|
return body if body else ''
|
|
|
|
def get_auth_token_id_tenant_id(self, url, username, password):
|
|
body = ('{"auth":{"tenantName": "%s", "passwordCredentials": '
|
|
'{"username": "%s", "password": "%s"}}}')
|
|
body = body % (self.tenant, username, password)
|
|
http = httplib2.Http(disable_ssl_certificate_validation=True)
|
|
req_headers = {'User-Agent': "python-example-client",
|
|
'Content-Type': "application/json",
|
|
'Accept': "application/json",
|
|
}
|
|
resp, body = http.request(url, 'POST', body=body, headers=req_headers)
|
|
auth = json.loads(body)
|
|
auth_id = auth['access']['token']['id']
|
|
tenant_id = auth['access']['token']['tenant']['id']
|
|
return auth_id, tenant_id
|
|
|
|
|
|
@test
|
|
def load_config_file():
|
|
global conf
|
|
print("RUNNING ARGS : " + str(sys.argv))
|
|
conf = None
|
|
for arg in sys.argv[1:]:
|
|
conf_file_path = os.path.expanduser(arg)
|
|
conf = ConfigFile(conf_file_path)
|
|
return
|
|
if not conf:
|
|
fail("Missing conf file.")
|
|
|
|
def create_client(cls=TroveHTTPClient):
|
|
client = Dbaas(conf.username, conf.password, tenant=conf.tenant,
|
|
auth_url="blah/", auth_strategy='fake',
|
|
insecure=True, service_type='trove',
|
|
service_url=conf.dbaas_url, client_cls=cls)
|
|
return client
|
|
|
|
class ClientPair(object):
|
|
"""
|
|
Combines a Json and XML version of the Dbaas client.
|
|
"""
|
|
|
|
def __init__(self):
|
|
snippet_writer = SnippetWriter(conf)
|
|
def make_client(cls):
|
|
client = create_client(cls)
|
|
client.client.name = "auth"
|
|
client.client.snippet_writer = snippet_writer
|
|
client.authenticate()
|
|
return client
|
|
self.json = make_client(JsonClient)
|
|
self.xml = make_client(XmlClient)
|
|
self.clients = [self.json, self.xml]
|
|
|
|
def do(self, name, url, method, status, reason, func, func_args=None):
|
|
"""
|
|
Performs the given function twice, first for the JSON client, then for
|
|
the XML one, and writes both to their respective files.
|
|
'name' is the name of the file, while 'url,' 'method,' 'status,'
|
|
and 'reason' are expected values that are asserted against.
|
|
If func_args is present, it is a list of lists, each one of which
|
|
is passed as the *args to the two invocations of "func".
|
|
"""
|
|
func_args = func_args or [[], []]
|
|
snippet_writer = SnippetWriter(conf)
|
|
results = []
|
|
for index, client in enumerate(self.clients):
|
|
client.client.snippet_writer = snippet_writer
|
|
client.client.name = name
|
|
args = func_args[index]
|
|
result = func(client, *args)
|
|
with Check() as check:
|
|
if isinstance(url, (list, tuple)):
|
|
check.equal(client.client.old_info['url'], url[index])
|
|
else:
|
|
check.equal(client.client.old_info['url'], url)
|
|
check.equal(client.client.old_info['method'], method)
|
|
check.equal(client.client.old_info['response_headers'].status,
|
|
status)
|
|
check.equal(client.client.old_info['response_headers'].reason,
|
|
reason)
|
|
results.append(result)
|
|
# To prevent this from writing a snippet somewhere else...
|
|
client.client.name = "junk"
|
|
|
|
return results
|
|
|
|
|
|
JSON_INDEX = 0
|
|
XML_INDEX = 1
|
|
|
|
@test(depends_on=[load_config_file])
|
|
class Versions(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def get_versions(self):
|
|
self.clients.do("versions",
|
|
"", "GET", 200, "OK",
|
|
lambda client : client.versions.index(conf.api_url))
|
|
|
|
|
|
@test
|
|
def get_version(self):
|
|
self.clients.do("versions",
|
|
"/v1.0", "GET", 200, "OK",
|
|
lambda client : client.versions.index(conf.api_url + "/v1.0/"))
|
|
|
|
|
|
@test(depends_on=[load_config_file])
|
|
class Flavors(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def get_flavors(self):
|
|
self.clients.do("flavors",
|
|
"/flavors", "GET", 200, "OK",
|
|
lambda client : client.flavors.list())
|
|
|
|
@test
|
|
def get_flavor_by_id(self):
|
|
self.clients.do("flavors_by_id",
|
|
"/flavors/1", "GET", 200, "OK",
|
|
lambda client : client.flavors.get(1))
|
|
|
|
|
|
@test(depends_on=[load_config_file])
|
|
def clean_slate():
|
|
client = create_client()
|
|
client.client.name = "list"
|
|
instances = client.instances.list()
|
|
assert_equal(0, len(instances), "Instance count must be zero.")
|
|
|
|
|
|
@test(depends_on=[clean_slate])
|
|
class CreateInstance(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def post_create_instance(self):
|
|
def create_instance(client, name):
|
|
instance = client.instances.create(name, 1, volume={'size':2},
|
|
databases=[{
|
|
"name": "sampledb",
|
|
"character_set": "utf8",
|
|
"collate": "utf8_general_ci"
|
|
},{
|
|
"name": "nextround"
|
|
}
|
|
],
|
|
users =[{
|
|
"databases":[{ "name":"sampledb"}],
|
|
"name":"demouser",
|
|
"password": "demopassword"
|
|
}
|
|
])
|
|
assert_equal(instance.status, "BUILD")
|
|
return instance
|
|
self.instances = self.clients.do("create_instance",
|
|
"/instances", "POST", 200, "OK",
|
|
create_instance,
|
|
(["json_rack_instance"], ["xml_rack_instance"]))
|
|
#self.instance_j = create_instance(self.clients.json,
|
|
# "json_rack_instance")
|
|
#self.instance_x = create_instance(self.clients.xml,
|
|
# "xml_rack_instance")
|
|
|
|
@test(depends_on=[post_create_instance])
|
|
def wait_for_instances(self):
|
|
for instance in self.instances:
|
|
while instance.status != "ACTIVE":
|
|
assert_equal(instance.status, "BUILD")
|
|
instance.get()
|
|
time.sleep(0.1)
|
|
global json_instance
|
|
json_instance = self.instances[0]
|
|
global xml_instance
|
|
xml_instance = self.instances[1]
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class Databases(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def post_create_databases(self):
|
|
self.clients.do("create_databases",
|
|
("/instances/%s/databases" % json_instance.id,
|
|
"/instances/%s/databases" % xml_instance.id),
|
|
"POST", 202, "Accepted",
|
|
lambda client, id : client.databases.create(id, databases=[
|
|
{
|
|
"name": "testingdb",
|
|
"character_set": "utf8",
|
|
"collate": "utf8_general_ci"
|
|
},
|
|
{
|
|
"name": "anotherdb"
|
|
},
|
|
{
|
|
"name": "oneMoreDB"
|
|
}
|
|
]), ([json_instance.id], [xml_instance.id]))
|
|
|
|
@test(depends_on=[post_create_databases])
|
|
def get_list_databases(self):
|
|
results = self.clients.do("list_databases",
|
|
("/instances/%s/databases" % json_instance.id,
|
|
"/instances/%s/databases" % xml_instance.id),
|
|
"GET", 200, "OK",
|
|
lambda client, id : client.databases.list(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
|
|
@test(depends_on=[post_create_databases])
|
|
def get_list_databases_limit_two(self):
|
|
results = self.clients.do("list_databases_pagination",
|
|
("/instances/%s/databases?limit=1" % json_instance.id,
|
|
"/instances/%s/databases?limit=2" % xml_instance.id),
|
|
"GET", 200, "OK",
|
|
lambda client, id, limit : client.databases.list(id, limit=limit),
|
|
([json_instance.id, 1], [xml_instance.id, 2]))
|
|
assert_equal(1, len(results[JSON_INDEX]))
|
|
assert_equal(2, len(results[XML_INDEX]))
|
|
assert_equal("anotherdb", results[JSON_INDEX].next)
|
|
assert_equal("nextround", results[XML_INDEX].next)
|
|
|
|
@test(depends_on=[post_create_databases],
|
|
runs_after=[get_list_databases, get_list_databases_limit_two])
|
|
def delete_databases(self):
|
|
results = self.clients.do("delete_databases",
|
|
("/instances/%s/databases/testingdb" % json_instance.id,
|
|
"/instances/%s/databases/oneMoreDB" % xml_instance.id),
|
|
"DELETE", 202, "Accepted",
|
|
lambda client, id, name : client.databases.delete(id, name),
|
|
([json_instance.id, 'testingdb'], [xml_instance.id, 'oneMoreDB']))
|
|
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class Users(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def post_create_users(self):
|
|
results = self.clients.do("create_users",
|
|
("/instances/%s/users" % json_instance.id,
|
|
"/instances/%s/users" % xml_instance.id),
|
|
"POST", 202, "Accepted",
|
|
lambda client, id : client.users.create(id, [
|
|
{
|
|
"name": "dbuser1",
|
|
"password": "password",
|
|
"database": "databaseA"
|
|
},
|
|
{
|
|
"name": "dbuser2",
|
|
"password": "password",
|
|
"databases": [
|
|
{
|
|
"name": "databaseB"
|
|
},
|
|
{
|
|
"name": "databaseC"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "dbuser3",
|
|
"password": "password",
|
|
"database": "databaseD"
|
|
}
|
|
]),
|
|
([json_instance.id], [xml_instance.id]))
|
|
|
|
@test(depends_on=[post_create_users])
|
|
def get_list_users(self):
|
|
results = self.clients.do("list_users",
|
|
("/instances/%s/users" % json_instance.id,
|
|
"/instances/%s/users" % xml_instance.id),
|
|
"GET", 200, "OK",
|
|
lambda client, id : client.users.list(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
|
|
@test(depends_on=[post_create_users])
|
|
def get_list_users_limit_two(self):
|
|
results = self.clients.do("list_users_pagination",
|
|
("/instances/%s/users?limit=2" % json_instance.id,
|
|
"/instances/%s/users?limit=2" % xml_instance.id),
|
|
"GET", 200, "OK",
|
|
lambda client, id : client.users.list(id, limit=2),
|
|
([json_instance.id], [xml_instance.id]))
|
|
|
|
@test(depends_on=[post_create_users],
|
|
runs_after=[get_list_users, get_list_users_limit_two])
|
|
def delete_users(self):
|
|
user_name = "testuser"
|
|
results = self.clients.do("delete_users",
|
|
("/instances/%s/users/%s" % (json_instance.id, user_name),
|
|
"/instances/%s/users/%s" % (xml_instance.id, user_name)),
|
|
"DELETE", 202, "Accepted",
|
|
lambda client, id : client.users.delete(id, user=user_name),
|
|
([json_instance.id], [xml_instance.id]))
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class Root(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def post_enable_root_access(self):
|
|
results = self.clients.do("enable_root_user",
|
|
("/instances/%s/root" % json_instance.id,
|
|
"/instances/%s/root" % xml_instance.id),
|
|
"POST", 200, "OK",
|
|
lambda client, id : client.root.create(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
|
|
@test(depends_on=[post_enable_root_access])
|
|
def get_check_root_access(self):
|
|
results = self.clients.do("check_root_user",
|
|
("/instances/%s/root" % json_instance.id,
|
|
"/instances/%s/root" % xml_instance.id),
|
|
"GET", 200, "OK",
|
|
lambda client, id : client.root.is_root_enabled(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
assert_equal(results[JSON_INDEX], True)
|
|
assert_equal(results[XML_INDEX], True)
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class InstanceList(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def get_list_instance_index(self):
|
|
results = self.clients.do("instances_index",
|
|
"/instances", "GET", 200, "OK",
|
|
lambda client : client.instances.list())
|
|
for result in results:
|
|
assert_equal(2, len(result))
|
|
|
|
@test
|
|
def get_instance_details(self):
|
|
results = self.clients.do("instance_status_detail",
|
|
("/instances/%s" % json_instance.id,
|
|
"/instances/%s" % xml_instance.id),
|
|
"GET", 200, "OK",
|
|
lambda client, id : client.instances.get(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
assert_equal(results[JSON_INDEX].id, json_instance.id)
|
|
assert_equal(results[XML_INDEX].id, xml_instance.id)
|
|
|
|
@test
|
|
def get_list_instance_index_limit_two(self):
|
|
third_instance = self.clients.json.instances.create(
|
|
"The Third Instance", 1, volume={'size':2})
|
|
while third_instance.status != "ACTIVE":
|
|
third_instance.get()
|
|
time.sleep(0.1)
|
|
|
|
results = self.clients.do("instances_index_pagination",
|
|
"/instances?limit=2", "GET", 200, "OK",
|
|
lambda client : client.instances.list(limit=2))
|
|
for result in results:
|
|
assert_equal(2, len(result))
|
|
|
|
self.clients.json.instances.delete(third_instance.id)
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class Actions(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
def _wait_for_active(self, *acceptable_states):
|
|
for instance in (json_instance, xml_instance):
|
|
instance.get()
|
|
print('instance.status=%s' % instance.status)
|
|
while instance.status != "ACTIVE":
|
|
assert_true(instance.status in acceptable_states,
|
|
"Instance status == %s; expected it to be one of these: %s"
|
|
% (instance.status, acceptable_states))
|
|
instance.get()
|
|
time.sleep(0.1)
|
|
|
|
@test
|
|
def instance_restart(self):
|
|
results = self.clients.do("instance_restart",
|
|
("/instances/%s/action" % json_instance.id,
|
|
"/instances/%s/action" % xml_instance.id),
|
|
"POST", 202, "Accepted",
|
|
lambda client, id : client.instances.restart(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
self._wait_for_active("RESTART")
|
|
|
|
@test
|
|
def instance_resize_volume(self):
|
|
results = self.clients.do("instance_resize_volume",
|
|
("/instances/%s/action" % json_instance.id,
|
|
"/instances/%s/action" % xml_instance.id),
|
|
"POST", 202, "Accepted",
|
|
lambda client, id : client.instances.resize_volume(id, 4),
|
|
([json_instance.id], [xml_instance.id]))
|
|
self._wait_for_active("RESIZE")
|
|
assert_equal(json_instance.volume['size'], 4)
|
|
assert_equal(xml_instance.volume['size'], '4')
|
|
|
|
@test
|
|
def instance_resize_flavor(self):
|
|
results = self.clients.do("instance_resize_flavor",
|
|
("/instances/%s/action" % json_instance.id,
|
|
"/instances/%s/action" % xml_instance.id),
|
|
"POST", 202, "Accepted",
|
|
lambda client, id : client.instances.resize_flavor(id, 3),
|
|
([json_instance.id], [xml_instance.id]))
|
|
self._wait_for_active("RESIZE")
|
|
assert_equal(json_instance.flavor['id'], '3')
|
|
assert_equal(xml_instance.flavor['id'], '3')
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances', "MgmtHosts"])
|
|
class MgmtHosts(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def mgmt_list_hosts(self):
|
|
results = self.clients.do("mgmt_list_hosts",
|
|
"/mgmt/hosts", "GET", 200, "OK",
|
|
lambda client : client.mgmt.hosts.index())
|
|
with Check() as check:
|
|
for hosts in results:
|
|
check.equal(1, len(hosts))
|
|
check.equal("fake_host", hosts[0].name)
|
|
check.equal(2, results[0][0].instanceCount)
|
|
# In XML land this is a string. :'(
|
|
check.equal("2", results[1][0].instanceCount)
|
|
|
|
@test
|
|
def mgmt_get_host_detail(self):
|
|
results = self.clients.do("mgmt_get_host_detail",
|
|
"/mgmt/hosts/fake_host", "GET", 200, "OK",
|
|
lambda client : client.mgmt.hosts.get("fake_host"))
|
|
with Check() as check:
|
|
for host in results:
|
|
check.equal(results[0].name, "fake_host")
|
|
check.equal(results[1].name, "fake_host")
|
|
# XML entries won't come back as these types. :(
|
|
check.true(isinstance(results[0].percentUsed, int)),
|
|
check.true(isinstance(results[0].totalRAM, int)),
|
|
check.true(isinstance(results[0].usedRAM, int)),
|
|
with Check() as check:
|
|
for host in results:
|
|
check.equal(2, len(host.instances))
|
|
for instance in host.instances:
|
|
check.equal(instance['status'], 'ACTIVE')
|
|
check.true(instance['name'] == 'json_rack_instance' or
|
|
instance['name'] == 'xml_rack_instance')
|
|
#TODO: Check with GUID regex.
|
|
check.true(isinstance(instance['id'], six.string_types))
|
|
check.true(isinstance(instance['server_id'],
|
|
six.string_types))
|
|
check.true(isinstance(instance['tenant_id'],
|
|
six.string_types))
|
|
|
|
@test
|
|
def mgmt_host_update_all(self):
|
|
results = self.clients.do("mgmt_host_update",
|
|
"/mgmt/hosts/fake_host/instances/action",
|
|
"POST", 202, "Accepted",
|
|
lambda client : client.mgmt.hosts.update_all("fake_host"))
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class MgmtStorage(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def mgmt_get_storage(self):
|
|
results = self.clients.do("mgmt_get_storage",
|
|
"/mgmt/storage", "GET", 200, "OK",
|
|
lambda client : client.mgmt.storage.index())
|
|
for index, devices in enumerate(results):
|
|
with Check() as check:
|
|
check.equal(1, len(devices))
|
|
device = devices[0]
|
|
check.equal(int(device.capacity['available']), 90)
|
|
check.equal(int(device.capacity['total']), 100)
|
|
check.equal(device.name, "fake_storage")
|
|
check.equal(int(device.provision['available']), 40)
|
|
check.equal(int(device.provision['percent']), 10)
|
|
check.equal(int(device.provision['total']), 50)
|
|
check.equal(device.type, "test_type")
|
|
check.equal(int(device.used), 10)
|
|
if index == JSON_INDEX:
|
|
check.true(isinstance(device.capacity['available'], int))
|
|
check.true(isinstance(device.capacity['total'], int))
|
|
check.true(isinstance(device.provision['available'], int))
|
|
check.true(isinstance(device.provision['percent'], int))
|
|
check.true(isinstance(device.provision['total'], int))
|
|
check.true(isinstance(device.used, int))
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class MgmtAccount(object):
|
|
|
|
@before_class
|
|
def setup(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def mgmt_get_account_details(self):
|
|
results = self.clients.do("mgmt_get_account_details",
|
|
"/mgmt/accounts/admin", "GET", 200, "OK",
|
|
lambda client : client.mgmt.accounts.show("admin"))
|
|
with Check() as check:
|
|
for account_info in results:
|
|
check.equal(2, len(account_info.instances))
|
|
check.equal('admin', account_info.id)
|
|
|
|
@test
|
|
def mgmt_get_account_list(self):
|
|
results = self.clients.do("mgmt_list_accounts",
|
|
"/mgmt/accounts", "GET", 200, "OK",
|
|
lambda client : client.mgmt.accounts.index())
|
|
for index, result in enumerate(results):
|
|
for account in result.accounts:
|
|
assert_equal('admin', account['id'])
|
|
if index == JSON_INDEX:
|
|
assert_equal(2, account['num_instances'])
|
|
else:
|
|
assert_equal("2", account['num_instances'])
|
|
|
|
|
|
def for_both(func):
|
|
def both(self):
|
|
for result in self.results:
|
|
func(self, result)
|
|
return both
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class MgmtInstance(object):
|
|
|
|
@before_class
|
|
def mgmt_get_instance_details(self):
|
|
self.clients = ClientPair()
|
|
self.results = self.clients.do("mgmt_get_instance_details",
|
|
("/mgmt/instances/%s" % json_instance.id,
|
|
"/mgmt/instances/%s" % xml_instance.id),
|
|
"GET", 200, "OK",
|
|
lambda client, id : client.mgmt.instances.show(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
|
|
@test
|
|
@for_both
|
|
def created(self, result):
|
|
#TODO: use regex
|
|
assert_true(isinstance(result.created, six.string_types))
|
|
|
|
@test
|
|
def deleted(self):
|
|
assert_equal(self.results[JSON_INDEX].deleted, False)
|
|
assert_equal(self.results[XML_INDEX].deleted, "False")
|
|
|
|
@test
|
|
@for_both
|
|
def flavor(self, result):
|
|
assert_true(result.flavor['id'] == "1" or result.flavor['id'] == "3")
|
|
assert_equal(len(result.flavor['links']), 2)
|
|
#TODO: validate the flavors format.
|
|
|
|
@test
|
|
@for_both
|
|
def guest_status(self, result):
|
|
assert_equal(result.guest_status['state_description'], 'running')
|
|
|
|
@test
|
|
@for_both
|
|
def host(self, result):
|
|
assert_equal(result.host, 'fake_host')
|
|
|
|
@test
|
|
def id(self):
|
|
assert_equal(self.results[JSON_INDEX].id, json_instance.id)
|
|
assert_equal(self.results[XML_INDEX].id, xml_instance.id)
|
|
|
|
@test
|
|
@for_both
|
|
def links(self, result):
|
|
assert_true(isinstance(result.links, list))
|
|
for link in result.links:
|
|
assert_true(isinstance(link, dict))
|
|
assert_true(isinstance(link['href'], six.string_types))
|
|
assert_true(isinstance(link['rel'], six.string_types))
|
|
|
|
@test
|
|
def local_id(self):
|
|
#TODO: regex
|
|
assert_true(isinstance(self.results[JSON_INDEX].local_id, int))
|
|
assert_true(isinstance(self.results[XML_INDEX].local_id,
|
|
six.string_types))
|
|
|
|
@test
|
|
@for_both
|
|
def name(self, result):
|
|
#TODO: regex
|
|
assert_true(isinstance(result.name,
|
|
six.string_types))
|
|
|
|
@test
|
|
@for_both
|
|
def server_id(self, result):
|
|
#TODO: regex
|
|
assert_true(isinstance(result.server_id,
|
|
six.string_types))
|
|
|
|
@test
|
|
@for_both
|
|
def status(self, result):
|
|
#TODO: regex
|
|
assert_equal("ACTIVE", result.status)
|
|
|
|
@test
|
|
@for_both
|
|
def task_description(self, result):
|
|
assert_equal(result.task_description, "No tasks for the instance.")
|
|
|
|
@test
|
|
@for_both
|
|
def tenant_id(self, result):
|
|
assert_equal(result.tenant_id, "admin")
|
|
|
|
@test
|
|
@for_both
|
|
def updated(self, result):
|
|
#TODO: regex
|
|
assert_true(isinstance(result.updated,
|
|
six.string_types))
|
|
|
|
@test
|
|
@for_both
|
|
def volume(self, result):
|
|
#TODO: regex
|
|
assert_true(isinstance(result.volume, dict))
|
|
assert_true('id' in result.volume)
|
|
assert_true('size' in result.volume)
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class MgmtInstanceIndex(object):
|
|
|
|
@before_class
|
|
def mgmt_get_instance_details(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def mgmt_instance_index(self, deleted=False):
|
|
url = "/mgmt/instances?deleted=false"
|
|
results = self.clients.do("mgmt_instance_index",
|
|
"/mgmt/instances?deleted=false", "GET", 200, "OK",
|
|
lambda client : client.mgmt.instances.index(deleted=False))
|
|
#TODO: Valdiate everything... *sigh*
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class MgmtInstanceDiagnostics(object):
|
|
|
|
@before_class
|
|
def mgmt_get_instance_details(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def mgmt_get_instance_diagnostics(self):
|
|
results = self.clients.do("mgmt_instance_diagnostics",
|
|
("/mgmt/instances/%s/diagnostics" % json_instance.id,
|
|
"/mgmt/instances/%s/diagnostics" % xml_instance.id),
|
|
"GET", 200, "OK",
|
|
lambda client, id: client.diagnostics.get(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
#TODO: validate the actual stuff that comes back (booorring!).
|
|
|
|
|
|
@test(depends_on=[CreateInstance])
|
|
class MgmtInstanceRoot(object):
|
|
|
|
@before_class
|
|
def mgmt_get_instance_details(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def mgmt_get_root_details(self):
|
|
results = self.clients.do("mgmt_get_root_details",
|
|
("/mgmt/instances/%s/root" % json_instance.id,
|
|
"/mgmt/instances/%s/root" % xml_instance.id),
|
|
"GET", 200, "OK",
|
|
lambda client, id: client.mgmt.instances.root_enabled_history(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
#TODO: validate the actual stuff that comes back (booorring!).
|
|
|
|
|
|
@test(depends_on=[CreateInstance])
|
|
class MgmtInstanceHWInfo(object):
|
|
|
|
@before_class
|
|
def mgmt_get_instance_details(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def mgmt_get_hw_info(self):
|
|
results = self.clients.do("mgmt_get_hw_info",
|
|
("/mgmt/instances/%s/hwinfo" % json_instance.id,
|
|
"/mgmt/instances/%s/hwinfo" % xml_instance.id),
|
|
"GET", 200, "OK",
|
|
lambda client, id: client.hw_info.get(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
|
|
|
|
@test(depends_on=[CreateInstance], groups=['uses_instances'])
|
|
class MgmtInstanceReboot(object):
|
|
|
|
@before_class
|
|
def mgmt_get_instance_details(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def mgmt_instance_reboot(self):
|
|
results = self.clients.do("instance_reboot",
|
|
("/mgmt/instances/%s/action" % json_instance.id,
|
|
"/mgmt/instances/%s/action" % xml_instance.id),
|
|
"POST", 202, "Accepted",
|
|
lambda client, id: client.mgmt.instances.reboot(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
|
|
|
|
@test(depends_on=[CreateInstance],
|
|
groups=['uses_instances'], enabled=False)
|
|
class MgmtInstanceGuestUpdate(object):
|
|
|
|
@before_class
|
|
def mgmt_get_instance_details(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def mgmt_instance_guest_update(self):
|
|
results = self.clients.do("guest_update",
|
|
("/mgmt/instances/%s/action" % json_instance.id,
|
|
"/mgmt/instances/%s/action" % xml_instance.id),
|
|
"POST", 202, "Accepted",
|
|
lambda client, id: client.mgmt.instances.update(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
|
|
|
|
@test(depends_on=[CreateInstance], runs_after_groups=['uses_instances'])
|
|
class ZzzDeleteInstance(object):
|
|
|
|
@before_class
|
|
def mgmt_get_instance_details(self):
|
|
self.clients = ClientPair()
|
|
|
|
@test
|
|
def zzz_delete_instance(self):
|
|
results = self.clients.do("delete_instance",
|
|
("/instances/%s" % json_instance.id,
|
|
"/instances/%s" % xml_instance.id),
|
|
"DELETE", 202, "Accepted",
|
|
lambda client, id: client.instances.delete(id),
|
|
([json_instance.id], [xml_instance.id]))
|
|
for result in json_instance, xml_instance:
|
|
result.get()
|
|
assert_equal(result.status, "SHUTDOWN")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
TestProgram().run_and_exit()
|