Skip to content

Commit

Permalink
Merge a0c908f into 763cc25
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardogpsf committed Oct 8, 2018
2 parents 763cc25 + a0c908f commit 9dec300
Show file tree
Hide file tree
Showing 7 changed files with 542 additions and 26 deletions.
8 changes: 6 additions & 2 deletions oneview_redfish_toolkit/blueprints/resource_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@
from oneview_redfish_toolkit.services.manager_service import \
get_manager_uuid
from oneview_redfish_toolkit.services.zone_service import ZoneService
from oneview_redfish_toolkit.single_oneview_context import single_oneview

resource_block = Blueprint("resource_block", __name__)


@resource_block.route(ResourceBlock.BASE_URI + "/<uuid>", methods=["GET"])
@single_oneview
def get_resource_block(uuid):
"""Get the Redfish ResourceBlock for a given UUID.
Expand Down Expand Up @@ -104,6 +106,7 @@ def get_resource_block(uuid):

@resource_block.route(
ResourceBlock.BASE_URI + "/<uuid>/Systems/1", methods=["GET"])
@single_oneview
def get_resource_block_computer_system(uuid):
"""Get Computer System of a Resource Block
Expand All @@ -129,6 +132,7 @@ def get_resource_block_computer_system(uuid):
@resource_block.route(
ResourceBlock.BASE_URI + "/<uuid>/EthernetInterfaces/<id>",
methods=["GET"])
@single_oneview
def get_resource_block_ethernet_interface(uuid, id):
"""Get the Redfish ResourceBlock of type Network for the given UUID and ID.
Expand All @@ -144,10 +148,10 @@ def get_resource_block_ethernet_interface(uuid, id):
server_profile_template = \
g.oneview_client.server_profile_templates.get(uuid)

connSettings = server_profile_template["connectionSettings"]
conn_settings = server_profile_template["connectionSettings"]
connection = None

for conn in connSettings["connections"]:
for conn in conn_settings["connections"]:
if str(conn["id"]) == id:
connection = conn
break
Expand Down
97 changes: 81 additions & 16 deletions oneview_redfish_toolkit/multiple_oneview.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,49 @@
from oneview_redfish_toolkit import client_session
from oneview_redfish_toolkit import config
from oneview_redfish_toolkit.config import PERFORMANCE_LOGGER_NAME
from oneview_redfish_toolkit import single_oneview_context as single

# Globals vars:
# globals()['map_resources_ov']


lock = threading.Lock()


def init_map_resources():
"""Initialize cached resources map"""
globals()['map_resources_ov'] = OrderedDict()


def init_map_appliances():
"""Initialize cached appliances map"""
globals()['map_appliances_ov'] = OrderedDict()


def get_map_resources():
"""Get cached resources map"""
return globals()['map_resources_ov']


def get_map_appliances():
"""Get cached appliances map"""
return globals()['map_appliances_ov']


def set_map_resources_entry(resource_id, ip_oneview):
lock = threading.Lock()
"""Set new cached resource"""
with lock:
get_map_resources()[resource_id] = ip_oneview


def cleanup_map_resources_entry(resource_id):
with lock:
if resource_id in get_map_resources().keys():
del get_map_resources()[resource_id]


def set_map_appliances_entry(ip_oneview, appliance_uuid):
"""Set new cached appliance"""
get_map_appliances()[ip_oneview] = appliance_uuid


Expand All @@ -67,23 +82,56 @@ def query_ov_client_by_resource(resource_id, resource, function,
Query specific resource ID on multiple OneViews.
Look resource ID on cached map ResourceID->OneViewIP for query
on specific cached OneView IP.
If the resource ID is not cached yet it searchs on all OneViews.
If the resource ID is not cached yet it searches on all OneViews.
Returns:
dict: OneView resource
"""
# Get cached OneView IP by resource ID
ip_oneview = get_ov_ip_by_resource(resource_id)
# Get OneView's IP in the single OneView context
single_oneview_ip = single.is_single_oneview_context() and \
single.get_single_oneview_ip()
# Get OneView's IP for cached resource ID
cached_oneview_ip = get_ov_ip_by_resource(resource_id)

# Get OneView's IP in the single OneView context or cached by resource ID
ip_oneview = single_oneview_ip or cached_oneview_ip

# If resource is not cached yet search in all OneViews
if not ip_oneview:
return search_resource_multiple_ov(resource, function, resource_id,
*args, **kwargs)
None, *args, **kwargs)

# If it's Single Oneview context and no IP is saved on context yet
if single.is_single_oneview_context() and not single_oneview_ip:
single.set_single_oneview_ip(ip_oneview)

