bigbang 0.0.1 → 0.0.2
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/README.rdoc +113 -0
- data/bin/bigbang +4 -2
- data/lib/bigbang/cluster_run.rb +14 -0
- data/lib/bigbang/dsl.rb +22 -8
- data/lib/bigbang/explode.rb +174 -0
- data/lib/bigbang/instance.rb +1 -2
- data/lib/bigbang/kill.rb +56 -0
- data/lib/bigbang/run.rb +26 -0
- data/lib/bigbang/test.rb +50 -0
- data/lib/bigbang/universe.rb +52 -164
- data/lib/bigbang.rb +0 -1
- metadata +10 -6
- data/README +0 -19
- data/lib/bigbang/cluster.rb +0 -10
data/README.rdoc
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
= BigBang
|
2
|
+
|
3
|
+
== What is BigBang?
|
4
|
+
|
5
|
+
Bigbang is a tool to create clusters using Amazon EC2 in a scriptable way.
|
6
|
+
You create a descriptor file (called universe file) which describes your whole
|
7
|
+
cluster and then you can launch it on EC2 with a single command.
|
8
|
+
Bigbang allows you to use the same "universe" file to create multiple "universes", say
|
9
|
+
for example a live, a QA and staging clusters.
|
10
|
+
You can even use it to automate the creation of a cluster for performance testing
|
11
|
+
purposes.
|
12
|
+
|
13
|
+
== What can it do for you?
|
14
|
+
|
15
|
+
BigBang can do the following:
|
16
|
+
- startup ec2 instances
|
17
|
+
- allocate and assign elastic ip's to instances
|
18
|
+
- assign instances to load balancer
|
19
|
+
- create DNS record entries (Amazon and Zerigo supported).
|
20
|
+
- shutdown your whole cluster
|
21
|
+
|
22
|
+
== How does it work?
|
23
|
+
|
24
|
+
As stated before, all you have to do is create a "universe.rb" file which describes
|
25
|
+
your cluster.
|
26
|
+
You then run "bigbang explode <cluster-name>" and it will "explode your universe" :).
|
27
|
+
|
28
|
+
== Installation
|
29
|
+
|
30
|
+
$> gem install bigbang
|
31
|
+
|
32
|
+
|
33
|
+
== How does it bootstrap the boxes?
|
34
|
+
|
35
|
+
Bigbang uses a "git-based" bootstraper. What it means it that you configure a git repo which
|
36
|
+
contains a "run" script. Bigbang will make sure this repo is cloned inside your ec2 instance
|
37
|
+
and executed. What this script does is up to you.
|
38
|
+
It can then for example install and setup puppet or chef which will continue the provisioning
|
39
|
+
of the instance.
|
40
|
+
|
41
|
+
== A simple example
|
42
|
+
|
43
|
+
Consider the following universe file:
|
44
|
+
|
45
|
+
universe do
|
46
|
+
config do |c|
|
47
|
+
c.access_key_id = "YOUR-AMAZON-ACCESS_KEY"
|
48
|
+
c.secret_key = "YOUR-AMAZON-SECRET_KEY"
|
49
|
+
|
50
|
+
c.dns :provider => 'Zerigo',
|
51
|
+
:zerigo_email => "example@example.com",
|
52
|
+
:zerigo_token => 'xxxxxxxxxxxxx'
|
53
|
+
|
54
|
+
c.domain = "example.com"
|
55
|
+
end
|
56
|
+
|
57
|
+
# describe your instance
|
58
|
+
instance "ubuntu" do |i|
|
59
|
+
i.ami = "ami-e2af508b"
|
60
|
+
i.key_name = "dev"
|
61
|
+
i.type = "m1.small"
|
62
|
+
i.bootstrap_repo = "git://github.com/giorgenes/ec2-chef-bootstrap.git"
|
63
|
+
end
|
64
|
+
|
65
|
+
# run a single instance
|
66
|
+
run_single_instance("ubuntu") do |r|
|
67
|
+
r.domain = ["db"]
|
68
|
+
r.wildcard_domain = true
|
69
|
+
r.elastic_ip = true
|
70
|
+
end
|
71
|
+
|
72
|
+
# runs a cluster of db instances
|
73
|
+
run_cluster("ubuntu") do |r|
|
74
|
+
r.domain = ["app"]
|
75
|
+
availability_zone "us-east-1a" => 1
|
76
|
+
availability_zone "us-east-1b" => 1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
In this example we have a single instance of "ubuntu" AND a cluster of "ubuntu".
|
81
|
+
So if you run for example "bigbang explode live" it will do the following:
|
82
|
+
- For the single instance:
|
83
|
+
- create an ec2 instance with type "m1.small" and ami and key as stated.
|
84
|
+
- allocate an elastic ip and associate with the intance.
|
85
|
+
- clone the specified repo inside the box and run it (in this example, it will install chef).
|
86
|
+
- create DNS records pointing to the instance: live.db.example.com
|
87
|
+
- it will also create wildcard DNS records: *.live.db.example.com
|
88
|
+
- For the cluster
|
89
|
+
- create 2 ec2 instances on the specified availability zones.
|
90
|
+
- clone the repo in the boxes and install chef
|
91
|
+
- create DNS records to the boxes: live.app0.example.com and live.app1.example.com
|
92
|
+
|
93
|
+
== Commands
|
94
|
+
|
95
|
+
- creates a universe called <universe-name>
|
96
|
+
|
97
|
+
bigbang explode <universe-name>
|
98
|
+
|
99
|
+
- list universes
|
100
|
+
|
101
|
+
bigbang list
|
102
|
+
|
103
|
+
- kill a universe
|
104
|
+
|
105
|
+
bigbang kill <universe-name>
|
106
|
+
|
107
|
+
- test configuration
|
108
|
+
|
109
|
+
bigbang test
|
110
|
+
|
111
|
+
= IMPORTANT
|
112
|
+
|
113
|
+
This gem is still in very early development stage.
|
data/bin/bigbang
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
$: << File.dirname(__FILE__) + "/../lib/"
|
3
4
|
require File.dirname(__FILE__) + "/../lib/bigbang"
|
4
5
|
|
5
6
|
def help
|
@@ -9,8 +10,9 @@ end
|
|
9
10
|
$universe = nil
|
10
11
|
|
11
12
|
def self.universe(&block)
|
12
|
-
|
13
|
-
|
13
|
+
dsl = BigBang::DSL.new
|
14
|
+
dsl.instance_eval(&block)
|
15
|
+
$universe = BigBang::Universe.new(dsl)
|
14
16
|
end
|
15
17
|
|
16
18
|
if ARGV.empty?
|
data/lib/bigbang/dsl.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
require 'bigbang/config'
|
2
2
|
require 'bigbang/instance'
|
3
|
-
require 'bigbang/
|
3
|
+
require 'bigbang/cluster_run'
|
4
|
+
require 'bigbang/run'
|
4
5
|
|
5
6
|
module BigBang
|
6
|
-
|
7
|
-
|
8
|
-
@instances << Cluster.new(name).tap do |cluster|
|
9
|
-
cluster.instance_eval(&block)
|
10
|
-
end
|
11
|
-
end
|
7
|
+
class DSL
|
8
|
+
attr_accessor :instances, :conf, :runs
|
12
9
|
|
10
|
+
def initialize
|
11
|
+
@instances = []
|
12
|
+
@runs = []
|
13
|
+
end
|
14
|
+
|
13
15
|
def instance(name, &block)
|
14
16
|
@instances << Instance.new(name).tap do |i|
|
15
17
|
i.instance_eval(&block)
|
@@ -17,9 +19,21 @@ module BigBang
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def config(&block)
|
20
|
-
@
|
22
|
+
@conf = Config.new.tap do |c|
|
21
23
|
c.instance_eval(&block)
|
22
24
|
end
|
23
25
|
end
|
26
|
+
|
27
|
+
def run_single_instance(name, &block)
|
28
|
+
@runs << Run.new(name, @instances).tap do |r|
|
29
|
+
r.instance_eval(&block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def run_cluster(name, &block)
|
34
|
+
@runs << ClusterRun.new(name, @instances).tap do |r|
|
35
|
+
r.instance_eval(&block)
|
36
|
+
end
|
37
|
+
end
|
24
38
|
end
|
25
39
|
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
module BigBang
|
2
|
+
module ExplodeCmd
|
3
|
+
def wait_for_eips(expected)
|
4
|
+
print "waiting for eips to be allocated"
|
5
|
+
STDOUT.flush
|
6
|
+
addrs = provider.free_eips
|
7
|
+
while(addrs.size < expected)
|
8
|
+
sleep(1)
|
9
|
+
print "."
|
10
|
+
STDOUT.flush
|
11
|
+
addrs = provider.free_eips
|
12
|
+
end
|
13
|
+
puts
|
14
|
+
addrs
|
15
|
+
end
|
16
|
+
|
17
|
+
def allocate_addresses
|
18
|
+
runs = @runs.find_all { |r| r.elastic_ip == true }
|
19
|
+
if runs.empty?
|
20
|
+
puts "no need to allocate elastic ips"
|
21
|
+
return []
|
22
|
+
end
|
23
|
+
free_ips = provider.free_eips
|
24
|
+
ninstances = runs.inject(0) { |m,r| m += r.instances_count }
|
25
|
+
toalloc = ninstances
|
26
|
+
blacklist = free_ips
|
27
|
+
if free_ips.size > 0
|
28
|
+
n = nil
|
29
|
+
if free_ips.size >= ninstances
|
30
|
+
n = ninstances
|
31
|
+
else
|
32
|
+
n = free_ips.size
|
33
|
+
end
|
34
|
+
confirm("Use #{n} of your #{free_ips.size} free eips?") do
|
35
|
+
blacklist = []
|
36
|
+
toalloc -= n
|
37
|
+
end
|
38
|
+
end
|
39
|
+
puts "need to alloc: #{toalloc}"
|
40
|
+
1.upto(toalloc) do |i|
|
41
|
+
puts "allocating eip address #{i}"
|
42
|
+
provider.ec2.allocate_address
|
43
|
+
end
|
44
|
+
|
45
|
+
addrs = wait_for_eips(free_ips.size + toalloc)
|
46
|
+
avail_ips = addrs.collect { |a| a.publicIp }.to_set
|
47
|
+
black_ips = blacklist.collect { |a| a.publicIp }.to_set
|
48
|
+
(avail_ips - black_ips).to_a[0,ninstances]
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
def wait_for_running(instances)
|
54
|
+
ids = instances.collect { |i| i.instanceId }.to_set
|
55
|
+
print "Waiting for all instances to be in running state. "
|
56
|
+
STDOUT.flush
|
57
|
+
while running_instances_count(ids) < instances.size
|
58
|
+
print "."
|
59
|
+
sleep(5)
|
60
|
+
STDOUT.flush
|
61
|
+
end
|
62
|
+
puts
|
63
|
+
end
|
64
|
+
|
65
|
+
def tag_instance(instance, ec2_instance, name)
|
66
|
+
provider.ec2.create_tags(:resource_id => ec2_instance.instanceId,
|
67
|
+
:tag => [
|
68
|
+
{ 'bb_name' => instance.name },
|
69
|
+
{ 'bb_universe' => name},
|
70
|
+
])
|
71
|
+
end
|
72
|
+
|
73
|
+
def run_instance(instance, userdata, zone, size)
|
74
|
+
puts "launching #{size} instance(s) on availability zone '#{zone}'"
|
75
|
+
provider.ec2.run_instances(
|
76
|
+
:image_id => instance.ami,
|
77
|
+
:key_name => instance.key_name,
|
78
|
+
:instance_type => instance.type,
|
79
|
+
:user_data => userdata,
|
80
|
+
:availability_zone => zone,
|
81
|
+
:min_count => size,
|
82
|
+
:max_count => size
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
def run_instances(name)
|
87
|
+
instances = []
|
88
|
+
gen = Ec2BootstrapGenerator.new
|
89
|
+
@runs.each do |r|
|
90
|
+
instance = r.instance
|
91
|
+
userdata = Base64.encode64(gen.generate_from_hash(
|
92
|
+
"bootstrap-repo" => instance.bootstrap_repo
|
93
|
+
))
|
94
|
+
r.zones.each_pair do |zone,size|
|
95
|
+
res = run_instance(instance, userdata, zone, size)
|
96
|
+
res.instancesSet.item.each do |i|
|
97
|
+
instances << i
|
98
|
+
r.ec2_instances << i.instanceId
|
99
|
+
tag_instance(instance, i, name)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
wait_for_running(instances)
|
104
|
+
end
|
105
|
+
|
106
|
+
def assign_addresses(addrs)
|
107
|
+
@runs.each do |r|
|
108
|
+
r.ec2_instances.each do |instance|
|
109
|
+
addr = addrs.pop
|
110
|
+
puts "associating address #{addr} " +
|
111
|
+
"to instance #{instance.instanceId}"
|
112
|
+
provider.ec2.associate_address(
|
113
|
+
:instance_id => instance.instanceId,
|
114
|
+
:public_ip => addr)
|
115
|
+
r.assigned_ips[instance.instanceId] = addr
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def create_dns_entry_for(instance, universe_name, domain, addr, wildcard)
|
121
|
+
domain = "#{universe_name}.#{domain}"
|
122
|
+
puts "creating domain #{domain}.#{@config.domain} to #{addr}"
|
123
|
+
provider.create_dns(domain, addr)
|
124
|
+
if wildcard == true
|
125
|
+
provider.create_dns("*.#{domain}", addr)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def create_dns_entries(universe_name)
|
130
|
+
instances_map = get_instances_map
|
131
|
+
@runs.each do |r|
|
132
|
+
addsufix = false
|
133
|
+
if r.is_a?(ClusterRun)
|
134
|
+
addsufix = true
|
135
|
+
end
|
136
|
+
|
137
|
+
domains = [r.domain]
|
138
|
+
if r.domain.is_a?(Array)
|
139
|
+
domains = r.domain
|
140
|
+
end
|
141
|
+
|
142
|
+
sufix = 0
|
143
|
+
r.ec2_instances.each do |instance_id|
|
144
|
+
instance = instances_map[instance_id]
|
145
|
+
domains.each do |domain|
|
146
|
+
addr = r.assigned_ips[instance.instanceId]
|
147
|
+
# use the elastic ip
|
148
|
+
if addr.nil?
|
149
|
+
addr = instance.ipAddress
|
150
|
+
end
|
151
|
+
|
152
|
+
if addsufix
|
153
|
+
domain = "#{domain}#{sufix}"
|
154
|
+
end
|
155
|
+
create_dns_entry_for(instance, universe_name, domain, addr, r.wildcard_domain)
|
156
|
+
end
|
157
|
+
sufix += 1
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def explode(name)
|
163
|
+
free_eips = allocate_addresses
|
164
|
+
run_instances(name)
|
165
|
+
unless free_eips.empty?
|
166
|
+
confirm("Will assign the following ips:\n" +
|
167
|
+
"#{free_eips.join("\n")}\nConfirm") do
|
168
|
+
assign_addresses(free_eips)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
create_dns_entries(name)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
data/lib/bigbang/instance.rb
CHANGED
data/lib/bigbang/kill.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module BigBang
|
2
|
+
module KillCmd
|
3
|
+
def kill_instance(instance)
|
4
|
+
confirm("kill instance #{instance.instanceId}") do
|
5
|
+
provider.ec2.terminate_instances(:instance_id => [instance.instanceId])
|
6
|
+
puts "sent termination signal to #{instance.instanceId}"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def kill_dns_entry(instance)
|
11
|
+
records = provider.configured_zone.records
|
12
|
+
|
13
|
+
records = records.find_all do |r|
|
14
|
+
r.value == instance.ipAddress
|
15
|
+
end
|
16
|
+
if records.empty?
|
17
|
+
puts "no DNS records found for ip #{instance.ipAddress}"
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
domains = records.collect { |r| r.domain }
|
22
|
+
confirm("Would you like to remove the following dns records?\n" +
|
23
|
+
domains.join("\n") + "\n") do
|
24
|
+
records.each do |r|
|
25
|
+
puts "removing DNS #{r.domain}"
|
26
|
+
r.destroy
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def kill_eip(i, addresses)
|
32
|
+
addr = addresses.find { |a| a.publicIp == i.ipAddress }
|
33
|
+
|
34
|
+
unless addr.nil?
|
35
|
+
confirm("Would you like to release EIP address #{addr.publicIp} of instance #{i.instanceId}") do
|
36
|
+
puts "disassociating address #{addr.publicIp}"
|
37
|
+
provider.ec2.disassociate_address(:public_ip => addr.publicIp)
|
38
|
+
|
39
|
+
puts "releasing address #{addr.publicIp}"
|
40
|
+
provider.ec2.release_address(:public_ip => addr.publicIp)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def kill(name)
|
46
|
+
running = running_instances
|
47
|
+
instances = universe_running_instances(running, universe_tags(name))
|
48
|
+
addresses = get_addresses
|
49
|
+
instances.each do |i|
|
50
|
+
kill_dns_entry(i)
|
51
|
+
kill_eip(i, addresses)
|
52
|
+
kill_instance(i)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/bigbang/run.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module BigBang
|
2
|
+
class Run
|
3
|
+
attr_accessor :instance, :domain, :wildcard_domain, :elastic_ip
|
4
|
+
attr_accessor :zone_sizes
|
5
|
+
attr_accessor :ec2_instances
|
6
|
+
attr_accessor :assigned_ips
|
7
|
+
|
8
|
+
def initialize(name, instances)
|
9
|
+
@zone_sizes = {}
|
10
|
+
@ec2_instances = []
|
11
|
+
@assigned_ips = {}
|
12
|
+
@instance = instances.find { |i| i.name == name }
|
13
|
+
raise "instance #{name} not found" if @instance.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def zones
|
17
|
+
return @zone_sizes unless @zone_sizes.empty?
|
18
|
+
|
19
|
+
{ nil => 1 }
|
20
|
+
end
|
21
|
+
|
22
|
+
def instances_count
|
23
|
+
zones.values.inject(0) { |m,v| m += v }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/bigbang/test.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module BigBang
|
2
|
+
module TestCmd
|
3
|
+
def test_availability_zones
|
4
|
+
zones = Set.new
|
5
|
+
@runs.each do |r|
|
6
|
+
r.zone_sizes.each_key do |k|
|
7
|
+
zones << k
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
return if zones.empty?
|
12
|
+
ec2_zones = get_availability_zones
|
13
|
+
zones.each do |zone|
|
14
|
+
unless ec2_zones.find { |z| z.zoneName == zone}
|
15
|
+
raise "zone '#{zone}' not found"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
puts "Availability zones OK"
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_amis
|
23
|
+
@instances.collect { |i| i.ami }.to_set.each do |ami|
|
24
|
+
begin
|
25
|
+
provider.ec2.describe_images(:image_id => [ami])
|
26
|
+
rescue AWS::InvalidAMIIDNotFound => e
|
27
|
+
puts "ami #{ami} not found"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
puts "AMI's OK"
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_dns
|
34
|
+
if provider.configured_zone.nil?
|
35
|
+
puts "Configured DNS domain zone not found"
|
36
|
+
else
|
37
|
+
puts "DNS domain OK"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test
|
42
|
+
get_instances
|
43
|
+
puts "ec2 access OK"
|
44
|
+
|
45
|
+
test_availability_zones
|
46
|
+
test_amis
|
47
|
+
test_dns
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/bigbang/universe.rb
CHANGED
@@ -7,21 +7,29 @@ require 'bigbang/provider'
|
|
7
7
|
require 'bigbang/instance'
|
8
8
|
require 'bigbang/dsl'
|
9
9
|
require 'bigbang/ec2-git-bootstrap'
|
10
|
+
require 'bigbang/kill'
|
11
|
+
require 'bigbang/test'
|
12
|
+
require 'bigbang/explode'
|
10
13
|
|
11
14
|
module BigBang
|
12
15
|
class Universe
|
13
|
-
def initialize
|
14
|
-
@
|
15
|
-
@
|
16
|
+
def initialize(dsl)
|
17
|
+
@instances = dsl.instances
|
18
|
+
@runs = dsl.runs
|
19
|
+
@config = dsl.conf
|
16
20
|
end
|
17
21
|
|
18
|
-
include DSL
|
19
|
-
|
20
22
|
def provider
|
21
23
|
return @provider unless @provider.nil?
|
22
24
|
@provider = Provider.new(@config)
|
23
25
|
end
|
24
26
|
|
27
|
+
def get_availability_zones
|
28
|
+
item = provider.ec2.describe_availability_zones.availabilityZoneInfo.item
|
29
|
+
item = [] if item.nil?
|
30
|
+
item
|
31
|
+
end
|
32
|
+
|
25
33
|
def get_instances
|
26
34
|
rset = provider.ec2.describe_instances.reservationSet
|
27
35
|
if rset.nil?
|
@@ -37,72 +45,20 @@ module BigBang
|
|
37
45
|
end
|
38
46
|
end
|
39
47
|
|
40
|
-
def
|
41
|
-
|
42
|
-
get_instances
|
43
|
-
|
44
|
-
@instances.collect { |i| i.ami }.to_set.each do |ami|
|
45
|
-
begin
|
46
|
-
provider.ec2.describe_images(:image_id => [ami])
|
47
|
-
rescue AWS::InvalidAMIIDNotFound => e
|
48
|
-
puts "ami #{ami} not found"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
puts "AMI's OK"
|
52
|
-
if provider.configured_zone.nil?
|
53
|
-
puts "Configured DNS domain zone not found"
|
54
|
-
else
|
55
|
-
puts "DNS domain OK"
|
48
|
+
def get_instances_map
|
49
|
+
map = {}
|
50
|
+
get_instances.each do |i|
|
51
|
+
map[i.instanceId] = i
|
56
52
|
end
|
53
|
+
map
|
57
54
|
end
|
58
55
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
while(addrs.size < expected)
|
64
|
-
sleep(1)
|
65
|
-
print "."
|
66
|
-
STDOUT.flush
|
67
|
-
addrs = provider.free_eips
|
68
|
-
end
|
69
|
-
puts
|
70
|
-
addrs
|
56
|
+
def get_addresses
|
57
|
+
items = provider.ec2.describe_addresses.addressesSet.item
|
58
|
+
items = [] if items.nil?
|
59
|
+
items
|
71
60
|
end
|
72
|
-
|
73
|
-
def allocate_addresses
|
74
|
-
instances = @instances.find_all { |i| i.elastic_ip == true }
|
75
|
-
if instances.empty?
|
76
|
-
puts "no need to allocate elastic ips"
|
77
|
-
return
|
78
|
-
end
|
79
|
-
free_ips = provider.free_eips
|
80
|
-
toalloc = instances.size
|
81
|
-
blacklist = free_ips
|
82
|
-
if free_ips.size > 0
|
83
|
-
n = nil
|
84
|
-
if free_ips.size >= instances.size
|
85
|
-
n = instances.size
|
86
|
-
else
|
87
|
-
n = free_ips.size
|
88
|
-
end
|
89
|
-
confirm("Use #{n} of your #{free_ips.size} free eips?") do
|
90
|
-
blacklist = []
|
91
|
-
toalloc -= n
|
92
|
-
end
|
93
|
-
end
|
94
|
-
puts "need to alloc: #{toalloc}"
|
95
|
-
1.upto(toalloc) do |i|
|
96
|
-
puts "allocating eip address #{i}"
|
97
|
-
provider.ec2.allocate_address
|
98
|
-
end
|
99
|
-
|
100
|
-
addrs = wait_for_eips(free_ips.size + toalloc)
|
101
|
-
avail_ips = addrs.collect { |a| a.publicIp }.to_set
|
102
|
-
black_ips = blacklist.collect { |a| a.publicIp }.to_set
|
103
|
-
(avail_ips - black_ips).to_a[0,instances.size]
|
104
|
-
end
|
105
|
-
|
61
|
+
|
106
62
|
def running_instances
|
107
63
|
get_instances.find_all { |i| i.instanceState.name == "running" }
|
108
64
|
end
|
@@ -111,87 +67,7 @@ module BigBang
|
|
111
67
|
running_instances.count { |i| ids.include?(i.instanceId) }
|
112
68
|
end
|
113
69
|
|
114
|
-
def
|
115
|
-
ids = instances.collect { |i| i.instanceId }.to_set
|
116
|
-
print "Waiting for all instances to be in running state. "
|
117
|
-
STDOUT.flush
|
118
|
-
while running_instances_count(ids) < instances.size
|
119
|
-
print "."
|
120
|
-
sleep(5)
|
121
|
-
STDOUT.flush
|
122
|
-
end
|
123
|
-
puts
|
124
|
-
end
|
125
|
-
|
126
|
-
def run_instances(name)
|
127
|
-
instances = []
|
128
|
-
gen = Ec2BootstrapGenerator.new
|
129
|
-
@instances.each do |instance|
|
130
|
-
userdata = Base64.encode64(gen.generate_from_hash(
|
131
|
-
"bootstrap-repo" => instance.bootstrap_repo
|
132
|
-
))
|
133
|
-
res = provider.ec2.run_instances(
|
134
|
-
:image_id => instance.ami,
|
135
|
-
:key_name => instance.key_name,
|
136
|
-
:instance_type => instance.type,
|
137
|
-
:user_data => userdata)
|
138
|
-
ap res
|
139
|
-
res.instancesSet.item.each do |i|
|
140
|
-
instances << i
|
141
|
-
provider.ec2.create_tags(:resource_id => i.instanceId,
|
142
|
-
:tag => [
|
143
|
-
{ 'bb_name' => instance.name },
|
144
|
-
{ 'bb_universe' => name},
|
145
|
-
])
|
146
|
-
end
|
147
|
-
end
|
148
|
-
instances.tap do |i|
|
149
|
-
wait_for_running(i)
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
def assign_addresses(instances, addrs)
|
154
|
-
if instances.size != addrs.size
|
155
|
-
raise "error: instances number and addresses don't match"
|
156
|
-
end
|
157
|
-
|
158
|
-
instances.each_index do |i|
|
159
|
-
puts "associating address #{addrs[i]} " +
|
160
|
-
"to instance #{instances[i].instanceId}"
|
161
|
-
provider.ec2.associate_address(
|
162
|
-
:instance_id => instances[i].instanceId,
|
163
|
-
:public_ip => addrs[i])
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
def create_dns_entries(name, instances, addrs)
|
168
|
-
@instances.each_index do |i|
|
169
|
-
domains = [@instances[i].domain]
|
170
|
-
if @instances[i].domain.is_a?(Array)
|
171
|
-
domains = @instances[i].domain
|
172
|
-
end
|
173
|
-
domains.each do |domain|
|
174
|
-
domain = "#{name}.#{domain}"
|
175
|
-
puts "creating domain #{domain}.#{@config.domain} to #{addrs[i]}"
|
176
|
-
provider.create_dns(domain, addrs[i])
|
177
|
-
if @instances[i].wildcard_domain == true
|
178
|
-
provider.create_dns("*.#{domain}", addrs[i])
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def explode(name)
|
185
|
-
free_eips = allocate_addresses
|
186
|
-
confirm("Will assign the following ips:\n" +
|
187
|
-
"#{free_eips.join("\n")}\nConfirm") do
|
188
|
-
instances = run_instances(name)
|
189
|
-
assign_addresses(instances, free_eips)
|
190
|
-
create_dns_entries(name, instances, free_eips)
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def tags
|
70
|
+
def get_tags
|
195
71
|
tag_set = provider.ec2.describe_tags(:filter =>
|
196
72
|
[{'key' => 'bb_universe'}]).tagSet
|
197
73
|
if tag_set.nil?
|
@@ -203,11 +79,19 @@ module BigBang
|
|
203
79
|
|
204
80
|
def list
|
205
81
|
universes = Set.new
|
206
|
-
|
82
|
+
get_tags.each do |tag|
|
207
83
|
universes << tag.value
|
208
84
|
end
|
85
|
+
|
86
|
+
running = running_instances
|
87
|
+
|
209
88
|
universes.each do |u|
|
210
|
-
|
89
|
+
instances = universe_running_instances(running, universe_tags(u))
|
90
|
+
if instances.empty?
|
91
|
+
puts "#{u} (defunct)"
|
92
|
+
else
|
93
|
+
puts "#{u} (#{instances.size} running instances)"
|
94
|
+
end
|
211
95
|
end
|
212
96
|
end
|
213
97
|
|
@@ -222,25 +106,29 @@ module BigBang
|
|
222
106
|
end
|
223
107
|
end
|
224
108
|
|
225
|
-
def
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
109
|
+
def instance_tags(tags = nil)
|
110
|
+
tags = get_tags if tags.nil?
|
111
|
+
tags.find_all { |t| t.resourceType == 'instance' }
|
112
|
+
end
|
113
|
+
|
114
|
+
def universe_running_instances(running, universe_tags)
|
115
|
+
res = []
|
116
|
+
instance_tags(universe_tags).each do |t|
|
117
|
+
i = running.find { |i| i.instanceId == t.resourceId }
|
118
|
+
res << i unless i.nil?
|
234
119
|
end
|
120
|
+
|
121
|
+
res
|
235
122
|
end
|
236
123
|
|
237
|
-
def
|
238
|
-
|
239
|
-
tags.find_all do |tag|
|
124
|
+
def universe_tags(name)
|
125
|
+
get_tags.find_all do |tag|
|
240
126
|
tag.value == name
|
241
|
-
end.each do |tag|
|
242
|
-
send("kill_#{tag.resourceType}", tag, running)
|
243
127
|
end
|
244
128
|
end
|
129
|
+
|
130
|
+
include KillCmd
|
131
|
+
include TestCmd
|
132
|
+
include ExplodeCmd
|
245
133
|
end
|
246
134
|
end
|
data/lib/bigbang.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bigbang
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Giorgenes Gelatti
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-16 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -59,15 +59,19 @@ files:
|
|
59
59
|
- src/post-extract.sh
|
60
60
|
- src/bootstrap.sh
|
61
61
|
- bin/bigbang
|
62
|
-
- README
|
62
|
+
- README.rdoc
|
63
63
|
- lib/bigbang.rb
|
64
|
+
- lib/bigbang/explode.rb
|
64
65
|
- lib/bigbang/instance.rb
|
65
66
|
- lib/bigbang/provider.rb
|
66
67
|
- lib/bigbang/dsl.rb
|
68
|
+
- lib/bigbang/run.rb
|
67
69
|
- lib/bigbang/universe.rb
|
70
|
+
- lib/bigbang/test.rb
|
68
71
|
- lib/bigbang/ec2-git-bootstrap.rb
|
72
|
+
- lib/bigbang/kill.rb
|
69
73
|
- lib/bigbang/config.rb
|
70
|
-
- lib/bigbang/
|
74
|
+
- lib/bigbang/cluster_run.rb
|
71
75
|
has_rdoc: true
|
72
76
|
homepage: http://github.com/giorgenes/bigbang/
|
73
77
|
licenses: []
|
data/README
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# creates the base images
|
4
|
-
bigbang base
|
5
|
-
|
6
|
-
# run the instances
|
7
|
-
bigbang explode <universe-info.rb>
|
8
|
-
|
9
|
-
# list universes
|
10
|
-
bigbang list
|
11
|
-
|
12
|
-
# kill a universe
|
13
|
-
bigbang kill <universe-name>
|
14
|
-
|
15
|
-
# resize clusters
|
16
|
-
bigbang resize
|
17
|
-
|
18
|
-
# test configuration
|
19
|
-
bigbang test
|