cloudstack_client 0.2.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +26 -0
  6. data/cloudstack_client.gemspec +24 -0
  7. data/lib/cloudstack_client.rb +2 -0
  8. data/lib/cloudstack_client/client.rb +136 -0
  9. data/lib/cloudstack_client/commands/account.rb +22 -0
  10. data/lib/cloudstack_client/commands/capacity.rb +19 -0
  11. data/lib/cloudstack_client/commands/cluster.rb +19 -0
  12. data/lib/cloudstack_client/commands/disk_offering.rb +49 -0
  13. data/lib/cloudstack_client/commands/domain.rb +22 -0
  14. data/lib/cloudstack_client/commands/host.rb +28 -0
  15. data/lib/cloudstack_client/commands/ip_address.rb +82 -0
  16. data/lib/cloudstack_client/commands/iso.rb +64 -0
  17. data/lib/cloudstack_client/commands/job.rb +29 -0
  18. data/lib/cloudstack_client/commands/load_balancer_rule.rb +61 -0
  19. data/lib/cloudstack_client/commands/network.rb +128 -0
  20. data/lib/cloudstack_client/commands/pod.rb +19 -0
  21. data/lib/cloudstack_client/commands/port_forwarding_rule.rb +49 -0
  22. data/lib/cloudstack_client/commands/project.rb +32 -0
  23. data/lib/cloudstack_client/commands/router.rb +89 -0
  24. data/lib/cloudstack_client/commands/server.rb +311 -0
  25. data/lib/cloudstack_client/commands/service_offering.rb +98 -0
  26. data/lib/cloudstack_client/commands/snapshot.rb +40 -0
  27. data/lib/cloudstack_client/commands/ssh_key_pair.rb +106 -0
  28. data/lib/cloudstack_client/commands/template.rb +60 -0
  29. data/lib/cloudstack_client/commands/user.rb +32 -0
  30. data/lib/cloudstack_client/commands/volume.rb +20 -0
  31. data/lib/cloudstack_client/commands/zone.rb +57 -0
  32. data/lib/cloudstack_client/version.rb +3 -0
  33. data/lib/connection_helper.rb +12 -0
  34. metadata +106 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 43c3f2c6cbd2c9fce29924116038430b9ac604e0
