Skip to content

Commit

Permalink
Merge branch 'refactors'
Browse files Browse the repository at this point in the history
  • Loading branch information
freels committed Mar 15, 2010
2 parents ac0b149 + bc01619 commit fb41a36
Show file tree
Hide file tree
Showing 12 changed files with 293 additions and 221 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pkg/*
21 changes: 0 additions & 21 deletions Capfile

This file was deleted.

52 changes: 52 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
require 'rubygems'
require 'rake'

begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = "murder"
gem.summary = %Q{Large scale server deploys using BitTorrent and the BitTornado library}
gem.description = %Q{Large scale server deploys using BitTorrent and the BitTornado library}
gem.email = "[email protected]"
gem.homepage = "http://github.com/lg/murder"
gem.authors = ["Larry Gadea"]
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
end
Jeweler::GemcutterTasks.new
rescue LoadError
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
end

# require 'rake/testtask'
# Rake::TestTask.new(:test) do |test|
# test.libs << 'lib' << 'test'
# test.pattern = 'test/**/test_*.rb'
# test.verbose = true
# end

# begin
# require 'rcov/rcovtask'
# Rcov::RcovTask.new do |test|
# test.libs << 'test'
# test.pattern = 'test/**/test_*.rb'
# test.verbose = true
# end
# rescue LoadError
# task :rcov do
# abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
# end
# end

# task :test => :check_dependencies

# task :default => :test

# require 'rake/rdoctask'
# Rake::RDocTask.new do |rdoc|
# version = File.exist?('VERSION') ? File.read('VERSION') : ""

# rdoc.rdoc_dir = 'rdoc'
# rdoc.title = "murder #{version}"
# rdoc.rdoc_files.include('README*')
# rdoc.rdoc_files.include('lib/**/*.rb')
# end
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.0.0.pre
28 changes: 28 additions & 0 deletions doc/examples/Capfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Capfile with example murder config

require 'rubygems'
require 'murder'

set :application, 'example-app'

set :scm, 'git'
set :repository, 'ssh://git.example.com/my/app.git'
set :copy_exclude, '.git'

# use murder
set :deploy_via, :murder

# convenient hooks
after 'deploy:setup', 'murder:distribute_files' # setup remote murder support files on all hosts
before 'murder:start_seeding', 'murder:start_tracker' # let deploy manage the tracker as well
after 'murder:stop_seeding', 'murder:stop_tracker'

# define an app server role
role :app, 'w01', 'w02', 'w03', 'w04', 'w05'

# murder roles (optional. seeder/tracker will default to the first deployable server)
role :tracker, 'tracker01'
role :seeder, 'seeder01'
# peer role defaults to all deployable servers (all except :no_release => true)
# you shouldn't need to set this if you are using the deploy strategy.
#role :peer, 'w01', 'w02', 'w03', 'w04', 'w05'
52 changes: 52 additions & 0 deletions lib/capistrano/recipes/deploy/strategy/murder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright 2010 Twitter, Inc.
# Copyright 2010 Larry Gadea <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require 'capistrano/recipes/deploy/strategy/copy'

module Capistrano
module Deploy
module Strategy
class Murder < Capistrano::Deploy::Strategy::Copy
def upload(filename, remote_filename)
puts "Uploading release to seeder..."
configuration.upload(filename, remote_filename, :roles => :seeder)

ENV["tag"] = File.basename(filename)
ENV["path_is_file"] = "yes"
ENV["files_path"] = remote_filename
ENV['destination_path'] = remote_filename

puts "Creating torrent..."
murder.create_torrent

puts "Starting seeding..."
murder.start_seeding

puts "Peering..."
murder.peer

puts "Done. Killing seeding and all peering..."
murder.stop_peering
murder.stop_seeding

puts "Cleaning temp files..."
murder.clean_temp_files

