Add support to re-assign a set of nodes

This patch adds an ability to re-assign a set of the given nodes at
once. This feature was technically available but not exposed to the
client. A groupped re-assigning allows to effectively re-provision nodes
by creating an atomic task in Astute.

Change-Id: Ia239d37ec0497de73715640e62205f6d3252f61b
Related-Bug: #1616925
This commit is contained in:
Sergey Abramov 2016-09-26 15:57:09 +03:00
parent e9f9acadcb
commit 390756d365
4 changed files with 32 additions and 16 deletions

View File

@ -82,9 +82,10 @@ class NodeReassignHandler(base.BaseHandler):
self.get_object_or_404(self.single, cluster_id))
data = self.checked_data(cluster=cluster)
node = adapters.NailgunNodeAdapter(
self.get_object_or_404(objects.Node, data['node_id']))
upgrade.UpgradeHelper.assign_node_to_cluster(node, cluster)
self.handle_task(cluster_id, [node.node, ])
nodes_to_provision = []
for node_id in data['nodes_ids']:
node = adapters.NailgunNodeAdapter(
self.get_object_or_404(objects.Node, node_id))
nodes_to_provision.append(node.node)
upgrade.UpgradeHelper.assign_node_to_cluster(node, cluster)
self.handle_task(cluster_id, nodes_to_provision)

View File

@ -88,7 +88,7 @@ class TestNodeReassignHandler(base.BaseIntegrationTest):
resp = self.app.post(
reverse('NodeReassignHandler',
kwargs={'cluster_id': seed_cluster['id']}),
jsonutils.dumps({'node_id': node_id}),
jsonutils.dumps({'nodes_ids': [node_id, ]}),
headers=self.default_headers)
self.assertEqual(202, resp.status_code)
@ -105,7 +105,7 @@ class TestNodeReassignHandler(base.BaseIntegrationTest):
resp = self.app.post(
reverse('NodeReassignHandler',
kwargs={'cluster_id': cluster['id']}),
jsonutils.dumps({'node_id': 42}),
jsonutils.dumps({'nodes_ids': [42]}),
headers=self.default_headers,
expect_errors=True)
self.assertEqual(404, resp.status_code)
@ -121,7 +121,7 @@ class TestNodeReassignHandler(base.BaseIntegrationTest):
resp = self.app.post(
reverse('NodeReassignHandler',
kwargs={'cluster_id': cluster['id']}),
jsonutils.dumps({'node_id': cluster.nodes[0]['id']}),
jsonutils.dumps({'nodes_ids': [cluster.nodes[0]['id']]}),
headers=self.default_headers,
expect_errors=True)
self.assertEqual(400, resp.status_code)
@ -138,7 +138,7 @@ class TestNodeReassignHandler(base.BaseIntegrationTest):
resp = self.app.post(
reverse('NodeReassignHandler',
kwargs={'cluster_id': cluster['id']}),
jsonutils.dumps({'node_id': cluster.nodes[0]['id']}),
jsonutils.dumps({'nodes_ids': [cluster.nodes[0]['id']]}),
headers=self.default_headers,
expect_errors=True)
self.assertEqual(400, resp.status_code)
@ -156,7 +156,7 @@ class TestNodeReassignHandler(base.BaseIntegrationTest):
resp = self.app.post(
reverse('NodeReassignHandler',
kwargs={'cluster_id': cluster_id}),
jsonutils.dumps({'node_id': node_id}),
jsonutils.dumps({'nodes_ids': [node_id]}),
headers=self.default_headers,
expect_errors=True)
self.assertEqual(400, resp.status_code)

View File

@ -129,7 +129,7 @@ class TestNodeReassignValidator(base.BaseTestCase):
node = self.env.create_node(cluster_id=cluster.id,
roles=["compute"],
status="ready")
msg = "^'node_id' is a required property"
msg = "^'nodes_ids' is a required property"
with self.assertRaisesRegexp(errors.InvalidData, msg):
self.validator.validate("{}", node)

View File

@ -91,17 +91,32 @@ class NodeReassignValidator(base.BasicValidator):
"description": "Serialized parameters to assign node",
"type": "object",
"properties": {
"node_id": {"type": "number"},
"nodes_ids": {
"type": "array",
"items": {"type": "number"},
"uniqueItems": True,
"minItems": 1,
},
},
"required": ["node_id"],
"required": ["nodes_ids"],
}
@classmethod
def validate(cls, data, cluster):
data = super(NodeReassignValidator, cls).validate(data)
cls.validate_schema(data, cls.schema)
node = cls.validate_node(data['node_id'])
cls.validate_node_cluster(node, cluster)
nodes = []
roles = set([])
for node_id in data['nodes_ids']:
node = cls.validate_node(node_id)
cls.validate_node_cluster(node, cluster)
nodes.append(node)
roles.add(' '.join(sorted(node.roles)))
if len(roles) != 1:
raise errors.InvalidData(
"All sending nodes should have the same roles",
log_message=True)
return data
@classmethod