From fa1683ca9d4d69fafb36d8ca8acfa7c23ec6b4eb Mon Sep 17 00:00:00 2001 From: Mathieu Bultel Date: Thu, 16 Mar 2017 16:29:51 +0100 Subject: [PATCH] create history for the overcloud deploy command Add a history directory in user $HOME for tracking all the calls of the openstack overcloud deploy command passed by the users. Each deploy command run by a user is now track in an history file under $HOME/.tripleo directory. It allow to retrieve all the previous calls from the openstack overcloud deploy command, the environment files used and the templates directories used, for analysis, debugging or tracking. See https://bugs.launchpad.net/tripleo/+bug/1673700 It will be very usefull for post deployment user experience and for customer debuging. This review aim to be backport for old releases support. I will implement a mistral workflow in a follow up review for Pike, as suggested by D0ugal (D Matthews) Change-Id: Ibf7dd4a7b0036b6f2a0809d0448a05665c809167 Closes-Bug: #1673700 --- ...cloud-deploy-history-4a54b53ac10e6542.yaml | 7 +++ tripleoclient/tests/test_utils.py | 45 +++++++++++++++++++ tripleoclient/utils.py | 30 +++++++++++++ tripleoclient/v1/overcloud_deploy.py | 1 + 4 files changed, 83 insertions(+) create mode 100644 releasenotes/notes/overcloud-deploy-history-4a54b53ac10e6542.yaml diff --git a/releasenotes/notes/overcloud-deploy-history-4a54b53ac10e6542.yaml b/releasenotes/notes/overcloud-deploy-history-4a54b53ac10e6542.yaml new file mode 100644 index 000000000..91c9cb935 --- /dev/null +++ b/releasenotes/notes/overcloud-deploy-history-4a54b53ac10e6542.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - Each deploy command run by a user is now track in an history file under + $HOME/.tripleo directory. It allow to retrieve all the previous calls from + the openstack overcloud deploy command, the environment files used and the + templates directories used, for analysis, debugging or tracking. See + https://bugs.launchpad.net/tripleo/+bug/1673700 diff --git a/tripleoclient/tests/test_utils.py b/tripleoclient/tests/test_utils.py index 6d558c4dc..d04dda0da 100644 --- a/tripleoclient/tests/test_utils.py +++ b/tripleoclient/tests/test_utils.py @@ -15,9 +15,12 @@ from uuid import uuid4 +import argparse import mock +from mock import call import os.path import tempfile + from unittest import TestCase import yaml @@ -712,3 +715,45 @@ class TestBracketIPV6(TestCase): def test_already_bracketed(self): result = utils.bracket_ipv6('[::1]') self.assertEqual('[::1]', result) + + +class TestStoreCliParam(TestCase): + + def setUp(self): + self.args = argparse.ArgumentParser() + + @mock.patch('os.mkdir') + @mock.patch('os.path.exists') + def test_fail_to_create_file(self, mock_exists, mock_mkdir): + mock_exists.return_value = False + mock_mkdir.side_effect = OSError() + self.assertRaises(OSError, utils.store_cli_param, self.args) + + @mock.patch('os.path.isdir') + @mock.patch('os.path.exists') + def test_exists_but_not_dir(self, mock_exists, mock_isdir): + mock_exists.return_value = True + mock_isdir.return_value = False + self.assertRaises(exceptions.InvalidConfiguration, + utils.store_cli_param, + self.args) + + @mock.patch('six.moves.builtins.open') + @mock.patch('os.path.isdir') + @mock.patch('os.path.exists') + def test_write_cli_param(self, mock_exists, mock_isdir, mock_open): + history_path = os.path.join(os.path.expanduser("~"), '.tripleo') + mock_exists.return_value = True + mock_isdir.return_value = True + utils.store_cli_param(self.args) + expected_call = [call("%s/history" % history_path, 'a')] + mock_open.assert_has_calls(expected_call) + + @mock.patch('six.moves.builtins.open') + @mock.patch('os.path.isdir') + @mock.patch('os.path.exists') + def test_fail_to_write_data(self, mock_exists, mock_isdir, mock_open): + mock_exists.return_value = True + mock_isdir.return_value = True + mock_open.side_effect = IOError() + self.assertRaises(IOError, utils.store_cli_param, self.args) diff --git a/tripleoclient/utils.py b/tripleoclient/utils.py index ff31dc895..1f5bc47c5 100644 --- a/tripleoclient/utils.py +++ b/tripleoclient/utils.py @@ -15,6 +15,7 @@ from __future__ import print_function import csv +import datetime import hashlib import json import logging @@ -77,6 +78,35 @@ def write_overcloudrc(stack_name, overcloudrcs, config_directory='.'): os.chmod(rcv3path, 0o600) +def store_cli_param(parsed_args): + """write the cli parameters into an history file""" + + history_path = os.path.join(os.path.expanduser("~"), '.tripleo') + if not os.path.exists(history_path): + try: + os.mkdir(history_path) + except OSError as e: + messages = "Unable to create TripleO history directory: " + "{0}, {1}".format(history_path, e) + raise OSError(messages) + if os.path.isdir(history_path): + try: + with open(os.path.join(history_path, + 'history'), 'a') as history: + args = parsed_args.__dict__.copy() + used_args = ', '.join('%s=%s' % (key, value) + for key, value in args.items()) + history.write(' '.join([str(datetime.datetime.now()), + used_args])) + except IOError as e: + messages = "Unable to write into TripleO history file: " + "{0}, {1}".format(history_path, e) + raise IOError(messages) + else: + raise exceptions.InvalidConfiguration("Target path %s is not a " + "directory" % history_path) + + def create_tempest_deployer_input(config_name='tempest-deployer-input.conf'): config = configparser.ConfigParser() diff --git a/tripleoclient/v1/overcloud_deploy.py b/tripleoclient/v1/overcloud_deploy.py index e4f93155d..6abb14ef2 100644 --- a/tripleoclient/v1/overcloud_deploy.py +++ b/tripleoclient/v1/overcloud_deploy.py @@ -812,6 +812,7 @@ class DeployOvercloud(command.Command): sc_logger.setLevel(logging.CRITICAL) self._validate_args(parsed_args) + utils.store_cli_param(parsed_args) stack = utils.get_stack(self.orchestration_client, parsed_args.stack)