pylon 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in pylon.gemspec
4
+ gemspec
data/NOTICE ADDED
@@ -0,0 +1,8 @@
1
+ Pylon Notice
2
+ ===========
3
+
4
+ Developed by AJ Christensen (http://junglist.gen.nz)
5
+
6
+ * Copyright 2011, AJ Christensen <aj@junglist.gen.nz>
7
+
8
+
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require "rubygems"
4
+ require "bundler"
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+
13
+ require "rake"
14
+ require "jeweler"
15
+ require "rake/testtask"
16
+ require "bundler/gem_tasks"
17
+ require_relative "lib/pylon"
18
+
19
+ Jeweler::Tasks.new do |gem|
20
+ gem.name = "pylon"
21
+ gem.homepage = "http://github.com/fujin/pylon"
22
+ gem.license = "APLv2"
23
+ gem.summary = %Q{standalone leader election with zeromq for ruby}
24
+ gem.description = %Q{leader election with zeromq for ruby using widely available leader election algorithms, similar to gen_leader erlang project in essence}
25
+ gem.email = "aj@junglist.gen.nz"
26
+ gem.authors = ["AJ Christensen"]
27
+ gem.version = Pylon::VERSION
28
+ { "ffi-rzmq" => "~> 0.8.2",
29
+ "mixlib-log" => ">= 0",
30
+ "mixlib-cli" => ">= 0",
31
+ "mixlib-config" => ">= 0",
32
+ "uuidtools" => "~> 2.1.2",
33
+ "json" => ">= 0"
34
+ }.each { |dep,ver| gem.add_runtime_dependency dep, ver }
35
+ { "minitest" => "~> 2.6.0",
36
+ "bundler" => "~> 1.0.0",
37
+ "jeweler" => "~> 1.6.4",
38
+ "rcov" => ">= 0",
39
+ "vagrant" => ">= 0",
40
+ "virtualbox" => ">= 0"
41
+ }.each { |dep,ver| gem.add_development_dependency dep, ver }
42
+ end
43
+
44
+ Jeweler::RubygemsDotOrgTasks.new
45
+
46
+ Rake::TestTask.new(:test) do |test|
47
+ test.libs << 'lib' << 'test'
48
+ test.pattern = 'test/**/test_*.rb'
49
+ test.verbose = true
50
+ end
51
+
52
+
53
+
@@ -0,0 +1,18 @@
1
+ def pylon_vm(config=nil, name=:pylon, count=0)
2
+ return unless config
3
+ config.vm.define(name) do |config|
4
+ config.vm.box = 'natty64_cloudscaling_4.1'
5
+ config.vm.box_url = "http://d1lfnqkkmlbdsd.cloudfront.net/vagrant/natty64_cloudscaling_4.1.box"
6
+ config.vm.network "33.33.33.#{10 + count}"
7
+ config.vm.provision :chef_solo do |chef|
8
+ chef.cookbooks_path = "cookbooks"
9
+ chef.add_recipe "pylon"
10
+ end
11
+ end
12
+ end
13
+
14
+ Vagrant::Config.run do |config|
15
+ 10.times do |i|
16
+ pylon_vm(config, "pylon#{i}".to_sym, i)
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ = DESCRIPTION:
2
+
3
+ = REQUIREMENTS:
4
+
5
+ = ATTRIBUTES:
6
+
7
+ = USAGE:
8
+
@@ -0,0 +1,7 @@
1
+ maintainer "AJ Christensen"
2
+ maintainer_email "aj@junglist.gen.nz"
3
+ license "Apache 2.0"
4
+ description "Installs/Configures pylon"
5
+ long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
6
+ require File.expand_path(File.join(File.dirname(__FILE__),"..", "..", "lib", "/pylon.rb"))
7
+ version Pylon::VERSION
@@ -0,0 +1,43 @@
1
+ #
2
+ # Cookbook Name:: pylon
3
+ # Recipe:: default
4
+ #
5
+ # Copyright 2011, AJ Christensen
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ execute "apt-get update"
21
+ %w{zeromq build-essential tmux}.each do |pkg|
22
+ package pkg
23
+ end
24
+
25
+ execute "rsync -avu --progress --delete /vagrant/ /srv/pylon/" do
26
+ notifies :delete, "directory[/srv/pylon/vendor/bundle]"
27
+ notifies :run, "execute[bundle]"
28
+ end
29
+
30
+ directory "/srv/pylon/vendor/bundle" do
31
+ action :nothing
32
+ recursive true
33
+ end
34
+
35
+ execute "bundle" do
36
+ command "bundle install --deployment"
37
+ cwd "/srv/pylon"
38
+ user "vagrant"
39
+ group "vagrant"
40
+ action :nothing
41
+ end
42
+
43
+
@@ -15,5 +15,5 @@
15
15
  # limitations under the License.
16
16
 
17
17
  class Pylon
18
- VERSION = "0.2.2"
18
+ VERSION = "0.2.3"
19
19
  end
@@ -53,9 +53,9 @@ class Pylon
53
53
  sleep_after_announce 5
54
54
 
55
55
  # TODO: not implemented
56
- ping_interval 1
57
- ping_timeout 30
58
- ping_retries 3
56
+ fd_interval 30
57
+ fd_timeout 30
58
+ fd_retries 3
59
59
 
60
60
  end
61
61
  end
@@ -37,7 +37,7 @@ class Pylon
37
37
  Pylon::Log.info "elector[#{cluster_name}] initialized, starting pub/sub sockets on #{multicast_endpoint} and tcp listener socket on #{node.unicast_endpoint}"
38
38
 
39
39
  Thread.abort_on_exception = true
40
-
40
+
41
41
  scheduler = Thread.new do
42
42
  @unicast_announcer_thread = node.unicast_announcer
43
43
  @multicast_announcer_thread = node.multicast_announcer
@@ -88,12 +88,65 @@ class Pylon
88
88
  end
89
89
 
90
90
  def add_node node
91
- @nodes << node unless @nodes.include? node
91
+ nodes << node unless nodes.include? node
92
+ # fire up a new failure detector
93
+ failure_detectors.each do |thread|
94
+ thread.join
95
+ end
96
+ end
97
+
98
+ def ping_node node
99
+ begin
100
+ Pylon::Config[:fd_retries].times do |attempt|
101
+ begin
102
+ Timeout::timeout(Pylon::Config[:fd_timeout]) do
103
+ pong, timestamp = node.send "ping", :attempt => attempt
104
+ if (timestamp - Time.now.to_i) >= 600
105
+ Log.warn "failure_detector: received bad timestamp from #{node}, sending 'exit' message"
106
+ node.send "exit", {"message" => "bad timestamp received after #{Pylon::Config[:fd_retries]}"}
107
+ nodes.delete node
108
+ else
109
+ Log.debug "failure_detector: received good pong with timestamp: #{timestamp}"
110
+ Thread.pass
111
+ end
112
+ end
113
+ rescue Timeout::Error
114
+ Log.warn "failure_detector: #{node} timed out, removing"
115
+ nodes.delete node
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ def assert_leadership
122
+ nodes.each do |node|
123
+ Thread.new do
124
+ status = node.send "status"
125
+ Log.info "assert_leadership: status of #{node}: #{status}"
126
+ sync_time = node.send "sync_time"
127
+ Log.info "assert_leadership: sync_time: #{sync_time}"
128
+ end
129
+ end.each do |thread|
130
+ thread.join
131
+ end if master
132
+ end
133
+
134
+ def failure_detectors
135
+ nodes.reject{|n| n == node}.map do |node|
136
+ Thread.new do
137
+ Log.info "failure_detector: starting failure detection against #{node}"
138
+ loop do
139
+ assert_leadership
140
+ ping_node node
141
+ allocate_master
142
+ end
143
+ end
144
+ end
92
145
  end
93
146
 
94
147
  def multicast_listener
95
148
  Thread.new do
96
- Log.debug "multicast_listener: zeromq sub socket starting up on #{@multicast_endpoint}"
149
+ Log.debug "multicast_listener: zeromq sub socket starting up on #{multicast_endpoint}"
97
150
  sub_socket = context.socket ZMQ::SUB
98
151
  sub_socket.setsockopt ZMQ::IDENTITY, "node"
99
152
  sub_socket.setsockopt ZMQ::SUBSCRIBE, ""
@@ -109,14 +162,14 @@ class Pylon
109
162
  end
110
163
 
111
164
  def allocate_master
112
- nodes.sort.each do |node|
113
- Log.debug "node: #{node}"
165
+ nodes.sort!.each do |node|
166
+ Log.debug "allocate_master: node: #{node}"
114
167
  end
115
- if node.uuid == nodes.sort.last.uuid
168
+ if node.uuid == nodes.last.uuid
116
169
  @master = true
117
- Log.info "allocate_master: master allocated"
170
+ Log.info "allocate_master: master allocated; sending new_leader"
118
171
  nodes.each do |node|
119
- connect_node node.uuid.to_s, node.unicast_endpoint
172
+ node.send "new_leader", node
120
173
  end
121
174
  else
122
175
  Log.info "allocate_master: someone else is the master, getting ready for work"
@@ -126,33 +179,34 @@ class Pylon
126
179
 
127
180
  def handle_announce recv_string
128
181
  Log.info "handle_announce: got string #{recv_string}"
129
- node = JSON.parse(recv_string)
130
- Log.info "handle_anounce: got announce from #{node}"
182
+ new_node = JSON.parse(recv_string)
183
+ Log.info "handle_anounce: got announce from #{new_node}"
131
184
  if master
132
- Log.info "handle_announce: I am the master: updating #{node} of leadership status"
133
- connect_node(node.uuid.to_s, node.unicast_endpoint)
185
+ Log.info "handle_announce: I am the master: updating #{new_node} of leadership status"
186
+ if node.weight > new_node.weight
187
+ Log.info "handle_announce: I'm bigger than you: sending new_leader to #{new_node}"
188
+ new_node.send "new_leader", node
189
+ else
190
+ Log.info "handle_announce: new leader, sending change_leader to all nodes"
191
+ nodes.each do |n|
192
+ n.send "change_leader", new_node
193
+ end
194
+ end
134
195
  elsif nodes.length < Pylon::Config[:minimum_master_nodes]
135
196
  if nodes.include? node
136
197
  Log.info "handle_announce: skipping node #{node}, already known"
137
198
  Log.debug "handle_announce: nodes: #{nodes}"
138
199
  else
139
- Log.info "handle_announce: subscribing for #{node} on endpoint: #{node.unicast_endpoint}"
140
- connect_node(node.uuid.to_s, node.unicast_endpoint)
200
+ Log.info "handle_announce: connecting to #{node} on endpoint: #{node.unicast_endpoint}"
201
+ connect_node node
141
202
  end
142
- else
143
- allocate_master
144
203
  end
145
204
  end
146
205
 
147
- def connect_node uuid, endpoint
148
- Log.debug "connect_node: subscribe socket connecting to #{endpoint}"
149
- sub_socket = context.socket ZMQ::SUB
150
- sub_socket.setsockopt ZMQ::IDENTITY, uuid
151
- sub_socket.setsockopt ZMQ::SUBSCRIBE, uuid
152
- sub_socket.connect endpoint
153
- uuid = sub_socket.recv_string
154
- Log.debug "connect_node: got uuid on sub socket, parsing node"
155
- new_node = JSON.parse(sub_socket.recv_string) if sub_socket.more_parts?
206
+
207
+ def connect_node node
208
+ Log.debug "connect_node: request socket connecting to #{node}"
209
+ new_node = node.send "status"
156
210
  Log.debug "connect_node: node: #{new_node}"
157
211
  if nodes.include? new_node
158
212
  Log.info "connect_node: skipping node #{new_node}, already in local list, sleeping for 60 secs"
@@ -163,5 +217,6 @@ class Pylon
163
217
  add_node new_node
164
218
  end
165
219
  end
166
- end
167
- end
220
+
221
+ end # Elector
222
+ end # Pylon
@@ -78,18 +78,64 @@ class Pylon
78
78
  UUIDTools::UUID.timestamp_create
79
79
  end
80
80
 
81
+ # Expects a two element tuple containing a string command and a
82
+ # hash of params:
83
+ # ["command", :params => {}]
84
+ def handle_command string
85
+ command, params = JSON.parse(string)
86
+ case command
87
+ when "sync_time"
88
+ Log.info "handle_command: sync time received, running ntpdate"
89
+ ["sync_time", %x{ntpdate -u pool.ntp.org}]
90
+ when "add"
91
+ Log.info "handle_command: add message received, params: #{params.inspect}"
92
+ when "new_leader"
93
+ Log.info "handle_command: new_leader message received"
94
+ new_leader = params
95
+ new_leader.send "add", self
96
+ self
97
+ when "status"
98
+ Log.info "handle_command: status message received, sending node back"
99
+ self
100
+ when "ping"
101
+ timestamp = Time.now.to_i
102
+ Log.info "handle_command: ping requested, sending pong with timestamp: #{timestamp}"
103
+ ["pong", timestamp]
104
+ when "exit"
105
+ error = "handle_command: exit command received"
106
+ error << " with message: #{params["message"]}" if params.has_key? "message"
107
+ Pylon::Application.fatal! error, 1
108
+ else
109
+ Pylon::Application.fatal! "handle_command: unrecognized command '#{command.inspect}' (params: #{params.inspect}), exiting!", -99
110
+ end
111
+ end
112
+
113
+ def send(command = "status", params = {})
114
+ Thread.new do
115
+ req_socket = context.socket ZMQ::REQ
116
+ req_socket.setsockopt ZMQ::LINGER, 0
117
+ req_socket.connect unicast_endpoint
118
+ if req_socket.send_string "command", ZMQ::SNDMORE
119
+ Log.debug "connect_node: sent command protocol initiator"
120
+ if req_socket.send_string([command, params].to_json)
121
+ response = JSON.parse(req_socket.recv_string)
122
+ end
123
+ end
124
+ response
125
+ end.value
126
+ end
127
+
81
128
  def unicast_announcer
82
129
  Thread.new do
83
130
  Log.debug "unicast_announcer: zeromq pub socket announcer starting up on #{unicast_endpoint}"
84
- pub_socket = context.socket ZMQ::PUB
85
- pub_socket.setsockopt ZMQ::IDENTITY, "node"
86
- pub_socket.bind unicast_endpoint
131
+ rep_socket = context.socket ZMQ::REP
132
+ rep_socket.bind unicast_endpoint
87
133
  loop do
134
+ if rep_socket.recv_string == "command"
135
+ rep_socket.send_string handle_command(rep_socket.recv_string).to_json if rep_socket.more_parts?
136
+ end
88
137
  sleep_after_announce = Pylon::Config[:sleep_after_announce]
89
- Log.debug "#{self}: unicast announcing then sleeping #{sleep_after_announce} secs"
90
- pub_socket.send_string uuid.to_s, ZMQ::SNDMORE
91
- pub_socket.send_string self.to_json
92
- #Thread.pass
138
+ Thread.pass
93
139
  sleep sleep_after_announce
94
140
  end
95
141
 
@@ -109,7 +155,7 @@ class Pylon
109
155
  Log.debug "#{self}: announcing then sleeping #{sleep_after_announce} secs"
110
156
  pub_socket.send_string uuid.to_s, ZMQ::SNDMORE
111
157
  pub_socket.send_string self.to_json
112
- #Thread.pass
158
+ Thread.pass
113
159
  sleep sleep_after_announce
114
160
  end
115
161
  end
@@ -143,5 +189,7 @@ class Pylon
143
189
  Log.debug "#{node}: created from json succesfully"
144
190
  node
145
191
  end
192
+
146
193
  end
147
194
  end
195
+
@@ -0,0 +1,116 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{pylon}
8
+ s.version = "0.2.3"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["AJ Christensen"]
12
+ s.date = %q{2011-09-19}
13
+ s.default_executable = %q{pylon}
14
+ s.description = %q{leader election with zeromq for ruby using widely available leader election algorithms, similar to gen_leader erlang project in essence}
15
+ s.email = %q{aj@junglist.gen.nz}
16
+ s.executables = ["pylon"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.org"
20
+ ]
21
+ s.files = [
22
+ "Gemfile",
23
+ "LICENSE",
24
+ "NOTICE",
25
+ "README.org",
26
+ "Rakefile",
27
+ "Vagrantfile",
28
+ "bin/pylon",
29
+ "cookbooks/pylon/README.rdoc",
30
+ "cookbooks/pylon/metadata.rb",
31
+ "cookbooks/pylon/recipes/default.rb",
32
+ "lib/pylon.rb",
33
+ "lib/pylon/application.rb",
34
+ "lib/pylon/config.rb",
35
+ "lib/pylon/daemon.rb",
36
+ "lib/pylon/elector.rb",
37
+ "lib/pylon/log.rb",
38
+ "lib/pylon/node.rb",
39
+ "lib/pylon/version.rb",
40
+ "pylon.gemspec",
41
+ "test/helper.rb",
42
+ "test/test_pylon.rb"
43
+ ]
44
+ s.homepage = %q{http://github.com/fujin/pylon}
45
+ s.licenses = ["APLv2"]
46
+ s.require_paths = ["lib"]
47
+ s.rubygems_version = %q{1.6.2}
48
+ s.summary = %q{standalone leader election with zeromq for ruby}
49
+
50
+ if s.respond_to? :specification_version then
51
+ s.specification_version = 3
52
+
53
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ s.add_runtime_dependency(%q<pylon>, [">= 0"])
55
+ s.add_development_dependency(%q<minitest>, [">= 0"])
56
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
57
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
58
+ s.add_development_dependency(%q<rcov>, [">= 0"])
59
+ s.add_development_dependency(%q<vagrant>, [">= 0"])
60
+ s.add_development_dependency(%q<virtualbox>, [">= 0"])
61
+ s.add_runtime_dependency(%q<ffi-rzmq>, ["~> 0.8.2"])
62
+ s.add_runtime_dependency(%q<mixlib-log>, [">= 0"])
63
+ s.add_runtime_dependency(%q<mixlib-cli>, [">= 0"])
64
+ s.add_runtime_dependency(%q<mixlib-config>, [">= 0"])
65
+ s.add_runtime_dependency(%q<uuidtools>, ["~> 2.1.2"])
66
+ s.add_runtime_dependency(%q<json>, [">= 0"])
67
+ s.add_development_dependency(%q<minitest>, ["~> 2.6.0"])
68
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
69
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
70
+ s.add_development_dependency(%q<rcov>, [">= 0"])
71
+ s.add_development_dependency(%q<vagrant>, [">= 0"])
72
+ s.add_development_dependency(%q<virtualbox>, [">= 0"])
73
+ else
74
+ s.add_dependency(%q<pylon>, [">= 0"])
75
+ s.add_dependency(%q<minitest>, [">= 0"])
76
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
77
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
78
+ s.add_dependency(%q<rcov>, [">= 0"])
79
+ s.add_dependency(%q<vagrant>, [">= 0"])
80
+ s.add_dependency(%q<virtualbox>, [">= 0"])
81
+ s.add_dependency(%q<ffi-rzmq>, ["~> 0.8.2"])
82
+ s.add_dependency(%q<mixlib-log>, [">= 0"])
83
+ s.add_dependency(%q<mixlib-cli>, [">= 0"])
84
+ s.add_dependency(%q<mixlib-config>, [">= 0"])
85
+ s.add_dependency(%q<uuidtools>, ["~> 2.1.2"])
86
+ s.add_dependency(%q<json>, [">= 0"])
87
+ s.add_dependency(%q<minitest>, ["~> 2.6.0"])
88
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
89
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
90
+ s.add_dependency(%q<rcov>, [">= 0"])
91
+ s.add_dependency(%q<vagrant>, [">= 0"])
92
+ s.add_dependency(%q<virtualbox>, [">= 0"])
93
+ end
94
+ else
95
+ s.add_dependency(%q<pylon>, [">= 0"])
96
+ s.add_dependency(%q<minitest>, [">= 0"])
97
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
98
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
99
+ s.add_dependency(%q<rcov>, [">= 0"])
100
+ s.add_dependency(%q<vagrant>, [">= 0"])
101
+ s.add_dependency(%q<virtualbox>, [">= 0"])
102
+ s.add_dependency(%q<ffi-rzmq>, ["~> 0.8.2"])
103
+ s.add_dependency(%q<mixlib-log>, [">= 0"])
104
+ s.add_dependency(%q<mixlib-cli>, [">= 0"])
105
+ s.add_dependency(%q<mixlib-config>, [">= 0"])
106
+ s.add_dependency(%q<uuidtools>, ["~> 2.1.2"])
107
+ s.add_dependency(%q<json>, [">= 0"])
108
+ s.add_dependency(%q<minitest>, ["~> 2.6.0"])
109
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
110
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
111
+ s.add_dependency(%q<rcov>, [">= 0"])
112
+ s.add_dependency(%q<vagrant>, [">= 0"])
113
+ s.add_dependency(%q<virtualbox>, [">= 0"])
114
+ end
115
+ end
116
+
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'minitest/unit'
11
+
12
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ require 'pylon'
15
+
16
+ class MiniTest::Unit::TestCase
17
+ end
18
+
19
+ MiniTest::Unit.autorun
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestPylon < MiniTest::Unit::TestCase
4
+ def test_something_for_real
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pylon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,89 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-18 00:00:00.000000000 +12:00
12
+ date: 2011-09-19 00:00:00.000000000 +12:00
13
13
  default_executable: pylon
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: pylon
17
+ requirement: &2162102520 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2162102520
26
+ - !ruby/object:Gem::Dependency
27
+ name: minitest
28
+ requirement: &2162101520 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *2162101520
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
+ requirement: &2162099020 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: 1.0.0
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *2162099020
48
+ - !ruby/object:Gem::Dependency
49
+ name: jeweler
50
+ requirement: &2162097740 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: 1.6.4
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *2162097740
59
+ - !ruby/object:Gem::Dependency
60
+ name: rcov
61
+ requirement: &2162096500 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *2162096500
70
+ - !ruby/object:Gem::Dependency
71
+ name: vagrant
72
+ requirement: &2162095180 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *2162095180
81
+ - !ruby/object:Gem::Dependency
82
+ name: virtualbox
83
+ requirement: &2162093740 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: *2162093740
15
92
  - !ruby/object:Gem::Dependency
16
93
  name: ffi-rzmq
17
- requirement: &2170156880 !ruby/object:Gem::Requirement
94
+ requirement: &2162092260 !ruby/object:Gem::Requirement
18
95
  none: false
19
96
  requirements:
20
97
  - - ~>
@@ -22,10 +99,10 @@ dependencies:
22
99
  version: 0.8.2
23
100
  type: :runtime
24
101
  prerelease: false
25
- version_requirements: *2170156880
102
+ version_requirements: *2162092260
26
103
  - !ruby/object:Gem::Dependency
27
104
  name: mixlib-log
28
- requirement: &2170156400 !ruby/object:Gem::Requirement
105
+ requirement: &2162054420 !ruby/object:Gem::Requirement
29
106
  none: false
30
107
  requirements:
31
108
  - - ! '>='
@@ -33,10 +110,10 @@ dependencies:
33
110
  version: '0'
34
111
  type: :runtime
35
112
  prerelease: false
36
- version_requirements: *2170156400
113
+ version_requirements: *2162054420
37
114
  - !ruby/object:Gem::Dependency
38
115
  name: mixlib-cli
39
- requirement: &2170155920 !ruby/object:Gem::Requirement
116
+ requirement: &2162053640 !ruby/object:Gem::Requirement
40
117
  none: false
41
118
  requirements:
42
119
  - - ! '>='
@@ -44,10 +121,10 @@ dependencies:
44
121
  version: '0'
45
122
  type: :runtime
46
123
  prerelease: false
47
- version_requirements: *2170155920
124
+ version_requirements: *2162053640
48
125
  - !ruby/object:Gem::Dependency
49
126
  name: mixlib-config
50
- requirement: &2170155440 !ruby/object:Gem::Requirement
127
+ requirement: &2162052900 !ruby/object:Gem::Requirement
51
128
  none: false
52
129
  requirements:
53
130
  - - ! '>='
@@ -55,10 +132,10 @@ dependencies:
55
132
  version: '0'
56
133
  type: :runtime
57
134
  prerelease: false
58
- version_requirements: *2170155440
135
+ version_requirements: *2162052900
59
136
  - !ruby/object:Gem::Dependency
60
137
  name: uuidtools
61
- requirement: &2170154960 !ruby/object:Gem::Requirement
138
+ requirement: &2162052220 !ruby/object:Gem::Requirement
62
139
  none: false
63
140
  requirements:
64
141
  - - ~>
@@ -66,10 +143,10 @@ dependencies:
66
143
  version: 2.1.2
67
144
  type: :runtime
68
145
  prerelease: false
69
- version_requirements: *2170154960
146
+ version_requirements: *2162052220
70
147
  - !ruby/object:Gem::Dependency
71
148
  name: json
72
- requirement: &2170154480 !ruby/object:Gem::Requirement
149
+ requirement: &2162051620 !ruby/object:Gem::Requirement
73
150
  none: false
74
151
  requirements:
75
152
  - - ! '>='
@@ -77,21 +154,21 @@ dependencies:
77
154
  version: '0'
78
155
  type: :runtime
79
156
  prerelease: false
80
- version_requirements: *2170154480
157
+ version_requirements: *2162051620
81
158
  - !ruby/object:Gem::Dependency
82
159
  name: minitest
83
- requirement: &2170154000 !ruby/object:Gem::Requirement
160
+ requirement: &2162051020 !ruby/object:Gem::Requirement
84
161
  none: false
85
162
  requirements:
86
- - - ! '>='
163
+ - - ~>
87
164
  - !ruby/object:Gem::Version
88
- version: '0'
165
+ version: 2.6.0
89
166
  type: :development
90
167
  prerelease: false
91
- version_requirements: *2170154000
168
+ version_requirements: *2162051020
92
169
  - !ruby/object:Gem::Dependency
93
170
  name: bundler
94
- requirement: &2170153520 !ruby/object:Gem::Requirement
171
+ requirement: &2162050280 !ruby/object:Gem::Requirement
95
172
  none: false
96
173
  requirements:
97
174
  - - ~>
@@ -99,10 +176,10 @@ dependencies:
99
176
  version: 1.0.0
100
177
  type: :development
101
178
  prerelease: false
102
- version_requirements: *2170153520
179
+ version_requirements: *2162050280
103
180
  - !ruby/object:Gem::Dependency
104
181
  name: jeweler
105
- requirement: &2170153040 !ruby/object:Gem::Requirement
182
+ requirement: &2162049140 !ruby/object:Gem::Requirement
106
183
  none: false
107
184
  requirements:
108
185
  - - ~>
@@ -110,10 +187,10 @@ dependencies:
110
187
  version: 1.6.4
111
188
  type: :development
112
189
  prerelease: false
113
- version_requirements: *2170153040
190
+ version_requirements: *2162049140
114
191
  - !ruby/object:Gem::Dependency
115
192
  name: rcov
116
- requirement: &2170152560 !ruby/object:Gem::Requirement
193
+ requirement: &2162047900 !ruby/object:Gem::Requirement
117
194
  none: false
118
195
  requirements:
119
196
  - - ! '>='
@@ -121,10 +198,10 @@ dependencies:
121
198
  version: '0'
122
199
  type: :development
123
200
  prerelease: false
124
- version_requirements: *2170152560
201
+ version_requirements: *2162047900
125
202
  - !ruby/object:Gem::Dependency
126
203
  name: vagrant
127
- requirement: &2170180220 !ruby/object:Gem::Requirement
204
+ requirement: &2162005180 !ruby/object:Gem::Requirement
128
205
  none: false
129
206
  requirements:
130
207
  - - ! '>='
@@ -132,10 +209,10 @@ dependencies:
132
209
  version: '0'
133
210
  type: :development
134
211
  prerelease: false
135
- version_requirements: *2170180220
212
+ version_requirements: *2162005180
136
213
  - !ruby/object:Gem::Dependency
137
214
  name: virtualbox
138
- requirement: &2170179740 !ruby/object:Gem::Requirement
215
+ requirement: &2162004500 !ruby/object:Gem::Requirement
139
216
  none: false
140
217
  requirements:
141
218
  - - ! '>='
@@ -143,7 +220,7 @@ dependencies:
143
220
  version: '0'
144
221
  type: :development
145
222
  prerelease: false
146
- version_requirements: *2170179740
223
+ version_requirements: *2162004500
147
224
  description: leader election with zeromq for ruby using widely available leader election
148
225
  algorithms, similar to gen_leader erlang project in essence
149
226
  email: aj@junglist.gen.nz
@@ -154,6 +231,17 @@ extra_rdoc_files:
154
231
  - LICENSE
155
232
  - README.org
156
233
  files:
234
+ - Gemfile
235
+ - LICENSE
236
+ - NOTICE
237
+ - README.org
238
+ - Rakefile
239
+ - Vagrantfile
240
+ - bin/pylon
241
+ - cookbooks/pylon/README.rdoc
242
+ - cookbooks/pylon/metadata.rb
243
+ - cookbooks/pylon/recipes/default.rb
244
+ - lib/pylon.rb
157
245
  - lib/pylon/application.rb
158
246
  - lib/pylon/config.rb
159
247
  - lib/pylon/daemon.rb
@@ -161,10 +249,9 @@ files:
161
249
  - lib/pylon/log.rb
162
250
  - lib/pylon/node.rb
163
251
  - lib/pylon/version.rb
164
- - lib/pylon.rb
165
- - bin/pylon
166
- - LICENSE
167
- - README.org
252
+ - pylon.gemspec
253
+ - test/helper.rb
254
+ - test/test_pylon.rb
168
255
  has_rdoc: true
169
256
  homepage: http://github.com/fujin/pylon
170
257
  licenses:
@@ -179,6 +266,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
179
266
  - - ! '>='
180
267
  - !ruby/object:Gem::Version
181
268
  version: '0'
269
+ segments:
270
+ - 0
271
+ hash: 352816243979508191
182
272
  required_rubygems_version: !ruby/object:Gem::Requirement
183
273
  none: false
184
274
  requirements: