Add plan export command

Depends-On: I789c960f61a30ccd4b076fcae4b3e1b80e825585
Implements: blueprint plan-export-command

Change-Id: Ibedca0d80f93ab5e4bf7f105472bb384bc9506e6
This commit is contained in:
Ana Krivokapic 2017-01-26 19:35:11 +01:00
parent 90a9ae0b6d
commit 41bf090d01
5 changed files with 135 additions and 0 deletions

View File

@ -0,0 +1,3 @@
---
features:
- Add a new plan export command for exporting deployment plans.

View File

@ -78,6 +78,7 @@ openstack.tripleoclient.v1 =
overcloud_plan_delete = tripleoclient.v1.overcloud_plan:DeletePlan
overcloud_plan_deploy = tripleoclient.v1.overcloud_plan:DeployPlan
overcloud_plan_list = tripleoclient.v1.overcloud_plan:ListPlans
overcloud_plan_export = tripleoclient.v1.overcloud_plan:ExportPlan
overcloud_profiles_match = tripleoclient.v1.overcloud_profiles:MatchProfiles
overcloud_profiles_list = tripleoclient.v1.overcloud_profiles:ListProfiles
overcloud_raid_create = tripleoclient.v1.overcloud_raid:CreateRAID

View File

@ -359,3 +359,59 @@ class TestOvercloudDeployPlan(utils.TestCommand):
'queue_name': 'UUID4'
}
)
class TestOvercloudExportPlan(utils.TestCommand):
def setUp(self):
super(TestOvercloudExportPlan, self).setUp()
self.cmd = overcloud_plan.ExportPlan(self.app, None)
self.app.client_manager = mock.Mock()
self.clients = self.app.client_manager
# Mock UUID4 generation for every test
uuid4_patcher = mock.patch('uuid.uuid4', return_value="UUID4")
self.mock_uuid4 = uuid4_patcher.start()
self.addCleanup(self.mock_uuid4.stop)
# Mock urlopen
f = mock.Mock()
f.read.return_value = 'tarball contents'
urlopen_patcher = mock.patch('six.moves.urllib.request.urlopen',
return_value=f)
self.mock_urlopen = urlopen_patcher.start()
self.addCleanup(self.mock_urlopen.stop)
@mock.patch(
'tripleoclient.workflows.plan_management.export_deployment_plan',
autospec=True)
def test_export_plan(self, export_deployment_plan_mock):
parsed_args = self.check_parser(self.cmd, ['test-plan'],
[('plans', ['test-plan'])])
export_deployment_plan_mock.return_value = 'http://fake-url.com'
with mock.patch('six.moves.builtins.open', mock.mock_open()):
self.cmd.take_action(parsed_args)
export_deployment_plan_mock.assert_called_once_with(
self.clients, plan='test-plan', queue_name='UUID4')
@mock.patch(
'tripleoclient.workflows.plan_management.export_deployment_plan',
autospec=True)
def test_export_multiple_plans(self, export_deployment_plan_mock):
argslist = ['test-plan1', 'test-plan2']
verifylist = [('plans', ['test-plan1', 'test-plan2'])]
parsed_args = self.check_parser(self.cmd, argslist, verifylist)
export_deployment_plan_mock.return_value = 'http://fake-url.com'
with mock.patch('six.moves.builtins.open', mock.mock_open()):
self.cmd.take_action(parsed_args)
expected = [
mock.call(self.clients, plan='test-plan1', queue_name='UUID4'),
mock.call(self.clients, plan='test-plan2', queue_name='UUID4'),
]
self.assertEqual(export_deployment_plan_mock.call_args_list, expected)

View File

@ -12,10 +12,13 @@
import json
import logging
import os.path
import uuid
from osc_lib.command import command
from osc_lib.i18n import _
from six.moves.urllib import request
from tripleoclient import utils
from tripleoclient.workflows import deployment
@ -146,3 +149,51 @@ class DeployPlan(command.Command):
self.app_args.verbose_level,
timeout=parsed_args.timeout,
run_validations=parsed_args.run_validations)
class ExportPlan(command.Command):
"""Export a deployment plan"""
log = logging.getLogger(__name__ + ".ExportPlan")
def get_parser(self, prog_name):
parser = super(ExportPlan, self).get_parser(prog_name)
parser.add_argument('plans', metavar='<name>', nargs='+',
help=_('Name of the plan(s) to export.'))
parser.add_argument('--output-files', '-o', metavar='<output file>',
nargs='+', default=[],
help=_('Name of the output file(s) for exports. '
'Each will default to "<name>.tar.gz".')
)
parser.add_argument('--force-overwrite', '-f', action='store_true',
default=False,
help=_('Overwrite output files if they exist.'))
return parser
def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args)
clients = self.app.client_manager
plans = parsed_args.plans
outfiles = parsed_args.output_files
overwrite = parsed_args.force_overwrite
for i, plan in enumerate(plans):
print("Exporting plan %s..." % plan)
try:
tarball_name = outfiles[i]
except IndexError:
tarball_name = '%s.tar.gz' % plan
if os.path.exists(tarball_name) and not overwrite:
print("File '%s' already exists, not exporting."
% tarball_name)
continue
tempurl = plan_management.export_deployment_plan(
clients, plan=plan, queue_name=str(uuid.uuid4()))
f = request.urlopen(tempurl)
tarball_contents = f.read()
with open(tarball_name, 'w') as f:
f.write(tarball_contents)

View File

@ -183,3 +183,27 @@ def update_plan_from_templates(clients, name, tht_root, roles_file=None,
update_deployment_plan(clients, container=name,
queue_name=str(uuid.uuid4()),
generate_passwords=generate_passwords)
def export_deployment_plan(clients, **workflow_input):
workflow_client = clients.workflow_engine
tripleoclients = clients.tripleoclient
queue_name = workflow_input['queue_name']
execution = base.start_workflow(
workflow_client,
'tripleo.plan_management.v1.export_deployment_plan',
workflow_input=workflow_input
)
with tripleoclients.messaging_websocket(queue_name) as ws:
for payload in base.wait_for_messages(workflow_client, ws, execution,
_WORKFLOW_TIMEOUT):
if 'message' in payload:
print(payload['message'])
if payload['status'] == 'SUCCESS':
return payload['tempurl']
else:
raise exceptions.WorkflowServiceError(
'Exception exporting plan: {}'.format(payload['message']))