Merge "Add 'deployed_before' flag to cluster that forbids stop deployment"
This commit is contained in:
commit
a9281e8d79
|
@ -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:
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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."""
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
|
|
|
@ -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'])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue