fluent-plugin-cloudstack 0.0.1

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: 2c162238913dc3df257fced1b4511542da70bcc8
4
+ data.tar.gz: ff71b4d47e21628a944fc89626ff2c2d069a7467
5
+ SHA512:
6
+ metadata.gz: 5e73c124caa441d3453bf58143d466bae661dcc906c721d0ab8b4ad1b0547300db7c57e72a654876532b2a3e86ced2c2b0979c0094ca2f35d58456376fb2614a
7
+ data.tar.gz: c31c87c1f4d276742f9de37d67df857f6a9642188f8079f1b9622cf516227c77e4a50baacbcd6af8dd7eec5acb9c88394184ffc261e1a82ad6bb14a61ee641c0
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+ vendor/*
20
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fluent-plugin-cloudstack (0.0.1)
5
+ eventmachine
6
+ fluentd (>= 0.10.7)
7
+ fog
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ builder (3.2.2)
13
+ cool.io (1.1.1)
14
+ iobuffer (>= 1.0.0)
15
+ eventmachine (1.0.3)
16
+ excon (0.27.6)
17
+ fluentd (0.10.39)
18
+ cool.io (~> 1.1.1)
19
+ http_parser.rb (~> 0.5.1)
20
+ json (>= 1.4.3)
21
+ msgpack (>= 0.4.4, < 0.6.0, != 0.5.3, != 0.5.2, != 0.5.1, != 0.5.0)
22
+ yajl-ruby (~> 1.0)
23
+ fog (1.16.0)
24
+ builder
25
+ excon (~> 0.27.0)
26
+ formatador (~> 0.2.0)
27
+ mime-types
28
+ multi_json (~> 1.0)
29
+ net-scp (~> 1.1)
30
+ net-ssh (>= 2.1.3)
31
+ nokogiri (~> 1.5)
32
+ ruby-hmac
33
+ unicode (~> 0.4.4)
34
+ formatador (0.2.4)
35
+ http_parser.rb (0.5.3)
36
+ iobuffer (1.1.2)
37
+ json (1.8.1)
38
+ mime-types (1.25)
39
+ mini_portile (0.5.2)
40
+ msgpack (0.5.6)
41
+ multi_json (1.8.2)
42
+ net-scp (1.1.2)
43
+ net-ssh (>= 2.6.5)
44
+ net-ssh (2.7.0)
45
+ nokogiri (1.6.0)
46
+ mini_portile (~> 0.5.0)
47
+ rake (10.1.0)
48
+ ruby-hmac (0.4.0)
49
+ unicode (0.4.4)
50
+ yajl-ruby (1.1.0)
51
+
52
+ PLATFORMS
53
+ ruby
54
+
55
+ DEPENDENCIES
56
+ fluent-plugin-cloudstack!
57
+ rake
data/README.textile ADDED
@@ -0,0 +1,83 @@
1
+ h1. Fluent::Plugin::CloudStack
2
+
3
+ Fluentd input plugin to get usages and events from CloudStack API.
4
+
5
+ * usages
6
+ ** instance_usage
7
+ ** memory_usage
8
+ ** root_volume_usage
9
+ ** data_volume_usage
10
+ ** usages_per_service_offering
11
+ ** usages_per_disk_offering
12
+ * event
13
+
14
+
15
+ h2. Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ <pre>
20
+ gem 'fluent-plugin-cloudstack'
21
+ </pre>
22
+
23
+ Or install it yourself as:
24
+
25
+ <pre>
26
+ $ gem install fluent-plugin-cloudstack
27
+ </pre>
28
+
29
+ Or use td-agent : (on Ubuntu12.04)
30
+
31
+ <pre>
32
+ $ sudo /usr/lib/fluent/ruby/bin/fluent-gem install fluent-plugin-cloudstack
33
+ </pre>
34
+
35
+
36
+
37
+ h2. Configuration
38
+
39
+ <pre>
40
+ <source>
41
+ type cloudstack
42
+ host $cloudtack_host
43
+ apikey $cloudstack_apikey
44
+ secretkey $cloustack_secretkey
45
+
46
+ # optional
47
+ protocol $cloudstack_protocol_scheme # https or http, default https
48
+ path $cloudstack_path # default /client/api
49
+ port $cloudstack_port # default 443
50
+ interval $get_interval_sec # min 300, default 300
51
+ ssl $cloudtack_api_ssl # true or false, default true
52
+ domain_id $cloudstack_domain_id
53
+
54
+ tag $fluentd_tag # default cloudstack
55
+ </source>
56
+ </pre>
57
+
58
+
59
+
60
+ h2. Data Example
61
+
62
+ <pre>
63
+ 20131027T193928+0000 cloudstack.usages {"instances_usage":1,
64
+ "memory_usage":512,
65
+ "cpu_usage":1,
66
+ "root_volume_usage":16106127360,
67
+ "data_volume_usage":42949672960,
68
+ "usages_per_service_offering":{"t1.micro":1},
69
+ "usages_per_disk_offering":{"Datadisk 40GB":1}}
70
+
71
+ 20130507T041336+0000 cloudstack.event {"id":"xxxxxxx-4e64-4fa5-8045-5ecffb7e2417",
72
+ "username":"clnxxxxxxxxx",
73
+ "type":"USER.LOGIN",
74
+ "level":"INFO",
75
+ "description":"user has logged in from IP Address xxx.xxx.xxx.xxx",
76
+ "account":"clnxxxxxxx",
77
+ "domainid":"xxxxxxxx-dcc3-486b-90e8-02c514c93d1f",
78
+ "domain":"cln10000004",
79
+ "created":"2013-05-07T13:13:36+0900",
80
+ "state":"Completed",
81
+ "parentid":"0"}
82
+ </pre>
83
+
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.test_files = Dir['test/plugin/*.rb']
9
+ test.ruby_opts = ['-rubygems'] if defined? Gem
10
+ test.ruby_opts << '-I.'
11
+ test.verbose = true
12
+ end
13
+
14
+ task :default => :test
15
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "fluent-plugin-cloudstack"
6
+ gem.version = File.read("VERSION").strip
7
+ gem.authors = ["Yuichi UEMURA"]
8
+ gem.email = ["yuichi.u@gmail.com"]
9
+ gem.homepage = "https://github.com/u-ichi/fluent-plugin-cloudstack"
10
+ gem.summary = %q{cloudstack plugin for fluentd, a log collector}
11
+ gem.description = %q{cloudstack plugin for fluentd, a log collector}
12
+
13
+ gem.files = `git ls-files`.split("\n")
14
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ gem.require_paths = ["lib"]
17
+
18
+ gem.add_dependency "fluentd", ">= 0.10.7"
19
+ gem.add_dependency "fog"
20
+ gem.add_dependency "eventmachine"
21
+
22
+ gem.add_development_dependency "rake"
23
+ end
24
+
@@ -0,0 +1,175 @@
1
+ module Fluent
2
+ class CloudStackInput < Input
3
+ Fluent::Plugin.register_input("cloudstack", self)
4
+
5
+ INTERVAL_MIN = 300
6
+
7
+ config_param :host
8
+ config_param :path, :default =>'/client/api'
9
+ config_param :protocol, :default =>'https'
10
+ config_param :port, :default =>443
11
+ config_param :apikey
12
+ config_param :secretkey
13
+ config_param :domain_id, :default => nil
14
+ config_param :interval, :default => INTERVAL_MIN
15
+
16
+ config_param :tag, :string, :default => "cloudstack"
17
+ config_param :ssl, :bool, :default => true
18
+
19
+ attr_writer :before_events
20
+
21
+ def initialize
22
+ require "fog"
23
+ require "eventmachine"
24
+ init_eventmachine
25
+
26
+ @before_events_filepath = "logs/before_events.yml"
27
+
28
+ if File.exist?(@before_events_filepath)
29
+ @before_events = YAML.load_file(@before_events_filepath)
30
+ else
31
+ @before_events = nil
32
+ end
33
+
34
+ super
35
+ end
36
+
37
+ def configure(conf)
38
+ super
39
+ @conf = conf
40
+ unless @host && @apikey && @secretkey
41
+ raise ConfigError, "'host' and 'apikey' and 'secretkey' must be all specified."
42
+ end
43
+
44
+ if @interval < INTERVAL_MIN
45
+ raise ConfigError, "'interval' must be over #{INTERVAL_MIN}."
46
+ end
47
+ end
48
+
49
+ def start
50
+ super
51
+ run_reactor_thread
52
+ @thread = Thread.new(&method(:run))
53
+ $log.info "listening cloudstack api on #{@host}"
54
+ end
55
+
56
+ def shutdown
57
+ super
58
+ @thread.join
59
+ EM.stop if EM.reactor_running?
60
+ @reactor_thread.join if @reactor_thread
61
+ end
62
+
63
+ def run
64
+ EM.add_periodic_timer(@interval) do
65
+ emit_new_events
66
+ emit_usages
67
+ end
68
+ end
69
+
70
+ def emit_new_events
71
+ new_events = get_new_events
72
+ output_tag = "#{@tag}.event"
73
+ new_events.each do |event|
74
+ time = Time.parse(event["created"]).to_i
75
+ Engine.emit(output_tag, time, event)
76
+ end
77
+ end
78
+
79
+ def emit_usages
80
+ usages = get_usages
81
+ time = Engine.now
82
+ output_tag = "#{@tag}.usages"
83
+ Engine.emit(output_tag, time, usages)
84
+ end
85
+
86
+ def get_new_events
87
+ if @before_events
88
+ startdate = Time.parse(@before_events[0]["created"])
89
+ event_responses = cs.list_events(:startdate => startdate.strftime("%Y-%m-%d %H:%M:%S"), :domainid => @domain_id)
90
+ events = Array.new
91
+ event_responses["listeventsresponse"]["event"].each do |event|
92
+ unless Time.parse(event["created"]) == startdate
93
+ events.push event
94
+ end
95
+ end
96
+ else
97
+ events = cs.list_events(:domainid => @domain_id)["listeventsresponse"]["event"]
98
+ end
99
+
100
+ if events.size > 0
101
+ File.write(@before_events_filepath, events.to_yaml)
102
+ @before_events = events
103
+ end
104
+
105
+ events
106
+ end
107
+
108
+ def get_usages
109
+ usages_per_service_offering = Hash.new(0)
110
+ usages_per_disk_offering = Hash.new(0)
111
+ memory_usage = 0
112
+ cpu_usage = 0
113
+ root_volume_usage = 0
114
+ data_volume_usage = 0
115
+
116
+ vms_responses = cs.list_virtual_machines(:domainid=>@domain_id)
117
+ vms = vms_responses["listvirtualmachinesresponse"]["virtualmachine"]
118
+ vms.each do |vm|
119
+ memory_usage += vm["memory"].to_i
120
+ cpu_usage += vm["cpunumber"].to_i
121
+ usages_per_service_offering[vm["serviceofferingname"]] += 1
122
+ end
123
+
124
+ volumes_responses = cs.list_volumes(:domainid=>@domain_id)
125
+ volumes = volumes_responses["listvolumesresponse"]["volume"]
126
+ volumes.each do |volume|
127
+ case volume["type"]
128
+ when "ROOT"
129
+ root_volume_usage += volume["size"]
130
+ when "DATADISK"
131
+ data_volume_usage += volume["size"]
132
+ usages_per_disk_offering[volume["diskofferingname"]] += 1
133
+ end
134
+ end
135
+
136
+ results = {:vm_usage => vms.size,
137
+ :memory_usage => memory_usage,
138
+ :cpu_usage => cpu_usage,
139
+ :root_volume_usage => root_volume_usage,
140
+ :data_volume_usage => data_volume_usage,
141
+ :usages_per_service_offering => usages_per_service_offering,
142
+ :usages_per_disk_offering => usages_per_disk_offering,
143
+ }
144
+ end
145
+
146
+ def cs
147
+ @@cs ||= Fog::Compute.new(
148
+ :provider => 'CloudStack',
149
+ :cloudstack_api_key => @apikey,
150
+ :cloudstack_secret_access_key => @secretkey,
151
+ :cloudstack_host => @host,
152
+ :cloudstack_port => @port,
153
+ :cloudstack_path => @path,
154
+ :cloudstack_scheme => @protocol,
155
+ )
156
+ end
157
+
158
+ private
159
+
160
+ def run_reactor_thread
161
+ unless EM.reactor_running?
162
+ @reactor_thread = Thread.new { EM.run }
163
+ end
164
+ end
165
+
166
+ def init_eventmachine
167
+ EM.epoll; EM.kqueue
168
+ EM.error_handler do |ex|
169
+ $log.error("Eventmachine problem")
170
+ $log.error("#{ex}, tracelog : \n#{ex.backtrace.join("\n")}")
171
+ end
172
+ end
173
+ end
174
+ end
175
+
@@ -0,0 +1,48 @@
1
+ require 'test/unit'
2
+ require 'test_helper'
3
+ require 'lib/fluent/plugin/in_cloudstack.rb'
4
+ require 'pp'
5
+
6
+
7
+ class CloudStackInputTest < Test::Unit::TestCase
8
+ def setup
9
+ Fluent::Test.setup
10
+ end
11
+
12
+ CONFIG = %[
13
+ host localhost
14
+ apikey hoge
15
+ secretkey fuga
16
+ domain_id domain_id
17
+ ]
18
+
19
+
20
+ def create_driver(conf=CONFIG)
21
+ Fluent::Test::InputTestDriver.new(Fluent::CloudStackInput).configure(conf)
22
+ end
23
+
24
+ def test_configure
25
+ d = create_driver
26
+ assert_equal 'localhost', d.instance.host
27
+ assert_equal 'hoge', d.instance.apikey
28
+ assert_equal 'fuga', d.instance.secretkey
29
+ assert_equal 'domain_id', d.instance.domain_id
30
+ end
31
+
32
+
33
+ def test_get_events
34
+ d = create_driver
35
+
36
+ # d.instance.before_events = before_events_stub
37
+ end
38
+
39
+ def test_get_usage
40
+ d = create_driver
41
+
42
+ # d.instance.get_usages
43
+ end
44
+
45
+ end
46
+
47
+
48
+
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'test/unit'
13
+
14
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+ require 'fluent/test'
17
+
18
+ unless ENV.has_key?('VERBOSE')
19
+ nulllogger = Object.new
20
+ nulllogger.instance_eval {|obj|
21
+ def method_missing(method, *args)
22
+ # pass
23
+ end
24
+ }
25
+ $log = nulllogger
26
+ end
27
+
28
+
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-cloudstack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Yuichi UEMURA
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.10.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.10.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: fog
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: eventmachine
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: cloudstack plugin for fluentd, a log collector
70
+ email:
71
+ - yuichi.u@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - Gemfile.lock
79
+ - README.textile
80
+ - Rakefile
81
+ - VERSION
82
+ - fluent-plugin-cloudstack.gemspec
83
+ - lib/fluent/plugin/in_cloudstack.rb
84
+ - test/plugin/in_cloudstack.rb
85
+ - test/test_helper.rb
86
+ homepage: https://github.com/u-ichi/fluent-plugin-cloudstack
87
+ licenses: []
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.1.10
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: cloudstack plugin for fluentd, a log collector
109
+ test_files:
110
+ - test/plugin/in_cloudstack.rb
111
+ - test/test_helper.rb