Merge "Add subcloud deploy install option to dcmanager"
This commit is contained in:
commit
822cd5c0c4
|
@ -43,6 +43,12 @@ class phased_subcloud_deploy_manager(base.ResourceManager):
|
|||
files = kwargs.get('files')
|
||||
return self._deploy_operation(BASE_URL, files, data)
|
||||
|
||||
def subcloud_deploy_install(self, subcloud_ref, **kwargs):
|
||||
data = kwargs.get('data')
|
||||
files = kwargs.get('files')
|
||||
url = BASE_URL + "%s/install" % subcloud_ref
|
||||
return self._deploy_operation(url, files, data, method='patch')
|
||||
|
||||
def subcloud_deploy_bootstrap(self, subcloud_ref, **kwargs):
|
||||
data = kwargs.get('data')
|
||||
files = kwargs.get('files')
|
||||
|
|
|
@ -44,8 +44,8 @@ class CreatePhasedSubcloudDeploy(base.DCManagerShowOne):
|
|||
parser.add_argument(
|
||||
'--install-values',
|
||||
required=False,
|
||||
help='YAML file containing subcloud variables required for remote '
|
||||
'install playbook.'
|
||||
help='YAML file containing parameters required for the '
|
||||
'remote install of the subcloud.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
|
@ -120,6 +120,93 @@ class CreatePhasedSubcloudDeploy(base.DCManagerShowOne):
|
|||
files=files, data=data)
|
||||
|
||||
|
||||
class InstallPhasedSubcloudDeploy(base.DCManagerShowOne):
|
||||
"""Install a subcloud."""
|
||||
|
||||
def _get_format_function(self):
|
||||
return utils.subcloud_detail_format
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(InstallPhasedSubcloudDeploy, self).get_parser(prog_name)
|
||||
|
||||
parser.add_argument(
|
||||
'subcloud',
|
||||
help='Name or ID of the subcloud to install.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--install-values',
|
||||
required=False,
|
||||
help='YAML file containing parameters required for the '
|
||||
'remote install of the subcloud.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--sysadmin-password',
|
||||
required=False,
|
||||
help='sysadmin password of the subcloud to be configured, '
|
||||
'if not provided you will be prompted.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--bmc-password',
|
||||
required=False,
|
||||
help='bmc password of the subcloud to be configured, '
|
||||
'if not provided you will be prompted. This parameter is only'
|
||||
' valid if the --install-values are specified.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--release',
|
||||
required=False,
|
||||
help='software release used to install the subcloud with. '
|
||||
'If not specified, the current software release '
|
||||
'of the system controller will be used.'
|
||||
)
|
||||
return parser
|
||||
|
||||
def _get_resources(self, parsed_args):
|
||||
subcloud_ref = parsed_args.subcloud
|
||||
dcmanager_client = self.app.client_manager.\
|
||||
phased_subcloud_deploy_manager.phased_subcloud_deploy_manager
|
||||
files = dict()
|
||||
data = dict()
|
||||
|
||||
# Prompt the user for the subcloud's password if it isn't provided
|
||||
if parsed_args.sysadmin_password is not None:
|
||||
data['sysadmin_password'] = base64.b64encode(
|
||||
parsed_args.sysadmin_password.encode("utf-8"))
|
||||
else:
|
||||
password = utils.prompt_for_password()
|
||||
data["sysadmin_password"] = base64.b64encode(
|
||||
password.encode("utf-8"))
|
||||
|
||||
if parsed_args.install_values is not None:
|
||||
if not os.path.isfile(parsed_args.install_values):
|
||||
error_msg = "install-values does not exist: %s" % \
|
||||
parsed_args.install_values
|
||||
raise exceptions.DCManagerClientException(error_msg)
|
||||
files['install_values'] = parsed_args.install_values
|
||||
if parsed_args.bmc_password is not None:
|
||||
data['bmc_password'] = base64.b64encode(
|
||||
parsed_args.bmc_password.encode("utf-8"))
|
||||
else:
|
||||
password = utils.prompt_for_password('bmc')
|
||||
data["bmc_password"] = base64.b64encode(
|
||||
password.encode("utf-8"))
|
||||
|
||||
if parsed_args.release is not None:
|
||||
data['release'] = parsed_args.release
|
||||
|
||||
try:
|
||||
return dcmanager_client.subcloud_deploy_install(
|
||||
subcloud_ref=subcloud_ref, files=files, data=data)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
error_msg = "Unable to install subcloud %s" % (subcloud_ref)
|
||||
raise exceptions.DCManagerClientException(error_msg)
|
||||
|
||||
|
||||
class BootstrapPhasedSubcloudDeploy(base.DCManagerShowOne):
|
||||
"""Bootstrap a subcloud."""
|
||||
|
||||
|
|
|
@ -155,8 +155,8 @@ class AddSubcloud(base.DCManagerShowOne):
|
|||
parser.add_argument(
|
||||
'--install-values',
|
||||
required=False,
|
||||
help='YAML file containing subcloud variables required for remote '
|
||||
'install playbook.'
|
||||
help='YAML file containing parameters required for the '
|
||||
'remote install of the subcloud.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
|
@ -492,8 +492,8 @@ class UpdateSubcloud(base.DCManagerShowOne):
|
|||
parser.add_argument(
|
||||
'--install-values',
|
||||
required=False,
|
||||
help='YAML file containing subcloud variables required for remote '
|
||||
'install playbook.'
|
||||
help='YAML file containing parameters required for the '
|
||||
'remote install of the subcloud.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
|
|
|
@ -547,6 +547,7 @@ class DCManagerShell(app.App):
|
|||
'subcloud deploy create': psdm.CreatePhasedSubcloudDeploy,
|
||||
'subcloud deploy bootstrap': psdm.BootstrapPhasedSubcloudDeploy,
|
||||
'subcloud deploy config': psdm.ConfigPhasedSubcloudDeploy,
|
||||
'subcloud deploy install': psdm.InstallPhasedSubcloudDeploy,
|
||||
'subcloud-deploy upload': sdm.SubcloudDeployUpload,
|
||||
'subcloud-deploy show': sdm.SubcloudDeployShow,
|
||||
'alarm summary': am.ListAlarmSummary,
|
||||
|
|
|
@ -133,6 +133,25 @@ FAKE_BOOTSTRAP_VALUES = {
|
|||
'backup_datetime': BACKUP_DATETIME
|
||||
}
|
||||
|
||||
FAKE_INSTALL_VALUES = {
|
||||
"image": "http://192.168.101.2:8080/iso/bootimage.iso",
|
||||
"software_version": SOFTWARE_VERSION,
|
||||
"bootstrap_interface": "eno1",
|
||||
"bootstrap_address": "128.224.151.183",
|
||||
"bootstrap_address_prefix": 23,
|
||||
"bmc_address": "128.224.64.180",
|
||||
"bmc_username": "root",
|
||||
"nexthop_gateway": "128.224.150.1",
|
||||
"network_address": "128.224.144.0",
|
||||
"network_mask": "255.255.254.0",
|
||||
"install_type": 3,
|
||||
"console_type": "tty0",
|
||||
"bootstrap_vlan": 128,
|
||||
"rootfs_device": "/dev/disk/by-path/pci-0000:5c:00.0-scsi-0:1:0:0",
|
||||
"boot_device": "/dev/disk/by-path/pci-0000:5c:00.0-scsi-0:1:0:0",
|
||||
"rd.net.timeout.ipv6dad": 300,
|
||||
}
|
||||
|
||||
|
||||
class FakeResponse(object):
|
||||
"""Fake response for testing DC Manager Client."""
|
||||
|
|
|
@ -8,6 +8,7 @@ import os
|
|||
import tempfile
|
||||
|
||||
import mock
|
||||
import yaml
|
||||
|
||||
from dcmanagerclient.commands.v1 import phased_subcloud_deploy_manager as cmd
|
||||
from dcmanagerclient.exceptions import DCManagerClientException
|
||||
|
@ -60,6 +61,62 @@ class TestCLIPhasedSubcloudDeployManagerV1(base.BaseCommandTest):
|
|||
])
|
||||
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
|
||||
|
||||
@mock.patch('getpass.getpass', return_value='testpassword')
|
||||
def test_install_subcloud(self, getpass):
|
||||
self.client.subcloud_deploy_install.return_value = [
|
||||
base.SUBCLOUD_RESOURCE]
|
||||
|
||||
with tempfile.NamedTemporaryFile(mode='w') as f:
|
||||
yaml.dump(base.FAKE_INSTALL_VALUES, f)
|
||||
file_path = os.path.abspath(f.name)
|
||||
actual_call = self.call(
|
||||
cmd.InstallPhasedSubcloudDeploy, app_args=[
|
||||
base.NAME, '--install-values', file_path,
|
||||
])
|
||||
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
|
||||
|
||||
@mock.patch('getpass.getpass', return_value='testpassword')
|
||||
def test_install_subcloud_with_release(self, getpass):
|
||||
self.client.subcloud_deploy_install.return_value = [
|
||||
base.SUBCLOUD_RESOURCE]
|
||||
|
||||
with tempfile.NamedTemporaryFile(mode='w') as f:
|
||||
yaml.dump(base.FAKE_INSTALL_VALUES, f)
|
||||
file_path = os.path.abspath(f.name)
|
||||
actual_call = self.call(
|
||||
cmd.InstallPhasedSubcloudDeploy, app_args=[
|
||||
base.NAME,
|
||||
'--install-values', file_path,
|
||||
'--release', base.SOFTWARE_VERSION,
|
||||
])
|
||||
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
|
||||
|
||||
@mock.patch('getpass.getpass', return_value='testpassword')
|
||||
def test_install_subcloud_without_install_values(self, getpass):
|
||||
self.client.subcloud_deploy_install.return_value = [
|
||||
base.SUBCLOUD_RESOURCE]
|
||||
|
||||
actual_call = self.call(
|
||||
cmd.InstallPhasedSubcloudDeploy, app_args=[base.NAME])
|
||||
|
||||
self.assertEqual(base.SUBCLOUD_FIELD_RESULT_LIST, actual_call[1])
|
||||
|
||||
@mock.patch('getpass.getpass', return_value='testpassword')
|
||||
def test_install_file_does_not_exist(self, getpass):
|
||||
self.client.subcloud_deploy_install.return_value = [
|
||||
base.SUBCLOUD_RESOURCE]
|
||||
with tempfile.NamedTemporaryFile() as f:
|
||||
file_path = os.path.abspath(f.name)
|
||||
|
||||
e = self.assertRaises(DCManagerClientException,
|
||||
self.call,
|
||||
cmd.InstallPhasedSubcloudDeploy,
|
||||
app_args=[base.NAME,
|
||||
'--install-values', file_path]
|
||||
)
|
||||
self.assertTrue('install-values does not exist'
|
||||
in str(e))
|
||||
|
||||
@mock.patch('getpass.getpass', return_value='testpassword')
|
||||
def test_success_configure_subcloud(self, getpass):
|
||||
self.client.subcloud_deploy_config.return_value = [
|
||||
|
|
Loading…
Reference in New Issue