Add designate-status command for upgrade checks
This checks for duplicate entries in the service_statuses table which will be an error after change I307a8f7dd8b8a83effa447a846db3288efa32dba. Related-Bug: 1768824 Story: 2003657 Task: 26127 Change-Id: Ie0350b034f0eb03749138aadd0951d30073214c0 Co-authored-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
parent
7c0ebd310c
commit
1842802de4
57
designate/cmd/status.py
Normal file
57
designate/cmd/status.py
Normal file
@ -0,0 +1,57 @@
|
||||
# Copyright 2018 Red Hat 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 oslo_config import cfg
|
||||
from oslo_upgradecheck import upgradecheck
|
||||
from sqlalchemy import MetaData, Table, select, func
|
||||
|
||||
from designate.i18n import _
|
||||
from designate.sqlalchemy import session
|
||||
# This import is not used, but is needed to register the storage:sqlalchemy
|
||||
# group.
|
||||
import designate.storage.impl_sqlalchemy # noqa
|
||||
from designate import utils
|
||||
|
||||
|
||||
class Checks(upgradecheck.UpgradeCommands):
|
||||
def _duplicate_service_status(self):
|
||||
engine = session.get_engine('storage:sqlalchemy')
|
||||
metadata = MetaData(bind=engine)
|
||||
status = Table('service_statuses', metadata, autoload=True)
|
||||
service_select = (select([func.count()])
|
||||
.select_from(status)
|
||||
.group_by('service_name', 'hostname')
|
||||
)
|
||||
service_counts = engine.execute(service_select).fetchall()
|
||||
duplicated_services = [i for i in service_counts if i[0] > 1]
|
||||
if duplicated_services:
|
||||
return upgradecheck.Result(upgradecheck.Code.FAILURE,
|
||||
_('Duplicated services found in '
|
||||
'service_statuses table.'))
|
||||
return upgradecheck.Result(upgradecheck.Code.SUCCESS)
|
||||
|
||||
_upgrade_checks = ((_('Duplicate service status'),
|
||||
_duplicate_service_status),
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
config_files = utils.find_config('designate.conf')
|
||||
checker = Checks()
|
||||
return upgradecheck.main(
|
||||
conf=cfg.CONF,
|
||||
project='designate',
|
||||
upgrade_command=checker,
|
||||
default_config_files=config_files,
|
||||
)
|
74
designate/tests/unit/test_upgrade_checks.py
Normal file
74
designate/tests/unit/test_upgrade_checks.py
Normal file
@ -0,0 +1,74 @@
|
||||
# Copyright 2018 Red Hat 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 migrate.changeset.constraint import UniqueConstraint
|
||||
from oslo_upgradecheck import upgradecheck
|
||||
from sqlalchemy.schema import MetaData
|
||||
from sqlalchemy.schema import Table
|
||||
|
||||
from designate.cmd import status
|
||||
from designate import tests
|
||||
from designate.sqlalchemy import session
|
||||
|
||||
|
||||
class TestDuplicateServiceStatus(tests.TestCase):
|
||||
def setUp(self):
|
||||
super(TestDuplicateServiceStatus, self).setUp()
|
||||
self.engine = session.get_engine('storage:sqlalchemy')
|
||||
self.meta = MetaData()
|
||||
self.meta.bind = self.engine
|
||||
self.service_statuses_table = Table('service_statuses', self.meta,
|
||||
autoload=True)
|
||||
|
||||
def test_success(self):
|
||||
fake_record = {'id': '1',
|
||||
'service_name': 'worker',
|
||||
'hostname': 'localhost',
|
||||
'status': 'UP',
|
||||
'stats': '',
|
||||
'capabilities': '',
|
||||
}
|
||||
self.service_statuses_table.insert().execute(fake_record)
|
||||
# Different hostname should be fine
|
||||
fake_record['id'] = '2'
|
||||
fake_record['hostname'] = 'otherhost'
|
||||
self.service_statuses_table.insert().execute(fake_record)
|
||||
# Different service_name should be fine
|
||||
fake_record['id'] = '3'
|
||||
fake_record['service_name'] = 'producer'
|
||||
self.service_statuses_table.insert().execute(fake_record)
|
||||
checks = status.Checks()
|
||||
self.assertEqual(upgradecheck.Code.SUCCESS,
|
||||
checks._duplicate_service_status().code)
|
||||
|
||||
def test_failure(self):
|
||||
# Drop unique constraint so we can test error cases
|
||||
constraint = UniqueConstraint('service_name', 'hostname',
|
||||
table=self.service_statuses_table,
|
||||
name="unique_service_status")
|
||||
constraint.drop()
|
||||
fake_record = {'id': '1',
|
||||
'service_name': 'worker',
|
||||
'hostname': 'localhost',
|
||||
'status': 'UP',
|
||||
'stats': '',
|
||||
'capabilities': '',
|
||||
}
|
||||
self.service_statuses_table.insert().execute(fake_record)
|
||||
fake_record['id'] = '2'
|
||||
self.service_statuses_table.insert().execute(fake_record)
|
||||
|
||||
checks = status.Checks()
|
||||
self.assertEqual(upgradecheck.Code.FAILURE,
|
||||
checks._duplicate_service_status().code)
|
@ -4,6 +4,10 @@ Upgrades
|
||||
|
||||
In this section, you will find documentation relevant for upgrading Designate.
|
||||
|
||||
.. note:: The :ref:`designate-status upgrade check <designate-status-upgrade-check>`
|
||||
command can be used to verify a deployment before starting services
|
||||
with new code.
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
|
86
doc/source/cli/designate-status.rst
Normal file
86
doc/source/cli/designate-status.rst
Normal file
@ -0,0 +1,86 @@
|
||||
====================
|
||||
Designate Status CLI
|
||||
====================
|
||||
|
||||
This chapter documents :command:`designate-status`.
|
||||
|
||||
For help on a specific :command:`designate-status` command, enter:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ designate-status COMMAND --help
|
||||
|
||||
designate-status
|
||||
================
|
||||
|
||||
:program:`designate-status` is a tool that provides routines for checking the
|
||||
status of a Designate deployment.
|
||||
|
||||
The standard pattern for executing a :program:`designate-status` command is:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
designate-status <category> <command> [<args>]
|
||||
|
||||
Run without arguments to see a list of available command categories:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
designate-status
|
||||
|
||||
Categories are:
|
||||
|
||||
* ``upgrade``
|
||||
|
||||
Detailed descriptions are below.
|
||||
|
||||
You can also run with a category argument such as ``upgrade`` to see a list of
|
||||
all commands in that category:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
designate-status upgrade
|
||||
|
||||
The following sections describe the available categories and arguments for
|
||||
:program:`designate-status`.
|
||||
|
||||
designate-status upgrade
|
||||
========================
|
||||
|
||||
.. _designate-status-upgrade-check:
|
||||
|
||||
designate-status upgrade check
|
||||
------------------------------
|
||||
|
||||
``designate-status upgrade check``
|
||||
Performs a release-specific readiness check before running db sync for the
|
||||
new version. This command expects to have complete configuration and access
|
||||
to the database.
|
||||
|
||||
**Return Codes**
|
||||
|
||||
.. list-table::
|
||||
:widths: 20 80
|
||||
:header-rows: 1
|
||||
|
||||
* - Return code
|
||||
- Description
|
||||
* - 0
|
||||
- All upgrade readiness checks passed successfully and there is nothing
|
||||
to do.
|
||||
* - 1
|
||||
- At least one check encountered an issue and requires further
|
||||
investigation. This is considered a warning but the upgrade may be OK.
|
||||
* - 2
|
||||
- There was an upgrade status check failure that needs to be
|
||||
investigated. This should be considered something that stops an
|
||||
upgrade.
|
||||
* - 255
|
||||
- An unexpected error occurred.
|
||||
|
||||
**History of Checks**
|
||||
|
||||
**8.0.0 (Stein)**
|
||||
|
||||
* Checks that duplicate entries do not exist in the ``service_statuses``
|
||||
table.
|
@ -8,3 +8,4 @@ Interface (CLI) can be found in this section.
|
||||
:maxdepth: 1
|
||||
|
||||
designate-manage
|
||||
designate-status
|
||||
|
@ -89,6 +89,7 @@ oslo.reports==1.18.0
|
||||
oslo.rootwrap==5.8.0
|
||||
oslo.serialization==2.18.0
|
||||
oslo.service==1.24.0
|
||||
oslo.upgradecheck==0.1.0
|
||||
oslo.utils==3.33.0
|
||||
oslo.versionedobjects==1.31.2
|
||||
oslotest==3.2.0
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
A new ``designate-status upgrade check`` command has been added which can
|
||||
be used to validate a deployment before starting services with new code.
|
||||
See the documentation for details:
|
||||
https://docs.openstack.org/designate/latest/cli/designate-status.html
|
@ -20,6 +20,7 @@ oslo.reports>=1.18.0 # Apache-2.0
|
||||
oslo.rootwrap>=5.8.0 # Apache-2.0
|
||||
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
|
||||
oslo.service!=1.28.1,>=1.24.0 # Apache-2.0
|
||||
oslo.upgradecheck>=0.1.0
|
||||
oslo.utils>=3.33.0 # Apache-2.0
|
||||
oslo.versionedobjects>=1.31.2 # Apache-2.0
|
||||
Paste>=2.0.2 # MIT
|
||||
|
Loading…
Reference in New Issue
Block a user