murder 0.0.0.pre → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +115 -102
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/dist/murder_client.py +15 -14
- data/dist/murder_make_torrent.py +1 -0
- data/dist/murder_tracker.py +1 -0
- data/lib/capistrano/recipes/deploy/strategy/murder.rb +1 -0
- data/lib/murder.rb +1 -0
- data/lib/murder/admin.rb +8 -0
- data/lib/murder/murder.rb +16 -8
- data/murder.gemspec +4 -4
- metadata +8 -10
data/README
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
Murder by Larry Gadea and Matt Freels
|
1
|
+
Murder by Larry Gadea <lg@twitter.com> and Matt Freels <freels@twitter.com>
|
2
2
|
Copyright 2010 Twitter Inc.
|
3
3
|
|
4
|
+
|
4
5
|
DESCRIPTION
|
5
6
|
-----------
|
6
7
|
|
@@ -11,6 +12,23 @@ centralized distribution systems wouldn't otherwise function. A "Murder" is
|
|
11
12
|
normally used to refer to a flock of crows, which in this case applies to a
|
12
13
|
bunch of servers doing something.
|
13
14
|
|
15
|
+
|
16
|
+
QUICK START
|
17
|
+
-----------
|
18
|
+
|
19
|
+
For the impatient, `gem install murder` and add these lines to your Capfile:
|
20
|
+
|
21
|
+
require 'murder'
|
22
|
+
|
23
|
+
set :deploy_via, :murder
|
24
|
+
after 'deploy:setup', 'murder:distribute_files'
|
25
|
+
before 'murder:start_seeding', 'murder:start_tracker'
|
26
|
+
after 'murder:stop_seeding', 'murder:stop_tracker'
|
27
|
+
|
28
|
+
|
29
|
+
HOW IT WORKS
|
30
|
+
------------
|
31
|
+
|
14
32
|
In order to do a Murder transfer, there are several components required to be
|
15
33
|
set up beforehand -- many the result of BitTorrent nature of the system. Murder
|
16
34
|
is based on BitTornado.
|
@@ -23,68 +41,99 @@ acceptable. To keep things simple tracker-less distribution (DHT) is currently
|
|
23
41
|
not supported. The tracker is actually just a mini-httpd that hosts a
|
24
42
|
/announce path which the Bittorrent clients update their state onto.
|
25
43
|
|
26
|
-
- A seeder. This is the server which has the files that you'd like to
|
27
|
-
onto all other servers.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
.torrent files are currently being distributed. Once a Murder transfer
|
33
|
-
started, the seeder will be the first server many machines go to to
|
34
|
-
pieces. These pieces will then be distributed in a tree-fashion to
|
35
|
-
the network, but without necessarily getting the parts
|
44
|
+
- A seeder. This is the server which has the files that you'd like to
|
45
|
+
deploy onto all other servers. The files are placed into a directory
|
46
|
+
that a torrent gets created from. Murder will tgz up the directory and
|
47
|
+
create a .torrent file (a very small file containing basic hash
|
48
|
+
information about the tgz file). This .torrent file lets the peers
|
49
|
+
know what they're downloading. The tracker keeps track of which
|
50
|
+
.torrent files are currently being distributed. Once a Murder transfer
|
51
|
+
is started, the seeder will be the first server many machines go to to
|
52
|
+
get pieces. These pieces will then be distributed in a tree-fashion to
|
53
|
+
the rest of the network, but without necessarily getting the parts
|
54
|
+
from the seeder.
|
36
55
|
|
37
56
|
- Peers. This is the group of servers (hundreds to tens of thousands) which
|
38
57
|
will be receiving the files and distributing the pieces amongst themselves.
|
39
58
|
Once a peer is done downloading the entire tgz file, it will continue seeding
|
40
59
|
for a while to prevent a hotspot effect on the seeder.
|
41
60
|
|
42
|
-
|
61
|
+
|
62
|
+
CONFIGURATION AND USAGE
|
43
63
|
-----------------------
|
44
64
|
|
45
|
-
|
46
|
-
|
65
|
+
Murder integrates with Capistrano. The most simple way to use it is as
|
66
|
+
a deploy strategy, by setting `:deploy_via` to `:murder`. By default,
|
67
|
+
murder makes the same assumptions that cap makes. All servers without
|
68
|
+
`:no_release => true` will act as peers. Additionally, murder will
|
69
|
+
automatically use the first peer as both tracker and seeder. you may
|
70
|
+
redefine the `tracker`, `seeder` and `peer` roles yourself to change
|
71
|
+
these defaults, for instance, if you want to set up a dedicated
|
72
|
+
tracker.
|
73
|
+
|
74
|
+
All involved servers must have python installed and the related murder
|
75
|
+
support files (BitTornado, etc.). To upload the support files to the
|
76
|
+
tracker, seeder, and peers, run:
|
77
|
+
|
47
78
|
cap murder:distribute_files
|
48
|
-
|
79
|
+
|
80
|
+
By default, these will go in `shared/murder` in your apps deploy
|
81
|
+
directory. Override this by setting the variable
|
82
|
+
`remote_murder_path`. For convenience, you can add an after hook to
|
83
|
+
run this on `deploy:setup`:
|
84
|
+
|
85
|
+
after 'deploy:setup', 'murder:distribute_files'
|
86
|
+
|
87
|
+
Before deploying, you must start the tracker:
|
88
|
+
|
49
89
|
cap murder:start_tracker
|
50
|
-
4. Create a torrent file from a remote directory of files (on seeder):
|
51
|
-
cap murder:create_torrent tag="Deploy20100101" files_path="~/files"
|
52
|
-
5. Start seeding the files:
|
53
|
-
cap murder:start_seeding tag="Deploy20100101"
|
54
|
-
6. Distribute the files to all servers:
|
55
|
-
cap murder:peer tag="Deploy20100101" destination_path="/tmp/out"
|
56
90
|
|
57
|
-
|
91
|
+
To have this happen automatically during a deploy, add the following hooks:
|
58
92
|
|
59
|
-
|
60
|
-
|
93
|
+
before 'murder:start_seeding', 'murder:start_tracker'
|
94
|
+
after 'murder:stop_seeding', 'murder:stop_tracker'
|
95
|
+
|
96
|
+
At this point you should be able to deploy normally:
|
97
|
+
|
98
|
+
cap deploy
|
99
|
+
|
100
|
+
|
101
|
+
MANUAL USAGE (murder without a deploy strategy)
|
102
|
+
-----------------------------------------------
|
103
|
+
|
104
|
+
Murder can also be used as a general mechanism to distribute files
|
105
|
+
across a generic set of servers. To do so create a Capfile, require
|
106
|
+
murder, and manually define roles:
|
107
|
+
|
108
|
+
require 'rubygems'
|
109
|
+
require 'murder'
|
110
|
+
|
111
|
+
set :remote_murder_path, '/opt/local/murder' # or some other directory
|
112
|
+
|
113
|
+
role :peer, 'host1', 'host2', 'host3', 'host4', 'host5', host6', host7'
|
114
|
+
role :seeder, 'host1'
|
115
|
+
role :tracker, 'host1'
|
116
|
+
|
117
|
+
To distribute a directory of files, first make sure that murder is set
|
118
|
+
up on all hosts, then manually run the murder cap tasks:
|
119
|
+
|
120
|
+
1. Start the tracker:
|
121
|
+
cap murder:start_tracker
|
122
|
+
|
123
|
+
2. Create a torrent from a directory of files on the seeder, and start seeding:
|
124
|
+
scp -r ./files host1:~/files
|
125
|
+
cap murder:create_torrent tag="Deploy1" files_path="~/files"
|
126
|
+
cap murder:start_seeding tag="Deploy1"
|
127
|
+
|
128
|
+
3. Distribute the torrent to all peers:
|
129
|
+
cap murder:peer tag="Deploy1" destination_path="/tmp"
|
130
|
+
|
131
|
+
4. Stop the seeder and tracker:
|
132
|
+
cap murder:stop_seeding
|
133
|
+
cap murder:stop_tracker
|
134
|
+
|
135
|
+
When this finishes, all peers will have the files in /tmp/Deploy1
|
61
136
|
|
62
|
-
cap murder:distribute_files
|
63
|
-
cap murder:start_tracker
|
64
|
-
cap murder:create_torrent tag="Deploy20100101"
|
65
|
-
files_path="/usr/local/twitter/production/current"
|
66
|
-
cap murder:start_seeding tag="Deploy20100101"
|
67
|
-
time cap murder:peer tag="Deploy20100101"
|
68
|
-
destination_path="/usr/local/twitter/releases"
|
69
|
-
|
70
|
-
All the files have been transferred to all servers at this point. To clean up
|
71
|
-
use:
|
72
|
-
|
73
|
-
cap murder:stop_seeding
|
74
|
-
cap murder:stop_tracker
|
75
|
-
|
76
|
-
HOW TO LEARN MURDER INCREMENTALLY
|
77
|
-
---------------------------------
|
78
|
-
|
79
|
-
- Skim dist/*.py to see what Murder does behind the scenes
|
80
|
-
- Experiment with the python scripts
|
81
|
-
- Read Capfile
|
82
|
-
- Read murder_config.rb
|
83
|
-
- Read murder_admin.rb
|
84
|
-
- Read murder.rb
|
85
|
-
- Read the reference below
|
86
|
-
- Experiment with the Capistrano deploy methods
|
87
|
-
- Read and experiment with the Murder Capistrano strategy
|
88
137
|
|
89
138
|
TASK REFERENCE
|
90
139
|
--------------
|
@@ -151,15 +200,11 @@ stop_all_peering:
|
|
151
200
|
command will forcibly kill all "murder_client.py peer" commands that are
|
152
201
|
running.
|
153
202
|
|
154
|
-
CONFIG REFERENCE
|
155
|
-
|
156
|
-
user:
|
157
|
-
Provided by Capistrano to specify if to use a different username when sshing
|
158
|
-
into machines.
|
203
|
+
CONFIG REFERENCE
|
204
|
+
----------------
|
159
205
|
|
160
|
-
|
161
|
-
|
162
|
-
be added to the end when trying to connect to them.
|
206
|
+
Variables
|
207
|
+
---------
|
163
208
|
|
164
209
|
default_tag:
|
165
210
|
A tag name to use by default such that a tag parameter doesn't need to be
|
@@ -174,51 +219,19 @@ default_destination_path:
|
|
174
219
|
A path on the peers' file system where the files that were distributed
|
175
220
|
should be decompressed into.
|
176
221
|
|
177
|
-
|
178
|
-
|
179
|
-
|
222
|
+
remote_murder_path:
|
223
|
+
A path where murder will look for its support files on each host. `cap
|
224
|
+
murder:distribute_files` will upload murder support files here.
|
225
|
+
|
226
|
+
|
227
|
+
Roles
|
228
|
+
-----
|
180
229
|
|
181
|
-
|
182
|
-
|
183
|
-
libraries run is hosted on. Must be 8998 for now.
|
230
|
+
tracker:
|
231
|
+
Host on which to run the BitTorrent tracker
|
184
232
|
|
185
|
-
|
186
|
-
|
187
|
-
the files that the peers want. If you're using a host_suffix, do not specify a
|
188
|
-
suffix here.
|
233
|
+
seeder:
|
234
|
+
Host which will be the source of the files to be distributed via BitTorrent
|
189
235
|
|
190
236
|
peers:
|
191
|
-
|
192
|
-
amongst themselves. If you're using a host_suffix, do not specify a suffix
|
193
|
-
here.
|
194
|
-
|
195
|
-
CAPISTRANO COPY STRATEGY
|
196
|
-
------------------------
|
197
|
-
|
198
|
-
In addition to being usable from both the commandline and Capistrano commands,
|
199
|
-
an optional Capistrano copy strategy is included to help easily retrofit
|
200
|
-
existing deploy environments you might already have.
|
201
|
-
|
202
|
-
Requirements to use build.rb
|
203
|
-
- Add a require line for build.rb in your Capfile. This will override the
|
204
|
-
default build strategy. There are some other parameters you must now
|
205
|
-
specify though.
|
206
|
-
- To enable it, add the following to your Capfile:
|
207
|
-
load 'deploy'
|
208
|
-
set :strategy, Capistrano::Deploy::Strategy::Build.new(self)
|
209
|
-
- Add "set :murder, true" to your Capfile
|
210
|
-
- Make sure your release_name is correct (should be already)
|
211
|
-
- If you're distribution is a file instead of a directory,
|
212
|
-
Add "distribution_is_a_file" to your Capfile
|
213
|
-
- Add the following to your Capfile:
|
214
|
-
set :build_task do
|
215
|
-
"true"
|
216
|
-
end
|
217
|
-
set :copy_compression, :gz
|
218
|
-
set :package_name do
|
219
|
-
"#{release_name}-#{real_revision[0, 8]}.tar.#{copy_compression}"
|
220
|
-
end
|
221
|
-
set :branch, variables[:branch] || 'deploy'
|
222
|
-
|
223
|
-
The requirements are a bit hefty for now, though hopefully this will get easier
|
224
|
-
in the future.
|
237
|
+
All hosts to which files should be distributed
|
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ begin
|
|
9
9
|
gem.description = %Q{Large scale server deploys using BitTorrent and the BitTornado library}
|
10
10
|
gem.email = "lg@twitter.com"
|
11
11
|
gem.homepage = "http://github.com/lg/murder"
|
12
|
-
gem.authors = ["Larry Gadea"]
|
12
|
+
gem.authors = ["Larry Gadea", "Matt Freels"]
|
13
13
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
14
|
end
|
15
15
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.0
|
data/dist/murder_client.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Copyright 2010 Twitter, Inc.
|
2
2
|
# Copyright 2010 Larry Gadea <lg@twitter.com>
|
3
|
+
# Copyright 2010 Matt Freels <freels@twitter.com>
|
3
4
|
#
|
4
5
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
5
6
|
# not use this file except in compliance with the License. You may obtain
|
@@ -27,7 +28,7 @@ if PSYCO.psyco:
|
|
27
28
|
psyco.full()
|
28
29
|
except:
|
29
30
|
pass
|
30
|
-
|
31
|
+
|
31
32
|
from BitTornado.download_bt1 import BT1Download, defaults, parse_params, get_usage, get_response
|
32
33
|
from BitTornado.RawServer import RawServer, UPnP_ERROR
|
33
34
|
from random import seed
|
@@ -91,17 +92,17 @@ class HeadlessDisplayer:
|
|
91
92
|
|
92
93
|
def finished(self):
|
93
94
|
global doneFlag
|
94
|
-
|
95
|
+
|
95
96
|
self.done = True
|
96
97
|
self.percentDone = '100'
|
97
98
|
self.timeEst = 'Download Succeeded!'
|
98
99
|
self.downRate = ''
|
99
100
|
#self.display()
|
100
|
-
|
101
|
+
|
101
102
|
global isPeer
|
102
|
-
|
103
|
+
|
103
104
|
print "done and done"
|
104
|
-
|
105
|
+
|
105
106
|
if isPeer:
|
106
107
|
if os.fork():
|
107
108
|
os._exit(0)
|
@@ -118,7 +119,7 @@ class HeadlessDisplayer:
|
|
118
119
|
|
119
120
|
t = threading.Timer(30.0, ok_close_now)
|
120
121
|
t.start()
|
121
|
-
|
122
|
+
|
122
123
|
def failed(self):
|
123
124
|
self.done = True
|
124
125
|
self.percentDone = '0'
|
@@ -135,12 +136,12 @@ class HeadlessDisplayer:
|
|
135
136
|
print errormsg
|
136
137
|
doneFlag.set()
|
137
138
|
|
138
|
-
def display(self, dpflag = Event(), fractionDone = None, timeEst = None,
|
139
|
+
def display(self, dpflag = Event(), fractionDone = None, timeEst = None,
|
139
140
|
downRate = None, upRate = None, activity = None,
|
140
141
|
statistics = None, **kws):
|
141
142
|
if self.last_update_time + 0.1 > clock() and fractionDone not in (0.0, 1.0) and activity is not None:
|
142
143
|
return
|
143
|
-
self.last_update_time = clock()
|
144
|
+
self.last_update_time = clock()
|
144
145
|
if fractionDone is not None:
|
145
146
|
self.percentDone = str(float(int(fractionDone * 1000)) / 10)
|
146
147
|
if timeEst is not None:
|
@@ -174,7 +175,7 @@ class HeadlessDisplayer:
|
|
174
175
|
#print 'seed status: ', self.seedStatus
|
175
176
|
#print 'peer status: ', self.peerStatus
|
176
177
|
#stdout.flush()
|
177
|
-
dpflag.set()
|
178
|
+
dpflag.set()
|
178
179
|
|
179
180
|
def chooseFile(self, default, size, saveas, dir):
|
180
181
|
self.file = '%s (%.1f MB)' % (default, float(size) / (1 << 20))
|
@@ -212,7 +213,7 @@ def run(params):
|
|
212
213
|
|
213
214
|
myid = createPeerID()
|
214
215
|
seed(myid)
|
215
|
-
|
216
|
+
|
216
217
|
global doneFlag
|
217
218
|
doneFlag = Event()
|
218
219
|
def disp_exception(text):
|
@@ -245,7 +246,7 @@ def run(params):
|
|
245
246
|
dow = BT1Download(h.display, h.finished, h.error, disp_exception, doneFlag,
|
246
247
|
config, response, infohash, myid, rawserver, listen_port,
|
247
248
|
configdir)
|
248
|
-
|
249
|
+
|
249
250
|
if not dow.saveAs(h.chooseFile, h.newpath):
|
250
251
|
break
|
251
252
|
|
@@ -283,9 +284,9 @@ if __name__ == '__main__':
|
|
283
284
|
sys.exit(1)
|
284
285
|
|
285
286
|
argv = ["--responsefile", sys.argv[2],
|
286
|
-
"--saveas", sys.argv[3],
|
287
|
+
"--saveas", sys.argv[3],
|
287
288
|
"--ip", sys.argv[4]]
|
288
|
-
|
289
|
+
|
289
290
|
isPeer = sys.argv[1] == "peer"
|
290
|
-
|
291
|
+
|
291
292
|
run(argv[1:])
|
data/dist/murder_make_torrent.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Copyright 2010 Twitter, Inc.
|
2
2
|
# Copyright 2010 Larry Gadea <lg@twitter.com>
|
3
|
+
# Copyright 2010 Matt Freels <freels@twitter.com>
|
3
4
|
#
|
4
5
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
5
6
|
# not use this file except in compliance with the License. You may obtain
|
data/dist/murder_tracker.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Copyright 2010 Twitter, Inc.
|
2
2
|
# Copyright 2010 Larry Gadea <lg@twitter.com>
|
3
|
+
# Copyright 2010 Matt Freels <freels@twitter.com>
|
3
4
|
#
|
4
5
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
5
6
|
# not use this file except in compliance with the License. You may obtain
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# Copyright 2010 Twitter, Inc.
|
2
2
|
# Copyright 2010 Larry Gadea <lg@twitter.com>
|
3
|
+
# Copyright 2010 Matt Freels <freels@twitter.com>
|
3
4
|
#
|
4
5
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
5
6
|
# not use this file except in compliance with the License. You may obtain
|
data/lib/murder.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Copyright 2010 Twitter, Inc.
|
2
2
|
# Copyright 2010 Larry Gadea <lg@twitter.com>
|
3
|
+
# Copyright 2010 Matt Freels <freels@twitter.com>
|
3
4
|
#
|
4
5
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
5
6
|
# not use this file except in compliance with the License. You may obtain
|
data/lib/murder/admin.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Copyright 2010 Twitter, Inc.
|
2
2
|
# Copyright 2010 Larry Gadea <lg@twitter.com>
|
3
|
+
# Copyright 2010 Matt Freels <freels@twitter.com>
|
3
4
|
#
|
4
5
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
5
6
|
# not use this file except in compliance with the License. You may obtain
|
@@ -14,6 +15,9 @@
|
|
14
15
|
# limitations under the License.
|
15
16
|
|
16
17
|
namespace :murder do
|
18
|
+
desc <<-DESC
|
19
|
+
SCPs a compressed version of all files from ./dist (the python Bittorrent library and custom scripts) to all server. The entire directory is sent, regardless of the role of each individual server. The path on the server is specified by remote_murder_path and will be cleared prior to transferring files over.
|
20
|
+
DESC
|
17
21
|
task :distribute_files, :roles => [:tracker, :seeder, :peer] do
|
18
22
|
dist_path = File.expand_path('../../dist', __FILE__)
|
19
23
|
|
@@ -29,18 +33,22 @@ namespace :murder do
|
|
29
33
|
system "rm /tmp/murder_dist.tgz"
|
30
34
|
end
|
31
35
|
|
36
|
+
desc "Starts the Bittorrent tracker (essentially a mini-web-server) listening on port 8998."
|
32
37
|
task :start_tracker, :roles => :tracker do
|
33
38
|
run("screen -dms murder_tracker python #{remote_murder_path}/murder_tracker.py && sleep 0.2", :pty => true)
|
34
39
|
end
|
35
40
|
|
41
|
+
desc "If the Bittorrent tracker is running, this will kill the process. Note that if it is not running you will receive an error."
|
36
42
|
task :stop_tracker, :roles => :tracker do
|
37
43
|
run("pkill -f 'SCREEN.*murder_tracker.py'")
|
38
44
|
end
|
39
45
|
|
46
|
+
desc "Identical to stop_seeding, except this will kill all seeding processes. No 'tag' argument is needed."
|
40
47
|
task :stop_all_seeding, :roles => :seeder do
|
41
48
|
run("pkill -f \"SCREEN.*seeder-\"")
|
42
49
|
end
|
43
50
|
|
51
|
+
desc 'Sometimes peers can go on forever (usually because of an error). This command will forcibly kill all "murder_client.py peer" commands that are running.'
|
44
52
|
task :stop_all_peering, :roles => :peer do
|
45
53
|
run("pkill -f \"murder_client.py peer\"")
|
46
54
|
end
|
data/lib/murder/murder.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Copyright 2010 Twitter, Inc.
|
2
2
|
# Copyright 2010 Larry Gadea <lg@twitter.com>
|
3
|
+
# Copyright 2010 Matt Freels <freels@twitter.com>
|
3
4
|
#
|
4
5
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
5
6
|
# not use this file except in compliance with the License. You may obtain
|
@@ -13,15 +14,10 @@
|
|
13
14
|
# See the License for the specific language governing permissions and
|
14
15
|
# limitations under the License.
|
15
16
|
|
16
|
-
# no default defaults...
|
17
|
-
set :default_tag, ''
|
18
|
-
set :default_seeder_files_path, ''
|
19
|
-
set :default_destination_path, ''
|
20
|
-
|
21
|
-
# default remote dist path in app shared directory
|
22
|
-
set(:remote_murder_path) { "#{shared_path}/murder" }
|
23
|
-
|
24
17
|
namespace :murder do
|
18
|
+
desc <<-DESC
|
19
|
+
Compresses the directory specified by the passed-in argument 'files_path' and creates a .torrent file identified by the 'tag' argument. Be sure to use the same 'tag' value with any following commands. Any .git directories will be skipped. Once completed, the .torrent will be downloaded to your local /tmp/TAG.tgz.torrent.
|
20
|
+
DESC
|
25
21
|
task :create_torrent, :roles => :seeder do
|
26
22
|
require_tag
|
27
23
|
if !(seeder_files_path = (default_seeder_files_path if default_seeder_files_path != "") || ENV['files_path'])
|
@@ -44,21 +40,33 @@ namespace :murder do
|
|
44
40
|
download_torrent unless ENV['do_not_download_torrent']
|
45
41
|
end
|
46
42
|
|
43
|
+
desc <<-DESC
|
44
|
+
Although not necessary to run, if the file from create_torrent was lost, you can redownload it from the seeder using this task. You must specify a valid 'tag' argument.
|
45
|
+
DESC
|
47
46
|
task :download_torrent, :roles => :seeder do
|
48
47
|
require_tag
|
49
48
|
download("#{filename}.torrent", "#{filename}.torrent", :via => :scp)
|
50
49
|
end
|
51
50
|
|
51
|
+
desc <<-DESC
|
52
|
+
Will cause the seeder machine to connect to the tracker and start seeding. The ip address returned by the 'host' bash command will be announced to the tracker. The server will not stop seeding until the stop_seeding task is called. You must specify a valid 'tag' argument (which identifies the .torrent in /tmp to use)
|
53
|
+
DESC
|
52
54
|
task :start_seeding, :roles => :seeder do
|
53
55
|
require_tag
|
54
56
|
run "screen -dms 'seeder-#{tag}' python #{remote_murder_path}/murder_client.py seeder '#{filename}.torrent' '#{filename}' `host $HOSTNAME | awk '{print $4}'`"
|
55
57
|
end
|
56
58
|
|
59
|
+
desc <<-DESC
|
60
|
+
If the seeder is currently seeding, this will kill the process. Note that if it is not running, you will receive an error. If a peer was downloading from this seed, the peer will find another host to receive any remaining data. You must specify a valid 'tag' argument.
|
61
|
+
DESC
|
57
62
|
task :stop_seeding, :roles => :seeder do
|
58
63
|
require_tag
|
59
64
|
run("pkill -f \"SCREEN.*seeder-#{tag}\"")
|
60
65
|
end
|
61
66
|
|
67
|
+
desc <<-DESC
|
68
|
+
Instructs all the peer servers to connect to the tracker and start download and spreading pieces and files amongst themselves. You must specify a valid 'tag' argument. Once the download is complete on a server, that server will fork the download process and seed for 30 seconds while returning control to Capistrano. Cap will then extract the files to the passed in 'destination_path' argument to destination_path/TAG/*. To not create this tag named directory, pass in the 'no_tag_directory=1' argument. If the directory is empty, this command will fail. To clean it, pass in the 'unsafe_please_delete=1' argument. The compressed tgz in /tmp is never removed. When this task completes, all files have been transferred and moved into the requested directory.
|
69
|
+
DESC
|
62
70
|
task :peer, :roles => :peer do
|
63
71
|
require_tag
|
64
72
|
|
data/murder.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{murder}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
11
|
-
s.authors = ["Larry Gadea"]
|
12
|
-
s.date = %q{2010-03-
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Larry Gadea", "Matt Freels"]
|
12
|
+
s.date = %q{2010-03-17}
|
13
13
|
s.description = %q{Large scale server deploys using BitTorrent and the BitTornado library}
|
14
14
|
s.email = %q{lg@twitter.com}
|
15
15
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: murder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
4
|
+
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
- pre
|
10
|
-
version: 0.0.0.pre
|
9
|
+
version: 0.1.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Larry Gadea
|
13
|
+
- Matt Freels
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-03-
|
18
|
+
date: 2010-03-17 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -111,13 +111,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
111
|
version: "0"
|
112
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
113
|
requirements:
|
114
|
-
- - "
|
114
|
+
- - ">="
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
segments:
|
117
|
-
-
|
118
|
-
|
119
|
-
- 1
|
120
|
-
version: 1.3.1
|
117
|
+
- 0
|
118
|
+
version: "0"
|
121
119
|
requirements: []
|
122
120
|
|
123
121
|
rubyforge_project:
|