fuel-web/nailgun/nailgun/test/integration/test_node_deletion.py

201 lines
6.7 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2013 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
from nailgun import consts
from nailgun import objects
from nailgun.db.sqlalchemy.models import IPAddr
from nailgun.db.sqlalchemy.models import NetworkGroup
from nailgun.db.sqlalchemy.models import Node
from nailgun.test.base import BaseIntegrationTest
from nailgun.test.base import fake_tasks
from nailgun.test.base import mock_rpc
from nailgun.utils import reverse
logger = logging.getLogger(__name__)
class TestNodeDeletion(BaseIntegrationTest):
def setUp(self):
super(TestNodeDeletion, self).setUp()
self.cluster = self.env.create(
nodes_kwargs=[{"pending_addition": True}])
self.node_ids = [node.id for node in self.cluster.nodes]
@fake_tasks()
def test_node_deletion_and_attributes_clearing(self):
node_id = self.node_ids[0]
resp = self.app.delete(
reverse(
'NodeHandler',
kwargs={'obj_id': node_id}),
headers=self.default_headers
)
# @fake_tasks runs synchoronously, so nodes are removed
# that's why API returns 200, not 202
self.assertEqual(200, resp.status_code)
task = objects.Task.get_by_uuid(resp.json_body['uuid'])
self.assertEqual(task.status, consts.TASK_STATUSES.ready)
node_try = self.db.query(Node).filter_by(
cluster_id=self.cluster.id
).first()
self.assertIsNone(node_try)
management_net = self.db.query(NetworkGroup).\
filter(NetworkGroup.group_id ==
objects.Cluster.get_default_group(self.cluster).id).\
filter_by(name='management').first()
ipaddrs = self.db.query(IPAddr).\
filter_by(node=node_id).all()
self.assertEqual(list(management_net.nodes), [])
self.assertEqual(list(ipaddrs), [])
@fake_tasks()
def test_batch_node_deletion_and_attributes_clearing(self):
url = reverse('NodeCollectionHandler')
query_str = 'ids={0}'.format(','.join(map(str, self.node_ids)))
resp = self.app.delete(
'{0}?{1}'.format(url, query_str),
headers=self.default_headers
)
# @fake_tasks runs synchoronously, so nodes are removed
# that's why API returns 200, not 202
self.assertEqual(200, resp.status_code)
task = objects.Task.get_by_uuid(resp.json_body['uuid'])
self.assertEqual(task.status, consts.TASK_STATUSES.ready)
node_query = self.db.query(Node).filter_by(cluster_id=self.cluster.id)
self.assertEquals(node_query.count(), 0)
@fake_tasks(fake_rpc=False, mock_rpc=True)
def test_delete_nodes_error_message(self, _):
url = reverse('NodeCollectionHandler')
query_str = 'ids={0}'.format(','.join(map(str, self.node_ids)))
self.app.delete(
'{0}?{1}'.format(url, query_str),
headers=self.default_headers
)
resp = self.app.delete(
'{0}?{1}'.format(url, query_str),
headers=self.default_headers,
expect_errors=True
)
self.assertIn('message', resp.json_body)
self.assertEqual(403, resp.status_code)
self.assertEqual(
resp.json_body['message'],
'Cannot perform the actions because there are running tasks.'
)
@fake_tasks(fake_rpc=False, mock_rpc=True)
def test_delete_node_error_message(self, _):
self.app.delete(
reverse('NodeHandler', {'obj_id': self.node_ids[0]}),
headers=self.default_headers
)
resp = self.app.delete(
reverse('NodeHandler', {'obj_id': self.node_ids[0]}),
headers=self.default_headers,
expect_errors=True
)
self.assertIn('message', resp.json_body)
self.assertEqual(403, resp.status_code)
self.assertEqual(
resp.json_body['message'],
'Cannot perform the actions because there are running tasks.'
)
@mock_rpc(pass_mock=True)
def test_mclient_remove_is_false_on_node_deletion(self, mrpc):
url = reverse(
'NodeHandler',
kwargs={'obj_id': self.node_ids[0]}
)
self.app.delete(
url,
headers=self.default_headers
)
msg = mrpc.call_args[0][1]
self.assertTrue(
all([node['mclient_remove'] is False
for node in msg['args']['nodes']])
)
@mock_rpc(pass_mock=True)
def test_mclient_remove_is_false_on_node_collection_deletion(self, mrpc):
url = reverse('NodeCollectionHandler')
query_str = 'ids={0}'.format(','.join(map(str, self.node_ids)))
self.app.delete(
'{0}?{1}'.format(url, query_str),
headers=self.default_headers
)
msg = mrpc.call_args[0][1]
self.assertTrue(
all([node['mclient_remove'] is False
for node in msg['args']['nodes']])
)
class TestNodeDeletionBadRequest(BaseIntegrationTest):
def test_node_handlers_deletion_bad_request(self):
cluster = self.env.create(nodes_kwargs=[
{'roles': ['controller'], 'status': consts.NODE_STATUSES.error}
])
node_to_delete = self.env.create_node(
cluster_id=cluster.id,
roles=['controller'],
status=consts.NODE_STATUSES.ready
)
err_msg = ("One of the cluster controllers is in error state, "
"please, eliminate the problem prior to proceeding further")
resp = self.app.delete(
reverse(
'NodeHandler',
kwargs={'obj_id': node_to_delete.id}),
headers=self.default_headers,
expect_errors=True
)
self.assertEqual(resp.status_code, 403)
self.assertIn(err_msg, resp.body)
url = reverse('NodeCollectionHandler')
query_str = 'ids={0}'.format(node_to_delete.id)
resp = self.app.delete(
'{0}?{1}'.format(url, query_str),
headers=self.default_headers,
expect_errors=True
)
self.assertEqual(resp.status_code, 403)
self.assertIn(err_msg, resp.body)