ov_client = client_session.get_oneview_client(ip_oneview)
try:
resp = execute_query_ov_client(ov_client, resource, function,
*args, **kwargs)
except HPOneViewException as e:
if e.oneview_response["errorCode"] not in NOT_FOUND_ONEVIEW_ERRORS:
raise

return execute_query_ov_client(ov_client, resource, function,
*args, **kwargs)
cleanup_map_resources_entry(resource_id)
ov_ips = config.get_oneview_multiple_ips()
ov_ips.remove(ip_oneview) # just search in the other ips

if not ov_ips:
raise

return search_resource_multiple_ov(resource, function,
resource_id,
ov_ips, *args,
**kwargs)

# If it's on Single OneView Context and the resource is not
# mapped to an OneView IP, then we update cache in advance for
# future requests for this resource
if single_oneview_ip and not cached_oneview_ip:
set_map_resources_entry(resource_id, single_oneview_ip)

return resp


def get_ov_ip_by_resource(resource_id):
Expand All @@ -93,7 +141,7 @@ def get_ov_ip_by_resource(resource_id):
return map_resources.get(resource_id)


def search_resource_multiple_ov(resource, function, resource_id,
def search_resource_multiple_ov(resource, function, resource_id, ov_ips,
*args, **kwargs):
"""Search resource on multiple OneViews
Expand All @@ -110,6 +158,8 @@ def search_resource_multiple_ov(resource, function, resource_id,
resource: resource type (server_hardware)
function: resource function name (get_all)
resource_id: set only if it should look for a specific resource ID
ov_ips: List of Oneview IPs to search the resource. If None is
passed, the the list of IPs will be all IPs configured
*args: original arguments for the OneView client query
**kwargs: original keyword arguments for the OneView client query
Expand All @@ -125,9 +175,18 @@ def search_resource_multiple_ov(resource, function, resource_id,
"""
result = []
error_not_found = []
single_oneview_ip = single.is_single_oneview_context() and \
single.get_single_oneview_ip()

# If it's on Single Oneview Context and there is already an OneView IP
# on the context, then uses it. If not search on All OneViews
if not ov_ips and single_oneview_ip:
list_ov_ips = [single_oneview_ip]
else:
list_ov_ips = ov_ips or config.get_oneview_multiple_ips()

# Loop in all OneView's IP
for ov_ip in config.get_oneview_multiple_ips():
for ov_ip in list_ov_ips:

ov_client = client_session.get_oneview_client(ov_ip)

Expand All @@ -141,22 +200,30 @@ def search_resource_multiple_ov(resource, function, resource_id,
# If it's looking for a especific resource and was found
if resource_id:
set_map_resources_entry(resource_id, ov_ip)

# If it's SingleOneviewContext and there is no OneView IP
# on the context, then set OneView's IP on the context
if single.is_single_oneview_context() and \
not single_oneview_ip:
single.set_single_oneview_ip(ov_ip)

return expected_resource
else:
# If it's looking for a resource list (get_all)
if isinstance(expected_resource, list):
result.extend(expected_resource)
else:
result.append(expected_resource)
except HPOneViewException as e:
except HPOneViewException as exception:
# If get any error that is not a notFoundError
if e.oneview_response["errorCode"] not in NOT_FOUND_ONEVIEW_ERRORS:
if exception.oneview_response["errorCode"] not in \
NOT_FOUND_ONEVIEW_ERRORS:
logging.exception("Error while searching on multiple "
"OneViews for Oneview {}: {}".
format(ov_ip, e))
raise e
format(ov_ip, exception))
raise exception

error_not_found.append(e)
error_not_found.append(exception)

# If it's looking for a specific resource returns a NotFound exception
if resource_id and error_not_found:
Expand All @@ -176,8 +243,6 @@ def execute_query_ov_client(ov_client, resource, function, *args, **kwargs):
try:
result = ov_function(*args, **kwargs)
return result
except Exception as e:
raise e
finally:
elapsed_time = time.time() - start_time

Expand Down
62 changes: 62 additions & 0 deletions oneview_redfish_toolkit/single_oneview_context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-

# Copyright (2018) Hewlett Packard Enterprise Development LP
#
# 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.

# Python libs
import logging
import threading

# 3rd party libs
from flask import g

# Modules own libs
from oneview_redfish_toolkit.config import PERFORMANCE_LOGGER_NAME


def single_oneview(original_func):
"""Python decorator for endpoints with single OneView context"""
def new_function(*args, **kwargs):
"""Function to set single OneView context"""
logging.getLogger(PERFORMANCE_LOGGER_NAME).debug(
"Thread {} in Single OneView Context".
format(threading.get_ident()))
set_single_oneview_context()
return original_func(*args, **kwargs)

new_function.__name__ = original_func.__name__
return new_function


def set_single_oneview_context():
"""Set to use the same OneView IP in the same request"""
g.single_oneview_context = True


def is_single_oneview_context():
"""Check if it ot be used the same OneView IP on the request context"""
return 'single_oneview_context' in g


def get_single_oneview_ip():
"""Get the same OneView's IP in request context"""
if 'single_oneview_ip' in g:
return g.single_oneview_ip
return None


def set_single_oneview_ip(oneview_ip):
"""Set OneView's IP to be used in the same request context"""
if not get_single_oneview_ip():
g.single_oneview_ip = oneview_ip
4 changes: 3 additions & 1 deletion oneview_redfish_toolkit/strategy_multiple_oneview.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ def filter_uuid_parameter_resource(resource, function, *args, **kwargs):

def all_oneviews_resource(resource, function, *args, **kwargs):
all_results = multiple_oneview.search_resource_multiple_ov(resource,
function, None,
function,
None,
None,
*args,
**kwargs)

Expand Down
27 changes: 22 additions & 5 deletions oneview_redfish_toolkit/tests/blueprints/test_chassis.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,17 @@ def test_get_enclosure_chassis(self, get_map_appliances,
"{}{}".format("W/", self.enclosure["eTag"]),
response.headers["ETag"])

@mock.patch.object(multiple_oneview, 'config')
@mock.patch.object(multiple_oneview, 'get_map_resources')
@mock.patch.object(multiple_oneview, 'get_map_appliances')
def test_get_enclosure_not_found(self, get_map_appliances,
get_map_resources):
def test_get_enclosure_not_found(self,
get_map_appliances,
get_map_resources,
config_mock):
"""Tests EnclosureChassis with Enclosure not found"""

config_mock.get_oneview_multiple_ips.return_value = ['10.0.0.1']

get_map_resources.return_value = OrderedDict({
"0000000000A66101": "10.0.0.1",
})
Expand All @@ -168,12 +173,16 @@ def test_get_enclosure_not_found(self, get_map_appliances,
self.assertEqual(status.HTTP_404_NOT_FOUND, response.status_code)
self.assertEqual("application/json", response.mimetype)

@mock.patch.object(multiple_oneview, 'config')
@mock.patch.object(multiple_oneview, 'get_map_resources')
@mock.patch.object(multiple_oneview, 'get_map_appliances')
def test_get_enclosure_env_config_not_found(self, get_map_appliances,
get_map_resources):
get_map_resources,
config_mock):
"""Tests EnclosureChassis with Enclosure env_config not found"""

config_mock.get_oneview_multiple_ips.return_value = ['10.0.0.1']

get_map_resources.return_value = OrderedDict({
"0000000000A66101": "10.0.0.1",
})
Expand Down Expand Up @@ -366,12 +375,16 @@ def test_get_blade_chassis_with_computer_system(self,
"{}{}".format("W/", self.server_hardware["eTag"]),
response.headers["ETag"])

@mock.patch.object(multiple_oneview, 'config')
@mock.patch.object(multiple_oneview, 'get_map_resources')
@mock.patch.object(multiple_oneview, 'get_map_appliances')
def test_get_server_hardware_not_found(self, get_map_appliances,
get_map_resources):
get_map_resources,
config_mock):
"""Tests BladeChassis with Server Hardware not found"""

config_mock.get_oneview_multiple_ips.return_value = ['10.0.0.1']

self.oneview_client.index_resources.get_all.return_value = [
{"category": "server-hardware"}]
self.oneview_client.server_hardware.get.return_value =\
Expand Down Expand Up @@ -495,11 +508,15 @@ def test_get_rack_chassis(self, get_map_appliances, get_map_resources):
"{}{}".format("W/", self.rack["eTag"]),
response.headers["ETag"])

@mock.patch.object(multiple_oneview, 'config')
@mock.patch.object(multiple_oneview, 'get_map_resources')
@mock.patch.object(multiple_oneview, 'get_map_appliances')
def test_get_rack_not_found(self, get_map_appliances, get_map_resources):
def test_get_rack_not_found(self, get_map_appliances, get_map_resources,
config_mock):
"""Tests RackChassis with Racks not found"""

config_mock.get_oneview_multiple_ips.return_value = ['10.0.0.1']

get_map_resources.return_value = OrderedDict({
"2AB100LMNB": "10.0.0.1",
})
Expand Down
Loading

0 comments on commit 9dec300

Please sign in to comment.