Merge "Add 'deployed_before' flag to cluster that forbids stop deployment"

This commit is contained in:
Jenkins 2016-02-01 14:04:44 +00:00 committed by Gerrit Code Review
commit a9281e8d79
14 changed files with 176 additions and 5 deletions

View File

@ -562,6 +562,7 @@ class DeferredTaskHandler(BaseHandler):
errors.NoDeploymentTasks, errors.NoDeploymentTasks,
errors.WrongNodeStatus, errors.WrongNodeStatus,
errors.UnavailableRelease, errors.UnavailableRelease,
errors.CannotBeStopped,
) as exc: ) as exc:
raise self.http(400, exc.message) raise self.http(400, exc.message)
except Exception as exc: except Exception as exc:

View File

@ -29,6 +29,7 @@ from nailgun.api.v1.handlers.base import SingleHandler
from nailgun.api.v1.validators.cluster import AttributesValidator from nailgun.api.v1.validators.cluster import AttributesValidator
from nailgun.api.v1.validators.cluster import ClusterChangesValidator from nailgun.api.v1.validators.cluster import ClusterChangesValidator
from nailgun.api.v1.validators.cluster import ClusterStopDeploymentValidator
from nailgun.api.v1.validators.cluster import ClusterValidator from nailgun.api.v1.validators.cluster import ClusterValidator
from nailgun.api.v1.validators.cluster import VmwareAttributesValidator from nailgun.api.v1.validators.cluster import VmwareAttributesValidator
@ -92,6 +93,7 @@ class ClusterStopDeploymentHandler(DeferredTaskHandler):
log_error = u"Error during execution of deployment " \ log_error = u"Error during execution of deployment " \
u"stopping task on environment '{env_id}': {error}" u"stopping task on environment '{env_id}': {error}"
task_manager = StopDeploymentTaskManager task_manager = StopDeploymentTaskManager
validator = ClusterStopDeploymentValidator
class ClusterResetHandler(DeferredTaskHandler): class ClusterResetHandler(DeferredTaskHandler):

View File

@ -433,6 +433,19 @@ class ClusterChangesValidator(BaseDefferedTaskValidator):
ProvisionSelectedNodesValidator.validate_provision(None, cluster) ProvisionSelectedNodesValidator.validate_provision(None, cluster)
class ClusterStopDeploymentValidator(BaseDefferedTaskValidator):
@classmethod
def validate(cls, cluster):
super(ClusterStopDeploymentValidator, cls).validate(cluster)
# FIXME(aroma): remove when stop action will be reworked for ha
# cluster. To get more details, please, refer to [1]
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
if cluster.attributes.generated['deployed_before']['value']:
raise errors.CannotBeStopped()
class VmwareAttributesValidator(BasicValidator): class VmwareAttributesValidator(BasicValidator):
single_schema = cluster_schema.vmware_attributes_schema single_schema = cluster_schema.vmware_attributes_schema

View File