4
+ data.tar.gz: 6a1f2a09db25a4e900b789745319198759bf38bd
5
+ SHA512:
6
+ metadata.gz: d96c69957ef3a4fd0776edecc5b452b8fb827a67b9f38cac4f8dbc00a5ccaa8519f79aceb4eb367ff6ee48b58d26f126f7031e5cd588bdc96972d9f273d1286d
7
+ data.tar.gz: c2aace87c686c8e7b7bb5e7f3bf3aeba2dc326b6f14d30881e66d575f7f2af6eb0c7670615f7438ba1a9f681fdcb4dc045ae09e67779c0ff194774491259fce7
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ Gemfile.lock
2
+ .bundle/*
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cloudstack-client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Nik Wolfgramm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # cloudstack_client
2
+
3
+ A ruby CloudStack API client.
4
+
5
+ ## Installation
6
+
7
+ Install the cloudstack-cli gem:
8
+
9
+ $ gem install cloudstack_client
10
+
11
+ ## References
12
+ - [Cloudstack API documentation](http://cloudstack.apache.org/docs/api/apidocs-4.2/TOC_Root_Admin.html)
13
+
14
+ ## Contributing
15
+
16
+ 1. Fork it
17
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
18
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
19
+ 4. Push to the branch (`git push origin my-new-feature`)
20
+ 5. Create new Pull Request
21
+
22
+ ## License
23
+
24
+ Copyright (c) 2013, Nik Wolfgramm
25
+
26
+ Released under the MIT License. See the [LICENSE](https://bitbucket.org/swisstxt/cloudstack-cli/raw/master/LICENSE.txt) file for further details.
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cloudstack_client/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "cloudstack_client"
8
+ gem.version = CloudstackClient::VERSION
9
+ gem.authors = ["Nik Wolfgramm"]
10
+ gem.email = ["nik.wolfgramm@gmail.com"]
11
+ gem.description = %q{A ruby CloudStack API client}
12
+ gem.summary = %q{A ruby CloudStack API client}
13
+ gem.homepage = "https://bitbucket.org/swisstxt/cloudstack_client"
14
+ gem.license = 'MIT'
15
+
16
+ gem.required_ruby_version = '>= 1.9.3'
17
+ gem.files = `git ls-files`.split($/)
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+ gem.rdoc_options = %w[--line-numbers --inline-source]
21
+
22
+ gem.add_development_dependency('rdoc')
23
+ gem.add_development_dependency('rake', '~> 10.0.4')
24
+ end
@@ -0,0 +1,2 @@
1
+ require "cloudstack_client/version"
2
+ require "cloudstack_client/client"
@@ -0,0 +1,136 @@
1
+ require 'base64'
2
+ require 'openssl'
3
+ require 'uri'
4
+ require 'cgi'
5
+ require 'net/http'
6
+ require 'net/https'
7
+ require 'json'
8
+ require 'yaml'
9
+
10
+ module CloudstackClient
11
+ class Connection
12
+
13
+ @@async_poll_interval = 2.0
14
+ @@async_timeout = 400
15
+
16
+ # include all commands
17
+ Dir.glob(File.dirname(__FILE__) + "/commands/*.rb").each do |file|
18
+ require file
19
+ module_name = File.basename(file, '.rb').split('_').map{|f| f.capitalize}.join
20
+ include Object.const_get("CloudstackClient").const_get(module_name)
21
+ end
22
+
23
+ attr_accessor :verbose
24
+
25
+ def initialize(api_url, api_key, secret_key, opts = {})
26
+ @api_url = api_url
27
+ @api_key = api_key
28
+ @secret_key = secret_key
29
+ @use_ssl = api_url.start_with? "https"
30
+ @verbose = opts[:quiet] ? false : true
31
+ @debug = opts[:debug] ? true : false
32
+ end
33
+
34
+ ##
35
+ # Sends a synchronous request to the CloudStack API and returns the response as a Hash.
36
+ #
37
+ # The wrapper element of the response (e.g. mycommandresponse) is discarded and the
38
+ # contents of that element are returned.
39
+
40
+ def send_request(params)
41
+ params['response'] = 'json'
42
+ params['apiKey'] = @api_key
43
+
44
+ params_arr = []
45
+ params.sort.each { |elem|
46
+ params_arr << elem[0].to_s + '=' + CGI.escape(elem[1].to_s).gsub('+', '%20').gsub(' ','%20')
47
+ }
48
+
49
+ debug_output JSON.pretty_generate(params) if @debug
50
+
51
+ data = params_arr.join('&')
52
+ signature = OpenSSL::HMAC.digest('sha1', @secret_key, data.downcase)
53
+ signature = Base64.encode64(signature).chomp
54
+ signature = CGI.escape(signature)
55
+
56
+ url = "#{@api_url}?#{data}&signature=#{signature}"
57
+
58
+ uri = URI.parse(url)
59
+ http = Net::HTTP.new(uri.host, uri.port)
60
+ http.use_ssl = @use_ssl
61
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
62
+
63
+ begin
64
+ response = http.request(Net::HTTP::Get.new(uri.request_uri))
65
+ rescue
66
+ puts "Error connecting to API:"
67
+ puts "#{@api_url} is not reachable"
68
+ exit 1
69
+ end
70
+
71
+ if !response.is_a?(Net::HTTPOK)
72
+ puts "Error #{response.code}: #{response.message}"
73
+ puts JSON.pretty_generate(JSON.parse(response.body))
74
+ puts "URL: #{url}"
75
+ exit 1
76
+ end
77
+
78
+ begin
79
+ json = JSON.parse(response.body)
80
+ rescue JSON::ParserError
81
+ puts "Error parsing response from server."
82
+ exit 1
83
+ end
84
+ json[params['command'].downcase + 'response']
85
+ end
86
+
87
+ ##
88
+ # Sends an asynchronous request and waits for the response.
89
+ #
90
+ # The contents of the 'jobresult' element are returned upon completion of the command.
91
+
92
+ def send_async_request(params)
93
+
94
+ json = send_request(params)
95
+
96
+ params = {
97
+ 'command' => 'queryAsyncJobResult',
98
+ 'jobId' => json['jobid']
99
+ }
100
+
101
+ max_tries = (@@async_timeout / @@async_poll_interval).round
102
+ max_tries.times do
103
+ json = send_request(params)
104
+ status = json['jobstatus']
105
+
106
+ print "." if @verbose
107
+
108
+ if status == 1
109
+ return json['jobresult']
110
+ elsif status == 2
111
+ puts
112
+ puts "Request failed (#{json['jobresultcode']}): #{json['jobresult']}"
113
+ exit 1
114
+ end
115
+
116
+ STDOUT.flush
117
+ sleep @@async_poll_interval
118
+ end
119
+
120
+ print "\n"
121
+ puts "Error: Asynchronous request timed out"
122
+ exit 1
123
+ end
124
+
125
+ private
126
+
127
+ def debug_output(output, seperator = '-' * 80)
128
+ puts
129
+ puts seperator
130
+ puts output
131
+ puts seperator
132
+ puts
133
+ end
134
+
135
+ end # class
136
+ end
@@ -0,0 +1,22 @@
1
+ module CloudstackClient
2
+
3
+ module Account
4
+
5
+ ##
6
+ # Lists accounts.
7
+
8
+ def list_accounts(args = { :name => nil })
9
+ params = {
10
+ 'command' => 'listAccounts',
11
+ 'listall' => 'true',
12
+ 'isrecursive' => 'true'
13
+ }
14
+ params['name'] = args[:name] if args[:name]
15
+
16
+ json = send_request(params)
17
+ json['account'] || []
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,19 @@
1
+ module CloudstackClient
2
+
3
+ module Capacity
4
+
5
+ ##
6
+ # List capacity.
7
+
8
+ def list_capacity(args = {})
9
+ params = {
10
+ 'command' => 'listCapacity',
11
+ }
12
+
13
+ json = send_request(params)
14
+ json['capacity'] || []
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,19 @@
1
+ module CloudstackClient
2
+
3
+ module Cluster
4
+
5
+ ##
6
+ # Lists clusters.
7
+
8
+ def list_clusters(args = {})
9
+ params = {
10
+ 'command' => 'listClusters',
11
+ }
12
+
13
+ json = send_request(params)
14
+ json['cluster'] || []
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,49 @@
1
+ module CloudstackClient
2
+
3
+ module DiskOffering
4
+
5
+ ##
6
+ # Lists all available disk offerings.
7
+
8
+ def list_disk_offerings(domain = nil)
9
+ params = {
10
+ 'command' => 'listDiskOfferings'
11
+ }
12
+
13
+ if domain
14
+ params['domainid'] = list_domains(domain).first["id"]
15
+ end
16
+
17
+ json = send_request(params)
18
+ json['diskoffering'] || []
19
+ end
20
+
21
+ ##
22
+ # Get disk offering by name.
23
+
24
+ def get_disk_offering(name)
25
+
26
+ # TODO: use name parameter
27
+ # listServiceOfferings in CloudStack 2.2 doesn't seem to work
28
+ # when the name parameter is specified. When this is fixed,
29
+ # the name parameter should be added to the request.
30
+ params = {
31
+ 'command' => 'listDiskOfferings'
32
+ }
33
+ json = send_request(params)
34
+
35
+ services = json['diskoffering']
36
+ return nil unless services
37
+
38
+ services.each { |s|
39
+ if s['name'] == name then
40
+ return s
41
+ end
42
+ }
43
+ nil
44
+ end
45
+
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,22 @@
1
+ module CloudstackClient
2
+
3
+ module Domain
4
+
5
+ ##
6
+ # List domains.
7
+
8
+ def list_domains(name = nil)
9
+ params = {
10
+ 'command' => 'listDomains',
11
+ 'listall' => 'true',
12
+ 'isrecursive' => 'true'
13
+ }
14
+ params['name'] = name if name
15
+
16
+ json = send_request(params)
17
+ json['domain'] || []
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,28 @@
1
+ module CloudstackClient
2
+
3
+ module Host
4
+
5
+ ##
6
+ # Lists hosts.
7
+
8
+ def list_hosts(args = {})
9
+ params = {
10
+ 'command' => 'listHosts'
11
+ }
12
+
13
+ if args[:zone]
14
+ zone = get_zone(args[:zone])
15
+ unless zone
16
+ puts "Error: zone #{args[:project]} not found."
17
+ exit 1
18
+ end
19
+ params['zoneid'] = zone['id']
20
+ end
21
+
22
+ json = send_request(params)
23
+ json['host'] || []
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,82 @@
1
+ module CloudstackClient
2
+
3
+ module IpAddress
4
+
5
+ ##
6
+ # Lists the public ip addresses.
7
+
8
+ def list_public_ip_addresses(args = {})
9
+ params = {
10
+ 'command' => 'listPublicIpAddresses',
11
+ 'isrecursive' => true
12
+ }
13
+ if args[:project]
14
+ project = get_project(args[:project])
15
+ unless project
16
+ puts "Error: project #{args[:project]} not found."
17
+ exit 1
18
+ end
19
+ params['projectid'] = project['id']
20
+ end
21
+ if args[:account]
22
+ account = list_accounts({name: args[:account]}).first
23
+ unless account
24
+ puts "Error: Account #{args[:account]} not found."
25
+ exit 1
26
+ end
27
+ params['domainid'] = account["domainid"]
28
+ params['account'] = args[:account]
29
+ end
30
+ params['listall'] = args[:listall] if args[:listall]
31
+
32
+ json = send_request(params)
33
+ json['publicipaddress'] || []
34
+ end
35
+
36
+ ##
37
+ # Finds the public ip address for a given ip address string.
38
+
39
+ def get_public_ip_address(ip_address, project_id = nil)
40
+ params = {
41
+ 'command' => 'listPublicIpAddresses',
42
+ 'ipaddress' => ip_address
43
+ }
44
+ params['projectid'] = project_id if project_id
45
+ json = send_request(params)
46
+ ip_address = json['publicipaddress']
47
+
48
+ return nil unless ip_address
49
+ ip_address.first
50
+ end
51
+
52
+
53
+ ##
54
+ # Acquires and associates a public IP to an account.
55
+
56
+ def associate_ip_address(network_id)
57
+ params = {
58
+ 'command' => 'associateIpAddress',
59
+ 'networkid' => network_id
60
+ }
61
+
62
+ json = send_async_request(params)
63
+ json['ipaddress']
64
+ end
65
+
66
+ ##
67
+ # Disassociates an ip address from the account.
68
+ #
69
+ # Returns true if successful, false otherwise.
70
+
71
+ def disassociate_ip_address(id)
72
+ params = {
73
+ 'command' => 'disassociateIpAddress',
74
+ 'id' => id
75
+ }
76
+ json = send_async_request(params)
77
+ json['success']
78
+ end
79
+
80
+ end
81
+
82
+ end