oneview-sdk 4.0.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/README.md +34 -11
- data/Rakefile +0 -1
- data/lib/oneview-sdk.rb +6 -4
- data/lib/oneview-sdk/cli.rb +2 -2
- data/lib/oneview-sdk/client.rb +33 -8
- data/lib/oneview-sdk/exceptions.rb +52 -16
- data/lib/oneview-sdk/image-streamer/client.rb +6 -3
- data/lib/oneview-sdk/image-streamer/resource/api300/artifact_bundle.rb +215 -0
- data/lib/oneview-sdk/image-streamer/resource/api300/build_plan.rb +10 -3
- data/lib/oneview-sdk/image-streamer/resource/api300/{artifacts_bundle.rb → deployment_group.rb} +21 -6
- data/lib/oneview-sdk/image-streamer/resource/api300/deployment_plan.rb +10 -3
- data/lib/oneview-sdk/image-streamer/resource/api300/golden_image.rb +121 -3
- data/lib/oneview-sdk/resource.rb +4 -4
- data/lib/oneview-sdk/resource/api200.rb +1 -1
- data/lib/oneview-sdk/resource/api200/firmware_bundle.rb +11 -4
- data/lib/oneview-sdk/resource/api200/volume_attachment.rb +1 -1
- data/lib/oneview-sdk/resource/api300.rb +1 -1
- data/lib/oneview-sdk/resource/api300/c7000/switch.rb +4 -4
- data/lib/oneview-sdk/rest.rb +80 -16
- data/lib/oneview-sdk/version.rb +1 -1
- data/oneview-sdk.gemspec +4 -4
- metadata +21 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33d01d70d21a357c6e0c4f9295f039d874aea7b1
|
4
|
+
data.tar.gz: f5bd6ddea83a0124bf87c034b2107b7949a1004b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81644b00704bc889c5f62fbeb98fc2ef00fd7c0ba2a66631016aa867a298207bfc109eb904a8f404768779447f34b9f40a1cc17c3fb1efea46f2be3bd64811ae
|
7
|
+
data.tar.gz: d469232c518d22bc5ec52d828b929093a5bdac8a7d8ac12bbf647d4c1ca7f6be6f60ac817638e805d2d47dad578649e3ca7d4a310e9251a2bbdb34ab2c3304eb
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,30 @@
|
|
1
1
|
# Unreleased Changes
|
2
|
+
(none)
|
3
|
+
|
4
|
+
# v4.1.0
|
5
|
+
|
6
|
+
#### New Resources:
|
7
|
+
Added full support to Image Streamer Rest API version 300:
|
8
|
+
- Artifact Bundle
|
9
|
+
- Build Plan
|
10
|
+
- Deployment Group
|
11
|
+
- Deployment Plan
|
12
|
+
- Golden Image
|
13
|
+
- OS Volume
|
14
|
+
- Plan Script
|
15
|
+
|
16
|
+
#### Bug fixes & Enhancements:
|
17
|
+
- Give custom exception classes a data attribute for more error context and default message
|
18
|
+
- [#116](https://github.com/HewlettPackard/oneview-sdk-ruby/issues/112) VolumeAttachment::remove_extra_unmanaged_volume throw Unexpected Http Error
|
19
|
+
- [#135](https://github.com/HewlettPackard/oneview-sdk-ruby/issues/135) Firmware Bundle timeout does not give proper instructions for user post failure
|
20
|
+
- [#146](https://github.com/HewlettPackard/oneview-sdk-ruby/issues/146) Why is Switch the only resource that directly implements #set_scope_uris?
|
21
|
+
- [#166](https://github.com/HewlettPackard/oneview-sdk-ruby/issues/166) I3S - Simplify login to i3s through oneview client
|
22
|
+
- [#178](https://github.com/HewlettPackard/oneview-sdk-ruby/issues/178) Add client destroy_session method and domain attribute
|
23
|
+
- [#174](https://github.com/HewlettPackard/oneview-sdk-ruby/issues/174) I3S - Integration test for Build Plan failing
|
24
|
+
- [#176](https://github.com/HewlettPackard/oneview-sdk-ruby/issues/176) OneviewSDK.resource_named now finds resources that are not children of Resource
|
25
|
+
- [#183](https://github.com/HewlettPackard/oneview-sdk-ruby/issues/183) Image Streamer Client cannot be created with the OneView environment variables
|
26
|
+
- [#184](https://github.com/HewlettPackard/oneview-sdk-ruby/issues/184) Coveralls badge showing coverage as unknown
|
27
|
+
- [#196](https://github.com/HewlettPackard/oneview-sdk-ruby/issues/196) Missing endpoint for extract backup in Artifact Bundle
|
2
28
|
|
3
29
|
# v4.0.0
|
4
30
|
|
data/README.md
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# oneview-sdk for Ruby
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/oneview-sdk.svg)](https://badge.fury.io/rb/oneview-sdk)
|
3
|
+
[![Yard Docs](https://img.shields.io/badge/yard-docs-yellow.svg)](http://www.rubydoc.info/gems/oneview-sdk)
|
3
4
|
|
5
|
+
[![Build Status](https://travis-ci.org/HewlettPackard/oneview-sdk-ruby.svg?branch=master)](https://travis-ci.org/HewlettPackard/oneview-sdk-ruby)
|
6
|
+
[![Coverage Status](https://coveralls.io/repos/github/HewlettPackard/oneview-sdk-ruby/badge.svg)](https://coveralls.io/github/HewlettPackard/oneview-sdk-ruby)
|
7
|
+
[![Code Climate](https://codeclimate.com/github/HewlettPackard/oneview-sdk-ruby/badges/gpa.svg)](https://codeclimate.com/github/HewlettPackard/oneview-sdk-ruby)
|
4
8
|
|
5
9
|
The OneView SDK provides a Ruby library to easily interact with HPE OneView and Image Streamer APIs. The Ruby SDK enables developers to easily build integrations and scalable solutions with HPE OneView and Image Streamer.
|
6
10
|
|
7
|
-
Note that currently the Image Streamer resources are a work in progress, so should be treated as experimental.
|
8
|
-
Many of these resources are unimplemented, and all are subject to change in ways that are incompatible with current usage & docs.
|
9
|
-
|
10
11
|
## Installation
|
11
12
|
- Require the gem in your Gemfile:
|
12
13
|
|
13
14
|
```ruby
|
14
|
-
gem 'oneview-sdk', '~> 4.
|
15
|
+
gem 'oneview-sdk', '~> 4.1'
|
15
16
|
```
|
16
17
|
|
17
18
|
Then run `$ bundle install`
|
@@ -36,6 +37,7 @@ client = OneviewSDK::Client.new(
|
|
36
37
|
ssl_enabled: true, # This is the default and strongly encouraged
|
37
38
|
logger: Logger.new(STDOUT), # This is the default
|
38
39
|
log_level: :info, # This is the default
|
40
|
+
domain: 'LOCAL', # This is the default
|
39
41
|
api_version: 200 # Defaults to minimum of 200 and appliance's max API version
|
40
42
|
)
|
41
43
|
```
|
@@ -60,6 +62,19 @@ i3s_client = OneviewSDK::ImageStreamer::Client.new(
|
|
60
62
|
)
|
61
63
|
```
|
62
64
|
|
65
|
+
You can also create the i3s client through the Oneview client instance.
|
66
|
+
```ruby
|
67
|
+
# Create an Image Streamer client object through the Oneview client object:
|
68
|
+
require 'oneview-sdk'
|
69
|
+
i3s_client = client.new_i3s_client(
|
70
|
+
url: 'https://image-streamer.example.com',
|
71
|
+
ssl_enabled: true, # This is the default and strongly encouraged
|
72
|
+
logger: Logger.new(STDOUT), # This is the default
|
73
|
+
log_level: :info, # This is the default
|
74
|
+
api_version: 300 # Defaults to minimum of 300 and appliance's max API version
|
75
|
+
)
|
76
|
+
```
|
77
|
+
|
63
78
|
##### Environment Variables
|
64
79
|
|
65
80
|
You can also set many of the client attributes using environment variables. To set these variables in bash:
|
@@ -67,6 +82,7 @@ You can also set many of the client attributes using environment variables. To s
|
|
67
82
|
```bash
|
68
83
|
# OneView client options:
|
69
84
|
export ONEVIEWSDK_URL='https://oneview.example.com'
|
85
|
+
export ONEVIEWSDK_DOMAIN='LOCAL'
|
70
86
|
# You can set the token if you know it, or set the user and password to generate one:
|
71
87
|
export ONEVIEWSDK_TOKEN='xxxx...'
|
72
88
|
export ONEVIEWSDK_USER='Administrator'
|
@@ -76,7 +92,6 @@ export ONEVIEWSDK_SSL_ENABLED=false
|
|
76
92
|
|
77
93
|
# Image Streamer (I3S) client options:
|
78
94
|
export I3S_URL='https://image-streamer.example.com'
|
79
|
-
export I3S_TOKEN='xxxx...'
|
80
95
|
export I3S_SSL_ENABLED=false
|
81
96
|
# NOTE: Disabling SSL is strongly discouraged. Please see the CLI section for import instructions.
|
82
97
|
```
|
@@ -88,7 +103,18 @@ Then you can leave out these options from your config, enabling you to just do:
|
|
88
103
|
```ruby
|
89
104
|
require 'oneview-sdk'
|
90
105
|
client = OneviewSDK::Client.new
|
91
|
-
|
106
|
+
```
|
107
|
+
|
108
|
+
You can create the i3s client with environment variables in the following ways:
|
109
|
+
```ruby
|
110
|
+
require 'oneview-sdk'
|
111
|
+
# Note: Both options require the I3S_URL environment variable to be set.
|
112
|
+
|
113
|
+
# This way uses the ONEVIEWSDK_URL, ONEVIEWSDK_USER and ONEVIEWSDK_PASSWORD environment variables to generate a token:
|
114
|
+
client = OneviewSDK::Client.new
|
115
|
+
i3s_client = client.new_i3s_client
|
116
|
+
|
117
|
+
# This way uses the ONEVIEWSDK_TOKEN environment variable directly:
|
92
118
|
i3s_client = OneviewSDK::ImageStreamer::Client.new
|
93
119
|
```
|
94
120
|
|
@@ -152,7 +178,7 @@ OneviewSDK.api_version = 300
|
|
152
178
|
OneviewSDK.api_version # 300
|
153
179
|
OneviewSDK.api_version_updated? # true
|
154
180
|
|
155
|
-
# The API200 module has
|
181
|
+
# The API200 module has no variants, but API300 has 2 (C7000 & Synergy):
|
156
182
|
OneviewSDK::API300::SUPPORTED_VARIANTS # ['C7000', 'Synergy']
|
157
183
|
OneviewSDK::API300::DEFAULT_VARIANT # 'C7000'
|
158
184
|
OneviewSDK::API300.variant # 'C7000'
|
@@ -406,7 +432,4 @@ First run `$ bundle` (requires the bundler gem), then...
|
|
406
432
|
Note: run `$ rake -T` to get a list of all the available rake tasks.
|
407
433
|
|
408
434
|
## Authors
|
409
|
-
|
410
|
-
- Henrique Diomede - [@hdiomede](https://github.com/hdiomede)
|
411
|
-
- Thiago Miotto - [@tmiotto](https://github.com/tmiotto)
|
412
|
-
- Ricardo Piantola - [@piantola](https://github.com/piantola)
|
435
|
+
See the [contributors graph](https://github.com/HewlettPackard/oneview-sdk-ruby/graphs/contributors)
|
data/Rakefile
CHANGED
data/lib/oneview-sdk.rb
CHANGED
@@ -19,9 +19,9 @@ require_relative 'oneview-sdk/image_streamer'
|
|
19
19
|
|
20
20
|
# Module for interacting with the HPE OneView API
|
21
21
|
module OneviewSDK
|
22
|
-
env_sdk = %w(ONEVIEWSDK_URL ONEVIEWSDK_USER ONEVIEWSDK_PASSWORD ONEVIEWSDK_TOKEN)
|
22
|
+
env_sdk = %w(ONEVIEWSDK_URL ONEVIEWSDK_USER ONEVIEWSDK_PASSWORD ONEVIEWSDK_TOKEN ONEVIEWSDK_DOMAIN)
|
23
23
|
env_sdk.concat %w(ONEVIEWSDK_SSL_ENABLED ONEVIEWSDK_API_VERSION ONEVIEWSDK_VARIANT)
|
24
|
-
env_i3s = %w(I3S_URL
|
24
|
+
env_i3s = %w(I3S_URL I3S_SSL_ENABLED)
|
25
25
|
ENV_VARS = env_sdk.concat(env_i3s).freeze
|
26
26
|
|
27
27
|
SUPPORTED_API_VERSIONS = [200, 300].freeze
|
@@ -37,8 +37,10 @@ module OneviewSDK
|
|
37
37
|
# Set the default API version
|
38
38
|
def self.api_version=(version)
|
39
39
|
version = version.to_i rescue version
|
40
|
-
raise "API version #{version} is not supported!"
|
41
|
-
|
40
|
+
raise UnsupportedVersion, "API version #{version} is not supported!"\
|
41
|
+
unless SUPPORTED_API_VERSIONS.include?(version)
|
42
|
+
raise UnsupportedVariant, "The module for API version #{@api_version} is undefined"\
|
43
|
+
unless constants.include?("API#{@api_version}".to_sym)
|
42
44
|
@api_version_updated = true
|
43
45
|
@api_version = version
|
44
46
|
end
|
data/lib/oneview-sdk/cli.rb
CHANGED
@@ -466,13 +466,13 @@ module OneviewSDK
|
|
466
466
|
r = OneviewSDK.resource_named(type, api_ver, variant)
|
467
467
|
# Try default API version as last resort
|
468
468
|
r ||= OneviewSDK.resource_named(type, OneviewSDK.api_version, variant) unless api_ver == OneviewSDK.api_version
|
469
|
-
return r if r
|
469
|
+
return r if r && r.respond_to?(:find_by)
|
470
470
|
valid_classes = []
|
471
471
|
api_module = OneviewSDK.const_get("API#{api_ver}")
|
472
472
|
api_module = api_module.const_get(variant.to_s) unless api_ver.to_i == 200
|
473
473
|
api_module.constants.each do |c|
|
474
474
|
klass = api_module.const_get(c)
|
475
|
-
next unless klass.is_a?(Class) && klass
|
475
|
+
next unless klass.is_a?(Class) && klass.respond_to?(:find_by)
|
476
476
|
valid_classes.push(klass.name.split('::').last)
|
477
477
|
end
|
478
478
|
vc = valid_classes.sort_by!(&:downcase).join("\n ")
|
data/lib/oneview-sdk/client.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
# (
|
1
|
+
# (c) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
#
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
5
|
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
6
|
#
|
7
7
|
# Unless required by applicable law or agreed to in writing, software distributed
|
@@ -18,7 +18,7 @@ module OneviewSDK
|
|
18
18
|
# The client defines the connection to the OneView server and handles communication with it.
|
19
19
|
class Client
|
20
20
|
attr_reader :max_api_version
|
21
|
-
attr_accessor :url, :user, :token, :password, :ssl_enabled, :api_version, \
|
21
|
+
attr_accessor :url, :user, :token, :password, :domain, :ssl_enabled, :api_version, \
|
22
22
|
:logger, :log_level, :cert_store, :print_wait_dots, :timeout
|
23
23
|
|
24
24
|
include Rest
|
@@ -32,6 +32,7 @@ module OneviewSDK
|
|
32
32
|
# @option options [String] :url URL of OneView appliance
|
33
33
|
# @option options [String] :user ('Administrator') The username to use for authentication with the OneView appliance
|
34
34
|
# @option options [String] :password (ENV['ONEVIEWSDK_PASSWORD']) The password to use for authentication with OneView appliance
|
35
|
+
# @option options [String] :domain ('LOCAL') The name of the domain directory used for authentication
|
35
36
|
# @option options [String] :token (ENV['ONEVIEWSDK_TOKEN']) The token to use for authentication with OneView appliance
|
36
37
|
# Use the token or the username and password (not both). The token has precedence.
|
37
38
|
# @option options [Integer] :api_version (200) This is the API version to use by default for requests
|
@@ -65,12 +66,12 @@ module OneviewSDK
|
|
65
66
|
@timeout = options[:timeout] unless options[:timeout].nil?
|
66
67
|
@cert_store = OneviewSDK::SSLHelper.load_trusted_certs if @ssl_enabled
|
67
68
|
@token = options[:token] || ENV['ONEVIEWSDK_TOKEN']
|
68
|
-
|
69
|
-
@logger.warn 'User option not set. Using default (Administrator)' unless options[:user] || ENV['ONEVIEWSDK_USER']
|
69
|
+
@logger.warn 'User option not set. Using default (Administrator)' unless @token || options[:user] || ENV['ONEVIEWSDK_USER']
|
70
70
|
@user = options[:user] || ENV['ONEVIEWSDK_USER'] || 'Administrator'
|
71
71
|
@password = options[:password] || ENV['ONEVIEWSDK_PASSWORD']
|
72
|
-
raise InvalidClient, 'Must set user & password options or token option' unless @password
|
73
|
-
@
|
72
|
+
raise InvalidClient, 'Must set user & password options or token option' unless @token || @password
|
73
|
+
@domain = options[:domain] || ENV['ONEVIEWSDK_DOMAIN'] || 'LOCAL'
|
74
|
+
@token ||= login
|
74
75
|
end
|
75
76
|
|
76
77
|
def log_level=(level)
|
@@ -157,6 +158,30 @@ module OneviewSDK
|
|
157
158
|
self
|
158
159
|
end
|
159
160
|
|
161
|
+
# Delete the session on the appliance, invalidating the client's token.
|
162
|
+
# To generate a new token after calling this method, use the refresh_login method.
|
163
|
+
# Call this after a token expires or the user and/or password is updated on the client object.
|
164
|
+
# @return [OneviewSDK::Client] self
|
165
|
+
def destroy_session
|
166
|
+
response_handler(rest_delete('/rest/login-sessions'))
|
167
|
+
self
|
168
|
+
end
|
169
|
+
|
170
|
+
# Creates the image streamer client object.
|
171
|
+
# @param [Hash] options the options to configure the client
|
172
|
+
# @option options [Logger] :logger (Logger.new(STDOUT)) Logger object to use.
|
173
|
+
# Must implement debug(String), info(String), warn(String), error(String), & level=
|
174
|
+
# @option options [Symbol] :log_level (:info) Log level. Logger must define a constant with this name. ie Logger::INFO
|
175
|
+
# @option options [Boolean] :print_wait_dots (false) When true, prints status dots while waiting on the tasks to complete.
|
176
|
+
# @option options [String] :url URL of Image Streamer
|
177
|
+
# @option options [Integer] :api_version (300) This is the API version to use by default for requests
|
178
|
+
# @option options [Boolean] :ssl_enabled (true) Use ssl for requests? Respects ENV['I3S_SSL_ENABLED']
|
179
|
+
# @option options [Integer] :timeout (nil) Override the default request timeout value
|
180
|
+
# @return [OneviewSDK::ImageStreamer::Client] New instance of image streamer client
|
181
|
+
def new_i3s_client(options = {})
|
182
|
+
OneviewSDK::ImageStreamer::Client.new(options.merge(token: @token))
|
183
|
+
end
|
184
|
+
|
160
185
|
|
161
186
|
private
|
162
187
|
|
@@ -179,7 +204,7 @@ module OneviewSDK
|
|
179
204
|
'body' => {
|
180
205
|
'userName' => @user,
|
181
206
|
'password' => @password,
|
182
|
-
'authLoginDomain' =>
|
207
|
+
'authLoginDomain' => @domain
|
183
208
|
}
|
184
209
|
}
|
185
210
|
response = rest_post('/rest/login-sessions', options)
|
@@ -1,7 +1,7 @@
|
|
1
|
-
# (
|
1
|
+
# (c) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
#
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
5
|
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
6
|
#
|
7
7
|
# Unless required by applicable law or agreed to in writing, software distributed
|
@@ -11,45 +11,81 @@
|
|
11
11
|
|
12
12
|
# Contains all the custom Exception classes
|
13
13
|
module OneviewSDK
|
14
|
-
|
14
|
+
# Error class allowing storage of a data attribute
|
15
|
+
class OneViewError < ::StandardError
|
16
|
+
attr_accessor :data
|
17
|
+
MESSAGE = '(No message)'.freeze
|
18
|
+
|
19
|
+
def initialize(msg = self.class::MESSAGE, data = nil)
|
20
|
+
@data = data
|
21
|
+
super(msg)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Shorthand method to raise an error.
|
25
|
+
# @example
|
26
|
+
# OneviewSDK::OneViewError.raise! 'Message', { data: 'stuff' }
|
27
|
+
def self.raise!(msg = self::MESSAGE, data = nil)
|
28
|
+
raise new(msg, data)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class ConnectionError < OneViewError # Cannot connect to client/resource
|
33
|
+
MESSAGE = 'Cannot connect to client/resource'.freeze
|
34
|
+
end
|
35
|
+
|
36
|
+
class InvalidURL < OneViewError # URL is invalid
|
37
|
+
MESSAGE = 'URL is invalid'.freeze
|
15
38
|
end
|
16
39
|
|
17
|
-
class
|
40
|
+
class InvalidClient < OneViewError # Client configuration is invalid
|
41
|
+
MESSAGE = 'Client configuration is invalid'.freeze
|
18
42
|
end
|
19
43
|
|
20
|
-
class
|
44
|
+
class InvalidResource < OneViewError # Failed resource validations
|
45
|
+
MESSAGE = 'Failed resource validations'.freeze
|
21
46
|
end
|
22
47
|
|
23
|
-
class
|
48
|
+
class IncompleteResource < OneViewError # Missing required resource data to complete action
|
49
|
+
MESSAGE = 'Missing required resource data to complete action'.freeze
|
24
50
|
end
|
25
51
|
|
26
|
-
class
|
52
|
+
class MethodUnavailable < OneViewError # Resource does not support this method
|
53
|
+
MESSAGE = 'Resource does not support this method'.freeze
|
27
54
|
end
|
28
55
|
|
29
|
-
class
|
56
|
+
class UnsupportedVariant < OneViewError # Variant is not supported
|
57
|
+
MESSAGE = 'Variant is not supported'.freeze
|
30
58
|
end
|
31
59
|
|
32
|
-
class UnsupportedVersion <
|
60
|
+
class UnsupportedVersion < OneViewError # Resource not supported on this API version
|
61
|
+
MESSAGE = 'Resource not supported on this API version'.freeze
|
33
62
|
end
|
34
63
|
|
35
|
-
class InvalidRequest <
|
64
|
+
class InvalidRequest < OneViewError # Could not make request
|
65
|
+
MESSAGE = 'Could not make request'.freeze
|
36
66
|
end
|
37
67
|
|
38
|
-
class BadRequest <
|
68
|
+
class BadRequest < OneViewError # 400
|
69
|
+
MESSAGE = '400'.freeze
|
39
70
|
end
|
40
71
|
|
41
|
-
class Unauthorized <
|
72
|
+
class Unauthorized < OneViewError # 401
|
73
|
+
MESSAGE = '401'.freeze
|
42
74
|
end
|
43
75
|
|
44
|
-
class NotFound <
|
76
|
+
class NotFound < OneViewError # 404
|
77
|
+
MESSAGE = '404'.freeze
|
45
78
|
end
|
46
79
|
|
47
|
-
class RequestError <
|
80
|
+
class RequestError < OneViewError # Other bad response codes
|
81
|
+
MESSAGE = 'Bad response code'.freeze
|
48
82
|
end
|
49
83
|
|
50
|
-
class TaskError <
|
84
|
+
class TaskError < OneViewError # Task ended in a bad state
|
85
|
+
MESSAGE = 'Task ended in a bad state'.freeze
|
51
86
|
end
|
52
87
|
|
53
|
-
class InvalidFormat <
|
88
|
+
class InvalidFormat < OneViewError # File format is invalid
|
89
|
+
MESSAGE = 'File format is invalid'.freeze
|
54
90
|
end
|
55
91
|
end
|
@@ -19,7 +19,10 @@ module OneviewSDK
|
|
19
19
|
undef :user=
|
20
20
|
undef :password
|
21
21
|
undef :password=
|
22
|
+
undef :domain
|
23
|
+
undef :domain=
|
22
24
|
undef :refresh_login
|
25
|
+
undef :destroy_session
|
23
26
|
|
24
27
|
# Creates client object, establish connection, and set up logging and api version.
|
25
28
|
# @param [Hash] options the options to configure the client
|
@@ -28,7 +31,7 @@ module OneviewSDK
|
|
28
31
|
# @option options [Symbol] :log_level (:info) Log level. Logger must define a constant with this name. ie Logger::INFO
|
29
32
|
# @option options [Boolean] :print_wait_dots (false) When true, prints status dots while waiting on the tasks to complete.
|
30
33
|
# @option options [String] :url URL of Image Streamer
|
31
|
-
# @option options [String] :token (ENV['
|
34
|
+
# @option options [String] :token (ENV['ONEVIEWSDK_TOKEN']) The token to use for authentication
|
32
35
|
# @option options [Integer] :api_version (300) This is the API version to use by default for requests
|
33
36
|
# @option options [Boolean] :ssl_enabled (true) Use ssl for requests? Respects ENV['I3S_SSL_ENABLED']
|
34
37
|
# @option options [Integer] :timeout (nil) Override the default request timeout value
|
@@ -60,8 +63,8 @@ module OneviewSDK
|
|
60
63
|
@ssl_enabled = options[:ssl_enabled] unless options[:ssl_enabled].nil?
|
61
64
|
@timeout = options[:timeout] unless options[:timeout].nil?
|
62
65
|
@cert_store = OneviewSDK::SSLHelper.load_trusted_certs if @ssl_enabled
|
63
|
-
raise InvalidClient, 'Must set token option' unless options[:token] || ENV['
|
64
|
-
@token = options[:token] || ENV['
|
66
|
+
raise InvalidClient, 'Must set token option' unless options[:token] || ENV['ONEVIEWSDK_TOKEN']
|
67
|
+
@token = options[:token] || ENV['ONEVIEWSDK_TOKEN']
|
65
68
|
end
|
66
69
|
|
67
70
|
# Get array of all resources of a specified type
|
@@ -0,0 +1,215 @@
|
|
1
|
+
# (C) Copyright 2017 Hewlett Packard Enterprise Development LP
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# You may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software distributed
|
8
|
+
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
9
|
+
# CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
|
10
|
+
# language governing permissions and limitations under the License.
|
11
|
+
|
12
|
+
require_relative 'resource'
|
13
|
+
|
14
|
+
module OneviewSDK
|
15
|
+
module ImageStreamer
|
16
|
+
module API300
|
17
|
+
# Artifacts Bundle resource implementation for Image Streamer
|
18
|
+
class ArtifactBundle < Resource
|
19
|
+
ACCEPTED_FORMATS = %w(.zip .ZIP).freeze # Supported upload extensions
|
20
|
+
|
21
|
+
BASE_URI = '/rest/artifact-bundles'.freeze
|
22
|
+
BACKUPS_URI = "#{BASE_URI}/backups".freeze
|
23
|
+
BACKUPS_ARCHIVE_URI = "#{BACKUPS_URI}/archive".freeze
|
24
|
+
|
25
|
+
# Create a resource object, associate it with a client, and set its properties.
|
26
|
+
# @param [OneviewSDK::ImageStreamer::Client] client The client object for the Image Streamer appliance
|
27
|
+
# @param [Hash] params The options for this resource (key-value pairs)
|
28
|
+
# @param [Integer] api_ver The api version to use when interracting with this resource.
|
29
|
+
def initialize(client, params = {}, api_ver = nil)
|
30
|
+
super
|
31
|
+
@data['buildPlans'] ||= []
|
32
|
+
@data['planScripts'] ||= []
|
33
|
+
@data['deploymentPlans'] ||= []
|
34
|
+
@data['goldenImages'] ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
# Creates an artifact bundle resource from the file that is uploaded from admin's local drive
|
38
|
+
# @param [OneviewSDK::ImageStreamer::Client] client The client object for the Image Streamer appliance
|
39
|
+
# @param [String] file_path The file path with file extension
|
40
|
+
# @param [String] artifact_name The name for the artifact that will be created
|
41
|
+
# @param [Integer] timeout The number of seconds to wait for completing the request. Default is 300.
|
42
|
+
# @return [OneviewSDK::ImageStreamer::API300::ArtifactBundle] if the upload was successful, return a ArtifactBundle object
|
43
|
+
def self.create_from_file(client, file_path, artifact_name, timeout = OneviewSDK::Rest::READ_TIMEOUT)
|
44
|
+
ensure_file_path_extension!(file_path)
|
45
|
+
|
46
|
+
file_name = artifact_name.dup
|
47
|
+
if file_name && !file_name.empty?
|
48
|
+
file_name += File.extname(file_path)
|
49
|
+
else
|
50
|
+
file_name = File.basename(file_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
params = { 'name' => file_name }
|
54
|
+
body = client.upload_file(file_path, BASE_URI, params, timeout)
|
55
|
+
ArtifactBundle.new(client, body)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Gets the backup bundles created
|
59
|
+
# @param [OneviewSDK::ImageStreamer::Client] client The client object for the Image Streamer appliance
|
60
|
+
# @return [Array<ArtifactBundle>] Array of ArtifactBundle
|
61
|
+
def self.get_backups(client)
|
62
|
+
find_by(client, {}, BACKUPS_URI)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Creates a backup bundle with all the artifacts present on the appliance.
|
66
|
+
# @param [OneviewSDK::ImageStreamer::Client] client The client object for the Image Streamer appliance
|
67
|
+
# @param [DeploymentGroup] deployment_group The DeploymentGroup with name or uri
|
68
|
+
# @return [Hash] The result hash with DeploymentGroup data
|
69
|
+
def self.create_backup(client, deployment_group)
|
70
|
+
ensure_resource!(deployment_group)
|
71
|
+
response = client.rest_post(BACKUPS_URI, 'body' => { 'deploymentGroupURI' => deployment_group['uri'] })
|
72
|
+
client.response_handler(response)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Creates a backup bundle from the zip file and extract all the artifacts present in the uploaded file
|
76
|
+
# If there are any artifacts existing, they will be removed before the extract operation.
|
77
|
+
# @param [OneviewSDK::ImageStreamer::Client] client The client object for the Image Streamer appliance
|
78
|
+
# @param [String] file_path The file path with file extension
|
79
|
+
# @param [String] artifact_name The name for the artifact that will be created
|
80
|
+
# @param [Integer] timeout The number of seconds to wait for completing the request. Default is 300.
|
81
|
+
# @return [Hash] The result hash with DeploymentGroup data
|
82
|
+
def self.create_backup_from_file!(client, deployment_group, file_path, artifact_name, timeout = OneviewSDK::Rest::READ_TIMEOUT)
|
83
|
+
ensure_resource!(deployment_group)
|
84
|
+
ensure_file_path_extension!(file_path)
|
85
|
+
|
86
|
+
file_name = artifact_name.dup
|
87
|
+
if file_name && !file_name.empty?
|
88
|
+
file_name += File.extname(file_path)
|
89
|
+
else
|
90
|
+
file_name = File.basename(file_path)
|
91
|
+
end
|
92
|
+
|
93
|
+
params = { 'name' => file_name, 'deploymentGrpUri' => deployment_group['uri'] }
|
94
|
+
client.upload_file(file_path, BACKUPS_ARCHIVE_URI, params, timeout)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Download the backup bundle
|
98
|
+
# @param [OneviewSDK::ImageStreamer::Client] client The client object for the Image Streamer appliance
|
99
|
+
# @param [String] local_drive_path The path where file will be saved
|
100
|
+
# @param [ArtifactBundle] bundle_backup The backup ArtifactBundle with 'downloadURI'
|
101
|
+
# @return [Boolean] true if backup was downloaded
|
102
|
+
def self.download_backup(client, local_drive_path, bundle_backup)
|
103
|
+
raise IncompleteResource, "Missing required attribute 'downloadURI'" unless bundle_backup['downloadURI']
|
104
|
+
client.download_file(bundle_backup['downloadURI'], local_drive_path)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Extracts the existing backup bundle on the appliance and creates all the artifacts.
|
108
|
+
# If there are any artifacts existing, they will be removed before the extract operation.
|
109
|
+
# @param [DeploymentGroup] deployment_group The DeploymentGroup with 'name' or 'uri'
|
110
|
+
# @param [ArtifactBundle] bundle_backup The backup ArtifactBundle with 'uri'
|
111
|
+
# @return [Boolean] true if backup bundle was extracted
|
112
|
+
# @raise [OneviewSDK::IncompleteResource] if the client or uri is not set
|
113
|
+
def self.extract_backup(client, deployment_group, bundle_backup)
|
114
|
+
ensure_resource!(deployment_group)
|
115
|
+
raise IncompleteResource, "Missing required attribute 'uri' of backup bundle" unless bundle_backup['uri']
|
116
|
+
id = bundle_backup['uri'].split('/').last
|
117
|
+
response = client.rest_put("#{BACKUPS_URI}/#{id}", 'body' => { 'deploymentGroupURI' => deployment_group['uri'] })
|
118
|
+
client.response_handler(response)
|
119
|
+
true
|
120
|
+
end
|
121
|
+
|
122
|
+
# Method is not available
|
123
|
+
# @raise [OneviewSDK::MethodUnavailable] method is not available
|
124
|
+
def update(*)
|
125
|
+
unavailable_method
|
126
|
+
end
|
127
|
+
|
128
|
+
# Update the name of Artifact Bundle
|
129
|
+
# @param [String] new_name Name to update the Artifact Bundle
|
130
|
+
# @return [Boolean] true if name was updated
|
131
|
+
# @raise [OneviewSDK::IncompleteResource] if the client or uri is not set
|
132
|
+
def update_name(new_name)
|
133
|
+
ensure_uri
|
134
|
+
response = @client.rest_put(@data['uri'], 'body' => { 'name' => new_name, 'type' => 'ArtifactsBundle' })
|
135
|
+
@client.response_handler(response)
|
136
|
+
@data['name'] = new_name
|
137
|
+
true
|
138
|
+
end
|
139
|
+
|
140
|
+
# Extracts the artifact bundle and creates the artifacts on the appliance
|
141
|
+
# @param [Boolean] force Forces the extract operation even when there are any conflicts
|
142
|
+
# @return [Boolean] true if artifact bundle was extracted
|
143
|
+
# @raise [OneviewSDK::IncompleteResource] if the client or uri is not set
|
144
|
+
def extract(force = true)
|
145
|
+
ensure_uri
|
146
|
+
options = { 'Content-Type' => 'text/plain' }
|
147
|
+
response = @client.rest_put(@data['uri'] + "?extract=true&forceImport=#{force}", options)
|
148
|
+
@client.response_handler(response)
|
149
|
+
true
|
150
|
+
end
|
151
|
+
|
152
|
+
# Downloads the content of the selected artifact bundle to the admin's local drive.
|
153
|
+
# @param [String] local_drive_path Path to save file downloaded
|
154
|
+
# @return [Boolean] true if the file was downloaded
|
155
|
+
def download(local_drive_path)
|
156
|
+
raise IncompleteResource, "Missing required attribute 'downloadURI'" unless @data['downloadURI']
|
157
|
+
client.download_file(@data['downloadURI'], local_drive_path)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Add a Build Plan to this ArtifactBundle
|
161
|
+
# @param [OneviewSDK::ImageStreamer::API300::BuildPlan] resource The BuildPlan resource with uri
|
162
|
+
# @param [TrueClass, FalseClass] read_only Indicates whether the BuildPlan will be readonly in artifact bundle package
|
163
|
+
# @raise [RuntimeError] if the BuildPlan uri is not set or it is not valid
|
164
|
+
def add_build_plan(resource, read_only = true)
|
165
|
+
add_resource(resource, 'buildPlans', read_only)
|
166
|
+
end
|
167
|
+
|
168
|
+
# Add a Plan Script to this ArtifactBundle
|
169
|
+
# @param [OneviewSDK::ImageStreamer::API300::PlanScript] resource The PlanScripts resource with uri
|
170
|
+
# @param [TrueClass, FalseClass] read_only Indicates whether the PlanScripts will be readonly in artifact bundle package
|
171
|
+
# @raise [RuntimeError] if the PlanScripts uri is not set or it is not valid
|
172
|
+
def add_plan_script(resource, read_only = true)
|
173
|
+
add_resource(resource, 'planScripts', read_only)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Add a Deployment Plan to this ArtifactBundle
|
177
|
+
# @param [OneviewSDK::ImageStreamer::API300::DeploymentPlans] resource The DeploymentPlans resource with uri
|
178
|
+
# @param [TrueClass, FalseClass] read_only Indicates whether the DeploymentPlans will be readonly in artifact bundle package
|
179
|
+
# @raise [RuntimeError] if the DeploymentPlans uri is not set or it is not valid
|
180
|
+
def add_deployment_plan(resource, read_only = true)
|
181
|
+
add_resource(resource, 'deploymentPlans', read_only)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Add a Golden Image to this ArtifactBundle
|
185
|
+
# @param [OneviewSDK::ImageStreamer::API300::GoldenImage] resource The GoldenImage resource with uri
|
186
|
+
# @param [TrueClass, FalseClass] read_only Indicates whether the GoldenImage will be readonly in artifact bundle package
|
187
|
+
# @raise [RuntimeError] if the GoldenImage uri is not set or it is not valid
|
188
|
+
def add_golden_image(resource, read_only = true)
|
189
|
+
add_resource(resource, 'goldenImages', read_only)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Fail unless resource can be retrieved
|
193
|
+
def self.ensure_resource!(resource)
|
194
|
+
raise IncompleteResource, "The resource #{resource.class} can not be retrieved. Ensure it can be retrieved." unless resource.retrieve!
|
195
|
+
end
|
196
|
+
|
197
|
+
# Fail unless file extension of file_path is in ACCEPTED_FORMATS array
|
198
|
+
def self.ensure_file_path_extension!(file_path)
|
199
|
+
raise InvalidFormat, "File extension should be #{ACCEPTED_FORMATS}" unless ACCEPTED_FORMATS.include?(File.extname(file_path))
|
200
|
+
end
|
201
|
+
|
202
|
+
private
|
203
|
+
|
204
|
+
# Add resource data to data hash
|
205
|
+
# @param [OneviewSDK::Resource] resource The resource with uri
|
206
|
+
# @param [String] key_name The hash key of data hash
|
207
|
+
# @param [TrueClass, FalseClass] read_only The value of readOnly attribute
|
208
|
+
def add_resource(resource, key_name, read_only)
|
209
|
+
self.class.ensure_resource!(resource)
|
210
|
+
@data[key_name] << { 'resourceUri' => resource['uri'], 'readOnly' => read_only }
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
@@ -15,11 +15,18 @@ module OneviewSDK
|
|
15
15
|
module ImageStreamer
|
16
16
|
module API300
|
17
17
|
# Build Plan resource implementation for Image Streamer
|
18
|
-
# @note This resource is unimplemented/unfinished at this point, so use at your own risk.
|
19
|
-
# This resource is subject to change drastically in the near future without a major version
|
20
|
-
# bump, which may break your code.
|
21
18
|
class BuildPlan < Resource
|
22
19
|
BASE_URI = '/rest/build-plans'.freeze
|
20
|
+
|
21
|
+
# Create a resource object, associate it with a client, and set its properties.
|
22
|
+
# @param [OneviewSDK::ImageStreamer::Client] client The client object for the Image Streamer appliance
|
23
|
+
# @param [Hash] params The options for this resource (key-value pairs)
|
24
|
+
# @param [Integer] api_ver The api version to use when interracting with this resource.
|
25
|
+
def initialize(client, params = {}, api_ver = nil)
|
26
|
+
super
|
27
|
+
# Default values:
|
28
|
+
@data['type'] ||= 'OeBuildPlan'
|
29
|
+
end
|
23
30
|
end
|
24
31
|
end
|
25
32
|
end
|
data/lib/oneview-sdk/image-streamer/resource/api300/{artifacts_bundle.rb → deployment_group.rb}
RENAMED
@@ -14,12 +14,27 @@ require_relative 'resource'
|
|
14
14
|
module OneviewSDK
|
15
15
|
module ImageStreamer
|
16
16
|
module API300
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
# Deployment Group resource implementation for Image Streamer
|
18
|
+
class DeploymentGroup < Resource
|
19
|
+
BASE_URI = '/rest/deployment-groups'.freeze
|
20
|
+
|
21
|
+
# Method is not available
|
22
|
+
# @raise [OneviewSDK::MethodUnavailable] method is not available
|
23
|
+
def create(*)
|
24
|
+
unavailable_method
|
25
|
+
end
|
26
|
+
|
27
|
+
# Method is not available
|
28
|
+
# @raise [OneviewSDK::MethodUnavailable] method is not available
|
29
|
+
def update(*)
|
30
|
+
unavailable_method
|
31
|
+
end
|
32
|
+
|
33
|
+
# Method is not available
|
34
|
+
# @raise [OneviewSDK::MethodUnavailable] method is not available
|
35
|
+
def delete(*)
|
36
|
+
unavailable_method
|
37
|
+
end
|
23
38
|
end
|
24
39
|
end
|
25
40
|
end
|
@@ -15,11 +15,18 @@ module OneviewSDK
|
|
15
15
|
module ImageStreamer
|
16
16
|
module API300
|
17
17
|
# Deployment Plan resource implementation for Image Streamer
|
18
|
-
# @note This resource is unimplemented/unfinished at this point, so use at your own risk.
|
19
|
-
# This resource is subject to change drastically in the near future without a major version
|
20
|
-
# bump, which may break your code.
|
21
18
|
class DeploymentPlan < Resource
|
22
19
|
BASE_URI = '/rest/deployment-plans'.freeze
|
20
|
+
|
21
|
+
# Create a resource object, associate it with a client, and set its properties.
|
22
|
+
# @param [OneviewSDK::ImageStreamer::Client] client The client object for the Image Streamer appliance
|
23
|
+
# @param [Hash] params The options for this resource (key-value pairs)
|
24
|
+
# @param [Integer] api_ver The api version to use when interracting with this resource.
|
25
|
+
def initialize(client, params = {}, api_ver = nil)
|
26
|
+
super
|
27
|
+
# Default values:
|
28
|
+
@data['type'] ||= 'OEDeploymentPlan'
|
29
|
+
end
|
23
30
|
end
|
24
31
|
end
|
25
32
|
end
|
@@ -10,16 +10,134 @@
|
|
10
10
|
# language governing permissions and limitations under the License.
|
11
11
|
|
12
12
|
require_relative 'resource'
|
13
|
+
require 'net/http/post/multipart'
|
13
14
|
|
14
15
|
module OneviewSDK
|
15
16
|
module ImageStreamer
|
16
17
|
module API300
|
17
18
|
# Golden Image resource implementation for Image Streamer
|
18
|
-
# @note This resource is unimplemented/unfinished at this point, so use at your own risk.
|
19
|
-
# This resource is subject to change drastically in the near future without a major version
|
20
|
-
# bump, which may break your code.
|
21
19
|
class GoldenImage < Resource
|
22
20
|
BASE_URI = '/rest/golden-images'.freeze
|
21
|
+
READ_TIMEOUT = 300 # in seconds (5 minutes)
|
22
|
+
ACCEPTED_FORMATS = %w(.zip .ZIP).freeze # Supported upload extensions
|
23
|
+
|
24
|
+
# Create a resource object, associate it with a client, and set its properties.
|
25
|
+
# @param [OneviewSDK::ImageStreamer::Client] client The client object for the Image Streamer appliance
|
26
|
+
# @param [Hash] params The options for this resource (key-value pairs)
|
27
|
+
# @param [Integer] api_ver The api version to use when interracting with this resource.
|
28
|
+
def initialize(client, params = {}, api_ver = nil)
|
29
|
+
super
|
30
|
+
# Default values:
|
31
|
+
@data['type'] ||= 'GoldenImage'
|
32
|
+
end
|
33
|
+
|
34
|
+
# Download the details of the golden image capture logs which has been archived based on the specific attribute ID.
|
35
|
+
# @param [String] file_path
|
36
|
+
# @return [True] When was saved successfully
|
37
|
+
def download_details_archive(file_path)
|
38
|
+
ensure_client && ensure_uri
|
39
|
+
resp = @client.rest_api(:get, "#{BASE_URI}/archive/#{@data['uri'].split('/').last}")
|
40
|
+
File.open(file_path, 'wb') { |file| file.write(resp.body) }
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
# Downloads the content of the selected golden image to the specified file path.
|
45
|
+
# @param [String] file_path
|
46
|
+
# @param [Integer] timeout The number of seconds to wait for the request to complete
|
47
|
+
# @return [True] When was saved successfully
|
48
|
+
def download(file_path, timeout = READ_TIMEOUT)
|
49
|
+
ensure_client && ensure_uri
|
50
|
+
uri = URI.parse(URI.escape("#{client.url}#{BASE_URI}/download/#{@data['uri'].split('/').last}"))
|
51
|
+
req = Net::HTTP::Get.new(uri.request_uri)
|
52
|
+
|
53
|
+
options = {}
|
54
|
+
options['Content-Type'] = 'application/json'
|
55
|
+
options['X-Api-Version'] = @client.api_version.to_s
|
56
|
+
options['auth'] = @client.token
|
57
|
+
options.each do |key, val|
|
58
|
+
req[key] = val
|
59
|
+
end
|
60
|
+
|
61
|
+
http_request = Net::HTTP.new(uri.host, uri.port)
|
62
|
+
http_request.use_ssl = true
|
63
|
+
http_request.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
64
|
+
http_request.read_timeout = timeout
|
65
|
+
|
66
|
+
http_request.start do |http|
|
67
|
+
http.request(req) do |res|
|
68
|
+
client.response_handler(res) unless res.code.to_i.between?(200, 204)
|
69
|
+
File.open(file_path, 'wb') do |file|
|
70
|
+
res.read_body do |segment|
|
71
|
+
file.write(segment)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
true
|
77
|
+
end
|
78
|
+
|
79
|
+
# Upload a golden image from the specified local file path.
|
80
|
+
# Only the .zip format file can be used for upload.
|
81
|
+
# @param [OneviewSDK::ImageStreamer::Client] client The client object for the Image Streamer appliance
|
82
|
+
# @param [String] file_path
|
83
|
+
# @param [Hash] data_options Attributes of the golden image, passed in the request
|
84
|
+
# @option data_options [String] :name The name of the Golden Image (required)
|
85
|
+
# @option data_options [String] :description The description of the Golden Image (required)
|
86
|
+
# @param [Integer] timeout The number of seconds to wait for the request to complete
|
87
|
+
# @return [OneviewSDK::ImageStreamer::API300::GoldenImage] if the upload was successful, return a GoldenImage object
|
88
|
+
def self.add(client, file_path, data_options, timeout = READ_TIMEOUT)
|
89
|
+
data_options = Hash[data_options.map { |k, v| [k.to_s, v] }] # Convert symbols hash keys to string
|
90
|
+
raise NotFound, "ERROR: File '#{file_path}' not found!" unless File.file?(file_path)
|
91
|
+
raise InvalidFormat, 'ERROR: File with extension not supported!' unless ACCEPTED_FORMATS.include? File.extname(file_path)
|
92
|
+
raise IncompleteResource, 'Please set the name of the golden image!' unless data_options['name']
|
93
|
+
raise IncompleteResource, 'Please set the description of the golden image!' unless data_options['description']
|
94
|
+
options = {}
|
95
|
+
options['Content-Type'] = 'multipart/form-data'
|
96
|
+
options['X-Api-Version'] = client.api_version.to_s
|
97
|
+
options['auth'] = client.token
|
98
|
+
options['file'] = File.basename(file_path)
|
99
|
+
url = URI.parse(URI.escape("#{client.url}#{BASE_URI}"))
|
100
|
+
|
101
|
+
File.open(file_path) do |file|
|
102
|
+
req = Net::HTTP::Post::Multipart.new(
|
103
|
+
url.path,
|
104
|
+
{ 'file' => UploadIO.new(file, 'application/octet-stream', File.basename(file_path)) }.merge(data_options),
|
105
|
+
options
|
106
|
+
)
|
107
|
+
|
108
|
+
http_request = Net::HTTP.new(url.host, url.port)
|
109
|
+
http_request.use_ssl = true if url.scheme == 'https'
|
110
|
+
if client.ssl_enabled
|
111
|
+
http_request.cert_store = client.cert_store if client.cert_store
|
112
|
+
else http_request.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
113
|
+
end
|
114
|
+
http_request.read_timeout = timeout
|
115
|
+
|
116
|
+
http_request.start do |http|
|
117
|
+
response = http.request(req)
|
118
|
+
data = client.response_handler(response)
|
119
|
+
return OneviewSDK::ImageStreamer::API300::GoldenImage.new(client, data)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Sets the OS volume
|
125
|
+
# @param [OneviewSDK::ImageStreamer::API300::OSVolume] os_volume
|
126
|
+
# @raise [OneviewSDK::NotFound] if the os volume uri is not set and cannot be retrieved
|
127
|
+
def set_os_volume(os_volume)
|
128
|
+
os_volume.retrieve! unless os_volume['uri']
|
129
|
+
raise NotFound, 'The os volume was not found!' unless os_volume['uri']
|
130
|
+
set('osVolumeURI', os_volume['uri'])
|
131
|
+
end
|
132
|
+
|
133
|
+
# Sets the build plan
|
134
|
+
# @param [OneviewSDK::ImageStreamer::API300::BuildPlan] build_plan
|
135
|
+
# @raise [OneviewSDK::NotFound] if the build plan uri is not set and cannot be retrieved
|
136
|
+
def set_build_plan(build_plan)
|
137
|
+
build_plan.retrieve! unless build_plan['uri']
|
138
|
+
raise NotFound, 'The build plan was not found!' unless build_plan['uri']
|
139
|
+
set('buildPlanUri', build_plan['uri'])
|
140
|
+
end
|
23
141
|
end
|
24
142
|
end
|
25
143
|
end
|
data/lib/oneview-sdk/resource.rb
CHANGED
@@ -31,7 +31,8 @@ module OneviewSDK
|
|
31
31
|
# @param [Integer] api_ver The api version to use when interracting with this resource.
|
32
32
|
# Defaults to the client.api_version if it exists, or the OneviewSDK::Client::DEFAULT_API_VERSION.
|
33
33
|
def initialize(client, params = {}, api_ver = nil)
|
34
|
-
raise InvalidClient, 'Must specify a valid client'
|
34
|
+
raise InvalidClient, 'Must specify a valid client'\
|
35
|
+
unless client.is_a?(OneviewSDK::Client) || client.is_a?(OneviewSDK::ImageStreamer::Client)
|
35
36
|
@client = client
|
36
37
|
@logger = @client.logger
|
37
38
|
@api_version = api_ver || @client.api_version
|
@@ -364,9 +365,8 @@ module OneviewSDK
|
|
364
365
|
# @param [String] variant API module variant to fetch resource from
|
365
366
|
# @return [Class] Resource class or nil if not found
|
366
367
|
def self.resource_named(type, api_ver = @api_version, variant = nil)
|
367
|
-
|
368
|
-
|
369
|
-
end
|
368
|
+
raise UnsupportedVersion, "API version #{api_ver} is not supported! Try one of: #{SUPPORTED_API_VERSIONS}"\
|
369
|
+
unless SUPPORTED_API_VERSIONS.include?(api_ver)
|
370
370
|
api_module = OneviewSDK.const_get("API#{api_ver}")
|
371
371
|
variant ? api_module.resource_named(type, variant) : api_module.resource_named(type)
|
372
372
|
end
|
@@ -21,7 +21,7 @@ module OneviewSDK
|
|
21
21
|
new_type = type.to_s.downcase.gsub(/[ -_]/, '')
|
22
22
|
constants.each do |c|
|
23
23
|
klass = const_get(c)
|
24
|
-
next unless klass.is_a?(Class)
|
24
|
+
next unless klass.is_a?(Class)
|
25
25
|
name = klass.name.split('::').last.downcase.delete('_').delete('-')
|
26
26
|
return klass if new_type =~ /^#{name}[s]?$/
|
27
27
|
end
|
@@ -22,7 +22,7 @@ module OneviewSDK
|
|
22
22
|
# @param [OneviewSDK::Client] client The client object for the OneView appliance
|
23
23
|
# @param [String] file_path
|
24
24
|
# @param [Integer] timeout The number of seconds to wait for completing the request
|
25
|
-
# @return [OneviewSDK::FirmwareDriver] if the upload was
|
25
|
+
# @return [OneviewSDK::FirmwareDriver] if the upload was successful, return a FirmwareDriver object
|
26
26
|
def self.add(client, file_path, timeout = READ_TIMEOUT)
|
27
27
|
raise NotFound, "ERROR: File '#{file_path}' not found!" unless File.file?(file_path)
|
28
28
|
options = {}
|
@@ -45,9 +45,16 @@ module OneviewSDK
|
|
45
45
|
http_request.read_timeout = timeout
|
46
46
|
|
47
47
|
http_request.start do |http|
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
begin
|
49
|
+
response = http.request(req)
|
50
|
+
data = client.response_handler(response)
|
51
|
+
return OneviewSDK::FirmwareDriver.new(client, data)
|
52
|
+
rescue Net::ReadTimeout
|
53
|
+
raise "The connection was closed because the timeout of #{timeout} seconds has expired."\
|
54
|
+
'You can specify the timeout in seconds by passing the timeout on the method call.'\
|
55
|
+
'Interrupted firmware uploads may result in corrupted firmware remaining in the appliance.'\
|
56
|
+
'HPE recommends checking the appliance for corrupted firmware and removing it.'
|
57
|
+
end
|
51
58
|
end
|
52
59
|
end
|
53
60
|
end
|
@@ -60,7 +60,7 @@ module OneviewSDK
|
|
60
60
|
type: 'ExtraUnmanagedStorageVolumes',
|
61
61
|
resourceUri: resource['uri']
|
62
62
|
}
|
63
|
-
response = client.rest_post(BASE_URI + '/repair', 'body' => requestBody)
|
63
|
+
response = client.rest_post(BASE_URI + '/repair', { 'Accept-Language' => 'en_US', 'body' => requestBody }, client.api_version)
|
64
64
|
client.response_handler(response)
|
65
65
|
end
|
66
66
|
|
@@ -27,7 +27,7 @@ module OneviewSDK
|
|
27
27
|
api_module = OneviewSDK::API300.const_get(variant)
|
28
28
|
api_module.constants.each do |c|
|
29
29
|
klass = api_module.const_get(c)
|
30
|
-
next unless klass.is_a?(Class)
|
30
|
+
next unless klass.is_a?(Class)
|
31
31
|
name = klass.name.split('::').last.downcase.delete('_').delete('-')
|
32
32
|
return klass if new_type =~ /^#{name}[s]?$/
|
33
33
|
end
|
@@ -10,20 +10,20 @@
|
|
10
10
|
# language governing permissions and limitations under the License.
|
11
11
|
|
12
12
|
require_relative '../../api200/switch'
|
13
|
+
require_relative 'scope'
|
13
14
|
|
14
15
|
module OneviewSDK
|
15
16
|
module API300
|
16
17
|
module C7000
|
17
18
|
# Switch resource implementation
|
18
19
|
class Switch < OneviewSDK::API200::Switch
|
20
|
+
include OneviewSDK::API300::C7000::Scope::ScopeHelperMethods
|
19
21
|
|
20
22
|
# Updates the scope URIs of a specific switch
|
21
23
|
# @param [Array] scope_uris Array of scope uri strings
|
24
|
+
# @deprecated Use {#add_scope}, {#remove_scope}, and {#replace_scopes} instead.
|
22
25
|
def set_scope_uris(scope_uris)
|
23
|
-
|
24
|
-
body = { op: 'replace', path: '/scopeUris', value: scope_uris }
|
25
|
-
response = @client.rest_patch(@data['uri'], { 'body' => [body] }, @api_version)
|
26
|
-
@client.response_handler(response)
|
26
|
+
patch('replace', '/scopeUris', scope_uris)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
data/lib/oneview-sdk/rest.rb
CHANGED
@@ -13,10 +13,13 @@ require 'uri'
|
|
13
13
|
require 'net/http'
|
14
14
|
require 'openssl'
|
15
15
|
require 'json'
|
16
|
+
require 'net/http/post/multipart'
|
16
17
|
|
17
18
|
module OneviewSDK
|
18
19
|
# Contains all of the methods for making API REST calls
|
19
20
|
module Rest
|
21
|
+
READ_TIMEOUT = 300 # in seconds, 5 minutes
|
22
|
+
|
20
23
|
# Makes a restful API request to OneView
|
21
24
|
# @param [Symbol] type The rest method/type Options: [:get, :post, :delete, :patch, :put]
|
22
25
|
# @param [String] path The path for the request. Usually starts with "/rest/"
|
@@ -32,17 +35,8 @@ module OneviewSDK
|
|
32
35
|
def rest_api(type, path, options = {}, api_ver = @api_version, redirect_limit = 3)
|
33
36
|
@logger.debug "Making :#{type} rest call to #{@url}#{path}"
|
34
37
|
raise InvalidRequest, 'Must specify path' unless path
|
35
|
-
|
36
38
|
uri = URI.parse(URI.escape(@url + path))
|
37
|
-
http =
|
38
|
-
http.use_ssl = true if uri.scheme == 'https'
|
39
|
-
if @ssl_enabled
|
40
|
-
http.cert_store = @cert_store if @cert_store
|
41
|
-
else http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
42
|
-
end
|
43
|
-
http.read_timeout = @timeout if @timeout # Timeout for a request
|
44
|
-
http.open_timeout = @timeout if @timeout # Timeout for a connection
|
45
|
-
|
39
|
+
http = build_http_object(uri)
|
46
40
|
request = build_request(type, uri, options.dup, api_ver)
|
47
41
|
response = http.request(request)
|
48
42
|
@logger.debug " Response: Code=#{response.code}. Headers=#{response.to_hash}\n Body=#{response.body}"
|
@@ -121,6 +115,64 @@ module OneviewSDK
|
|
121
115
|
rest_api(:delete, path, options, api_ver)
|
122
116
|
end
|
123
117
|
|
118
|
+
# Uploads a file to a specific uri
|
119
|
+
# @param [String] file_path
|
120
|
+
# @param [String] path The url path starting with "/"
|
121
|
+
# @param [Hash] body_params The params to append to body of http request. Default is {}.
|
122
|
+
# @option body_params [String] 'name' The name to show (when resource accepts a name)
|
123
|
+
# @param [Integer] timeout The number of seconds to wait for completing the request. Default is 300.
|
124
|
+
# @return [Hash] The parsed JSON body of response
|
125
|
+
def upload_file(file_path, path, body_params = {}, timeout = READ_TIMEOUT)
|
126
|
+
raise NotFound, "ERROR: File '#{file_path}' not found!" unless File.file?(file_path)
|
127
|
+
options = {
|
128
|
+
'Content-Type' => 'multipart/form-data',
|
129
|
+
'X-Api-Version' => @api_version.to_s,
|
130
|
+
'auth' => @token
|
131
|
+
}
|
132
|
+
|
133
|
+
File.open(file_path) do |file|
|
134
|
+
name_to_show = body_params.delete('name') || body_params.delete(:name) || File.basename(file_path)
|
135
|
+
body_params['file'] = UploadIO.new(file, 'application/octet-stream', name_to_show)
|
136
|
+
|
137
|
+
uri = URI.parse(URI.escape(@url + path))
|
138
|
+
http_request = build_http_object(uri)
|
139
|
+
http_request.read_timeout = timeout
|
140
|
+
|
141
|
+
req = Net::HTTP::Post::Multipart.new(
|
142
|
+
uri.path,
|
143
|
+
body_params,
|
144
|
+
options
|
145
|
+
)
|
146
|
+
|
147
|
+
http_request.start do |http|
|
148
|
+
response = http.request(req)
|
149
|
+
return response_handler(response)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Download a file from a specific uri
|
155
|
+
# @param [String] path The url path starting with "/"
|
156
|
+
# @param [String] local_drive_path Path to save file downloaded
|
157
|
+
# @return [Boolean] if file was downloaded
|
158
|
+
def download_file(path, local_drive_path)
|
159
|
+
uri = URI.parse(URI.escape(@url + path))
|
160
|
+
http_request = build_http_object(uri)
|
161
|
+
req = build_request(:get, uri, {}, @api_version.to_s)
|
162
|
+
|
163
|
+
http_request.start do |http|
|
164
|
+
http.request(req) do |res|
|
165
|
+
response_handler(res) unless res.code.to_i.between?(200, 204)
|
166
|
+
File.open(local_drive_path, 'wb') do |file|
|
167
|
+
res.read_body do |segment|
|
168
|
+
file.write(segment)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
true
|
174
|
+
end
|
175
|
+
|
124
176
|
RESPONSE_CODE_OK = 200
|
125
177
|
RESPONSE_CODE_CREATED = 201
|
126
178
|
RESPONSE_CODE_ACCEPTED = 202
|
@@ -133,8 +185,7 @@ module OneviewSDK
|
|
133
185
|
# If an asynchronous task was started, this waits for it to complete.
|
134
186
|
# @param [HTTPResponse] response HTTP response
|
135
187
|
# @param [Boolean] wait_on_task Wait on task (or just return task details)
|
136
|
-
# @raise [
|
137
|
-
# @raise [StandardError] if a task was returned that did not complete successfully
|
188
|
+
# @raise [OneviewSDK::OneViewError] if the request failed or a task did not complete successfully
|
138
189
|
# @return [Hash] The parsed JSON body
|
139
190
|
def response_handler(response, wait_on_task = true)
|
140
191
|
case response.code.to_i
|
@@ -158,19 +209,32 @@ module OneviewSDK
|
|
158
209
|
when RESPONSE_CODE_NO_CONTENT # Synchronous delete
|
159
210
|
return {}
|
160
211
|
when RESPONSE_CODE_BAD_REQUEST
|
161
|
-
raise
|
212
|
+
BadRequest.raise! "400 BAD REQUEST #{response.body}", response
|
162
213
|
when RESPONSE_CODE_UNAUTHORIZED
|
163
|
-
raise
|
214
|
+
Unauthorized.raise! "401 UNAUTHORIZED #{response.body}", response
|
164
215
|
when RESPONSE_CODE_NOT_FOUND
|
165
|
-
raise
|
216
|
+
NotFound.raise! "404 NOT FOUND #{response.body}", response
|
166
217
|
else
|
167
|
-
raise
|
218
|
+
RequestError.raise! "#{response.code} #{response.body}", response
|
168
219
|
end
|
169
220
|
end
|
170
221
|
|
171
222
|
|
172
223
|
private
|
173
224
|
|
225
|
+
# Builds a http object using the data given
|
226
|
+
def build_http_object(uri)
|
227
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
228
|
+
http.use_ssl = true if uri.scheme == 'https'
|
229
|
+
if @ssl_enabled
|
230
|
+
http.cert_store = @cert_store if @cert_store
|
231
|
+
else http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
232
|
+
end
|
233
|
+
http.read_timeout = @timeout if @timeout # Timeout for a request
|
234
|
+
http.open_timeout = @timeout if @timeout # Timeout for a connection
|
235
|
+
http
|
236
|
+
end
|
237
|
+
|
174
238
|
# Builds a request object using the data given
|
175
239
|
def build_request(type, uri, options, api_ver)
|
176
240
|
case type.downcase.to_sym
|
data/lib/oneview-sdk/version.rb
CHANGED
data/oneview-sdk.gemspec
CHANGED
@@ -34,11 +34,11 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_runtime_dependency 'pry'
|
35
35
|
spec.add_runtime_dependency 'multipart-post'
|
36
36
|
|
37
|
+
spec.add_development_dependency 'coveralls'
|
37
38
|
spec.add_development_dependency 'bundler'
|
38
|
-
spec.add_development_dependency '
|
39
|
+
spec.add_development_dependency 'byebug'
|
39
40
|
spec.add_development_dependency 'rake'
|
40
|
-
spec.add_development_dependency '
|
41
|
+
spec.add_development_dependency 'rspec'
|
41
42
|
spec.add_development_dependency 'rubocop', '= 0.42.0'
|
42
|
-
spec.add_development_dependency '
|
43
|
-
|
43
|
+
spec.add_development_dependency 'simplecov'
|
44
44
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oneview-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henrique Diomede
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2017-02-
|
14
|
+
date: 2017-02-24 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: thor
|
@@ -69,6 +69,20 @@ dependencies:
|
|
69
69
|
- - ">="
|
70
70
|
- !ruby/object:Gem::Version
|
71
71
|
version: '0'
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: coveralls
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
72
86
|
- !ruby/object:Gem::Dependency
|
73
87
|
name: bundler
|
74
88
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,7 +98,7 @@ dependencies:
|
|
84
98
|
- !ruby/object:Gem::Version
|
85
99
|
version: '0'
|
86
100
|
- !ruby/object:Gem::Dependency
|
87
|
-
name:
|
101
|
+
name: byebug
|
88
102
|
requirement: !ruby/object:Gem::Requirement
|
89
103
|
requirements:
|
90
104
|
- - ">="
|
@@ -112,7 +126,7 @@ dependencies:
|
|
112
126
|
- !ruby/object:Gem::Version
|
113
127
|
version: '0'
|
114
128
|
- !ruby/object:Gem::Dependency
|
115
|
-
name:
|
129
|
+
name: rspec
|
116
130
|
requirement: !ruby/object:Gem::Requirement
|
117
131
|
requirements:
|
118
132
|
- - ">="
|
@@ -140,7 +154,7 @@ dependencies:
|
|
140
154
|
- !ruby/object:Gem::Version
|
141
155
|
version: 0.42.0
|
142
156
|
- !ruby/object:Gem::Dependency
|
143
|
-
name:
|
157
|
+
name: simplecov
|
144
158
|
requirement: !ruby/object:Gem::Requirement
|
145
159
|
requirements:
|
146
160
|
- - ">="
|
@@ -176,8 +190,9 @@ files:
|
|
176
190
|
- lib/oneview-sdk/config_loader.rb
|
177
191
|
- lib/oneview-sdk/exceptions.rb
|
178
192
|
- lib/oneview-sdk/image-streamer/client.rb
|
179
|
-
- lib/oneview-sdk/image-streamer/resource/api300/
|
193
|
+
- lib/oneview-sdk/image-streamer/resource/api300/artifact_bundle.rb
|
180
194
|
- lib/oneview-sdk/image-streamer/resource/api300/build_plan.rb
|
195
|
+
- lib/oneview-sdk/image-streamer/resource/api300/deployment_group.rb
|
181
196
|
- lib/oneview-sdk/image-streamer/resource/api300/deployment_plan.rb
|
182
197
|
- lib/oneview-sdk/image-streamer/resource/api300/golden_image.rb
|
183
198
|
- lib/oneview-sdk/image-streamer/resource/api300/os_volume.rb
|