integration test updated and delete method for cluster/node
This commit is contained in:
parent
6557dc18e4
commit
458bb51a36
1
.gitignore
vendored
1
.gitignore
vendored
@ -12,3 +12,4 @@
|
||||
/.vagrant
|
||||
|
||||
/build
|
||||
/test/nosetests.xml
|
||||
|
@ -193,7 +193,7 @@ class ClusterCollectionHandler(BaseHandler):
|
||||
|
||||
class ClusterHandler(JSONHandler):
|
||||
|
||||
allowed_methods = ('GET', 'PUT')
|
||||
allowed_methods = ('GET', 'PUT', 'DELETE')
|
||||
model = Cluster
|
||||
fields = ('id', 'name')
|
||||
special_fields = ('nodes', 'release', 'task')
|
||||
@ -241,6 +241,14 @@ class ClusterHandler(JSONHandler):
|
||||
except ObjectDoesNotExist:
|
||||
return rc.NOT_FOUND
|
||||
|
||||
def delete(self, request, cluster_id):
|
||||
try:
|
||||
cluster = Cluster.objects.get(id=cluster_id)
|
||||
cluster.delete()
|
||||
return rc.DELETED
|
||||
except ObjectDoesNotExist:
|
||||
return rc.NOT_FOUND
|
||||
|
||||
|
||||
class NodeCollectionHandler(BaseHandler):
|
||||
|
||||
@ -269,7 +277,7 @@ class NodeCollectionHandler(BaseHandler):
|
||||
|
||||
class NodeHandler(JSONHandler):
|
||||
|
||||
allowed_methods = ('GET', 'PUT')
|
||||
allowed_methods = ('GET', 'PUT', 'DELETE')
|
||||
model = Node
|
||||
fields = ('id', 'name', 'metadata', 'status', 'mac', 'fqdn', 'ip',
|
||||
'redeployment_needed')
|
||||
@ -307,6 +315,14 @@ class NodeHandler(JSONHandler):
|
||||
node.save()
|
||||
return NodeHandler.render(node)
|
||||
|
||||
def delete(self, request, node_id):
|
||||
try:
|
||||
node = Node.objects.get(id=node_id)
|
||||
node.delete()
|
||||
return rc.DELETED
|
||||
except ObjectDoesNotExist:
|
||||
return rc.NOT_FOUND
|
||||
|
||||
|
||||
class AttributeCollectionHandler(BaseHandler):
|
||||
|
||||
@ -531,7 +547,7 @@ class ReleaseCollectionHandler(BaseHandler):
|
||||
|
||||
class ReleaseHandler(JSONHandler):
|
||||
|
||||
allowed_methods = ('GET',)
|
||||
allowed_methods = ('GET', 'DELETE')
|
||||
model = Release
|
||||
fields = ('id', 'name', 'version', 'description', 'networks_metadata')
|
||||
special_fields = ('roles',)
|
||||
@ -554,6 +570,14 @@ class ReleaseHandler(JSONHandler):
|
||||
except ObjectDoesNotExist:
|
||||
return rc.NOT_FOUND
|
||||
|
||||
def delete(self, request, release_id):
|
||||
try:
|
||||
release = Release.objects.get(id=release_id)
|
||||
release.delete()
|
||||
return rc.DELETED
|
||||
except ObjectDoesNotExist:
|
||||
return rc.NOT_FOUND
|
||||
|
||||
|
||||
class NetworkHandler(JSONHandler):
|
||||
|
||||
|
@ -137,11 +137,6 @@ def deploy_cluster(cluster_id):
|
||||
add_attrs = {}
|
||||
|
||||
roles_for_node = node.roles.all()
|
||||
# TODO(mihgen): It should be possible to have node w/o role assigned
|
||||
if not roles_for_node:
|
||||
message = "Task %s failed: Roles list for node %s is empty" \
|
||||
% (deploy_cluster.request.id, node.id)
|
||||
raise EmptyListError(message)
|
||||
|
||||
node_json['cluster_id'] = cluster_id
|
||||
for f in node._meta.fields:
|
||||
|
@ -154,6 +154,13 @@ class TestHandlers(TestCase):
|
||||
self.another_node.id)
|
||||
cluster = clusters_from_db[0]
|
||||
self.assertEquals(len(cluster.release.networks.all()), 3)
|
||||
# test delete
|
||||
resp = self.client.delete(
|
||||
reverse('cluster_handler', kwargs={'cluster_id': cluster.id}),
|
||||
"",
|
||||
"application/json"
|
||||
)
|
||||
self.assertEquals(resp.status_code, 204)
|
||||
|
||||
def test_cluster_update(self):
|
||||
updated_name = 'Updated cluster'
|
||||
@ -207,6 +214,14 @@ class TestHandlers(TestCase):
|
||||
nodes_from_db = Node.objects.filter(id=node_id)
|
||||
self.assertEquals(len(nodes_from_db), 1)
|
||||
|
||||
# test delete
|
||||
resp = self.client.delete(
|
||||
reverse('node_handler', kwargs={'node_id': node_id}),
|
||||
"",
|
||||
"application/json"
|
||||
)
|
||||
self.assertEquals(resp.status_code, 204)
|
||||
|
||||
def test_node_creation_using_put(self):
|
||||
node_id = '080000000002'
|
||||
|
||||
|
@ -67,7 +67,7 @@ class SSHClient(object):
|
||||
|
||||
|
||||
def exec_cmd(self, command):
|
||||
logging.info("Executing command: '%s'" % command)
|
||||
logging.info("Executing command: '%s'" % command.rstrip())
|
||||
chan = self.ssh_client.get_transport().open_session()
|
||||
stdin = chan.makefile('wb')
|
||||
stdout = chan.makefile('rb')
|
||||
|
@ -21,7 +21,8 @@ SOLO_PATH = os.path.join(os.path.dirname(__file__), "..", "..", "scripts", "agen
|
||||
DEPLOY_PATH = os.path.join(os.path.dirname(__file__), "..", "..", "bin", "deploy")
|
||||
COOKBOOKS_PATH = os.path.join(os.path.dirname(__file__), "..", "..", "cookbooks")
|
||||
SAMPLE_PATH = os.path.join(os.path.dirname(__file__), "..", "..", "scripts", "ci")
|
||||
SAMPLE_REMOTE_PATH = "/root"
|
||||
SAMPLE_REMOTE_PATH = "/home/ubuntu"
|
||||
|
||||
|
||||
class StillPendingException(Exception):
|
||||
pass
|
||||
@ -34,16 +35,18 @@ class TestNode(TestCase):
|
||||
self.remote = SSHClient()
|
||||
|
||||
def test_node(self):
|
||||
cookbook_remote_path = os.path.join(SAMPLE_REMOTE_PATH, "sample-cook")
|
||||
release_remote_path = os.path.join(SAMPLE_REMOTE_PATH, "sample-release.json")
|
||||
|
||||
logging.info("Starting slave node")
|
||||
admin_node = ci.environment.node['admin']
|
||||
admin_ip = admin_node.ip_address
|
||||
node = ci.environment.node['slave']
|
||||
node.start()
|
||||
|
||||
slave_id = node.interfaces[0].mac_address.replace(":", "").upper()
|
||||
admin_ip = str(admin_node.ip_address)
|
||||
slave = ci.environment.node['slave']
|
||||
slave_id = slave.interfaces[0].mac_address.replace(":", "").upper()
|
||||
logging.info("Starting slave node")
|
||||
slave.start()
|
||||
|
||||
self._load_sample_admin(
|
||||
host=admin_ip,
|
||||
user="ubuntu",
|
||||
passwd="r00tme"
|
||||
)
|
||||
|
||||
while True:
|
||||
logging.info("Waiting for slave agent to run...")
|
||||
@ -56,11 +59,18 @@ class TestNode(TestCase):
|
||||
else:
|
||||
time.sleep(15)
|
||||
|
||||
cluster = json.loads(self.client.post(
|
||||
"http://%s:8000/api/clusters" % admin_ip,
|
||||
data='{ "name": "MyOwnPrivateCluster", "release": 1 }',
|
||||
log=True
|
||||
))
|
||||
try:
|
||||
cluster = json.loads(self.client.get(
|
||||
"http://%s:8000/api/clusters/1" % admin_ip,
|
||||
log=True
|
||||
))
|
||||
except ValueError:
|
||||
logging.info("No clusters found - creating test cluster...")
|
||||
cluster = json.loads(self.client.post(
|
||||
"http://%s:8000/api/clusters" % admin_ip,
|
||||
data='{ "name": "MyOwnPrivateCluster", "release": 2 }',
|
||||
log=True
|
||||
))
|
||||
|
||||
resp = json.loads(self.client.put(
|
||||
"http://%s:8000/api/clusters/1" % admin_ip,
|
||||
@ -75,7 +85,7 @@ class TestNode(TestCase):
|
||||
|
||||
resp = json.loads(self.client.put(
|
||||
"http://%s:8000/api/nodes/%s" % (admin_ip, slave_id),
|
||||
data='{ "new_roles": [1, 2], "redeployment_needed": true }'
|
||||
data='{ "new_roles": [2, 3], "redeployment_needed": true }'
|
||||
))
|
||||
if len(resp["new_roles"]) == 0:
|
||||
raise ValueError("Failed to assign roles to node")
|
||||
@ -87,13 +97,13 @@ class TestNode(TestCase):
|
||||
))
|
||||
task_id = task['task_id']
|
||||
logging.info("Task created: %s" % task_id)
|
||||
logging.info("Waiting for completion of admin node software installation")
|
||||
logging.info("Waiting for completion of slave node software installation")
|
||||
while True:
|
||||
try:
|
||||
task = json.loads(self.client.get(
|
||||
"http://%s:8000/api/tasks/%s/" % (admin_ip, task_id)
|
||||
))
|
||||
self.check_tasks(task)
|
||||
self._check_tasks(task)
|
||||
break
|
||||
except StillPendingException:
|
||||
time.sleep(30)
|
||||
@ -106,58 +116,15 @@ class TestNode(TestCase):
|
||||
wait(lambda: tcp_ping(node["ip"], 22), timeout=1800)
|
||||
self.remote.connect_ssh(node["ip"], "root", "r00tme")
|
||||
|
||||
self.remote.rmdir(cookbook_remote_path)
|
||||
self.remote.rmdir(os.path.join(SAMPLE_REMOTE_PATH, "cookbooks"))
|
||||
self.remote.rmdir(os.path.join(SAMPLE_REMOTE_PATH, "solo"))
|
||||
|
||||
self.remote.scp(
|
||||
os.path.join(SAMPLE_PATH, "sample-release.json"),
|
||||
release_remote_path
|
||||
)
|
||||
|
||||
self.remote.mkdir(os.path.join(SAMPLE_REMOTE_PATH, "solo"))
|
||||
self.remote.mkdir(os.path.join(SAMPLE_REMOTE_PATH, "solo/config"))
|
||||
|
||||
self.remote.scp(
|
||||
DEPLOY_PATH,
|
||||
os.path.join(SAMPLE_REMOTE_PATH, "deploy")
|
||||
)
|
||||
self.remote.scp(
|
||||
os.path.join(SOLO_PATH, "solo.json"),
|
||||
os.path.join(SAMPLE_REMOTE_PATH, "solo", "config", "solo.json")
|
||||
)
|
||||
self.remote.scp(
|
||||
os.path.join(SOLO_PATH, "solo.rb"),
|
||||
os.path.join(SAMPLE_REMOTE_PATH, "solo", "config", "solo.rb")
|
||||
)
|
||||
|
||||
self.remote.scp_d(
|
||||
os.path.join(SAMPLE_PATH, "sample-cook"),
|
||||
SAMPLE_REMOTE_PATH
|
||||
)
|
||||
self.remote.scp_d(
|
||||
COOKBOOKS_PATH,
|
||||
SAMPLE_REMOTE_PATH
|
||||
)
|
||||
|
||||
self.remote.exec_cmd("rm /tmp/chef_success")
|
||||
result = self.remote.exec_cmd("chef-solo -l debug -c %s -j %s" % (
|
||||
os.path.join(SAMPLE_REMOTE_PATH, "solo", "config", "solo.rb"),
|
||||
os.path.join(SAMPLE_REMOTE_PATH, "solo", "config", "solo.json")
|
||||
))
|
||||
if result['exit_status'] != 0:
|
||||
self.remote.disconnect()
|
||||
raise Exception("Error while executing chef-solo: %s" % str(result))
|
||||
|
||||
# check if recipes executed
|
||||
ret = self.remote.exec_cmd("test -f /tmp/chef_success && echo 'SUCCESS'")
|
||||
if not "SUCCESS" in ret.split("\r\n")[1:]:
|
||||
raise Exception("Recipe failed to execute!")
|
||||
ret = self.remote.exec_cmd("test -f /tmp/chef_success")
|
||||
if ret['exit_status'] != 0:
|
||||
raise Exception("Recipes failed to execute!")
|
||||
# check recipes execution order
|
||||
ret = self.remote.exec_cmd("cat /tmp/chef_success")
|
||||
if not ret.split("\r\n")[1:-1] == ['monitor', 'default', 'compute']:
|
||||
if not ret['stdout'].split("\r\n") == ['monitor', 'default', 'compute']:
|
||||
raise Exception("Recipes executed in a wrong order: %s!" \
|
||||
% str(ret.split("\r\n")[1:-1]))
|
||||
% str(ret['stdout'].split("\r\n")))
|
||||
"""
|
||||
# check passwords
|
||||
self.remote.exec_cmd("tar -C %s -xvf /root/nodes.tar.gz" % SAMPLE_REMOTE_PATH)
|
||||
@ -170,7 +137,7 @@ class TestNode(TestCase):
|
||||
|
||||
self.remote.disconnect()
|
||||
|
||||
def check_tasks(self, task):
|
||||
def _check_tasks(self, task):
|
||||
if task['status'] != 'SUCCESS':
|
||||
if task['status'] == 'PENDING':
|
||||
raise StillPendingException("Task %s is still pending")
|
||||
@ -180,4 +147,50 @@ class TestNode(TestCase):
|
||||
)
|
||||
if 'subtasks' in task and task['subtasks']:
|
||||
for subtask in task['subtasks']:
|
||||
self.check_tasks(subtask)
|
||||
self._check_tasks(subtask)
|
||||
|
||||
def _load_sample_admin(self, host, user, passwd):
|
||||
cookbook_remote_path = os.path.join(SAMPLE_REMOTE_PATH, "sample-cook")
|
||||
release_remote_path = os.path.join(SAMPLE_REMOTE_PATH, "sample-release.json")
|
||||
self.remote.connect_ssh(host, user, passwd)
|
||||
self.remote.rmdir(cookbook_remote_path)
|
||||
self.remote.rmdir(os.path.join(SAMPLE_REMOTE_PATH, "cookbooks"))
|
||||
self.remote.rmdir(os.path.join(SAMPLE_REMOTE_PATH, "solo"))
|
||||
self.remote.scp(
|
||||
os.path.join(SAMPLE_PATH, "sample-release.json"),
|
||||
release_remote_path
|
||||
)
|
||||
self.remote.mkdir(os.path.join(SAMPLE_REMOTE_PATH, "solo"))
|
||||
self.remote.mkdir(os.path.join(SAMPLE_REMOTE_PATH, "solo/config"))
|
||||
self.remote.scp(
|
||||
os.path.join(SOLO_PATH, "solo.json"),
|
||||
os.path.join(SAMPLE_REMOTE_PATH, "solo", "config", "solo.json")
|
||||
)
|
||||
self.remote.scp(
|
||||
os.path.join(SOLO_PATH, "solo.rb"),
|
||||
os.path.join(SAMPLE_REMOTE_PATH, "solo", "config", "solo.rb")
|
||||
)
|
||||
self.remote.scp_d(
|
||||
os.path.join(SAMPLE_PATH, "sample-cook"),
|
||||
SAMPLE_REMOTE_PATH
|
||||
)
|
||||
self.remote.scp_d(
|
||||
COOKBOOKS_PATH,
|
||||
SAMPLE_REMOTE_PATH
|
||||
)
|
||||
commands = [
|
||||
#"rm -rf /opt/nailgun/nailgun.sqlite",
|
||||
#"/opt/nailgun-venv/bin/python /opt/nailgun/manage.py syncdb --noinput",
|
||||
#"chown nailgun:nailgun /opt/nailgun/nailgun.sqlite",
|
||||
"/opt/nailgun/bin/install_cookbook %s" % cookbook_remote_path,
|
||||
"/opt/nailgun/bin/create_release %s" % release_remote_path
|
||||
]
|
||||
|
||||
with self.remote.sudo:
|
||||
for cmd in commands:
|
||||
res = self.remote.exec_cmd(cmd)
|
||||
if res['exit_status'] != 0:
|
||||
self.remote.disconnect()
|
||||
raise Exception("Command failed: %s" % str(res))
|
||||
|
||||
self.remote.disconnect()
|
Loading…
Reference in New Issue
Block a user