diff --git a/CHANGELOG.md b/CHANGELOG.md
index eac8fe11..a9a69f67 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,14 @@
-# 4.7.1
+# 5.0.0 (Unreleased)
+#### Notes
+Major release where the resource file is revamped, so that it can be used to instantiate the resource object.
+Addition helper methods where necessary to make the sdk more user friendly and to reduce the dependency on hard coded values.
+
+#### Breaking changes
+Resource file now instantiates the object, which is used to directly call the available methods.
+
+#### Features supported with current release:
+- Firmware Bundle
+
#### Bug fixes
- [#364] (https://github.com/HewlettPackard/python-hpOneView/issues/364) Bug in index_resources.get_all()
diff --git a/endpoints-support.md b/endpoints-support.md
index d1e7df72..901460e5 100755
--- a/endpoints-support.md
+++ b/endpoints-support.md
@@ -130,7 +130,7 @@
|/rest/fcoe-networks/{id} | PUT | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark:
|/rest/fcoe-networks/{id} | DELETE | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark:
| **Firmware Bundles** |
-|/rest/firmware-bundles | POST | :white_check_mark: | :white_check_mark: | :white_check_mark: |
+|/rest/firmware-bundles | POST | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| **Firmware Drivers** |
|/rest/firmware-drivers | GET | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|/rest/firmware-drivers | POST | :white_check_mark: | :white_check_mark: | :white_check_mark: |
diff --git a/examples/firmware_bundles.py b/examples/firmware_bundles.py
index 202d2ca0..16513706 100644
--- a/examples/firmware_bundles.py
+++ b/examples/firmware_bundles.py
@@ -37,12 +37,15 @@
# To run this example you must define a path to a valid file
firmware_path = ""
+# Use the below option to specify additional request headers as required
+custom_headers = {'initialScopeUris': ''}
+
# Try load config from a file (if there is a config file)
config = try_load_from_file(config)
oneview_client = OneViewClient(config)
# Upload a firmware bundle
print("\nUpload a firmware bundle")
-firmware_bundle_information = oneview_client.firmware_bundles.upload(file_path=firmware_path)
+firmware_bundle_information = oneview_client.firmware_bundles.upload(file_path=firmware_path, custom_headers=custom_headers)
print("\n Upload successful! Firmware information returned: \n")
-pprint(firmware_bundle_information)
+pprint(firmware_bundle_information['name'])
diff --git a/hpOneView/connection.py b/hpOneView/connection.py
index 99c420cb..f456cb7a 100644
--- a/hpOneView/connection.py
+++ b/hpOneView/connection.py
@@ -271,8 +271,8 @@ def encode_multipart_formdata(self, fields, files, baseName, verbose=False):
fin.close()
return content_type
- def post_multipart_with_response_handling(self, uri, file_path, baseName):
- resp, body = self.post_multipart(uri, None, file_path, baseName)
+ def post_multipart_with_response_handling(self, uri, file_path, baseName, custom_headers):
+ resp, body = self.post_multipart(uri, None, file_path, baseName, custom_headers)
if resp.status == 202:
task = self.__get_task_from_response(resp, body)
@@ -283,7 +283,7 @@ def post_multipart_with_response_handling(self, uri, file_path, baseName):
return None, body
- def post_multipart(self, uri, fields, files, baseName, verbose=False):
+ def post_multipart(self, uri, fields, files, baseName, verbose=False, custom_headers=None):
content_type = self.encode_multipart_formdata(fields, files, baseName,
verbose)
inputfile = self._open(files + '.b64', 'rb')
@@ -295,6 +295,7 @@ def post_multipart(self, uri, fields, files, baseName, verbose=False):
conn.connect()
conn.putrequest('POST', uri)
conn.putheader('uploadfilename', baseName)
+ conn.putheader('initialScopeUris', custom_headers['initialScopeUris'])
conn.putheader('auth', self._headers['auth'])
conn.putheader('Content-Type', content_type)
totalSize = os.path.getsize(files + '.b64')
diff --git a/hpOneView/oneview_client.py b/hpOneView/oneview_client.py
index 56c2c342..ec86e03a 100755
--- a/hpOneView/oneview_client.py
+++ b/hpOneView/oneview_client.py
@@ -905,9 +905,7 @@ def firmware_bundles(self):
Returns:
FirmwareBundles:
"""
- if not self.__firmware_bundles:
- self.__firmware_bundles = FirmwareBundles(self.__connection)
- return self.__firmware_bundles
+ return FirmwareBundles(self.__connection)
@property
def uplink_sets(self):
diff --git a/hpOneView/resources/resource.py b/hpOneView/resources/resource.py
index f6f0064d..8fcb946d 100755
--- a/hpOneView/resources/resource.py
+++ b/hpOneView/resources/resource.py
@@ -1209,7 +1209,7 @@ def create(self, resource, uri=None, timeout=-1, custom_headers=None, default_va
return self.__do_post(uri, resource, timeout, custom_headers)
- def upload(self, file_path, uri=None, timeout=-1):
+ def upload(self, file_path, uri=None, timeout=-1, custom_headers=None):
"""
Makes a multipart request.
@@ -1221,6 +1221,8 @@ def upload(self, file_path, uri=None, timeout=-1):
timeout:
Timeout in seconds. Wait for task completion by default. The timeout does not abort the operation
in OneView; it just stops waiting for its completion.
+ custom_headers:
+ Allows set specific HTTP headers.
Returns:
dict: Response body.
@@ -1229,7 +1231,7 @@ def upload(self, file_path, uri=None, timeout=-1):
uri = self._uri
upload_file_name = os.path.basename(file_path)
- task, entity = self._connection.post_multipart_with_response_handling(uri, file_path, upload_file_name)
+ task, entity = self._connection.post_multipart_with_response_handling(uri, file_path, upload_file_name, custom_headers)
if not task:
return entity
diff --git a/hpOneView/resources/settings/firmware_bundles.py b/hpOneView/resources/settings/firmware_bundles.py
index e3b12506..0ffee7e5 100644
--- a/hpOneView/resources/settings/firmware_bundles.py
+++ b/hpOneView/resources/settings/firmware_bundles.py
@@ -45,7 +45,7 @@ def __init__(self, con):
self._connection = con
self._client = ResourceClient(con, self.URI)
- def upload(self, file_path, timeout=-1):
+ def upload(self, file_path, timeout=-1, custom_headers=None):
"""
Upload an SPP ISO image file or a hotfix file to the appliance.
The API supports upload of one hotfix at a time into the system.
@@ -59,4 +59,5 @@ def upload(self, file_path, timeout=-1):
Returns:
dict: Information about the updated firmware bundle.
"""
- return self._client.upload(file_path, timeout=timeout)
+# custom_headers = { 'initialScopeUris': '/rest/scopes/bf3e77e3-3248-41b3-aaee-5d83b6ac4b49'}
+ return self._client.upload(file_path, timeout=timeout, custom_headers=custom_headers)
diff --git a/tests/unit/resources/settings/test_firmware_bundles.py b/tests/unit/resources/settings/test_firmware_bundles.py
index 15a5c3d0..26b06949 100644
--- a/tests/unit/resources/settings/test_firmware_bundles.py
+++ b/tests/unit/resources/settings/test_firmware_bundles.py
@@ -42,4 +42,4 @@ def test_upload(self, mock_upload):
self._firmware_bundles.upload(firmware_path)
- mock_upload.assert_called_once_with(firmware_path, timeout=-1)
+ mock_upload.assert_called_once_with(firmware_path, timeout=-1, custom_headers=None)
diff --git a/tests/unit/resources/test_resource.py b/tests/unit/resources/test_resource.py
index 94b85448..3ba56fbd 100644
--- a/tests/unit/resources/test_resource.py
+++ b/tests/unit/resources/test_resource.py
@@ -1217,7 +1217,7 @@ def test_upload_should_call_post_multipart(self, mock_post_multipart):
self.resource_client.upload(filepath, uri)
- mock_post_multipart.assert_called_once_with(uri, filepath, 'SPPgen9snap6.2015_0405.81.iso')
+ mock_post_multipart.assert_called_once_with(uri, filepath, 'SPPgen9snap6.2015_0405.81.iso', None)
@mock.patch.object(connection, 'post_multipart_with_response_handling')
def test_upload_should_call_post_multipart_with_resource_uri_when_not_uri_provided(self, mock_post_multipart):
@@ -1226,7 +1226,7 @@ def test_upload_should_call_post_multipart_with_resource_uri_when_not_uri_provid
self.resource_client.upload(filepath)
- mock_post_multipart.assert_called_once_with('/rest/testuri', mock.ANY, mock.ANY)
+ mock_post_multipart.assert_called_once_with('/rest/testuri', mock.ANY, mock.ANY, mock.ANY)
@mock.patch.object(connection, 'post_multipart_with_response_handling')
@mock.patch.object(TaskMonitor, 'wait_for_task')
diff --git a/tests/unit/test_connection.py b/tests/unit/test_connection.py
index 17877d8a..303dee87 100644
--- a/tests/unit/test_connection.py
+++ b/tests/unit/test_connection.py
@@ -629,6 +629,7 @@ def test_post_multipart_should_put_request(self, mock_rm, mock_path_size, mock_c
self.connection.post_multipart(uri='/rest/resources/',
fields=None,
files="/a/path/filename.zip",
+ custom_headers={'initialScopeUris': '/rest/scopes/fake'},
baseName="archive.zip")
internal_conn = self.connection.get_connection.return_value
@@ -646,10 +647,12 @@ def test_post_multipart_should_put_headers(self, mock_rm, mock_path_size, mock_c
self.connection.post_multipart(uri='/rest/resources/',
fields=None,
files="/a/path/filename.zip",
+ custom_headers={'initialScopeUris': '/rest/scopes/fake'},
baseName="archive.zip")
expected_putheader_calls = [
call('uploadfilename', 'archive.zip'),
+ call(u'initialScopeUris', '/rest/scopes/fake'),
call('auth', 'LTIxNjUzMjc0OTUzzHoF7eEkZLEUWVA-fuOZP4VGA3U8e67E'),
call('Content-Type', 'multipart/form-data; boundary=----------ThIs_Is_tHe_bouNdaRY_$'),
call('Content-Length', 2621440),
@@ -669,6 +672,7 @@ def test_post_multipart_should_read_file_in_chunks_of_1mb(self, mock_rm, mock_pa
self.connection.post_multipart(uri='/rest/resources/',
fields=None,
files="/a/path/filename.zip",
+ custom_headers={'initialScopeUris': '/rest/scopes/fake'},
baseName="archive.zip")
expected_mmap_read_calls = [
@@ -689,6 +693,7 @@ def test_post_multipart_should_send_file_in_chuncks_of_1mb(self, mock_rm, mock_p
self.connection.post_multipart(uri='/rest/resources/',
fields=None,
files="/a/path/filename.zip",
+ custom_headers={'initialScopeUris': '/rest/scopes/fake'},
baseName="archive.zip")
expected_conn_send_calls = [
@@ -710,6 +715,7 @@ def test_post_multipart_should_remove_temp_encoded_file(self, mock_rm, mock_path
self.connection.post_multipart(uri='/rest/resources/',
fields=None,
files="/a/path/filename.zip",
+ custom_headers={'initialScopeUris': '/rest/scopes/fake'},
baseName="archive.zip")
mock_rm.assert_called_once_with('/a/path/filename.zip.b64')
@@ -727,6 +733,7 @@ def test_post_multipart_should_raise_exception_when_response_status_400(self, mo
self.connection.post_multipart(uri='/rest/resources/',
fields=None,
files="/a/path/filename.zip",
+ custom_headers={'initialScopeUris': '/rest/scopes/fake'},
baseName="archive.zip")
except HPOneViewException as e:
self.assertEqual(e.msg, "An error occurred.")
@@ -745,6 +752,7 @@ def test_post_multipart_should_return_response_and_body_when_response_status_200
response, body = self.connection.post_multipart(uri='/rest/resources/',
fields=None,
files="/a/path/filename.zip",
+ custom_headers={'initialScopeUris': '/rest/scopes/fake'},
baseName="archive.zip")
self.assertEqual(body, self.expected_response_body)
@@ -764,6 +772,7 @@ def test_post_multipart_should_handle_json_load_exception(self, mock_json_loads,
response, body = self.connection.post_multipart(uri='/rest/resources/',
fields=None,
files="/a/path/filename.zip",
+ custom_headers={'initialScopeUris': '/rest/scopes/fake'},
baseName="archive.zip")
self.assertTrue(body)
@@ -775,7 +784,7 @@ def test_post_multipart_with_response_handling_when_status_202_without_task(self
mock_response.getheader.return_value = None
mock_post_multipart.return_value = mock_response, "content"
- task, body = self.connection.post_multipart_with_response_handling("uri", "filepath", "basename")
+ task, body = self.connection.post_multipart_with_response_handling("uri", "filepath", "custom_headers", "basename")
self.assertFalse(task)
self.assertEqual(body, "content")
@@ -789,7 +798,7 @@ def test_post_multipart_with_response_handling_when_status_202_with_task(self, m
mock_post_multipart.return_value = mock_response, "content"
mock_get.return_value = fake_task
- task, body = self.connection.post_multipart_with_response_handling("uri", "filepath", "basename")
+ task, body = self.connection.post_multipart_with_response_handling("uri", "filepath", "custom_headers", "basename")
self.assertEqual(task, fake_task)
self.assertEqual(body, "content")
@@ -799,7 +808,7 @@ def test_post_multipart_with_response_handling_when_status_200_and_body_is_task(
fake_task = {"category": "tasks"}
mock_post_multipart.return_value = Mock(status=200), fake_task
- task, body = self.connection.post_multipart_with_response_handling("uri", "filepath", "basename")
+ task, body = self.connection.post_multipart_with_response_handling("uri", "filepath", "custom_headers", "basename")
self.assertEqual(task, fake_task)
self.assertEqual(body, fake_task)
@@ -808,7 +817,7 @@ def test_post_multipart_with_response_handling_when_status_200_and_body_is_task(
def test_post_multipart_with_response_handling_when_status_200_and_body_is_not_task(self, mock_post_multipart):
mock_post_multipart.return_value = Mock(status=200), "content"
- task, body = self.connection.post_multipart_with_response_handling("uri", "filepath", "basename")
+ task, body = self.connection.post_multipart_with_response_handling("uri", "filepath", "custom_headers", "basename")
self.assertFalse(task)
self.assertEqual(body, "content")
diff --git a/tests/unit/test_oneview_client.py b/tests/unit/test_oneview_client.py
index 21dfb6c4..5282a9a4 100755
--- a/tests/unit/test_oneview_client.py
+++ b/tests/unit/test_oneview_client.py
@@ -79,6 +79,7 @@
from hpOneView.resources.settings.appliance_node_information import ApplianceNodeInformation
from hpOneView.resources.settings.appliance_time_and_locale_configuration import ApplianceTimeAndLocaleConfiguration
from hpOneView.resources.settings.versions import Versions
+from hpOneView.resources.settings.firmware_bundles import FirmwareBundles
from tests.test_utils import mock_builtin
from hpOneView.resources.settings.licenses import Licenses
@@ -566,9 +567,11 @@ def test_lazy_loading_firmware_drivers(self):
firmware_drivers = self._oneview.firmware_drivers
self.assertEqual(firmware_drivers, self._oneview.firmware_drivers)
- def test_lazy_loading_firmware_bundles(self):
- firmware_bundles = self._oneview.firmware_bundles
- self.assertEqual(firmware_bundles, self._oneview.firmware_bundles)
+ def test_firmware_bundles_has_right_type(self):
+ self.assertIsInstance(self._oneview.firmware_bundles, FirmwareBundles)
+
+ def test_firmware_bundles_has_value(self):
+ self.assertIsNotNone(self._oneview.firmware_bundles)
def test_migratable_vc_domains_has_right_type(self):
self.assertIsInstance(self._oneview.migratable_vc_domains, MigratableVcDomains)