puts "THANK YOU FOR USING MURDER, HAVE A NICE DAY"
end
end
end
end
end
43 changes: 43 additions & 0 deletions lib/murder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Copyright 2010 Twitter, Inc.
# Copyright 2010 Larry Gadea <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Capistrano::Configuration.instance(:must_exist).load do

load_paths.push File.expand_path('../', __FILE__)

load 'murder/murder'
load 'murder/admin'

# no default defaults...
set :default_tag, ''
set :default_seeder_files_path, ''
set :default_destination_path, ''

# default remote dist path in app shared directory
set(:remote_murder_path) { "#{shared_path}/murder" }

# roles
excluded_roles = [:peer, :tracker, :seeder]

# get around the fact that find_servers does not work in role evaluation
# (it tries to evaluate all roles, leading to infinite recursion)
role :peer do
roles.reject{|k,v| excluded_roles.include? k }.values.map(&:servers).flatten.uniq.reject{|s| s.options[:no_release] }
end

role(:tracker) { roles[:peer].servers.first }
role(:seeder) { roles[:peer].servers.first }

end
11 changes: 5 additions & 6 deletions murder_admin.rb → lib/murder/admin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# Load the basic functionality from murder.rb
load "murder"

namespace :murder do
task :distribute_files, :roles => [:tracker, :seeder, :peer] do
dist_path = File.expand_path('../../dist', __FILE__)

run "mkdir -p #{remote_murder_path}/"
run "[ $(find '#{remote_murder_path}/'* | wc -l ) -lt 1000 ] && rm -rf '#{remote_murder_path}/'* || ( echo 'Cowardly refusing to remove files! Check the remote_murder_path.' ; exit 1 )"

# TODO: Skip hidden (.*) files
# TODO: Specifyable tmp file
system "tar -c -z -C dist -f /tmp/murder_dist.tgz ."
system "tar -c -z -C #{dist_path} -f /tmp/murder_dist.tgz ."
upload("/tmp/murder_dist.tgz", "/tmp/murder_dist.tgz", :via => :sftp)
run "tar xf /tmp/murder_dist.tgz -C #{remote_murder_path}"
run "rm /tmp/murder_dist.tgz"
system "rm /tmp/murder_dist.tgz"
end

task :start_tracker, :roles => :tracker do
run("screen -dms murder_tracker python #{remote_murder_path}/murder_tracker.py", :pty => true)
run("screen -dms murder_tracker python #{remote_murder_path}/murder_tracker.py && sleep 0.2", :pty => true)
end

task :stop_tracker, :roles => :tracker do
Expand All @@ -45,4 +44,4 @@
task :stop_all_peering, :roles => :peer do
run("pkill -f \"murder_client.py peer\"")
end
end
end
17 changes: 10 additions & 7 deletions murder.rb → lib/murder/murder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# Be sure to import the murder config from your Capfile.
# Note that you shouldn't need to modify this file unless you want to
# change functionality.
# no default defaults...
set :default_tag, ''
set :default_seeder_files_path, ''
set :default_destination_path, ''

# Generate roles based on config
role :tracker, "#{tracker_host}#{host_suffix}", :no_release => true
role :seeder, "#{seeder_host}#{host_suffix}", :no_release => true
peers.each { |host| eval "role :peer, \"#{host}#{host_suffix}\", :no_release => true;" } if respond_to?(:peers)
# default remote dist path in app shared directory
set(:remote_murder_path) { "#{shared_path}/murder" }

namespace :murder do
task :create_torrent, :roles => :seeder do
Expand All @@ -36,6 +35,10 @@
run "tar -c -z -C #{seeder_files_path}/ -f #{filename} --exclude \".git*\" ."
end

tracker = find_servers(:roles => :tracker).first
tracker_host = tracker.host
tracker_port = variables[:tracker_port] || '8998'

run "python #{remote_murder_path}/murder_make_torrent.py '#{filename}' #{tracker_host}:#{tracker_port} '#{filename}.torrent'"

download_torrent unless ENV['do_not_download_torrent']
Expand Down
101 changes: 101 additions & 0 deletions murder.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Generated by jeweler
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
# -*- encoding: utf-8 -*-

