RBD: enclose ipv6 addresses in square brackets

When using ipv6, the IP address must be enclosed in square brackets
according to RFC 3986, Section 3.2.2.  Without this, an ipv6 cloud will
fail to connect to the ceph cluster prior to backup because the address
and port are not parsed correctly.

Closes-Bug: #1640914
Change-Id: I6501c7cdac38fe545d12e786448a8e0c0a4f6a25
This commit is contained in:
Jon Bernard 2016-11-11 10:56:55 -05:00
parent fb0b7e3e3e
commit f3db22f57a
2 changed files with 35 additions and 6 deletions

View File

@ -18,6 +18,7 @@ import tempfile
from oslo_concurrency import processutils as putils
from oslo_log import log as logging
from oslo_utils import netutils
from os_brick.i18n import _, _LE
from os_brick import exception
@ -60,16 +61,24 @@ class RBDConnector(base.BaseLinuxConnector):
# TODO(e0ne): Implement this for local volume.
return []
def _sanitize_mon_hosts(self, hosts):
def _sanitize_host(host):
if netutils.is_valid_ipv6(host):
host = '[%s]' % host
return host
return list(map(_sanitize_host, hosts))
def _create_ceph_conf(self, monitor_ips, monitor_ports,
cluster_name, user):
monitors = ["%s:%s" % (ip, port) for ip, port in
zip(self._sanitize_mon_hosts(monitor_ips), monitor_ports)]
mon_hosts = "mon_host = %s" % (','.join(monitors))
client_section = "[client.%s]" % user
keyring = ("keyring = /etc/ceph/%s.client.%s.keyring" %
(cluster_name, user))
try:
fd, ceph_conf_path = tempfile.mkstemp()
monitors = ["%s:%s" % (ip, port) for ip, port
in zip(monitor_ips, monitor_ports)]
mon_hosts = "mon_host = %s" % (','.join(monitors))
client_section = "[client.%s]" % user
keyring = ("keyring = /etc/ceph/%s.client.%s.keyring" %
(cluster_name, user))
with os.fdopen(fd, 'w') as conf_file:
conf_file.writelines([mon_hosts, "\n",
client_section, "\n", keyring])

View File

@ -11,6 +11,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import ddt
import mock
from os_brick.initiator.connectors import rbd
@ -20,6 +21,7 @@ from os_brick.tests.initiator import test_connector
from os_brick import utils
@ddt.ddt
class RBDConnectorTestCase(test_connector.ConnectorTestCase):
def setUp(self):
@ -92,6 +94,24 @@ class RBDConnectorTestCase(test_connector.ConnectorTestCase):
self.assertIsInstance(device_info['path'],
linuxrbd.RBDVolumeIOWrapper)
@ddt.data((['192.168.1.1', '192.168.1.2'],
['192.168.1.1', '192.168.1.2']),
(['3ffe:1900:4545:3:200:f8ff:fe21:67cf',
'fe80:0:0:0:200:f8ff:fe21:67cf'],
['[3ffe:1900:4545:3:200:f8ff:fe21:67cf]',
'[fe80:0:0:0:200:f8ff:fe21:67cf]']),
(['foobar', 'fizzbuzz'], ['foobar', 'fizzbuzz']),
(['192.168.1.1',
'3ffe:1900:4545:3:200:f8ff:fe21:67cf',
'hello, world!'],
['192.168.1.1',
'[3ffe:1900:4545:3:200:f8ff:fe21:67cf]',
'hello, world!']))
@ddt.unpack
def test_sanitize_mon_host(self, hosts_in, hosts_out):
conn = rbd.RBDConnector(None)
self.assertEqual(hosts_out, conn._sanitize_mon_hosts(hosts_in))
@mock.patch('os_brick.initiator.connectors.rbd.tempfile.mkstemp')
def test_create_ceph_conf(self, mock_mkstemp):
mockopen = mock.mock_open()