@ -42,6 +42,7 @@ default_messages = {
"NoDeploymentTasks": "Deployment tasks not found for specific release in the database", "NoDeploymentTasks": "Deployment tasks not found for specific release in the database",
"DeletionAlreadyStarted": "Environment removal already started", "DeletionAlreadyStarted": "Environment removal already started",
"StopAlreadyRunning": "Stopping deployment already initiated", "StopAlreadyRunning": "Stopping deployment already initiated",
"CannotBeStopped": "Stop action is forbidden for the cluster",
"FailedProvisioning": "Failed to start provisioning", "FailedProvisioning": "Failed to start provisioning",
"WrongNodeStatus": "Wrong node status", "WrongNodeStatus": "Wrong node status",
"NodeOffline": "Node is offline", "NodeOffline": "Node is offline",

View File

@ -1351,6 +1351,8 @@
puppet: puppet:
manifests: "rsync://{settings.MASTER_IP}:/puppet/{cluster.release.version}/manifests/" manifests: "rsync://{settings.MASTER_IP}:/puppet/{cluster.release.version}/manifests/"
modules: "rsync://{settings.MASTER_IP}:/puppet/{cluster.release.version}/modules/" modules: "rsync://{settings.MASTER_IP}:/puppet/{cluster.release.version}/modules/"
deployed_before:
value: false
wizard_metadata: wizard_metadata:
Mode: Mode:
metadata: metadata:

View File

@ -1339,6 +1339,29 @@ class Cluster(NailgunObject):
attrs = cls.get_editable_attributes(instance, False) attrs = cls.get_editable_attributes(instance, False)
return attrs['common'].get('task_deploy', {}).get('value') return attrs['common'].get('task_deploy', {}).get('value')
# FIXME(aroma): remove updating of 'deployed_before'
# when stop action is reworked. 'deployed_before'
# flag identifies whether stop action is allowed for the
# cluster. Please, refer to [1] for more details.
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
@classmethod
def set_deployed_before_flag(cls, instance, value):
"""Change value for before_deployed if needed
:param instance: nailgun.db.sqlalchemy.models.Cluster instance
:param value: new value for flag
:type value: bool
"""
if instance.attributes.generated['deployed_before']['value'] != value:
# TODO(aroma): remove unnecessary copying when enhancement
# of Mutable types will be introduced for corresponding
# fields of ORM models
generated_attrs = copy.deepcopy(instance.attributes.generated)
generated_attrs['deployed_before']['value'] = value
instance.attributes.generated = generated_attrs
db.flush()
class ClusterCollection(NailgunCollection): class ClusterCollection(NailgunCollection):
"""Cluster collection.""" """Cluster collection."""

View File

@ -167,7 +167,18 @@ class Task(NailgunObject):
logger.debug( logger.debug(
"Updating cluster (%s) status: from %s to %s", "Updating cluster (%s) status: from %s to %s",
cluster.full_name, cluster.status, status) cluster.full_name, cluster.status, status)
Cluster.update(cluster, data={'status': status})
data = {'status': status}
# FIXME(aroma): remove updating of 'deployed_before'
# when stop action is reworked. 'deployed_before'
# flag identifies whether stop action is allowed for the
# cluster. Please, refer to [1] for more details.
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
if status == consts.CLUSTER_STATUSES.operational:
Cluster.set_deployed_before_flag(cluster, value=True)
Cluster.update(cluster, data)
@classmethod @classmethod
def _update_cluster_data(cls, instance): def _update_cluster_data(cls, instance):
@ -175,7 +186,7 @@ class Task(NailgunObject):
if instance.name == 'deploy': if instance.name == 'deploy':
if instance.status == 'ready': if instance.status == 'ready':
# If for some reasosns orchestrator # If for some reasons orchestrator
# didn't send ready status for node # didn't send ready status for node
# we should set it explicitly # we should set it explicitly
for n in cluster.nodes: for n in cluster.nodes:

View File

@ -747,6 +747,14 @@ class StopDeploymentTaskManager(TaskManager):
class ResetEnvironmentTaskManager(TaskManager): class ResetEnvironmentTaskManager(TaskManager):
def execute(self): def execute(self):
# FIXME(aroma): remove updating of 'deployed_before'
# when stop action is reworked. 'deployed_before'
# flag identifies whether stop action is allowed for the
# cluster. Please, refer to [1] for more details.
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
objects.Cluster.set_deployed_before_flag(self.cluster, value=False)
deploy_running = db().query(Task).filter_by( deploy_running = db().query(Task).filter_by(
cluster=self.cluster, cluster=self.cluster,
name=consts.TASK_NAMES.deploy, name=consts.TASK_NAMES.deploy,

View File

@ -59,6 +59,12 @@ class TestResetEnvironment(BaseIntegrationTest):
self.assertEqual(cluster_db.status, "new") self.assertEqual(cluster_db.status, "new")
# FIXME(aroma): remove when stop action will be reworked for ha
# cluster. To get more details, please, refer to [1]
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
self.assertFalse(
cluster_db.attributes.generated['deployed_before']['value'])
for n in cluster_db.nodes: for n in cluster_db.nodes:
self.assertEqual(n.online, False) self.assertEqual(n.online, False)
self.assertEqual(n.status, "discover") self.assertEqual(n.status, "discover")

View File

@ -23,6 +23,7 @@ from nailgun.db.sqlalchemy.models.task import Task
from nailgun import objects from nailgun import objects
from nailgun.test.base import BaseIntegrationTest from nailgun.test.base import BaseIntegrationTest
from nailgun.test.base import fake_tasks from nailgun.test.base import fake_tasks
from nailgun.test.base import reverse
class TestStopDeployment(BaseIntegrationTest): class TestStopDeployment(BaseIntegrationTest):
@ -78,6 +79,42 @@ class TestStopDeployment(BaseIntegrationTest):
'Please make changes and reset the environment ' 'Please make changes and reset the environment '
'if you want to redeploy it.') 'if you want to redeploy it.')
# FIXME(aroma): remove when stop action will be reworked for ha
# cluster. To get more details, please, refer to [1]
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
@fake_tasks(tick_interval=1)
def test_stop_deployment_fail_if_deployed_before(self):
deploy_task = self.env.launch_deployment()
self.env.wait_ready(deploy_task)
# changes to deploy
self.env.create_node(
cluster_id=self.cluster.id,
roles=["controller"],
pending_addition=True
)
redeploy_task = self.env.launch_deployment()
self.env.wait_until_task_pending(redeploy_task)
# stop task will not be created as in this situation
# the error will be raised by validator thus we cannot use
# self.env.stop_deployment to check the result
resp = self.app.put(
reverse(
'ClusterStopDeploymentHandler',
kwargs={'cluster_id': self.cluster.id}),
expect_errors=True,
headers=self.default_headers
)
self.assertEqual(resp.status_code, 400)
self.assertEqual(resp.json_body['message'],
'Stop action is forbidden for the cluster')
# wait that redeployment end successfully
self.env.wait_ready(redeploy_task)
@fake_tasks(fake_rpc=False, mock_rpc=False) @fake_tasks(fake_rpc=False, mock_rpc=False)
@patch('nailgun.rpc.cast') @patch('nailgun.rpc.cast')
def test_admin_ip_in_args(self, mocked_rpc): def test_admin_ip_in_args(self, mocked_rpc):

View File

@ -14,7 +14,6 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from mock import patch from mock import patch
from nailgun.test.base import BaseIntegrationTest from nailgun.test.base import BaseIntegrationTest
@ -162,6 +161,13 @@ class TestTasksLogging(BaseIntegrationTest):
self.env.wait_ready(deploy) self.env.wait_ready(deploy)
self.simulate_running_deployment(deploy) self.simulate_running_deployment(deploy)
# FIXME(aroma): remove when stop action will be reworked for ha
# cluster. To get more details, please, refer to [1]
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
cluster = self.env.clusters[0]
objects.Cluster.set_deployed_before_flag(cluster, value=False)
self.env.stop_deployment() self.env.stop_deployment()
self.assertGreaterEqual(len(logger.call_args_list), 1) self.assertGreaterEqual(len(logger.call_args_list), 1)
@ -283,6 +289,12 @@ class TestTasksLogging(BaseIntegrationTest):
deploy_uuid = deploy.uuid deploy_uuid = deploy.uuid
self.simulate_running_deployment(deploy) self.simulate_running_deployment(deploy)
# FIXME(aroma): remove when stop action will be reworked for ha
# cluster. To get more details, please, refer to [1]
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
cluster = self.env.clusters[0]
objects.Cluster.set_deployed_before_flag(cluster, value=False)
# Stopping deployment # Stopping deployment
self.env.stop_deployment() self.env.stop_deployment()

View File

@ -22,6 +22,7 @@ from six.moves import range
import unittest2 import unittest2
from nailgun import consts from nailgun import consts
from nailgun import objects
from nailgun.test.base import BaseIntegrationTest from nailgun.test.base import BaseIntegrationTest
from nailgun.test.base import fake_tasks from nailgun.test.base import fake_tasks
from nailgun.utils import reverse from nailgun.utils import reverse
@ -691,6 +692,12 @@ class TestVerifyNeutronVlan(BaseIntegrationTest):
cluster = self.env.clusters[0] cluster = self.env.clusters[0]
deploy_task = self.env.launch_deployment() deploy_task = self.env.launch_deployment()
self.env.wait_until_task_pending(deploy_task) self.env.wait_until_task_pending(deploy_task)
# FIXME(aroma): remove when stop action will be reworked for ha
# cluster. To get more details, please, refer to [1]
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
objects.Cluster.set_deployed_before_flag(cluster, value=False)
stop_task = self.env.stop_deployment() stop_task = self.env.stop_deployment()
self.env.wait_ready(stop_task, 60) self.env.wait_ready(stop_task, 60)
self.db.refresh(cluster) self.db.refresh(cluster)

View File

@ -18,9 +18,11 @@ from mock import patch
from mock import PropertyMock from mock import PropertyMock
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from nailgun.api.v1.validators.cluster import ClusterStopDeploymentValidator
from nailgun.api.v1.validators.cluster import ClusterValidator from nailgun.api.v1.validators.cluster import ClusterValidator
from nailgun import consts from nailgun import consts
from nailgun.errors import errors from nailgun.errors import errors
from nailgun import objects
from nailgun.test.base import BaseTestCase from nailgun.test.base import BaseTestCase
@ -214,3 +216,20 @@ class TestClusterValidator(BaseTestCase):
ClusterValidator.validate_update, ClusterValidator.validate_update,
self.cluster_data, self.cluster_data,
cluster_mock) cluster_mock)
class TestClusterStopDeploymentValidator(BaseTestCase):
# FIXME(aroma): remove this test when stop action will be reworked for ha
# cluster. To get more details, please, refer to [1]
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
def test_stop_deployment_failed_for_once_deployed_cluster(self):
cluster = self.env.create_cluster(api=False)
objects.Cluster.set_deployed_before_flag(cluster, value=True)
self.assertRaises(
errors.CannotBeStopped,
ClusterStopDeploymentValidator.validate,
cluster
)

