sumo 0.1.2 → 0.2.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/README.rdoc +39 -6
- data/VERSION +1 -1
- data/bin/sumo +42 -1
- data/lib/sumo.rb +74 -2
- metadata +2 -2
data/README.rdoc
CHANGED
|
@@ -50,24 +50,57 @@ Then create ~/.sumo/config.yml containing:
|
|
|
50
50
|
access_id: <your amazon access key id>
|
|
51
51
|
access_secret: <your amazon secret access key>
|
|
52
52
|
|
|
53
|
-
Optional config you can include in config.yml:
|
|
53
|
+
Optional config you can include any of the following in your config.yml:
|
|
54
54
|
|
|
55
55
|
user: root
|
|
56
56
|
ami: ami-ed46a784
|
|
57
|
+
availability_zone: us-east-1b
|
|
57
58
|
cookbooks_url: git://github.com/adamwiggins/chef-cookbooks.git
|
|
58
59
|
|
|
59
|
-
If you run any production machines from your EC2 account, I recommend setting up a separate account for use with Sumo. It does not prompt for confirmation when terminating an instance or differentiate between instances started by it vs. instances started by other tools.
|
|
60
|
-
|
|
61
60
|
You'll need Bacon and Mocha if you want to run the specs, and Jewler if you want to create gems.
|
|
62
61
|
|
|
63
|
-
==
|
|
62
|
+
== Managing volumes
|
|
63
|
+
|
|
64
|
+
Create and attach a volume to your running instance:
|
|
65
|
+
|
|
66
|
+
$ sumo create_volume
|
|
67
|
+
---> Create 5MB volume... vol-8a9c6ae3 (1.1s)
|
|
68
|
+
$ sumo volumes
|
|
69
|
+
vol-8a9c6ae3 5MB available
|
|
70
|
+
$ sumo attach
|
|
71
|
+
---> Attach vol-8a9c6ae3 to i-bc32cbd4 as /dev/sdc1... done (0.6s)
|
|
72
|
+
|
|
73
|
+
Log in to format and mount the volume:
|
|
74
|
+
|
|
75
|
+
$ sumo ssh
|
|
76
|
+
root@ip-10-251-122-175:~# mkfs.ext3 /dev/sdc1
|
|
77
|
+
mke2fs 1.41.4 (27-Jan-2009)
|
|
78
|
+
Filesystem label=
|
|
79
|
+
OS type: Linux
|
|
80
|
+
Block size=4096 (log=2)
|
|
81
|
+
...
|
|
82
|
+
$ mkdir /myvol
|
|
83
|
+
$ mount /dev/sdc1 /myvol
|
|
84
|
+
$ echo "I'm going to persist to a volume" > /myvol/hello.txt
|
|
64
85
|
|
|
65
|
-
|
|
86
|
+
To detach from a running instance (perhaps so you can attach elsewhere):
|
|
87
|
+
|
|
88
|
+
$ sumo detatch
|
|
89
|
+
---> Detach vol-8a9c6ae3... done (0.6s)
|
|
90
|
+
|
|
91
|
+
Destroy it if you no longer want the data stored on it:
|
|
92
|
+
|
|
93
|
+
$ sumo destroy_volume
|
|
94
|
+
---> Destroy volume... done (0.8s)
|
|
95
|
+
|
|
96
|
+
== Some details you might want to know
|
|
66
97
|
|
|
67
98
|
Sumo creates its own keypair named sumo, which is stored in ~/.ssh/keypair.pem. Amazon doesn't let you upload your own ssh public key, which is lame, so this is the best option for making the launch-and-connect process a single step.
|
|
68
99
|
|
|
69
100
|
It will also create an Amazon security group called sumo, so that it can lower the firewall for services you configure via cookbook roles.
|
|
70
101
|
|
|
102
|
+
If you run any production machines from your EC2 account, I recommend setting up a separate account for use with Sumo. It does not prompt for confirmation when terminating an instance or differentiate between instances started by it vs. instances started by other tools.
|
|
103
|
+
|
|
71
104
|
== Anti-features
|
|
72
105
|
|
|
73
106
|
Sumo is not a cloud management tool, a monitor tool, or anything more than a way to get an instance up right quick. If you're looking for a way to manage a cluster of production instances, try one of these fine tools.
|
|
@@ -81,7 +114,7 @@ Sumo is not a cloud management tool, a monitor tool, or anything more than a way
|
|
|
81
114
|
|
|
82
115
|
Created by Adam Wiggins
|
|
83
116
|
|
|
84
|
-
Patches contributed by Blake Mizerany and
|
|
117
|
+
Patches contributed by Orion Henry, Blake Mizerany, Jesse Newland, and Gert Goet
|
|
85
118
|
|
|
86
119
|
Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
|
|
87
120
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1
|
|
1
|
+
0.2.1
|
data/bin/sumo
CHANGED
|
@@ -19,7 +19,7 @@ class CLI < Thor
|
|
|
19
19
|
|
|
20
20
|
resources = sumo.resources(host)
|
|
21
21
|
unless resources.empty?
|
|
22
|
-
task("
|
|
22
|
+
task("Open firewall") do
|
|
23
23
|
ports = resources.map { |r| r.match(/:(\d+)\//)[1] }
|
|
24
24
|
ports.each { |port| sumo.open_firewall(port) }
|
|
25
25
|
"ports " + ports.join(", ")
|
|
@@ -72,6 +72,13 @@ class CLI < Thor
|
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
desc "console [<instance_id or hostname>]", "get console output for instance or first available"
|
|
76
|
+
def console(id=nil)
|
|
77
|
+
inst = sumo.find(id) || (sumo.running | sumo.pending).first || abort("No running or pending instances")
|
|
78
|
+
|
|
79
|
+
puts sumo.console_output(inst[:instance_id]).inspect
|
|
80
|
+
end
|
|
81
|
+
|
|
75
82
|
desc "terminate [<instance_id or hostname>]", "terminate specified instance or first available"
|
|
76
83
|
def terminate(id=nil)
|
|
77
84
|
inst = sumo.find(id) || (sumo.running | sumo.pending).first || abort("No running or pending instances")
|
|
@@ -90,6 +97,40 @@ class CLI < Thor
|
|
|
90
97
|
end
|
|
91
98
|
end
|
|
92
99
|
|
|
100
|
+
desc "volumes", "list all volumes"
|
|
101
|
+
def volumes
|
|
102
|
+
sumo.volumes.each do |v|
|
|
103
|
+
printf "%-10s %4sGB %10s %15s %15s\n", v[:volume_id], v[:size], v[:status], v[:instance], v[:device]
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
desc "create_volume [<megabytes>]", "create a volume"
|
|
108
|
+
def create_volume(size=5)
|
|
109
|
+
task("Create #{size}GB volume") { sumo.create_volume(size) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
desc "destroy_volume [<volume_id>]", "destroy a volume"
|
|
113
|
+
def destroy_volume(volume=nil)
|
|
114
|
+
vol_id = (sumo.find_volume(volume) || sumo.nondestroyed_volumes.first || abort("No volumes"))[:volume_id]
|
|
115
|
+
task("Destroy volume") { sumo.destroy_volume(vol_id) }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
desc "attach [<volume_id>] [<instance_id or hostname>] [<device>]", "attach volume to running instance"
|
|
119
|
+
def attach(volume=nil, inst_id=nil, device=nil)
|
|
120
|
+
vol_id = (sumo.find_volume(volume) || sumo.available_volumes.first || abort("No available volumes"))[:volume_id]
|
|
121
|
+
inst_id = (sumo.find(inst_id) || sumo.running.first || abort("No running instances"))[:instance_id]
|
|
122
|
+
device ||= '/dev/sdc1'
|
|
123
|
+
task("Attach #{vol_id} to #{inst_id} as #{device}") do
|
|
124
|
+
sumo.attach(vol_id, inst_id, device)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
desc "detach [<volume_id>]", "detach volume from instance"
|
|
129
|
+
def detach(volume=nil)
|
|
130
|
+
vol_id = (sumo.find_volume(volume) || sumo.attached_volumes.first || abort("No attached volumes"))[:volume_id]
|
|
131
|
+
task("Detach #{vol_id}") { sumo.detach(vol_id) }
|
|
132
|
+
end
|
|
133
|
+
|
|
93
134
|
no_tasks do
|
|
94
135
|
def sumo
|
|
95
136
|
@sumo ||= Sumo.new
|
data/lib/sumo.rb
CHANGED
|
@@ -16,7 +16,8 @@ class Sumo
|
|
|
16
16
|
:image_id => ami,
|
|
17
17
|
:instance_type => config['instance_size'] || 'm1.small',
|
|
18
18
|
:key_name => 'sumo',
|
|
19
|
-
:group_id => [ 'sumo' ]
|
|
19
|
+
:group_id => [ 'sumo' ],
|
|
20
|
+
:availability_zone => config['availability_zone']
|
|
20
21
|
)
|
|
21
22
|
result.instancesSet.item[0].instanceId
|
|
22
23
|
end
|
|
@@ -25,6 +26,60 @@ class Sumo
|
|
|
25
26
|
@list ||= fetch_list
|
|
26
27
|
end
|
|
27
28
|
|
|
29
|
+
def volumes
|
|
30
|
+
result = ec2.describe_volumes
|
|
31
|
+
return [] unless result.volumeSet
|
|
32
|
+
|
|
33
|
+
result.volumeSet.item.map do |row|
|
|
34
|
+
{
|
|
35
|
+
:volume_id => row["volumeId"],
|
|
36
|
+
:size => row["size"],
|
|
37
|
+
:status => row["status"],
|
|
38
|
+
:device => (row["attachmentSet"]["item"].first["device"] rescue ""),
|
|
39
|
+
:instance_id => (row["attachmentSet"]["item"].first["instanceId"] rescue ""),
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def available_volumes
|
|
45
|
+
volumes.select { |vol| vol[:status] == 'available' }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def attached_volumes
|
|
49
|
+
volumes.select { |vol| vol[:status] == 'in-use' }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def nondestroyed_volumes
|
|
53
|
+
volumes.select { |vol| vol[:status] != 'deleting' }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def attach(volume, instance, device)
|
|
57
|
+
result = ec2.attach_volume(
|
|
58
|
+
:volume_id => volume,
|
|
59
|
+
:instance_id => instance,
|
|
60
|
+
:device => device
|
|
61
|
+
)
|
|
62
|
+
"done"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def detach(volume)
|
|
66
|
+
result = ec2.detach_volume(:volume_id => volume, :force => "true")
|
|
67
|
+
"done"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def create_volume(size)
|
|
71
|
+
result = ec2.create_volume(
|
|
72
|
+
:availability_zone => config['availability_zone'],
|
|
73
|
+
:size => size.to_s
|
|
74
|
+
)
|
|
75
|
+
result["volumeId"]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def destroy_volume(volume)
|
|
79
|
+
ec2.delete_volume(:volume_id => volume)
|
|
80
|
+
"done"
|
|
81
|
+
end
|
|
82
|
+
|
|
28
83
|
def fetch_list
|
|
29
84
|
result = ec2.describe_instances
|
|
30
85
|
return [] unless result.reservationSet
|
|
@@ -52,6 +107,15 @@ class Sumo
|
|
|
52
107
|
end
|
|
53
108
|
end
|
|
54
109
|
|
|
110
|
+
def find_volume(volume_id)
|
|
111
|
+
return unless volume_id
|
|
112
|
+
volume_id = volume_id.strip.downcase
|
|
113
|
+
volumes.detect do |volume|
|
|
114
|
+
volume[:volume_id] == volume_id or
|
|
115
|
+
volume[:volume_id].gsub(/^vol-/, '') == volume_id
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
55
119
|
def running
|
|
56
120
|
list_by_status('running')
|
|
57
121
|
end
|
|
@@ -146,12 +210,20 @@ class Sumo
|
|
|
146
210
|
ec2.terminate_instances(:instance_id => [ instance_id ])
|
|
147
211
|
end
|
|
148
212
|
|
|
213
|
+
def console_output(instance_id)
|
|
214
|
+
ec2.get_console_output(:instance_id => instance_id)["output"]
|
|
215
|
+
end
|
|
216
|
+
|
|
149
217
|
def config
|
|
150
218
|
@config ||= default_config.merge read_config
|
|
151
219
|
end
|
|
152
220
|
|
|
153
221
|
def default_config
|
|
154
|
-
{
|
|
222
|
+
{
|
|
223
|
+
'user' => 'root',
|
|
224
|
+
'ami' => 'ami-ed46a784',
|
|
225
|
+
'availability_zone' => 'us-east-1b'
|
|
226
|
+
}
|
|
155
227
|
end
|
|
156
228
|
|
|
157
229
|
def sumo_dir
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sumo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adam Wiggins
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-09-
|
|
12
|
+
date: 2009-09-10 00:00:00 -07:00
|
|
13
13
|
default_executable: sumo
|
|
14
14
|
dependencies: []
|
|
15
15
|
|