bblib 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ require_relative 'attr'
2
+ require_relative 'hooks'
3
+ require_relative 'simple_serialize'
4
+
1
5
  module BBLib
2
6
 
3
7
  def self.to_hash obj
@@ -25,4 +29,16 @@ module BBLib
25
29
  return hash
26
30
  end
27
31
 
32
+ def self.named_args *args
33
+ args.last.is_a?(Hash) && args.last.keys.all?{|k|k.is_a?(Symbol)} ? args.last : Hash.new
34
+ end
35
+
36
+ def self.named_args! *args
37
+ if args.last.is_a?(Hash) && args.last.keys.all?{|k|k.is_a?(Symbol)}
38
+ args.delete_at(-1)
39
+ else
40
+ Hash.new
41
+ end
42
+ end
43
+
28
44
  end
@@ -0,0 +1,69 @@
1
+ module BBLib::Hooks
2
+
3
+ def method_added name
4
+ before_hooks_for(name).each do |hook|
5
+ next if before_hooked_methods[hook] && before_hooked_methods[hook].include?(name)
6
+ add_before_hook(name, hook)
7
+ end
8
+ after_hooks_for(name).each do |hook|
9
+ next if after_hooked_methods[hook] && after_hooked_methods[hook].include?(name)
10
+ add_after_hook(name, hook)
11
+ end
12
+ end
13
+
14
+ def before hook, *methods
15
+ methods.each{ |m| before_hooks[hook] = methods }
16
+ end
17
+
18
+ def before_hooks
19
+ @before_hooks ||= {}
20
+ end
21
+
22
+ def before_hooked_methods
23
+ @before_hooked_methods ||= {}
24
+ end
25
+
26
+ def before_hooks_for name
27
+ before_hooks.map{ |n, m| m.include?(name)? n : nil }.reject(&:nil?)
28
+ end
29
+
30
+ def add_before_hook method, hook
31
+ before_hooked_methods[hook] = Array.new unless before_hooked_methods[hook]
32
+ before_hooked_methods[hook] += [method]
33
+ original = instance_method(method)
34
+ define_method(method) do |*args, &block|
35
+ # puts "ARGS: #{args}"
36
+ method(hook).call
37
+ original.bind(self).call(*args, &block)
38
+ end
39
+ end
40
+
41
+ def after hook, *methods
42
+ methods.each{ |m| after_hooks[hook] = methods }
43
+ end
44
+
45
+ def after_hooks
46
+ @after_hooks ||= {}
47
+ end
48
+
49
+ def after_hooked_methods
50
+ @after_hooked_methods ||= {}
51
+ end
52
+
53
+ def after_hooks_for name
54
+ after_hooks.map{ |n, m| m.include?(name) ? n : nil }.reject(&:nil?)
55
+ end
56
+
57
+ def add_after_hook method, hook
58
+ after_hooked_methods[hook] = Array.new unless after_hooked_methods[hook]
59
+ after_hooked_methods[hook] += [method]
60
+ original = instance_method(method)
61
+
62
+ define_method(method) do |*args, &block|
63
+ rtr = original.bind(self).call(*args, &block)
64
+ method(hook).call
65
+ rtr
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,73 @@
1
+
2
+ module BBLib
3
+
4
+ class LazyClass
5
+ extend Hooks
6
+ extend Attr
7
+ attr_reader :_serialize_fields
8
+
9
+ def initialize *args
10
+ _pre_setup
11
+ lazy_setup
12
+ _lazy_init(*args)
13
+ end
14
+
15
+ def serialize
16
+ _serialize_fields.map do |name, h|
17
+ value = send(h[:method])
18
+ if !h[:always] && value == h[:ignore]
19
+ nil
20
+ else
21
+ [ name, value ]
22
+ end
23
+ end.reject(&:nil?).to_h
24
+ end
25
+
26
+ protected
27
+
28
+ def lazy_setup
29
+ # Instantiate necessary variables here
30
+ end
31
+
32
+ def _lazy_init *args
33
+ BBLib::named_args(*args).each do |k,v|
34
+ if self.respond_to?("#{k}=".to_sym)
35
+ send("#{k}=".to_sym, v)
36
+ end
37
+ end
38
+ lazy_init *args
39
+ custom_lazy_init BBLib::named_args(*args), *args
40
+ end
41
+
42
+ def _pre_setup
43
+ self.methods.each do |m|
44
+ if m.to_s.start_with?('__reset_')
45
+ send(m) rescue nil
46
+ end
47
+ end
48
+ end
49
+
50
+ def lazy_init *args
51
+ # Define custom initialization here...
52
+ end
53
+
54
+ def custom_lazy_init *args
55
+ # Left in for legacy support...don't use this!
56
+ end
57
+
58
+ def serialize_method name, method = nil, ignore: nil, always: false
59
+ return if method == :serialize || name == :serialize && method.nil?
60
+ _serialize_fields[name.to_sym] = {
61
+ method: (method.nil? ? name.to_sym : method.to_sym),
62
+ ignore: ignore,
63
+ always: always
64
+ }
65
+ end
66
+
67
+ def _serialize_fields
68
+ @_serialize_fields ||= Hash.new
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,16 @@
1
+ module BBLib
2
+
3
+ def self.in_opal?
4
+ RUBY_ENGINE == 'opal'
5
+ end
6
+
7
+ end
8
+
9
+ if BBLib.in_opal?
10
+ class Element
11
+
12
+ alias_native :replace_with, :replaceWith
13
+ alias_native :prepend
14
+ alias_native :get_context, :getContext
15
+ end
16
+ end
@@ -0,0 +1,93 @@
1
+ require_relative 'bbsys'
2
+
3
+ module BBLib
4
+
5
+ module OS
6
+
7
+ def self.os
8
+ return :windows if windows?
9
+ return :mac if mac?
10
+ return :linux if linux?
11
+ end
12
+
13
+ def self.windows?
14
+ builds = ['mingw', 'mswin', 'cygwin', 'bccwin']
15
+ !(/#{builds.join('|')}/i =~ RUBY_PLATFORM).nil?
16
+ end
17
+
18
+ def self.linux?
19
+ !windows? && !mac?
20
+ end
21
+
22
+ def self.unix?
23
+ !windows?
24
+ end
25
+
26
+ def self.mac?
27
+ builds = ['darwin']
28
+ !(/#{builds.join('|')}/i =~ RUBY_PLATFORM).nil?
29
+ end
30
+
31
+ def self.os_info
32
+ if windows?
33
+ data = `wmic os get manufacturer,name,organization,osarchitecture,version /format:list`
34
+ data = data.split("\n").reject{ |r| r.strip == '' }.map do |m|
35
+ spl = m.split('=')
36
+ [spl.first.to_clean_sym.downcase, spl[1..-1].join('=')]
37
+ end.to_h
38
+ data[:name] = data[:name].split('|').first
39
+ data[:osarchitecture] = data[:osarchitecture].extract_integers.first
40
+ data.hpath_move( 'osarchitecture' => 'bits' )
41
+ data[:host] = `hostname`.strip
42
+ data[:os] = os
43
+ data
44
+ else
45
+ release = {}
46
+ begin
47
+ # First attempt to get release info uses lsb_release
48
+ release = `lsb_release -a`.split("\n").map do |l|
49
+ spl = l.split(':')
50
+ [
51
+ spl.first.downcase.to_clean_sym,
52
+ spl[1..-1].join(':').strip
53
+ ]
54
+ end.to_h
55
+ release.hpath_move('description' => 'name', 'release' => 'name', 'distributor_id' => 'manufacturer')
56
+ rescue
57
+ # Try finding the release file and parsing it instead of lsb_release
58
+ begin
59
+ release = `cat /etc/*release`
60
+ .split("\n")
61
+ .reject{ |l| !(l.include?(':') || l.include?('=')) }
62
+ .map{|l| l.msplit('=',':') }
63
+ .map{ |a| [a.first.downcase.to_clean_sym, a[1..-1].join(':').uncapsulate] }
64
+ .to_h
65
+ rescue
66
+ # Both attempts failed
67
+ end
68
+ end
69
+ {
70
+ release: `uname -r`.strip,
71
+ bits: `uname -r` =~ /x86_64/i ? 64 : 32,
72
+ host: `uname -n`.strip,
73
+ os: os
74
+ }.merge(release)
75
+ end
76
+ end
77
+
78
+ # The following is Windows specific code
79
+ if windows?
80
+
81
+ def self.parse_wmic cmd
82
+ `#{cmd} /format:list`
83
+ .split("\n\n\n").reject(&:empty?)
84
+ .map{ |l| l.split("\n\n")
85
+ .map{ |l| spl = l.split('='); [spl.first.strip.downcase.to_clean_sym, spl[1..-1].join('=').strip ] }.to_h
86
+ }.reject(&:empty?)
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,238 @@
1
+
2
+
3
+
4
+ module BBLib
5
+ module OS
6
+
7
+ def self.cpu_usages
8
+ if windows?
9
+ {
10
+ total: `wmic cpu get loadpercentage /format:value`.extract_numbers.first.to_f
11
+ }
12
+ elsif linux? || mac?
13
+ system_stats[:cpu]
14
+ else
15
+ nil
16
+ end
17
+ end
18
+
19
+ def self.uptime
20
+ if windows?
21
+ uptime = `net statistics server`.split("\n").find{|l| l.start_with?('Statistics since ')}.split(/since /i).last.strip
22
+ Time.now - Time.strptime(uptime, '%m/%d/%Y %l:%M:%S %p')
23
+ else
24
+ `cat /proc/uptime`.extract_numbers.first
25
+ end
26
+ end
27
+
28
+ def self.cpu_used_p
29
+ cpu_usages[:total]
30
+ end
31
+
32
+ def self.cpu_free_p
33
+ 100 - cpu_used
34
+ end
35
+
36
+ def self.mem_total
37
+ if windows?
38
+ `wmic computersystem get TotalPhysicalMemory`.extract_numbers.first / 1024.0
39
+ elsif linux?
40
+ system_stats.hpath('memory.total')
41
+ else
42
+ nil
43
+ end
44
+ end
45
+
46
+ def self.mem_used
47
+ mem_total.to_f - mem_free.to_f
48
+ end
49
+
50
+ def self.mem_used_p
51
+ (mem_used.to_f / mem_total.to_f) * 100.0
52
+ end
53
+
54
+ def self.mem_free
55
+ if windows?
56
+ `wmic os get freephysicalmemory /format:value`.extract_numbers.first
57
+ elsif linux?
58
+ system_stats.hpath('memory.free')
59
+ else
60
+ nil
61
+ end
62
+ end
63
+
64
+ def self.mem_free_p
65
+ (mem_free.to_f / mem_total.to_f) * 100.0
66
+ end
67
+
68
+ def self.system_stats
69
+ if windows?
70
+ memfree = mem_free
71
+ memtotal = mem_total
72
+ memused = memtotal - memfree
73
+ {
74
+ cpu: cpu_usages,
75
+ memory: {
76
+ free: memfree,
77
+ used: memused,
78
+ total: memtotal,
79
+ free_p: (memfree / memtotal.to_f) * 100,
80
+ used_p: (memused / memtotal.to_f) * 100
81
+ },
82
+ uptime: uptime
83
+ }
84
+ else
85
+ stats = `top -b -n2 -d 0.1`.split("\n")
86
+ cpu = stats.find_all{|l| l =~ /\A\%?Cpu\(s\)/i }.last.extract_numbers
87
+ loads = stats.find_all{|l| l =~ / load average\: /i }.last.scan(/load average:.*/i).first.extract_numbers
88
+ mem = stats.find_all{|l| l =~ /KiB Mem|Mem\:/i }.last.extract_numbers
89
+ time = `cat /proc/uptime`.extract_numbers
90
+ {
91
+ cpu: {
92
+ user: cpu[0],
93
+ system: cpu[1],
94
+ nice: cpu[2],
95
+ total: cpu[0..2].inject(0){ |sum, v| sum += v.to_f },
96
+ idle: cpu[3],
97
+ wait: cpu[4],
98
+ hardware_interrupts: cpu[5],
99
+ software_interrupts: cpu[6],
100
+ hypervisor: cpu[7]
101
+ },
102
+ uptime: time[0],
103
+ uptime_idle: time[1],
104
+ memory: {
105
+ free: mem[1],
106
+ used: mem[2],
107
+ total: mem[0],
108
+ cache: mem[3],
109
+ free_p: (mem[1] / mem[0].to_f) * 100,
110
+ used_p: (mem[2] / mem[0].to_f) * 100
111
+ },
112
+ load_average: {
113
+ 1 => loads[0],
114
+ 5 => loads[1],
115
+ 15 => loads[2]
116
+ }
117
+ }
118
+ end
119
+ end
120
+
121
+ def self.processes
122
+ if windows?
123
+ tasks = `tasklist /v`
124
+ cpu = `wmic path win32_perfformatteddata_perfproc_process get PercentProcessorTime,percentusertime,IDProcess /format:list`
125
+ cpu = cpu.split("\n\n\n\n").reject(&:empty?)
126
+ .map{ |l| l.scan(/\d+/).map(&:to_i)}
127
+ .map{ |n|[ n[0], {cpu: n[1], user: n[2] }]}.to_h
128
+ lines = tasks.split("\n")[3..-1].map{ |l| l.split(/\s{2,}/) }
129
+ mem = mem_total
130
+ cmds = `wmic process get processid,commandline /format:csv`.split("\n")[1..-1].reject{ |r| r.strip == ''}.map{ |l| l.split(',')[1..-1] }.map{ |l| [l.last.to_i, l[0..-2].join(',')]}.to_h
131
+ lines.map do |l|
132
+ pid = l[1].extract_numbers.first
133
+ {
134
+ name: l[0],
135
+ pid: pid,
136
+ user: l[4],
137
+ mem: (((l[3].gsub(',', '').extract_numbers.first / mem_total) * 100) rescue nil),
138
+ cpu: (cpu[pid][:cpu] rescue nil),
139
+ cmd: cmds[pid]
140
+ }
141
+ end
142
+ else
143
+ t = `ps -e -o comm,pid,ruser,%cpu,%mem,cmd`
144
+ lines = t.split("\n")[1..-1].map{ |l| l.split(/\s+/) }
145
+ lines.map{ |l| l.size == 6 ? l : [l[0], l[1], l[2], l[3], l[4], l[5..-1].join(' ')] }
146
+ lines.map do |l|
147
+ {
148
+ name: l[0],
149
+ pid: l[1].to_i,
150
+ user: l[2],
151
+ cpu: l[3].to_f,
152
+ mem: l[4].to_f,
153
+ cmd: l[5]
154
+ }
155
+ end
156
+ end
157
+ end
158
+
159
+ def self.filesystems
160
+ if windows?
161
+ types = {
162
+ 0 => 'Unknown',
163
+ 1 => 'No Root Directory',
164
+ 2 => 'Removable Disk',
165
+ 3 => 'Local Disk',
166
+ 4 => 'Network Drive',
167
+ 5 => 'Compact Disc',
168
+ 6 => 'RAM Disk'
169
+ }
170
+ parse_wmic('wmic logicaldisk get name,description,filesystem,freespace,size,volumename,volumeserialnumber,providername,drivetype')
171
+ .map do |v|
172
+ v.hpath_move(
173
+ 'freespace' => 'free',
174
+ 'providername' => 'provider',
175
+ 'volumename' => 'volume_name',
176
+ 'volumeserialnumber' => 'serial_number',
177
+ 'filesystem' => 'filesystem_type',
178
+ 'name' => 'disk'
179
+ )
180
+ dt = v.delete(:drivetype).to_i
181
+ v[:type] = types[dt]
182
+ if (2..4) === dt
183
+ v[:free] = v[:free].to_i
184
+ v[:size] = v[:size].to_i
185
+ v[:used] = v[:size] - v[:free]
186
+ v[:free_p] = (v[:free] / v[:size].to_f) * 100
187
+ v[:used_p] = (v[:used] / v[:size].to_f) * 100
188
+ end
189
+ v
190
+ end
191
+ else
192
+ `df -aTB 1`
193
+ .split("\n")[1..-1]
194
+ .map{ |l| l.split(/\s{2,}|(?<=\d)\s|(?<=%)\s|(?<=\-)\s|(?<=\w)\s+(?=\w+\s+\d)/)}
195
+ .map do |i|
196
+ {
197
+ filesystem: i[0],
198
+ type: i[1],
199
+ size: i[2].to_i,
200
+ used: i[3].to_i,
201
+ available: i[4].to_i,
202
+ used_p: i[5].extract_integers.first.to_f,
203
+ mount: i[6],
204
+ }
205
+ end
206
+ end
207
+ end
208
+
209
+
210
+ # A mostly platform agnostic call to get root volumes
211
+ def self.root_volumes
212
+ if BBLib.windows?
213
+ begin # For windows
214
+ `wmic logicaldisk get name`.split("\n").map{ |m| m.strip }[1..-1].reject{ |r| r == '' }
215
+ rescue
216
+ begin # Windows attempt 2
217
+ `fsutil fsinfo drives`.scan(/(?<=\s)\w\:/)
218
+ rescue
219
+ nil
220
+ end
221
+ end
222
+ else
223
+ begin
224
+ `ls /`.split("\n").map{ |m| m.strip }.reject{ |r| r == '' }
225
+ rescue # All attempts failed
226
+ nil
227
+ end
228
+ end
229
+ end
230
+
231
+ # Windows only method to get the volume labels of disk drives
232
+ def self.root_volume_labels
233
+ return nil unless BBLib.windows?
234
+ `wmic logicaldisk get caption,volumename`.split("\n")[1..-1].map{ |m| [m.split(" ").first.to_s.strip, m.split(" ")[1..-1].to_a.join(' ').strip] }.reject{ |o,t| o == '' }.to_h
235
+ end
236
+
237
+ end
238
+ end