Replace all occurrences of $ with $$ in vCenter

Backport from 6.1

OpenStack services may reference to previously defined variable in
configuration files using $ (dollar sign), e.g. 'metadata_host =
$my_ip'. Interpolation can be avoided by using $$.  Passwords often
contain metachars and $ is one of them.  We must replace all $
occurrences with $$, otherwise service will fail to start because it
cannot interpolate non-existing variable.

Change-Id: I0d7d9f2d7f0ccaa3310c865a7f467c377c067442
Closes-bug: #1436083
This commit is contained in:
Andriy Popovych 2015-05-12 21:41:37 +03:00
parent a268337c7f
commit 9f77fda680
2 changed files with 124 additions and 0 deletions

View File

@ -1143,12 +1143,51 @@ class DeploymentMultinodeSerializer60(DeploymentMultinodeSerializer):
nova_network_serializer = NovaNetworkDeploymentSerializer
neutron_network_serializer = NeutronNetworkDeploymentSerializer60
def get_common_attrs(self, cluster):
attrs = super(DeploymentMultinodeSerializer60, self).\
get_common_attrs(cluster)
if attrs['libvirt_type'] == 'vcenter':
data_to_replace = [
('vcenter', 'vc_user'),
('vcenter', 'vc_password'),
('vcenter', 'datastore_regex'),
('storage', 'vc_user'),
('storage', 'vc_password')
]
# In order to disable variable interpolation in values
# that we write to configuration files during deployment
# we must replace all $ (dollar sign) occurrences.
for group, key in data_to_replace:
attrs[group][key] = str(attrs[group][key]).replace('$', '$$')
return attrs
class DeploymentHASerializer60(DeploymentHASerializer):
nova_network_serializer = NovaNetworkDeploymentSerializer
neutron_network_serializer = NeutronNetworkDeploymentSerializer60
def get_common_attrs(self, cluster):
attrs = super(DeploymentHASerializer60, self).\
get_common_attrs(cluster)
if attrs['libvirt_type'] == 'vcenter':
data_to_replace = [
('vcenter', 'vc_user'),
('vcenter', 'vc_password'),
('vcenter', 'datastore_regex'),
('storage', 'vc_user'),
('storage', 'vc_password')
]
for group, key in data_to_replace:
attrs[group][key] = str(attrs[group][key]).replace('$', '$$')
return attrs
def create_serializer(cluster):
"""Returns a serializer depends on a given `cluster`.

View File

@ -34,17 +34,25 @@ from nailgun.orchestrator.deployment_serializers import\
DeploymentHASerializer
from nailgun.orchestrator.deployment_serializers import\
DeploymentHASerializer51
from nailgun.orchestrator.deployment_serializers import\
DeploymentHASerializer60
from nailgun.orchestrator.deployment_serializers import\
DeploymentMultinodeSerializer
from nailgun.orchestrator.deployment_serializers import\
DeploymentMultinodeSerializer60
from nailgun.orchestrator.priority_serializers import\
PriorityHASerializer50
from nailgun.orchestrator.priority_serializers import\
PriorityHASerializer51
from nailgun.orchestrator.priority_serializers import\
PriorityHASerializer60
from nailgun.orchestrator.priority_serializers import\
PriorityHASerializerPatching
from nailgun.orchestrator.priority_serializers import\
PriorityMultinodeSerializer50
from nailgun.orchestrator.priority_serializers import\
PriorityMultinodeSerializer60
from nailgun.db.sqlalchemy import models
from nailgun import objects
@ -58,6 +66,22 @@ from nailgun.volumes import manager
class OrchestratorSerializerTestBase(BaseIntegrationTest):
"""Class containts helpers."""
def create_env(self, mode):
cluster = self.env.create(
cluster_kwargs={
'mode': mode,
'net_provider': 'neutron'},
nodes_kwargs=[{
'roles': ['controller'],
'pending_addition': True}])
cluster_db = self.db.query(Cluster).get(cluster['id'])
objects.NodeCollection.prepare_for_deployment(
cluster_db.nodes)
self.db.flush()
return cluster_db
def filter_by_role(self, nodes, role):
return filter(lambda node: role in node['role'], nodes)
@ -90,6 +114,37 @@ class OrchestratorSerializerTestBase(BaseIntegrationTest):
'''
return copy.deepcopy(data_to_copy)
def check_vmware_escaped_dollar_sign(self):
cluster_attrs = objects.Cluster.get_attributes(
self.cluster_db).editable
cluster_attrs['common']['libvirt_type']['value'] = 'vcenter'
cluster_attrs['vcenter']['vc_user']['value'] = 'user$'
cluster_attrs['vcenter']['vc_password']['value'] = 'pass$word'
cluster_attrs['vcenter']['datastore_regex']['value'] = '^stack-[0-9]$'
cluster_attrs['storage']['vc_user']['value'] = 'user$'
cluster_attrs['storage']['vc_password']['value'] = 'pass$word'
objects.Cluster.update_attributes(
self.cluster_db, {'editable': cluster_attrs})
result = self.serializer.get_common_attrs(self.cluster_db)
self.assertEqual(
result['vcenter']['vc_user'],
"user$$")
self.assertEqual(
result['vcenter']['vc_password'],
"pass$$word")
self.assertEqual(
result['vcenter']['datastore_regex'],
"^stack-[0-9]$$")
self.assertEqual(
result['storage']['vc_user'],
"user$$")
self.assertEqual(
result['storage']['vc_password'],
"pass$$word")
# TODO(awoodward): multinode deprecation: probably has duplicates
class TestNovaOrchestratorSerializer(OrchestratorSerializerTestBase):
@ -1643,3 +1698,33 @@ class TestNSXOrchestratorSerializer(OrchestratorSerializerTestBase):
self.assertIn('enable_metadata_network', l3_settings['dhcp_agent'])
self.assertEqual(l3_settings['dhcp_agent']['enable_metadata_network'],
True)
class TestDeploymentHASerializer60(OrchestratorSerializerTestBase):
def setUp(self):
super(TestDeploymentHASerializer60, self).setUp()
self.cluster_db = self.create_env('ha_compact')
@property
def serializer(self):
return DeploymentHASerializer60(
PriorityHASerializer60)
def test_vmware_escaped_dollar_sign(self):
self.check_vmware_escaped_dollar_sign()
class TestDeploymentMultinodeSerializer60(OrchestratorSerializerTestBase):
def setUp(self):
super(TestDeploymentMultinodeSerializer60, self).setUp()
self.cluster_db = self.create_env('multinode')
@property
def serializer(self):
return DeploymentMultinodeSerializer60(
PriorityMultinodeSerializer60)
def test_vmware_escaped_dollar_sign(self):
self.check_vmware_escaped_dollar_sign()