From 3d42dae017dfbb660c3b0f3819baaac77e3b091d Mon Sep 17 00:00:00 2001 From: Maciej Kwiek Date: Tue, 20 Oct 2015 11:40:25 +0200 Subject: [PATCH] Replace release.is_deployable with release.state is_deployable doesn't really give any additional information for a release, it is removed. To make change API-backward-compatible, it is retained as a property dependent on release.state. New state is added - manageonly, for environments that are not able to be deployed, but can still be managed. Change-Id: I518a0114730a2f227c9ef035a376f9a90d3d5bbd Closes-bug: #1503303 DocImpact --- .gitignore | 1 + .../fuel_package_updates/tests/base.py | 1 - .../fuel_upgrade/engines/openstack.py | 2 +- .../tests/test_openstack_upgrader.py | 2 +- nailgun/nailgun/consts.py | 1 + .../alembic_migrations/versions/fuel_8_0.py | 54 +++++++++++++++++++ .../nailgun/db/sqlalchemy/models/release.py | 2 - .../cluster_upgrade/objects/adapters.py | 2 +- .../extensions/cluster_upgrade/tests/base.py | 2 +- .../cluster_upgrade/tests/test_validators.py | 6 ++- .../extensions/cluster_upgrade/validators.py | 2 +- nailgun/nailgun/fixtures/openstack.yaml | 1 - nailgun/nailgun/objects/release.py | 3 +- .../test/unit/test_migration_fuel_8_0.py | 20 +++++-- .../nailgun/test/unit/test_release_handler.py | 11 ++-- nailgun/static/translations/core.json | 6 ++- nailgun/static/views/releases_page.jsx | 6 +-- nailgun/static/views/wizard.js | 2 +- 18 files changed, 99 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 4887eed590..2548ee72c8 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ lock node_modules nailgun/static/vendor/npm/* +nailgun/built-static/ *.egg .testrepository diff --git a/fuel_upgrade_system/fuel_package_updates/fuel_package_updates/tests/base.py b/fuel_upgrade_system/fuel_package_updates/fuel_package_updates/tests/base.py index 619d4c7e04..9494d6b97d 100644 --- a/fuel_upgrade_system/fuel_package_updates/fuel_package_updates/tests/base.py +++ b/fuel_upgrade_system/fuel_package_updates/fuel_package_updates/tests/base.py @@ -28,7 +28,6 @@ def make_release(**overrides): 'name': 'Kilo on Ubuntu 14.04.1', 'operating_system': 'Ubuntu', 'version': '2015.1.0-7.0', - 'is_deployable': True, 'state': 'available', 'attributes_metadata': {}, 'can_update_from_versions': [], diff --git a/fuel_upgrade_system/fuel_upgrade/fuel_upgrade/engines/openstack.py b/fuel_upgrade_system/fuel_upgrade/fuel_upgrade/engines/openstack.py index 497acf3d37..d91b771b78 100644 --- a/fuel_upgrade_system/fuel_upgrade/fuel_upgrade/engines/openstack.py +++ b/fuel_upgrade_system/fuel_upgrade/fuel_upgrade/engines/openstack.py @@ -124,7 +124,7 @@ class OpenStackUpgrader(UpgradeEngine): self._rollback_ids['release'].append(response['id']) self.upload_release_deployment_tasks(response) - if not release.get('is_deployable', True): + if not release.get('state', 'available') == 'available': continue # add notification abot successfull releases diff --git a/fuel_upgrade_system/fuel_upgrade/fuel_upgrade/tests/test_openstack_upgrader.py b/fuel_upgrade_system/fuel_upgrade/fuel_upgrade/tests/test_openstack_upgrader.py index 3cc637a30c..a9e9a48a0a 100644 --- a/fuel_upgrade_system/fuel_upgrade/fuel_upgrade/tests/test_openstack_upgrader.py +++ b/fuel_upgrade_system/fuel_upgrade/fuel_upgrade/tests/test_openstack_upgrader.py @@ -205,7 +205,7 @@ class TestOpenStackUpgrader(BaseTestCase): "name": "Undeployable releases name", "version": "2014.1", "operating_system": "CentOS", - "is_deployable": False, + "state": "unavailable", } } ] diff --git a/nailgun/nailgun/consts.py b/nailgun/nailgun/consts.py index 4417a37a5b..8d5852631b 100644 --- a/nailgun/nailgun/consts.py +++ b/nailgun/nailgun/consts.py @@ -26,6 +26,7 @@ def Enum(*values, **kwargs): RELEASE_STATES = Enum( 'available', 'unavailable', + 'manageonly' ) RELEASE_OS = Enum( diff --git a/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_8_0.py b/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_8_0.py index 2f2b294df7..97f0dbd20a 100644 --- a/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_8_0.py +++ b/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_8_0.py @@ -30,20 +30,50 @@ from sqlalchemy.dialects import postgresql as psql from nailgun.utils.migration import drop_enum +from nailgun.utils.migration import upgrade_enum + +release_states_old = ( + 'available', + 'unavailable', +) +release_states_new = ( + 'available', + 'unavailable', + 'manageonly', +) + def upgrade(): create_components_table() create_release_components_table() upgrade_nodegroups_name_cluster_constraint() + upgrade_release_state() def downgrade(): + downgrade_release_state() op.drop_constraint('_name_cluster_uc', 'nodegroups',) op.drop_table('release_components') op.drop_table('components') drop_enum('component_types') +def upgrade_release_state(): + connection = op.get_bind() + op.drop_column('releases', 'is_deployable') + + upgrade_enum( + 'releases', + 'state', + 'release_state', + release_states_old, + release_states_new, + ) + + connection.execute(sa.sql.text( + "UPDATE releases SET state='manageonly' WHERE state!='unavailable'")) + + def upgrade_nodegroups_name_cluster_constraint(): connection = op.get_bind() select_query = sa.sql.text( @@ -104,3 +134,27 @@ def create_release_components_table(): ['release_id'], ['releases.id'], ondelete='CASCADE'), sa.PrimaryKeyConstraint('id') ) + + +def downgrade_release_state(): + connection = op.get_bind() + + connection.execute(sa.sql.text( + "UPDATE releases SET state='available' WHERE state!='unavailable'")) + op.add_column( + 'releases', + sa.Column( + 'is_deployable', + sa.Boolean(), + nullable=False, + server_default='true', + ) + ) + + upgrade_enum( + 'releases', + 'state', + 'release_state', + release_states_new, + release_states_old, + ) diff --git a/nailgun/nailgun/db/sqlalchemy/models/release.py b/nailgun/nailgun/db/sqlalchemy/models/release.py index 91b734899f..c5288b7046 100644 --- a/nailgun/nailgun/db/sqlalchemy/models/release.py +++ b/nailgun/nailgun/db/sqlalchemy/models/release.py @@ -14,7 +14,6 @@ # License for the specific language governing permissions and limitations # under the License. -from sqlalchemy import Boolean from sqlalchemy import Column from sqlalchemy import Enum from sqlalchemy import Integer @@ -57,7 +56,6 @@ class Release(Base): roles_metadata = Column(JSON, default={}) network_roles_metadata = Column(JSON, default=[], server_default='[]') wizard_metadata = Column(JSON, default={}) - is_deployable = Column(Boolean, default=True, nullable=False) deployment_tasks = Column(JSON, default=[]) vmware_attributes_metadata = Column(JSON, default=[]) modes = Column(JSON, default=[]) diff --git a/nailgun/nailgun/extensions/cluster_upgrade/objects/adapters.py b/nailgun/nailgun/extensions/cluster_upgrade/objects/adapters.py index 3e107bdfb0..7bc67760fb 100644 --- a/nailgun/nailgun/extensions/cluster_upgrade/objects/adapters.py +++ b/nailgun/nailgun/extensions/cluster_upgrade/objects/adapters.py @@ -95,7 +95,7 @@ class NailgunReleaseAdapter(object): @property def is_deployable(self): - return self.release.is_deployable + return objects.Release.is_deployable(self.release) @property def environment_version(self): diff --git a/nailgun/nailgun/extensions/cluster_upgrade/tests/base.py b/nailgun/nailgun/extensions/cluster_upgrade/tests/base.py index df35c2a2dc..e5bbeeec64 100644 --- a/nailgun/nailgun/extensions/cluster_upgrade/tests/base.py +++ b/nailgun/nailgun/extensions/cluster_upgrade/tests/base.py @@ -29,7 +29,7 @@ class BaseCloneClusterTest(nailgun_test_base.BaseIntegrationTest): self.release_61 = self.env.create_release( operating_system=consts.RELEASE_OS.ubuntu, version="2014.2.2-6.1", - is_deployable=False, + state=consts.RELEASE_STATES.manageonly ) self.release_70 = self.env.create_release( operating_system=consts.RELEASE_OS.ubuntu, diff --git a/nailgun/nailgun/extensions/cluster_upgrade/tests/test_validators.py b/nailgun/nailgun/extensions/cluster_upgrade/tests/test_validators.py index 16ec066586..7f9984a094 100644 --- a/nailgun/nailgun/extensions/cluster_upgrade/tests/test_validators.py +++ b/nailgun/nailgun/extensions/cluster_upgrade/tests/test_validators.py @@ -20,6 +20,7 @@ from oslo_serialization import jsonutils from nailgun import consts from nailgun.errors import errors +from nailgun.settings import settings from nailgun.test import base from .. import validators @@ -35,11 +36,12 @@ class TestClusterUpgradeValidator(tests_base.BaseCloneClusterTest): self.validator.validate_release_upgrade(self.release_61, self.release_70) + @mock.patch.dict(settings.VERSION, {'feature_groups': ['mirantis']}) def test_validate_release_upgrade_deprecated_release(self): release_511 = self.env.create_release( operating_system=consts.RELEASE_OS.ubuntu, version="2014.1.3-5.1.1", - is_deployable=False, + state=consts.RELEASE_STATES.manageonly ) msg = "^Upgrade to the given release \({0}\).*is deprecated and " \ "cannot be installed\.$".format(self.release_61.id) @@ -48,7 +50,7 @@ class TestClusterUpgradeValidator(tests_base.BaseCloneClusterTest): self.release_61) def test_validate_release_upgrade_to_older_release(self): - self.release_61.is_deployable = True + self.release_61.state = consts.RELEASE_STATES.available msg = "^Upgrade to the given release \({0}\).*release is equal or " \ "lower than the release of the original cluster\.$" \ .format(self.release_61.id) diff --git a/nailgun/nailgun/extensions/cluster_upgrade/validators.py b/nailgun/nailgun/extensions/cluster_upgrade/validators.py index a86201c840..5a6a735dd8 100644 --- a/nailgun/nailgun/extensions/cluster_upgrade/validators.py +++ b/nailgun/nailgun/extensions/cluster_upgrade/validators.py @@ -49,7 +49,7 @@ class ClusterUpgradeValidator(base.BasicValidator): @classmethod def validate_release_upgrade(cls, orig_release, new_release): - if not new_release.is_deployable: + if not objects.Release.is_deployable(new_release): raise errors.InvalidData( "Upgrade to the given release ({0}) is not possible because " "this release is deprecated and cannot be installed." diff --git a/nailgun/nailgun/fixtures/openstack.yaml b/nailgun/nailgun/fixtures/openstack.yaml index c3f89f55d1..dd71e867c5 100644 --- a/nailgun/nailgun/fixtures/openstack.yaml +++ b/nailgun/nailgun/fixtures/openstack.yaml @@ -1524,7 +1524,6 @@ name: "Kilo on CentOS 6.5" state: "unavailable" version: "2015.1.0-8.0" - is_deployable: false can_update_from_versions: [] operating_system: "CentOS" description: "This option will install the OpenStack Kilo packages using a CentOS based operating system. With high availability features built in, you are getting a robust, enterprise-grade OpenStack deployment." diff --git a/nailgun/nailgun/objects/release.py b/nailgun/nailgun/objects/release.py index a6c0569906..ac3f265194 100644 --- a/nailgun/nailgun/objects/release.py +++ b/nailgun/nailgun/objects/release.py @@ -111,7 +111,8 @@ class Release(NailgunObject): # in experimental mode we deploy all releases if 'experimental' in settings.VERSION['feature_groups']: return True - return instance.is_deployable + + return instance.state == consts.RELEASE_STATES.available @classmethod def is_granular_enabled(cls, instance): diff --git a/nailgun/nailgun/test/unit/test_migration_fuel_8_0.py b/nailgun/nailgun/test/unit/test_migration_fuel_8_0.py index 78a9323c15..63794646fb 100644 --- a/nailgun/nailgun/test/unit/test_migration_fuel_8_0.py +++ b/nailgun/nailgun/test/unit/test_migration_fuel_8_0.py @@ -258,6 +258,20 @@ class TestNodeGroupsMigration(base.BaseAlembicMigrationTest): nodegroup = db.execute( sa.select([self.meta.tables['nodegroups'].c.cluster_id, self.meta.tables['nodegroups'].c.name])).fetchone() - insert_table_row(self.meta.tables['nodegroups'], - {'cluster_id': nodegroup['cluster_id'], - 'name': uuid.uuid4()}) + db.execute(self.meta.tables['nodegroups'].insert(), + [{'cluster_id': nodegroup['cluster_id'], + 'name': uuid.uuid4()}]) + + +class TestReleaseMigrations(base.BaseAlembicMigrationTest): + + def test_release_is_deployable_deleted(self): + self.assertNotIn('is_deployable', + [c.name for c in self.meta.tables['releases'].c]) + + def test_releases_are_manageonly(self): + states = [r[0] for r in db.execute( + sa.select([self.meta.tables['releases'].c.state])).fetchall()] + + for state in states: + self.assertEqual(state, 'manageonly') diff --git a/nailgun/nailgun/test/unit/test_release_handler.py b/nailgun/nailgun/test/unit/test_release_handler.py index c8feadacdd..c8c6b4a74d 100644 --- a/nailgun/nailgun/test/unit/test_release_handler.py +++ b/nailgun/nailgun/test/unit/test_release_handler.py @@ -71,11 +71,15 @@ class TestHandlers(BaseIntegrationTest): def test_release_put_deployable(self): release = self.env.create_release(api=False) - for deployable in (False, True): + for state, deployable in ( + ('available', True), + ('unavailable', False), + ('manageonly', False) + ): resp = self.app.put( reverse('ReleaseHandler', kwargs={'obj_id': release.id}), params=jsonutils.dumps({ - 'is_deployable': deployable, + 'state': state, }), headers=self.default_headers) self.assertEqual(200, resp.status_code) @@ -88,7 +92,7 @@ class TestHandlers(BaseIntegrationTest): resp = self.app.put( reverse('ReleaseHandler', kwargs={'obj_id': release.id}), params=jsonutils.dumps({ - 'is_deployable': False, + 'state': consts.RELEASE_STATES.manageonly, }), headers=self.default_headers) self.assertEqual(200, resp.status_code) @@ -108,7 +112,6 @@ class TestHandlers(BaseIntegrationTest): resp = self.app.put( reverse('ReleaseHandler', kwargs={'obj_id': release.id}), params=jsonutils.dumps({ - 'is_deployable': False, 'state': consts.RELEASE_STATES.unavailable }), headers=self.default_headers) diff --git a/nailgun/static/translations/core.json b/nailgun/static/translations/core.json index c6d10acc43..0b2a05c653 100644 --- a/nailgun/static/translations/core.json +++ b/nailgun/static/translations/core.json @@ -258,12 +258,14 @@ "title": "Releases", "name": "OpenStack Release", "version": "Version", - "is_deployable": "Available for New Deployments", + "state": "Available for New Deployments", "no_releases_message": "There are no releases available.", "release": { "available": "Available", "error": "Error", - "not_available": "Not available" + "not_available": "Not available", + "unavailable": "Not available", + "manageonly": "Manage only" } }, "plugins_page": { diff --git a/nailgun/static/views/releases_page.jsx b/nailgun/static/views/releases_page.jsx index ed03b344e5..8740ae9194 100644 --- a/nailgun/static/views/releases_page.jsx +++ b/nailgun/static/views/releases_page.jsx @@ -28,7 +28,7 @@ function(_, i18n, React, models, controls, componentMixins) { var ReleasesPage = React.createClass({ mixins: [componentMixins.backboneMixin('releases')], getDefaultProps: function() { - return {columns: ['name', 'version', 'is_deployable']}; + return {columns: ['name', 'version', 'state']}; }, statics: { title: i18n('release_page.title'), @@ -43,8 +43,8 @@ function(_, i18n, React, models, controls, componentMixins) { }, getReleaseData: function(release) { return _.map(this.props.columns, function(attr) { - if (attr == 'is_deployable') { - return i18n('release_page.release.' + (release.get(attr) ? 'available' : 'not_available')); + if (attr == 'state') { + return i18n('release_page.release.' + (release.get(attr))); } return release.get(attr) || i18n('common.not_available'); }); diff --git a/nailgun/static/views/wizard.js b/nailgun/static/views/wizard.js index 5a325ef570..f9f6a5c92c 100644 --- a/nailgun/static/views/wizard.js +++ b/nailgun/static/views/wizard.js @@ -633,7 +633,7 @@ function(require, $, _, i18n, Backbone, utils, models, createClusterWizardTempla this.addPasswordToggle(); if (!_.isUndefined(this.releases) && this.releases.length) { - this.releases = new Backbone.Collection(this.releases.where({is_deployable: true})); + this.releases = new Backbone.Collection(this.releases.where({state: 'available'})); } this.composePaneBindings(); return this;