rackspace-scaling 0.0.1
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.
- data/.gitignore +19 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +78 -0
- data/Rakefile +2 -0
- data/bin/rackspace_scale_down +114 -0
- data/bin/rackspace_scale_up +141 -0
- data/lib/rackspace-scaling.rb +14 -0
- data/lib/rackspace-scaling/authentication.rb +56 -0
- data/lib/rackspace-scaling/cmd_util.rb +35 -0
- data/lib/rackspace-scaling/load_balancer_operation.rb +51 -0
- data/lib/rackspace-scaling/server_operation.rb +68 -0
- data/lib/rackspace-scaling/version.rb +5 -0
- data/rackspace-scaling.gemspec +19 -0
- metadata +95 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use 1.9.3-p327@rackspace-scaling --create
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Mike Emery
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Rackspace::Scaling
|
2
|
+
|
3
|
+
This gem aims to provide a relatively simple library to increase your number of servers in a rackspace cloud and, optionally, attach those servers to a load balancer. This gem is pretty low level in relation to the API, and doesn't abstract away much.
|
4
|
+
|
5
|
+
Detailed information about the API can be found here:
|
6
|
+
|
7
|
+
http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_api_operations.html
|
8
|
+
http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/API_Operations-d1e1354.html
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'rackspace-scaling'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install rackspace-scaling
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
### Api
|
27
|
+
|
28
|
+
The very first thing you need to do is get an authentication token.
|
29
|
+
|
30
|
+
auth = Rackspace::Scaling::Authentication.new('account_name', 'api_key')
|
31
|
+
|
32
|
+
You can then perform operations for servers or load balancers.
|
33
|
+
|
34
|
+
#### Load Balancers
|
35
|
+
|
36
|
+
lb = Rackspace::Scaling::LoadBalancerOperation.new(auth, 'DFW')
|
37
|
+
|
38
|
+
#list all load balancers
|
39
|
+
puts lb.list
|
40
|
+
|
41
|
+
#list all nodes attached to a load balancer
|
42
|
+
puts lb.nodes(12345)
|
43
|
+
|
44
|
+
#Add a node to a load balancer, defaults to port 80, can be overriden with the :port option
|
45
|
+
puts lb.add_node(:load_balancer_id => 12345, :node_ip => 'internal or external ip')
|
46
|
+
|
47
|
+
#remove a node
|
48
|
+
puts lb.remove_node(:load_balancer_id => 12345, :node_id => 67890)
|
49
|
+
|
50
|
+
#### Servers
|
51
|
+
srv = Rackspace::Scaling::ServerOperation.new(auth, 'DFW')
|
52
|
+
|
53
|
+
# lists all the available images you can create servers with
|
54
|
+
srv.list_images
|
55
|
+
|
56
|
+
#list flavours (sizes) of machines you can spin up
|
57
|
+
srv.list_flavors
|
58
|
+
|
59
|
+
#get the status for a specific instance
|
60
|
+
srv.status('server guid')
|
61
|
+
|
62
|
+
#create a new server, required parameters are :image_id, :flavor_id, and :name
|
63
|
+
puts = srv.create(:flavor_id => '2', :image_id => 'guid', :name => 'fooserver')
|
64
|
+
|
65
|
+
#destroy a server
|
66
|
+
puts srv.destroy('server-guid')
|
67
|
+
|
68
|
+
### Command-LIne
|
69
|
+
|
70
|
+
Still in progress
|
71
|
+
|
72
|
+
## Contributing
|
73
|
+
|
74
|
+
1. Fork it
|
75
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
76
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
77
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
78
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'rackspace-scaling'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
class ScaleDown
|
8
|
+
include Rackspace::Scaling::CmdUtil
|
9
|
+
attr_reader :options
|
10
|
+
|
11
|
+
def initialize(args)
|
12
|
+
@options = OpenStruct.new
|
13
|
+
@options.n_decrease = 1
|
14
|
+
@options.region = 'DFW'
|
15
|
+
parse_options(args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_options(args)
|
19
|
+
parser = OptionParser.new do |opts|
|
20
|
+
opts.banner = "Usage: --login LOGIN --api-key API_KEY rackspace_scale_down -l LOAD_BALANCER_ID [-n INSTANCES_TO_CREATE] [-s SCALE_FACTOR]"
|
21
|
+
|
22
|
+
opts.on('--login LOGIN', 'Your rackspace login.') { |login|
|
23
|
+
options.login = login
|
24
|
+
}
|
25
|
+
|
26
|
+
opts.on('--api-key API_KEY', 'Your rackspace API key.') { |api_key|
|
27
|
+
options.api_key = api_key
|
28
|
+
}
|
29
|
+
|
30
|
+
opts.on('-r REGION', 'Three letter acronym representing the data center. Defaults to DFW.')
|
31
|
+
|
32
|
+
opts.on('-l LOAD_BALANCER_ID', OptionParser::DecimalInteger, 'Numeric id of the load balancer.') { |lb_id|
|
33
|
+
options.load_balancer_id = lb_id
|
34
|
+
}
|
35
|
+
|
36
|
+
opts.on('-s SCALE_FACTOR', OptionParser::DecimalInteger, 'Decrease the number of instances on the load balancer by 1/s times, rounded down.') { |scale|
|
37
|
+
options.scale = scale
|
38
|
+
}
|
39
|
+
|
40
|
+
opts.on('-n INSTANCES_TO_DESTROY', OptionParser::DecimalInteger, 'Increase the number of instances by n') { |n_decrease|
|
41
|
+
options.n_decrease = n_decrease
|
42
|
+
}
|
43
|
+
|
44
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
45
|
+
puts parser
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
parser.parse!(args)
|
51
|
+
|
52
|
+
if (options.login.nil? || options.api_key.nil? || options.load_balancer_id.nil?)
|
53
|
+
puts parser
|
54
|
+
exit(1)
|
55
|
+
end
|
56
|
+
|
57
|
+
if(options.n_decrease && options.scale)
|
58
|
+
puts "You can't specify both a fixed decrease in instances and a scale factor"
|
59
|
+
puts parser
|
60
|
+
exit(1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def run
|
65
|
+
print "Getting api token..."
|
66
|
+
auth = Rackspace::Scaling::Authentication.new(options.login, options.api_key)
|
67
|
+
lb = Rackspace::Scaling::LoadBalancerOperation.new(auth, options.region)
|
68
|
+
srv = Rackspace::Scaling::ServerOperation.new(auth, options.region)
|
69
|
+
puts "done"
|
70
|
+
|
71
|
+
print "Getting list of nodes attached to load balancer..."
|
72
|
+
nodes = lb.nodes(options.load_balancer_id)
|
73
|
+
puts "done"
|
74
|
+
|
75
|
+
print("Listing servers...")
|
76
|
+
servers = srv.list_servers(:detail => true)
|
77
|
+
puts("done")
|
78
|
+
|
79
|
+
if(options.scale)
|
80
|
+
options.n_decrease = (nodes.size / options.scale).floor
|
81
|
+
puts "You only have #{nodes.size} nodes available, scaling down by #{options.n_decrease} instead"
|
82
|
+
end
|
83
|
+
|
84
|
+
options.n_decrease = [nodes.size - 1, options.n_decrease].min
|
85
|
+
|
86
|
+
puts "Scaling down by #{options.n_decrease}"
|
87
|
+
|
88
|
+
nodes.sort!{ |a, b| a['condition'] <=> b['condition'] } # take disabled nodes first
|
89
|
+
removed_nodes = 0
|
90
|
+
|
91
|
+
nodes.each do |node|
|
92
|
+
|
93
|
+
if(removed_nodes >= options.n_decrease)
|
94
|
+
break
|
95
|
+
end
|
96
|
+
|
97
|
+
instance_ip = node['address']
|
98
|
+
server = find_instance_by_ip(instance_ip, servers)
|
99
|
+
|
100
|
+
print("Removing node #{node['address']} from load balancer...")
|
101
|
+
lb.remove_node(:load_balancer_id => options.load_balancer_id, :node_id => node['id'])
|
102
|
+
puts "done"
|
103
|
+
|
104
|
+
print("Destroying server for ip #{node['address']}...")
|
105
|
+
result = srv.destroy(server['id'])
|
106
|
+
puts(result)
|
107
|
+
|
108
|
+
removed_nodes += 1
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
scale_down = ScaleDown.new(ARGV)
|
114
|
+
scale_down.run
|
@@ -0,0 +1,141 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'rackspace-scaling'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
class ScaleUp
|
8
|
+
include Rackspace::Scaling::CmdUtil
|
9
|
+
attr_reader :options
|
10
|
+
|
11
|
+
def initialize(args)
|
12
|
+
@options = OpenStruct.new
|
13
|
+
@options.n_increase = 1
|
14
|
+
@options.region = 'DFW'
|
15
|
+
parse_options(args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_options(args)
|
19
|
+
|
20
|
+
parser = OptionParser.new do |opts|
|
21
|
+
opts.banner = "Usage: --login LOGIN --api-key API_KEY rackspace_scale_up -l LOAD_BALANCER_ID -i IMAGE_NAME [-n INSTANCES_TO_CREATE] [-s SCALE_FACTOR]"
|
22
|
+
|
23
|
+
opts.on('--login LOGIN', 'Your rackspace login.') { |login|
|
24
|
+
options.login = login
|
25
|
+
}
|
26
|
+
|
27
|
+
opts.on('--api-key API_KEY', 'Your rackspace API key.') { |api_key|
|
28
|
+
options.api_key = api_key
|
29
|
+
}
|
30
|
+
|
31
|
+
opts.on('-r REGION', 'Three letter acronym representing the data center. Defaults to DFW.')
|
32
|
+
|
33
|
+
opts.on('-l LOAD_BALANCER_ID', OptionParser::DecimalInteger, 'Numeric id of the load balancer.') { |lb_id|
|
34
|
+
options.load_balancer_id = lb_id
|
35
|
+
}
|
36
|
+
|
37
|
+
opts.on('-i IMAGE_NAME', 'Name of the image you want to use to scale') { |image_name|
|
38
|
+
options.image_name = image_name
|
39
|
+
}
|
40
|
+
|
41
|
+
opts.on('-s SCALE_FACTOR', OptionParser::DecimalInteger, 'Increase the number of instances on the load balancer by s times.') { |scale|
|
42
|
+
options.scale = scale
|
43
|
+
}
|
44
|
+
|
45
|
+
opts.on('-n INSTANCES_TO_CREATE', OptionParser::DecimalInteger, 'Increase the number of instances by n') { |n_increase|
|
46
|
+
options.n_increase = n_increase
|
47
|
+
}
|
48
|
+
|
49
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
50
|
+
puts parser
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
parser.parse!(args)
|
56
|
+
|
57
|
+
if (options.login.nil? || options.api_key.nil? || options.load_balancer_id.nil? || options.image_name.nil?)
|
58
|
+
puts parser
|
59
|
+
exit(1)
|
60
|
+
end
|
61
|
+
|
62
|
+
if(options.n_increase && options.scale)
|
63
|
+
puts "You can't specify both a fixed increase in instances and a scale factor"
|
64
|
+
puts parser
|
65
|
+
exit(1)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def run
|
70
|
+
print "Getting api token..."
|
71
|
+
auth = Rackspace::Scaling::Authentication.new(options.login, options.api_key)
|
72
|
+
lb = Rackspace::Scaling::LoadBalancerOperation.new(auth, options.region)
|
73
|
+
srv = Rackspace::Scaling::ServerOperation.new(auth, options.region)
|
74
|
+
puts "done"
|
75
|
+
|
76
|
+
nodes = lb.nodes(options.load_balancer_id)
|
77
|
+
|
78
|
+
instance_ip = nodes.first['address']
|
79
|
+
|
80
|
+
print("Listing servers...")
|
81
|
+
servers = srv.list_servers(:detail => true)
|
82
|
+
puts("done")
|
83
|
+
|
84
|
+
print("Retrieving server for IP #{instance_ip}...")
|
85
|
+
server = find_instance_by_ip(instance_ip, servers)
|
86
|
+
puts("done")
|
87
|
+
|
88
|
+
print("Listing images...")
|
89
|
+
images = srv.list_images(:detail => true)
|
90
|
+
puts("done")
|
91
|
+
|
92
|
+
print("Finding image for name #{options.image_name}...")
|
93
|
+
image = find_image_by_name(options.image_name, images)
|
94
|
+
puts("done")
|
95
|
+
|
96
|
+
if(options.scale)
|
97
|
+
options.n_increase = nodes * options.scale
|
98
|
+
end
|
99
|
+
|
100
|
+
puts "Increasing number of instances by #{options.n_increase}"
|
101
|
+
|
102
|
+
created_servers = []
|
103
|
+
options.n_increase.times do |i|
|
104
|
+
print("Creating server...")
|
105
|
+
new_server = srv.create(:name => "#{image['name']}", :image_id => image['id'], :flavor_id => server['flavor']['id'])
|
106
|
+
puts("done")
|
107
|
+
|
108
|
+
if(new_server)
|
109
|
+
created_servers << new_server['id']
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
puts "Created #{created_servers.size} new servers"
|
114
|
+
|
115
|
+
while(created_servers.size > 0)
|
116
|
+
created_servers.dup.each do |server_id|
|
117
|
+
new_server_details = srv.status(server_id)
|
118
|
+
|
119
|
+
if(new_server_details['addresses'].any? && new_server_details['status'] == 'ACTIVE')
|
120
|
+
private_ip = new_server_details['addresses']['private'].first['addr']
|
121
|
+
puts "Server #{server_id} has ip #{private_ip}"
|
122
|
+
|
123
|
+
print("Adding server to load balancer...")
|
124
|
+
lb.add_node(:load_balancer_id => options.load_balancer_id, :node_ip => private_ip)
|
125
|
+
puts("done")
|
126
|
+
created_servers.delete(server_id)
|
127
|
+
else
|
128
|
+
puts "Server #{server_id} is not ready to be put into rotation (ip: #{new_server_details['addresses'].any?}, status: #{new_server_details['status']}), waiting."
|
129
|
+
end
|
130
|
+
end
|
131
|
+
sleep(5) if created_servers.any?
|
132
|
+
end
|
133
|
+
|
134
|
+
puts 'Scaling complete'
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
s = ScaleUp.new(ARGV)
|
141
|
+
s.run
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'typhoeus'
|
2
|
+
require 'json'
|
3
|
+
require 'net/http'
|
4
|
+
require 'rackspace-scaling/version'
|
5
|
+
require 'rackspace-scaling/authentication'
|
6
|
+
require 'rackspace-scaling/load_balancer_operation'
|
7
|
+
require 'rackspace-scaling/server_operation'
|
8
|
+
require 'rackspace-scaling/cmd_util'
|
9
|
+
|
10
|
+
module Rackspace
|
11
|
+
module Scaling
|
12
|
+
# Your code goes here...
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
module Rackspace
|
3
|
+
module Scaling
|
4
|
+
class Authentication
|
5
|
+
|
6
|
+
attr_reader :user_name
|
7
|
+
|
8
|
+
ENDPOINT = 'https://identity.api.rackspacecloud.com/v2.0/tokens'
|
9
|
+
|
10
|
+
def initialize(username, api_key)
|
11
|
+
@user_name = username
|
12
|
+
@payload = {
|
13
|
+
:auth => {
|
14
|
+
"RAX-KSKEY:apiKeyCredentials" => {
|
15
|
+
'username' => username,
|
16
|
+
'apiKey' => api_key
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def authenticate
|
23
|
+
@authenticated ||= begin
|
24
|
+
resp = Typhoeus::Request.post(ENDPOINT, :body => @payload.to_json, :headers => {'Content-Type' => 'application/json'})
|
25
|
+
parsed_response = JSON.parse(resp.body)
|
26
|
+
@token = parsed_response['access']['token']['id']
|
27
|
+
@service_catalog = {}
|
28
|
+
|
29
|
+
parsed_response['access']['serviceCatalog'].each do |entry|
|
30
|
+
@service_catalog[entry['name']] = {
|
31
|
+
'type' => entry['type'],
|
32
|
+
'endpoints' => {}
|
33
|
+
}
|
34
|
+
|
35
|
+
entry['endpoints'].each do |endpoint|
|
36
|
+
@service_catalog[entry['name']]['endpoints'][endpoint['region']] = endpoint
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def endpoints
|
45
|
+
authenticate
|
46
|
+
@service_catalog
|
47
|
+
end
|
48
|
+
|
49
|
+
def token
|
50
|
+
authenticate
|
51
|
+
@token
|
52
|
+
end
|
53
|
+
|
54
|
+
end # /Authentication
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Rackspace
|
2
|
+
module Scaling
|
3
|
+
module CmdUtil
|
4
|
+
|
5
|
+
def find_instance_by_ip(target_ip, server_list)
|
6
|
+
server_list.each do |server|
|
7
|
+
server['addresses'].each do |k, v|
|
8
|
+
v.each do |ip|
|
9
|
+
if(ip['addr'] == target_ip)
|
10
|
+
return server
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_image_by_name(name, images)
|
20
|
+
images.sort!{ |a, b| b['created'] <=> a['created']}
|
21
|
+
found_image = nil
|
22
|
+
|
23
|
+
images.each do |image|
|
24
|
+
if(image['name'] == name)
|
25
|
+
found_image = image
|
26
|
+
break
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
found_image
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Rackspace
|
2
|
+
module Scaling
|
3
|
+
class LoadBalancerOperation
|
4
|
+
def initialize(auth, region = 'DFW')
|
5
|
+
@auth = auth
|
6
|
+
@endpoint = @auth.endpoints['cloudLoadBalancers']['endpoints'][region]['publicURL']+"/loadbalancers"
|
7
|
+
end
|
8
|
+
|
9
|
+
def list
|
10
|
+
@list ||= begin
|
11
|
+
resp = Typhoeus::Request.get(@endpoint, :headers => { 'X-Auth-Token' => @auth.token, 'Accept' => 'application/json'})
|
12
|
+
parsed_response = JSON.parse(resp.body)['loadBalancers']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def nodes(load_balancer_id)
|
17
|
+
path = "#{@endpoint}/#{load_balancer_id}/nodes"
|
18
|
+
@images ||= begin
|
19
|
+
resp = Typhoeus::Request.get(path, :headers => { 'X-Auth-Token' => @auth.token, 'Accept' => 'application/json'})
|
20
|
+
parsed_response = JSON.parse(resp.body)['nodes']
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_node(options = {})
|
25
|
+
load_balancer_id = options[:load_balancer_id]
|
26
|
+
body = {
|
27
|
+
:nodes => [
|
28
|
+
{
|
29
|
+
:address => options[:node_ip],
|
30
|
+
:port => (options[:port] || 80),
|
31
|
+
:condition => (options[:condition] || 'ENABLED'),
|
32
|
+
:type => (options[:type] || 'PRIMARY')
|
33
|
+
}
|
34
|
+
]
|
35
|
+
}
|
36
|
+
path = "#{@endpoint}/#{load_balancer_id}/nodes"
|
37
|
+
resp = Typhoeus::Request.post(path, :headers => { 'X-Auth-Token' => @auth.token, 'Accept' => 'application/json', 'Content-Type' => 'application/json'}, :body => body.to_json)
|
38
|
+
JSON.parse(resp.body)['nodes']
|
39
|
+
end
|
40
|
+
|
41
|
+
def remove_node(options = {})
|
42
|
+
load_balancer_id = options[:load_balancer_id]
|
43
|
+
node_id = options[:node_id]
|
44
|
+
path = "#{@endpoint}/#{load_balancer_id}/nodes/#{node_id}"
|
45
|
+
resp = Typhoeus::Request.delete(path, :headers => { 'X-Auth-Token' => @auth.token, 'Accept' => 'application/json'})
|
46
|
+
resp.success?
|
47
|
+
end
|
48
|
+
|
49
|
+
end # /LoadBalancerOperation
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Rackspace
|
2
|
+
module Scaling
|
3
|
+
class ServerOperation
|
4
|
+
def initialize(auth, region = 'DFW')
|
5
|
+
@auth = auth
|
6
|
+
@server_endpoint = @auth.endpoints['cloudServersOpenStack']['endpoints'][region]['publicURL']+"/servers"
|
7
|
+
@flavor_endpoint = @auth.endpoints['cloudServersOpenStack']['endpoints'][region]['publicURL']+"/flavors"
|
8
|
+
@image_endpoint = @auth.endpoints['cloudServersOpenStack']['endpoints'][region]['publicURL']+"/images"
|
9
|
+
end
|
10
|
+
|
11
|
+
def list_images(options = {})
|
12
|
+
url = "#{@image_endpoint}"
|
13
|
+
if(options[:detail])
|
14
|
+
url = "#{url}/detail"
|
15
|
+
end
|
16
|
+
|
17
|
+
@image_list ||= begin
|
18
|
+
resp = Typhoeus::Request.get(url, :headers => { 'X-Auth-Token' => @auth.token, 'Accept' => 'application/json'})
|
19
|
+
parsed_response = JSON.parse(resp.body)['images']
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def list_flavors
|
24
|
+
@flavor_list ||= begin
|
25
|
+
resp = Typhoeus::Request.get(@flavor_endpoint, :headers => { 'X-Auth-Token' => @auth.token, 'Accept' => 'application/json'})
|
26
|
+
parsed_response = JSON.parse(resp.body)['flavors']
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def status(server_id)
|
31
|
+
url = "#{@server_endpoint}/#{server_id}"
|
32
|
+
resp = Typhoeus::Request.get(url, :headers => { 'X-Auth-Token' => @auth.token, 'Accept' => 'application/json'})
|
33
|
+
JSON.parse(resp.body)['server']
|
34
|
+
end
|
35
|
+
|
36
|
+
def create(options = {})
|
37
|
+
create_options = {
|
38
|
+
:server => {
|
39
|
+
'name' => options[:name],
|
40
|
+
'imageRef' => options[:image_id],
|
41
|
+
'flavorRef' => options[:flavor_id]
|
42
|
+
}
|
43
|
+
}
|
44
|
+
resp = Typhoeus::Request.post(@server_endpoint, :headers => { 'X-Auth-Token' => @auth.token, 'Accept' => 'application/json', 'Content-Type' => 'application/json'}, :body => create_options.to_json)
|
45
|
+
parsed_response = JSON.parse(resp.body)['server']
|
46
|
+
end
|
47
|
+
|
48
|
+
def destroy(guid)
|
49
|
+
server_url = "#{@server_endpoint}/#{guid}"
|
50
|
+
resp = Typhoeus::Request.delete(server_url, :headers => { 'X-Auth-Token' => @auth.token, 'Accept' => 'application/json'})
|
51
|
+
return resp.success?
|
52
|
+
end
|
53
|
+
|
54
|
+
def list_servers(options = {})
|
55
|
+
url = "#{@server_endpoint}"
|
56
|
+
|
57
|
+
if(options[:detail])
|
58
|
+
url += '/detail'
|
59
|
+
end
|
60
|
+
|
61
|
+
@server_list ||= begin
|
62
|
+
resp = Typhoeus::Request.get(url, :headers => { 'X-Auth-Token' => @auth.token, 'Accept' => 'application/json'})
|
63
|
+
parsed_response = JSON.parse(resp.body)['servers']
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end # /ServerOperation
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/rackspace-scaling/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Mike Emery"]
|
6
|
+
gem.email = ["philodoxx@gmail.com"]
|
7
|
+
gem.description = %q{Gem that allows you to scale up or scale down the number of machines you ahve running in the rackspace cloud.}
|
8
|
+
gem.summary = %q{Gem that lets you scale the number of rackspace instances you have.}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "rackspace-scaling"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Rackspace::Scaling::VERSION
|
17
|
+
gem.add_runtime_dependency 'typhoeus', '~> 0.4.2'
|
18
|
+
gem.add_runtime_dependency 'json'
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rackspace-scaling
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mike Emery
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-22 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: typhoeus
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.4.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.4.2
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: json
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Gem that allows you to scale up or scale down the number of machines
|
47
|
+
you ahve running in the rackspace cloud.
|
48
|
+
email:
|
49
|
+
- philodoxx@gmail.com
|
50
|
+
executables:
|
51
|
+
- rackspace_scale_down
|
52
|
+
- rackspace_scale_up
|
53
|
+
extensions: []
|
54
|
+
extra_rdoc_files: []
|
55
|
+
files:
|
56
|
+
- .gitignore
|
57
|
+
- .rvmrc
|
58
|
+
- Gemfile
|
59
|
+
- LICENSE
|
60
|
+
- README.md
|
61
|
+
- Rakefile
|
62
|
+
- bin/rackspace_scale_down
|
63
|
+
- bin/rackspace_scale_up
|
64
|
+
- lib/rackspace-scaling.rb
|
65
|
+
- lib/rackspace-scaling/authentication.rb
|
66
|
+
- lib/rackspace-scaling/cmd_util.rb
|
67
|
+
- lib/rackspace-scaling/load_balancer_operation.rb
|
68
|
+
- lib/rackspace-scaling/server_operation.rb
|
69
|
+
- lib/rackspace-scaling/version.rb
|
70
|
+
- rackspace-scaling.gemspec
|
71
|
+
homepage: ''
|
72
|
+
licenses: []
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.8.24
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Gem that lets you scale the number of rackspace instances you have.
|
95
|
+
test_files: []
|