vines-services 0.1.0
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/LICENSE +19 -0
- data/README +40 -0
- data/Rakefile +130 -0
- data/bin/vines-services +95 -0
- data/conf/config.rb +25 -0
- data/lib/vines/services/command/init.rb +209 -0
- data/lib/vines/services/command/restart.rb +14 -0
- data/lib/vines/services/command/start.rb +30 -0
- data/lib/vines/services/command/stop.rb +20 -0
- data/lib/vines/services/command/views.rb +26 -0
- data/lib/vines/services/component.rb +26 -0
- data/lib/vines/services/config.rb +105 -0
- data/lib/vines/services/connection.rb +120 -0
- data/lib/vines/services/controller/attributes_controller.rb +19 -0
- data/lib/vines/services/controller/base_controller.rb +99 -0
- data/lib/vines/services/controller/disco_info_controller.rb +61 -0
- data/lib/vines/services/controller/labels_controller.rb +17 -0
- data/lib/vines/services/controller/members_controller.rb +44 -0
- data/lib/vines/services/controller/messages_controller.rb +66 -0
- data/lib/vines/services/controller/probes_controller.rb +45 -0
- data/lib/vines/services/controller/services_controller.rb +81 -0
- data/lib/vines/services/controller/subscriptions_controller.rb +39 -0
- data/lib/vines/services/controller/systems_controller.rb +45 -0
- data/lib/vines/services/controller/transfers_controller.rb +58 -0
- data/lib/vines/services/controller/uploads_controller.rb +62 -0
- data/lib/vines/services/controller/users_controller.rb +127 -0
- data/lib/vines/services/core_ext/blather.rb +46 -0
- data/lib/vines/services/core_ext/couchrest.rb +33 -0
- data/lib/vines/services/indexer.rb +195 -0
- data/lib/vines/services/priority_queue.rb +94 -0
- data/lib/vines/services/roster.rb +70 -0
- data/lib/vines/services/storage/couchdb/fragment.rb +23 -0
- data/lib/vines/services/storage/couchdb/service.rb +170 -0
- data/lib/vines/services/storage/couchdb/system.rb +141 -0
- data/lib/vines/services/storage/couchdb/upload.rb +66 -0
- data/lib/vines/services/storage/couchdb/user.rb +137 -0
- data/lib/vines/services/storage/couchdb/vcard.rb +13 -0
- data/lib/vines/services/storage/couchdb.rb +157 -0
- data/lib/vines/services/storage.rb +33 -0
- data/lib/vines/services/throttle.rb +26 -0
- data/lib/vines/services/version.rb +7 -0
- data/lib/vines/services/vql/compiler.rb +94 -0
- data/lib/vines/services/vql/vql.citrus +115 -0
- data/lib/vines/services/vql/vql.rb +186 -0
- data/lib/vines/services.rb +71 -0
- data/test/config_test.rb +242 -0
- data/test/priority_queue_test.rb +23 -0
- data/test/storage/couchdb_test.rb +30 -0
- data/test/vql/compiler_test.rb +96 -0
- data/test/vql/vql_test.rb +233 -0
- data/web/coffeescripts/api.coffee +51 -0
- data/web/coffeescripts/commands.coffee +18 -0
- data/web/coffeescripts/files.coffee +315 -0
- data/web/coffeescripts/init.coffee +21 -0
- data/web/coffeescripts/services.coffee +356 -0
- data/web/coffeescripts/setup.coffee +503 -0
- data/web/coffeescripts/systems.coffee +371 -0
- data/web/images/default-service.png +0 -0
- data/web/images/linux.png +0 -0
- data/web/images/mac.png +0 -0
- data/web/images/run.png +0 -0
- data/web/images/windows.png +0 -0
- data/web/index.html +17 -0
- data/web/stylesheets/common.css +52 -0
- data/web/stylesheets/files.css +218 -0
- data/web/stylesheets/services.css +181 -0
- data/web/stylesheets/setup.css +117 -0
- data/web/stylesheets/systems.css +142 -0
- metadata +230 -0
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010-2011 Negative Code
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
== Welcome to Vines Services
|
2
|
+
|
3
|
+
Vines Services are dynamically updated groups of systems based on criteria like
|
4
|
+
hostname, installed software, operating system, etc. Send a command to the
|
5
|
+
service and it runs on every system in the group. Services, files and permissions
|
6
|
+
are managed via the bundled web application.
|
7
|
+
|
8
|
+
Services are defined using VinesQL, a simple query language that finds systems
|
9
|
+
based on their machine attributes. A "Mac OS X Lion" service might be
|
10
|
+
defined as: platform is 'mac_os_x' and platform_version starts with '10.7'.
|
11
|
+
As machines update to Lion, they will join this service automatically and may
|
12
|
+
be managed as one group.
|
13
|
+
|
14
|
+
== Usage
|
15
|
+
|
16
|
+
1. gem install vines-services
|
17
|
+
2. vines-services init wonderland.lit
|
18
|
+
3. cd wonderland.lit && vines-services start
|
19
|
+
|
20
|
+
== Dependencies
|
21
|
+
|
22
|
+
* bcrypt-ruby >= 3.0.0
|
23
|
+
* blather >= 0.5.4
|
24
|
+
* citrus >= 2.4.0
|
25
|
+
* eventmachine >= 0.12.10
|
26
|
+
* nokogiri >= 1.4.4
|
27
|
+
* sqlite3 >= 1.3.4
|
28
|
+
* ruby >= 1.9.2
|
29
|
+
|
30
|
+
== Ubuntu setup
|
31
|
+
$ sudo apt-get install build-essential ruby1.9.1 ruby1.9.1-dev libxml2-dev libxslt-dev
|
32
|
+
|
33
|
+
== Contact
|
34
|
+
|
35
|
+
* David Graham <david@negativecode.com>
|
36
|
+
* Chris Johnson <chris@negativecode.com>
|
37
|
+
|
38
|
+
== License
|
39
|
+
|
40
|
+
Vines Services is released under the MIT license. Check the LICENSE file for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rubygems/package_task'
|
5
|
+
require 'nokogiri'
|
6
|
+
require_relative 'lib/vines/services/version'
|
7
|
+
|
8
|
+
spec = Gem::Specification.new do |s|
|
9
|
+
s.name = "vines-services"
|
10
|
+
s.version = Vines::Services::VERSION
|
11
|
+
s.date = Time.now.strftime("%Y-%m-%d")
|
12
|
+
|
13
|
+
s.summary = "An XMPP component that broadcasts shell commands to many agents."
|
14
|
+
s.description = "Vines Services are dynamically updated groups of systems based
|
15
|
+
on criteria like hostname, installed software, operating system, etc. Send a
|
16
|
+
command to the service and it runs on every system in the group. Services, files
|
17
|
+
and permissions are managed via the bundled web application."
|
18
|
+
|
19
|
+
s.authors = ["David Graham", "Chris Johnson"]
|
20
|
+
s.email = %w[david@negativecode.com chris@negativecode.com]
|
21
|
+
s.homepage = "http://www.getvines.com"
|
22
|
+
|
23
|
+
s.files = FileList['[A-Z]*', '{bin,lib,conf,web}/**/*']
|
24
|
+
s.test_files = FileList["test/**/*"]
|
25
|
+
s.executables = %w[vines-services]
|
26
|
+
s.require_path = "lib"
|
27
|
+
|
28
|
+
s.add_dependency "bcrypt-ruby", "~> 3.0.0"
|
29
|
+
s.add_dependency "blather", "~> 0.5.4"
|
30
|
+
s.add_dependency "citrus", "~> 2.4.0"
|
31
|
+
s.add_dependency "couchrest_model", "~> 1.1.2"
|
32
|
+
s.add_dependency "em-http-request", "~> 0.3.0"
|
33
|
+
s.add_dependency "sqlite3", "~> 1.3.4"
|
34
|
+
s.add_dependency "vines", "~> 0.3"
|
35
|
+
|
36
|
+
s.add_development_dependency "minitest"
|
37
|
+
s.add_development_dependency "rake"
|
38
|
+
|
39
|
+
s.required_ruby_version = '>= 1.9.2'
|
40
|
+
end
|
41
|
+
|
42
|
+
Gem::PackageTask.new(spec) do |pkg|
|
43
|
+
pkg.need_tar = true
|
44
|
+
end
|
45
|
+
|
46
|
+
Rake::TestTask.new(:test) do |test|
|
47
|
+
test.libs << 'test'
|
48
|
+
test.pattern = 'test/**/*_test.rb'
|
49
|
+
test.warning = false
|
50
|
+
end
|
51
|
+
|
52
|
+
# Return an array of local, non-library, js includes.
|
53
|
+
def scripts(doc)
|
54
|
+
scripts = []
|
55
|
+
doc.css('script').each do |node|
|
56
|
+
file = node['src'].split('/').last()
|
57
|
+
if node['src'].start_with?('javascripts/')
|
58
|
+
scripts << file
|
59
|
+
end
|
60
|
+
end
|
61
|
+
scripts
|
62
|
+
end
|
63
|
+
|
64
|
+
# Replace script tags with combined and minimized files.
|
65
|
+
def rewrite_js(doc)
|
66
|
+
doc.css('script').each {|node| node.remove }
|
67
|
+
doc.css('head').each do |node|
|
68
|
+
%w[/lib/javascripts/base.js javascripts/app.js].each do |src|
|
69
|
+
script = doc.create_element('script',
|
70
|
+
'type' => 'text/javascript',
|
71
|
+
'src' => src)
|
72
|
+
node.add_child(script)
|
73
|
+
node.add_child(doc.create_text_node("\n"))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def stylesheets(doc)
|
79
|
+
sheets = []
|
80
|
+
doc.css('link[rel="stylesheet"]').each do |node|
|
81
|
+
file = node['href'].split('/').last()
|
82
|
+
if node['href'].start_with?('stylesheets/')
|
83
|
+
sheets << file
|
84
|
+
end
|
85
|
+
end
|
86
|
+
sheets
|
87
|
+
end
|
88
|
+
|
89
|
+
def rewrite_css(doc)
|
90
|
+
doc.css('link[rel="stylesheet"]').each {|node| node.remove }
|
91
|
+
doc.css('head').each do |node|
|
92
|
+
%w[/lib/stylesheets/base.css /lib/stylesheets/login.css stylesheets/app.css].each do |file|
|
93
|
+
link = doc.create_element('link',
|
94
|
+
'rel' => 'stylesheet',
|
95
|
+
'href' => file)
|
96
|
+
node.add_child(link)
|
97
|
+
node.add_child(doc.create_text_node("\n"))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
task :compile do
|
103
|
+
index = 'web/index.html'
|
104
|
+
doc = Nokogiri::HTML(File.read(index))
|
105
|
+
scripts, sheets = scripts(doc), stylesheets(doc)
|
106
|
+
|
107
|
+
rewrite_js(doc)
|
108
|
+
rewrite_css(doc)
|
109
|
+
|
110
|
+
# save index.html before rewriting
|
111
|
+
FileUtils.cp(index, '/tmp/index.html')
|
112
|
+
File.open(index, 'w') {|f| f.write(doc.to_xml(:indent => 2)) }
|
113
|
+
|
114
|
+
js_files = scripts.map {|f| "web/javascripts/#{f}"}.join(' ')
|
115
|
+
css_files = sheets.map {|f| "web/stylesheets/#{f}"}.join(' ')
|
116
|
+
|
117
|
+
sh %{coffee -c -b -o web/javascripts web/coffeescripts/*.coffee}
|
118
|
+
sh %{cat #{js_files} | uglifyjs -nc > web/javascripts/app.js}
|
119
|
+
|
120
|
+
sh %{cat #{css_files} > web/stylesheets/app.css}
|
121
|
+
end
|
122
|
+
|
123
|
+
task :cleanup do
|
124
|
+
# move index.html back into place after gem packaging
|
125
|
+
FileUtils.cp('/tmp/index.html', 'web/index.html')
|
126
|
+
File.delete('/tmp/index.html')
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
task :default => [:clobber, :test, :compile, :gem, :cleanup]
|
data/bin/vines-services
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
require 'vines/services'
|
6
|
+
|
7
|
+
COMMANDS = %w[start stop restart init views]
|
8
|
+
|
9
|
+
def parse(args)
|
10
|
+
options = {}
|
11
|
+
parser = OptionParser.new do |opts|
|
12
|
+
opts.banner = "Usage: vines-services [options] #{COMMANDS.join('|')}"
|
13
|
+
|
14
|
+
opts.separator ""
|
15
|
+
opts.separator "Daemon options:"
|
16
|
+
|
17
|
+
opts.on('-d', '--daemonize', 'Run daemonized in the background') do |daemonize|
|
18
|
+
options[:daemonize] = daemonize
|
19
|
+
end
|
20
|
+
|
21
|
+
options[:log] = 'log/vines-services.log'
|
22
|
+
opts.on('-l', '--log FILE', 'File to redirect output (default: log/vines-services.log)') do |log|
|
23
|
+
options[:log] = log
|
24
|
+
end
|
25
|
+
|
26
|
+
options[:pid] = 'pid/vines-services.pid'
|
27
|
+
opts.on('-P', '--pid FILE', 'File to store PID (default: pid/vines-services.pid)') do |pid|
|
28
|
+
options[:pid] = pid
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.separator ""
|
32
|
+
opts.separator "Common options:"
|
33
|
+
|
34
|
+
opts.on('-h', '--help', 'Show this message') do |help|
|
35
|
+
options[:help] = help
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on('-v', '--version', 'Show version') do |version|
|
39
|
+
options[:version] = version
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
begin
|
44
|
+
parser.parse!(args)
|
45
|
+
rescue
|
46
|
+
puts parser
|
47
|
+
exit(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
if options[:version]
|
51
|
+
puts Vines::Services::VERSION
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
|
55
|
+
if options[:help]
|
56
|
+
puts parser
|
57
|
+
exit
|
58
|
+
end
|
59
|
+
|
60
|
+
command = args.shift
|
61
|
+
unless COMMANDS.include?(command)
|
62
|
+
puts parser
|
63
|
+
exit(1)
|
64
|
+
end
|
65
|
+
|
66
|
+
options.tap do |opts|
|
67
|
+
opts[:args] = args
|
68
|
+
opts[:command] = command
|
69
|
+
opts[:config] = File.expand_path('conf/config.rb')
|
70
|
+
opts[:pid] = File.expand_path(opts[:pid])
|
71
|
+
opts[:log] = File.expand_path(opts[:log])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def check_config(opts)
|
76
|
+
return if %w[init].include?(opts[:command])
|
77
|
+
unless File.exists?(opts[:config])
|
78
|
+
puts "No config file found at #{opts[:config]}"
|
79
|
+
exit(1)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
VINES_ROOT = Dir.pwd
|
84
|
+
opts = parse(ARGV)
|
85
|
+
check_config(opts)
|
86
|
+
command = Vines::Services::Command.const_get(opts[:command].capitalize).new
|
87
|
+
begin
|
88
|
+
command.run(opts)
|
89
|
+
rescue SystemExit
|
90
|
+
# do nothing
|
91
|
+
rescue Exception => e
|
92
|
+
puts e.message
|
93
|
+
puts e.backtrace
|
94
|
+
exit(1)
|
95
|
+
end
|
data/conf/config.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# This is the Vines Services configuration file. Restart the service with
|
4
|
+
# 'vines-services restart' after updating this file.
|
5
|
+
|
6
|
+
Vines::Services::Config.configure do
|
7
|
+
# Set the logging level to debug, info, warn, error, or fatal. The debug
|
8
|
+
# level logs all XML sent and received by the server.
|
9
|
+
log :info
|
10
|
+
|
11
|
+
host 'vines.wonderland.lit' do
|
12
|
+
upstream 'localhost', 5347, 'secr3t'
|
13
|
+
uploads 'data/upload'
|
14
|
+
|
15
|
+
storage 'couchdb' do
|
16
|
+
host 'localhost'
|
17
|
+
port 5984
|
18
|
+
database 'xmpp'
|
19
|
+
tls false
|
20
|
+
username ''
|
21
|
+
password ''
|
22
|
+
index_dir 'data/index'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Vines
|
4
|
+
module Services
|
5
|
+
module Command
|
6
|
+
class Init
|
7
|
+
def run(opts)
|
8
|
+
raise 'vines-services init [domain]' unless opts[:args].size == 1
|
9
|
+
@domain = opts[:args].first.dup
|
10
|
+
dir = File.expand_path(@domain)
|
11
|
+
@component_password = Kit.generate_password
|
12
|
+
create_directories
|
13
|
+
initialize_server
|
14
|
+
initialize_component
|
15
|
+
initialize_agent
|
16
|
+
puts "Initialized service, agent, and server directories: #{@domain}"
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def initialize_server
|
22
|
+
Dir.chdir(File.join(@domain, "server"))
|
23
|
+
`vines init #{@domain}`
|
24
|
+
configure_database
|
25
|
+
FileUtils.mv Dir.glob("#{@domain}/*"), "./"
|
26
|
+
FileUtils.remove_dir(@domain)
|
27
|
+
`vines start -d`
|
28
|
+
FileUtils.cp_r(File.expand_path("../../../../../web/index.html", __FILE__), File.join("web", "index.html"))
|
29
|
+
FileUtils.cp_r(File.expand_path("../../../../../web/javascripts", __FILE__), File.join("web", "javascripts"))
|
30
|
+
FileUtils.cp_r(File.expand_path("../../../../../web/stylesheets", __FILE__), File.join("web", "stylesheets"))
|
31
|
+
FileUtils.cp_r(File.expand_path("../../../../../web/images", __FILE__), File.join("web", "images"))
|
32
|
+
FileUtils.cp_r(File.expand_path("../../../../../web/coffeescripts", __FILE__), File.join("web", "coffeescripts"))
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize_agent
|
36
|
+
Dir.chdir("../agent/")
|
37
|
+
`vines-agent init #{@domain}`
|
38
|
+
FileUtils.cp("../server/conf/certs/#{@domain}.crt", File.join("#{@domain}", "conf", "certs"))
|
39
|
+
agent_password = Kit.generate_password
|
40
|
+
jid = Vines::JID.new(fqdn, @domain).bare
|
41
|
+
id = "user:#{jid}"
|
42
|
+
Fiber.new do
|
43
|
+
user = Vines::Services::CouchModels::User.new(id: id)
|
44
|
+
user.name = jid
|
45
|
+
user.system = true
|
46
|
+
user.password = agent_password
|
47
|
+
if user.valid?
|
48
|
+
user.save
|
49
|
+
log.debug("Saving user: #{user}")
|
50
|
+
end
|
51
|
+
end.resume
|
52
|
+
update_agent_config(File.join("#{@domain}", "conf", "config.rb"), agent_password)
|
53
|
+
FileUtils.mv Dir.glob("#{@domain}/*"), "./"
|
54
|
+
FileUtils.remove_dir(@domain)
|
55
|
+
`vines-agent start -d`
|
56
|
+
end
|
57
|
+
|
58
|
+
# Coordinate all the configuration required for the service
|
59
|
+
def initialize_component
|
60
|
+
Dir.chdir("../services/")
|
61
|
+
%w[conf].each do |sub|
|
62
|
+
FileUtils.cp_r(File.expand_path("../../../../../#{sub}", __FILE__), File.join("."))
|
63
|
+
end
|
64
|
+
log, pid = %w[log pid data data/index].map do |sub|
|
65
|
+
File.join(sub).tap {|subdir| Dir.mkdir(subdir) }
|
66
|
+
end
|
67
|
+
update_config(File.join("conf", "config.rb"))
|
68
|
+
`vines-services start -d`
|
69
|
+
end
|
70
|
+
|
71
|
+
#create all the directories for the server, agent, and service
|
72
|
+
def create_directories
|
73
|
+
Dir.mkdir(@domain)
|
74
|
+
%w[server services agent].each do |sub|
|
75
|
+
Dir.mkdir(File.join(@domain, sub))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def create_db(host, port, db)
|
80
|
+
url = "http://#{host}:#{port}/#{db}"
|
81
|
+
begin
|
82
|
+
RestClient.head(url)
|
83
|
+
rescue RestClient::ResourceNotFound
|
84
|
+
RestClient.put(url, nil)
|
85
|
+
end
|
86
|
+
true
|
87
|
+
rescue
|
88
|
+
false
|
89
|
+
end
|
90
|
+
|
91
|
+
# This will attempt to create a new couch database. If one exists
|
92
|
+
# by the name generated, it will not be deleted. This will loop until
|
93
|
+
# it gets a valid couch db address and port
|
94
|
+
def configure_database
|
95
|
+
server, port = "127.0.0.1", 5984
|
96
|
+
db_name = @domain.gsub(".", "_").downcase()
|
97
|
+
until create_db(server, port, db_name)
|
98
|
+
puts "Unable to connect."
|
99
|
+
$stdout.write('CouchDB Server: ')
|
100
|
+
server = $stdin.gets.chomp
|
101
|
+
$stdout.write('CouchDB Port: ')
|
102
|
+
port = $stdin.gets.chomp
|
103
|
+
end
|
104
|
+
@couch_server = server
|
105
|
+
@couch_port = port
|
106
|
+
@couch_db = db_name
|
107
|
+
update_config(File.join(@domain, "conf", "config.rb"))
|
108
|
+
@storage = Vines::Services::Storage::CouchDB.new do
|
109
|
+
host server
|
110
|
+
port port
|
111
|
+
database db_name
|
112
|
+
index_dir '.'
|
113
|
+
end
|
114
|
+
create_user
|
115
|
+
end
|
116
|
+
|
117
|
+
#Create a new vines user object in the couch database
|
118
|
+
def create_user
|
119
|
+
jid, password = nil, nil
|
120
|
+
until jid
|
121
|
+
$stdout.write('JID: ')
|
122
|
+
if node = $stdin.gets.chomp.split('@').first
|
123
|
+
jid = Vines::JID.new(node, @domain) rescue nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
until password
|
128
|
+
$stdout.write('Password: ')
|
129
|
+
`stty -echo`
|
130
|
+
password = $stdin.gets.chomp
|
131
|
+
password = nil if password.empty?
|
132
|
+
`stty echo`
|
133
|
+
end
|
134
|
+
puts "\nCreated #{jid}"
|
135
|
+
|
136
|
+
id = "user:#{jid}"
|
137
|
+
Fiber.new do
|
138
|
+
user = Vines::Services::CouchModels::User.new(id: id)
|
139
|
+
user.name = jid
|
140
|
+
user.password = password
|
141
|
+
if user.valid?
|
142
|
+
user.save
|
143
|
+
log.debug("\nSaving user: #{user}")
|
144
|
+
end
|
145
|
+
end.resume
|
146
|
+
end
|
147
|
+
|
148
|
+
# Set the agents password to the one we generated in this initialization
|
149
|
+
def update_agent_config(config, password)
|
150
|
+
text = File.read(config)
|
151
|
+
File.open(config, 'w') do |f|
|
152
|
+
f.write(text.gsub(/password.*/, "password '#{password}'"))
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Return the fully qualified domain name for this machine. This is used
|
157
|
+
# to determine the agent's JID.
|
158
|
+
def fqdn
|
159
|
+
require 'ohai'
|
160
|
+
system = Ohai::System.new
|
161
|
+
system.require_plugin('os')
|
162
|
+
system.require_plugin('hostname')
|
163
|
+
system.fqdn.downcase
|
164
|
+
end
|
165
|
+
|
166
|
+
# Change the config file to contain the values we generated or validated.
|
167
|
+
def update_config(config)
|
168
|
+
# FIXME vines.local
|
169
|
+
orig_config = """
|
170
|
+
host 'vines.local' do
|
171
|
+
cross_domain_messages false
|
172
|
+
private_storage false
|
173
|
+
storage 'fs' do
|
174
|
+
dir 'data/users'
|
175
|
+
end
|
176
|
+
# components 'tea' => 'secr3t',
|
177
|
+
# 'cake' => 'passw0rd'
|
178
|
+
end"""
|
179
|
+
new_config = """
|
180
|
+
host '#{@domain}' do
|
181
|
+
cross_domain_messages false
|
182
|
+
private_storage true
|
183
|
+
storage 'couchdb' do
|
184
|
+
host '#{@couch_server}'
|
185
|
+
port #{@couch_port}
|
186
|
+
database '#{@couch_db}'
|
187
|
+
tls false
|
188
|
+
username ''
|
189
|
+
password ''
|
190
|
+
end
|
191
|
+
components 'vines' => '#{@component_password}'
|
192
|
+
end"""
|
193
|
+
text = File.read(config)
|
194
|
+
text = text.gsub(orig_config, new_config)
|
195
|
+
text = text.gsub("host 'vines.wonderland.lit'", "host 'vines.#{@domain}'")
|
196
|
+
text = text.gsub("secr3t", "#{@component_password}")
|
197
|
+
text = text.gsub("host 'localhost'", "host '#{@couch_server}'")
|
198
|
+
text = text.gsub("port 5984", "port #{@couch_port}")
|
199
|
+
text = text.gsub("database 'xmpp'", "database '#{@couch_db}'")
|
200
|
+
File.open(config, 'w') do |f|
|
201
|
+
f.write(text)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Vines
|
4
|
+
module Services
|
5
|
+
module Command
|
6
|
+
class Start
|
7
|
+
def run(opts)
|
8
|
+
raise 'vines-services [--pid FILE] start' unless opts[:args].size == 0
|
9
|
+
require opts[:config]
|
10
|
+
component = Vines::Services::Component.new(Config.instance)
|
11
|
+
daemonize(opts) if opts[:daemonize]
|
12
|
+
component.start
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def daemonize(opts)
|
18
|
+
daemon = Vines::Daemon.new(:pid => opts[:pid], :stdout => opts[:log],
|
19
|
+
:stderr => opts[:log])
|
20
|
+
if daemon.running?
|
21
|
+
raise "The vines service is running as process #{daemon.pid}"
|
22
|
+
else
|
23
|
+
puts "The vines service has started"
|
24
|
+
daemon.start
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Vines
|
4
|
+
module Services
|
5
|
+
module Command
|
6
|
+
class Stop
|
7
|
+
def run(opts)
|
8
|
+
raise 'vines-services [--pid FILE] stop' unless opts[:args].size == 0
|
9
|
+
daemon = Vines::Daemon.new(:pid => opts[:pid])
|
10
|
+
if daemon.running?
|
11
|
+
daemon.stop
|
12
|
+
puts 'The vines service has been shutdown'
|
13
|
+
else
|
14
|
+
puts 'The vines service is not running'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Vines
|
4
|
+
module Services
|
5
|
+
module Command
|
6
|
+
class Views
|
7
|
+
def run(opts)
|
8
|
+
raise 'vines-services views <domain>' unless opts[:args].size == 1
|
9
|
+
require opts[:config]
|
10
|
+
domain = opts[:args].first
|
11
|
+
unless host = Config.instance.vhosts[domain]
|
12
|
+
raise "#{domain} virtual host not found in conf/config.rb"
|
13
|
+
end
|
14
|
+
unless host.storage.respond_to?(:create_views)
|
15
|
+
raise "CouchDB storage not configured for #{domain} virtual host"
|
16
|
+
end
|
17
|
+
begin
|
18
|
+
host.storage.create_views
|
19
|
+
rescue Exception => e
|
20
|
+
raise "View creation failed: #{e.message}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Vines
|
4
|
+
module Services
|
5
|
+
# The main starting point for the Vines Services component process. Starts
|
6
|
+
# the EventMachine processing loop and registers the component with the
|
7
|
+
# configured upstream servers.
|
8
|
+
class Component
|
9
|
+
include Vines::Log
|
10
|
+
|
11
|
+
def initialize(config)
|
12
|
+
@config = config
|
13
|
+
end
|
14
|
+
|
15
|
+
def start
|
16
|
+
log.info('Vines component started')
|
17
|
+
at_exit { log.fatal('Vines component stopped') }
|
18
|
+
EM.epoll
|
19
|
+
EM.kqueue
|
20
|
+
EM.run do
|
21
|
+
@config.hosts.each {|host| host.start }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|