onering-agent 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ module Onering
2
+ module CLI
3
+ class Fact < Plugin
4
+ def self.configure(global={})
5
+ @opts = ::Trollop::options do
6
+ banner <<-EOS
7
+ Return the value of an internal fact.
8
+
9
+ Usage:
10
+ onering [global] fact [name]
11
+
12
+ EOS
13
+ end
14
+ end
15
+
16
+ def self.run(args)
17
+ args[0] = :hardwareid if args[0] and args[0] == 'id'
18
+ return Onering::Util.fact(args[0])
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,121 @@
1
+ module Onering
2
+ module CLI
3
+ class Report < Plugin
4
+ DEFAULT_CACHE_MAXAGE=600
5
+
6
+ def self.configure(global={})
7
+ @global_opts = global
8
+ @api = Onering::CLI.connect(@global_opts.merge({
9
+ :autoconnect => false
10
+ }))
11
+
12
+ @opts = ::Trollop::options do
13
+ banner <<-EOS
14
+ Generate a system report that can be saved or submitted to a Onering server
15
+
16
+ Subcommands:
17
+ <none>
18
+ Generate and output the system inventory report.
19
+
20
+ get <property> [fallback]
21
+ Get a specific <property> from the report, return [fallback] if not found.
22
+
23
+ save
24
+ Generate and save the system inventory report to Onering.
25
+
26
+ Usage:
27
+ onering [global] report [options] [subcommands]
28
+
29
+ Options:
30
+ EOS
31
+ opt :id, "Override the autodetected Hardware ID for this node", :short => '-I', :type => :string
32
+ opt :fields, "Set the named FIELD to equal VALUE in the format FIELD=VALUE. Can be specified multiple times", :short => '-o', :type => :string, :multi => true
33
+ opt :save, "Save the report output to the configured Onering server"
34
+ opt :timeout, "The maximum amount of time to wait for a report to be generated", :type => :integer, :default => 60
35
+ opt :plugin_timeout, "The maximum amount of time to wait for a report plugin to return data", :type => :integer, :default => 10
36
+ opt :local, "Do not attempt to contact a remote server for retrieving values not found locally", :type => :boolean, :default => false
37
+ opt :cachefile, "Use the specified file as a local report cache", :type => :string, :short => '-F'
38
+ opt :nocache, "Do not attempt to use a cache file for report generation", :type => :boolean, :default => false
39
+ opt :maxage, "Maxmimum age (in seconds) of the cache before it is automatically regenerated", :type => :integer, :default => DEFAULT_CACHE_MAXAGE
40
+
41
+ stop_on %w{get save}
42
+ end
43
+
44
+ # initialize report generator with user options
45
+ @_reporter = Onering::Reporter.new({
46
+ :id => @opts[:id],
47
+ :timeout => @opts[:timeout],
48
+ :plugin_timeout => @opts[:plugin_timeout],
49
+ :nocache => @opts[:nocache],
50
+ :cachefile => @opts[:cachefile],
51
+ :maxage => @opts[:maxage]
52
+ }.compact)
53
+ end
54
+
55
+ def self.run(args)
56
+ # saving, by default, should not use the cache (but should update it to keep it fresh)
57
+ if @opts[:save] === true or args[0] == 'save'
58
+ report = _report({
59
+ :cacheregen => true
60
+ })
61
+ else
62
+ report = _report()
63
+ end
64
+
65
+ # pull overrides from CLI arguments
66
+ @opts[:fields].each do |field|
67
+ key, value = field.split('=', 2)
68
+ Onering::Logger.debug("Override value #{key} from command line argument", "Onering::CLI::Report")
69
+
70
+ value = nil if ['null', '', '-'].include?(value.to_s.strip.chomp)
71
+ report = report.set(key, value)
72
+ end
73
+
74
+ # save if specified
75
+ if @opts[:save] === true
76
+ _save(report)
77
+
78
+ else
79
+ sc = args.shift
80
+
81
+ case (sc.downcase.to_sym rescue nil)
82
+ # -----------------------------------------------------------------------------
83
+ when :save
84
+ _save(report)
85
+ return nil
86
+
87
+ when :get
88
+ Onering::Logger.fatal!("Expected at least 1 parameter, got #{args.length}", "Onering::CLI::Report") unless args.length >= 1
89
+ return @_reporter.get(args[0], args[1], {
90
+ :data => report,
91
+ :api => @global_opts,
92
+ :local => @opts[:local]
93
+ })
94
+ end
95
+ end
96
+
97
+ return report
98
+ end
99
+
100
+ private
101
+ def self._save(report)
102
+ @api.connect()
103
+ @api.assets.save(report['id']) do
104
+ MultiJson.dump(report)
105
+ end
106
+ end
107
+
108
+ def self._report(options={})
109
+ begin
110
+ Onering::Logger.debug("Gathering local data for report", "Onering::CLI::Report")
111
+ Onering::Logger.fatal("Reporter not configured. This is a bug", "Onering::CLI::Report") if @_reporter.nil?
112
+ report = @_reporter.report(options).stringify_keys()
113
+
114
+ return report
115
+ rescue Timeout::Error
116
+ Onering::Logger.fatal!("Report took too long to generate, exiting...", "Onering::CLI::Report")
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,62 @@
1
+ require 'set'
2
+ require 'hashlib'
3
+
4
+ module Onering
5
+ class Config
6
+ class<<self
7
+ DEFAULT_CONFIG={}
8
+ DEFAULT_OPTIONS_FILE=["~/.onering/cli.yml", "~/.onering/key.yml", "/etc/onering/cli.yml", "/etc/onering/key.yml"]
9
+
10
+ def load(configfile=nil, config={})
11
+ if configfile.nil?
12
+ configfile = []
13
+ else
14
+ # recursively grab all .yml files if directory is specified
15
+ configfile = (File.directory?(configfile) ? Dir.glob(File.join(configfile, "**", "*.yml")).sort : [configfile])
16
+ end
17
+
18
+ # list all existing config files from least specific to most
19
+ @_configfiles = (configfile + DEFAULT_OPTIONS_FILE).compact.select{|i|
20
+ (File.exists?(File.expand_path(i)) rescue false)
21
+ }.reverse
22
+
23
+ # merge all config files with more-specific values overriding less-specific ones
24
+ @_config ||= DEFAULT_CONFIG
25
+ @_configfiles_seen ||= Set.new()
26
+
27
+ # only load files we haven't seen before
28
+ (@_configfiles - @_configfiles_seen.to_a).each do |i|
29
+ c = YAML.load(File.read(File.expand_path(i))) rescue {}
30
+
31
+ if c and not c.empty?
32
+ Onering::Logger.info("Loading config file at #{File.expand_path(i) rescue i}", "Onering::Config")
33
+ @_config.deep_merge!(c)
34
+ end
35
+
36
+ @_configfiles_seen << i
37
+ end
38
+
39
+
40
+ # settings specified in the library override everything
41
+ unless config.empty?
42
+ Onering::Logger.debug("Merging settings specified in library instantiation", "Onering::Config")
43
+ @_config.deep_merge!(config.compact)
44
+ end
45
+
46
+ return @_config
47
+ end
48
+
49
+ def get(key, default=nil)
50
+ @_config.get(key, default)
51
+ end
52
+
53
+ def set(key, value)
54
+ @_config.set(key, value)
55
+ end
56
+
57
+ def unset(key)
58
+ @_config.unset(key)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,141 @@
1
+ require 'logger'
2
+ require 'rainbow'
3
+ require 'onering/version'
4
+
5
+ module Onering
6
+ class Logger
7
+ def self.setup(options={})
8
+ outputfn = options[:destination]
9
+ @_verbosity = 1
10
+
11
+ if options[:destination] == /STDOUT/i
12
+ options[:destination] = STDOUT
13
+
14
+ elsif options[:destination] == /STDERR/i or
15
+ options[:destination].nil?
16
+ options[:destination] = STDERR
17
+
18
+ elsif File.writable?(options[:destination])
19
+ options[:destination] = File.open(options[:destination], 'a')
20
+
21
+ else
22
+ options[:destination] = STDERR
23
+ end
24
+
25
+ @_logger = ::Logger.new(options[:destination])
26
+ @_logger.formatter = (options[:formatter] || proc{|severity, datetime, source, msg|
27
+ case severity.downcase.to_sym
28
+ when :fatal then sevtag = '!!'
29
+ when :error then sevtag = 'EE'
30
+ when :warn then sevtag = 'WW'
31
+ when :info then sevtag = 'II'
32
+ when :debug then sevtag = 'DD'
33
+ when :output then sevtag = ''
34
+ else sevtag = '??'
35
+ end
36
+
37
+ if options[:sevtag] == false
38
+ logline = [(source.nil? ? nil : "[#{source}]"), msg].compact.join(' ')
39
+ else
40
+ logline = ["#{sevtag} ", (source.nil? ? nil : "[#{source}]"), msg].compact.join(' ')
41
+ end
42
+
43
+ if options[:destination] === STDOUT or options[:destination] === STDERR
44
+ case severity.downcase.to_sym
45
+ when :fatal, :error
46
+ logline = logline.foreground(:red)
47
+ when :warn
48
+ logline = logline.foreground(:yellow)
49
+ when :info
50
+ logline = logline.foreground(:green)
51
+ when :debug, :debug2, :debug3
52
+ logline = logline.foreground(:blue)
53
+ end
54
+ end
55
+
56
+ options[:destination].puts(logline)
57
+ })
58
+
59
+ self.level = (options[:threshold] || :info)
60
+
61
+ self.debug("onering-client v#{Onering::Client::VERSION} started") if defined?(Onering::FULL_CLIENT)
62
+ self.debug("Logger is initialized. Output is #{outputfn || 'stderr'}, threshold: #{options[:threshold]} or worse", (options[:name] || "Onering::Logger"))
63
+ end
64
+
65
+
66
+ def self.logger()
67
+ return @_logger
68
+ end
69
+
70
+ def self.level=(severity)
71
+ @_logger.sev_threshold = _get_level(severity)
72
+ @_verbosity = (Integer(severity.to_s[-1]) rescue 1)
73
+
74
+ @_logger.sev_threshold
75
+ end
76
+
77
+
78
+ def self.log(severity, message, source=nil, verbosity=1)
79
+ if defined?(@_logger)
80
+ if @_verbosity >= verbosity
81
+ @_logger.add(_get_level(severity), message, source)
82
+ return true
83
+ end
84
+ end
85
+
86
+ return false
87
+ end
88
+
89
+ def self.fatal(message, source=nil, raise_error=false)
90
+ self.log(:fatal, message, source)
91
+ raise Onering::Client::FatalError.new(message) if raise_error === true
92
+ end
93
+
94
+ def self.fatal!(message, source=nil)
95
+ self.fatal(message, source, true)
96
+ end
97
+
98
+ def self.error(message, source=nil)
99
+ self.log(:error, message, source)
100
+ end
101
+
102
+ def self.warn(message, source=nil)
103
+ self.log(:warn, message, source)
104
+ end
105
+
106
+ def self.info(message, source=nil)
107
+ self.log(:info, message, source)
108
+ end
109
+
110
+ def self.debug(message, source=nil)
111
+ self.log(:debug, message, source)
112
+ end
113
+
114
+ def self.debug2(message, source=nil)
115
+ self.log(:debug, message, source, 2)
116
+ end
117
+
118
+ def self.debug3(message, source=nil)
119
+ self.log(:debug, message, source, 3)
120
+ end
121
+
122
+ def self.output(message, source=nil)
123
+ self.log(:output, message, source)
124
+ end
125
+
126
+ def self._get_level(severity)
127
+ case severity.to_sym
128
+ when :fatal
129
+ return ::Logger::FATAL
130
+ when :error
131
+ return ::Logger::ERROR
132
+ when :warn
133
+ return ::Logger::WARN
134
+ when :info
135
+ return ::Logger::INFO
136
+ else
137
+ return ::Logger::DEBUG
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,54 @@
1
+ module Onering
2
+ class API
3
+ class Assets < API
4
+ def show(id)
5
+ get("/devices/#{id}").parsed_response
6
+ end
7
+
8
+ def get_field(id, field, fallback=nil)
9
+ rv = get("/devices/#{id}/get/#{field}")
10
+ rv = (rv.parsed_response rescue rv.response.body)
11
+ return fallback if rv.nil? or (rv.is_a?(String) and rv.strip.chomp.empty?)
12
+ return rv
13
+ end
14
+
15
+ def set_field(id, field, value)
16
+ rv = get("/devices/#{id}/set/#{field}/#{value}")
17
+ rv.parsed_response rescue rv.response.body
18
+ end
19
+
20
+ def list(field, options={
21
+ :unique => true,
22
+ :sort => true,
23
+ :filter => nil
24
+ })
25
+ qs = {
26
+ :q => make_filter(options[:filter])
27
+ } if options[:filter]
28
+
29
+ rv = get("/devices/list/#{[*field].join('/')}", {
30
+ :query => qs
31
+ }).parsed_response
32
+
33
+ rv = rv.uniq if options[:unique]
34
+ rv = rv.sort if options[:sort]
35
+
36
+ return rv
37
+ end
38
+
39
+ def find(filter, options={})
40
+ get("/devices/find/#{make_filter(filter)}").parsed_response
41
+ end
42
+
43
+ def save(id, data=nil, &block)
44
+ if block_given?
45
+ post("/devices/#{id}", {}, &block)
46
+ else
47
+ post("/devices/#{id}", {
48
+ :body => data
49
+ })
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ module Onering
2
+ class API
3
+ class Auth < API
4
+ def _check_type(type)
5
+ raise "Invalid authentication module object '#{type}'" unless %w{
6
+ users groups capabilities
7
+ }.include?(type.to_s)
8
+ end
9
+
10
+ def show(type, id='current')
11
+ _check_type(type)
12
+ get("#{type}/#{id}").parsed_response
13
+ end
14
+
15
+ def list(type, field='id', options={
16
+ :unique => true,
17
+ :sort => true,
18
+ :filter => nil
19
+ })
20
+ _check_type(type)
21
+ rv = get("#{type}/list").parsed_response.collect{|i| i[field.to_s] }
22
+ rv = rv.uniq if options[:unique]
23
+ rv = rv.sort if options[:sort]
24
+ rv
25
+ end
26
+
27
+ def save(type, id, data)
28
+ _check_type(type)
29
+ post("#{type}/#{id}", {
30
+ :body => data
31
+ }).parsed_response
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,70 @@
1
+ module Onering
2
+ class API
3
+ class AutomationRequests < API
4
+ def summary(fields)
5
+ get("/automation/requests/summary/#{[*fields].join('/')}").parsed_response
6
+ end
7
+
8
+ def find_by_status(status)
9
+ get("/automation/requests/status/#{status}").parsed_response
10
+ end
11
+
12
+ def show(id)
13
+ get("/automation/requests/#{id}").parsed_response
14
+ end
15
+
16
+ def requeue(id)
17
+ get("/automation/requests/#{id}/requeue").parsed_response
18
+ end
19
+
20
+ def flush_queue()
21
+ get("/automation/requests/flush").parsed_response
22
+ end
23
+
24
+ def purge()
25
+ get("/automation/requests/purge").parsed_response
26
+ end
27
+
28
+ def requeue_all_failed()
29
+ get("/automation/requests/requeue").parsed_response
30
+ end
31
+ end
32
+
33
+
34
+ # -----------------------------------------------------------------------------
35
+ class AutomationJobs < API
36
+ def list()
37
+ get("/automation/jobs/list").parsed_response
38
+ end
39
+
40
+ def show(name)
41
+ get("/automation/jobs/#{name}").parsed_response
42
+ end
43
+
44
+ def requests_waiting(name)
45
+ get("/automation/jobs/#{name}/waiting").parsed_response
46
+ end
47
+
48
+ def run(name, options={}, &block)
49
+ if block_given?
50
+ post("/automation/jobs/#{name}/run", {
51
+ :query => options
52
+ }, &block).parsed_response
53
+ else
54
+ get("/automation/jobs/#{name}/run", {
55
+ :query => options
56
+ }).parsed_response
57
+ end
58
+ end
59
+ end
60
+
61
+ # -----------------------------------------------------------------------------
62
+ class AutomationTasks < API
63
+ def run(name, options={})
64
+ get("/automation/tasks/#{name}/run", {
65
+ :query => options
66
+ }).parsed_response
67
+ end
68
+ end
69
+ end
70
+ end