overcloud deploy - provision virtual ips
When the --vip-file argument provides the vip_data.yaml provision Virtual IPs and include the deployed network environment file in user environments. Depends-On: https://review.opendev.org/795080 Change-Id: I1e4f8dde9f56311bed8dcbe1b08ade09225fd595
This commit is contained in:
parent
15f2539428
commit
ef077696a0
|
@ -30,6 +30,7 @@ UNDERCLOUD_ROLES_FILE = "roles_data_undercloud.yaml"
|
||||||
STANDALONE_EPHEMERAL_STACK_VSTATE = '/var/lib/tripleo-heat-installer'
|
STANDALONE_EPHEMERAL_STACK_VSTATE = '/var/lib/tripleo-heat-installer'
|
||||||
UNDERCLOUD_LOG_FILE = "install-undercloud.log"
|
UNDERCLOUD_LOG_FILE = "install-undercloud.log"
|
||||||
OVERCLOUD_NETWORKS_FILE = "network_data.yaml"
|
OVERCLOUD_NETWORKS_FILE = "network_data.yaml"
|
||||||
|
OVERCLOUD_VIP_FILE = "vip_data_default.yaml"
|
||||||
STANDALONE_NETWORKS_FILE = "/dev/null"
|
STANDALONE_NETWORKS_FILE = "/dev/null"
|
||||||
UNDERCLOUD_NETWORKS_FILE = "network_data_undercloud.yaml"
|
UNDERCLOUD_NETWORKS_FILE = "network_data_undercloud.yaml"
|
||||||
ANSIBLE_HOSTS_FILENAME = "hosts.yaml"
|
ANSIBLE_HOSTS_FILENAME = "hosts.yaml"
|
||||||
|
|
|
@ -110,6 +110,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
os.unlink(self.parameter_defaults_env_file)
|
os.unlink(self.parameter_defaults_env_file)
|
||||||
shutil.rmtree = self.real_shutil
|
shutil.rmtree = self.real_shutil
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
|
'_provision_virtual_ips', autospec=True)
|
||||||
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
'_provision_networks', autospec=True)
|
'_provision_networks', autospec=True)
|
||||||
@mock.patch('tripleoclient.utils.check_service_vips_migrated_to_service')
|
@mock.patch('tripleoclient.utils.check_service_vips_migrated_to_service')
|
||||||
|
@ -156,7 +158,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
mock_container_prepare, mock_generate_password,
|
mock_container_prepare, mock_generate_password,
|
||||||
mock_rc_params, mock_default_image_params,
|
mock_rc_params, mock_default_image_params,
|
||||||
mock_stack_data, mock_check_service_vip_migr,
|
mock_stack_data, mock_check_service_vip_migr,
|
||||||
mock_provision_networks):
|
mock_provision_networks, mock_provision_virtual_ips):
|
||||||
fixture = deployment.DeploymentWorkflowFixture()
|
fixture = deployment.DeploymentWorkflowFixture()
|
||||||
self.useFixture(fixture)
|
self.useFixture(fixture)
|
||||||
clients = self.app.client_manager
|
clients = self.app.client_manager
|
||||||
|
@ -340,6 +342,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
mock_validate_args.assert_called_once_with(parsed_args)
|
mock_validate_args.assert_called_once_with(parsed_args)
|
||||||
self.assertFalse(mock_invoke_plan_env_wf.called)
|
self.assertFalse(mock_invoke_plan_env_wf.called)
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
|
'_provision_virtual_ips', autospec=True)
|
||||||
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
'_provision_networks', autospec=True)
|
'_provision_networks', autospec=True)
|
||||||
@mock.patch('tripleoclient.utils.build_stack_data', autospec=True)
|
@mock.patch('tripleoclient.utils.build_stack_data', autospec=True)
|
||||||
|
@ -382,7 +386,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
mock_process_env, mock_roles_data,
|
mock_process_env, mock_roles_data,
|
||||||
mock_image_prepare, mock_generate_password,
|
mock_image_prepare, mock_generate_password,
|
||||||
mock_rc_params, mock_stack_data,
|
mock_rc_params, mock_stack_data,
|
||||||
mock_provision_networks):
|
mock_provision_networks, mock_provision_virtual_ips):
|
||||||
fixture = deployment.DeploymentWorkflowFixture()
|
fixture = deployment.DeploymentWorkflowFixture()
|
||||||
self.useFixture(fixture)
|
self.useFixture(fixture)
|
||||||
utils_fixture = deployment.UtilsFixture()
|
utils_fixture = deployment.UtilsFixture()
|
||||||
|
@ -431,6 +435,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
self.cmd.take_action(parsed_args)
|
self.cmd.take_action(parsed_args)
|
||||||
mock_copy.assert_called_once()
|
mock_copy.assert_called_once()
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
|
'_provision_virtual_ips', autospec=True)
|
||||||
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
'_provision_networks', autospec=True)
|
'_provision_networks', autospec=True)
|
||||||
@mock.patch('tripleoclient.utils.check_service_vips_migrated_to_service')
|
@mock.patch('tripleoclient.utils.check_service_vips_migrated_to_service')
|
||||||
|
@ -476,7 +482,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
mock_rc_params,
|
mock_rc_params,
|
||||||
mock_stack_data,
|
mock_stack_data,
|
||||||
mock_check_service_vip_migr,
|
mock_check_service_vip_migr,
|
||||||
mock_provision_networks):
|
mock_provision_networks,
|
||||||
|
mock_provision_virtual_ips):
|
||||||
fixture = deployment.DeploymentWorkflowFixture()
|
fixture = deployment.DeploymentWorkflowFixture()
|
||||||
self.useFixture(fixture)
|
self.useFixture(fixture)
|
||||||
utils_fixture = deployment.UtilsFixture()
|
utils_fixture = deployment.UtilsFixture()
|
||||||
|
@ -758,6 +765,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
self.assertFalse(utils_fixture.mock_deploy_tht.called)
|
self.assertFalse(utils_fixture.mock_deploy_tht.called)
|
||||||
self.assertFalse(mock_deploy.called)
|
self.assertFalse(mock_deploy.called)
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
|
'_provision_virtual_ips', autospec=True)
|
||||||
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
'_provision_networks', autospec=True)
|
'_provision_networks', autospec=True)
|
||||||
@mock.patch('tripleoclient.utils.check_service_vips_migrated_to_service')
|
@mock.patch('tripleoclient.utils.check_service_vips_migrated_to_service')
|
||||||
|
@ -788,7 +797,7 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
mock_roles_data, mock_image_prepare,
|
mock_roles_data, mock_image_prepare,
|
||||||
mock_generate_password, mock_rc_params,
|
mock_generate_password, mock_rc_params,
|
||||||
mock_check_service_vip_migr,
|
mock_check_service_vip_migr,
|
||||||
mock_provision_networks):
|
mock_provision_networks, mock_provision_virtual_ips):
|
||||||
fixture = deployment.DeploymentWorkflowFixture()
|
fixture = deployment.DeploymentWorkflowFixture()
|
||||||
self.useFixture(fixture)
|
self.useFixture(fixture)
|
||||||
clients = self.app.client_manager
|
clients = self.app.client_manager
|
||||||
|
@ -865,6 +874,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
output_dir=self.cmd.working_dir)
|
output_dir=self.cmd.working_dir)
|
||||||
mock_copy.assert_called_once()
|
mock_copy.assert_called_once()
|
||||||
|
|
||||||
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
|
'_provision_virtual_ips', autospec=True)
|
||||||
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
@mock.patch('tripleoclient.v1.overcloud_deploy.DeployOvercloud.'
|
||||||
'_provision_networks', autospec=True)
|
'_provision_networks', autospec=True)
|
||||||
@mock.patch('tripleoclient.utils.build_stack_data', autospec=True)
|
@mock.patch('tripleoclient.utils.build_stack_data', autospec=True)
|
||||||
|
@ -917,7 +928,8 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
mock_rc_params,
|
mock_rc_params,
|
||||||
mock_default_image_params,
|
mock_default_image_params,
|
||||||
mock_stack_data,
|
mock_stack_data,
|
||||||
mock_provision_networks):
|
mock_provision_networks,
|
||||||
|
mock_provision_virtual_ips):
|
||||||
fixture = deployment.DeploymentWorkflowFixture()
|
fixture = deployment.DeploymentWorkflowFixture()
|
||||||
self.useFixture(fixture)
|
self.useFixture(fixture)
|
||||||
utils_fixture = deployment.UtilsFixture()
|
utils_fixture = deployment.UtilsFixture()
|
||||||
|
@ -1553,6 +1565,47 @@ class TestDeployOvercloud(fakes.TestDeployOvercloud):
|
||||||
verbosity=3,
|
verbosity=3,
|
||||||
workdir=mock.ANY)
|
workdir=mock.ANY)
|
||||||
|
|
||||||
|
def test__provision_virtual_ips(self):
|
||||||
|
networks_file_path = self.tmp_dir.join('networks.yaml')
|
||||||
|
network_data = [
|
||||||
|
{'name': 'Network', 'name_lower': 'network', 'subnets': {}}
|
||||||
|
]
|
||||||
|
with open(networks_file_path, 'w') as temp_file:
|
||||||
|
yaml.safe_dump(network_data, temp_file)
|
||||||
|
vips_file_path = self.tmp_dir.join('virtual_ips.yaml')
|
||||||
|
vip_data = [
|
||||||
|
{'network': 'internal_api', 'subnet': 'internal_api_subnet'}
|
||||||
|
]
|
||||||
|
with open(vips_file_path, 'w') as temp_file:
|
||||||
|
yaml.safe_dump(vip_data, temp_file)
|
||||||
|
|
||||||
|
stack_name = 'overcloud'
|
||||||
|
arglist = ['--stack', stack_name,
|
||||||
|
'--vip-file', vips_file_path,
|
||||||
|
'--networks-file', networks_file_path]
|
||||||
|
verifylist = [('stack', stack_name),
|
||||||
|
('vip_file', vips_file_path),
|
||||||
|
('networks_file', networks_file_path)]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
tht_root = self.tmp_dir.join('tht')
|
||||||
|
env_dir = os.path.join(tht_root, 'user-environments')
|
||||||
|
env_path = os.path.join(env_dir, 'virtual-ips-deployed.yaml')
|
||||||
|
os.makedirs(env_dir)
|
||||||
|
|
||||||
|
result = self.cmd._provision_virtual_ips(parsed_args, tht_root)
|
||||||
|
self.assertEqual([env_path], result)
|
||||||
|
self.mock_playbook.assert_called_once_with(
|
||||||
|
extra_vars={'stack_name': stack_name,
|
||||||
|
'vip_data_path': vips_file_path,
|
||||||
|
'vip_deployed_path': env_path,
|
||||||
|
'overwrite': True},
|
||||||
|
inventory='localhost,',
|
||||||
|
playbook='cli-overcloud-network-vip-provision.yaml',
|
||||||
|
playbook_dir='/usr/share/ansible/tripleo-playbooks',
|
||||||
|
verbosity=3,
|
||||||
|
workdir=mock.ANY)
|
||||||
|
|
||||||
def test_check_limit_warning(self):
|
def test_check_limit_warning(self):
|
||||||
mock_warning = mock.MagicMock()
|
mock_warning = mock.MagicMock()
|
||||||
mock_log = mock.MagicMock()
|
mock_log = mock.MagicMock()
|
||||||
|
|
|
@ -1704,6 +1704,12 @@ def get_networks_file_path(networks_file, tht_root):
|
||||||
return os.path.abspath(networks_file)
|
return os.path.abspath(networks_file)
|
||||||
|
|
||||||
|
|
||||||
|
def get_vip_file_path(vip_file, tht_root):
|
||||||
|
vip_file = vip_file or os.path.join(
|
||||||
|
tht_root, constants.OVERCLOUD_VIP_FILE)
|
||||||
|
return os.path.abspath(vip_file)
|
||||||
|
|
||||||
|
|
||||||
def build_stack_data(clients, stack_name, template,
|
def build_stack_data(clients, stack_name, template,
|
||||||
files, env_files):
|
files, env_files):
|
||||||
orchestration_client = clients.orchestration
|
orchestration_client = clients.orchestration
|
||||||
|
@ -2789,3 +2795,21 @@ def copy_env_files(files_dict, tht_root):
|
||||||
relocate_path = os.path.join(tht_root, "user-environments",
|
relocate_path = os.path.join(tht_root, "user-environments",
|
||||||
os.path.basename(path))
|
os.path.basename(path))
|
||||||
safe_write(relocate_path, files_dict[full_path])
|
safe_write(relocate_path, files_dict[full_path])
|
||||||
|
|
||||||
|
|
||||||
|
def is_network_data_v2(networks_file_path):
|
||||||
|
"""Parse the network data, if any network have 'ip_subnet' or
|
||||||
|
'ipv6_subnet' keys this is not a network-v2 format file.
|
||||||
|
|
||||||
|
:param networks_file_path:
|
||||||
|
:return: boolean
|
||||||
|
"""
|
||||||
|
with open(networks_file_path, 'r') as f:
|
||||||
|
network_data = yaml.safe_load(f.read())
|
||||||
|
|
||||||
|
if isinstance(network_data, list):
|
||||||
|
for network in network_data:
|
||||||
|
if 'ip_subnet' in network or 'ipv6_subnet' in network:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
|
@ -89,8 +89,8 @@ def _validate_args(parsed_args):
|
||||||
|
|
||||||
not_found = [x for x in [parsed_args.networks_file,
|
not_found = [x for x in [parsed_args.networks_file,
|
||||||
parsed_args.plan_environment_file,
|
parsed_args.plan_environment_file,
|
||||||
parsed_args.plan_environment_file,
|
parsed_args.answers_file,
|
||||||
parsed_args.answers_file]
|
parsed_args.vip_file]
|
||||||
if x and not os.path.isfile(x)]
|
if x and not os.path.isfile(x)]
|
||||||
|
|
||||||
jinja2_envs = []
|
jinja2_envs = []
|
||||||
|
@ -118,6 +118,16 @@ def _validate_args(parsed_args):
|
||||||
"mean {}?".format(' -e '.join(jinja2_envs),
|
"mean {}?".format(' -e '.join(jinja2_envs),
|
||||||
' -e '.join(rewritten_paths)))
|
' -e '.join(rewritten_paths)))
|
||||||
|
|
||||||
|
if parsed_args.vip_file:
|
||||||
|
# Check vip_file only used with network data v2
|
||||||
|
networks_file_path = utils.get_networks_file_path(
|
||||||
|
parsed_args.networks_file, parsed_args.templates)
|
||||||
|
if not utils.is_network_data_v2(networks_file_path):
|
||||||
|
raise exceptions.CommandError(
|
||||||
|
'The --vip-file option can only be used in combination with a '
|
||||||
|
'network data v2 format networks file. The provided file {} '
|
||||||
|
'is network data v1 format'.format(networks_file_path))
|
||||||
|
|
||||||
|
|
||||||
class DeployOvercloud(command.Command):
|
class DeployOvercloud(command.Command):
|
||||||
"""Deploy Overcloud"""
|
"""Deploy Overcloud"""
|
||||||
|
@ -274,6 +284,8 @@ class DeployOvercloud(command.Command):
|
||||||
|
|
||||||
created_env_files.extend(
|
created_env_files.extend(
|
||||||
self._provision_networks(parsed_args, new_tht_root))
|
self._provision_networks(parsed_args, new_tht_root))
|
||||||
|
created_env_files.extend(
|
||||||
|
self._provision_virtual_ips(parsed_args, new_tht_root))
|
||||||
created_env_files.extend(
|
created_env_files.extend(
|
||||||
self._provision_baremetal(parsed_args, new_tht_root))
|
self._provision_baremetal(parsed_args, new_tht_root))
|
||||||
|
|
||||||
|
@ -472,24 +484,13 @@ class DeployOvercloud(command.Command):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _is_network_data_v2(networks_file_path):
|
|
||||||
with open(networks_file_path, 'r') as f:
|
|
||||||
network_data = yaml.safe_load(f.read())
|
|
||||||
for network in network_data:
|
|
||||||
if 'ip_subnet' in network or 'ipv6_subnet' in network:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _provision_networks(self, parsed_args, tht_root):
|
def _provision_networks(self, parsed_args, tht_root):
|
||||||
# Parse the network data, if any network have 'ip_subnet' or
|
# Parse the network data, if any network have 'ip_subnet' or
|
||||||
# 'ipv6_subnet' keys this is not a network-v2 format file. In this
|
# 'ipv6_subnet' keys this is not a network-v2 format file. In this
|
||||||
# case do nothing.
|
# case do nothing.
|
||||||
networks_file_path = utils.get_networks_file_path(
|
networks_file_path = utils.get_networks_file_path(
|
||||||
parsed_args.networks_file, parsed_args.templates)
|
parsed_args.networks_file, parsed_args.templates)
|
||||||
|
if not utils.is_network_data_v2(networks_file_path):
|
||||||
if not self._is_network_data_v2(networks_file_path):
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
output_path = utils.build_user_env_path(
|
output_path = utils.build_user_env_path(
|
||||||
|
@ -513,6 +514,37 @@ class DeployOvercloud(command.Command):
|
||||||
|
|
||||||
return [output_path]
|
return [output_path]
|
||||||
|
|
||||||
|
def _provision_virtual_ips(self, parsed_args, tht_root):
|
||||||
|
networks_file_path = utils.get_networks_file_path(
|
||||||
|
parsed_args.networks_file, parsed_args.templates)
|
||||||
|
if not utils.is_network_data_v2(networks_file_path):
|
||||||
|
return []
|
||||||
|
|
||||||
|
vip_file_path = utils.get_vip_file_path(parsed_args.vip_file,
|
||||||
|
parsed_args.templates)
|
||||||
|
output_path = utils.build_user_env_path(
|
||||||
|
'virtual-ips-deployed.yaml',
|
||||||
|
tht_root)
|
||||||
|
|
||||||
|
extra_vars = {
|
||||||
|
"stack_name": parsed_args.stack,
|
||||||
|
"vip_data_path": vip_file_path,
|
||||||
|
"vip_deployed_path": output_path,
|
||||||
|
"overwrite": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
with utils.TempDirs() as tmp:
|
||||||
|
utils.run_ansible_playbook(
|
||||||
|
playbook='cli-overcloud-network-vip-provision.yaml',
|
||||||
|
inventory='localhost,',
|
||||||
|
workdir=tmp,
|
||||||
|
playbook_dir=constants.ANSIBLE_TRIPLEO_PLAYBOOKS,
|
||||||
|
verbosity=utils.playbook_verbosity(self=self),
|
||||||
|
extra_vars=extra_vars,
|
||||||
|
)
|
||||||
|
|
||||||
|
return [output_path]
|
||||||
|
|
||||||
def setup_ephemeral_heat(self, parsed_args):
|
def setup_ephemeral_heat(self, parsed_args):
|
||||||
self.log.info("Using ephemeral heat for stack operation")
|
self.log.info("Using ephemeral heat for stack operation")
|
||||||
restore_db = (parsed_args.setup_only or
|
restore_db = (parsed_args.setup_only or
|
||||||
|
@ -613,6 +645,9 @@ class DeployOvercloud(command.Command):
|
||||||
help=_('Networks file, overrides the default %s in the '
|
help=_('Networks file, overrides the default %s in the '
|
||||||
'--templates directory') % constants.OVERCLOUD_NETWORKS_FILE
|
'--templates directory') % constants.OVERCLOUD_NETWORKS_FILE
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--vip-file', dest='vip_file',
|
||||||
|
help=_('Configuration file describing the network Virtual IPs.'))
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--plan-environment-file', '-p',
|
'--plan-environment-file', '-p',
|
||||||
help=_('Plan Environment file for derived parameters.')
|
help=_('Plan Environment file for derived parameters.')
|
||||||
|
|
|
@ -201,7 +201,7 @@ class OvercloudVirtualIPsProvision(command.Command):
|
||||||
parser.add_argument('vip_file',
|
parser.add_argument('vip_file',
|
||||||
metavar='<vip_data.yaml>',
|
metavar='<vip_data.yaml>',
|
||||||
help=_('Configuration file describing the network '
|
help=_('Configuration file describing the network '
|
||||||
'deployment.'))
|
'Virtual IPs.'))
|
||||||
parser.add_argument('--stack', dest='stack', required=True,
|
parser.add_argument('--stack', dest='stack', required=True,
|
||||||
help=_('Name of heat stack '
|
help=_('Name of heat stack '
|
||||||
'(default=Env: OVERCLOUD_STACK_NAME)'),
|
'(default=Env: OVERCLOUD_STACK_NAME)'),
|
||||||
|
|
Loading…
Reference in New Issue