View File

@ -723,8 +723,10 @@ class TestTaskObject(BaseIntegrationTest):
objects.Task._update_cluster_data(task) objects.Task._update_cluster_data(task)
self.db.flush() self.db.flush()
self.assertEquals(self.cluster.status, self.assertEqual(self.cluster.status,
consts.CLUSTER_STATUSES.operational) consts.CLUSTER_STATUSES.operational)
self.assertTrue(
self.cluster.attributes.generated['deployed_before']['value'])
def test_update_vms_conf(self): def test_update_vms_conf(self):
kvm_node = self.cluster.nodes[0] kvm_node = self.cluster.nodes[0]
@ -984,6 +986,33 @@ class TestClusterObject(BaseTestCase):
return dict_merge(network_role, kwargs) return dict_merge(network_role, kwargs)
# FIXME(aroma): remove this test when stop action will be reworked for ha
# cluster. To get more details, please, refer to [1]
# [1]: https://bugs.launchpad.net/fuel/+bug/1529691
def test_set_deployed_before_flag(self):
self.assertFalse(
self.cluster.attributes.generated['deployed_before']['value'])
# check that the flags is set to true if was false
objects.Cluster.set_deployed_before_flag(self.cluster, value=True)
self.assertTrue(
self.cluster.attributes.generated['deployed_before']['value'])
# check that flag is set to false if was true
objects.Cluster.set_deployed_before_flag(self.cluster, value=False)
self.assertFalse(
self.cluster.attributes.generated['deployed_before']['value'])
# check that flag is not changed when same value is given
# and interaction w/ db is not performed
with mock.patch.object(self.db, 'flush') as m_flush:
objects.Cluster.set_deployed_before_flag(self.cluster,
value=False)
self.assertFalse(
self.cluster.attributes.generated['deployed_before']['value'])
m_flush.assert_not_called()
def test_network_defaults(self): def test_network_defaults(self):
cluster = objects.Cluster.get_by_uid(self.env.create(api=True)['id']) cluster = objects.Cluster.get_by_uid(self.env.create(api=True)['id'])