gaddygaddy 0.1.78

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6179815ad86f1edb1a7571347aecf67360b39176
4
+ data.tar.gz: a9fbac4944dcd4a58676f6cf866c1f687b1fa935
5
+ SHA512:
6
+ metadata.gz: 4cb37474da862c7cfe4900f4148469f3368d72e64d6eea01201e4200025bf9c688c04d6744a9efc6320ea617f467e8968fa5b87d8bf549e7e2681ad156879327
7
+ data.tar.gz: b5b47bc9e70fe9608ec09fb0aa5a0857cb3d0741ecdf019eb14fe8e375f5b59b0baacdb4f105a9d713b56cd065ad5c558a047633bc3a6208b9768c8658040fbc
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # ./update_cookbook_versions
4
+ #
5
+
6
+ require 'rubygems'
7
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
8
+ require 'gaddygaddy-client'
9
+
10
+ GaddyGaddy_Client.new.run
data/bin/interval ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+
4
+ require 'rubygems'
5
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
6
+ require 'interval'
7
+
8
+ Interval.new.run
File without changes
data/conf/gaddy.yml ADDED
@@ -0,0 +1,2 @@
1
+ file_dir: /conf
2
+ speech_enabled: true
data/conf/log4r.yml ADDED
@@ -0,0 +1,47 @@
1
+ log4r_config:
2
+ # define all loggers ...
3
+ loggers:
4
+ - name : gaddygaddy-client
5
+ level : DEBUG
6
+ trace : 'false'
7
+ outputters:
8
+ - stderr
9
+ - stdout
10
+ - name : default
11
+ level : DEBUG
12
+ trace : 'false'
13
+ outputters:
14
+ - stderr
15
+ - stdout
16
+ - name : interval
17
+ level : DEBUG
18
+ trace : 'false'
19
+ outputters:
20
+ - stderr
21
+ - stdout
22
+ outputters:
23
+ - type : StderrOutputter
24
+ name : stderr
25
+ level : WARN
26
+ formatter:
27
+ date_pattern: '%y%m%d %H:%M:%S'
28
+ pattern : "[%5l] %d :: %m"
29
+ type : PatternFormatter
30
+
31
+ - type : StdoutOutputter
32
+ name : stdout
33
+ level : DEBUG
34
+ formatter:
35
+ date_pattern: '%y%m%d %H:%M:%S'
36
+ pattern : "[%5l] %d :: %m"
37
+ type : PatternFormatter
38
+
39
+ - type : StderrOutputter
40
+ name : stderr_test
41
+ level : ERROR
42
+ formatter:
43
+ date_pattern: '%y%m%d %H:%M:%S'
44
+ # Added 'M' and 't' here - they are slow, but we're not calling unless we need to
45
+ pattern : "[%5l] %d :: %M :: %t"
46
+ type : PatternFormatter
47
+
data/conf/test.yml ADDED
@@ -0,0 +1 @@
1
+ file_dir: ../../tmp/
@@ -0,0 +1,60 @@
1
+ #
2
+ # Name:
3
+ # device_data.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ # Will handle data about the client like node info from Ohai that will tell everything like ip-address, macaddress,
10
+ # hw config etc. The data will be sent to the GaddyGaddy service
11
+ #
12
+ # Copyright (c) 2013 GaddyGaddy
13
+ #
14
+ # All rights reserved.
15
+ #
16
+
17
+ require_relative '../logging/logging'
18
+ require 'ohai'
19
+
20
+ class DeviceInfo
21
+ include Logging
22
+ extend Logging
23
+
24
+ def initialize(host, gg_config)
25
+ @host = host
26
+ @gg_config = gg_config
27
+ end
28
+
29
+ # Give the host name set previous
30
+ def host
31
+ @host
32
+ end
33
+
34
+ def gg_config
35
+ @gg_config
36
+ end
37
+
38
+ # Get data about the client by using the Ohai component developed by Opscode
39
+ def get_ohai_data
40
+ Ohai::Config[:plugin_path] << '/etc/chef/ohai_plugins'
41
+ ohai_system = Ohai::System.new
42
+ ohai_system.all_plugins
43
+ ohai_system.data
44
+ end
45
+
46
+ # Get the device data, if the data does not exist get it from Ohai
47
+ def data
48
+ @data||=get_ohai_data
49
+ end
50
+
51
+ # Will post the device data to the client service
52
+ def post
53
+ url = Request.get_base_url(host) + "/device/set_device_data/1/#{gg_config.config[:user_id_salt]}/#{gg_config.config[:device_id]}/#{gg_config.config[:token]}"
54
+ logger.debug "Will post this ohai data:\n #{data}"
55
+ response = Request.client_service_post url, :ohai_data => data
56
+ logger.debug "The response for the request is #{response} #{response.class}"
57
+ raise JCouldNotPostClientDataException.new({:message=> "Could not post data to the gaddygaddy service, error code is #{response.body}"}) unless response[:status].to_i == 0
58
+ end
59
+
60
+ end
@@ -0,0 +1,98 @@
1
+ #
2
+ # Name:
3
+ # chef_files.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ #
10
+ #
11
+
12
+
13
+ DEFAULT_FILE_HOST_PORT = 80
14
+
15
+ require_relative '../utils/run'
16
+
17
+ class ChefFiles
18
+
19
+ include Logging
20
+
21
+ def initialize(config, ap_host, chef_dir)
22
+ @config = config
23
+ @ap_host = ap_host
24
+ @chef_dir = chef_dir
25
+ end
26
+
27
+ # Get the version of cookbook installed at the system
28
+
29
+ def installed_cookbook_version
30
+ installed_versions = Dir.glob(File.join(@chef_dir, 'cookbooks_version_[0-9]*'))
31
+ installed_versions.size > 0 ? installed_versions.map{|file| File.basename(file.split('_')[2])}.max : 0
32
+ end
33
+
34
+ def create_version_file(version)
35
+ File.open(File.join(@chef_dir,'cookbooks_version_' + version.to_s), "w") do |f|
36
+ f.puts "Version: #{version}"
37
+ f.puts "Created at #{Time.now}"
38
+ f.close
39
+ end
40
+ end
41
+
42
+ def get_cookbook_version
43
+ response = Request.client_service_get @ap_host, "/chef/cookbooks_version/1/#{@config.user_id_salt}/#{@config.device_id}/#{@config.token}"
44
+ raise "Could not get cookbook version" unless response['cookbooks_version']
45
+ logger.debug "Got cookbook version: #{response}"
46
+ response['cookbooks_version']
47
+ end
48
+
49
+ # Will return cookbook_uri depending on cookbook version
50
+ # -1 is not supported in production
51
+ def cookbook_path(prod_version, version)
52
+ if prod_version
53
+ '/' + URI.encode("pkg/gg_chef_#{version}.tar.gz")
54
+ else
55
+ '/chef/latest_cookbook'
56
+ end
57
+ end
58
+
59
+ #
60
+ # Will check version of installed cookbooks and update if it's old
61
+ #
62
+ def get_cookbooks(file_host, cookbooks_version)
63
+ version = cookbooks_version ? cookbooks_version : get_cookbook_version.to_s
64
+ installed_version = installed_cookbook_version.to_s
65
+ prod_version = version.split('_')[0].to_s != '0'
66
+ return if installed_version.size > 0 && (installed_version.to_s == version.to_s) && prod_version
67
+ tmp_file = "/tmp/cookbooks-#{version}.tar.gz"
68
+ port = DEFAULT_FILE_HOST_PORT
69
+ file_host = prod_version ? file_host : @ap_host
70
+ # The file host should be without http or port
71
+ file_host = file_host.split("://")[1] if file_host.index("://")
72
+ file_host,port = file_host.split(":") if file_host.index(":")
73
+ Net::HTTP.start(file_host, port) do |http|
74
+ begin
75
+ http.read_timeout = 500
76
+ file = open(tmp_file, 'wb')
77
+ logger.debug "Will request the cookbooks files from http://#{file_host}:#{port}#{cookbook_path(prod_version, version)}"
78
+ result = http.request_get(cookbook_path(prod_version, version)) do |response|
79
+ response.read_body do |segment|
80
+ file.write(segment)
81
+ end
82
+ end
83
+ logger.debug "The tar cookbook request response was #{result.inspect}"
84
+ ensure
85
+ file.close
86
+ end
87
+ end
88
+ logger.debug "Will untar the file to #{@chef_dir} and then remove file #{tmp_file}"
89
+ FileUtils.mkdir_p @chef_dir
90
+ # Check that the tar file is valid first
91
+ cmd = "tar --test-label -zvf #{tmp_file} && rm -rf #{@chef_dir}/* && tar -C #{@chef_dir} -zxvf #{tmp_file}"
92
+ run_cmd cmd
93
+ create_version_file version
94
+ cmd_remove = "rm #{tmp_file}"
95
+ run_cmd cmd_remove
96
+ end
97
+
98
+ end
File without changes
@@ -0,0 +1,26 @@
1
+ #
2
+ # Name:
3
+ # espeak.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ # Will manage espeak
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+
16
+ require 'stringex'
17
+
18
+ class ESpeak
19
+
20
+ def self.speak to_speak
21
+ file_name = to_speak.to_ascii.replace_whitespace('-').gsub('/','-')
22
+ wav_file = "/tmp/#{file_name}.wav"
23
+ `/usr/bin/espeak -w #{wav_file} "#{to_speak}"` unless File.exist?(wav_file)
24
+ `/usr/bin/aplay #{wav_file}`
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ #
2
+ # Name:
3
+ # log_data.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ # Will get log_data from a log file
9
+ #
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+
16
+ class LogData
17
+
18
+ #
19
+ # Get a specific number of lines from a log file
20
+ #
21
+ def self.get_log_data(log_file_name, lines)
22
+ unless log_file_name.index('/')
23
+ log_file_name = log_file_name + '.log' unless log_file_name[-4..-1] == '.log'
24
+ log_file_name = "/opt/log/#{log_file_name[0..-5]}/#{log_file_name}"
25
+ end
26
+ raise "File #{log_file_name} does not exist" unless File.exist?(log_file_name)
27
+ cmd = "tail -n #{lines} #{log_file_name}"
28
+ exit_code, stdout = systemu cmd
29
+ if exit_code.success?
30
+ stdout
31
+ else
32
+ 'Could not read log_data from ' + log_file_name
33
+ end
34
+ end
35
+
36
+ #
37
+ # Get the time when the log file was last modified
38
+ #
39
+ def self.get_log_file_time(log_file_name)
40
+ File.mtime(log_file_name).to_s
41
+ end
42
+ end
@@ -0,0 +1,32 @@
1
+ #
2
+ # Name:
3
+ # espeak.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ # Will notify via the speakers
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+
16
+ require_relative '../espeak'
17
+
18
+ module Notification
19
+ class ESpeakNotification
20
+
21
+ def self.espeak?
22
+ `whereis espeak`.index('bin')
23
+ end
24
+
25
+ def self.notify(event, message_text)
26
+ if espeak?
27
+ ESpeak.speak message_text
28
+ end
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,43 @@
1
+ #
2
+ # Name:
3
+ # file.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ # Will write the notification to a file
9
+ #
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+
16
+ module Notification
17
+
18
+ class FileNotification
19
+
20
+ def self.file_dir= file_dir
21
+ @file_dir = file_dir
22
+ end
23
+
24
+ def self.file_dir
25
+ @file_dir
26
+ end
27
+
28
+ def self.notify(event, message_text)
29
+ f=File.open(File.join(file_dir,'gaddy_notification.log'), 'a')
30
+ f.write "#{event['event_time'].strftime('%Y-%m-%d %H:%M')} #{event['type']} #{message_text}\n"
31
+ f.fsync
32
+ f.close
33
+ end
34
+
35
+ # This will check if the text is already in the log file
36
+ def self.text_in_log_file message
37
+ log_file=File.join(file_dir,'gaddy_notification.log')
38
+ `/bin/grep '#{message}' #{log_file} `.strip.length > 0
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,36 @@
1
+ #
2
+ # Name:
3
+ # file.rb
4
+ #
5
+ # Created by: mansson
6
+ #
7
+ # Description:
8
+ # Will write the notification to a file
9
+ #
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+
16
+ module Notification
17
+
18
+ class FileNotification
19
+
20
+ def self.file_dir= file_dir
21
+ @file_dir = file_dir
22
+ end
23
+
24
+ def self.file_dir
25
+ @file_dir
26
+ end
27
+
28
+ def self.notify(event, message_text)
29
+ f=File.open(File.join(file_dir,'gaddy_notification.log'), 'w')
30
+ f.write "#{event['event_time'].strftime('%Y-%m-%d %H:%M')} #{event['type']} #{message_text}\n"
31
+ f.close
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,40 @@
1
+ #
2
+ # Name:
3
+ # sensu.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ #
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+
16
+ module Notification
17
+
18
+ SENSU_HOST = 'localhost'
19
+ SENSU_PORT = 3030
20
+
21
+ class Sensu
22
+ # To change this template use File | Settings | File Templates.
23
+ def self.notify(event, message_text)
24
+ report = {
25
+ :name => "gaddy_notification",
26
+ :output => event.to_json,
27
+ :status => 2,
28
+ :handler => 'send_event'
29
+ }
30
+
31
+ begin
32
+ s = TCPSocket.open(SENSU_HOST, SENSU_PORT)
33
+ s.print JSON.generate(report)
34
+ s.close
35
+ rescue Exception => e
36
+ puts e.message
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,25 @@
1
+ #
2
+ # Name:
3
+ # wall.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ #
10
+
11
+ module Notification
12
+ class Wall
13
+
14
+ def self.wall?
15
+ `whereis wall`.index('bin')
16
+ end
17
+
18
+ def self.notify(event, message_text)
19
+ if wall?
20
+ systemu("echo 'Gaddy says: #{message_text}'|wall")
21
+ end
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,73 @@
1
+ #
2
+ # Name:
3
+ # notification.rb
4
+ #
5
+ # Created by: GaddyGaddy
6
+ #
7
+ # Description:
8
+ #
9
+ #
10
+ #
11
+ # Copyright (c) 2013 GaddyGaddy
12
+ #
13
+ # All rights reserved.
14
+ #
15
+
16
+ require_relative '../logging/logging'
17
+ require_relative 'notification/file_notification'
18
+ require_relative 'notification/espeak'
19
+ require_relative 'notification/sensu'
20
+ require_relative 'notification/wall'
21
+ require 'i18n'
22
+
23
+ module Notification
24
+ class Send
25
+ include Logging
26
+
27
+ def initialize(options = {})
28
+ I18n.load_path += Dir[File.join(File.dirname(__FILE__), '..','..','locales', '*.yml').to_s]
29
+ @speech_enabled = options[:speech_enabled]
30
+ end
31
+
32
+ # Language is english for now, we need to add a language parameter to the user info or config for gaddygaddy
33
+ def language
34
+ 'en'
35
+ end
36
+
37
+ def event= event
38
+ @event = JSON.parse(event)
39
+ end
40
+
41
+ def event
42
+ @event
43
+ end
44
+
45
+ def message_as_text
46
+ logger.debug "Will create message from event #{event['message_key']}"
47
+ translated_text = I18n.t event['message_key'], {locale: language}
48
+ count_values = translated_text.split("%").count - 1
49
+ if event['message_values']||count_values > 0
50
+ if count_values == event['message_values'].length
51
+ translated_text % event['message_values']
52
+ else
53
+ raise "Mismatch between the text for #{event['message_key']} - #{translated_text} have #{count_values} %s and the size of event values array is #{event['message_values'].length}"
54
+ end
55
+ else
56
+ translated_text
57
+ end
58
+ end
59
+
60
+ # Will do notifications to different sources like log file, web site and even speak
61
+
62
+ def notify(device_id)
63
+ event['event_time'] = Time.now unless event['event_time']
64
+ event['device_id'] = device_id
65
+ # Need to test before we put stuff in log file
66
+ should_speak = ! Notification::FileNotification.text_in_log_file(message_as_text)
67
+ Notification::Wall.notify(event, message_as_text)
68
+ Notification::FileNotification.notify(event, message_as_text)
69
+ Notification::Sensu.notify(event, message_as_text)
70
+ Notification::ESpeakNotification.notify(event, message_as_text) if should_speak && @speech_enabled
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,4 @@
1
+
2
+ --This line, and those below, will be ignored--
3
+
4
+ M notification/file_notification.rb