|
|
|
@ -18,7 +18,6 @@
|
|
|
|
|
|
|
|
|
|
"""Utilities and helper functions."""
|
|
|
|
|
|
|
|
|
|
import collections
|
|
|
|
|
import decimal
|
|
|
|
|
import errno
|
|
|
|
|
import functools
|
|
|
|
@ -34,10 +33,12 @@ import tempfile
|
|
|
|
|
import time
|
|
|
|
|
import uuid
|
|
|
|
|
|
|
|
|
|
from debtcollector import removals
|
|
|
|
|
import eventlet
|
|
|
|
|
from eventlet.green import subprocess
|
|
|
|
|
import netaddr
|
|
|
|
|
from neutron_lib import constants as n_const
|
|
|
|
|
from neutron_lib.utils import helpers
|
|
|
|
|
from oslo_concurrency import lockutils
|
|
|
|
|
from oslo_config import cfg
|
|
|
|
|
from oslo_db import exception as db_exc
|
|
|
|
@ -82,44 +83,13 @@ def subprocess_popen(args, stdin=None, stdout=None, stderr=None, shell=False,
|
|
|
|
|
close_fds=close_fds, env=env)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@removals.remove(
|
|
|
|
|
message="Use parse_mappings from neutron_lib.utils.helpers",
|
|
|
|
|
version="Ocata",
|
|
|
|
|
removal_version="Pike")
|
|
|
|
|
def parse_mappings(mapping_list, unique_values=True, unique_keys=True):
|
|
|
|
|
"""Parse a list of mapping strings into a dictionary.
|
|
|
|
|
|
|
|
|
|
:param mapping_list: a list of strings of the form '<key>:<value>'
|
|
|
|
|
:param unique_values: values must be unique if True
|
|
|
|
|
:param unique_keys: keys must be unique if True, else implies that keys
|
|
|
|
|
and values are not unique
|
|
|
|
|
:returns: a dict mapping keys to values or to list of values
|
|
|
|
|
"""
|
|
|
|
|
mappings = {}
|
|
|
|
|
for mapping in mapping_list:
|
|
|
|
|
mapping = mapping.strip()
|
|
|
|
|
if not mapping:
|
|
|
|
|
continue
|
|
|
|
|
split_result = mapping.split(':')
|
|
|
|
|
if len(split_result) != 2:
|
|
|
|
|
raise ValueError(_("Invalid mapping: '%s'") % mapping)
|
|
|
|
|
key = split_result[0].strip()
|
|
|
|
|
if not key:
|
|
|
|
|
raise ValueError(_("Missing key in mapping: '%s'") % mapping)
|
|
|
|
|
value = split_result[1].strip()
|
|
|
|
|
if not value:
|
|
|
|
|
raise ValueError(_("Missing value in mapping: '%s'") % mapping)
|
|
|
|
|
if unique_keys:
|
|
|
|
|
if key in mappings:
|
|
|
|
|
raise ValueError(_("Key %(key)s in mapping: '%(mapping)s' not "
|
|
|
|
|
"unique") % {'key': key,
|
|
|
|
|
'mapping': mapping})
|
|
|
|
|
if unique_values and value in mappings.values():
|
|
|
|
|
raise ValueError(_("Value %(value)s in mapping: '%(mapping)s' "
|
|
|
|
|
"not unique") % {'value': value,
|
|
|
|
|
'mapping': mapping})
|
|
|
|
|
mappings[key] = value
|
|
|
|
|
else:
|
|
|
|
|
mappings.setdefault(key, [])
|
|
|
|
|
if value not in mappings[key]:
|
|
|
|
|
mappings[key].append(value)
|
|
|
|
|
return mappings
|
|
|
|
|
return helpers.parse_mappings(mapping_list, unique_values=unique_values,
|
|
|
|
|
unique_keys=unique_keys)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_hostname():
|
|
|
|
@ -130,23 +100,20 @@ def get_first_host_ip(net, ip_version):
|
|
|
|
|
return str(netaddr.IPAddress(net.first + 1, ip_version))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@removals.remove(
|
|
|
|
|
message="Use compare_elements from neutron_lib.utils.helpers",
|
|
|
|
|
version="Ocata",
|
|
|
|
|
removal_version="Pike")
|
|
|
|
|
def compare_elements(a, b):
|
|
|
|
|
"""Compare elements if a and b have same elements.
|
|
|
|
|
|
|
|
|
|
This method doesn't consider ordering
|
|
|
|
|
"""
|
|
|
|
|
if a is None:
|
|
|
|
|
a = []
|
|
|
|
|
if b is None:
|
|
|
|
|
b = []
|
|
|
|
|
return set(a) == set(b)
|
|
|
|
|
return helpers.compare_elements(a, b)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@removals.remove(
|
|
|
|
|
message="Use safe_sort_key from neutron_lib.utils.helpers",
|
|
|
|
|
version="Ocata",
|
|
|
|
|
removal_version="Pike")
|
|
|
|
|
def safe_sort_key(value):
|
|
|
|
|
"""Return value hash or build one for dictionaries."""
|
|
|
|
|
if isinstance(value, collections.Mapping):
|
|
|
|
|
return sorted(value.items())
|
|
|
|
|
return value
|
|
|
|
|
return helpers.safe_sort_key(value)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def dict2str(dic):
|
|
|
|
|