**** CubicPower OpenStack Study ****
def provide_ems(requester, server, stats, netapp_backend,
server_type="cluster"):
"""Provide ems with volume stats for the requester.
:param server_type: cluster or 7mode.
"""
def _create_ems(stats, netapp_backend, server_type):
"""Create ems api request."""
ems_log = NaElement('ems-autosupport-log')
host = socket.getfqdn() or 'Cinder_node'
dest = "cluster node" if server_type == "cluster"\
else "7 mode controller"
ems_log.add_new_child('computer-name', host)
ems_log.add_new_child('event-id', '0')
ems_log.add_new_child('event-source',
'Cinder driver %s' % netapp_backend)
ems_log.add_new_child('app-version', stats.get('driver_version',
'Undefined'))
ems_log.add_new_child('category', 'provisioning')
ems_log.add_new_child('event-description',
'OpenStack volume created on %s' % dest)
ems_log.add_new_child('log-level', '6')
ems_log.add_new_child('auto-support', 'true')
return ems_log
def _create_vs_get():
"""Create vs_get api request."""
vs_get = NaElement('vserver-get-iter')
vs_get.add_new_child('max-records', '1')
query = NaElement('query')
query.add_node_with_children('vserver-info',
**{'vserver-type': 'node'})
vs_get.add_child_elem(query)
desired = NaElement('desired-attributes')
desired.add_node_with_children(
'vserver-info', **{'vserver-name': '', 'vserver-type': ''})
vs_get.add_child_elem(desired)
return vs_get
def _get_cluster_node(na_server):
"""Get the cluster node for ems."""
na_server.set_vserver(None)
vs_get = _create_vs_get()
res = na_server.invoke_successfully(vs_get)
if (res.get_child_content('num-records') and
int(res.get_child_content('num-records')) > 0):
attr_list = res.get_child_by_name('attributes-list')
vs_info = attr_list.get_child_by_name('vserver-info')
vs_name = vs_info.get_child_content('vserver-name')
return vs_name
return None
do_ems = True
if hasattr(requester, 'last_ems'):
sec_limit = 604800
if not (timeutils.is_older_than(requester.last_ems, sec_limit) or
timeutils.is_older_than(requester.last_ems, sec_limit - 59)):
do_ems = False
if do_ems:
na_server = copy.copy(server)
na_server.set_timeout(25)
ems = _create_ems(stats, netapp_backend, server_type)
try:
if server_type == "cluster":
api_version = na_server.get_api_version()
if api_version:
major, minor = api_version
else:
raise NaApiError(code='Not found',
message='No api version found')
if major == 1 and minor > 15:
node = getattr(requester, 'vserver', None)
else:
node = _get_cluster_node(na_server)
if node is None:
raise NaApiError(code='Not found',
message='No vserver found')
na_server.set_vserver(node)
else:
na_server.set_vfiler(None)
na_server.invoke_successfully(ems, True)
LOG.debug(_("ems executed successfully."))
except NaApiError as e:
LOG.warn(_("Failed to invoke ems. Message : %s") % e)
finally:
requester.last_ems = timeutils.utcnow()
**** CubicPower OpenStack Study ****
def validate_instantiation(**kwargs):
"""Checks if a driver is instantiated other than by the unified driver.
Helps check direct instantiation of netapp drivers.
Call this function in every netapp block driver constructor.
"""
if kwargs and kwargs.get('netapp_mode') == 'proxy':
return
LOG.warn(_("It is not the recommended way to use drivers by NetApp. "
"Please use NetAppDriver to achieve the functionality."))
**** CubicPower OpenStack Study ****
def invoke_api(na_server, api_name, api_family='cm', query=None,
des_result=None, additional_elems=None,
is_iter=False, records=0, tag=None,
timeout=0, tunnel=None):
"""Invokes any given api call to a NetApp server.
:param na_server: na_server instance
:param api_name: api name string
:param api_family: cm or 7m
:param query: api query as dict
:param des_result: desired result as dict
:param additional_elems: dict other than query and des_result
:param is_iter: is iterator api
:param records: limit for records, 0 for infinite
:param timeout: timeout seconds
:param tunnel: tunnel entity, vserver or vfiler name
"""
record_step = 50
if not (na_server or isinstance(na_server, NaServer)):
msg = _("Requires an NaServer instance.")
raise exception.InvalidInput(reason=msg)
server = copy.copy(na_server)
if api_family == 'cm':
server.set_vserver(tunnel)
else:
server.set_vfiler(tunnel)
if timeout > 0:
server.set_timeout(timeout)
iter_records = 0
cond = True
while cond:
na_element = create_api_request(
api_name, query, des_result, additional_elems,
is_iter, record_step, tag)
result = server.invoke_successfully(na_element, True)
if is_iter:
if records > 0:
iter_records = iter_records + record_step
if iter_records >= records:
cond = False
tag_el = result.get_child_by_name('next-tag')
tag = tag_el.get_content() if tag_el else None
if not tag:
cond = False
else:
cond = False
yield result
**** CubicPower OpenStack Study ****
def create_api_request(api_name, query=None, des_result=None,
additional_elems=None, is_iter=False,
record_step=50, tag=None):
"""Creates a NetApp api request.
:param api_name: api name string
:param query: api query as dict
:param des_result: desired result as dict
:param additional_elems: dict other than query and des_result
:param is_iter: is iterator api
:param record_step: records at a time for iter api
:param tag: next tag for iter api
"""
api_el = NaElement(api_name)
if query:
query_el = NaElement('query')
query_el.translate_struct(query)
api_el.add_child_elem(query_el)
if des_result:
res_el = NaElement('desired-attributes')
res_el.translate_struct(des_result)
api_el.add_child_elem(res_el)
if additional_elems:
api_el.translate_struct(additional_elems)
if is_iter:
api_el.add_new_child('max-records', str(record_step))
if tag:
api_el.add_new_child('tag', tag, True)
return api_el
**** CubicPower OpenStack Study ****
def to_bool(val):
"""Converts true, yes, y, 1 to True, False otherwise."""
if val:
strg = str(val).lower()
if (strg == 'true' or strg == 'y'
or strg == 'yes' or strg == 'enabled'
or strg == '1'):
return True
else:
return False
else:
return False
@utils.synchronized("safe_set_attr")
**** CubicPower OpenStack Study ****
def set_safe_attr(instance, attr, val):
"""Sets the attribute in a thread safe manner.
Returns if new val was set on attribute.
If attr already had the value then False.
"""
if not instance or not attr:
return False
old_val = getattr(instance, attr, None)
if val is None and old_val is None:
return False
elif val == old_val:
return False
else:
setattr(instance, attr, val)
return True
**** CubicPower OpenStack Study ****
def get_volume_extra_specs(volume):
"""Provides extra specs associated with volume."""
ctxt = context.get_admin_context()
type_id = volume.get('volume_type_id')
specs = None
if type_id is not None:
volume_type = volume_types.get_volume_type(ctxt, type_id)
specs = volume_type.get('extra_specs')
return specs
**** CubicPower OpenStack Study ****
def check_apis_on_cluster(na_server, api_list=[]):
"""Checks api availability and permissions on cluster.
Checks api availability and permissions for executing user.
Returns a list of failed apis.
"""
failed_apis = []
if api_list:
api_version = na_server.get_api_version()
if api_version:
major, minor = api_version
if major == 1 and minor < 20:
for api_name in api_list:
na_el = NaElement(api_name)
try:
na_server.invoke_successfully(na_el)
except Exception as e:
if isinstance(e, NaApiError):
if (e.code == NaErrors['API_NOT_FOUND'].code or
e.code ==
NaErrors['INSUFFICIENT_PRIVS'].code):
failed_apis.append(api_name)
elif major == 1 and minor >= 20:
failed_apis = copy.copy(api_list)
result = invoke_api(
na_server,
api_name='system-user-capability-get-iter',
api_family='cm',
additional_elems=None,
is_iter=True)
for res in result:
attr_list = res.get_child_by_name('attributes-list')
if attr_list:
capabilities = attr_list.get_children()
for capability in capabilities:
op_list = capability.get_child_by_name(
'operation-list')
if op_list:
ops = op_list.get_children()
for op in ops:
apis = op.get_child_content('api-name')
if apis:
api_list = apis.split(',')
for api_name in api_list:
if (api_name and
api_name.strip()
in failed_apis):
failed_apis.remove(api_name)
else:
continue
else:
msg = _("Unsupported Clustered Data ONTAP version.")
raise exception.VolumeBackendAPIException(data=msg)
else:
msg = _("Api version could not be determined.")
raise exception.VolumeBackendAPIException(data=msg)
return failed_apis
**** CubicPower OpenStack Study ****
def resolve_hostname(hostname):
"""Resolves host name to IP address."""
res = socket.getaddrinfo(hostname, None)[0]
family, socktype, proto, canonname, sockaddr = res
return sockaddr[0]
**** CubicPower OpenStack Study ****
def encode_hex_to_base32(hex_string):
"""Encodes hex to base32 bit as per RFC4648."""
bin_form = binascii.unhexlify(hex_string)
return base64.b32encode(bin_form)
**** CubicPower OpenStack Study ****
def decode_base32_to_hex(base32_string):
"""Decodes base32 string to hex string."""
bin_form = base64.b32decode(base32_string)
return binascii.hexlify(bin_form)
**** CubicPower OpenStack Study ****
def convert_uuid_to_es_fmt(uuid_str):
"""Converts uuid to e-series compatible name format."""
uuid_base32 = encode_hex_to_base32(uuid.UUID(str(uuid_str)).hex)
return uuid_base32.strip('=')
**** CubicPower OpenStack Study ****
def convert_es_fmt_to_uuid(es_label):
"""Converts e-series name format to uuid."""
es_label_b32 = es_label.ljust(32, '=')
return uuid.UUID(binascii.hexlify(base64.b32decode(es_label_b32)))