747efde470
The iSCSI and Fibre Channel volume drivers for DataCore’s SANsymphony and Hyper-converged Virtual SAN storage support the core/minimum feature set: - Volume Create/Delete - Volume Attach/Detach - Snapshot Create/Delete - Create Volume from Snapshot - Get Volume Stats - Copy Image to Volume - Copy Volume to Image - Clone Volume - Extend Volume DocImpact Implements: blueprint datacore-volume-driver Change-Id: I3308bdedbfe3bb83d695d38667eaea6327fa4461
74 lines
2.6 KiB
Python
74 lines
2.6 KiB
Python
# Copyright (c) 2017 DataCore Software Corp. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
"""Utilities and helper functions."""
|
|
|
|
from oslo_utils import netutils
|
|
import six
|
|
|
|
|
|
def build_network_address(host, port):
|
|
"""Combines the specified host name or IP address with the specified port.
|
|
|
|
:param host: Host name or IP address in presentation (string) format
|
|
:param port: Port number
|
|
:return: The host name or IP address and port combination;
|
|
IPv6 addresses are enclosed in the square brackets
|
|
"""
|
|
if netutils.is_valid_ipv6(host):
|
|
return '[%s]:%s' % (host, port)
|
|
else:
|
|
return '%s:%s' % (host, port)
|
|
|
|
|
|
def get_first(predicate, source):
|
|
"""Searches for an item that matches the conditions.
|
|
|
|
:param predicate: Defines the conditions of the item to search for
|
|
:param source: Iterable collection of items
|
|
:return: The first item that matches the conditions defined by the
|
|
specified predicate, if found; otherwise StopIteration is raised
|
|
"""
|
|
|
|
return six.next(item for item in source if predicate(item))
|
|
|
|
|
|
def get_first_or_default(predicate, source, default):
|
|
"""Searches for an item that matches the conditions.
|
|
|
|
:param predicate: Defines the conditions of the item to search for
|
|
:param source: Iterable collection of items
|
|
:param default: Value that is returned if the iterator is exhausted
|
|
:return: The first item that matches the conditions defined by the
|
|
specified predicate, if found; otherwise the default value
|
|
"""
|
|
|
|
try:
|
|
return get_first(predicate, source)
|
|
except StopIteration:
|
|
return default
|
|
|
|
|
|
def get_distinct_by(key, source):
|
|
"""Finds distinct items for the key and returns the result in a list.
|
|
|
|
:param key: Function computing a key value for each item
|
|
:param source: Iterable collection of items
|
|
:return: The list of distinct by the key value items
|
|
"""
|
|
|
|
seen_keys = set()
|
|
return [item for item in source
|
|
if key(item) not in seen_keys and not seen_keys.add(key(item))]
|