Browse Source
New `openstack overcloud external-update run` and `openstack overcloud external-upgrade run` commands are defined. These are meant to perform updates and upgrades for services deployed via external_deploy_tasks. A separate command is used because external installers don't fit well within the --nodes and --roles selection pattern we've established for the normal `update run` and `upgrade run` commands. Partial-Bug: #1783949 Depends-On: Ib2474e8f69711cd6610a78884d5032ffd19ad249 Depends-On: I982032a0eadfbfb7f1eadee9cae26c8cd5fcdbba Change-Id: Ib2f32ae8ac234b0c25b0e1ff1f8f8d8e041185e0changes/84/582284/3
16 changed files with 465 additions and 3 deletions
@ -0,0 +1,10 @@
|
||||
--- |
||||
upgrade: |
||||
- | |
||||
New `openstack overcloud external-update run` and `openstack |
||||
overcloud external-upgrade run` commands are defined. These are |
||||
meant to perform updates and upgrades for services deployed via |
||||
external_deploy_tasks. A separate command is used because external |
||||
installers don't fit well within the --nodes and --roles selection |
||||
pattern we've established for the normal `update run` and `upgrade |
||||
run` commands. |
@ -0,0 +1,49 @@
|
||||
# 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. |
||||
# |
||||
|
||||
import mock |
||||
from osc_lib.tests import utils |
||||
|
||||
from tripleoclient.tests import fakes |
||||
|
||||
|
||||
class FakeClientWrapper(object): |
||||
|
||||
def __init__(self): |
||||
self._instance = mock.Mock() |
||||
self.object_store = FakeObjectClient() |
||||
|
||||
def messaging_websocket(self): |
||||
return fakes.FakeWebSocket() |
||||
|
||||
|
||||
class FakeObjectClient(object): |
||||
|
||||
def __init__(self): |
||||
self._instance = mock.Mock() |
||||
self.put_object = mock.Mock() |
||||
|
||||
def get_object(self, *args): |
||||
return |
||||
|
||||
|
||||
class TestOvercloudExternalUpdateRun(utils.TestCommand): |
||||
|
||||
def setUp(self): |
||||
super(TestOvercloudExternalUpdateRun, self).setUp() |
||||
|
||||
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN") |
||||
self.app.client_manager.tripleoclient = FakeClientWrapper() |
||||
self.app.client_manager.workflow_engine = mock.Mock() |
@ -0,0 +1,66 @@
|
||||
# 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. |
||||
# |
||||
|
||||
import mock |
||||
|
||||
from tripleoclient import constants |
||||
from tripleoclient.tests.v1.overcloud_external_update import fakes |
||||
from tripleoclient.v1 import overcloud_external_update |
||||
|
||||
|
||||
class TestOvercloudExternalUpdateRun(fakes.TestOvercloudExternalUpdateRun): |
||||
|
||||
def setUp(self): |
||||
super(TestOvercloudExternalUpdateRun, self).setUp() |
||||
|
||||
# Get the command object to test |
||||
app_args = mock.Mock() |
||||
app_args.verbose_level = 1 |
||||
self.cmd = overcloud_external_update.ExternalUpdateRun( |
||||
self.app, app_args) |
||||
|
||||
uuid4_patcher = mock.patch('uuid.uuid4', return_value="UUID4") |
||||
self.mock_uuid4 = uuid4_patcher.start() |
||||
self.addCleanup(self.mock_uuid4.stop) |
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible', |
||||
autospec=True) |
||||
@mock.patch('os.path.expanduser') |
||||
@mock.patch('oslo_concurrency.processutils.execute') |
||||
@mock.patch('six.moves.builtins.open') |
||||
def test_update_with_user_and_tags(self, mock_open, mock_execute, |
||||
mock_expanduser, update_ansible): |
||||
mock_expanduser.return_value = '/home/fake/' |
||||
argslist = ['--ssh-user', 'tripleo-admin', |
||||
'--tags', 'ceph'] |
||||
verifylist = [ |
||||
('ssh_user', 'tripleo-admin'), |
||||
('tags', 'ceph'), |
||||
] |
||||
|
||||
parsed_args = self.check_parser(self.cmd, argslist, verifylist) |
||||
with mock.patch('os.path.exists') as mock_exists: |
||||
mock_exists.return_value = True |
||||
self.cmd.take_action(parsed_args) |
||||
update_ansible.assert_called_once_with( |
||||
self.app.client_manager, |
||||
nodes='all', |
||||
inventory_file=mock_open().read(), |
||||
playbook='external_update_steps_playbook.yaml', |
||||
ansible_queue_name=constants.EXTERNAL_UPDATE_QUEUE, |
||||
node_user='tripleo-admin', |
||||
tags='ceph', |
||||
skip_tags='', |
||||
) |
@ -0,0 +1,49 @@
|
||||
# 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. |
||||
# |
||||
|
||||
import mock |
||||
from osc_lib.tests import utils |
||||
|
||||
from tripleoclient.tests import fakes |
||||
|
||||
|
||||
class FakeClientWrapper(object): |
||||
|
||||
def __init__(self): |
||||
self._instance = mock.Mock() |
||||
self.object_store = FakeObjectClient() |
||||
|
||||
def messaging_websocket(self): |
||||
return fakes.FakeWebSocket() |
||||
|
||||
|
||||
class FakeObjectClient(object): |
||||
|
||||
def __init__(self): |
||||
self._instance = mock.Mock() |
||||
self.put_object = mock.Mock() |
||||
|
||||
def get_object(self, *args): |
||||
return |
||||
|
||||
|
||||
class TestOvercloudExternalUpgradeRun(utils.TestCommand): |
||||
|
||||
def setUp(self): |
||||
super(TestOvercloudExternalUpgradeRun, self).setUp() |
||||
|
||||
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN") |
||||
self.app.client_manager.tripleoclient = FakeClientWrapper() |
||||
self.app.client_manager.workflow_engine = mock.Mock() |
@ -0,0 +1,66 @@
|
||||
# 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. |
||||
# |
||||
|
||||
import mock |
||||
|
||||
from tripleoclient import constants |
||||
from tripleoclient.tests.v1.overcloud_external_upgrade import fakes |
||||
from tripleoclient.v1 import overcloud_external_upgrade |
||||
|
||||
|
||||
class TestOvercloudExternalUpgradeRun(fakes.TestOvercloudExternalUpgradeRun): |
||||
|
||||
def setUp(self): |
||||
super(TestOvercloudExternalUpgradeRun, self).setUp() |
||||
|
||||
# Get the command object to test |
||||
app_args = mock.Mock() |
||||
app_args.verbose_level = 1 |
||||
self.cmd = overcloud_external_upgrade.ExternalUpgradeRun( |
||||
self.app, app_args) |
||||
|
||||
uuid4_patcher = mock.patch('uuid.uuid4', return_value="UUID4") |
||||
self.mock_uuid4 = uuid4_patcher.start() |
||||
self.addCleanup(self.mock_uuid4.stop) |
||||
|
||||
@mock.patch('tripleoclient.workflows.package_update.update_ansible', |
||||
autospec=True) |
||||
@mock.patch('os.path.expanduser') |
||||
@mock.patch('oslo_concurrency.processutils.execute') |
||||
@mock.patch('six.moves.builtins.open') |
||||
def test_upgrade_with_user_and_tags(self, mock_open, mock_execute, |
||||
mock_expanduser, update_ansible): |
||||
mock_expanduser.return_value = '/home/fake/' |
||||
argslist = ['--ssh-user', 'tripleo-admin', |
||||
'--tags', 'ceph'] |
||||
verifylist = [ |
||||
('ssh_user', 'tripleo-admin'), |
||||
('tags', 'ceph'), |
||||
] |
||||
|
||||
parsed_args = self.check_parser(self.cmd, argslist, verifylist) |
||||
with mock.patch('os.path.exists') as mock_exists: |
||||
mock_exists.return_value = True |
||||
self.cmd.take_action(parsed_args) |
||||
update_ansible.assert_called_once_with( |
||||
self.app.client_manager, |
||||
nodes='all', |
||||
inventory_file=mock_open().read(), |
||||
playbook='external_upgrade_steps_playbook.yaml', |
||||
ansible_queue_name=constants.EXTERNAL_UPGRADE_QUEUE, |
||||
node_user='tripleo-admin', |
||||
tags='ceph', |
||||
skip_tags='', |
||||
) |
@ -0,0 +1,102 @@
|
||||
# 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_log import log as logging |
||||
|
||||
from osc_lib.i18n import _ |
||||
from osc_lib import utils |
||||
|
||||
from tripleoclient import command |
||||
from tripleoclient import constants |
||||
from tripleoclient import utils as oooutils |
||||
from tripleoclient.workflows import package_update |
||||
|
||||
CONF = cfg.CONF |
||||
logging.register_options(CONF) |
||||
logging.setup(CONF, '') |
||||
|
||||
|
||||
class ExternalUpdateRun(command.Command): |
||||
"""Run external minor update Ansible playbook |
||||
|
||||
This will run the external minor update Ansible playbook, |
||||
executing tasks from the undercloud. The update playbooks are |
||||
made available after completion of the 'overcloud update |
||||
prepare' command. |
||||
|
||||
""" |
||||
|
||||
log = logging.getLogger(__name__ + ".ExternalUpdateRun") |
||||
|
||||
def get_parser(self, prog_name): |
||||
parser = super(ExternalUpdateRun, self).get_parser(prog_name) |
||||
parser.add_argument('--static-inventory', |
||||
dest='static_inventory', |
||||
action="store", |
||||
default=None, |
||||
help=_('Path to an existing ansible inventory to ' |
||||
'use. If not specified, one will be ' |
||||
'generated in ' |
||||
'~/tripleo-ansible-inventory.yaml') |
||||
) |
||||
parser.add_argument("--ssh-user", |
||||
dest="ssh_user", |
||||
action="store", |
||||
default="heat-admin", |
||||
help=_("The ssh user name for connecting to " |
||||
"the overcloud nodes.") |
||||
) |
||||
parser.add_argument('--tags', |
||||
dest='tags', |
||||
action="store", |
||||
default="", |
||||
help=_('A string specifying the tag or comma ' |
||||
'separated list of tags to be passed ' |
||||
'as --tags to ansible-playbook. ') |
||||
) |
||||
parser.add_argument('--skip-tags', |
||||
dest='skip_tags', |
||||
action="store", |
||||
default="", |
||||
help=_('A string specifying the tag or comma ' |
||||
'separated list of tags to be passed ' |
||||
'as --skip-tags to ansible-playbook. ') |
||||
) |
||||
parser.add_argument('--stack', dest='stack', |
||||
help=_('Name or ID of heat stack ' |
||||
'(default=Env: OVERCLOUD_STACK_NAME)'), |
||||
default=utils.env('OVERCLOUD_STACK_NAME', |
||||
default='overcloud')) |
||||
|
||||
return parser |
||||
|
||||
def take_action(self, parsed_args): |
||||
self.log.debug("take_action(%s)" % parsed_args) |
||||
clients = self.app.client_manager |
||||
stack = parsed_args.stack |
||||
|
||||
# Run ansible: |
||||
inventory = oooutils.get_tripleo_ansible_inventory( |
||||
parsed_args.static_inventory, parsed_args.ssh_user, stack) |
||||
limit_hosts = 'all' |
||||
playbook = 'all' |
||||
oooutils.run_update_ansible_action( |
||||
self.log, clients, limit_hosts, inventory, playbook, |
||||
constants.EXTERNAL_UPDATE_QUEUE, |
||||
constants.EXTERNAL_UPDATE_PLAYBOOKS, |
||||
package_update, parsed_args.ssh_user, |
||||
tags=parsed_args.tags, skip_tags=parsed_args.skip_tags) |
||||
|
||||
self.log.info("Completed Overcloud External Update Run.") |
@ -0,0 +1,102 @@
|
||||
# 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_log import log as logging |
||||
|
||||
from osc_lib.i18n import _ |
||||
from osc_lib import utils |
||||
|
||||
from tripleoclient import command |
||||
from tripleoclient import constants |
||||
from tripleoclient import utils as oooutils |
||||
from tripleoclient.workflows import package_update |
||||
|
||||
CONF = cfg.CONF |
||||
logging.register_options(CONF) |
||||
logging.setup(CONF, '') |
||||
|
||||
|
||||
class ExternalUpgradeRun(command.Command): |
||||
"""Run external major upgrade Ansible playbook |
||||
|
||||
This will run the external major upgrade Ansible playbook, |
||||
executing tasks from the undercloud. The upgrade playbooks are |
||||
made available after completion of the 'overcloud upgrade |
||||
prepare' command. |
||||
|
||||
""" |
||||
|
||||
log = logging.getLogger(__name__ + ".ExternalUpgradeRun") |
||||
|
||||
def get_parser(self, prog_name): |
||||
parser = super(ExternalUpgradeRun, self).get_parser(prog_name) |
||||
parser.add_argument('--static-inventory', |
||||
dest='static_inventory', |
||||
action="store", |
||||
default=None, |
||||
help=_('Path to an existing ansible inventory to ' |
||||
'use. If not specified, one will be ' |
||||
'generated in ' |
||||
'~/tripleo-ansible-inventory.yaml') |
||||
) |
||||
parser.add_argument("--ssh-user", |
||||
dest="ssh_user", |
||||
action="store", |
||||
default="heat-admin", |
||||
help=_("The ssh user name for connecting to " |
||||
"the overcloud nodes.") |
||||
) |
||||
parser.add_argument('--tags', |
||||
dest='tags', |
||||
action="store", |
||||
default="", |
||||
help=_('A string specifying the tag or comma ' |
||||
'separated list of tags to be passed ' |
||||
'as --tags to ansible-playbook. ') |
||||
) |
||||
parser.add_argument('--skip-tags', |
||||
dest='skip_tags', |
||||
action="store", |
||||
default="", |
||||
help=_('A string specifying the tag or comma ' |
||||
'separated list of tags to be passed ' |
||||
'as --skip-tags to ansible-playbook. ') |
||||
) |
||||
parser.add_argument('--stack', dest='stack', |
||||
help=_('Name or ID of heat stack ' |
||||
'(default=Env: OVERCLOUD_STACK_NAME)'), |
||||
default=utils.env('OVERCLOUD_STACK_NAME', |
||||
default='overcloud')) |
||||
|
||||
return parser |
||||
|
||||
def take_action(self, parsed_args): |
||||
self.log.debug("take_action(%s)" % parsed_args) |
||||
clients = self.app.client_manager |
||||
stack = parsed_args.stack |
||||
|
||||
# Run ansible: |
||||
inventory = oooutils.get_tripleo_ansible_inventory( |
||||
parsed_args.static_inventory, parsed_args.ssh_user, stack) |
||||
limit_hosts = 'all' |
||||
playbook = 'all' |
||||
oooutils.run_update_ansible_action( |
||||
self.log, clients, limit_hosts, inventory, playbook, |
||||
constants.EXTERNAL_UPGRADE_QUEUE, |
||||
constants.EXTERNAL_UPGRADE_PLAYBOOKS, |
||||
package_update, parsed_args.ssh_user, |
||||
tags=parsed_args.tags, skip_tags=parsed_args.skip_tags) |
||||
|
||||
self.log.info("Completed Overcloud External Upgrade Run.") |
Loading…
Reference in new issue