Use multipart headers on subcloud-backup API

This change replaces the subcloud-backup API endpoints to accept
both multipart and JSON content types. Multipart is necessary to keep
uniformity with all other endpoints with file data upload, whereas JSON
should also be accepted to keep backwards compatibility with older
versions of the CLI so as not to break Conductor.

Test Plan:
1. PASS - Validate that the new API version works with older
versions of the CLI, which use JSON content type.
2. PASS - Validate the the new API version works with the new
version of CLI, which uses multipart content type.
3. PASS - Rerun steps 1 and 2 for backup create, delete and
restore operations.

Story: 2010116
Task: 47020

Signed-off-by: Andre Carneiro <Andre.DexheimerCarneiro@windriver.com>
Change-Id: Ia1c53a691a854efac1fb9a5187260ca5d9291ab0
This commit is contained in:
Andre Carneiro 2022-12-02 09:10:12 -03:00
parent 59bf9dca2e
commit 9ae409377e
2 changed files with 36 additions and 6 deletions

View File

@ -8,11 +8,13 @@ import json
from collections import namedtuple
import base64
import os
from oslo_config import cfg
from oslo_log import log as logging
from oslo_messaging import RemoteError
import pecan
import yaml
from pecan import expose
from pecan import request as pecan_request
from pecan import response
@ -80,8 +82,34 @@ class SubcloudBackupController(object):
else:
pecan.abort(400, _("Unexpected verb received"))
return SubcloudBackupController._get_json_payload(request,
expected_params)
content_type = request.headers.get('content-type')
LOG.info('Request content-type: %s' % content_type)
if 'multipart/form-data' in content_type.lower():
return SubcloudBackupController._get_multipart_payload(request,
expected_params)
else:
return SubcloudBackupController._get_json_payload(request,
expected_params)
@staticmethod
def _get_multipart_payload(request, expected_params):
payload = dict()
file_params = ['backup_values', 'restore_values']
for param in file_params:
if param in request.POST:
file_item = request.POST[param]
file_item.file.seek(0, os.SEEK_SET)
data = yaml.safe_load(file_item.file.read().decode('utf8'))
payload.update({param: data})
del request.POST[param]
payload.update(request.POST)
if not set(payload.keys()).issubset(expected_params.keys()):
LOG.info("Got an unexpected parameter in: %s" % payload)
pecan.abort(400, _("Unexpected parameter received"))
return payload
@staticmethod
def _get_json_payload(request, expected_params):
@ -95,7 +123,7 @@ class SubcloudBackupController(object):
if not isinstance(payload, dict):
pecan.abort(400, _('Invalid request body format'))
if not set(payload.keys()).issubset(expected_params.keys()):
LOG.info(payload.keys())
LOG.info("Got an unexpected parameter in: %s" % payload)
pecan.abort(400, _("Unexpected parameter received"))
return payload
@ -217,13 +245,11 @@ class SubcloudBackupController(object):
@index.when(method='POST', template='json')
def post(self):
"""Create a new subcloud backup."""
context = restcomm.extract_context_from_environ()
payload = self._get_payload(pecan_request, 'create')
policy.authorize(subcloud_backup_policy.POLICY_ROOT % "create", {},
restcomm.extract_credentials_for_policy())
self._validate_and_decode_sysadmin_password(payload, 'sysadmin_password')
if not payload.get('local_only') and payload.get('registry_images'):

View File

@ -1029,9 +1029,13 @@ class SubcloudManager(manager.Manager):
str(keyring.get_password('CGCS', 'admin'))
if payload.get('backup_values'):
LOG.info('Backup create: Received backup_values for subcloud %s'
% subcloud_name)
for key, value in payload.get('backup_values').items():
payload['override_values'][key] = value
elif payload.get('restore_values'):
LOG.info('Backup restore: Received restore_values for subcloud %s'
% subcloud_name)
for key, value in payload.get('restore_values').items():
payload['override_values'][key] = value