Move some code out of utils.py
Move code into more specific locations where it is applicable rather than the Cinder-wide utils.py. Change-Id: I87f80f041cec255d51145e39bc0c0781a81e6db8
This commit is contained in:
parent
48f9425d2c
commit
8a4dbf3eef
|
@ -130,3 +130,16 @@ def validate_integer(value, name, min_value=None, max_value=None):
|
||||||
return value
|
return value
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise webob.exc.HTTPBadRequest(explanation=six.text_type(e))
|
raise webob.exc.HTTPBadRequest(explanation=six.text_type(e))
|
||||||
|
|
||||||
|
|
||||||
|
def walk_class_hierarchy(clazz, encountered=None):
|
||||||
|
"""Walk class hierarchy, yielding most derived classes first."""
|
||||||
|
if not encountered:
|
||||||
|
encountered = []
|
||||||
|
for subclass in clazz.__subclasses__():
|
||||||
|
if subclass not in encountered:
|
||||||
|
encountered.append(subclass)
|
||||||
|
# drill down to leaves first
|
||||||
|
for subsubclass in walk_class_hierarchy(subclass, encountered):
|
||||||
|
yield subsubclass
|
||||||
|
yield subclass
|
||||||
|
|
|
@ -20,10 +20,10 @@ from six.moves import http_client
|
||||||
import webob.dec
|
import webob.dec
|
||||||
import webob.exc
|
import webob.exc
|
||||||
|
|
||||||
|
from cinder.api import api_utils
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
from cinder import utils
|
|
||||||
from cinder.wsgi import common as base_wsgi
|
from cinder.wsgi import common as base_wsgi
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ class FaultWrapper(base_wsgi.Middleware):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def status_to_type(status):
|
def status_to_type(status):
|
||||||
if not FaultWrapper._status_to_type:
|
if not FaultWrapper._status_to_type:
|
||||||
for clazz in utils.walk_class_hierarchy(webob.exc.HTTPError):
|
for clazz in api_utils.walk_class_hierarchy(webob.exc.HTTPError):
|
||||||
FaultWrapper._status_to_type[clazz.code] = clazz
|
FaultWrapper._status_to_type[clazz.code] = clazz
|
||||||
return FaultWrapper._status_to_type.get(
|
return FaultWrapper._status_to_type.get(
|
||||||
status, webob.exc.HTTPInternalServerError)()
|
status, webob.exc.HTTPInternalServerError)()
|
||||||
|
|
|
@ -29,7 +29,7 @@ from cinder import db
|
||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder import test
|
from cinder import test
|
||||||
from cinder.tests.unit import fake_constants as fake
|
from cinder.tests.unit import fake_constants as fake
|
||||||
from cinder import utils
|
from cinder.tests.unit import utils as test_utils
|
||||||
from cinder.volume import qos_specs
|
from cinder.volume import qos_specs
|
||||||
from cinder.volume import volume_types
|
from cinder.volume import volume_types
|
||||||
|
|
||||||
|
@ -374,7 +374,7 @@ class QoSSpecsTestCase(test.TestCase):
|
||||||
qos_specs_dict['specs'])
|
qos_specs_dict['specs'])
|
||||||
qos_specs_dict['id'] = qos_specs_id
|
qos_specs_dict['id'] = qos_specs_id
|
||||||
specs = db.qos_specs_get(self.ctxt, qos_specs_id)
|
specs = db.qos_specs_get(self.ctxt, qos_specs_id)
|
||||||
qos_specs_list[index]['created_at'] = utils.time_format(
|
qos_specs_list[index]['created_at'] = test_utils.time_format(
|
||||||
specs['created_at'])
|
specs['created_at'])
|
||||||
|
|
||||||
res = qos_specs.get_all_specs(self.ctxt)
|
res = qos_specs.get_all_specs(self.ctxt)
|
||||||
|
|
|
@ -33,6 +33,7 @@ from cinder import exception
|
||||||
from cinder import test
|
from cinder import test
|
||||||
from cinder.tests.unit import fake_constants as fake
|
from cinder.tests.unit import fake_constants as fake
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
|
from cinder.volume import utils as volume_utils
|
||||||
|
|
||||||
POOL_CAPS = {'total_capacity_gb': 0,
|
POOL_CAPS = {'total_capacity_gb': 0,
|
||||||
'free_capacity_gb': 0,
|
'free_capacity_gb': 0,
|
||||||
|
@ -124,26 +125,26 @@ class GenericUtilsTestCase(test.TestCase):
|
||||||
def test_hostname_unicode_sanitization(self):
|
def test_hostname_unicode_sanitization(self):
|
||||||
hostname = u"\u7684.test.example.com"
|
hostname = u"\u7684.test.example.com"
|
||||||
self.assertEqual("test.example.com",
|
self.assertEqual("test.example.com",
|
||||||
utils.sanitize_hostname(hostname))
|
volume_utils.sanitize_hostname(hostname))
|
||||||
|
|
||||||
def test_hostname_sanitize_periods(self):
|
def test_hostname_sanitize_periods(self):
|
||||||
hostname = "....test.example.com..."
|
hostname = "....test.example.com..."
|
||||||
self.assertEqual("test.example.com",
|
self.assertEqual("test.example.com",
|
||||||
utils.sanitize_hostname(hostname))
|
volume_utils.sanitize_hostname(hostname))
|
||||||
|
|
||||||
def test_hostname_sanitize_dashes(self):
|
def test_hostname_sanitize_dashes(self):
|
||||||
hostname = "----test.example.com---"
|
hostname = "----test.example.com---"
|
||||||
self.assertEqual("test.example.com",
|
self.assertEqual("test.example.com",
|
||||||
utils.sanitize_hostname(hostname))
|
volume_utils.sanitize_hostname(hostname))
|
||||||
|
|
||||||
def test_hostname_sanitize_characters(self):
|
def test_hostname_sanitize_characters(self):
|
||||||
hostname = "(#@&$!(@*--#&91)(__=+--test-host.example!!.com-0+"
|
hostname = "(#@&$!(@*--#&91)(__=+--test-host.example!!.com-0+"
|
||||||
self.assertEqual("91----test-host.example.com-0",
|
self.assertEqual("91----test-host.example.com-0",
|
||||||
utils.sanitize_hostname(hostname))
|
volume_utils.sanitize_hostname(hostname))
|
||||||
|
|
||||||
def test_hostname_translate(self):
|
def test_hostname_translate(self):
|
||||||
hostname = "<}\x1fh\x10e\x08l\x02l\x05o\x12!{>"
|
hostname = "<}\x1fh\x10e\x08l\x02l\x05o\x12!{>"
|
||||||
self.assertEqual("hello", utils.sanitize_hostname(hostname))
|
self.assertEqual("hello", volume_utils.sanitize_hostname(hostname))
|
||||||
|
|
||||||
@mock.patch('os.path.join', side_effect=lambda x, y: '/'.join((x, y)))
|
@mock.patch('os.path.join', side_effect=lambda x, y: '/'.join((x, y)))
|
||||||
def test_make_dev_path(self, mock_join):
|
def test_make_dev_path(self, mock_join):
|
||||||
|
@ -385,11 +386,11 @@ class WalkClassHierarchyTestCase(test.TestCase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class_pairs = zip((D, B, E),
|
class_pairs = zip((D, B, E),
|
||||||
utils.walk_class_hierarchy(A, encountered=[C]))
|
api_utils.walk_class_hierarchy(A, encountered=[C]))
|
||||||
for actual, expected in class_pairs:
|
for actual, expected in class_pairs:
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
class_pairs = zip((D, B, C, E), utils.walk_class_hierarchy(A))
|
class_pairs = zip((D, B, C, E), api_utils.walk_class_hierarchy(A))
|
||||||
for actual, expected in class_pairs:
|
for actual, expected in class_pairs:
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
|
|
@ -556,3 +556,19 @@ def set_timeout(timeout):
|
||||||
return _wrapper
|
return _wrapper
|
||||||
|
|
||||||
return _decorator
|
return _decorator
|
||||||
|
|
||||||
|
|
||||||
|
def time_format(at=None):
|
||||||
|
"""Format datetime string to date.
|
||||||
|
|
||||||
|
:param at: Type is datetime.datetime (example
|
||||||
|
'datetime.datetime(2017, 12, 24, 22, 11, 32, 6086)')
|
||||||
|
:returns: Format date (example '2017-12-24T22:11:32Z').
|
||||||
|
"""
|
||||||
|
if not at:
|
||||||
|
at = timeutils.utcnow()
|
||||||
|
date_string = at.strftime("%Y-%m-%dT%H:%M:%S")
|
||||||
|
tz = at.tzname(None) if at.tzinfo else 'UTC'
|
||||||
|
# Need to handle either iso8601 or python UTC format
|
||||||
|
date_string += ('Z' if tz in ['UTC', 'UTC+00:00'] else tz)
|
||||||
|
return date_string
|
||||||
|
|
|
@ -1055,7 +1055,7 @@ class NetAppCmodeClientTestCase(test.TestCase):
|
||||||
mock.call('qos-policy-group-delete-iter', api_args, False)])
|
mock.call('qos-policy-group-delete-iter', api_args, False)])
|
||||||
self.assertEqual(1, mock_log.call_count)
|
self.assertEqual(1, mock_log.call_count)
|
||||||
|
|
||||||
@mock.patch('cinder.utils.resolve_hostname',
|
@mock.patch('cinder.volume.utils.resolve_hostname',
|
||||||
return_value='192.168.1.101')
|
return_value='192.168.1.101')
|
||||||
def test_get_if_info_by_ip_not_found(self, mock_resolve_hostname):
|
def test_get_if_info_by_ip_not_found(self, mock_resolve_hostname):
|
||||||
fake_ip = '192.168.1.101'
|
fake_ip = '192.168.1.101'
|
||||||
|
@ -1070,7 +1070,7 @@ class NetAppCmodeClientTestCase(test.TestCase):
|
||||||
self.assertRaises(exception.NotFound, self.client.get_if_info_by_ip,
|
self.assertRaises(exception.NotFound, self.client.get_if_info_by_ip,
|
||||||
fake_ip)
|
fake_ip)
|
||||||
|
|
||||||
@mock.patch('cinder.utils.resolve_hostname',
|
@mock.patch('cinder.volume.utils.resolve_hostname',
|
||||||
return_value='192.168.1.101')
|
return_value='192.168.1.101')
|
||||||
def test_get_if_info_by_ip(self, mock_resolve_hostname):
|
def test_get_if_info_by_ip(self, mock_resolve_hostname):
|
||||||
fake_ip = '192.168.1.101'
|
fake_ip = '192.168.1.101'
|
||||||
|
|
|
@ -41,6 +41,7 @@ from cinder.volume.drivers.netapp.dataontap.utils import loopingcalls
|
||||||
from cinder.volume.drivers.netapp import utils as na_utils
|
from cinder.volume.drivers.netapp import utils as na_utils
|
||||||
from cinder.volume.drivers import nfs
|
from cinder.volume.drivers import nfs
|
||||||
from cinder.volume.drivers import remotefs
|
from cinder.volume.drivers import remotefs
|
||||||
|
from cinder.volume import utils as volume_utils
|
||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
|
@ -651,7 +652,7 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||||
fake.NFS_SHARE)
|
fake.NFS_SHARE)
|
||||||
|
|
||||||
def test_get_share_mount_and_vol_from_vol_ref(self):
|
def test_get_share_mount_and_vol_from_vol_ref(self):
|
||||||
self.mock_object(utils, 'resolve_hostname',
|
self.mock_object(volume_utils, 'resolve_hostname',
|
||||||
return_value='10.12.142.11')
|
return_value='10.12.142.11')
|
||||||
self.mock_object(os.path, 'isfile', return_value=True)
|
self.mock_object(os.path, 'isfile', return_value=True)
|
||||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||||
|
@ -669,7 +670,7 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||||
self.assertEqual('test_file_name', file_path)
|
self.assertEqual('test_file_name', file_path)
|
||||||
|
|
||||||
def test_get_share_mount_and_vol_from_vol_ref_with_bad_ref(self):
|
def test_get_share_mount_and_vol_from_vol_ref_with_bad_ref(self):
|
||||||
self.mock_object(utils, 'resolve_hostname',
|
self.mock_object(volume_utils, 'resolve_hostname',
|
||||||
return_value='10.12.142.11')
|
return_value='10.12.142.11')
|
||||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||||
vol_ref = {'source-id': '1234546'}
|
vol_ref = {'source-id': '1234546'}
|
||||||
|
@ -683,7 +684,7 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||||
vol_ref)
|
vol_ref)
|
||||||
|
|
||||||
def test_get_share_mount_and_vol_from_vol_ref_where_not_found(self):
|
def test_get_share_mount_and_vol_from_vol_ref_where_not_found(self):
|
||||||
self.mock_object(utils, 'resolve_hostname',
|
self.mock_object(volume_utils, 'resolve_hostname',
|
||||||
return_value='10.12.142.11')
|
return_value='10.12.142.11')
|
||||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||||
vol_path = "%s/%s" % (self.fake_nfs_export_2, 'test_file_name')
|
vol_path = "%s/%s" % (self.fake_nfs_export_2, 'test_file_name')
|
||||||
|
@ -698,7 +699,7 @@ class NetAppNfsDriverTestCase(test.TestCase):
|
||||||
vol_ref)
|
vol_ref)
|
||||||
|
|
||||||
def test_get_share_mount_and_vol_from_vol_ref_where_is_dir(self):
|
def test_get_share_mount_and_vol_from_vol_ref_where_is_dir(self):
|
||||||
self.mock_object(utils, 'resolve_hostname',
|
self.mock_object(volume_utils, 'resolve_hostname',
|
||||||
return_value='10.12.142.11')
|
return_value='10.12.142.11')
|
||||||
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
self.driver._mounted_shares = [self.fake_nfs_export_1]
|
||||||
vol_ref = {'source-name': self.fake_nfs_export_2}
|
vol_ref = {'source-name': self.fake_nfs_export_2}
|
||||||
|
|
|
@ -307,7 +307,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||||
self.driver.zapi_client, 'get_operational_lif_addresses',
|
self.driver.zapi_client, 'get_operational_lif_addresses',
|
||||||
return_value=[fake.SHARE_IP])
|
return_value=[fake.SHARE_IP])
|
||||||
mock_resolve_hostname = self.mock_object(
|
mock_resolve_hostname = self.mock_object(
|
||||||
utils, 'resolve_hostname', return_value=fake.SHARE_IP)
|
volume_utils, 'resolve_hostname', return_value=fake.SHARE_IP)
|
||||||
mock_get_flexvol = self.mock_object(
|
mock_get_flexvol = self.mock_object(
|
||||||
self.driver.zapi_client, 'get_flexvol',
|
self.driver.zapi_client, 'get_flexvol',
|
||||||
return_value={'name': fake.NETAPP_VOLUME})
|
return_value={'name': fake.NETAPP_VOLUME})
|
||||||
|
@ -330,7 +330,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||||
self.mock_object(self.driver.zapi_client,
|
self.mock_object(self.driver.zapi_client,
|
||||||
'get_operational_lif_addresses',
|
'get_operational_lif_addresses',
|
||||||
return_value=[])
|
return_value=[])
|
||||||
self.mock_object(utils,
|
self.mock_object(volume_utils,
|
||||||
'resolve_hostname',
|
'resolve_hostname',
|
||||||
return_value=fake.SHARE_IP)
|
return_value=fake.SHARE_IP)
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||||
self.mock_object(self.driver.zapi_client,
|
self.mock_object(self.driver.zapi_client,
|
||||||
'get_operational_lif_addresses',
|
'get_operational_lif_addresses',
|
||||||
return_value=[fake.SHARE_IP])
|
return_value=[fake.SHARE_IP])
|
||||||
self.mock_object(utils,
|
self.mock_object(volume_utils,
|
||||||
'resolve_hostname',
|
'resolve_hostname',
|
||||||
return_value=fake.SHARE_IP)
|
return_value=fake.SHARE_IP)
|
||||||
side_effect = exception.VolumeBackendAPIException(data='fake_data')
|
side_effect = exception.VolumeBackendAPIException(data='fake_data')
|
||||||
|
|
|
@ -32,7 +32,6 @@ import pyclbr
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import socket
|
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
@ -275,22 +274,6 @@ def last_completed_audit_period(unit=None):
|
||||||
return (begin, end)
|
return (begin, end)
|
||||||
|
|
||||||
|
|
||||||
def time_format(at=None):
|
|
||||||
"""Format datetime string to date.
|
|
||||||
|
|
||||||
:param at: Type is datetime.datetime (example
|
|
||||||
'datetime.datetime(2017, 12, 24, 22, 11, 32, 6086)')
|
|
||||||
:returns: Format date (example '2017-12-24T22:11:32Z').
|
|
||||||
"""
|
|
||||||
if not at:
|
|
||||||
at = timeutils.utcnow()
|
|
||||||
date_string = at.strftime("%Y-%m-%dT%H:%M:%S")
|
|
||||||
tz = at.tzname(None) if at.tzinfo else 'UTC'
|
|
||||||
# Need to handle either iso8601 or python UTC format
|
|
||||||
date_string += ('Z' if tz in ['UTC', 'UTC+00:00'] else tz)
|
|
||||||
return date_string
|
|
||||||
|
|
||||||
|
|
||||||
def monkey_patch():
|
def monkey_patch():
|
||||||
"""Patches decorators for all functions in a specified module.
|
"""Patches decorators for all functions in a specified module.
|
||||||
|
|
||||||
|
@ -353,23 +336,6 @@ def make_dev_path(dev, partition=None, base='/dev'):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
def sanitize_hostname(hostname):
|
|
||||||
"""Return a hostname which conforms to RFC-952 and RFC-1123 specs."""
|
|
||||||
if six.PY3:
|
|
||||||
hostname = hostname.encode('latin-1', 'ignore')
|
|
||||||
hostname = hostname.decode('latin-1')
|
|
||||||
else:
|
|
||||||
if isinstance(hostname, six.text_type):
|
|
||||||
hostname = hostname.encode('latin-1', 'ignore')
|
|
||||||
|
|
||||||
hostname = re.sub(r'[ _]', '-', hostname)
|
|
||||||
hostname = re.sub(r'[^\w.-]+', '', hostname)
|
|
||||||
hostname = hostname.lower()
|
|
||||||
hostname = hostname.strip('.-')
|
|
||||||
|
|
||||||
return hostname
|
|
||||||
|
|
||||||
|
|
||||||
def robust_file_write(directory, filename, data):
|
def robust_file_write(directory, filename, data):
|
||||||
"""Robust file write.
|
"""Robust file write.
|
||||||
|
|
||||||
|
@ -453,19 +419,6 @@ def tempdir(**kwargs):
|
||||||
six.text_type(e))
|
six.text_type(e))
|
||||||
|
|
||||||
|
|
||||||
def walk_class_hierarchy(clazz, encountered=None):
|
|
||||||
"""Walk class hierarchy, yielding most derived classes first."""
|
|
||||||
if not encountered:
|
|
||||||
encountered = []
|
|
||||||
for subclass in clazz.__subclasses__():
|
|
||||||
if subclass not in encountered:
|
|
||||||
encountered.append(subclass)
|
|
||||||
# drill down to leaves first
|
|
||||||
for subsubclass in walk_class_hierarchy(subclass, encountered):
|
|
||||||
yield subsubclass
|
|
||||||
yield subclass
|
|
||||||
|
|
||||||
|
|
||||||
def get_root_helper():
|
def get_root_helper():
|
||||||
return 'sudo cinder-rootwrap %s' % CONF.rootwrap_config
|
return 'sudo cinder-rootwrap %s' % CONF.rootwrap_config
|
||||||
|
|
||||||
|
@ -922,22 +875,6 @@ def setup_tracing(trace_flags):
|
||||||
TRACE_API = 'api' in trace_flags
|
TRACE_API = 'api' in trace_flags
|
||||||
|
|
||||||
|
|
||||||
def resolve_hostname(hostname):
|
|
||||||
"""Resolves host name to IP address.
|
|
||||||
|
|
||||||
Resolves a host name (my.data.point.com) to an IP address (10.12.143.11).
|
|
||||||
This routine also works if the data passed in hostname is already an IP.
|
|
||||||
In this case, the same IP address will be returned.
|
|
||||||
|
|
||||||
:param hostname: Host name to resolve.
|
|
||||||
:returns: IP Address for Host name.
|
|
||||||
"""
|
|
||||||
ip = socket.getaddrinfo(hostname, None)[0][4][0]
|
|
||||||
LOG.debug('Asked to resolve hostname %(host)s and got IP %(ip)s.',
|
|
||||||
{'host': hostname, 'ip': ip})
|
|
||||||
return ip
|
|
||||||
|
|
||||||
|
|
||||||
def build_or_str(elements, str_format=None):
|
def build_or_str(elements, str_format=None):
|
||||||
"""Builds a string of elements joined by 'or'.
|
"""Builds a string of elements joined by 'or'.
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ from cinder import utils
|
||||||
from cinder.volume.drivers.netapp.dataontap.client import api as netapp_api
|
from cinder.volume.drivers.netapp.dataontap.client import api as netapp_api
|
||||||
from cinder.volume.drivers.netapp.dataontap.client import client_base
|
from cinder.volume.drivers.netapp.dataontap.client import client_base
|
||||||
from cinder.volume.drivers.netapp import utils as na_utils
|
from cinder.volume.drivers.netapp import utils as na_utils
|
||||||
|
from cinder.volume import utils as volume_utils
|
||||||
|
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
|
|
||||||
|
@ -668,7 +669,7 @@ class Client(client_base.Client):
|
||||||
net_if_iter.add_child_elem(query)
|
net_if_iter.add_child_elem(query)
|
||||||
query.add_node_with_children(
|
query.add_node_with_children(
|
||||||
'net-interface-info',
|
'net-interface-info',
|
||||||
**{'address': utils.resolve_hostname(ip)})
|
**{'address': volume_utils.resolve_hostname(ip)})
|
||||||
result = self.connection.invoke_successfully(net_if_iter, True)
|
result = self.connection.invoke_successfully(net_if_iter, True)
|
||||||
num_records = result.get_child_content('num-records')
|
num_records = result.get_child_content('num-records')
|
||||||
if num_records and int(num_records) >= 1:
|
if num_records and int(num_records) >= 1:
|
||||||
|
|
|
@ -906,7 +906,7 @@ class NetAppNfsDriver(driver.ManageableVD,
|
||||||
# First strip out share and convert to IP format.
|
# First strip out share and convert to IP format.
|
||||||
share_split = vol_ref.rsplit(':', 1)
|
share_split = vol_ref.rsplit(':', 1)
|
||||||
|
|
||||||
vol_ref_share_ip = utils.resolve_hostname(share_split[0])
|
vol_ref_share_ip = volume_utils.resolve_hostname(share_split[0])
|
||||||
|
|
||||||
# Now place back into volume reference.
|
# Now place back into volume reference.
|
||||||
vol_ref_share = vol_ref_share_ip + ':' + share_split[1]
|
vol_ref_share = vol_ref_share_ip + ':' + share_split[1]
|
||||||
|
|
|
@ -327,7 +327,7 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver,
|
||||||
for share in self._mounted_shares:
|
for share in self._mounted_shares:
|
||||||
host, junction_path = na_utils.get_export_host_junction_path(share)
|
host, junction_path = na_utils.get_export_host_junction_path(share)
|
||||||
|
|
||||||
address = utils.resolve_hostname(host)
|
address = volume_utils.resolve_hostname(host)
|
||||||
|
|
||||||
if address not in vserver_addresses:
|
if address not in vserver_addresses:
|
||||||
LOG.warning('Address not found for NFS share %s.', share)
|
LOG.warning('Address not found for NFS share %s.', share)
|
||||||
|
@ -463,7 +463,7 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver,
|
||||||
|
|
||||||
def _get_ip_verify_on_cluster(self, host):
|
def _get_ip_verify_on_cluster(self, host):
|
||||||
"""Verifies if host on same cluster and returns ip."""
|
"""Verifies if host on same cluster and returns ip."""
|
||||||
ip = utils.resolve_hostname(host)
|
ip = volume_utils.resolve_hostname(host)
|
||||||
vserver = self._get_vserver_for_ip(ip)
|
vserver = self._get_vserver_for_ip(ip)
|
||||||
if not vserver:
|
if not vserver:
|
||||||
raise exception.NotFound(_("Unable to locate an SVM that is "
|
raise exception.NotFound(_("Unable to locate an SVM that is "
|
||||||
|
|
|
@ -263,7 +263,7 @@ class ZFSSAISCSIDriver(driver.ISCSIDriver):
|
||||||
|
|
||||||
# Lookup the zfssa_target_portal DNS name to an IP address
|
# Lookup the zfssa_target_portal DNS name to an IP address
|
||||||
host, port = lcfg.zfssa_target_portal.split(':')
|
host, port = lcfg.zfssa_target_portal.split(':')
|
||||||
host_ip_addr = utils.resolve_hostname(host)
|
host_ip_addr = volume_utils.resolve_hostname(host)
|
||||||
self.zfssa_target_portal = host_ip_addr + ':' + port
|
self.zfssa_target_portal = host_ip_addr + ':' + port
|
||||||
|
|
||||||
def check_for_setup_error(self):
|
def check_for_setup_error(self):
|
||||||
|
|
|
@ -1305,7 +1305,7 @@ class VolumeManager(manager.CleanableManager,
|
||||||
raise exception.InvalidVolume(
|
raise exception.InvalidVolume(
|
||||||
reason=_("being attached by different mode"))
|
reason=_("being attached by different mode"))
|
||||||
|
|
||||||
host_name_sanitized = utils.sanitize_hostname(
|
host_name_sanitized = vol_utils.sanitize_hostname(
|
||||||
host_name) if host_name else None
|
host_name) if host_name else None
|
||||||
if instance_uuid:
|
if instance_uuid:
|
||||||
attachments = (
|
attachments = (
|
||||||
|
|
|
@ -23,6 +23,7 @@ import operator
|
||||||
import os
|
import os
|
||||||
from os import urandom
|
from os import urandom
|
||||||
import re
|
import re
|
||||||
|
import socket
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
@ -1213,3 +1214,36 @@ def sanitize_host(host):
|
||||||
if netutils.is_valid_ipv6(host):
|
if netutils.is_valid_ipv6(host):
|
||||||
return '[%s]' % host
|
return '[%s]' % host
|
||||||
return host
|
return host
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize_hostname(hostname):
|
||||||
|
"""Return a hostname which conforms to RFC-952 and RFC-1123 specs."""
|
||||||
|
if six.PY3:
|
||||||
|
hostname = hostname.encode('latin-1', 'ignore')
|
||||||
|
hostname = hostname.decode('latin-1')
|
||||||
|
else:
|
||||||
|
if isinstance(hostname, six.text_type):
|
||||||
|
hostname = hostname.encode('latin-1', 'ignore')
|
||||||
|
|
||||||
|
hostname = re.sub(r'[ _]', '-', hostname)
|
||||||
|
hostname = re.sub(r'[^\w.-]+', '', hostname)
|
||||||
|
hostname = hostname.lower()
|
||||||
|
hostname = hostname.strip('.-')
|
||||||
|
|
||||||
|
return hostname
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_hostname(hostname):
|
||||||
|
"""Resolves host name to IP address.
|
||||||
|
|
||||||
|
Resolves a host name (my.data.point.com) to an IP address (10.12.143.11).
|
||||||
|
This routine also works if the data passed in hostname is already an IP.
|
||||||
|
In this case, the same IP address will be returned.
|
||||||
|
|
||||||
|
:param hostname: Host name to resolve.
|
||||||
|
:returns: IP Address for Host name.
|
||||||
|
"""
|
||||||
|
ip = socket.getaddrinfo(hostname, None)[0][4][0]
|
||||||
|
LOG.debug('Asked to resolve hostname %(host)s and got IP %(ip)s.',
|
||||||
|
{'host': hostname, 'ip': ip})
|
||||||
|
return ip
|
||||||
|
|
Loading…
Reference in New Issue