Workflow to setup validations
The new tripleo.validations.v1.copy_ssh_keys workflow copies the provided public key to the overcloud nodes in preparation for running ansible validations. When no public key exists, a new one will be generated and stored in a dedicated mistral environment. Change-Id: I93972b34186ac3aaf54fa6aebd14bf48b5247266
This commit is contained in:
parent
4e789a4838
commit
c31ed3db3b
17
README.rst
17
README.rst
|
@ -28,3 +28,20 @@ code to accomplish these tasks. ::
|
|||
# make sure the new actions got loaded
|
||||
mistral action-list | grep tripleo
|
||||
|
||||
Validations
|
||||
-----------
|
||||
|
||||
Prerequisites
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
If you haven't installed the undercloud with the ``enable_validations`` set to
|
||||
true, you will have to prepare your undercloud to run the validations::
|
||||
|
||||
$ sudo pip install git+https://git.openstack.org/openstack/tripleo-validations
|
||||
$ sudo yum install ansible
|
||||
$ sudo useradd validations
|
||||
|
||||
Finally you need to generate an SSH keypair for the validation user and copy
|
||||
it to the overcloud's authorized_keys files::
|
||||
|
||||
$ mistral execution-create tripleo.validations.v1.copy_ssh_key
|
||||
|
|
|
@ -31,6 +31,7 @@ scripts =
|
|||
data_files =
|
||||
lib/heat/undercloud_heat_plugins = undercloud_heat_plugins/*
|
||||
share/tripleo-common/image-yaml = image-yaml/*
|
||||
share/tripleo-common/workbooks = workbooks/*
|
||||
|
||||
[build_sphinx]
|
||||
source-dir = doc/source
|
||||
|
@ -69,3 +70,4 @@ mistral.actions =
|
|||
tripleo.get_parameters = tripleo_common.actions.parameters:GetParametersAction
|
||||
tripleo.update_parameters = tripleo_common.actions.parameters:UpdateParametersAction
|
||||
tripleo.deploy = tripleo_common.actions.deployment:DeployStackAction
|
||||
tripleo.validations.get_pubkey = tripleo_common.actions.validations:GetPubkeyAction
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
# Copyright 2016 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
from tripleo_common.actions import base
|
||||
from tripleo_common.utils import validations as utils
|
||||
|
||||
|
||||
class GetPubkeyAction(base.TripleOAction):
|
||||
def __init__(self):
|
||||
super(GetPubkeyAction, self).__init__()
|
||||
|
||||
def run(self):
|
||||
mc = self._get_workflow_client()
|
||||
try:
|
||||
env = mc.environments.get('ssh_keys')
|
||||
public_key = env.variables['public_key']
|
||||
except Exception:
|
||||
tmp_dir = tempfile.mkdtemp()
|
||||
private_key_path = os.path.join(tmp_dir, 'id_rsa')
|
||||
public_key_path = private_key_path + '.pub'
|
||||
utils.create_ssh_keypair(private_key_path)
|
||||
|
||||
with open(private_key_path, 'r') as f:
|
||||
private_key = f.read().strip()
|
||||
with open(public_key_path, 'r') as f:
|
||||
public_key = f.read().strip()
|
||||
|
||||
shutil.rmtree(tmp_dir)
|
||||
|
||||
workflow_env = {
|
||||
'name': 'ssh_keys',
|
||||
'description': 'SSH keys for TripleO validations',
|
||||
'variables': {
|
||||
'public_key': public_key,
|
||||
'private_key': private_key,
|
||||
}
|
||||
}
|
||||
mc.environments.create(**workflow_env)
|
||||
|
||||
return public_key
|
|
@ -0,0 +1,57 @@
|
|||
# Copyright 2016 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 collections
|
||||
import mock
|
||||
|
||||
from tripleo_common.actions import validations
|
||||
from tripleo_common.tests import base
|
||||
|
||||
|
||||
class GetPubkeyActionTest(base.TestCase):
|
||||
|
||||
@mock.patch(
|
||||
'tripleo_common.actions.base.TripleOAction._get_workflow_client')
|
||||
def test_run_existing_pubkey(self, get_workflow_client_mock):
|
||||
mistral = mock.MagicMock()
|
||||
get_workflow_client_mock.return_value = mistral
|
||||
environment = collections.namedtuple('environment', ['variables'])
|
||||
mistral.environments.get.return_value = environment(variables={
|
||||
'public_key': 'existing_pubkey'
|
||||
})
|
||||
action = validations.GetPubkeyAction()
|
||||
self.assertEqual('existing_pubkey', action.run())
|
||||
|
||||
@mock.patch(
|
||||
'tripleo_common.actions.base.TripleOAction._get_workflow_client')
|
||||
@mock.patch('tripleo_common.utils.validations.create_ssh_keypair')
|
||||
@mock.patch('tempfile.mkdtemp')
|
||||
@mock.patch('shutil.rmtree')
|
||||
def test_run_no_pubkey(self, mock_rmtree, mock_mkdtemp,
|
||||
mock_create_keypair, get_workflow_client_mock):
|
||||
mistral = mock.MagicMock()
|
||||
get_workflow_client_mock.return_value = mistral
|
||||
mistral.environments.get.side_effect = 'nope, sorry'
|
||||
mock_mkdtemp.return_value = '/tmp_path'
|
||||
|
||||
mock_open_context = mock.mock_open()
|
||||
mock_open_context().read.side_effect = ['private_key', 'public_key']
|
||||
|
||||
with mock.patch('six.moves.builtins.open', mock_open_context):
|
||||
action = validations.GetPubkeyAction()
|
||||
self.assertEqual('public_key', action.run())
|
||||
|
||||
mock_mkdtemp.assert_called_once()
|
||||
mock_create_keypair.assert_called_once_with('/tmp_path/id_rsa')
|
||||
mock_rmtree.asser_called_once_with('/tmp_path')
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright 2016 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 tripleo_common.tests import base
|
||||
from tripleo_common.utils import validations
|
||||
|
||||
|
||||
class ValidationsTest(base.TestCase):
|
||||
|
||||
@mock.patch("oslo_concurrency.processutils.execute")
|
||||
def test_create_ssh_keypair(self, mock_execute):
|
||||
validations.create_ssh_keypair('/path/to/key')
|
||||
mock_execute.assert_called_once_with(
|
||||
'/usr/bin/ssh-keygen', '-t', 'rsa', '-N', '',
|
||||
'-f', '/path/to/key', '-C', 'tripleo-validations')
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright 2016 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 logging
|
||||
|
||||
from oslo_concurrency import processutils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_ssh_keypair(key_path):
|
||||
"""Create SSH keypair"""
|
||||
LOG.debug('Creating SSH keypair at %s', key_path)
|
||||
processutils.execute('/usr/bin/ssh-keygen', '-t', 'rsa', '-N', '',
|
||||
'-f', key_path, '-C', 'tripleo-validations')
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
version: '2.0'
|
||||
name: tripleo.validations.v1
|
||||
description: TripleO Validations Workflows v1
|
||||
|
||||
workflows:
|
||||
|
||||
copy_ssh_key:
|
||||
type: direct
|
||||
input:
|
||||
- overcloud_admin: heat-admin
|
||||
- queue_name: tripleo
|
||||
tasks:
|
||||
get_servers:
|
||||
action: nova.servers_list
|
||||
on-success: get_pubkey
|
||||
publish:
|
||||
servers: <% task(get_servers).result._info %>
|
||||
|
||||
get_pubkey:
|
||||
action: tripleo.validations.get_pubkey
|
||||
on-success: deploy_ssh_key
|
||||
publish:
|
||||
pubkey: <% task(get_pubkey).result %>
|
||||
|
||||
deploy_ssh_key:
|
||||
workflow: tripleo.deployment.v1.deploy_on_server
|
||||
with-items: server in <% $.servers %>
|
||||
input:
|
||||
server_name: <% $.server.name %>
|
||||
server_uuid: <% $.server.id %>
|
||||
config: |
|
||||
#!/bin/bash
|
||||
if ! grep "<% $.pubkey %>" /home/<% $.overcloud_admin %>/.ssh/authorized_keys; then
|
||||
echo "<% $.pubkey %>" >> /home/<% $.overcloud_admin %>/.ssh/authorized_keys
|
||||
fi
|
||||
config_name: copy_ssh_key
|
||||
group: script
|
||||
queue_name: <% $.queue_name %>
|
Loading…
Reference in New Issue