riak-client 0.9.8 → 1.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +32 -0
- data/Gemfile +17 -11
- data/Guardfile +14 -0
- data/Rakefile +18 -44
- data/erl_src/riak_kv_test_backend.beam +0 -0
- data/erl_src/riak_kv_test_backend.erl +461 -128
- data/erl_src/riak_search_test_backend.beam +0 -0
- data/erl_src/riak_search_test_backend.erl +175 -0
- data/lib/active_support/cache/riak_store.rb +0 -13
- data/lib/riak.rb +11 -16
- data/lib/riak/bucket.rb +59 -41
- data/lib/riak/cache_store.rb +1 -14
- data/lib/riak/client.rb +145 -73
- data/lib/riak/client/beefcake/messages.rb +36 -31
- data/lib/riak/client/beefcake/object_methods.rb +27 -19
- data/lib/riak/client/beefcake_protobuffs_backend.rb +27 -33
- data/lib/riak/client/excon_backend.rb +0 -13
- data/lib/riak/client/http_backend.rb +95 -60
- data/lib/riak/client/http_backend/configuration.rb +144 -19
- data/lib/riak/client/http_backend/key_streamer.rb +1 -14
- data/lib/riak/client/http_backend/object_methods.rb +16 -16
- data/lib/riak/client/http_backend/request_headers.rb +0 -13
- data/lib/riak/client/http_backend/transport_methods.rb +26 -56
- data/lib/riak/client/net_http_backend.rb +11 -13
- data/lib/riak/client/protobuffs_backend.rb +21 -19
- data/lib/riak/client/pump.rb +1 -15
- data/lib/riak/client/search.rb +85 -0
- data/lib/riak/cluster.rb +151 -0
- data/lib/riak/core_ext.rb +1 -0
- data/lib/riak/core_ext/deep_dup.rb +13 -0
- data/lib/riak/core_ext/json.rb +15 -0
- data/lib/riak/core_ext/stringify_keys.rb +1 -1
- data/lib/riak/core_ext/symbolize_keys.rb +1 -1
- data/lib/riak/encoding.rb +6 -0
- data/lib/riak/failed_request.rb +2 -15
- data/lib/riak/i18n.rb +0 -13
- data/lib/riak/json.rb +19 -8
- data/lib/riak/link.rb +18 -20
- data/lib/riak/locale/en.yml +13 -16
- data/lib/riak/map_reduce.rb +40 -20
- data/lib/riak/map_reduce/filter_builder.rb +14 -18
- data/lib/riak/map_reduce/phase.rb +0 -13
- data/lib/riak/map_reduce_error.rb +0 -13
- data/lib/riak/node.rb +38 -0
- data/lib/riak/node/configuration.rb +286 -0
- data/lib/riak/node/console.rb +139 -0
- data/lib/riak/node/control.rb +207 -0
- data/lib/riak/node/defaults.rb +70 -0
- data/lib/riak/node/generation.rb +99 -0
- data/lib/riak/node/log.rb +34 -0
- data/lib/riak/node/version.rb +37 -0
- data/lib/riak/robject.rb +45 -41
- data/lib/riak/search.rb +2 -161
- data/lib/riak/serializers.rb +74 -0
- data/lib/riak/stamp.rb +77 -0
- data/lib/riak/test_server.rb +56 -220
- data/lib/riak/util/escape.rb +58 -17
- data/lib/riak/util/headers.rb +2 -15
- data/lib/riak/util/multipart.rb +0 -13
- data/lib/riak/util/multipart/stream_parser.rb +0 -13
- data/lib/riak/util/tcp_socket_extensions.rb +1 -14
- data/lib/riak/util/translation.rb +0 -13
- data/lib/riak/version.rb +3 -0
- data/lib/riak/walk_spec.rb +0 -13
- data/riak-client.gemspec +27 -47
- data/spec/fixtures/multipart-with-marked-tombstones.txt +17 -0
- data/spec/fixtures/multipart-with-unmarked-tombstone.txt +16 -0
- data/spec/integration/riak/cache_store_spec.rb +2 -40
- data/spec/integration/riak/cluster_spec.rb +88 -0
- data/spec/integration/riak/http_backends_spec.rb +6 -30
- data/spec/integration/riak/node_spec.rb +184 -0
- data/spec/integration/riak/protobuffs_backends_spec.rb +2 -26
- data/spec/integration/riak/test_server_spec.rb +31 -167
- data/spec/riak/beefcake_protobuffs_backend_spec.rb +5 -4
- data/spec/riak/bucket_spec.rb +26 -36
- data/spec/riak/client_spec.rb +44 -38
- data/spec/riak/escape_spec.rb +56 -30
- data/spec/riak/excon_backend_spec.rb +4 -17
- data/spec/riak/headers_spec.rb +1 -14
- data/spec/riak/http_backend/configuration_spec.rb +211 -34
- data/spec/riak/http_backend/object_methods_spec.rb +52 -18
- data/spec/riak/http_backend/transport_methods_spec.rb +5 -38
- data/spec/riak/http_backend_spec.rb +84 -78
- data/spec/riak/link_spec.rb +19 -18
- data/spec/riak/map_reduce/filter_builder_spec.rb +1 -14
- data/spec/riak/map_reduce/phase_spec.rb +1 -14
- data/spec/riak/map_reduce_spec.rb +141 -43
- data/spec/riak/multipart_spec.rb +1 -14
- data/spec/riak/net_http_backend_spec.rb +2 -15
- data/spec/riak/robject_spec.rb +129 -97
- data/spec/riak/search_spec.rb +45 -62
- data/spec/riak/serializers_spec.rb +93 -0
- data/spec/riak/stamp_spec.rb +54 -0
- data/spec/riak/stream_parser_spec.rb +3 -16
- data/spec/riak/walk_spec_spec.rb +1 -14
- data/spec/spec_helper.rb +22 -27
- data/spec/support/http_backend_implementation_examples.rb +49 -79
- data/spec/support/integration_setup.rb +10 -0
- data/spec/support/mock_server.rb +0 -14
- data/spec/support/mocks.rb +0 -13
- data/spec/support/test_server.rb +30 -0
- data/spec/support/test_server.yml.example +14 -2
- data/spec/support/unified_backend_examples.rb +36 -27
- metadata +100 -31
- data/lib/riak/client/curb_backend.rb +0 -89
- data/spec/riak/curb_backend_spec.rb +0 -76
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'expect'
|
2
|
+
require 'pathname'
|
3
|
+
require 'riak/util/translation'
|
4
|
+
|
5
|
+
if ENV['DEBUG_RIAK_CONSOLE']
|
6
|
+
$expect_verbose = true
|
7
|
+
end
|
8
|
+
|
9
|
+
module Riak
|
10
|
+
class Node
|
11
|
+
# Eases working with the Erlang console when attached to the Riak
|
12
|
+
# node.
|
13
|
+
class Console
|
14
|
+
include Util::Translation
|
15
|
+
|
16
|
+
# @return [String] the name of the connected node
|
17
|
+
attr_accessor :nodename
|
18
|
+
|
19
|
+
# Opens a {Console} by connecting to the node.
|
20
|
+
# @return [Console] the opened console
|
21
|
+
def self.open(node)
|
22
|
+
new node.pipe, node.name
|
23
|
+
end
|
24
|
+
|
25
|
+
# Creates a {Console} from the IO pipes connected to the node.
|
26
|
+
# @param [String,Pathname] pipedir path to the pipes opened by
|
27
|
+
# run_erl
|
28
|
+
# @param [String] nodename the name of the node the Console will
|
29
|
+
# be attached to
|
30
|
+
def initialize(pipedir, nodename)
|
31
|
+
@nodename = nodename
|
32
|
+
@mutex = Mutex.new
|
33
|
+
@winch = Signal.trap("WINCH", &method(:handle_winch))
|
34
|
+
@prompt = /\(#{Regexp.escape(nodename)}\)\d+>\s*/
|
35
|
+
pipedir = Pathname(pipedir)
|
36
|
+
pipedir.children.each do |path|
|
37
|
+
if path.pipe?
|
38
|
+
if path.fnmatch("*.r") # Read pipe
|
39
|
+
# debug "Found read pipe: #{path}"
|
40
|
+
@rfile ||= path
|
41
|
+
elsif path.fnmatch("*.w") # Write pipe
|
42
|
+
# debug "Found write pipe: #{path}"
|
43
|
+
@wfile ||= path
|
44
|
+
end
|
45
|
+
else
|
46
|
+
debug "Non-pipe found! #{path}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
raise ArgumentError, t('no_pipes', :path => pipedir.to_s) if [@rfile, @wfile].any? {|p| p.nil? }
|
50
|
+
# We have to open the read pipe AFTER we have sent some data
|
51
|
+
# to the write pipe, otherwise JRuby hangs.
|
52
|
+
begin
|
53
|
+
debug "Opening write pipe."
|
54
|
+
@w = open_write_pipe
|
55
|
+
@w.sync = true
|
56
|
+
debug "Opening read pipe."
|
57
|
+
@r = open_read_pipe
|
58
|
+
command 'ok.'
|
59
|
+
debug "Initialized console: #{@r.inspect} #{@w.inspect}"
|
60
|
+
rescue => e
|
61
|
+
debug e.message
|
62
|
+
close
|
63
|
+
raise t('no_pipes', :path => pipedir.to_s) + "[ #{e.message} ]"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Sends an Erlang command to the console
|
68
|
+
# @param [String] cmd an Erlang expression to send to the node
|
69
|
+
def command(cmd)
|
70
|
+
@mutex.synchronize do
|
71
|
+
begin
|
72
|
+
debug "Sending command #{cmd.inspect}"
|
73
|
+
@w.print "#{cmd}\n"
|
74
|
+
wait_for_erlang_prompt
|
75
|
+
rescue SystemCallError
|
76
|
+
close
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Detects whether the console connection is still open, that is,
|
82
|
+
# if the node hasn't disconnected from the other side of the
|
83
|
+
# pipe.
|
84
|
+
def open?
|
85
|
+
(@r && !@r.closed?) && (@w && !@w.closed?)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Scans the output of the console until an Erlang shell prompt
|
89
|
+
# is found. Called by {#command} to ensure that the submitted
|
90
|
+
# command succeeds.
|
91
|
+
def wait_for_erlang_prompt
|
92
|
+
wait_for @prompt
|
93
|
+
end
|
94
|
+
|
95
|
+
# Scans the output of the console for the given pattern.
|
96
|
+
# @param [String, Regexp] pattern the pattern to scan for
|
97
|
+
def wait_for(pattern)
|
98
|
+
debug "Scanning for #{pattern.inspect}"
|
99
|
+
@r.expect(pattern)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Closes the console by detaching from the pipes.
|
103
|
+
def close
|
104
|
+
@r.close if @r && !@r.closed?
|
105
|
+
@w.close if @w && !@w.closed?
|
106
|
+
Signal.trap("WINCH", @winch)
|
107
|
+
freeze
|
108
|
+
end
|
109
|
+
|
110
|
+
protected
|
111
|
+
# Handles the "window change" signal by faking it.
|
112
|
+
def handle_winch
|
113
|
+
debug "WINCHED!"
|
114
|
+
@w.print "\033_winsize=80,26\033\\"
|
115
|
+
Signal.trap("WINCH", &method(:handle_winch))
|
116
|
+
end
|
117
|
+
|
118
|
+
def debug(msg)
|
119
|
+
$stderr.puts msg if ENV["DEBUG_RIAK_CONSOLE"]
|
120
|
+
end
|
121
|
+
|
122
|
+
def open_write_pipe
|
123
|
+
if defined?(::Java)
|
124
|
+
java.io.FileOutputStream.new(@wfile.to_s).to_io
|
125
|
+
else
|
126
|
+
@wfile.open(File::WRONLY|File::NONBLOCK)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def open_read_pipe
|
131
|
+
if defined?(::Java)
|
132
|
+
IO.popen("cat #{@rfile}", "rb")
|
133
|
+
else
|
134
|
+
@rfile.open(File::RDONLY|File::NONBLOCK)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'riak/node/console'
|
2
|
+
require 'riak/util/tcp_socket_extensions'
|
3
|
+
|
4
|
+
module Riak
|
5
|
+
class Node
|
6
|
+
# Regexp for parsing riak-admin status output. Takes into account
|
7
|
+
# the minor bug fixed by {https://github.com/basho/riak_kv/pull/134}
|
8
|
+
# and multiline output used when lists of things grow long.
|
9
|
+
STATS_REGEXP = /^([^:\n]+)\s:\s((?:.*)(?:\n\s+[^\n]+)*)/
|
10
|
+
|
11
|
+
# Is the node running?
|
12
|
+
# @return [true, false] If the node is running
|
13
|
+
def started?
|
14
|
+
pinged = ping
|
15
|
+
pinged.strip =~ /pong/ || pinged.strip !~ /Node '[^']+' not responding to pings/
|
16
|
+
end
|
17
|
+
|
18
|
+
# Is the node stopped? (opposite of {#started?}).
|
19
|
+
# @return [true, false] If the node is stopped
|
20
|
+
# @see #started?
|
21
|
+
def stopped?
|
22
|
+
!started?
|
23
|
+
end
|
24
|
+
|
25
|
+
# Starts the node.
|
26
|
+
# @return [String] the output of the 'riak start' command
|
27
|
+
def start
|
28
|
+
res = riak 'start'
|
29
|
+
wait_for_startup
|
30
|
+
res
|
31
|
+
end
|
32
|
+
|
33
|
+
# Stops the node
|
34
|
+
# @return [String] the output of the 'riak stop' command
|
35
|
+
def stop
|
36
|
+
res = riak 'stop'
|
37
|
+
wait_for_shutdown
|
38
|
+
res
|
39
|
+
end
|
40
|
+
|
41
|
+
# Restarts the node
|
42
|
+
# @return [String] the output of the 'riak restart' command
|
43
|
+
def restart
|
44
|
+
riak 'restart'
|
45
|
+
end
|
46
|
+
|
47
|
+
# Reboots the node
|
48
|
+
# @return [String] the output of the 'riak reboot' command
|
49
|
+
def restart
|
50
|
+
riak 'reboot'
|
51
|
+
end
|
52
|
+
|
53
|
+
# Pings the node
|
54
|
+
# @return [String] the output of the 'riak ping' command
|
55
|
+
def ping
|
56
|
+
begin
|
57
|
+
riak 'ping'
|
58
|
+
rescue SystemCallError
|
59
|
+
# If the control script doesn't exist or has the wrong
|
60
|
+
# permissions, we should still return something sane so we can
|
61
|
+
# do the right thing.
|
62
|
+
"Node '#{name}' not responding to pings."
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Attach to the node's console via the pipe.
|
67
|
+
# @return [Riak::Node::Console] A console manager for sending
|
68
|
+
# commands to the Riak node
|
69
|
+
# @see #with_console
|
70
|
+
def attach
|
71
|
+
Console.open self
|
72
|
+
end
|
73
|
+
|
74
|
+
# Execute the block against the Riak node's console.
|
75
|
+
# @yield [console] A block of commands to be run against the console
|
76
|
+
# @yieldparam [Riak::Node::Console] console A console manager for
|
77
|
+
# sending commands to the Riak node
|
78
|
+
def with_console
|
79
|
+
begin
|
80
|
+
console = attach
|
81
|
+
yield console
|
82
|
+
ensure
|
83
|
+
console.close if console
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Joins the node to another node to create a cluster.
|
88
|
+
# @return [String] the output of the 'riak-admin join' command
|
89
|
+
def join(node)
|
90
|
+
node = node.name if Node === node
|
91
|
+
riak_admin 'join', node
|
92
|
+
end
|
93
|
+
|
94
|
+
# Removes this node from its current cluster, handing off all data.
|
95
|
+
# @return [String] the output of the 'riak-admin leave' command
|
96
|
+
def leave
|
97
|
+
riak_admin 'leave'
|
98
|
+
end
|
99
|
+
|
100
|
+
# Forcibly removes a node from the current cluster without
|
101
|
+
# invoking handoff.
|
102
|
+
# @return [String] the output of the 'riak-admin remove <node>'
|
103
|
+
# command
|
104
|
+
def remove(node)
|
105
|
+
node = node.name if Node === node
|
106
|
+
riak_admin 'remove', node
|
107
|
+
end
|
108
|
+
|
109
|
+
# Captures the status of the node.
|
110
|
+
# @return [Hash] a collection of information about the node
|
111
|
+
def status
|
112
|
+
output = riak_admin 'status'
|
113
|
+
if $?.success?
|
114
|
+
result = {}
|
115
|
+
Hash[output.scan(STATS_REGEXP)]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Detects whether the node's cluster has converged on the ring.
|
120
|
+
# @return [true,false] whether the ring is stable
|
121
|
+
def ringready?
|
122
|
+
output = riak_admin 'ringready'
|
123
|
+
output =~ /^TRUE/ || $?.success?
|
124
|
+
end
|
125
|
+
|
126
|
+
# Lists riak_core applications that have registered as available,
|
127
|
+
# e.g. ["riak_kv", "riak_search", "riak_pipe"]
|
128
|
+
# @return [Array<String>] a list of running services
|
129
|
+
def services
|
130
|
+
output = riak_admin 'services'
|
131
|
+
if $?.success?
|
132
|
+
output.strip.match(/^\[(.*)\]$/)[1].split(/,/)
|
133
|
+
else
|
134
|
+
[]
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Forces the node to restart/reload its JavaScript VMs,
|
139
|
+
# effectively reloading any user-provided code.
|
140
|
+
def js_reload
|
141
|
+
riak_admin 'js_reload'
|
142
|
+
end
|
143
|
+
|
144
|
+
# Provides the status of members of the ring.
|
145
|
+
# @return [Hash] a collection of stats about ring members
|
146
|
+
def member_status
|
147
|
+
output = riak_admin 'member_status'
|
148
|
+
result = {}
|
149
|
+
if $?.success?
|
150
|
+
output.each_line do |line|
|
151
|
+
next if line =~ /^(?:[=-]|Status)+/ # Skip the pretty headers
|
152
|
+
if line =~ %r{^Valid:(\d+) / Leaving:(\d+) / Exiting:(\d+) / Joining:(\d+) / Down:(\d+)}
|
153
|
+
result.merge!(:valid => $1.to_i,
|
154
|
+
:leaving => $2.to_i,
|
155
|
+
:exiting => $3.to_i,
|
156
|
+
:joining => $4.to_i,
|
157
|
+
:down => $5.to_i)
|
158
|
+
else
|
159
|
+
result[:members] ||= {}
|
160
|
+
status, ring, pending, node = line.split(/\s+/)
|
161
|
+
node = $1 if node =~ /^'(.*)'$/
|
162
|
+
ring = $1.to_f if ring =~ /(\d+\.\d+)%/
|
163
|
+
result[:members][node] = {
|
164
|
+
:status => status,
|
165
|
+
:ring => ring,
|
166
|
+
:pending => (pending == '--') ? 0 : pending.to_i
|
167
|
+
}
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
result
|
172
|
+
end
|
173
|
+
|
174
|
+
# @return [Array<String>] a list of node names that are also
|
175
|
+
# members of this node's cluster, and empty list if the
|
176
|
+
# {#member_status} fails or no other nodes are present
|
177
|
+
def peers
|
178
|
+
all_nodes = member_status[:members] && member_status[:members].keys.reject {|n| n == name }
|
179
|
+
all_nodes || []
|
180
|
+
end
|
181
|
+
|
182
|
+
protected
|
183
|
+
# Runs a command using the 'riak' control script.
|
184
|
+
def riak(*commands)
|
185
|
+
`#{control_script} #{commands.join(' ')} 2>&1`
|
186
|
+
end
|
187
|
+
|
188
|
+
# Runs a command using the 'riak-admin' script.
|
189
|
+
def riak_admin(*commands)
|
190
|
+
`#{admin_script} #{commands.join(' ')} 2>&1`
|
191
|
+
end
|
192
|
+
|
193
|
+
# Waits for the HTTP port to become available, which is a better
|
194
|
+
# indication of readiness than the start script finishing.
|
195
|
+
def wait_for_startup
|
196
|
+
TCPSocket.wait_for_service_with_timeout(:host => http_ip,
|
197
|
+
:port => http_port,
|
198
|
+
:timeout => 10)
|
199
|
+
end
|
200
|
+
|
201
|
+
def wait_for_shutdown
|
202
|
+
TCPSocket.wait_for_service_termination_with_timeout(:host => http_ip,
|
203
|
+
:port => http_port,
|
204
|
+
:timeout => 10)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'riak/core_ext/deep_dup'
|
2
|
+
|
3
|
+
module Riak
|
4
|
+
class Node
|
5
|
+
# Settings based on Riak master/1.0.
|
6
|
+
ENV_DEFAULTS = {
|
7
|
+
:riak_core => {
|
8
|
+
:ring_creation_size => 64
|
9
|
+
},
|
10
|
+
:riak_kv => {
|
11
|
+
:storage_backend => :riak_kv_bitcask_backend,
|
12
|
+
:map_js_vm_count => 8,
|
13
|
+
:reduce_js_vm_count => 6,
|
14
|
+
:hook_js_vm_count => 2,
|
15
|
+
:mapper_batch_size => 5,
|
16
|
+
:js_max_vm_mem => 8,
|
17
|
+
:js_thread_stack => 16,
|
18
|
+
:riak_kv_stat => true,
|
19
|
+
:legacy_stats => false,
|
20
|
+
:vnode_vclocks => true,
|
21
|
+
:http_url_encoding => :on,
|
22
|
+
:legacy_keylisting => false,
|
23
|
+
:mapred_system => :pipe,
|
24
|
+
:add_paths => []
|
25
|
+
},
|
26
|
+
:riak_search => {
|
27
|
+
:enabled => true
|
28
|
+
},
|
29
|
+
:luwak => {
|
30
|
+
:enabled => true
|
31
|
+
},
|
32
|
+
:merge_index => {
|
33
|
+
:buffer_rollover_size => 1048576,
|
34
|
+
:max_compact_segments => 20
|
35
|
+
},
|
36
|
+
:eleveldb => {},
|
37
|
+
:bitcask => {},
|
38
|
+
:lager => {
|
39
|
+
:crash_log_size => 65536,
|
40
|
+
:error_logger_redirect => true
|
41
|
+
},
|
42
|
+
:riak_sysmon => {
|
43
|
+
:process_limit => 30,
|
44
|
+
:port_limit => 30,
|
45
|
+
:gc_ms_limit => 50,
|
46
|
+
:heap_word_limit => 10485760
|
47
|
+
},
|
48
|
+
:sasl => {
|
49
|
+
:sasl_error_logger => false
|
50
|
+
}
|
51
|
+
}.freeze
|
52
|
+
|
53
|
+
# Based on Riak master/1.0.
|
54
|
+
VM_DEFAULTS = {
|
55
|
+
"+K" => true,
|
56
|
+
"+A" => 64,
|
57
|
+
"-smp" => "enable",
|
58
|
+
"+W" => "w",
|
59
|
+
"-env ERL_MAX_PORTS" => 4096,
|
60
|
+
"-env ERL_FULLSWEEP_AFTER" => 0
|
61
|
+
}.freeze
|
62
|
+
|
63
|
+
protected
|
64
|
+
# Populates the defaults
|
65
|
+
def set_defaults
|
66
|
+
@env = ENV_DEFAULTS.deep_dup
|
67
|
+
@vm = VM_DEFAULTS.deep_dup
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Riak
|
4
|
+
class Node
|
5
|
+
# Does the node exist on disk?
|
6
|
+
def exist?
|
7
|
+
manifest.exist?
|
8
|
+
end
|
9
|
+
|
10
|
+
# Deletes the node and regenerates it.
|
11
|
+
def recreate
|
12
|
+
delete
|
13
|
+
create
|
14
|
+
end
|
15
|
+
|
16
|
+
# Generates the node.
|
17
|
+
def create
|
18
|
+
unless exist?
|
19
|
+
create_directories
|
20
|
+
write_scripts
|
21
|
+
write_vm_args
|
22
|
+
write_app_config
|
23
|
+
write_manifest
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Clears data from known data directories. Stops the node if it is
|
28
|
+
# running.
|
29
|
+
def drop
|
30
|
+
was_started = started?
|
31
|
+
stop if was_started
|
32
|
+
data.children.each {|dir| dir.children.each {|c| c.rmtree } }
|
33
|
+
start if was_started
|
34
|
+
end
|
35
|
+
|
36
|
+
# Removes the node from disk and freezes the object.
|
37
|
+
def destroy
|
38
|
+
delete
|
39
|
+
freeze
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
def delete
|
44
|
+
stop unless stopped?
|
45
|
+
root.rmtree if root.exist?
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_directories
|
49
|
+
root.mkpath
|
50
|
+
NODE_DIRECTORIES.each {|d| send(d).mkpath }
|
51
|
+
end
|
52
|
+
|
53
|
+
def write_vm_args
|
54
|
+
(etc + 'vm.args').open('w') do |f|
|
55
|
+
vm.each do |k,v|
|
56
|
+
f.puts "#{k} #{v}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def write_app_config
|
62
|
+
(etc + 'app.config').open('w') do |f|
|
63
|
+
f.write to_erlang_config(env) + '.'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def write_scripts
|
68
|
+
[control_script, admin_script].each {|s| write_script(s.basename, s) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def write_script(name, target)
|
72
|
+
source_script = source + name
|
73
|
+
target.open('wb') do |f|
|
74
|
+
source_script.readlines.each do |line|
|
75
|
+
line.sub!(/(RUNNER_SCRIPT_DIR=)(.*)/, '\1' + bin.to_s)
|
76
|
+
line.sub!(/(RUNNER_ETC_DIR=)(.*)/, '\1' + etc.to_s)
|
77
|
+
line.sub!(/(RUNNER_USER=)(.*)/, '\1')
|
78
|
+
line.sub!(/(RUNNER_LOG_DIR=)(.*)/, '\1' + log.to_s)
|
79
|
+
line.sub!(/(PIPE_DIR=)(.*)/, '\1' + pipe.to_s)
|
80
|
+
line.sub!('grep "$RUNNER_BASE_DIR/.*/[b]eam"', 'grep "$RUNNER_ETC_DIR/app.config"')
|
81
|
+
if line.strip == "RUNNER_BASE_DIR=${RUNNER_SCRIPT_DIR%/*}"
|
82
|
+
line = "RUNNER_BASE_DIR=#{source.parent.to_s}\n"
|
83
|
+
end
|
84
|
+
f.write line
|
85
|
+
end
|
86
|
+
end
|
87
|
+
target.chmod 0755
|
88
|
+
end
|
89
|
+
|
90
|
+
def write_manifest
|
91
|
+
# TODO: For now this only saves the information that was used when
|
92
|
+
# configuring the node. Later we'll verify/warn if the settings
|
93
|
+
# used differ on subsequent generations.
|
94
|
+
@configuration[:env] = @env
|
95
|
+
@configuration[:vm] = @vm
|
96
|
+
manifest.open('w') {|f| YAML.dump(@configuration, f) }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|