rackspace-scaling 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|