Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
Merge pull request #313 from HewlettPackard/new-resource/index-resource
Browse files Browse the repository at this point in the history
Fixed #312
  • Loading branch information
fgbulsoni authored Sep 13, 2017
2 parents e97fcd5 + 570593c commit 88f7b6b
Show file tree
Hide file tree
Showing 9 changed files with 351 additions and 6 deletions.
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# v4.1.0
# v4.2.0
#### New Resources:
- Index resource

#### Bug fixes & Enhancements
- [#312](https://github.com/HewlettPackard/python-hpOneView/issues/312) Could not find mappings for OneView's Index Resources

# v4.1.0
#### New Resources:
- Appliance node information
- Appliance node information

#### Bug fixes & Enhancements
- [#309](https://github.com/HewlettPackard/python-hpOneView/issues/309) HPOneViewException not raised when connection with paused VM fails
Expand Down
55 changes: 55 additions & 0 deletions examples/index_resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
###
# (C) Copyright (2012-2017) Hewlett Packard Enterprise Development LP
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
###
from pprint import pprint

from hpOneView.oneview_client import OneViewClient
from config_loader import try_load_from_file

config = {
"ip": "<oneview_ip>",
"credentials": {
"userName": "<username>",
"password": "<password>"
}
}

attribute = 'Model'
category = 'server-hardware'

# Try load config from a file (if there is a config file)
config = try_load_from_file(config)

oneview_client = OneViewClient(config)

print('\nGetting all index resources:')
index_resources = oneview_client.index_resources.get_all()
pprint(index_resources)

sh = oneview_client.server_hardware.get_all()[0]
print('\nGetting index resource for server hardware with uri "{0}":'.format(sh['uri']))
index_resource = oneview_client.index_resources.get(sh['uri'])
pprint(index_resource)

print('\nGetting aggregated index resources with attribute: "{0}" and category: "{1}"'.format(attribute, category))
index_resources = oneview_client.index_resources.get_aggregated(attribute, category)
pprint(index_resources)
2 changes: 1 addition & 1 deletion hpOneView/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
standard_library.install_aliases()

__title__ = 'hpOneView'
__version__ = '3.3.0'
__version__ = '4.2.0'
__copyright__ = '(C) Copyright (2012-2017) Hewlett Packard Enterprise Development LP'
__license__ = 'MIT'

Expand Down
14 changes: 14 additions & 0 deletions hpOneView/oneview_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
from hpOneView.resources.networking.uplink_sets import UplinkSets
from hpOneView.resources.servers.migratable_vc_domains import MigratableVcDomains
from hpOneView.resources.networking.sas_logical_interconnect_groups import SasLogicalInterconnectGroups
from hpOneView.resources.search.index_resources import IndexResources
from hpOneView.resources.search.labels import Labels
from hpOneView.resources.activity.alerts import Alerts
from hpOneView.resources.activity.events import Events
Expand Down Expand Up @@ -175,6 +176,7 @@ def __init__(self, config):
self.__managed_sans = None
self.__migratable_vc_domains = None
self.__sas_interconnects = None
self.__index_resources = None
self.__labels = None
self.__sas_logical_interconnect_groups = None
self.__alerts = None
Expand Down Expand Up @@ -1019,6 +1021,18 @@ def labels(self):
self.__labels = Labels(self.__connection)
return self.__labels

@property
def index_resources(self):
"""
Gets the Index Resources API client.
Returns:
IndexResources:
"""
if not self.__index_resources:
self.__index_resources = IndexResources(self.__connection)
return self.__index_resources

@property
def alerts(self):
"""
Expand Down
171 changes: 171 additions & 0 deletions hpOneView/resources/search/index_resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
# -*- coding: utf-8 -*-
###
# (C) Copyright (2017) Hewlett Packard Enterprise Development LP
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
###

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from future import standard_library

standard_library.install_aliases()

from hpOneView.resources.resource import ResourceClient
from urllib.parse import quote


class IndexResources(object):
"""
Index Resources API client.
"""

URI = '/rest/index/resources'

def __init__(self, con):
self._connection = con
self._client = ResourceClient(con, self.URI)

def get_all(self, category='', count=-1, fields='', filter='', padding=0, query='', reference_uri='',
sort='', start=0, user_query='', view=''):
"""
Gets a list of index resources based on optional sorting and filtering and is constrained by start
and count parameters.
Args:
category (str or list):
Category of resources. Multiple Category parameters are applied with OR condition.
count (int):
The number of resources to return. A count of -1 requests all items.
The actual number of items in the response might differ from the requested
count if the sum of start and count exceeds the total number of items.
fields (str):
Specifies which fields should be returned in the result set.
filter (list or str):
A general filter/query string to narrow the list of items returned. The
default is no filter; all resources are returned.
padding (int):
Number of resources to be returned before the reference URI resource.
query (str):
A general query string to narrow the list of resources returned.
The default is no query - all resources are returned.
reference_uri (str):
Load one page of resources, pagination is applied with reference to referenceUri provided.
sort (str):
The sort order of the returned data set. By default, the sort order is based
on create time with the oldest entry first.
start (int):
The first item to return, using 0-based indexing.
If not specified, the default is 0 - start with the first available item.
user_query (str):
Free text Query string to search the resources. This will match the string in any field that is indexed.
view (str):
Return a specific subset of the attributes of the resource or collection, by specifying the name of a predefined view.
Returns:
list: A list of index resources.
"""
uri = self.URI + '?'

uri += self.__list_or_str_to_query(category, 'category')
uri += self.__list_or_str_to_query(count, 'count')
uri += self.__list_or_str_to_query(fields, 'fields')
uri += self.__list_or_str_to_query(filter, 'filter')
uri += self.__list_or_str_to_query(padding, 'padding')
uri += self.__list_or_str_to_query(query, 'query')
uri += self.__list_or_str_to_query(reference_uri, 'referenceUri')
uri += self.__list_or_str_to_query(sort, 'sort')
uri += self.__list_or_str_to_query(start, 'start')
uri += self.__list_or_str_to_query(user_query, 'userQuery')
uri += self.__list_or_str_to_query(view, 'view')

uri = uri.replace('?&', '?')

response = self._client.get(uri)

if response and 'members' in response and response['members']:
return response['members']
else:
return []

def get(self, uri):
"""
Gets an index resource by URI.
Args:
uri: The resource URI.
Returns:
dict: The index resource.
"""
uri = self.URI + uri
return self._client.get(uri)

def get_aggregated(self, attribute, category, child_limit=6, filter='', query='', user_query=''):
"""
Gets a list of index resources based on optional sorting and filtering and is constrained by start
and count parameters.
Args:
attribute (list or str):
Attribute to pass in as query filter.
category (str):
Category of resources. Multiple Category parameters are applied with an OR condition.
child_limit (int):
Number of resources to be retrieved. Default=6.
filter (list or str):
A general filter/query string to narrow the list of items returned. The
default is no filter; all resources are returned.
query (str):
A general query string to narrow the list of resources returned.
The default is no query - all resources are returned.
user_query (str):
Free text Query string to search the resources.
This will match the string in any field that is indexed.
Returns:
list: An aggregated list of index resources.
"""
uri = self.URI + '/aggregated?'

# Add attribute to query
uri += self.__list_or_str_to_query(attribute, 'attribute')
uri += self.__list_or_str_to_query(category, 'category')
uri += self.__list_or_str_to_query(child_limit, 'childLimit')
uri += self.__list_or_str_to_query(filter, 'filter')
uri += self.__list_or_str_to_query(query, 'query')
uri += self.__list_or_str_to_query(user_query, 'userQuery')

uri = uri.replace('?&', '?')

return self._client.get(uri)

def __list_or_str_to_query(self, list_or_str, field_name):
formated_query = ''
if list_or_str:
if isinstance(list_or_str, list):
for f in list_or_str:
formated_query = formated_query + "&{0}=".format(field_name) + ''.join(quote(str(f)))
else:
formated_query = "&{0}=".format(field_name) + str(list_or_str)
return formated_query
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
from setuptools import setup

setup(name='hpOneView',
version='4.1.0',
version='4.2.0',
description='HPE OneView Python Library',
url='https://github.com/HewlettPackard/python-hpOneView',
download_url="https://github.com/HewlettPackard/python-hpOneView/tarball/v4.1.0",
download_url="https://github.com/HewlettPackard/python-hpOneView/tarball/v4.2.0",
author='Hewlett Packard Enterprise Development LP',
author_email='[email protected]',
license='MIT',
Expand Down
91 changes: 91 additions & 0 deletions tests/unit/resources/search/test_index_resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
###
# (C) Copyright (2012-2017) Hewlett Packard Enterprise Development LP
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
###

import unittest

import mock

from hpOneView.connection import connection
from hpOneView.resources.search.index_resources import IndexResources
from hpOneView.resources.resource import ResourceClient


class IndexResourcesTest(unittest.TestCase):

INDEX_RESOURCE = dict(
uri="/rest/index/resources/rest/resource/uri",
resourceUri="/rest/resource/uri",
type="IndexResourceV300",
category="the-resource-category",
created="2014-03-31T02:08:27.884Z",
modified="2014-03-31T02:08:27.884Z",
eTag=None,
members=[{'name': 'sh1'}, {'name': 'sh2'}]
)

def return_index(self):
return self.INDEX_RESOURCE

def setUp(self):
self.host = '127.0.0.1'
self.connection = connection(self.host)
self._resource = IndexResources(self.connection)

@mock.patch.object(ResourceClient, 'get', return_value=dict(members='test'))
def test_get_all_called_once(self, mock_get_all):
filter = 'name=TestName'
sort = 'name:ascending'

expected_uri = '/rest/index/resources?count=500&filter=name=TestName&sort=name:ascending&start=2'

self._resource.get_all(start=2, count=500, filter=filter, sort=sort)
mock_get_all.assert_called_once_with(expected_uri)

@mock.patch.object(ResourceClient, 'get')
def test_get_all_called_once_without_results(self, mock_get_all):
filter = 'name=TestName'
sort = 'name:ascending'

expected_uri = '/rest/index/resources?count=500&filter=name=TestName&sort=name:ascending&start=2'

self._resource.get_all(start=2, count=500, filter=filter, sort=sort)
mock_get_all.assert_called_once_with(expected_uri)

@mock.patch.object(ResourceClient, 'get')
def test_get_called_once(self, mock_get):
index_uri = "/rest/server-hardwares/fake"
expected_call_uri = "/rest/index/resources/rest/server-hardwares/fake"
self._resource.get(index_uri)
mock_get.assert_called_once_with(expected_call_uri)

@mock.patch.object(ResourceClient, 'get')
def test_get_aggregated_called_once(self, mock_get_aggregated):

expected_uri = '/rest/index/resources/aggregated?attribute=Model&attribute=State&category=server-hardware&childLimit=6'

self._resource.get_aggregated(['Model', 'State'], 'server-hardware')
mock_get_aggregated.assert_called_once_with(expected_uri)


if __name__ == '__main__':
unittest.main()
Loading

0 comments on commit 88f7b6b

Please sign in to comment.