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
|
||||
def check_roles_for_conflicts(cls, roles, roles_metadata):
|
||||
all_roles = set(roles_metadata.keys())
|
||||
for role in roles:
|
||||
if "conflicts" in roles_metadata[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
|
||||
if conflicting_roles:
|
||||
raise errors.InvalidData(
|
||||
|
|
|
@ -102,7 +102,7 @@ ROLE_META_INFO = {
|
|||
"type": "string",
|
||||
"description": "Short description of role functionality"},
|
||||
"conflicts": {
|
||||
"type": "array",
|
||||
"type": ["array", "string"],
|
||||
"description": "Specify which roles conflict this one."},
|
||||
"has_primary": {
|
||||
"type": "boolean",
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import yaml
|
||||
|
||||
from oslo.serialization import jsonutils
|
||||
|
||||
from nailgun.db.sqlalchemy.models import NodeBondInterface
|
||||
|
@ -23,6 +25,17 @@ from nailgun.utils import reverse
|
|||
|
||||
|
||||
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):
|
||||
self.env.create(
|
||||
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]
|
||||
assignment_data = [
|
||||
{
|
||||
|
@ -41,30 +54,15 @@ class TestAssignmentHandlers(BaseIntegrationTest):
|
|||
"roles": ['controller']
|
||||
}
|
||||
]
|
||||
resp = self.app.post(
|
||||
reverse(
|
||||
'NodeAssignmentHandler',
|
||||
kwargs={'cluster_id': cluster.id}
|
||||
),
|
||||
jsonutils.dumps(assignment_data),
|
||||
headers=self.default_headers
|
||||
)
|
||||
resp = self._assign_roles(assignment_data)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(node.cluster, cluster)
|
||||
self.assertEqual(node.cluster, self.cluster)
|
||||
self.datadiff(
|
||||
node.pending_roles,
|
||||
assignment_data[0]["roles"]
|
||||
)
|
||||
|
||||
resp = self.app.post(
|
||||
reverse(
|
||||
'NodeAssignmentHandler',
|
||||
kwargs={'cluster_id': cluster.id}
|
||||
),
|
||||
jsonutils.dumps(assignment_data),
|
||||
headers=self.default_headers,
|
||||
expect_errors=True
|
||||
)
|
||||
resp = self._assign_roles(assignment_data, True)
|
||||
self.assertEqual(400, resp.status_code)
|
||||
|
||||
def test_unassignment(self):
|
||||
|
@ -160,9 +158,71 @@ class TestAssignmentHandlers(BaseIntegrationTest):
|
|||
headers=self.default_headers,
|
||||
expect_errors=True
|
||||
)
|
||||
|
||||
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):
|
||||
net_template = """
|
||||
{
|
||||
|
|
|
@ -276,15 +276,24 @@ define([
|
|||
model: models.Role,
|
||||
processConflicts: function() {
|
||||
this.each(function(role) {
|
||||
role.conflicts = _.chain(role.conflicts)
|
||||
.union(role.get('conflicts'))
|
||||
.uniq()
|
||||
.compact()
|
||||
.value();
|
||||
_.each(role.get('conflicts'), function(conflict) {
|
||||
var conflictingRole = this.findWhere({name: conflict});
|
||||
conflictingRole.conflicts = conflictingRole.conflicts || [];
|
||||
conflictingRole.conflicts.push(role.get('name'));
|
||||
var roleConflicts = role.get('conflicts'),
|
||||
roleName = role.get('name');
|
||||
|
||||
if (roleConflicts == '*') {
|
||||
role.conflicts = _.map(this.reject({name: roleName}), function(role) {
|
||||
return role.get('name');
|
||||
});
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1331,7 +1331,7 @@ function($, _, i18n, Backbone, React, utils, models, dispatcher, controls, dialo
|
|||
conflicts = _.chain(this.props.selectedRoles)
|
||||
.union(this.props.indeterminateRoles)
|
||||
.map(function(role) {
|
||||
return roles.find({name: role}).get('conflicts');
|
||||
return roles.find({name: role}).conflicts;
|
||||
})
|
||||
.flatten()
|
||||
.uniq()
|
||||
|
|
Loading…
Reference in New Issue