Gem::Specification.new do |s|
s.name = %q{murder}
s.version = "0.0.0.pre"

s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
s.authors = ["Larry Gadea"]
s.date = %q{2010-03-15}
s.description = %q{Large scale server deploys using BitTorrent and the BitTornado library}
s.email = %q{[email protected]}
s.extra_rdoc_files = [
"LICENSE",
"README"
]
s.files = [
".gitignore",
"LICENSE",
"README",
"Rakefile",
"VERSION",
"dist/BitTornado/BT1/Choker.py",
"dist/BitTornado/BT1/Connecter.py",
"dist/BitTornado/BT1/Downloader.py",
"dist/BitTornado/BT1/DownloaderFeedback.py",
"dist/BitTornado/BT1/Encrypter.py",
"dist/BitTornado/BT1/FileSelector.py",
"dist/BitTornado/BT1/Filter.py",
"dist/BitTornado/BT1/HTTPDownloader.py",
"dist/BitTornado/BT1/NatCheck.py",
"dist/BitTornado/BT1/PiecePicker.py",
"dist/BitTornado/BT1/Rerequester.py",
"dist/BitTornado/BT1/Statistics.py",
"dist/BitTornado/BT1/Storage.py",
"dist/BitTornado/BT1/StorageWrapper.py",
"dist/BitTornado/BT1/StreamCheck.py",
"dist/BitTornado/BT1/T2T.py",
"dist/BitTornado/BT1/Uploader.py",
"dist/BitTornado/BT1/__init__.py",
"dist/BitTornado/BT1/btformats.py",
"dist/BitTornado/BT1/fakeopen.py",
"dist/BitTornado/BT1/makemetafile.py",
"dist/BitTornado/BT1/track.py",
"dist/BitTornado/ConfigDir.py",
"dist/BitTornado/ConfigReader.py",
"dist/BitTornado/ConnChoice.py",
"dist/BitTornado/CreateIcons.py",
"dist/BitTornado/CurrentRateMeasure.py",
"dist/BitTornado/HTTPHandler.py",
"dist/BitTornado/PSYCO.py",
"dist/BitTornado/RateLimiter.py",
"dist/BitTornado/RateMeasure.py",
"dist/BitTornado/RawServer.py",
"dist/BitTornado/ServerPortHandler.py",
"dist/BitTornado/SocketHandler.py",
"dist/BitTornado/__init__.py",
"dist/BitTornado/bencode.py",
"dist/BitTornado/bitfield.py",
"dist/BitTornado/clock.py",
"dist/BitTornado/download_bt1.py",
"dist/BitTornado/inifile.py",
"dist/BitTornado/iprangeparse.py",
"dist/BitTornado/launchmanycore.py",
"dist/BitTornado/natpunch.py",
"dist/BitTornado/parseargs.py",
"dist/BitTornado/parsedir.py",
"dist/BitTornado/piecebuffer.py",
"dist/BitTornado/selectpoll.py",
"dist/BitTornado/subnetparse.py",
"dist/BitTornado/torrentlistparse.py",
"dist/BitTornado/zurllib.py",
"dist/murder_client.py",
"dist/murder_make_torrent.py",
"dist/murder_tracker.py",
"doc/examples/Capfile",
"lib/capistrano/recipes/deploy/strategy/murder.rb",
"lib/murder.rb",
"lib/murder/admin.rb",
"lib/murder/murder.rb",
"murder.gemspec"
]
s.homepage = %q{http://github.com/lg/murder}
s.rdoc_options = ["--charset=UTF-8"]
s.require_paths = ["lib"]
s.rubygems_version = %q{1.3.6}
s.summary = %q{Large scale server deploys using BitTorrent and the BitTornado library}

if s.respond_to? :specification_version then
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 3

if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
else
end
else
end
end

Loading

0 comments on commit fb41a36

Please sign in to comment.