solusvm 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,108 @@
1
+ Solusvm
2
+ =======
3
+
4
+ Solusvm allows for easy interaction with the SolusVM Admin::API.
5
+ This library was first created for internal use at {Site5 LLC}[http://www.site5.com].
6
+
7
+ Basic Examples
8
+ ==============
9
+
10
+ Solusvm.config('api_id', 'api_password', :url => 'http://www.example.com/api')
11
+ server = Solusvm::Server.new
12
+
13
+ # 200 is the id of the virtual server
14
+ server.shutdown(200) # => true
15
+ server.boot(200) # => true
16
+ server.reboot(200) # => true
17
+ server.suspend(200) # => true
18
+ server.resume(200) # => true
19
+
20
+ Server creation
21
+ ===============
22
+
23
+ options = {:type => 'xen', :username => 'bob', :node => 'node1', :plan => 'plan1', :template => 'mytpl', :ips => 1}
24
+ result = sever.create('server.hostname.com', 'password', options}
25
+ p server.successful?
26
+ => true
27
+
28
+ p result
29
+ => {"mainipaddress"=>"127.0.0.1", "consoleuser"=>"console-user", "vserverid"=>"10",
30
+ "statusmsg"=>"Virtual server created", "virtid"=>"vm10", "consolepassword"=>"myPassisL33t",
31
+ "extraipaddress"=>{}, "hostname"=>"server.hostname", "rootpassword"=>"password", "status"=>"success"}
32
+
33
+
34
+ Command Line Usage
35
+ ==================
36
+
37
+ USAGE: solusvm <command> [options]
38
+ -I, --api-login [id] API ID
39
+ -K, --api-key [key] API KEY
40
+ -N, --node [node] Node to provision on
41
+ -U, --api-url [URL] URL to the API
42
+ -u, --username [username] The client to put the VPS under
43
+ -k, --kind [kind] Type of VPS (openvz,xen,xen hvm)
44
+ -t, --template [template] VPS template to boot from
45
+ -p, --plan [plan] Plan to use
46
+ -i, --ips [number] Number of ips to add to the VPS
47
+ -h, --help Show help documentation
48
+ Commands:
49
+ server-check-exists <vserverid>
50
+ server-shutdown <vserverid>
51
+ server-changeplan <vserverid> <newplan>
52
+ server-resume <vserverid>
53
+ server-reboot <vserverid>
54
+ server-status <vserverid>
55
+ server-boot <vserverid>
56
+ server-create <hostname> <password> -t myimag -k xen -p myplan -i 1
57
+ server-suspend <vserverid>
58
+ server-addip <vserverid>
59
+
60
+ Default Config for Command Line
61
+ ================================
62
+
63
+ The command line utility, solusvm, will look for a .solusvm.yml file in ~/. You can specify some defaults.
64
+
65
+ ~/.solusvm.yml
66
+ id: api_id
67
+ key: api_key
68
+ # URL to the API endpoint
69
+ url: https://portal.yoursite.com/api/admin/command.php
70
+ # Default client to put servers under
71
+ username: bob
72
+
73
+ REQUIREMENTS
74
+ ============
75
+
76
+ * xml-simple
77
+
78
+ DOCUMENTATION
79
+ =============
80
+
81
+ * http://solusvm.rubyforge.org/solusvm/
82
+
83
+ INSTALL:
84
+ ========
85
+
86
+ gem install solusvm
87
+
88
+ Contributors
89
+ ============
90
+
91
+ * [Justin Mazzi](http://github.com/jmazzi)
92
+ * [Maran H.](http://github.com/maran)
93
+
94
+ Note on Patches/Pull Requests
95
+ =============================
96
+
97
+ * Fork the project.
98
+ * Make your feature addition or bug fix.
99
+ * Add tests for it. This is important so I don't break it in a
100
+ future version unintentionally.
101
+ * Commit, do not mess with rakefile, version, or history.
102
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
103
+ * Send me a pull request. Bonus points for topic branches.
104
+
105
+ Copyright
106
+ =========
107
+
108
+ Copyright (c) 2010 Site5. See LICENSE for details.
@@ -1,5 +1,5 @@
1
1
  ---
2
- :patch: 1
3
- :build:
4
2
  :major: 0
5
- :minor: 5
3
+ :build:
4
+ :minor: 6
5
+ :patch: 0
@@ -8,20 +8,28 @@ $:.unshift(File.join(File.dirname(__FILE__), "/../lib"))
8
8
  require "solusvm"
9
9
 
10
10
  opts = {}
11
- shell_methods = {}
12
- shell_methods['server-create'] = "<hostname> <password> -t myimage -k xen -p myplan -i 1"
13
- shell_methods['server-boot'] = "<vserverid>"
14
- shell_methods['server-reboot'] = "<vserverid>"
15
- shell_methods['server-shutdown'] = "<vserverid>"
16
- shell_methods['server-suspend'] = "<vserverid>"
17
- shell_methods['server-resume'] = "<vserverid>"
18
- shell_methods['server-status'] = "<vserverid>"
19
- shell_methods['server-addip'] = "<vserverid>"
20
- shell_methods['server-changeplan'] = "<vserverid> <newplan>"
21
- shell_methods['server-check-exists'] = "<vserverid>"
22
- shell_methods['server-terminate'] = "<vserverid>"
23
-
24
- OptionParser.new do |o|
11
+ $shell_methods = {}
12
+ $shell_methods['server-create'] = "<hostname> <password> -t myimage -k xen -p myplan -i 1"
13
+ $shell_methods['server-boot'] = "<vserverid>"
14
+ $shell_methods['server-reboot'] = "<vserverid>"
15
+ $shell_methods['server-shutdown'] = "<vserverid>"
16
+ $shell_methods['server-suspend'] = "<vserverid>"
17
+ $shell_methods['server-resume'] = "<vserverid>"
18
+ $shell_methods['server-status'] = "<vserverid>"
19
+ $shell_methods['server-addip'] = "<vserverid>"
20
+ $shell_methods['server-changeplan'] = "<vserverid> <newplan>"
21
+ $shell_methods['server-check-exists'] = "<vserverid>"
22
+ $shell_methods['server-terminate'] = "<vserverid>"
23
+
24
+ $shell_methods['node-available-ips'] = "<nodeid>"
25
+
26
+ def list_commands
27
+ puts "Commands:"
28
+ puts $shell_methods.collect { |k,v| " #{k} #{v}"}.join("\n")
29
+ exit
30
+ end
31
+
32
+ op = OptionParser.new do |o|
25
33
  o.banner = "USAGE: #{File.basename($0)} <command> [options]"
26
34
  o.on("-I", "--api-login [id]", "API ID") do |opt|
27
35
  opts[:api_id] = opt
@@ -61,17 +69,21 @@ OptionParser.new do |o|
61
69
 
62
70
  o.on("-h", "--help", "Show help documentation") do |h|
63
71
  puts o
64
- puts "Commands:"
65
- puts shell_methods.collect { |k,v| " #{k} #{v}"}.join("\n")
66
-
67
- exit
72
+ list_commands
68
73
  end
69
- end.parse!
74
+ end
75
+
76
+ optparse = op
77
+ op.parse!
70
78
 
71
79
  config_file = File.join(File.expand_path(ENV['HOME']), '.solusvm.yml')
72
80
  server = Solusvm::Server.new
81
+ general = Solusvm::General.new
82
+
73
83
  if ARGV.empty?
74
- STDERR.puts "USAGE: #{File.basename($0)} [function] [options]"
84
+ # STDERR.puts "USAGE: #{File.basename($0)} [function] [options]"
85
+ puts optparse.help
86
+ list_commands
75
87
  else
76
88
  if File.exists?(config_file)
77
89
  config = YAML::load(File.open(config_file))
@@ -84,37 +96,44 @@ else
84
96
  exit
85
97
  end
86
98
  meth = ARGV[0].chomp
87
- if shell_methods.include?(meth)
99
+ if $shell_methods.include?(meth)
88
100
  ARGV.shift
89
101
  if ARGV.empty?
90
- p shell_methods[meth]
102
+ p $shell_methods[meth]
91
103
  exit
92
104
  else
93
- case meth
94
- when 'server-create'
95
- unless ARGV.size == 2
96
- p shell_methods[meth]
97
- exit
105
+ begin
106
+ case meth
107
+ when 'server-create'
108
+ unless ARGV.size == 2
109
+ list_commands
110
+ end
111
+ p server.create(ARGV[0], ARGV[1], :plan => opts[:plan], :ips => opts[:ips], :type => opts[:kind],
112
+ :username => opts[:username], :template => opts[:template], :node => opts[:node])
113
+ when 'server-status'
114
+ p server.status(ARGV[0])
115
+ when 'server-boot'
116
+ p server.boot(ARGV[0])
117
+ when 'server-reboot'
118
+ p server.reboot(ARGV[0])
119
+ when 'server-suspend'
120
+ p server.suspend(ARGV[0])
121
+ when 'server-resume'
122
+ p server.resume(ARGV[0])
123
+ when 'server-check-exists'
124
+ p server.exists?(ARGV[0])
125
+ when 'server-terminate'
126
+ p server.terminate(ARGV[0])
127
+ when 'node-available-ips'
128
+ p general.node_available_ips(ARGV[0])
98
129
  end
99
- p server.create(ARGV[0], ARGV[1], :plan => opts[:plan], :ips => opts[:ips], :type => opts[:kind],
100
- :username => opts[:username], :template => opts[:template], :node => opts[:node])
101
- when 'server-status'
102
- p server.status(ARGV[0])
103
- when 'server-boot'
104
- p server.boot(ARGV[0])
105
- when 'server-reboot'
106
- p server.reboot(ARGV[0])
107
- when 'server-suspend'
108
- p server.suspend(ARGV[0])
109
- when 'server-resume'
110
- p server.resume(ARGV[0])
111
- when 'server-check-exists'
112
- p server.exists?(ARGV[0])
113
- when 'server-terminate'
114
- p server.terminate(ARGV[0])
130
+ rescue Exception => e
131
+ puts "Error: #{e}\n\n"
132
+ puts "Backtrace: \n\n"
133
+ puts e.backtrace.join("\n")
115
134
  end
116
135
  end
117
136
  else
118
137
  puts "#{meth} is not a valid function"
119
138
  end
120
- end
139
+ end
@@ -26,6 +26,7 @@ module Solusvm
26
26
  request = Net::HTTP::Get.new("#{api_endpoint.path}?#{options.to_query}")
27
27
  response = http.request(request)
28
28
 
29
+ handle_errors(response.body)
29
30
  @returned_parameters = parse_response(response.body)
30
31
  log_messages(options)
31
32
  end
@@ -38,6 +39,18 @@ module Solusvm
38
39
  XmlSimple.xml_in(body, 'ForceArray' => false)
39
40
  end
40
41
 
42
+ # Look for known error messages
43
+ def handle_errors(body)
44
+ case body.downcase
45
+ when /invalid ipaddress/i
46
+ raise "This IP is not authorized to use the API"
47
+ when /Invalid id or key/i
48
+ raise "Invalid ID or key"
49
+ when /Node not found/i
50
+ raise "Node does not exist"
51
+ end
52
+ end
53
+
41
54
  # Returns true when a request has been successful
42
55
  #
43
56
  # my_class = MyClass.new
@@ -80,4 +93,4 @@ module Solusvm
80
93
  end
81
94
  end
82
95
  end
83
- end
96
+ end
@@ -16,5 +16,16 @@ module Solusvm
16
16
  perform_request(:action => 'node-statistics', :nodeid => nodeid)
17
17
  returned_parameters
18
18
  end
19
+
20
+ # List a nodes available IPs
21
+ def node_available_ips(nodeid)
22
+ perform_request(:action => 'node-iplist', :nodeid => nodeid)
23
+ puts statusmsg
24
+ if statusmsg.match /no available ip/i
25
+ []
26
+ else
27
+ returned_parameters['ips'].split(',')
28
+ end
29
+ end
19
30
  end
20
- end
31
+ end
@@ -5,18 +5,18 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{solusvm}
8
- s.version = "0.5.1"
8
+ s.version = "0.6.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Justin Mazzi"]
12
- s.date = %q{2010-07-24}
12
+ s.date = %q{2010-08-04}
13
13
  s.default_executable = %q{solusvm}
14
14
  s.description = %q{Solusvm allows for easy interaction with the SolusVM Admin::API.}
15
15
  s.email = %q{jmazzi@gmail.com}
16
16
  s.executables = ["solusvm"]
17
17
  s.extra_rdoc_files = [
18
18
  "LICENSE",
19
- "README.rdoc"
19
+ "README.markdown"
20
20
  ]
21
21
  s.files = [
22
22
  ".document",
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
24
24
  "Gemfile",
25
25
  "Gemfile.lock",
26
26
  "LICENSE",
27
- "README.rdoc",
27
+ "README.markdown",
28
28
  "Rakefile",
29
29
  "VERSION.yml",
30
30
  "bin/solusvm",
@@ -36,6 +36,9 @@ Gem::Specification.new do |s|
36
36
  "lib/solusvm/hash.rb",
37
37
  "lib/solusvm/server.rb",
38
38
  "solusvm.gemspec",
39
+ "test/fixtures/base_bad_key.txt",
40
+ "test/fixtures/base_node_does_not_exist.txt",
41
+ "test/fixtures/base_unauthorized_ip.txt",
39
42
  "test/fixtures/client_authenticate_error.txt",
40
43
  "test/fixtures/client_authenticate_success.txt",
41
44
  "test/fixtures/client_change_password_error.txt",
@@ -44,6 +47,8 @@ Gem::Specification.new do |s|
44
47
  "test/fixtures/client_create_success.txt",
45
48
  "test/fixtures/client_exists_success.txt",
46
49
  "test/fixtures/error.txt",
50
+ "test/fixtures/general_node_list_all_ips_available.txt",
51
+ "test/fixtures/general_node_list_all_ips_not_available.txt",
47
52
  "test/fixtures/general_node_statistics_success.txt",
48
53
  "test/fixtures/general_nodes_success.txt",
49
54
  "test/fixtures/general_templates_success.txt",
@@ -0,0 +1 @@
1
+ Invalid id or key
@@ -0,0 +1 @@
1
+ Node not found
@@ -0,0 +1 @@
1
+ Invalid ipaddress
@@ -0,0 +1,4 @@
1
+ <status>success</status>
2
+ <statusmsg>Available ip addresses</statusmsg>
3
+ <ipcount>3</ipcount>
4
+ <ips>123.123.123.123,124.124.124.124,125.125.125.125</ips>
@@ -0,0 +1,4 @@
1
+ <status>success</status>
2
+ <statusmsg>No available ip addresses</statusmsg>
3
+ <ipcount>3</ipcount>
4
+ <ips></ips>
@@ -68,4 +68,37 @@ class TestBase < Test::Unit::TestCase
68
68
  assert_equal 'Invalid Virtual Server type: bob', e.message
69
69
  end
70
70
  end
71
+
72
+ def test_unautorized_ip
73
+ FakeWeb.register_uri(:get, "#{base_uri}&action=unauthorized", :body => load_response('base_unauthorized_ip'))
74
+ message = ""
75
+ begin
76
+ @base.perform_request(:action => 'unauthorized')
77
+ rescue Exception => e
78
+ message = e
79
+ end
80
+ assert_equal "This IP is not authorized to use the API", message.to_s
81
+ end
82
+
83
+ def test_invalid_key_or_id
84
+ FakeWeb.register_uri(:get, "#{base_uri}&action=badkey", :body => load_response('base_bad_key'))
85
+ message = ""
86
+ begin
87
+ @base.perform_request(:action => 'badkey')
88
+ rescue Exception => e
89
+ message = e
90
+ end
91
+ assert_equal "Invalid ID or key", message.to_s
92
+ end
93
+
94
+ def test_node_does_not_exist
95
+ FakeWeb.register_uri(:get, "#{base_uri}&action=nodeexist", :body => load_response('base_node_does_not_exist'))
96
+ message = ""
97
+ begin
98
+ @base.perform_request(:action => 'nodeexist')
99
+ rescue Exception => e
100
+ message = e
101
+ end
102
+ assert_equal "Node does not exist", message.to_s
103
+ end
71
104
  end
@@ -60,4 +60,20 @@ class TestGeneral < Test::Unit::TestCase
60
60
  assert_equal 'hostname.com', node_statistics['hostname']
61
61
  assert_equal 'success', node_statistics['status']
62
62
  end
63
- end
63
+
64
+ def test_list_all_ips_available
65
+ FakeWeb.register_uri(:get, "#{base_uri}&action=node-iplist&nodeid=1", :body => load_response('general_node_list_all_ips_available'))
66
+ avaialble_ips = @general.node_available_ips(1)
67
+
68
+ expected_ips = %w(123.123.123.123 124.124.124.124 125.125.125.125).sort
69
+ assert !avaialble_ips.empty?
70
+ assert_equal expected_ips, avaialble_ips.sort
71
+ end
72
+
73
+ def test_list_all_ips_not_available
74
+ FakeWeb.register_uri(:get, "#{base_uri}&action=node-iplist&nodeid=1", :body => load_response('general_node_list_all_ips_not_available'))
75
+ avaialble_ips = @general.node_available_ips(1)
76
+
77
+ assert avaialble_ips.empty?
78
+ end
79
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solusvm
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 5
9
- - 1
10
- version: 0.5.1
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Justin Mazzi
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-24 00:00:00 -04:00
18
+ date: 2010-08-04 00:00:00 -04:00
19
19
  default_executable: solusvm
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -40,14 +40,14 @@ extensions: []
40
40
 
41
41
  extra_rdoc_files:
42
42
  - LICENSE
43
- - README.rdoc
43
+ - README.markdown
44
44
  files:
45
45
  - .document
46
46
  - .gitignore
47
47
  - Gemfile
48
48
  - Gemfile.lock
49
49
  - LICENSE
50
- - README.rdoc
50
+ - README.markdown
51
51
  - Rakefile
52
52
  - VERSION.yml
53
53
  - bin/solusvm
@@ -59,6 +59,9 @@ files:
59
59
  - lib/solusvm/hash.rb
60
60
  - lib/solusvm/server.rb
61
61
  - solusvm.gemspec
62
+ - test/fixtures/base_bad_key.txt
63
+ - test/fixtures/base_node_does_not_exist.txt
64
+ - test/fixtures/base_unauthorized_ip.txt
62
65
  - test/fixtures/client_authenticate_error.txt
63
66
  - test/fixtures/client_authenticate_success.txt
64
67
  - test/fixtures/client_change_password_error.txt
@@ -67,6 +70,8 @@ files:
67
70
  - test/fixtures/client_create_success.txt
68
71
  - test/fixtures/client_exists_success.txt
69
72
  - test/fixtures/error.txt
73
+ - test/fixtures/general_node_list_all_ips_available.txt
74
+ - test/fixtures/general_node_list_all_ips_not_available.txt
70
75
  - test/fixtures/general_node_statistics_success.txt
71
76
  - test/fixtures/general_nodes_success.txt
72
77
  - test/fixtures/general_templates_success.txt
@@ -1,85 +0,0 @@
1
- = Solusvm
2
-
3
- Solusvm allows for easy interaction with the SolusVM Admin::API.
4
-
5
- This library was first created for internal use at {Site5 LLC}[http://www.site5.com].
6
-
7
- == Basic Examples
8
- Solusvm.config('api_id', 'api_password', :url => 'http://www.example.com/api')
9
- server = Solusvm::Server.new
10
-
11
- # 200 is the id of the virtual server
12
- server.shutdown(200) # => true
13
- server.boot(200) # => true
14
- server.reboot(200) # => true
15
- server.suspend(200) # => true
16
- server.resume(200) # => true
17
-
18
- == Server creation
19
- options = {:type => 'xen', :username => 'bob', :node => 'node1', :plan => 'plan1', :template => 'mytpl', :ips => 1}
20
- result = sever.create('server.hostname.com', 'password', options}
21
- p server.successful?
22
- => true
23
-
24
- p result
25
- => {"mainipaddress"=>"127.0.0.1", "consoleuser"=>"console-user", "vserverid"=>"10",
26
- "statusmsg"=>"Virtual server created", "virtid"=>"vm10", "consolepassword"=>"myPassisL33t",
27
- "extraipaddress"=>{}, "hostname"=>"server.hostname", "rootpassword"=>"password", "status"=>"success"}
28
-
29
-
30
- == Command Line Usage
31
- USAGE: solusvm <command> [options]
32
- -I, --api-login [id] API ID
33
- -K, --api-key [key] API KEY
34
- -N, --node [node] Node to provision on
35
- -U, --api-url [URL] URL to the API
36
- -u, --username [username] The client to put the VPS under
37
- -k, --kind [kind] Type of VPS (openvz,xen,xen hvm)
38
- -t, --template [template] VPS template to boot from
39
- -p, --plan [plan] Plan to use
40
- -i, --ips [number] Number of ips to add to the VPS
41
- -h, --help Show help documentation
42
- Commands:
43
- server-check-exists <vserverid>
44
- server-shutdown <vserverid>
45
- server-changeplan <vserverid> <newplan>
46
- server-resume <vserverid>
47
- server-reboot <vserverid>
48
- server-status <vserverid>
49
- server-boot <vserverid>
50
- server-create <hostname> <password> -t myimag -k xen -p myplan -i 1
51
- server-suspend <vserverid>
52
- server-addip <vserverid>
53
-
54
- == Default Config for Command Line
55
- The command line utility, solusvm, will look for a .solusvm.yml file in ~/. You can specify some defaults.
56
- ~/.solusvm.yml
57
- id: api_id
58
- key: api_key
59
- # URL to the API endpoint
60
- url: https://portal.yoursite.com/api/admin/command.php
61
- # Default client to put servers under
62
- username: bob
63
-
64
- == REQUIREMENTS:
65
- * xml-simple
66
-
67
- == DOCUMENTATION
68
- * http://solusvm.rubyforge.org/solusvm/
69
-
70
- == INSTALL:
71
- * gem install solusvm
72
-
73
- == Note on Patches/Pull Requests
74
-
75
- * Fork the project.
76
- * Make your feature addition or bug fix.
77
- * Add tests for it. This is important so I don't break it in a
78
- future version unintentionally.
79
- * Commit, do not mess with rakefile, version, or history.
80
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
81
- * Send me a pull request. Bonus points for topic branches.
82
-
83
- == Copyright
84
-
85
- Copyright (c) 2010 Site5. See LICENSE for details.