Adds "*" support in openstack.yaml for conflicts
"*" can now be used in openstack.yaml roles conflicts section if role conflicts with all others Change-Id: I4628ac55946f1b8d58d708cde0b9f45b3a61eb29 Closes-Bug: #1466420
This commit is contained in:
parent
8995e80e80
commit
9b1083d135
|
@ -122,10 +122,15 @@ class NodeAssignmentValidator(AssignmentValidator):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def check_roles_for_conflicts(cls, roles, roles_metadata):
|
def check_roles_for_conflicts(cls, roles, roles_metadata):
|
||||||
|
all_roles = set(roles_metadata.keys())
|
||||||
for role in roles:
|
for role in roles:
|
||||||
if "conflicts" in roles_metadata[role]:
|
if "conflicts" in roles_metadata[role]:
|
||||||
other_roles = roles - set([role])
|
other_roles = roles - set([role])
|
||||||
conflicting_roles = set(roles_metadata[role]["conflicts"])
|
conflicting_roles = roles_metadata[role]["conflicts"]
|
||||||
|
if conflicting_roles == "*":
|
||||||
|
conflicting_roles = all_roles - set([role])
|
||||||
|
else:
|
||||||
|
conflicting_roles = set(conflicting_roles)
|
||||||
conflicting_roles &= other_roles
|
conflicting_roles &= other_roles
|
||||||
if conflicting_roles:
|
if conflicting_roles:
|
||||||
raise errors.InvalidData(
|
raise errors.InvalidData(
|
||||||
|
|
|
@ -102,7 +102,7 @@ ROLE_META_INFO = {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Short description of role functionality"},
|
"description": "Short description of role functionality"},
|
||||||
"conflicts": {
|
"conflicts": {
|
||||||
"type": "array",
|
"type": ["array", "string"],
|
||||||
"description": "Specify which roles conflict this one."},
|
"description": "Specify which roles conflict this one."},
|
||||||
"has_primary": {
|
"has_primary": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
from oslo.serialization import jsonutils
|
from oslo.serialization import jsonutils
|
||||||
|
|
||||||
from nailgun.db.sqlalchemy.models import NodeBondInterface
|
from nailgun.db.sqlalchemy.models import NodeBondInterface
|
||||||
|
@ -23,6 +25,17 @@ from nailgun.utils import reverse
|
||||||
|
|
||||||
|
|
||||||
class TestAssignmentHandlers(BaseIntegrationTest):
|
class TestAssignmentHandlers(BaseIntegrationTest):
|
||||||
|
def _assign_roles(self, assignment_data, expect_errors=False):
|
||||||
|
return self.app.post(
|
||||||
|
reverse(
|
||||||
|
'NodeAssignmentHandler',
|
||||||
|
kwargs={'cluster_id': self.cluster.id}
|
||||||
|
),
|
||||||
|
jsonutils.dumps(assignment_data),
|
||||||
|
headers=self.default_headers,
|
||||||
|
expect_errors=expect_errors
|
||||||
|
)
|
||||||
|
|
||||||
def test_assignment(self):
|
def test_assignment(self):
|
||||||
self.env.create(
|
self.env.create(
|
||||||
cluster_kwargs={"api": True},
|
cluster_kwargs={"api": True},
|
||||||
|
@ -33,7 +46,7 @@ class TestAssignmentHandlers(BaseIntegrationTest):
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
cluster = self.env.clusters[0]
|
self.cluster = self.env.clusters[0]
|
||||||
node = self.env.nodes[0]
|
node = self.env.nodes[0]
|
||||||
assignment_data = [
|
assignment_data = [
|
||||||
{
|
{
|
||||||
|
@ -41,30 +54,15 @@ class TestAssignmentHandlers(BaseIntegrationTest):
|
||||||
"roles": ['controller']
|
"roles": ['controller']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
resp = self.app.post(
|
resp = self._assign_roles(assignment_data)
|
||||||
reverse(
|
|
||||||
'NodeAssignmentHandler',
|
|
||||||
kwargs={'cluster_id': cluster.id}
|
|
||||||
),
|
|
||||||
jsonutils.dumps(assignment_data),
|
|
||||||
headers=self.default_headers
|
|
||||||
)
|
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
self.assertEqual(node.cluster, cluster)
|
self.assertEqual(node.cluster, self.cluster)
|
||||||
self.datadiff(
|
self.datadiff(
|
||||||
node.pending_roles,
|
node.pending_roles,
|
||||||
assignment_data[0]["roles"]
|
assignment_data[0]["roles"]
|
||||||
)
|
)
|
||||||
|
|
||||||
resp = self.app.post(
|
resp = self._assign_roles(assignment_data, True)
|
||||||
reverse(
|
|
||||||
'NodeAssignmentHandler',
|
|
||||||
kwargs={'cluster_id': cluster.id}
|
|
||||||
),
|
|
||||||
jsonutils.dumps(assignment_data),
|
|
||||||
headers=self.default_headers,
|
|
||||||
expect_errors=True
|
|
||||||
)
|
|
||||||
self.assertEqual(400, resp.status_code)
|
self.assertEqual(400, resp.status_code)
|
||||||
|
|
||||||
def test_unassignment(self):
|
def test_unassignment(self):
|
||||||
|
@ -160,9 +158,71 @@ class TestAssignmentHandlers(BaseIntegrationTest):
|
||||||
headers=self.default_headers,
|
headers=self.default_headers,
|
||||||
expect_errors=True
|
expect_errors=True
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(404, resp.status_code)
|
self.assertEquals(404, resp.status_code)
|
||||||
|
|
||||||
|
def test_assign_conflicting_roles(self):
|
||||||
|
self.env.create(
|
||||||
|
cluster_kwargs={"api": True},
|
||||||
|
nodes_kwargs=[
|
||||||
|
{
|
||||||
|
"cluster_id": None,
|
||||||
|
"api": True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.cluster = self.env.clusters[0]
|
||||||
|
node = self.env.nodes[0]
|
||||||
|
assignment_data = [
|
||||||
|
{
|
||||||
|
"id": node.id,
|
||||||
|
"roles": ['controller', 'compute']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
resp = self._assign_roles(assignment_data, True)
|
||||||
|
self.assertEquals(400, resp.status_code)
|
||||||
|
|
||||||
|
def test_assign_conflicting_all_role(self):
|
||||||
|
ROLE = yaml.safe_load("""
|
||||||
|
name: test_role
|
||||||
|
meta:
|
||||||
|
name: "Some plugin role"
|
||||||
|
description: "Some description"
|
||||||
|
conflicts: "*"
|
||||||
|
volumes_roles_mapping:
|
||||||
|
- id: os
|
||||||
|
allocate_size: all
|
||||||
|
""")
|
||||||
|
|
||||||
|
release = self.env.create_release()
|
||||||
|
resp = self.env.create_role(release.id, ROLE)
|
||||||
|
|
||||||
|
self.env.create(
|
||||||
|
cluster_kwargs={
|
||||||
|
"api": True,
|
||||||
|
"release_id": release.id
|
||||||
|
},
|
||||||
|
nodes_kwargs=[
|
||||||
|
{
|
||||||
|
"cluster_id": None,
|
||||||
|
"api": True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.cluster = self.env.clusters[0]
|
||||||
|
node = self.env.nodes[0]
|
||||||
|
assignment_data = [
|
||||||
|
{
|
||||||
|
"id": node.id,
|
||||||
|
"roles": ['controller', 'test_role']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
resp = self._assign_roles(assignment_data, True)
|
||||||
|
self.assertEquals(400, resp.status_code, resp.body)
|
||||||
|
|
||||||
|
assignment_data[0]["roles"] = ['test_role']
|
||||||
|
resp = self._assign_roles(assignment_data)
|
||||||
|
self.assertEquals(200, resp.status_code, resp.body)
|
||||||
|
|
||||||
def test_add_node_with_cluster_network_template(self):
|
def test_add_node_with_cluster_network_template(self):
|
||||||
net_template = """
|
net_template = """
|
||||||
{
|
{
|
||||||
|
|
|
@ -276,15 +276,24 @@ define([
|
||||||
model: models.Role,
|
model: models.Role,
|
||||||
processConflicts: function() {
|
processConflicts: function() {
|
||||||
this.each(function(role) {
|
this.each(function(role) {
|
||||||
role.conflicts = _.chain(role.conflicts)
|
var roleConflicts = role.get('conflicts'),
|
||||||
.union(role.get('conflicts'))
|
roleName = role.get('name');
|
||||||
.uniq()
|
|
||||||
.compact()
|
if (roleConflicts == '*') {
|
||||||
.value();
|
role.conflicts = _.map(this.reject({name: roleName}), function(role) {
|
||||||
_.each(role.get('conflicts'), function(conflict) {
|
return role.get('name');
|
||||||
var conflictingRole = this.findWhere({name: conflict});
|
});
|
||||||
conflictingRole.conflicts = conflictingRole.conflicts || [];
|
} else {
|
||||||
conflictingRole.conflicts.push(role.get('name'));
|
role.conflicts = _.chain(role.conflicts)
|
||||||
|
.union(roleConflicts)
|
||||||
|
.uniq()
|
||||||
|
.compact()
|
||||||
|
.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
_.each(role.conflicts, function(conflictRoleName) {
|
||||||
|
var conflictingRole = this.findWhere({name: conflictRoleName});
|
||||||
|
conflictingRole.conflicts = _.uniq(_.union(conflictingRole.conflicts || [], [roleName]));
|
||||||
}, this);
|
}, this);
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1331,7 +1331,7 @@ function($, _, i18n, Backbone, React, utils, models, dispatcher, controls, dialo
|
||||||
conflicts = _.chain(this.props.selectedRoles)
|
conflicts = _.chain(this.props.selectedRoles)
|
||||||
.union(this.props.indeterminateRoles)
|
.union(this.props.indeterminateRoles)
|
||||||
.map(function(role) {
|
.map(function(role) {
|
||||||
return roles.find({name: role}).get('conflicts');
|
return roles.find({name: role}).conflicts;
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.uniq()
|
.uniq()
|
||||||
|
|
Loading…
Reference in New Issue