secured_cloud_api_client 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 916195ff166c0e20fa129e31f298034f147678dc
4
+ data.tar.gz: 0897f1d09d6f64740314bd33dfb90a29d8495a6f
5
+ SHA512:
6
+ metadata.gz: a2d734f61a03dfcb7966accd27efa0a90ecafcfda80d87f6057d50ede2f7c613c457701ce27c39fec398227b8d3fee6c8658b95fd02bc113a962a3aea01af0a7
7
+ data.tar.gz: a337d3ae467d0e7362f044633b3c2aae233120b3c9dfb2add5698bee7ead8e2a2563daa5ffd31476c0b3d86b8b5d8776647c2ede88264d47a4af6f4bf90f84be
@@ -0,0 +1,151 @@
1
+ require 'net/http'
2
+ require 'openssl'
3
+ require 'base64'
4
+
5
+
6
+ ##
7
+ # Class HttpClient performs HTTP requests to the Secured Cloud API Server.
8
+ # Authentication is handled via the supplied application key and shared secret.
9
+ #
10
+ # @author:: Alan Vella
11
+ ##
12
+
13
+ class HttpClient
14
+
15
+
16
+ APP_CONTENT_TYPE = "application/vnd.securedcloud.v7.0+json"
17
+ AUTH_SCHEME = "SC "
18
+
19
+
20
+ #Sends an HTTP GET request and returns response.
21
+ def self.sendGETRequest(authInfo, url)
22
+
23
+ @applicationKey = authInfo.getApplicationKey()
24
+ @sharedSecret = authInfo.getSharedSecret()
25
+
26
+ @url = URI.parse(url)
27
+ req = Net::HTTP::Get.new(url)
28
+
29
+ #Populate header with required stuff.
30
+ req['Accept'] = APP_CONTENT_TYPE
31
+ req['Authorization'] = AUTH_SCHEME + createAuthorization("GET", url)
32
+
33
+ #Execute request.
34
+ res = Net::HTTP.start(@url.host, @url.port) {|http|http.request(req)} # Net::HTTPResponse object
35
+
36
+ #Return response.
37
+ return res
38
+ end
39
+
40
+
41
+ #Sends an HTTP POST request and returns response.
42
+ def self.sendPOSTRequest(authInfo, url, body)
43
+
44
+ @applicationKey = authInfo.getApplicationKey()
45
+ @sharedSecret = authInfo.getSharedSecret()
46
+
47
+ @url = URI.parse(url)
48
+ req = Net::HTTP::Post.new(url)
49
+ req.body = body
50
+
51
+ #Populate header with required stuff.
52
+ req['Accept'] = APP_CONTENT_TYPE
53
+ req['Content-Type'] = APP_CONTENT_TYPE
54
+ req['Authorization'] = AUTH_SCHEME + createAuthorization("POST", url)
55
+
56
+ #Execute request.
57
+ res = Net::HTTP.start(@url.host, @url.port) {|http|http.request(req)} # Net::HTTPResponse object
58
+
59
+ #Return response.
60
+ return res
61
+ end
62
+
63
+
64
+ #Sends an HTTP DELETE request and returns response.
65
+ def self.sendDELETERequest(authInfo, url, params = nil)
66
+
67
+ @applicationKey = authInfo.getApplicationKey()
68
+ @sharedSecret = authInfo.getSharedSecret()
69
+
70
+ #Add parameters if present
71
+ if (params != nil) then
72
+ url += "?"
73
+ params.each do |param|
74
+ url += param[0] + "=" + param[1] + "&"
75
+ end
76
+
77
+ #Remove last ampersand
78
+ url = url[0...-1]
79
+ end
80
+
81
+ @url = URI.parse(url)
82
+ req = Net::HTTP::Delete.new(@url)
83
+
84
+ #Populate header with required stuff.
85
+ req['Accept'] = APP_CONTENT_TYPE
86
+ req['Content-Type'] = APP_CONTENT_TYPE
87
+ req['Authorization'] = AUTH_SCHEME + createAuthorization("DELETE", url)
88
+
89
+ #Execute request.
90
+ res = Net::HTTP.start(@url.host, @url.port) {|http|http.request(req)} # Net::HTTPResponse object
91
+
92
+ #Return response.
93
+ return res
94
+
95
+ end
96
+
97
+
98
+ #Sends an HTTP PUT request and returns response.
99
+ def self.sendPUTRequest(authInfo, url, params = nil)
100
+
101
+ @applicationKey = authInfo.getApplicationKey()
102
+ @sharedSecret = authInfo.getSharedSecret()
103
+
104
+ #Add parameters if present
105
+ if (params != nil) then
106
+ url += "?"
107
+ params.each do |param|
108
+ url += param[0] + "=" + param[1] + "&"
109
+ end
110
+ #Remove last ampersand
111
+ url = url[0...-1]
112
+ end
113
+
114
+ @url = URI.parse(url)
115
+ req = Net::HTTP::Put.new(@url)
116
+
117
+ #Populate header with required stuff.
118
+ req['Accept'] = APP_CONTENT_TYPE
119
+ req['Content-Type'] = APP_CONTENT_TYPE
120
+ req['Authorization'] = AUTH_SCHEME + createAuthorization("PUT", url)
121
+
122
+ #Execute request.
123
+ res = Net::HTTP.start(@url.host, @url.port) {|http|http.request(req)} # Net::HTTPResponse object
124
+
125
+ #Return response.
126
+ return res
127
+
128
+ end
129
+
130
+
131
+ #Removes the servlet name from a given external API URL.
132
+ def self.removeServletName(url)
133
+ urlAsArray = url.split("/");
134
+ newURL = ""
135
+ for i in 4..(urlAsArray.size() - 1)
136
+ newURL += "/" + urlAsArray[i]
137
+ end
138
+ return newURL
139
+ end
140
+
141
+
142
+ #Creates authorization header for a given method and URL.
143
+ def self.createAuthorization(method, url)
144
+ stringToSign = method + " " + removeServletName(url) + " " + @applicationKey
145
+ hash = OpenSSL::HMAC.digest('sha256', @sharedSecret, stringToSign)
146
+ requestSignature = Base64.encode64(hash).gsub(/\s+/, ' ').strip
147
+ credentials = @applicationKey + ":" + requestSignature;
148
+ encodedCredentials = Base64.encode64(credentials).gsub(/\s+/, ' ').strip
149
+ return encodedCredentials
150
+ end
151
+ end
@@ -0,0 +1,34 @@
1
+
2
+ ##
3
+ # A mapping between a set of public IPs and a private IP.
4
+ #
5
+ # @author:: Alan Vella
6
+ ##
7
+
8
+ class IpMapping
9
+
10
+
11
+ def initialize(privateIp, publicIps)
12
+ @privateIp = privateIp
13
+ @publicIps = publicIps
14
+ end
15
+
16
+
17
+ def get_details()
18
+ s = ""
19
+ if (@publicIps == nil) then
20
+ s = " Public IPs [ - ] => "
21
+ else
22
+ s = " Public IPs [" + @publicIps.join(", ") + "] => "
23
+ end
24
+ s += " Private IP [" + @privateIp + "]"
25
+ return s
26
+ end
27
+
28
+
29
+ def get_public_ips()
30
+ return @publicIps
31
+ end
32
+
33
+
34
+ end
@@ -0,0 +1,51 @@
1
+
2
+ ##
3
+ # OS Templates for creating new virtual machines.
4
+ #
5
+ # @author:: Alan Vella
6
+ ##
7
+
8
+ class OsTemplate
9
+
10
+
11
+ def initialize(name, version, minimumStorageSpace, defaultAdministratorUsername, diskExpandable)
12
+ @name = name
13
+ @version = version
14
+ @minimumStorageSpace = minimumStorageSpace
15
+ @defaultAdministratorUsername = defaultAdministratorUsername
16
+ @diskExpandable = diskExpandable
17
+ end
18
+
19
+
20
+ def get_details()
21
+ details = "Name : #{@name}\n"
22
+ details += "Version : #{@version}\n"
23
+ details += "Minimum Storage Space in Gb: #{@minimumStorageSpace}\n"
24
+ details += "Default Admin Username : #{@defaultAdministratorUsername}\n"
25
+ details += "Disk Expandable : #{@diskExpandable}\n"
26
+ return details
27
+ end
28
+
29
+
30
+ def get_name
31
+ return @name
32
+ end
33
+
34
+ def get_version
35
+ return @version
36
+ end
37
+
38
+ def get_minimum_storage_space
39
+ return @minimumStorageSpace
40
+ end
41
+
42
+ def get_administrator_username
43
+ return @defaultAdministratorUsername
44
+ end
45
+
46
+ def get_disk_expandable
47
+ return @diskExpandable
48
+ end
49
+
50
+
51
+ end
@@ -0,0 +1,43 @@
1
+
2
+ ##
3
+ # Class SecuredCloudConnection stores the details of a connection to the Secured Cloud API.
4
+ # An object of this type is needed whenever making calls to the API.
5
+ #
6
+ # @author:: Alan Vella
7
+ ##
8
+
9
+ class SecuredCloudConnection
10
+
11
+ #The URL must be in the format "http://10.239.32.201:8080/cloud-external-api-rest"
12
+ def initialize(url, applicationKey, sharedSecret)
13
+
14
+ #validation
15
+ raise ArgumentError, 'SecuredCloudConnection URL needs to be initialized' unless url != nil
16
+ raise ArgumentError, 'SecuredCloudConnection URL needs to be a valid string' unless url.respond_to?(:to_str)
17
+ raise ArgumentError, 'SecuredCloudConnection applicationKey needs to be initialized' unless applicationKey != nil
18
+ raise ArgumentError, 'SecuredCloudConnection applicationKey needs to be a valid string' unless applicationKey.respond_to?(:to_str)
19
+ raise ArgumentError, 'SecuredCloudConnection sharedSecret needs to be initialized' unless sharedSecret != nil
20
+ raise ArgumentError, 'SecuredCloudConnection sharedSecret needs to be a valid string' unless sharedSecret.respond_to?(:to_str)
21
+
22
+ @url = url
23
+ @applicationKey = applicationKey
24
+ @sharedSecret = sharedSecret
25
+
26
+ end
27
+
28
+
29
+ def getUrl
30
+ return @url
31
+ end
32
+
33
+
34
+ def getApplicationKey
35
+ return @applicationKey
36
+ end
37
+
38
+
39
+ def getSharedSecret
40
+ return @sharedSecret
41
+ end
42
+
43
+ end
@@ -0,0 +1,62 @@
1
+
2
+ ##
3
+ # Status of asynchronous tasks in Secured Cloud.
4
+ #
5
+ # @author:: Alan Vella
6
+ ##
7
+
8
+ class TaskStatus
9
+
10
+
11
+ def initialize(percentageComplete, requestStateEnum, result, errorCode, errorMessage, latestTaskDescription, processDescription, createdTimestamp, lastUpdatedTimeStamp)
12
+ @percentageComplete = percentageComplete
13
+ @requestStateEnum = requestStateEnum
14
+ @result = result
15
+ @errorCode = errorCode
16
+ @errorMessage = errorMessage
17
+ @latestTaskDescription = latestTaskDescription
18
+ @processDescription = processDescription
19
+ @createdTimestamp = createdTimestamp
20
+ @lastUpdatedTimeStamp = lastUpdatedTimeStamp
21
+ end
22
+
23
+
24
+ def get_details()
25
+ details = "Percentage Complete : #{@percentageComplete}\n"
26
+ details += "Request State : #{@requestStateEnum}\n"
27
+ details += "Result : #{@result}\n"
28
+ details += "Error Code : #{@errorCode}\n"
29
+ details += "Error Message : #{@errorMessage}\n"
30
+ details += "Latest Task Description: #{@latestTaskDescription}\n"
31
+ details += "Process Description : #{@processDescription}\n"
32
+ details += "Created Timestamp : #{@createdTimestamp}\n"
33
+ details += "Last Updated Timestamp : #{@lastUpdatedTimeStamp}\n"
34
+ return details
35
+ end
36
+
37
+
38
+ def get_result
39
+ return (@result.nil?) ? nil : @result["resourceURL"]
40
+ end
41
+
42
+ def get_error_code
43
+ return @errorCode
44
+ end
45
+
46
+
47
+ def get_error_message
48
+ return @errorMessage
49
+ end
50
+
51
+
52
+ def get_percentage_completed
53
+ return @percentageComplete
54
+ end
55
+
56
+
57
+ def get_latest_task_description
58
+ return @latestTaskDescription
59
+ end
60
+
61
+
62
+ end
@@ -0,0 +1,87 @@
1
+
2
+ ##
3
+ # Virtual machines.
4
+ #
5
+ # @author:: Alan Vella
6
+ ##
7
+
8
+ class VirtualMachine
9
+
10
+
11
+ def initialize(name, description, storageGB, storageType, memoryMB, vCPUs, powerStatus, nodeResource, organizationResource,
12
+ operatingSystemTemplate, imageResource, disks, macAddress, deducedPrivateIps, ipMappings)
13
+ @name = name
14
+ @description = description
15
+ @storageGB = storageGB
16
+ @storageType = storageType
17
+ @memoryMB = memoryMB
18
+ @vCPUs = vCPUs
19
+ @powerStatus = powerStatus
20
+ @nodeResource = nodeResource
21
+ @organizationResource = organizationResource
22
+ @operatingSystemTemplate = operatingSystemTemplate
23
+ @imageResource = imageResource
24
+ @disks = disks
25
+ @macAddress = macAddress
26
+ @deducedPrivateIps = deducedPrivateIps
27
+ @ipMappings = ipMappings
28
+ end
29
+
30
+
31
+ def get_details()
32
+ details = "Name : #{@name}\n"
33
+ details += "Description : #{@description}\n"
34
+ details += "Storage (GB) : #{@storageGB}\n"
35
+ details += "Storage Type : #{@storageType}\n"
36
+ details += "Memory (Mb) : #{@memoryMB}\n"
37
+ details += "vCPUs : #{@vCPUs}\n"
38
+ details += "Power Status : #{@powerStatus}\n"
39
+ details += "Node Resource : #{@nodeResource}\n"
40
+ details += "Organization Resource : #{@organizationResource}\n"
41
+ details += "Operation System Template: #{@operatingSystemTemplate}\n"
42
+ details += "Image Resource : #{@imageResource}\n"
43
+ if (@disks == nil) then
44
+ details += "Disks : -\n"
45
+ else
46
+ details += "Disks : #{@disks.join(", ")}\n"
47
+ end
48
+ if (@deducedPrivateIps == nil) then
49
+ details += "Deduced Private IPs : -\n"
50
+ else
51
+ details += "Deduced Private IPs : #{@deducedPrivateIps.join(", ")}\n"
52
+ end
53
+ details += "IP Mappings:"
54
+ @ipMappings.each do |ipMapping|
55
+ details += "\n\t#{ipMapping.get_details()}"
56
+ end
57
+ details += "\nMAC Address : #{@macAddress}\n"
58
+ return details
59
+ end
60
+
61
+
62
+ def get_power_status
63
+ return @powerStatus
64
+ end
65
+
66
+
67
+ def get_os_template_resource_url
68
+ return @operatingSystemTemplate
69
+ end
70
+
71
+
72
+ def get_image_resource_url
73
+ return @imageResource
74
+ end
75
+
76
+
77
+ def get_ip_mappings
78
+ return @ipMappings
79
+ end
80
+
81
+
82
+ def get_name
83
+ return @name
84
+ end
85
+
86
+
87
+ end
@@ -0,0 +1,30 @@
1
+
2
+ ##
3
+ # A private IP of a virtual machine.
4
+ #
5
+ # @author:: Alan Vella
6
+ ##
7
+
8
+ class VmPrivateIp
9
+
10
+
11
+ def initialize(ipAddress, assignedTo, publicIpMappings, nodeResource, organizationResource)
12
+ @ipAddress = ipAddress
13
+ @assignedTo = assignedTo
14
+ @publicIpMappings = publicIpMappings
15
+ @nodeResource = nodeResource
16
+ @organizationResource = organizationResource
17
+ end
18
+
19
+
20
+ def get_details()
21
+ details = "IP Address : #{@ipAddress}\n"
22
+ details += "Assigned To : #{@assignedTo.join(", ")}\n"
23
+ details += "Public IP Mappings : #{@publicIpMappings.join(", ")}\n"
24
+ details += "Node Resource : #{@nodeResource}\n"
25
+ details += "Organization Resource: #{@organizationResource}\n"
26
+ return details
27
+ end
28
+
29
+
30
+ end
@@ -0,0 +1,34 @@
1
+
2
+ ##
3
+ # A public IP of a virtual machine.
4
+ #
5
+ # @author:: Alan Vella
6
+ ##
7
+
8
+ class VmPublicIp
9
+
10
+
11
+ def initialize(ipAddress, ipType, reserved, assignedTo, privateIpMapping, nodeResource, organizationResource)
12
+ @ipAddress = ipAddress
13
+ @ipType = ipType
14
+ @reserved = reserved
15
+ @assignedTo = assignedTo
16
+ @privateIpMapping = privateIpMapping
17
+ @nodeResource = nodeResource
18
+ @organizationResource = organizationResource
19
+ end
20
+
21
+
22
+ def get_details()
23
+ details = "IP Address : #{@ipAddress}\n"
24
+ details += "IP Type : #{@ipType}\n"
25
+ details += "Reserved : #{@reserved}\n"
26
+ details += "Assigned To : #{@assignedTo.join(", ")}\n"
27
+ details += "Private IP Mapping : #{@privateIpMapping}\n"
28
+ details += "Node Resource : #{@nodeResource}\n"
29
+ details += "Organization Resource: #{@organizationResource}\n"
30
+ return details
31
+ end
32
+
33
+
34
+ end
@@ -0,0 +1,534 @@
1
+ require "json"
2
+
3
+ require_relative "secured_cloud_api_client/http_client"
4
+ require_relative "secured_cloud_api_client/sc_connection"
5
+ require_relative "secured_cloud_api_client/os_template"
6
+ require_relative "secured_cloud_api_client/task_status"
7
+ require_relative "secured_cloud_api_client/virtual_machine"
8
+ require_relative "secured_cloud_api_client/ip_mapping"
9
+ require_relative "secured_cloud_api_client/vm_private_ip"
10
+ require_relative "secured_cloud_api_client/vm_public_ip"
11
+
12
+
13
+ ##
14
+ # Class SecuredCloudRestClient provides a collection of methods that
15
+ # issue requests to the Secured Cloud RESTful External API.
16
+ #
17
+ # @author:: Alan Vella, Secured Cloud
18
+ ##
19
+
20
+ class SecuredCloudRestClient
21
+
22
+
23
+ #validation for sc_connection objects used by all api calls
24
+ def self.validate_sc_connection(sc_connection)
25
+ raise ArgumentError, 'SecuredCloudConnection needs to be initialized' unless sc_connection != nil
26
+ raise ArgumentError, 'SecuredCloudConnection needs to implement getUrl()' unless sc_connection.respond_to?(:getUrl)
27
+ raise ArgumentError, 'SecuredCloudConnection needs to implement getApplicationKey()' unless sc_connection.respond_to?(:getApplicationKey)
28
+ raise ArgumentError, 'SecuredCloudConnection needs to implement getSharedSecret()' unless sc_connection.respond_to?(:getSharedSecret)
29
+ end
30
+ private_class_method :validate_sc_connection
31
+
32
+ #validation for resource URLs used by all api calls
33
+ def self.validate_resource(resourceName, resource)
34
+ raise ArgumentError, resourceName.to_s + ' needs to be initialized' unless resource != nil
35
+ raise ArgumentError, resourceName.to_s + ' needs to be a valid string' unless resource.respond_to?(:to_str)
36
+ end
37
+ private_class_method :validate_sc_connection
38
+
39
+
40
+ # Returns a list of available nodes for a given organization.
41
+ def self.getNodesAvailable(sc_connection, orgResource)
42
+
43
+ #validation
44
+ validate_sc_connection(sc_connection)
45
+ validate_resource("Organization Resource", orgResource)
46
+
47
+ response = HttpClient.sendGETRequest( sc_connection, sc_connection.getUrl() + orgResource + "/node" )
48
+ nodesAvailable = []
49
+ responseBodyAsObject = JSON.parse(response.body)
50
+ responseBodyAsObject.each do |item|
51
+ nodesAvailable.push(item["resourceURL"])
52
+ end
53
+
54
+ return nodesAvailable
55
+ end
56
+
57
+
58
+ # Returns a list of available OS templates for a given organization and node.
59
+ def self.getOsTemplatesAvailable(sc_connection, orgResource, nodeResource)
60
+
61
+ #validation
62
+ validate_sc_connection(sc_connection)
63
+ validate_resource("Organization Resource", orgResource)
64
+ validate_resource("Node Resource", nodeResource)
65
+
66
+ response = HttpClient.sendGETRequest( sc_connection, sc_connection.getUrl() + orgResource + nodeResource + "/ostemplate")
67
+ osTemplatesAvailable = []
68
+ responseBodyAsObject = JSON.parse(response.body)
69
+
70
+ responseBodyAsObject.each do |item|
71
+ osTemplatesAvailable.push(item["resourceURL"])
72
+ end
73
+
74
+ return osTemplatesAvailable
75
+ end
76
+
77
+
78
+ # Returns the details of an OS template
79
+ def self.getOsTemplateDetails(sc_connection, osTemplateResource)
80
+
81
+ #validation
82
+ validate_sc_connection(sc_connection)
83
+ validate_resource("OS Template", osTemplateResource)
84
+
85
+ osResponse = HttpClient.sendGETRequest( sc_connection, sc_connection.getUrl() + osTemplateResource )
86
+ responseBodyAsObject = JSON.parse(osResponse.body)
87
+ osName = osVersion = minimumStorageSpace = defaultAdministratorUsername = diskExpandable = ""
88
+
89
+ responseBodyAsObject.each do |item|
90
+ if item[0] == "name" then
91
+ osName = item[1]
92
+ elsif item[0] == "version" then
93
+ osVersion = item[1]
94
+ elsif item[0] == "minimumStorageSpace" then
95
+ minimumStorageSpace = item[1]
96
+ elsif item[0] == "defaultAdministratorUsername" then
97
+ defaultAdministratorUsername = item[1]
98
+ elsif item[0] == "diskExpandable" then
99
+ diskExpandable = item[1]
100
+ end
101
+ end
102
+
103
+ return OsTemplate.new(osName, osVersion, minimumStorageSpace, defaultAdministratorUsername, diskExpandable)
104
+ end
105
+
106
+
107
+ # Starts a Create VM transaction.
108
+ # Returns the response code as well as the task resource
109
+ # if the transaction is triggered successfully.
110
+ def self.createVM(sc_connection, orgResource, nodeResource, name, description, storageGB, memoryMB, vCPUCount, powerStatus, imageResource, osTemplateResource, osPassword)
111
+
112
+ #validation
113
+ validate_sc_connection(sc_connection)
114
+ validate_resource("Organization Resource", orgResource)
115
+ validate_resource("Node Resource", nodeResource)
116
+
117
+ createVMPostBody = createVMJSONBody(name, description, storageGB, memoryMB, vCPUCount, powerStatus, imageResource, osTemplateResource, osPassword)
118
+ response = HttpClient.sendPOSTRequest( sc_connection, sc_connection.getUrl() + orgResource + nodeResource + "/virtualmachine", createVMPostBody)
119
+
120
+ if (response.code == "202") then
121
+ responseBodyAsObject = JSON.parse(response.body)
122
+ responseBodyAsObject.each do |item|
123
+ return "202", item[1]
124
+ end
125
+ else
126
+ return response.code, response['X-Application-Error-Reference'], response['X-Application-Error-Description']
127
+ end
128
+
129
+ end
130
+
131
+ #Gets the details of a VM
132
+ def self.getVMDetails(sc_connection, vmResource)
133
+
134
+ #validation
135
+ validate_sc_connection(sc_connection)
136
+ validate_resource("Virtual Machine Resource", vmResource)
137
+
138
+ response = HttpClient.sendGETRequest( sc_connection, sc_connection.getUrl() + vmResource )
139
+ responseBodyAsObject = JSON.parse(response.body)
140
+ name, description, storageGB, storageType, memoryMB, vCPUs, powerStatus, nodeResource, organizationResource,
141
+ operatingSystemTemplate, imageResource, disks, macAddress, deducedPrivateIps, ipMappings = ""
142
+
143
+ responseBodyAsObject.each do |item|
144
+ if item[0] == "name" then
145
+ name = item[1]
146
+ elsif item[0] == "description" then
147
+ description = item[1]
148
+ elsif item[0] == "storageGB" then
149
+ storageGB = item[1]
150
+ elsif item[0] == "storageType" then
151
+ storageType = item[1]
152
+ elsif item[0] == "memoryMB" then
153
+ memoryMB = item[1]
154
+ elsif item[0] == "vCPUs" then
155
+ vCPUs = item[1]
156
+ elsif item[0] == "powerStatus" then
157
+ powerStatus = item[1]
158
+ elsif item[0] == "nodeResource" then
159
+ nodeResource = item[1]["resourceURL"]
160
+ elsif item[0] == "organizationResource" then
161
+ organizationResource = item[1]["resourceURL"]
162
+ elsif item[0] == "operatingSystemTemplate" && !item[1].nil? then
163
+ operatingSystemTemplate = item[1]["resourceURL"]
164
+ elsif item[0] == "imageResource" then
165
+ imageResource = item[1]
166
+ elsif item[0] == "disks" then
167
+ diskArray = item[1]
168
+ disks = []
169
+ diskArray.each do |disk|
170
+ disks.push(disk["resourceURL"])
171
+ end
172
+ elsif item[0] == "macAddress" then
173
+ macAddress = item[1]
174
+ elsif item[0] == "deducedPrivateIps" then
175
+ deducedPrivateIps = item[1]
176
+ elsif item[0] == "ipMappings" then
177
+ ipMappingsArray = item[1]
178
+ ipMappings = []
179
+ ipMappingsArray.each do |ipMapping|
180
+ ipMappingToPush = IpMapping.new(ipMapping["privateIp"], ipMapping["publicIps"])
181
+ ipMappings.push(ipMappingToPush)
182
+ end
183
+ end
184
+ end
185
+
186
+ return VirtualMachine.new(name, description, storageGB, storageType, memoryMB, vCPUs, powerStatus, nodeResource, organizationResource,
187
+ operatingSystemTemplate, imageResource, disks, macAddress, deducedPrivateIps, ipMappings)
188
+ end
189
+
190
+
191
+ #Returns all public IPs on a VM
192
+ def self.getVMPublicIPs(sc_connection, vmResource)
193
+
194
+ #validation
195
+ validate_sc_connection(sc_connection)
196
+ validate_resource("Virtual Machine Resource", vmResource)
197
+
198
+ response = HttpClient.sendGETRequest( sc_connection, sc_connection.getUrl() + vmResource + "/publicip")
199
+ publicIps = []
200
+ responseBodyAsObject = JSON.parse(response.body)
201
+ responseBodyAsObject.each do |item|
202
+ publicIps.push(item["resourceURL"])
203
+ end
204
+ return publicIps
205
+
206
+ end
207
+
208
+
209
+
210
+ #Returns all private IPs on a VM
211
+ def self.getVMPrivateIPs(sc_connection, vmResource)
212
+
213
+ #validation
214
+ validate_sc_connection(sc_connection)
215
+ validate_resource("Virtual Machine Resource", vmResource)
216
+
217
+ response = HttpClient.sendGETRequest( sc_connection, sc_connection.getUrl() + vmResource + "/privateip")
218
+ privateIps = []
219
+ responseBodyAsObject = JSON.parse(response.body)
220
+ responseBodyAsObject.each do |item|
221
+ privateIps.push(item["resourceURL"])
222
+ end
223
+
224
+ return privateIps
225
+
226
+ end
227
+
228
+
229
+ #Returns the details of a VM public IP
230
+ def self.getVMPublicIpDetails(sc_connection, publicIpResource)
231
+
232
+ #validation
233
+ validate_sc_connection(sc_connection)
234
+ validate_resource("Public IP Resource", publicIpResource)
235
+
236
+ response = HttpClient.sendGETRequest( sc_connection, sc_connection.getUrl() + publicIpResource )
237
+ responseBodyAsObject = JSON.parse(response.body)
238
+ ipAddress, ipType, reserved, assignedTo, privateIpMapping, nodeResource, organizationResource = ""
239
+
240
+ responseBodyAsObject.each do |item|
241
+ if item[0] == "ipAddress" then
242
+ ipAddress = item[1]
243
+ elsif item[0] == "ipType" then
244
+ ipType = item[1]
245
+ elsif item[0] == "reserved" then
246
+ reserved = item[1]
247
+ elsif item[0] == "assignedTo" then
248
+ vmResourceArray = item[1]
249
+ assignedTo = []
250
+ vmResourceArray.each do |vmResource|
251
+ assignedTo.push(vmResource["resourceURL"])
252
+ end
253
+ elsif item[0] == "privateIpMapping" then
254
+ privateIpMapping = item[1]
255
+ elsif item[0] == "nodeResource" then
256
+ nodeResource = item[1]["resourceURL"]
257
+ elsif item[0] == "organizationResource" then
258
+ organizationResource = item[1]["resourceURL"]
259
+ end
260
+ end
261
+
262
+ return VmPublicIp.new(ipAddress, ipType, reserved, assignedTo, privateIpMapping, nodeResource, organizationResource)
263
+
264
+ end
265
+
266
+
267
+ # Returns the details of a VM private IP
268
+ def self.getVMPrivateIpDetails(sc_connection, privateIpResource)
269
+
270
+ #validation
271
+ validate_sc_connection(sc_connection)
272
+ validate_resource("Private IP Resource", privateIpResource)
273
+
274
+ response = HttpClient.sendGETRequest( sc_connection, sc_connection.getUrl() + privateIpResource )
275
+ responseBodyAsObject = JSON.parse(response.body)
276
+ ipAddress, assignedTo, publicIpMappings, nodeResource, organizationResource = ""
277
+
278
+ responseBodyAsObject.each do |item|
279
+ if item[0] == "ipAddress" then
280
+ ipAddress = item[1]
281
+ elsif item[0] == "assignedTo" then
282
+ vmResourceArray = item[1]
283
+ assignedTo = []
284
+ vmResourceArray.each do |vmResource|
285
+ assignedTo.push(vmResource["resourceURL"])
286
+ end
287
+ elsif item[0] == "publicIpMappings" then
288
+ publicIpMappings = item[1]
289
+ elsif item[0] == "nodeResource" then
290
+ nodeResource = item[1]["resourceURL"]
291
+ elsif item[0] == "organizationResource" then
292
+ organizationResource = item[1]["resourceURL"]
293
+ end
294
+ end
295
+
296
+ return VmPrivateIp.new(ipAddress, assignedTo, publicIpMappings, nodeResource, organizationResource)
297
+
298
+ end
299
+
300
+
301
+ # Assigns a public IP to a VM.
302
+ # ipFromReserved: a new IP will be assigned if set to nil
303
+ # privateIpMapping: Private ip mappings are only supported for nodes
304
+ # with custom network configurations. Should this field be set for
305
+ # nodes with a different network configuration, a 405 �Method not
306
+ # allowed� error will be returned.
307
+ def self.assignPublicIpToVM(sc_connection, vmResource, ipFromReserved, privateIpMapping)
308
+
309
+ #validation
310
+ validate_sc_connection(sc_connection)
311
+ validate_resource("Virtual Machine Resource", vmResource)
312
+ if (ipFromReserved != nil) then
313
+ raise ArgumentError, 'ipFromReserved needs to be a valid string' unless ipFromReserved.respond_to?(:to_str)
314
+ end
315
+ if (privateIpMapping != nil) then
316
+ raise ArgumentError, 'privateIpMapping needs to be a valid string' unless privateIpMapping.respond_to?(:to_str)
317
+ end
318
+
319
+ ipFromReserved = (ipFromReserved == nil) ? 'null' : '"' + ipFromReserved + '"'
320
+ privateIpMapping = (privateIpMapping == nil) ? 'null' : '"' + privateIpMapping + '"'
321
+ jsonBody = '{"ipFromReserved":' + ipFromReserved + ',"privateIpMapping":' + privateIpMapping + '}'
322
+
323
+ response = HttpClient.sendPOSTRequest( sc_connection, sc_connection.getUrl() + vmResource + "/publicip", jsonBody)
324
+
325
+ if (response.code == "202") then
326
+ responseBodyAsObject = JSON.parse(response.body)
327
+ responseBodyAsObject.each do |item|
328
+ return "202", item[1]
329
+ end
330
+ else
331
+ return response.code, response['X-Application-Error-Reference'], response['X-Application-Error-Description']
332
+ end
333
+
334
+ end
335
+
336
+
337
+
338
+
339
+ # Starts a Delete VM transaction.
340
+ # Returns the response code as well as the task resource
341
+ # if the transaction is triggered successfully.
342
+ def self.deleteVM(sc_connection, vmResource, releaseIPs)
343
+
344
+ #validation
345
+ validate_sc_connection(sc_connection)
346
+ validate_resource("Virtual Machine Resource", vmResource)
347
+
348
+ params = []
349
+
350
+ if ((releaseIPs != nil) && (releaseIPs)) then
351
+ params.push(["released","true"])
352
+ else
353
+ params.push(["released","false"])
354
+ end
355
+
356
+ response = HttpClient.sendDELETERequest( sc_connection, sc_connection.getUrl() + vmResource, params)
357
+
358
+ if (response.code == "202") then
359
+ responseBodyAsObject = JSON.parse(response.body)
360
+
361
+ responseBodyAsObject.each do |item|
362
+ return "202", item[1]
363
+ end
364
+ else
365
+ return response.code, response['X-Application-Error-Reference'], response['X-Application-Error-Description']
366
+ end
367
+
368
+ end
369
+
370
+
371
+ # Starts a Power On/Off transaction.
372
+ # Returns the response code as well as the task resource
373
+ # if the transaction is triggered successfully.
374
+ def self.powerVM(sc_connection, vmResource, powerState)
375
+
376
+ #validation
377
+ validate_sc_connection(sc_connection)
378
+ validate_resource("Virtual Machine Resource", vmResource)
379
+ raise ArgumentError, 'powerState needs to be initialized' unless powerState != nil
380
+ raise ArgumentError, 'powerState needs to be a valid string' unless powerState.respond_to?(:to_str)
381
+
382
+ params = []
383
+ params.push(["powerState", powerState])
384
+ response = HttpClient.sendPUTRequest( sc_connection, sc_connection.getUrl() + vmResource + "/power", params)
385
+
386
+ if (response.code == "202") then
387
+ responseBodyAsObject = JSON.parse(response.body)
388
+ responseBodyAsObject.each do |item|
389
+ return "202", item[1]
390
+ end
391
+ else
392
+ return response.code, response['X-Application-Error-Reference'], response['X-Application-Error-Description']
393
+ end
394
+ end
395
+
396
+
397
+ # Starts a Reboot VM transaction.
398
+ # Returns the response code as well as the task resource
399
+ # if the transaction is triggered successfully.
400
+ def self.rebootVM(sc_connection, vmResource)
401
+
402
+ #validation
403
+ validate_sc_connection(sc_connection)
404
+ validate_resource("Virtual Machine Resource", vmResource)
405
+
406
+ response = HttpClient.sendPUTRequest( sc_connection, sc_connection.getUrl() + vmResource + "/reboot")
407
+ if (response.code == "202") then
408
+ responseBodyAsObject = JSON.parse(response.body)
409
+ responseBodyAsObject.each do |item|
410
+ return "202", item[1]
411
+ end
412
+ else
413
+ return response.code, response['X-Application-Error-Reference'], response['X-Application-Error-Description']
414
+ end
415
+
416
+ end
417
+
418
+
419
+
420
+
421
+ # Returns the status of a task.
422
+ def self.getTaskStatus(sc_connection, taskResource)
423
+
424
+ #validation
425
+ raise ArgumentError, 'SecuredCloudConnection needs to be initialized' unless sc_connection != nil
426
+ raise ArgumentError, 'Task Resource needs to be initialized' unless taskResource != nil
427
+ raise ArgumentError, 'Task Resource needs to be a valid string' unless taskResource.respond_to?(:to_s)
428
+
429
+ response = HttpClient.sendGETRequest( sc_connection, sc_connection.getUrl() + taskResource )
430
+ responseBodyAsObject = JSON.parse(response.body)
431
+ percentageComplete, requestStateEnum, result, errorCode, errorMessage, latestTaskDescription, processDescription, createdTimestamp, lastUpdatedTimeStamp = ""
432
+
433
+ responseBodyAsObject.each do |item|
434
+ if item[0] == "percentageComplete" then
435
+ percentageComplete = item[1]
436
+ elsif item[0] == "requestStateEnum" then
437
+ requestStateEnum = item[1]
438
+ elsif item[0] == "result" then
439
+ result = item[1]
440
+ elsif item[0] == "errorCode" then
441
+ errorCode = item[1]
442
+ elsif item[0] == "errorMessage" then
443
+ errorMessage = item[1]
444
+ elsif item[0] == "latestTaskDescription" then
445
+ latestTaskDescription = item[1]
446
+ elsif item[0] == "processDescription" then
447
+ processDescription = item[1]
448
+ elsif item[0] == "createdTimestamp" then
449
+ createdTimestamp = item[1]
450
+ elsif item[0] == "lastUpdatedTimeStamp" then
451
+ lastUpdatedTimeStamp = item[1]
452
+ end
453
+ end
454
+
455
+ return TaskStatus.new(percentageComplete, requestStateEnum, result, errorCode, errorMessage, latestTaskDescription, processDescription, createdTimestamp, lastUpdatedTimeStamp)
456
+ end
457
+
458
+
459
+ def self.createVMJSONBody(name, description, storageGB, memoryMB, vCPUCount, powerStatus, imageResource, osTemplateResource, osPassword)
460
+
461
+ if (name == nil) then
462
+ name = 'null'
463
+ else
464
+ raise ArgumentError, 'name needs to be a valid string' unless name.respond_to?(:to_str)
465
+ name = '"' + name + '"'
466
+ end
467
+
468
+ if (description == nil) then
469
+ description = 'null'
470
+ else
471
+ raise ArgumentError, 'description needs to be a valid string' unless description.respond_to?(:to_str)
472
+ description = '"' + description + '"'
473
+ end
474
+
475
+ storageType = '"SATA"'
476
+
477
+ if (storageGB == nil) then
478
+ storageGB = 'null'
479
+ else
480
+ raise ArgumentError, 'storageGB needs to be a valid number' unless storageGB.is_a? Numeric
481
+ end
482
+
483
+ if (memoryMB == nil) then
484
+ memoryMB = 'null'
485
+ else
486
+ raise ArgumentError, 'memoryMB needs to be a valid number' unless memoryMB.is_a? Numeric
487
+ end
488
+
489
+ if (vCPUCount == nil) then
490
+ vCPUCount = 'null'
491
+ else
492
+ raise ArgumentError, 'vCPUCount needs to be a valid number' unless vCPUCount.is_a? Numeric
493
+ end
494
+
495
+ if (powerStatus == nil) then
496
+ powerStatus = 'null'
497
+ else
498
+ raise ArgumentError, 'powerStatus needs to be a valid string' unless powerStatus.respond_to?(:to_str)
499
+ powerStatus = '"' + powerStatus + '"'
500
+ end
501
+
502
+ if (imageResource == nil) then
503
+ imageResource = 'null'
504
+ else
505
+ raise ArgumentError, 'imageResource needs to be a valid string' unless imageResource.respond_to?(:to_str)
506
+ imageResource = '{"resourceURL":"' + imageResource + '"}'
507
+ end
508
+
509
+ if (osTemplateResource == nil) then
510
+ osTemplateResource = 'null'
511
+ else
512
+ raise ArgumentError, 'osTemplateResource needs to be a valid string' unless osTemplateResource.respond_to?(:to_str)
513
+ osTemplateResource = '{"resourceURL":"' + osTemplateResource + '"}'
514
+ end
515
+
516
+ if (osPassword == nil) then
517
+ osPassword = 'null'
518
+ else
519
+ raise ArgumentError, 'osPassword needs to be a valid string' unless osPassword.respond_to?(:to_str)
520
+ osPassword = '"' + osPassword + '"'
521
+ end
522
+
523
+ return '{"name":' + name + ',"description":' + description +
524
+ ',"storageGB":' + storageGB.to_s() + ',"memoryMB":' + memoryMB.to_s() +
525
+ ',"vCPUs":' + vCPUCount.to_s() + ',"storageType":' + storageType +
526
+ ',"powerStatus":' + powerStatus + ',"operatingSystemTemplate":' + osTemplateResource +
527
+ ',"newOperatingSystemAdminPassword":' + osPassword +
528
+ ',"imageResource":' + imageResource + '}'
529
+ end
530
+ private_class_method :createVMJSONBody
531
+
532
+
533
+ end
534
+
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: secured_cloud_api_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Alan Vella
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-13 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple API client for the Secured Cloud
14
+ email: alanv@ccbilleu.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/secured_cloud_api_client.rb
20
+ - lib/secured_cloud_api_client/http_client.rb
21
+ - lib/secured_cloud_api_client/ip_mapping.rb
22
+ - lib/secured_cloud_api_client/os_template.rb
23
+ - lib/secured_cloud_api_client/sc_connection.rb
24
+ - lib/secured_cloud_api_client/task_status.rb
25
+ - lib/secured_cloud_api_client/virtual_machine.rb
26
+ - lib/secured_cloud_api_client/vm_private_ip.rb
27
+ - lib/secured_cloud_api_client/vm_public_ip.rb
28
+ homepage: http://www.phoenixnap.com/secured-cloud/about-our-cloud/api.php
29
+ licenses:
30
+ - SecuredCloud
31
+ metadata: {}
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 2.2.1
49
+ signing_key:
50
+ specification_version: 4
51
+ summary: Secured Cloud API Client
52
+ test_files: []