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
(cherry picked from commit f3db22f57a)
This commit is contained in:
Jon Bernard 2016-11-11 10:56:55 -05:00
parent 376638513d
commit 3766c65c43
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.assertTrue(isinstance(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()