diff --git a/nailgun/nailgun/api/handlers/cluster.py b/nailgun/nailgun/api/handlers/cluster.py index f527f15a7c..e40fc34487 100644 --- a/nailgun/nailgun/api/handlers/cluster.py +++ b/nailgun/nailgun/api/handlers/cluster.py @@ -18,22 +18,22 @@ Handlers dealing with clusters """ -import json import traceback from nailgun.api.handlers.base import BaseHandler from nailgun.api.handlers.base import DeferredTaskHandler +from nailgun.api.handlers.base import CollectionHandler +from nailgun.api.handlers.base import SingleHandler + +from nailgun import objects + from nailgun.api.handlers.base import content_json from nailgun.api.validators.cluster import AttributesValidator from nailgun.api.validators.cluster import ClusterValidator from nailgun.db import db -from nailgun.db.sqlalchemy.models import Attributes from nailgun.db.sqlalchemy.models import Cluster -from nailgun.db.sqlalchemy.models import Node -from nailgun.db.sqlalchemy.models import Release -from nailgun.errors import errors from nailgun.logger import logger from nailgun.task.manager import ApplyChangesTaskManager from nailgun.task.manager import ClusterDeletionManager @@ -42,81 +42,21 @@ from nailgun.task.manager import StopDeploymentTaskManager from nailgun import utils -class ClusterHandler(BaseHandler): +class ClusterHandler(SingleHandler): """Cluster single handler """ - fields = ( - "id", - "name", - "mode", - "changes", - "status", - "grouping", - "is_customized", - "net_provider", - "net_segment_type", - "release_id" - ) - - model = Cluster + single = objects.Cluster validator = ClusterValidator @content_json - def GET(self, cluster_id): - """:returns: JSONized Cluster object. - :http: * 200 (OK) - * 404 (cluster not found in db) - """ - cluster = self.get_object_or_404(Cluster, cluster_id) - return self.render(cluster) - - @content_json - def PUT(self, cluster_id): - """:returns: JSONized Cluster object. - :http: * 200 (OK) - * 400 (invalid cluster data specified) - * 404 (cluster not found in db) - """ - cluster = self.get_object_or_404(Cluster, cluster_id) - data = self.checked_data(cluster_id=cluster_id) - network_manager = cluster.network_manager - - for key, value in data.iteritems(): - if key == "nodes": - # TODO(NAME): sepatate nodes - #for deletion and addition by set(). - new_nodes = db().query(Node).filter( - Node.id.in_(value) - ) - nodes_to_remove = [n for n in cluster.nodes - if n not in new_nodes] - nodes_to_add = [n for n in new_nodes - if n not in cluster.nodes] - for node in nodes_to_add: - if not node.online: - raise self.http( - 400, "Can not add offline node to cluster" - ) - map(cluster.nodes.remove, nodes_to_remove) - map(cluster.nodes.append, nodes_to_add) - for node in nodes_to_remove: - network_manager.clear_assigned_networks(node) - for node in nodes_to_add: - network_manager.assign_networks_by_default(node) - else: - setattr(cluster, key, value) - db().commit() - return self.render(cluster) - - @content_json - def DELETE(self, cluster_id): + def DELETE(self, obj_id): """:returns: {} :http: * 202 (cluster deletion process launched) * 400 (failed to execute cluster deletion process) * 404 (cluster not found in db) """ - cluster = self.get_object_or_404(Cluster, cluster_id) + cluster = self.get_object_or_404(self.single.model, obj_id) task_manager = ClusterDeletionManager(cluster_id=cluster.id) try: logger.debug('Trying to execute cluster deletion task') @@ -130,90 +70,13 @@ class ClusterHandler(BaseHandler): raise self.http(202, '{}') -class ClusterCollectionHandler(BaseHandler): +class ClusterCollectionHandler(CollectionHandler): """Cluster collection handler """ + collection = objects.ClusterCollection validator = ClusterValidator - @content_json - def GET(self): - """:returns: Collection of JSONized Cluster objects. - :http: * 200 (OK) - """ - return map( - ClusterHandler.render, - db().query(Cluster).all() - ) - - @content_json - def POST(self): - """:returns: JSONized Cluster object. - :http: * 201 (cluster successfully created) - * 400 (invalid cluster data specified) - * 409 (cluster with such parameters already exists) - """ - # It's used for cluster creating only. - data = self.checked_data() - - cluster = Cluster() - cluster.release = db().query(Release).get(data["release"]) - # TODO(NAME): use fields - for field in ( - "name", - "mode", - "net_provider", - "net_segment_type", - "status" - ): - if data.get(field): - setattr(cluster, field, data.get(field)) - db().add(cluster) - db().commit() - attributes = Attributes( - editable=cluster.release.attributes_metadata.get("editable"), - generated=cluster.release.attributes_metadata.get("generated"), - cluster=cluster - ) - attributes.generate_fields() - - netmanager = cluster.network_manager - - try: - netmanager.create_network_groups(cluster.id) - if cluster.net_provider == 'neutron': - netmanager.create_neutron_config(cluster) - - cluster.add_pending_changes("attributes") - cluster.add_pending_changes("networks") - - if 'nodes' in data and data['nodes']: - nodes = db().query(Node).filter( - Node.id.in_(data['nodes']) - ).all() - map(cluster.nodes.append, nodes) - db().commit() - for node in nodes: - netmanager.assign_networks_by_default(node) - - raise self.http( - 201, json.dumps(ClusterHandler.render(cluster), indent=4) - ) - - except ( - errors.OutOfVLANs, - errors.OutOfIPs, - errors.NoSuitableCIDR, - errors.InvalidNetworkPool - ) as e: - # Cluster was created in this request, - # so we no need to use ClusterDeletionManager. - # All relations wiil be cascade deleted automaticly. - # TODO(NAME): investigate transactions - db().delete(cluster) - - raise self.http(400, e.message) - class ClusterChangesHandler(DeferredTaskHandler): diff --git a/nailgun/nailgun/api/serializers/cluster.py b/nailgun/nailgun/api/serializers/cluster.py new file mode 100644 index 0000000000..f059179eab --- /dev/null +++ b/nailgun/nailgun/api/serializers/cluster.py @@ -0,0 +1,33 @@ +# -*- 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. + +from nailgun.api.serializers.base import BasicSerializer + + +class ClusterSerializer(BasicSerializer): + + fields = ( + "id", + "name", + "mode", + "changes", + "status", + "grouping", + "is_customized", + "net_provider", + "net_segment_type", + "release_id" + ) diff --git a/nailgun/nailgun/api/urls/v1.py b/nailgun/nailgun/api/urls/v1.py index ac5e6b5aa9..3a3871fc1f 100644 --- a/nailgun/nailgun/api/urls/v1.py +++ b/nailgun/nailgun/api/urls/v1.py @@ -89,7 +89,7 @@ urls = ( r'/clusters/?$', ClusterCollectionHandler, - r'/clusters/(?P\d+)/?$', + r'/clusters/(?P\d+)/?$', ClusterHandler, r'/clusters/(?P\d+)/changes/?$', ClusterChangesHandler, diff --git a/nailgun/nailgun/api/validators/cluster.py b/nailgun/nailgun/api/validators/cluster.py index 65f0b089a5..6202120fea 100644 --- a/nailgun/nailgun/api/validators/cluster.py +++ b/nailgun/nailgun/api/validators/cluster.py @@ -22,9 +22,8 @@ from nailgun.errors import errors class ClusterValidator(BasicValidator): @classmethod - def validate(cls, data, **kwargs): + def _validate_common(cls, data): d = cls.validate_json(data) - cluster_id = kwargs.get("cluster_id") or d.get("id") if d.get("name"): if db().query(Cluster).filter_by( name=d["name"] @@ -37,18 +36,24 @@ class ClusterValidator(BasicValidator): release = db().query(Release).get(d.get("release")) if not release: raise errors.InvalidData( - "Invalid release id", + "Invalid release ID", + log_message=True + ) + return d + + @classmethod + def validate(cls, data): + return cls._validate_common(data) + + @classmethod + def validate_update(cls, data, instance): + d = cls._validate_common(data) + for k in ("net_provider", "net_segment_type"): + if k in d and getattr(instance, k) != d[k]: + raise errors.InvalidData( + u"Changing '{0}' for environment is prohibited".format(k), log_message=True ) - if cluster_id: - cluster = db().query(Cluster).get(cluster_id) - if cluster: - for k in ("net_provider", "net_segment_type"): - if k in d and getattr(cluster, k) != d[k]: - raise errors.InvalidData( - "Change of '%s' is prohibited" % k, - log_message=True - ) return d diff --git a/nailgun/nailgun/consts.py b/nailgun/nailgun/consts.py index 7f00803f6c..4f6f3dfcfe 100644 --- a/nailgun/nailgun/consts.py +++ b/nailgun/nailgun/consts.py @@ -30,6 +30,47 @@ RELEASE_STATES = Enum( 'available' ) +CLUSTER_MODES = Enum( + 'multinode', + 'ha_full', + 'ha_compact' +) + +CLUSTER_STATUSES = Enum( + 'new', + 'deployment', + 'stopped', + 'operational', + 'error', + 'remove' +) + +CLUSTER_NET_MANAGERS = Enum( + 'FlatDHCPManager', + 'VlanManager' +) + +CLUSTER_GROUPING = Enum( + 'roles', + 'hardware', + 'both' +) + +CLUSTER_NET_PROVIDERS = Enum( + 'nova_network', + 'neutron' +) + +CLUSTER_NET_L23_PROVIDERS = Enum( + 'ovs' +) + +CLUSTER_NET_SEGMENT_TYPES = Enum( + 'none', + 'vlan', + 'gre' +) + NETWORK_INTERFACE_TYPES = Enum( 'ether', 'bond' diff --git a/nailgun/nailgun/db/sqlalchemy/models/cluster.py b/nailgun/nailgun/db/sqlalchemy/models/cluster.py index d4c0cbb806..e61c16ef75 100644 --- a/nailgun/nailgun/db/sqlalchemy/models/cluster.py +++ b/nailgun/nailgun/db/sqlalchemy/models/cluster.py @@ -25,6 +25,8 @@ from sqlalchemy import Integer from sqlalchemy import Unicode from sqlalchemy.orm import relationship, backref +from nailgun import consts + from nailgun.db import db from nailgun.db.sqlalchemy.models.base import Base from nailgun.db.sqlalchemy.models.fields import JSON @@ -52,57 +54,42 @@ class ClusterChanges(Base): class Cluster(Base): __tablename__ = 'clusters' - MODES = ('multinode', 'ha_full', 'ha_compact') - STATUSES = ( - 'new', - 'deployment', - 'stopped', - 'operational', - 'error', - 'remove' - ) - NET_MANAGERS = ('FlatDHCPManager', 'VlanManager') - GROUPING = ('roles', 'hardware', 'both') - # Neutron-related - NET_PROVIDERS = ('nova_network', 'neutron') - NET_L23_PROVIDERS = ('ovs',) - NET_SEGMENT_TYPES = ('none', 'vlan', 'gre') id = Column(Integer, primary_key=True) mode = Column( - Enum(*MODES, name='cluster_mode'), + Enum(*consts.CLUSTER_MODES, name='cluster_mode'), nullable=False, - default='multinode' + default=consts.CLUSTER_MODES.multinode ) status = Column( - Enum(*STATUSES, name='cluster_status'), + Enum(*consts.CLUSTER_STATUSES, name='cluster_status'), nullable=False, - default='new' + default=consts.CLUSTER_STATUSES.new ) net_provider = Column( - Enum(*NET_PROVIDERS, name='net_provider'), + Enum(*consts.CLUSTER_NET_PROVIDERS, name='net_provider'), nullable=False, - default='nova_network' + default=consts.CLUSTER_NET_PROVIDERS.nova_network ) net_l23_provider = Column( - Enum(*NET_L23_PROVIDERS, name='net_l23_provider'), + Enum(*consts.CLUSTER_NET_L23_PROVIDERS, name='net_l23_provider'), nullable=False, - default='ovs' + default=consts.CLUSTER_NET_L23_PROVIDERS.ovs ) net_segment_type = Column( - Enum(*NET_SEGMENT_TYPES, + Enum(*consts.CLUSTER_NET_SEGMENT_TYPES, name='net_segment_type'), nullable=False, - default='vlan' + default=consts.CLUSTER_NET_SEGMENT_TYPES.vlan ) net_manager = Column( - Enum(*NET_MANAGERS, name='cluster_net_manager'), + Enum(*consts.CLUSTER_NET_MANAGERS, name='cluster_net_manager'), nullable=False, - default='FlatDHCPManager' + default=consts.CLUSTER_NET_MANAGERS.FlatDHCPManager ) grouping = Column( - Enum(*GROUPING, name='cluster_grouping'), + Enum(*consts.CLUSTER_GROUPING, name='cluster_grouping'), nullable=False, - default='roles' + default=consts.CLUSTER_GROUPING.roles ) name = Column(Unicode(50), unique=True, nullable=False) release_id = Column(Integer, ForeignKey('releases.id'), nullable=False) @@ -197,7 +184,7 @@ class Cluster(Base): if node_id: ch.node_id = node_id db().add(ch) - db().commit() + db().flush() def clear_pending_changes(self, node_id=None): chs = db().query(ClusterChanges).filter_by( @@ -206,7 +193,7 @@ class Cluster(Base): if node_id: chs = chs.filter_by(node_id=node_id) map(db().delete, chs.all()) - db().commit() + db().flush() @property def network_manager(self): @@ -249,7 +236,7 @@ class Attributes(Base): def generate_fields(self): self.generated = self.traverse(self.generated) db().add(self) - db().commit() + db().flush() @classmethod def traverse(cls, cdict): diff --git a/nailgun/nailgun/errors/__init__.py b/nailgun/nailgun/errors/__init__.py index 5e7cfb5388..d81c5ab2ef 100644 --- a/nailgun/nailgun/errors/__init__.py +++ b/nailgun/nailgun/errors/__init__.py @@ -24,6 +24,7 @@ default_messages = { # REST errors "CannotDelete": "Can't delete object", + "CannotCreate": "Can't create object", "InvalidField": "Invalid field specified for object", # node discovering errors diff --git a/nailgun/nailgun/network/manager.py b/nailgun/nailgun/network/manager.py index 0e92791e53..9145b8b19a 100644 --- a/nailgun/nailgun/network/manager.py +++ b/nailgun/nailgun/network/manager.py @@ -103,7 +103,7 @@ class NetworkManager(object): IPAddr.network == nw_group.id ).all() map(db().delete, ips) - db().commit() + db().flush() @classmethod def assign_admin_ips(cls, node_id, num=1): @@ -377,7 +377,7 @@ class NetworkManager(object): for nic in node.interfaces: while nic.assigned_networks_list: nic.assigned_networks_list.pop() - db().commit() + db().flush() @classmethod def get_default_networks_assignment(cls, node): @@ -464,7 +464,7 @@ class NetworkManager(object): nics[nic['id']].assigned_networks_list = list( db().query(NetworkGroup).filter( NetworkGroup.id.in_(ng_ids))) - db().commit() + db().flush() @classmethod def get_cluster_networkgroups_by_node(cls, node): @@ -1047,10 +1047,10 @@ class NetworkManager(object): meta=net ) db().add(nw_group) - db().commit() + db().flush() if net.get("notation"): nw_group.ip_ranges.append(new_ip_range) - db().commit() + db().flush() cls.cleanup_network_group(nw_group) @classmethod diff --git a/nailgun/nailgun/network/neutron.py b/nailgun/nailgun/network/neutron.py index e9221a6156..694b4cdea3 100644 --- a/nailgun/nailgun/network/neutron.py +++ b/nailgun/nailgun/network/neutron.py @@ -123,7 +123,7 @@ class NeutronManager(NetworkManager): .items(): setattr(cluster.neutron_config, key, value) db().add(cluster.neutron_config) - db().commit() + db().flush() @classmethod def generate_vlan_ids_list(cls, data, cluster, ng): diff --git a/nailgun/nailgun/objects/__init__.py b/nailgun/nailgun/objects/__init__.py index 96547cf427..2ddb3bc0da 100644 --- a/nailgun/nailgun/objects/__init__.py +++ b/nailgun/nailgun/objects/__init__.py @@ -20,5 +20,8 @@ from nailgun.objects.base import NailgunCollection from nailgun.objects.release import Release from nailgun.objects.release import ReleaseCollection +from nailgun.objects.cluster import Cluster +from nailgun.objects.cluster import ClusterCollection + from nailgun.objects.task import Task from nailgun.objects.task import TaskCollection diff --git a/nailgun/nailgun/objects/cluster.py b/nailgun/nailgun/objects/cluster.py new file mode 100644 index 0000000000..00dc6ae0a4 --- /dev/null +++ b/nailgun/nailgun/objects/cluster.py @@ -0,0 +1,172 @@ +# -*- 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. + +from nailgun import consts + +from nailgun.api.serializers.cluster import ClusterSerializer + +from nailgun.db import db + +from nailgun.db.sqlalchemy import models + +from nailgun.errors import errors + +from nailgun.objects import NailgunCollection +from nailgun.objects import NailgunObject + + +class Cluster(NailgunObject): + + model = models.Cluster + serializer = ClusterSerializer + + schema = { + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Cluster", + "description": "Serialized Cluster object", + "type": "object", + "properties": { + "id": {"type": "number"}, + "name": {"type": "string"}, + "mode": { + "type": "string", + "enum": list(consts.CLUSTER_MODES) + }, + "status": { + "type": "string", + "enum": list(consts.CLUSTER_STATUSES) + }, + "net_provider": { + "type": "string", + "enum": list(consts.CLUSTER_NET_PROVIDERS) + }, + "net_l23_provider": { + "type": "string", + "enum": list(consts.CLUSTER_NET_L23_PROVIDERS) + }, + "net_segment_type": { + "type": "string", + "enum": list(consts.CLUSTER_NET_SEGMENT_TYPES) + }, + "net_manager": { + "type": "string", + "enum": list(consts.CLUSTER_NET_MANAGERS) + }, + "grouping": { + "type": "string", + "enum": list(consts.CLUSTER_GROUPING) + }, + "release_id": {"type": "number"}, + "dns_nameservers": {"type": "array"}, + "replaced_deployment_info": {"type": "object"}, + "replaced_provisioning_info": {"type": "object"}, + "is_customized": {"type": "boolean"} + } + } + + @classmethod + def create(cls, data): + #TODO(enchantner): fix this temporary hack in clients + if "release_id" not in data: + release_id = data.pop("release", None) + data["release_id"] = release_id + + assign_nodes = data.pop("nodes", []) + + with db().begin(subtransactions=True): + new_cluster = super(Cluster, cls).create(data) + + attributes = models.Attributes( + editable=new_cluster.release.attributes_metadata.get( + "editable" + ), + generated=new_cluster.release.attributes_metadata.get( + "generated" + ), + cluster=new_cluster + ) + attributes.generate_fields() + + netmanager = new_cluster.network_manager + + try: + netmanager.create_network_groups(new_cluster.id) + if new_cluster.net_provider == 'neutron': + netmanager.create_neutron_config(new_cluster) + + new_cluster.add_pending_changes("attributes") + new_cluster.add_pending_changes("networks") + + if assign_nodes: + cls.update_nodes(new_cluster, assign_nodes) + + except ( + errors.OutOfVLANs, + errors.OutOfIPs, + errors.NoSuitableCIDR, + errors.InvalidNetworkPool + ) as exc: + db().delete(new_cluster) + raise errors.CannotCreate(exc.message) + + return new_cluster + + @classmethod + def update(cls, instance, data): + nodes = data.pop("nodes", None) + super(Cluster, cls).update(instance, data) + if nodes is not None: + cls.update_nodes(instance, nodes) + return instance + + @classmethod + def update_nodes(cls, instance, nodes_ids): + with db().begin(subtransactions=True): + # TODO(NAME): sepatate nodes + #for deletion and addition by set(). + new_nodes = [] + if nodes_ids: + new_nodes = db().query(models.Node).filter( + models.Node.id.in_(nodes_ids) + ) + + nodes_to_remove = [n for n in instance.nodes + if n not in new_nodes] + nodes_to_add = [n for n in new_nodes + if n not in instance.nodes] + + for node in nodes_to_add: + if not node.online: + raise errors.NodeOffline( + u"Cannot add offline node " + u"'{0}' to environment".format(node.id) + ) + + map(instance.nodes.remove, nodes_to_remove) + map(instance.nodes.append, nodes_to_add) + map( + instance.network_manager.clear_assigned_networks, + nodes_to_remove + ) + map( + instance.network_manager.assign_networks_by_default, + nodes_to_add + ) + + +class ClusterCollection(NailgunCollection): + + single = Cluster diff --git a/nailgun/nailgun/test/integration/test_changes_model.py b/nailgun/nailgun/test/integration/test_changes_model.py index 9552c0399b..8a126cc8e2 100644 --- a/nailgun/nailgun/test/integration/test_changes_model.py +++ b/nailgun/nailgun/test/integration/test_changes_model.py @@ -57,7 +57,7 @@ class TestClusterChanges(BaseIntegrationTest): resp = self.app.get( reverse( 'ClusterHandler', - kwargs={'cluster_id': cluster['id']}), + kwargs={'obj_id': cluster['id']}), headers=self.default_headers ) response = json.loads(resp.body) diff --git a/nailgun/nailgun/test/integration/test_charset_issues.py b/nailgun/nailgun/test/integration/test_charset_issues.py index 9ea4d2dea4..922a310067 100644 --- a/nailgun/nailgun/test/integration/test_charset_issues.py +++ b/nailgun/nailgun/test/integration/test_charset_issues.py @@ -71,7 +71,7 @@ class TestCharsetIssues(BaseIntegrationTest): self.app.delete( reverse( 'ClusterHandler', - kwargs={'cluster_id': cluster_id}), + kwargs={'obj_id': cluster_id}), headers=self.default_headers ) timeout = 10 diff --git a/nailgun/nailgun/test/integration/test_cluster_handler.py b/nailgun/nailgun/test/integration/test_cluster_handler.py index 47cd96fb46..4dbc62e4bd 100644 --- a/nailgun/nailgun/test/integration/test_cluster_handler.py +++ b/nailgun/nailgun/test/integration/test_cluster_handler.py @@ -30,7 +30,7 @@ class TestHandlers(BaseIntegrationTest): def delete(self, cluster_id): return self.app.delete( - reverse('ClusterHandler', kwargs={'cluster_id': cluster_id}), + reverse('ClusterHandler', kwargs={'obj_id': cluster_id}), '', headers=self.default_headers ) @@ -38,7 +38,7 @@ class TestHandlers(BaseIntegrationTest): def test_cluster_get(self): cluster = self.env.create_cluster(api=False) resp = self.app.get( - reverse('ClusterHandler', kwargs={'cluster_id': cluster.id}), + reverse('ClusterHandler', kwargs={'obj_id': cluster.id}), headers=self.default_headers ) self.assertEquals(200, resp.status_code) @@ -70,7 +70,7 @@ class TestHandlers(BaseIntegrationTest): clusters_before = len(self.db.query(Cluster).all()) resp = self.app.put( - reverse('ClusterHandler', kwargs={'cluster_id': cluster.id}), + reverse('ClusterHandler', kwargs={'obj_id': cluster.id}), json.dumps({'name': updated_name}), headers=self.default_headers ) @@ -89,7 +89,7 @@ class TestHandlers(BaseIntegrationTest): cluster = self.env.create_cluster(api=False) self.assertEquals(cluster.net_manager, "FlatDHCPManager") resp = self.app.put( - reverse('ClusterHandler', kwargs={'cluster_id': cluster.id}), + reverse('ClusterHandler', kwargs={'obj_id': cluster.id}), json.dumps({'net_manager': 'VlanManager'}), headers=self.default_headers ) @@ -101,13 +101,16 @@ class TestHandlers(BaseIntegrationTest): cluster = self.env.create_cluster(api=False) self.assertEquals(cluster.net_provider, "nova_network") resp = self.app.put( - reverse('ClusterHandler', kwargs={'cluster_id': cluster.id}), + reverse('ClusterHandler', kwargs={'obj_id': cluster.id}), json.dumps({'net_provider': 'neutron'}), headers=self.default_headers, expect_errors=True ) self.assertEquals(resp.status_code, 400) - self.assertEquals(resp.body, "Change of 'net_provider' is prohibited") + self.assertEquals( + resp.body, + "Changing 'net_provider' for environment is prohibited" + ) def test_cluster_update_fails_on_net_segment_type_change(self): cluster = self.env.create_cluster( @@ -117,23 +120,26 @@ class TestHandlers(BaseIntegrationTest): ) self.assertEquals(cluster.net_provider, "neutron") resp = self.app.put( - reverse('ClusterHandler', kwargs={'cluster_id': cluster.id}), + reverse('ClusterHandler', kwargs={'obj_id': cluster.id}), json.dumps({'net_segment_type': 'vlan'}), headers=self.default_headers, expect_errors=True ) self.assertEquals(resp.status_code, 400) - self.assertEquals(resp.body, - "Change of 'net_segment_type' is prohibited") + self.assertEquals( + resp.body, + "Changing 'net_segment_type' for environment is prohibited" + ) def test_cluster_node_list_update(self): node1 = self.env.create_node(api=False) node2 = self.env.create_node(api=False) cluster = self.env.create_cluster(api=False) resp = self.app.put( - reverse('ClusterHandler', kwargs={'cluster_id': cluster.id}), + reverse('ClusterHandler', kwargs={'obj_id': cluster.id}), json.dumps({'nodes': [node1.id]}), - headers=self.default_headers + headers=self.default_headers, + expect_errors=True ) self.assertEquals(resp.status_code, 200) @@ -142,7 +148,7 @@ class TestHandlers(BaseIntegrationTest): self.assertEquals(nodes[0].id, node1.id) resp = self.app.put( - reverse('ClusterHandler', kwargs={'cluster_id': cluster.id}), + reverse('ClusterHandler', kwargs={'obj_id': cluster.id}), json.dumps({'nodes': [node2.id]}), headers=self.default_headers ) diff --git a/nailgun/nailgun/test/integration/test_node_nic_assignment.py b/nailgun/nailgun/test/integration/test_node_nic_assignment.py index a5d377136b..92ba372179 100644 --- a/nailgun/nailgun/test/integration/test_node_nic_assignment.py +++ b/nailgun/nailgun/test/integration/test_node_nic_assignment.py @@ -65,7 +65,7 @@ class TestClusterHandlers(BaseIntegrationTest): node = self.env.create_node(api=True, meta=meta, mac=mac) cluster = self.env.create_cluster(api=True, nodes=[node['id']]) resp = self.app.put( - reverse('ClusterHandler', kwargs={'cluster_id': cluster['id']}), + reverse('ClusterHandler', kwargs={'obj_id': cluster['id']}), json.dumps({'nodes': []}), headers=self.default_headers ) diff --git a/nailgun/nailgun/test/integration/test_orchestrator_serializer.py b/nailgun/nailgun/test/integration/test_orchestrator_serializer.py index 3fdbad13e5..5b7d77d805 100644 --- a/nailgun/nailgun/test/integration/test_orchestrator_serializer.py +++ b/nailgun/nailgun/test/integration/test_orchestrator_serializer.py @@ -21,7 +21,6 @@ import json from netaddr import IPRange from nailgun.consts import OVS_BOND_MODES -from nailgun.db import db from nailgun.db.sqlalchemy.models import Cluster from nailgun.db.sqlalchemy.models import IPAddrRange from nailgun.db.sqlalchemy.models import NetworkGroup @@ -50,7 +49,7 @@ class OrchestratorSerializerTestBase(BaseIntegrationTest): self.assertEquals(len(self.filter_by_role(nodes, role)), count) def get_controllers(self, cluster_id): - return db().query(Node).\ + return self.db.query(Node).\ filter_by(cluster_id=cluster_id, pending_deletion=False).\ filter(Node.role_list.any(name='controller')).\ @@ -526,7 +525,7 @@ class TestNeutronOrchestratorSerializer(OrchestratorSerializerTestBase): # Remove 'vlan_splinters' attribute and check results. editable_attrs.pop('vlan_splinters', None) - db.refresh(cluster.attributes) + self.db.refresh(cluster.attributes) cluster.attributes.editable = editable_attrs self.db.commit() @@ -545,7 +544,7 @@ class TestNeutronOrchestratorSerializer(OrchestratorSerializerTestBase): # Set 'vlan_splinters' to 'some_text' and check results. editable_attrs['vlan_splinters'] = {'value': 'some_text'} - db.refresh(cluster.attributes) + self.db.refresh(cluster.attributes) cluster.attributes.editable = editable_attrs self.db.commit() @@ -565,7 +564,7 @@ class TestNeutronOrchestratorSerializer(OrchestratorSerializerTestBase): # Set 'vlan_splinters' to 'disabled' and check results. editable_attrs['vlan_splinters'] = {'value': 'disabled'} - db.refresh(cluster.attributes) + self.db.refresh(cluster.attributes) cluster.attributes.editable = editable_attrs self.db.commit() @@ -591,7 +590,7 @@ class TestNeutronOrchestratorSerializer(OrchestratorSerializerTestBase): #value of kernel-ml should end up with vlan_splinters = off editable_attrs['vlan_splinters'] = {'value': 'kernel_lt'} - db.refresh(cluster.attributes) + self.db.refresh(cluster.attributes) cluster.attributes.editable = editable_attrs self.db.commit() @@ -617,7 +616,7 @@ class TestNeutronOrchestratorSerializer(OrchestratorSerializerTestBase): editable_attrs.setdefault( 'vlan_splinters', {'value': 'hard'} )['value'] = 'hard' - db.refresh(cluster.attributes) + self.db.refresh(cluster.attributes) cluster.attributes.editable = editable_attrs self.db.commit() @@ -647,7 +646,7 @@ class TestNeutronOrchestratorSerializer(OrchestratorSerializerTestBase): editable_attrs.setdefault( 'vlan_splinters', {'value': 'hard'} )['value'] = 'hard' - db.refresh(cluster.attributes) + self.db.refresh(cluster.attributes) cluster.attributes.editable = editable_attrs self.db.commit() @@ -682,7 +681,7 @@ class TestNeutronOrchestratorSerializer(OrchestratorSerializerTestBase): editable_attrs.setdefault( 'vlan_splinters', {'value': 'soft'} )['value'] = 'soft' - db.refresh(cluster.attributes) + self.db.refresh(cluster.attributes) cluster.attributes.editable = editable_attrs self.db.commit() diff --git a/nailgun/nailgun/test/integration/test_provisioning_serializer.py b/nailgun/nailgun/test/integration/test_provisioning_serializer.py index 55e29b3a03..5a47adf5bf 100644 --- a/nailgun/nailgun/test/integration/test_provisioning_serializer.py +++ b/nailgun/nailgun/test/integration/test_provisioning_serializer.py @@ -15,7 +15,6 @@ # under the License. -from nailgun.db import db from nailgun.db.sqlalchemy.models import Cluster from nailgun.db.sqlalchemy.models import Node from nailgun.orchestrator.provisioning_serializers import serialize @@ -40,7 +39,9 @@ class TestProvisioningSerializer(BaseIntegrationTest): serialized_cluster = serialize(cluster_db, cluster_db.nodes) for node in serialized_cluster['nodes']: - node_db = db().query(Node).filter_by(fqdn=node['hostname']).first() + node_db = self.db.query(Node).filter_by( + fqdn=node['hostname'] + ).first() self.assertEquals( node['kernel_options']['netcfg/choose_interface'], node_db.admin_interface.mac) diff --git a/nailgun/nailgun/test/integration/test_roles.py b/nailgun/nailgun/test/integration/test_roles.py index 3126a15a00..56010b4399 100644 --- a/nailgun/nailgun/test/integration/test_roles.py +++ b/nailgun/nailgun/test/integration/test_roles.py @@ -18,7 +18,6 @@ import json from sqlalchemy.exc import IntegrityError -from nailgun.db import db from nailgun.db.sqlalchemy.models import Role from nailgun.test.base import BaseIntegrationTest from nailgun.test.base import reverse @@ -108,10 +107,10 @@ class TestRoles(BaseIntegrationTest): release_id=release_json["id"]) added = True try: - db().add(role) - db().commit() + self.db.add(role) + self.db.commit() except IntegrityError: - db.rollback() + self.db.rollback() added = False self.assertFalse(added) diff --git a/nailgun/nailgun/test/integration/test_stop_deployment.py b/nailgun/nailgun/test/integration/test_stop_deployment.py index cfbeb18f17..d96b3e3005 100644 --- a/nailgun/nailgun/test/integration/test_stop_deployment.py +++ b/nailgun/nailgun/test/integration/test_stop_deployment.py @@ -14,7 +14,6 @@ # License for the specific language governing permissions and limitations # under the License. -from nailgun.db import db from nailgun.db.sqlalchemy.models.task import Task from nailgun.test.base import BaseIntegrationTest @@ -51,7 +50,7 @@ class TestStopDeployment(BaseIntegrationTest): stop_task = self.env.stop_deployment() self.env.wait_ready(stop_task, 60) self.assertIsNone( - db().query(Task).filter_by( + self.db.query(Task).filter_by( uuid=deploy_task_uuid ).first() ) diff --git a/nailgun/nailgun/test/integration/test_task_managers.py b/nailgun/nailgun/test/integration/test_task_managers.py index 5ce2f6e533..0efc635ee9 100644 --- a/nailgun/nailgun/test/integration/test_task_managers.py +++ b/nailgun/nailgun/test/integration/test_task_managers.py @@ -205,7 +205,7 @@ class TestTaskManagers(BaseIntegrationTest): resp = self.app.delete( reverse( 'ClusterHandler', - kwargs={'cluster_id': self.env.clusters[0].id}), + kwargs={'obj_id': self.env.clusters[0].id}), headers=self.default_headers ) self.assertEquals(202, resp.status_code) @@ -246,7 +246,7 @@ class TestTaskManagers(BaseIntegrationTest): resp = self.app.delete( reverse( 'ClusterHandler', - kwargs={'cluster_id': cluster_id}), + kwargs={'obj_id': cluster_id}), headers=self.default_headers ) self.assertEquals(202, resp.status_code) @@ -291,7 +291,7 @@ class TestTaskManagers(BaseIntegrationTest): resp = self.app.delete( reverse( 'ClusterHandler', - kwargs={'cluster_id': cluster_id}), + kwargs={'obj_id': cluster_id}), headers=self.default_headers ) timeout = 120 @@ -335,7 +335,7 @@ class TestTaskManagers(BaseIntegrationTest): resp = self.app.delete( reverse( 'ClusterHandler', - kwargs={'cluster_id': cluster_id}), + kwargs={'obj_id': cluster_id}), headers=self.default_headers ) self.assertEquals(202, resp.status_code) diff --git a/nailgun/nailgun/test/unit/test_handlers.py b/nailgun/nailgun/test/unit/test_handlers.py index 4eec20198c..356d461d43 100644 --- a/nailgun/nailgun/test/unit/test_handlers.py +++ b/nailgun/nailgun/test/unit/test_handlers.py @@ -25,7 +25,7 @@ from nailgun.test.base import reverse class TestHandlers(BaseIntegrationTest): def test_all_api_urls_404_or_405(self): urls = { - 'ClusterHandler': {'cluster_id': 1}, + 'ClusterHandler': {'obj_id': 1}, 'NodeHandler': {'node_id': 1}, 'ReleaseHandler': {'obj_id': 1}, } diff --git a/nailgun/nailgun/test/unit/test_logs_handlers.py b/nailgun/nailgun/test/unit/test_logs_handlers.py index 68717858c9..7553b6e8e6 100644 --- a/nailgun/nailgun/test/unit/test_logs_handlers.py +++ b/nailgun/nailgun/test/unit/test_logs_handlers.py @@ -25,7 +25,6 @@ from mock import patch import nailgun from nailgun.api.handlers.logs import read_backwards -from nailgun.db import db from nailgun.db.sqlalchemy.models import RedHatAccount from nailgun.db.sqlalchemy.models import Role from nailgun.errors import errors @@ -394,7 +393,7 @@ class TestLogs(BaseIntegrationTest): """ def dump_task_with_bad_model(*args, **kwargs): - db().add(Role()) + self.db.add(Role()) raise errors.DumpRunning() dump_manager().execute.side_effect = dump_task_with_bad_model diff --git a/nailgun/nailgun/test/unit/test_rpc_receiver.py b/nailgun/nailgun/test/unit/test_rpc_receiver.py index e62d24c990..3ec82bfc7d 100644 --- a/nailgun/nailgun/test/unit/test_rpc_receiver.py +++ b/nailgun/nailgun/test/unit/test_rpc_receiver.py @@ -16,7 +16,6 @@ from nailgun.errors import errors from nailgun.test.base import BaseTestCase -from nailgun.db import db from nailgun.db.sqlalchemy.models import Task from nailgun.task.helpers import TaskHelper @@ -25,8 +24,8 @@ class TestUtils(BaseTestCase): def test_get_task_by_uuid_returns_task(self): task = Task(name='deploy') - db().add(task) - db().commit() + self.db.add(task) + self.db.commit() task_by_uuid = TaskHelper.get_task_by_uuid(task.uuid) self.assertEquals(task.uuid, task_by_uuid.uuid)