choria-mcorpc-support 0.0.1
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.
- checksums.yaml +7 -0
- data/bin/mco +64 -0
- data/lib/mcollective.rb +63 -0
- data/lib/mcollective/agent.rb +5 -0
- data/lib/mcollective/agents.rb +149 -0
- data/lib/mcollective/aggregate.rb +85 -0
- data/lib/mcollective/aggregate/average.ddl +33 -0
- data/lib/mcollective/aggregate/average.rb +29 -0
- data/lib/mcollective/aggregate/base.rb +40 -0
- data/lib/mcollective/aggregate/result.rb +9 -0
- data/lib/mcollective/aggregate/result/base.rb +25 -0
- data/lib/mcollective/aggregate/result/collection_result.rb +19 -0
- data/lib/mcollective/aggregate/result/numeric_result.rb +13 -0
- data/lib/mcollective/aggregate/sum.ddl +33 -0
- data/lib/mcollective/aggregate/sum.rb +18 -0
- data/lib/mcollective/aggregate/summary.ddl +33 -0
- data/lib/mcollective/aggregate/summary.rb +53 -0
- data/lib/mcollective/application.rb +365 -0
- data/lib/mcollective/application/completion.rb +104 -0
- data/lib/mcollective/application/describe_filter.rb +87 -0
- data/lib/mcollective/application/facts.rb +62 -0
- data/lib/mcollective/application/find.rb +23 -0
- data/lib/mcollective/application/help.rb +28 -0
- data/lib/mcollective/application/inventory.rb +344 -0
- data/lib/mcollective/application/ping.rb +82 -0
- data/lib/mcollective/application/plugin.rb +369 -0
- data/lib/mcollective/application/rpc.rb +111 -0
- data/lib/mcollective/applications.rb +134 -0
- data/lib/mcollective/cache.rb +145 -0
- data/lib/mcollective/client.rb +353 -0
- data/lib/mcollective/config.rb +245 -0
- data/lib/mcollective/connector.rb +18 -0
- data/lib/mcollective/connector/base.rb +26 -0
- data/lib/mcollective/data.rb +91 -0
- data/lib/mcollective/data/agent_data.ddl +22 -0
- data/lib/mcollective/data/agent_data.rb +17 -0
- data/lib/mcollective/data/base.rb +67 -0
- data/lib/mcollective/data/collective_data.ddl +20 -0
- data/lib/mcollective/data/collective_data.rb +9 -0
- data/lib/mcollective/data/fact_data.ddl +28 -0
- data/lib/mcollective/data/fact_data.rb +55 -0
- data/lib/mcollective/data/fstat_data.ddl +89 -0
- data/lib/mcollective/data/fstat_data.rb +56 -0
- data/lib/mcollective/data/result.rb +45 -0
- data/lib/mcollective/ddl.rb +113 -0
- data/lib/mcollective/ddl/agentddl.rb +253 -0
- data/lib/mcollective/ddl/base.rb +217 -0
- data/lib/mcollective/ddl/dataddl.rb +56 -0
- data/lib/mcollective/ddl/discoveryddl.rb +52 -0
- data/lib/mcollective/ddl/validatorddl.rb +6 -0
- data/lib/mcollective/discovery.rb +143 -0
- data/lib/mcollective/discovery/flatfile.ddl +11 -0
- data/lib/mcollective/discovery/flatfile.rb +48 -0
- data/lib/mcollective/discovery/mc.ddl +11 -0
- data/lib/mcollective/discovery/mc.rb +30 -0
- data/lib/mcollective/discovery/stdin.ddl +11 -0
- data/lib/mcollective/discovery/stdin.rb +68 -0
- data/lib/mcollective/exceptions.rb +28 -0
- data/lib/mcollective/facts.rb +39 -0
- data/lib/mcollective/facts/base.rb +100 -0
- data/lib/mcollective/facts/yaml_facts.rb +65 -0
- data/lib/mcollective/generators.rb +7 -0
- data/lib/mcollective/generators/agent_generator.rb +51 -0
- data/lib/mcollective/generators/base.rb +46 -0
- data/lib/mcollective/generators/data_generator.rb +51 -0
- data/lib/mcollective/generators/templates/action_snippet.erb +13 -0
- data/lib/mcollective/generators/templates/data_input_snippet.erb +7 -0
- data/lib/mcollective/generators/templates/ddl.erb +8 -0
- data/lib/mcollective/generators/templates/plugin.erb +7 -0
- data/lib/mcollective/log.rb +118 -0
- data/lib/mcollective/logger.rb +5 -0
- data/lib/mcollective/logger/base.rb +77 -0
- data/lib/mcollective/logger/console_logger.rb +61 -0
- data/lib/mcollective/logger/file_logger.rb +53 -0
- data/lib/mcollective/logger/syslog_logger.rb +53 -0
- data/lib/mcollective/matcher.rb +224 -0
- data/lib/mcollective/matcher/parser.rb +128 -0
- data/lib/mcollective/matcher/scanner.rb +241 -0
- data/lib/mcollective/message.rb +248 -0
- data/lib/mcollective/monkey_patches.rb +152 -0
- data/lib/mcollective/optionparser.rb +197 -0
- data/lib/mcollective/pluginmanager.rb +180 -0
- data/lib/mcollective/pluginpackager.rb +98 -0
- data/lib/mcollective/pluginpackager/agent_definition.rb +94 -0
- data/lib/mcollective/pluginpackager/debpackage_packager.rb +237 -0
- data/lib/mcollective/pluginpackager/modulepackage_packager.rb +127 -0
- data/lib/mcollective/pluginpackager/ospackage_packager.rb +59 -0
- data/lib/mcollective/pluginpackager/rpmpackage_packager.rb +180 -0
- data/lib/mcollective/pluginpackager/standard_definition.rb +69 -0
- data/lib/mcollective/pluginpackager/templates/debian/Makefile.erb +7 -0
- data/lib/mcollective/pluginpackager/templates/debian/changelog.erb +5 -0
- data/lib/mcollective/pluginpackager/templates/debian/compat.erb +1 -0
- data/lib/mcollective/pluginpackager/templates/debian/control.erb +15 -0
- data/lib/mcollective/pluginpackager/templates/debian/copyright.erb +8 -0
- data/lib/mcollective/pluginpackager/templates/debian/rules.erb +6 -0
- data/lib/mcollective/pluginpackager/templates/module/Modulefile.erb +5 -0
- data/lib/mcollective/pluginpackager/templates/module/README.md.erb +37 -0
- data/lib/mcollective/pluginpackager/templates/module/_manifest.pp.erb +9 -0
- data/lib/mcollective/pluginpackager/templates/redhat/rpm_spec.erb +63 -0
- data/lib/mcollective/registration/base.rb +91 -0
- data/lib/mcollective/rpc.rb +182 -0
- data/lib/mcollective/rpc/actionrunner.rb +158 -0
- data/lib/mcollective/rpc/agent.rb +374 -0
- data/lib/mcollective/rpc/audit.rb +38 -0
- data/lib/mcollective/rpc/client.rb +1066 -0
- data/lib/mcollective/rpc/helpers.rb +321 -0
- data/lib/mcollective/rpc/progress.rb +63 -0
- data/lib/mcollective/rpc/reply.rb +87 -0
- data/lib/mcollective/rpc/request.rb +86 -0
- data/lib/mcollective/rpc/result.rb +90 -0
- data/lib/mcollective/rpc/stats.rb +294 -0
- data/lib/mcollective/runnerstats.rb +90 -0
- data/lib/mcollective/security.rb +26 -0
- data/lib/mcollective/security/base.rb +244 -0
- data/lib/mcollective/shell.rb +126 -0
- data/lib/mcollective/ssl.rb +285 -0
- data/lib/mcollective/util.rb +579 -0
- data/lib/mcollective/validator.rb +85 -0
- data/lib/mcollective/validator/array_validator.ddl +7 -0
- data/lib/mcollective/validator/array_validator.rb +9 -0
- data/lib/mcollective/validator/ipv4address_validator.ddl +7 -0
- data/lib/mcollective/validator/ipv4address_validator.rb +16 -0
- data/lib/mcollective/validator/ipv6address_validator.ddl +7 -0
- data/lib/mcollective/validator/ipv6address_validator.rb +16 -0
- data/lib/mcollective/validator/length_validator.ddl +7 -0
- data/lib/mcollective/validator/length_validator.rb +11 -0
- data/lib/mcollective/validator/regex_validator.ddl +7 -0
- data/lib/mcollective/validator/regex_validator.rb +9 -0
- data/lib/mcollective/validator/shellsafe_validator.ddl +7 -0
- data/lib/mcollective/validator/shellsafe_validator.rb +13 -0
- data/lib/mcollective/validator/typecheck_validator.ddl +7 -0
- data/lib/mcollective/validator/typecheck_validator.rb +28 -0
- metadata +215 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
7
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Source: <%= @package_name %>
|
|
2
|
+
Homepage: <%= @plugin.metadata[:url] %>
|
|
3
|
+
Section: utils
|
|
4
|
+
Priority: extra
|
|
5
|
+
Build-Depends: debhelper (>= 7), cdbs, dpatch
|
|
6
|
+
Maintainer: <%= @plugin.metadata[:author] %>
|
|
7
|
+
Standards-Version: 3.9.1
|
|
8
|
+
<% @plugin.packagedata.each do |type, data| %>
|
|
9
|
+
Package: <%= "#{@package_name}-#{type}" %>
|
|
10
|
+
Architecture: all
|
|
11
|
+
Depends: <%= build_dependency_string(data) %>
|
|
12
|
+
Description: <%= @plugin.metadata[:description]%>
|
|
13
|
+
<%= data[:description]%>
|
|
14
|
+
.
|
|
15
|
+
<% end -%>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# <%= @package_name %>
|
|
2
|
+
|
|
3
|
+
#### Table of Contents
|
|
4
|
+
|
|
5
|
+
1. [Overview](#overview)
|
|
6
|
+
2. [Module Description - What the module does and why it is useful](#module-description)
|
|
7
|
+
3. [Setup - The basics of getting started with <%= @package_name %>](#setup)
|
|
8
|
+
* [What the <%= @package_name %> module affects](#what-the-<%= @package_name %>-module-affects)
|
|
9
|
+
* [Setup requirements](#setup-requirements)
|
|
10
|
+
4. [Usage - Configuration options and additional functionality](#usage)
|
|
11
|
+
5. [Reference - An under-the-hood peek at what the module is doing and how](#reference)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
The <%= @package_name %> module is a module that wraps a source release of the
|
|
17
|
+
<%= @plugin.metadata[:name] %> mcollective plugin for use with the
|
|
18
|
+
[puppetlabs mcollective](http://forge.puppetlabs.com/puppetlabs/mcollective)
|
|
19
|
+
module.
|
|
20
|
+
|
|
21
|
+
## Module description
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
<% @plugin.packagedata.keys.map { |x| x.to_s }.sort.each do |klass| -%>
|
|
26
|
+
<%# Don't document common class -%>
|
|
27
|
+
<% if klass != "common" -%>
|
|
28
|
+
### class <%= @package_name %>::<%= klass %>
|
|
29
|
+
|
|
30
|
+
Installs the <%= klass %> component of the <%= @plugin.metadata[:name] %> plugin.
|
|
31
|
+
|
|
32
|
+
```puppet
|
|
33
|
+
include <%= @package_name%>::<%= klass %>
|
|
34
|
+
```
|
|
35
|
+
<% end %>
|
|
36
|
+
<% end %>
|
|
37
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#
|
|
2
|
+
class <%= @package_name %>::<%= @klass %> {
|
|
3
|
+
<% if @plugin.packagedata[:common] && @klass != 'common' %>
|
|
4
|
+
include ::<%= @package_name %>::common
|
|
5
|
+
<% end %>
|
|
6
|
+
mcollective::plugin { '<%= @package_name %>/<%= @klass %>':
|
|
7
|
+
source => 'puppet:///modules/<%= @package_name %>/<%= @klass %>',
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Name: <%= @package_name %>
|
|
2
|
+
Summary: <%= @plugin.metadata[:description] %>
|
|
3
|
+
Version: <%= @plugin.metadata[:version] %>
|
|
4
|
+
Release: <%= @plugin.revision %>%{?dist}
|
|
5
|
+
License: <%= @plugin.metadata[:license]%>
|
|
6
|
+
URL: <%= @plugin.metadata[:url]%>
|
|
7
|
+
Vendor: <%= @plugin.vendor%>
|
|
8
|
+
Packager: <%= @plugin.metadata[:author]%>
|
|
9
|
+
BuildArch: noarch
|
|
10
|
+
Group: System Tools
|
|
11
|
+
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
|
12
|
+
Source0: <%= @package_name_and_version%>.tgz
|
|
13
|
+
|
|
14
|
+
%description
|
|
15
|
+
<%= @plugin.metadata[:description] %>
|
|
16
|
+
|
|
17
|
+
%prep
|
|
18
|
+
%setup
|
|
19
|
+
|
|
20
|
+
%build
|
|
21
|
+
<% package_files = plugin_files.map{ |f| File.join(@libdir, File.expand_path(f).gsub(/#{File.expand_path(@plugin.path)}|\.\//, '')) } -%>
|
|
22
|
+
<% dirs = package_files.map{ |f| File.dirname(f) }.uniq -%>
|
|
23
|
+
|
|
24
|
+
%install
|
|
25
|
+
rm -rf %{buildroot}
|
|
26
|
+
<% dirs.each do |dir| -%>
|
|
27
|
+
%{__install} -d -m0755 %{buildroot}<%= dir%>
|
|
28
|
+
<% end -%>
|
|
29
|
+
<% package_files.each do |file| -%>
|
|
30
|
+
%{__install} -m0644 -v <%= (file[0].chr == '/') ? file[1..file.size-1]: file%> %{buildroot}<%=file %>
|
|
31
|
+
<% end -%>
|
|
32
|
+
|
|
33
|
+
<% @plugin.packagedata.each do |type, data| %>
|
|
34
|
+
%package <%= type %>
|
|
35
|
+
Summary: <%= @plugin.metadata[:description] %>
|
|
36
|
+
<% if data[:plugindependency] %>
|
|
37
|
+
Requires: <%= data[:plugindependency][:name] -%> = <%= data[:plugindependency][:version]%>-<%= data[:plugindependency][:revision]%>%{?dist}
|
|
38
|
+
<% end -%>
|
|
39
|
+
<% PluginPackager.filter_dependencies('redhat', data[:dependencies]).each do |dep|-%>
|
|
40
|
+
Requires: <%= dep[:name] -%> <%= ">= #{dep[:version]}" if dep[:version]%><%="-#{dep[:revision]}" if dep[:revision]%>
|
|
41
|
+
<% end -%>
|
|
42
|
+
%description <%= type %>
|
|
43
|
+
<%= data[:description] %>
|
|
44
|
+
|
|
45
|
+
%files <%= type %>
|
|
46
|
+
%defattr(-, root, root, -)
|
|
47
|
+
<% package_files(data[:files]).each do |file| -%>
|
|
48
|
+
<%= file %>
|
|
49
|
+
<% end -%>
|
|
50
|
+
<% end -%>
|
|
51
|
+
|
|
52
|
+
<% if @plugin.preinstall -%>
|
|
53
|
+
%pre
|
|
54
|
+
<%= @plugin.preinstall %>
|
|
55
|
+
<% end -%>
|
|
56
|
+
<% if @plugin.postinstall -%>
|
|
57
|
+
%post
|
|
58
|
+
<%= @plugin.postinstall%>
|
|
59
|
+
<% end -%>
|
|
60
|
+
|
|
61
|
+
%changelog
|
|
62
|
+
* <%= Time.now.strftime("%a %b %d %Y") -%> <%= @plugin.metadata[:author]%> - <%= @plugin.metadata[:version]%>-<%= @plugin.revision %>
|
|
63
|
+
- Built Package <%= @plugin.metadata[:name] -%>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
module Registration
|
|
3
|
+
# This is a base class that other registration plugins can use
|
|
4
|
+
# to handle regular announcements to the mcollective
|
|
5
|
+
#
|
|
6
|
+
# The configuration file determines how often registration messages
|
|
7
|
+
# gets sent using the _registerinterval_ option, the plugin runs in the
|
|
8
|
+
# background in a thread.
|
|
9
|
+
class Base
|
|
10
|
+
# Register plugins that inherits base
|
|
11
|
+
def self.inherited(klass)
|
|
12
|
+
PluginManager << {:type => "registration_plugin", :class => klass.to_s}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Creates a background thread that periodically send a registration notice.
|
|
16
|
+
#
|
|
17
|
+
# The actual registration notices comes from the 'body' method of the registration
|
|
18
|
+
# plugins.
|
|
19
|
+
def run(connection)
|
|
20
|
+
return false if interval == 0
|
|
21
|
+
|
|
22
|
+
Thread.new do
|
|
23
|
+
publish_thread(connection)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def config
|
|
28
|
+
Config.instance
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def msg_filter
|
|
32
|
+
filter = Util.empty_filter
|
|
33
|
+
filter["agent"] << "registration"
|
|
34
|
+
filter
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def target_collective
|
|
38
|
+
main_collective = config.main_collective
|
|
39
|
+
|
|
40
|
+
collective = config.registration_collective || main_collective
|
|
41
|
+
|
|
42
|
+
unless config.collectives.include?(collective)
|
|
43
|
+
Log.warn("Sending registration to #{main_collective}: #{collective} is not a valid collective")
|
|
44
|
+
collective = main_collective
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
return collective
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def interval
|
|
51
|
+
config.registerinterval
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def publish(message)
|
|
55
|
+
unless message
|
|
56
|
+
Log.debug("Skipping registration due to nil body")
|
|
57
|
+
else
|
|
58
|
+
req = Message.new(message, nil, {:type => :request, :agent => "registration", :collective => target_collective, :filter => msg_filter})
|
|
59
|
+
req.encode!
|
|
60
|
+
|
|
61
|
+
Log.debug("Sending registration #{req.requestid} to collective #{req.collective}")
|
|
62
|
+
|
|
63
|
+
req.publish
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def body
|
|
68
|
+
raise "Registration Plugins must implement the #body method"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
def publish_thread(connnection)
|
|
73
|
+
if config.registration_splay
|
|
74
|
+
splay_delay = rand(interval)
|
|
75
|
+
Log.debug("registration_splay enabled. Registration will start in #{splay_delay} seconds")
|
|
76
|
+
sleep splay_delay
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
loop do
|
|
80
|
+
begin
|
|
81
|
+
publish(body)
|
|
82
|
+
sleep interval
|
|
83
|
+
rescue Exception => e
|
|
84
|
+
Log.error("Sending registration message failed: #{e}")
|
|
85
|
+
sleep interval
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
require 'pp'
|
|
2
|
+
|
|
3
|
+
module MCollective
|
|
4
|
+
# Toolset to create a standard interface of client and agent using
|
|
5
|
+
# an RPC metaphor, standard compliant agents will make it easier
|
|
6
|
+
# to create generic clients like web interfaces etc
|
|
7
|
+
module RPC
|
|
8
|
+
require "mcollective/rpc/actionrunner"
|
|
9
|
+
require "mcollective/rpc/agent"
|
|
10
|
+
require "mcollective/rpc/audit"
|
|
11
|
+
require "mcollective/rpc/client"
|
|
12
|
+
require "mcollective/rpc/helpers"
|
|
13
|
+
require "mcollective/rpc/progress"
|
|
14
|
+
require "mcollective/rpc/reply"
|
|
15
|
+
require "mcollective/rpc/request"
|
|
16
|
+
require "mcollective/rpc/result"
|
|
17
|
+
require "mcollective/rpc/stats"
|
|
18
|
+
|
|
19
|
+
# Creates a standard options hash, pass in a block to add extra headings etc
|
|
20
|
+
# see Optionparser
|
|
21
|
+
def rpcoptions
|
|
22
|
+
oparser = MCollective::Optionparser.new({:verbose => false, :progress_bar => true}, "filter")
|
|
23
|
+
|
|
24
|
+
options = oparser.parse do |parser, options|
|
|
25
|
+
if block_given?
|
|
26
|
+
yield(parser, options)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
Helpers.add_simplerpc_options(parser, options)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
return options
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Wrapper to create clients, supposed to be used as
|
|
36
|
+
# a mixin:
|
|
37
|
+
#
|
|
38
|
+
# include MCollective::RPC
|
|
39
|
+
#
|
|
40
|
+
# exim = rpcclient("exim")
|
|
41
|
+
# printrpc exim.mailq
|
|
42
|
+
#
|
|
43
|
+
# or
|
|
44
|
+
#
|
|
45
|
+
# rpcclient("exim") do |exim|
|
|
46
|
+
# printrpc exim.mailq
|
|
47
|
+
# end
|
|
48
|
+
#
|
|
49
|
+
# It will take a few flags:
|
|
50
|
+
# :configfile => "etc/client.cfg"
|
|
51
|
+
# :options => options
|
|
52
|
+
# :exit_on_failure => true
|
|
53
|
+
#
|
|
54
|
+
# Options would be a build up options hash from the Optionparser
|
|
55
|
+
# you can use the rpcoptions helper to create this
|
|
56
|
+
#
|
|
57
|
+
# :exit_on_failure is true by default, and causes the application to
|
|
58
|
+
# exit if there is a failure constructing the RPC client. Set this flag
|
|
59
|
+
# to false to cause an Exception to be raised instead.
|
|
60
|
+
def rpcclient(agent, flags = {})
|
|
61
|
+
configfile = flags[:configfile] || Util.config_file_for_user
|
|
62
|
+
options = flags[:options] || nil
|
|
63
|
+
|
|
64
|
+
if flags.key?(:exit_on_failure)
|
|
65
|
+
exit_on_failure = flags[:exit_on_failure]
|
|
66
|
+
else
|
|
67
|
+
# We exit on failure by default for CLI-friendliness
|
|
68
|
+
exit_on_failure = true
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
begin
|
|
72
|
+
if options
|
|
73
|
+
rpc = Client.new(agent, :configfile => options[:config], :options => options)
|
|
74
|
+
@options = rpc.options
|
|
75
|
+
else
|
|
76
|
+
rpc = Client.new(agent, :configfile => configfile)
|
|
77
|
+
@options = rpc.options
|
|
78
|
+
end
|
|
79
|
+
rescue Exception => e
|
|
80
|
+
if exit_on_failure
|
|
81
|
+
puts("Could not create RPC client: #{e}")
|
|
82
|
+
exit!
|
|
83
|
+
else
|
|
84
|
+
raise e
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
if block_given?
|
|
89
|
+
yield(rpc)
|
|
90
|
+
else
|
|
91
|
+
return rpc
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# means for other classes to drop stats into this module
|
|
96
|
+
# its a bit hacky but needed so that the mixin methods like
|
|
97
|
+
# printrpcstats can easily get access to it without
|
|
98
|
+
# users having to pass it around in params.
|
|
99
|
+
def self.stats(stats)
|
|
100
|
+
@@stats = stats
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# means for other classes to drop discovered hosts into this module
|
|
104
|
+
# its a bit hacky but needed so that the mixin methods like
|
|
105
|
+
# printrpcstats can easily get access to it without
|
|
106
|
+
# users having to pass it around in params.
|
|
107
|
+
def self.discovered(discovered)
|
|
108
|
+
@@discovered = discovered
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Prints stats, requires stats to be saved from elsewhere
|
|
112
|
+
# using the MCollective::RPC.stats method.
|
|
113
|
+
#
|
|
114
|
+
# If you've passed -v on the command line a detailed stat block
|
|
115
|
+
# will be printed, else just a one liner.
|
|
116
|
+
#
|
|
117
|
+
# You can pass flags into it:
|
|
118
|
+
#
|
|
119
|
+
# printrpcstats :caption => "Foo", :summarize => true
|
|
120
|
+
#
|
|
121
|
+
# This will use "Foo" as the caption to the stats in verbose
|
|
122
|
+
# mode and print out any aggregate summary information if present
|
|
123
|
+
def printrpcstats(flags={})
|
|
124
|
+
return unless @options[:output_format] == :console
|
|
125
|
+
|
|
126
|
+
flags = {:summarize => false, :caption => "rpc stats"}.merge(flags)
|
|
127
|
+
|
|
128
|
+
verbose = @options[:verbose] rescue verbose = false
|
|
129
|
+
|
|
130
|
+
begin
|
|
131
|
+
stats = @@stats
|
|
132
|
+
rescue
|
|
133
|
+
puts("no stats to display")
|
|
134
|
+
return
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
puts stats.report(flags[:caption], flags[:summarize], verbose)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Prints the result of an RPC call.
|
|
141
|
+
#
|
|
142
|
+
# In the default quiet mode - no flattening or verbose - only results
|
|
143
|
+
# that produce an error will be printed
|
|
144
|
+
#
|
|
145
|
+
# To get details of each result run with the -v command line option.
|
|
146
|
+
def printrpc(result, flags = {})
|
|
147
|
+
verbose = @options[:verbose] rescue verbose = false
|
|
148
|
+
verbose = flags[:verbose] || verbose
|
|
149
|
+
flatten = flags[:flatten] || false
|
|
150
|
+
format = @options[:output_format]
|
|
151
|
+
forced_mode = @options[:force_display_mode] || false
|
|
152
|
+
|
|
153
|
+
result_text = Helpers.rpcresults(result, {:verbose => verbose, :flatten => flatten, :format => format, :force_display_mode => forced_mode})
|
|
154
|
+
|
|
155
|
+
if result.is_a?(Array) && format == :console
|
|
156
|
+
puts "\n%s\n" % [ result_text ]
|
|
157
|
+
else
|
|
158
|
+
# when we get just one result to print dont pad them all with
|
|
159
|
+
# blank spaces etc, just print the individual result with no
|
|
160
|
+
# padding
|
|
161
|
+
puts result_text unless result_text == ""
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Wrapper for MCollective::Util.empty_filter? to make clients less fugly
|
|
166
|
+
# to write - ticket #18
|
|
167
|
+
def empty_filter?(options)
|
|
168
|
+
if options.include?(:filter)
|
|
169
|
+
Util.empty_filter?(options[:filter])
|
|
170
|
+
else
|
|
171
|
+
Util.empty_filter?(options)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def self.const_missing(const_name)
|
|
176
|
+
super unless const_name == :DDL
|
|
177
|
+
|
|
178
|
+
Log.warn("MCollective::RPC::DDL is deprecatd, please use MCollective::DDL instead")
|
|
179
|
+
MCollective::DDL
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
module RPC
|
|
3
|
+
# A helper used by RPC::Agent#implemented_by to delegate an action to
|
|
4
|
+
# an external script. At present only JSON based serialization is
|
|
5
|
+
# supported in future ones based on key=val pairs etc will be added
|
|
6
|
+
#
|
|
7
|
+
# It serializes the request object into an input file and creates an
|
|
8
|
+
# empty output file. It then calls the external command reading the
|
|
9
|
+
# output file at the end.
|
|
10
|
+
#
|
|
11
|
+
# any STDERR gets logged at error level and any STDOUT gets logged at
|
|
12
|
+
# info level.
|
|
13
|
+
#
|
|
14
|
+
# It will interpret the exit code from the application the same way
|
|
15
|
+
# RPC::Reply#fail! and #fail handles their codes creating a consistent
|
|
16
|
+
# interface, the message part of the fail message will come from STDERR
|
|
17
|
+
#
|
|
18
|
+
# Generally externals should just exit with code 1 on failure and print to
|
|
19
|
+
# STDERR, this is exactly what Perl die() does and translates perfectly
|
|
20
|
+
# to our model
|
|
21
|
+
#
|
|
22
|
+
# It uses the MCollective::Shell wrapper to call the external application
|
|
23
|
+
class ActionRunner
|
|
24
|
+
attr_reader :command, :agent, :action, :format, :stdout, :stderr, :request
|
|
25
|
+
|
|
26
|
+
def initialize(command, request, format=:json)
|
|
27
|
+
@agent = request.agent
|
|
28
|
+
@action = request.action
|
|
29
|
+
@format = format
|
|
30
|
+
@request = request
|
|
31
|
+
@command = path_to_command(command)
|
|
32
|
+
@stdout = ""
|
|
33
|
+
@stderr = ""
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def run
|
|
37
|
+
unless canrun?(command)
|
|
38
|
+
Log.warn("Cannot run #{to_s}")
|
|
39
|
+
raise RPCAborted, "Cannot execute #{to_s}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Log.debug("Running #{to_s}")
|
|
43
|
+
|
|
44
|
+
request_file = saverequest(request)
|
|
45
|
+
reply_file = tempfile("reply")
|
|
46
|
+
reply_file.close
|
|
47
|
+
|
|
48
|
+
runner = shell(command, request_file.path, reply_file.path)
|
|
49
|
+
|
|
50
|
+
runner.runcommand
|
|
51
|
+
|
|
52
|
+
Log.debug("#{command} exited with #{runner.status.exitstatus}")
|
|
53
|
+
|
|
54
|
+
stderr.each_line {|l| Log.error("#{to_s}: #{l.chomp}")} unless stderr.empty?
|
|
55
|
+
stdout.each_line {|l| Log.info("#{to_s}: #{l.chomp}")} unless stdout.empty?
|
|
56
|
+
|
|
57
|
+
{:exitstatus => runner.status.exitstatus,
|
|
58
|
+
:stdout => runner.stdout,
|
|
59
|
+
:stderr => runner.stderr,
|
|
60
|
+
:data => load_results(reply_file.path)}
|
|
61
|
+
ensure
|
|
62
|
+
request_file.close! if request_file.respond_to?("close!")
|
|
63
|
+
reply_file.close! if reply_file.respond_to?("close")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def shell(command, infile, outfile)
|
|
67
|
+
env = {"MCOLLECTIVE_REQUEST_FILE" => infile,
|
|
68
|
+
"MCOLLECTIVE_REPLY_FILE" => outfile}
|
|
69
|
+
|
|
70
|
+
Shell.new("#{command} #{infile} #{outfile}", :cwd => Dir.tmpdir, :stdout => stdout, :stderr => stderr, :environment => env)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def load_results(file)
|
|
74
|
+
Log.debug("Attempting to load results in #{format} format from #{file}")
|
|
75
|
+
|
|
76
|
+
data = {}
|
|
77
|
+
|
|
78
|
+
if respond_to?("load_#{format}_results")
|
|
79
|
+
tempdata = send("load_#{format}_results", file)
|
|
80
|
+
|
|
81
|
+
tempdata.each_pair do |k,v|
|
|
82
|
+
data[k.to_sym] = v
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
data
|
|
87
|
+
rescue Exception => e
|
|
88
|
+
{}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def load_json_results(file)
|
|
92
|
+
return {} unless File.readable?(file)
|
|
93
|
+
|
|
94
|
+
JSON.load(File.read(file)) || {}
|
|
95
|
+
rescue JSON::ParserError
|
|
96
|
+
{}
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def saverequest(req)
|
|
100
|
+
Log.debug("Attempting to save request in #{format} format")
|
|
101
|
+
|
|
102
|
+
if respond_to?("save_#{format}_request")
|
|
103
|
+
data = send("save_#{format}_request", req)
|
|
104
|
+
|
|
105
|
+
request_file = tempfile("request")
|
|
106
|
+
request_file.puts data
|
|
107
|
+
request_file.close
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
request_file
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def save_json_request(req)
|
|
114
|
+
req.to_json
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def canrun?(command)
|
|
118
|
+
File.executable?(command)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def to_s
|
|
122
|
+
"%s#%s command: %s" % [ agent, action, command ]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def tempfile(prefix)
|
|
126
|
+
Tempfile.new("mcollective_#{prefix}", Dir.tmpdir)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def path_to_command(command)
|
|
130
|
+
if Util.absolute_path?(command)
|
|
131
|
+
return command
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
Config.instance.libdir.each do |libdir|
|
|
135
|
+
command_file_old = File.join(libdir, "agent", agent, command)
|
|
136
|
+
command_file_new = File.join(libdir, "mcollective", "agent", agent, command)
|
|
137
|
+
command_file_old_exists = File.exists?(command_file_old)
|
|
138
|
+
command_file_new_exists = File.exists?(command_file_new)
|
|
139
|
+
|
|
140
|
+
if command_file_new_exists && command_file_old_exists
|
|
141
|
+
Log.debug("Found 'implemented_by' scripts found in two locations #{command_file_old} and #{command_file_new}")
|
|
142
|
+
Log.debug("Running script: #{command_file_new}")
|
|
143
|
+
return command_file_new
|
|
144
|
+
elsif command_file_old_exists
|
|
145
|
+
Log.debug("Running script: #{command_file_old}")
|
|
146
|
+
return command_file_old
|
|
147
|
+
elsif command_file_new_exists
|
|
148
|
+
Log.debug("Running script: #{command_file_new}")
|
|
149
|
+
return command_file_new
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
Log.warn("No script found for: #{command}")
|
|
154
|
+
command
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|