storazzo 0.0.6 → 0.2.0

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.
@@ -0,0 +1,358 @@
1
+ # A RicDisk wraps a local mount/disk/folder
2
+ # it's considered interesting if there's a ".ricdisk/.ricdisk"
3
+
4
+ module Storazzo
5
+ class Storazzo::RicDisk
6
+
7
+ include Hashify
8
+ extend Storazzo::Colors
9
+
10
+
11
+ ## Instance variables
12
+
13
+ # in order of finding, so the first will be the one we actually READ and use. I could looknat the date but cmon...
14
+ @@config_files = %W{ ricdisk.yaml .ricdisk }
15
+ @@ricdisk_version = '2.0'
16
+ @@default_gemfile_test_disks_folder = Storazzo.root + "/var/test/disks/"
17
+ # Immutable
18
+ DEFAULT_MEDIA_FOLDERS = %w{
19
+ /Volumes/
20
+ /mnt/
21
+ }.append(@@default_gemfile_test_disks_folder ).append("/media/#{ENV["USER"]}/" )
22
+
23
+ # # todo substitute with protobuf..
24
+ attr_accessor :name, :description, :ricdisk_file, :local_mountpoint, :wr, :path, :ricdisk_file_empty, :size, :active_dirs
25
+
26
+
27
+ ################################
28
+ ## INSTANCE methods
29
+ ################################
30
+
31
+
32
+ def initialize(path, opts={})
33
+ puts "[DEB] RicDisk initialize.. path=#{path}"
34
+ @local_mountpoint = path
35
+ @description = "This is an automated RicDisk description from v.#{@@ricdisk_version}. Created on #{Time.now}'"
36
+ @ricdisk_version = @@ricdisk_version
37
+ #@ricdisk_file = ricdisk_file
38
+ @ricdisk_file = RicDisk.get_ricdisk_file(path)
39
+ @ricdisk_file_empty = ricdisk_file_empty?
40
+ @label = path.split("/").last
41
+ @name = path.split("/").last
42
+ #@wr = File.writable?("#{path}/#{ricdisk_file}" ) # .writeable?
43
+ @tags = ['ricdisk', 'storazzo']
44
+ @size = `du -s '#{path}'`.split(/\s/)[0] # self.size
45
+ puts :beleza
46
+ # @config = RicDiskConfig.instance.get_config
47
+ # #puts @config if @config
48
+ # find_info_from_mount(path)
49
+ # find_info_from_df()
50
+ end
51
+
52
+ def ricdisk_file_empty?()
53
+ File.empty?( "#{local_mountpoint}/#.ricdisk.yaml")
54
+ end
55
+
56
+ def ok_dir?
57
+ not @ricdisk_file.nil?
58
+ end
59
+
60
+
61
+ def analyze_local_system()
62
+ puts :TODO
63
+ puts "1. Interesting Mounts: #{green interesting_mount_points}"
64
+ puts "2. Sbrodoling everything: :TODO"
65
+ # find_info_from_mount(path)
66
+ # find_info_from_df()
67
+ end
68
+
69
+ def path
70
+ local_mountpoint
71
+ end
72
+
73
+ def to_s
74
+ "RicDisk(paz=#{path}, writeable=#{writeable?}, size=#{size}B)"
75
+ end
76
+
77
+ # could take long..
78
+ # def size
79
+ # `du -s '#{path}'`.split(/\s/)[0]
80
+ # end
81
+
82
+ def writeable?()
83
+ :boh
84
+ end
85
+
86
+ ################################
87
+ ## CLASS methods
88
+ ################################
89
+
90
+
91
+ # All places where to find for something :)
92
+ def self.default_media_folders
93
+ DEFAULT_MEDIA_FOLDERS
94
+ end
95
+
96
+
97
+ def self.test # _localgem_disks
98
+ d = RicDisk.new( @@default_gemfile_test_disks_folder)
99
+ puts (d)
100
+ puts "do something with it: #{d}"
101
+ #d.find_active_dirs()
102
+ end
103
+
104
+
105
+
106
+
107
+
108
+ def self.find_active_dirs(base_dirs=nil, also_mountpoints=true)
109
+ if base_dirs.nil?
110
+ base_dirs = default_media_folders
111
+ puts "find_active_dirs with empty input -> using default_media_folders: #{yellow default_media_folders}"
112
+ end
113
+ active_dirs = []
114
+ base_dirs.each do |ugly_dir|
115
+ # https://stackoverflow.com/questions/1899072/getting-a-list-of-folders-in-a-directory#:~:text=Dir.chdir(%27/destination_directory%27)%0ADir.glob(%27*%27).select%20%7B%7Cf%7C%20File.directory%3F%20f%7D
116
+ dir = File.expand_path(ugly_dir)
117
+ begin
118
+ x=[]
119
+ # puts "TEST2 DIR EXISTS: #{dir} -> #{Dir.exists?(dir)}"
120
+ unless Dir.exists?(dir)
121
+ deb "Dir doesnt exist, skipping: #{dir}"
122
+ next
123
+ end
124
+ Dir.chdir(dir)
125
+ x = Dir.glob('*').select {|f| File.directory? f}
126
+ subdirs = x.map{|subdir| "#{dir}#{subdir}"}
127
+ subdirs.each{|subdir|
128
+ #puts `ls -al "#{subdir}"`
129
+ active_dirs << subdir if ok_dir? # self.ok_dir?(subdir)
130
+ }
131
+ #puts(white x)
132
+ rescue Exception => e # optionally: `rescue Exception => ex`
133
+ puts "Exception: '#{e}'"
134
+ ensure # will always get executed
135
+ #deb 'Always gets executed.'
136
+ #x = []
137
+ end
138
+ end
139
+ end
140
+
141
+
142
+ # new
143
+ def self.get_ricdisk_file(path)
144
+ puts "RICC_WARNING TODO use @@config_files instead"
145
+ return ".ricdisk.yaml" if File.exist?("#{path}/.ricdisk.yaml") #and File.empty?( "#{path}/.ricdisk.yaml")
146
+ return ".ricdisk" if File.exist?("#{path}/.ricdisk") # and File.empty?( "#{path}/.ricdisk")
147
+ return nil
148
+ end
149
+
150
+
151
+ def self.interesting_mount_points(opts={})
152
+ #https://unix.stackexchange.com/questions/177014/showing-only-interesting-mount-points-filtering-non-interesting-types
153
+ `mount | grep -Ev 'type (proc|sysfs|tmpfs|devpts|debugfs|rpc_pipefs|nfsd|securityfs|fusectl|devtmpfs) '`.split(/\n+/)
154
+ end
155
+
156
+ # maybe move to a RiccFile class? Maybe even INHERIT from FILE?
157
+ def self.obsolescence_seconds file_path
158
+ creation_time = File.stat(file_path).ctime
159
+ deb("[obsolescence_seconds] File #{file_path}: #{creation_time} - #{(Time.now - creation_time)} seconds ago")
160
+ (Time.now - creation_time).to_i
161
+ end
162
+ # maybe move to a RiccFile class? Maybe even INHERIT from FILE?
163
+ def self.obsolescence_days(file_path)
164
+ return obsolescence_seconds(file_path) / 86400
165
+ end
166
+
167
+
168
+ # FORMER SBRODOLA, now write_config_yaml_to_disk
169
+ def self.write_config_yaml_to_disk(subdir) # sbrodola_ricdisk(subdir)
170
+ # given a path, if .ricdisk exists i do stuff with it..
171
+ disk_info = nil
172
+ unless self.ok_dir?(subdir)
173
+ puts("Nothing for me here: '#{subdir}'. Existing")
174
+ return
175
+ end
176
+ if File.exists?( "#{subdir}/.ricdisk") and File.empty?( "#{subdir}/.ricdisk")
177
+ deb("Interesting1. Empty file! Now I write YAML with it.")
178
+ disk_info = RicDisk.new(subdir, '.ricdisk')
179
+ end
180
+ if File.exists?( "#{subdir}/.ricdisk.yaml") and File.empty?( "#{subdir}/.ricdisk.yaml")
181
+ deb("Interesting2. Empty file! TODO write YAML with it.")
182
+ disk_info = RicDisk.new(subdir, '.ricdisk.yaml')
183
+ puts(yellow disk_info.to_yaml)
184
+ end
185
+ if disk_info
186
+ if File.empty?(disk_info.ricdisk_absolute_path) and (disk_info.wr)
187
+ puts(green("yay, we can now write the file '#{disk_info.ricdisk_absolute_path}' (which is R/W, I just checked!) with proper YAML content.."))
188
+ ret = File.write(disk_info.ricdisk_absolute_path, disk_info.to_yaml)
189
+ puts("Written file! ret=#{ret}")
190
+ else
191
+ puts(red("Nope, qualcosa non va.. #{File.empty?(disk_info.ricdisk_absolute_path)}"))
192
+ puts("File size: #{File.size(disk_info.ricdisk_absolute_path)}")
193
+ end
194
+ end
195
+ if File.exists?( "#{subdir}/.ricdisk") and ! File.empty?( "#{subdir}/.ricdisk")
196
+ puts("Config File found with old-style name: '#{subdir}/.ricdisk' !")
197
+ #puts(white `cat "#{subdir}/.ricdisk"`)
198
+ end
199
+ end
200
+
201
+ # TODO obsolete this as i should NOT be calling it from clas, but from method.
202
+ def self.ok_dir?(subdir)
203
+ File.exists?( "#{subdir}/.ricdisk") or File.exists?( "#{subdir}/.ricdisk.yaml")
204
+ end
205
+
206
+
207
+
208
+ # Create RDS file.
209
+ def self.calculate_stats_files(dir, opts={})
210
+ opts_upload_to_gcs = opts.fetch :upload_to_gcs, true
211
+ full_file_path = "#{dir}/#{$stats_file}"
212
+ return "This refacgtor is for another day"
213
+
214
+ puts("calculate_stats_files(#{white dir}): #{white full_file_path}")
215
+ puts "TEST1 DIR EXISTS: #{dir} -> #{File.directory? dir}"
216
+ Dir.chdir(dir)
217
+ if File.exists?(full_file_path) and ($opts[:force] == false)
218
+ puts "File '#{$stats_file}' exists already." # - now should see if its too old, like more than 1 week old"
219
+ # TODO check for file time...
220
+ print "Lines found: #{yellow `wc -l "#{full_file_path}" `.chomp }. File obsolescence (days): #{yellow obsolescence_days(full_file_path)}."
221
+ if obsolescence_days(full_file_path) > 7
222
+ puts("*** ACHTUNG *** FIle is pretty old. You might consider rotating: #{yellow "mv #{full_file_path} #{full_file_path}_old"}. Or invoke with --force")
223
+ end
224
+ upload_to_gcs(full_file_path) if opts_upload_to_gcs
225
+ else
226
+ puts "Crunching data stats from '#{dir}' into '#{$stats_file}' ... please bear with me.. [maybe file didnt exist, maybe $opts[:force] is true]"
227
+ command = "find . -print0 | xargs -0 stats-with-md5.rb --no-color | tee '#{full_file_path}'"
228
+ puts("[#{`pwd`.chomp}] Executing: #{azure command}")
229
+ ret = backquote_execute command
230
+ puts "Done. #{ret.split("\n").count} files processed."
231
+ end
232
+ end
233
+
234
+ # if also_mountpoints
235
+ # =begin
236
+ # Example output from mount:
237
+
238
+ # devfs on /dev (devfs, local, nobrowse)
239
+ # /dev/disk3s6 on /System/Volumes/VM (apfs, local, noexec, journaled, noatime, nobrowse)
240
+ # /dev/disk3s2 on /System/Volumes/Preboot (apfs, local, journaled, nobrowse)
241
+ # /dev/disk3s4 on /System/Volumes/Update (apfs, local, journaled, nobrowse)
242
+ # /dev/disk1s2 on /System/Volumes/xarts (apfs, local, noexec, journaled, noatime, nobrowse)
243
+ # /dev/disk1s1 on /System/Volumes/iSCPreboot (apfs, local, journaled, nobrowse)
244
+ # /dev/disk1s3 on /System/Volumes/Hardware (apfs, local, journaled, nobrowse)
245
+ # /dev/disk3s5 on /System/Volumes/Data (apfs, local, journaled, nobrowse, protect)
246
+ # map auto_home on /System/Volumes/Data/home (autofs, automounted, nobrowse)
247
+ # //riccardo@1.0.1.10/video on /Volumes/video (afpfs, nodev, nosuid, mounted by ricc)
248
+ # //riccardo@1.0.1.10/photo on /Volumes/photo (afpfs, nodev, nosuid, mounted by ricc)
249
+ # =end
250
+ # # add directories from current mountpoints...
251
+ # mount_table_lines = interesting_mount_points()
252
+ # mount_table_lines.each{|line|
253
+ # next if line =~ /^map /
254
+ # dev, on, path, mode = line.split(/ /)
255
+ # #puts line
256
+ # #deb yellow(path)
257
+ # active_dirs << path if self.ok_dir?(path)
258
+ # }
259
+ # end
260
+ # active_dirs.uniq!
261
+ # puts("find_active_dirs(): found dirs " + green(active_dirs))
262
+ # return active_dirs
263
+ # end
264
+
265
+
266
+
267
+ end #/Class
268
+ end #/Module
269
+
270
+
271
+
272
+
273
+
274
+ # def initialize(path, ricdisk_file)
275
+ # puts "[DEB] RicDisk initialize.. path=#{path}"
276
+ # @local_mountpoint = path
277
+ # @description = "This is an automated RicDisk description from v.#{VERSION}. Riccardo feel free to edit away with characteristicshs of this device.. Created on #{Time.now}'"
278
+ # @ricdisk_version = VERSION
279
+ # @ricdisk_file = ricdisk_file
280
+ # #@questo_non_esiste = :sobenme
281
+ # @label = path.split("/").last
282
+ # @name = path.split("/").last
283
+ # @wr = File.writable?("#{path}/#{ricdisk_file}" ) # .writeable?
284
+ # @tags = 'ricdisk'
285
+ # puts :beleza
286
+ # @config = RicDiskConfig.instance.get_config
287
+ # #puts @config if @config
288
+ # find_info_from_mount(path)
289
+ # find_info_from_df()
290
+ # end
291
+
292
+ # def ricdisk_absolute_path
293
+ # @local_mountpoint + "/" + @ricdisk_file
294
+ # end
295
+
296
+ # def add_tag(tag)
297
+ # @tags += ", #{tag}"
298
+ # end
299
+
300
+ # # might have other things in the future...
301
+ # def find_info_from_mount(path)
302
+ # mount_table_lines = interesting_mount_points()
303
+ # mount_line = nil
304
+ # mount_table_lines.each do |line|
305
+ # next if line =~ /^map /
306
+ # dev, on, mount_path, mode = line.split(/ /)
307
+ # if mount_path==path
308
+ # mount_line = line
309
+ # else
310
+ # @info_from_mount = false
311
+ # end
312
+ # end
313
+ # @info_from_mount = ! (mount_line.nil?)
314
+ # if @info_from_mount
315
+ # #@mount_line = mount_line
316
+ # @description += "\nMount line:\n" + mount_line
317
+ # @remote_mountpoint = mount_line.split(/ /)[0]
318
+ # @fstype = mount_line.split(/ /)[3].gsub(/[\(,]/, '')
319
+ # add_tag(:synology) if @remote_mountpoint.match('1.0.1.10')
320
+ # end
321
+ # end
322
+
323
+ # def find_info_from_df()
324
+ # path = @local_mountpoint
325
+ # df_info = `df -h "#{path}"`
326
+ # @df_info = df_info
327
+ # lines = df_info.split(/\n+/)
328
+ # raise "I need exactly TWO lines! Or no info is served here..." unless lines.size == 2
329
+ # mount, @size_readable, used_size, avail_size, @disk_utilization, other = lines[1].split(/\s+/) # second line..
330
+ # end
331
+
332
+
333
+
334
+
335
+
336
+
337
+ # def self.backquote_execute(cmd)
338
+ # # executed a command wrapped by dryrun though
339
+ # return "DRYRUN backquote_execute(#{cmd})" if $opts[:dryrun]
340
+ # `#{cmd}`
341
+ # end
342
+
343
+ # def self.upload_to_gcs(file, opts={})
344
+ # deb("upload_to_gcs(#{file}). TODO(ricc) after breafast upload to GCS : #{file}")
345
+ # mount_name = file.split('/')[-2]
346
+ # filename = "#{mount_name}-#{File.basename file}"
347
+ # hostname = Socket.gethostname[/^[^.]+/]
348
+ # command = "gsutil cp '#{file}' gs://#{$gcs_bucket}/backup/ricdisk-magic/#{ hostname }-#{filename}"
349
+ # deb("Command: #{command}")
350
+ # ret = backquote_execute(command)
351
+ # # if $opts[:debug] do
352
+ # # puts "+ Current list of files:"
353
+ # # ret = backquote_execute("gsutil ls -al gs://#{$gcs_bucket}/backup/ricdisk-magic/")
354
+ # # puts ret
355
+ # # end
356
+ # ret
357
+ # end
358
+
@@ -0,0 +1,93 @@
1
+ require 'singleton'
2
+ require 'yaml'
3
+
4
+ module Storazzo
5
+ class Storazzo::RicDiskConfig
6
+ include Singleton
7
+ include Storazzo::Common
8
+ include Storazzo::Colors
9
+
10
+ @@default_config_location = "~/.storazzo.yaml"
11
+ attr_accessor :config, :config_file
12
+
13
+ def load(config_path=nil, opts={})
14
+ verbose = opts.fetch :verbose, false
15
+
16
+ puts "[VERBOSE] Storazzo::RicDiskConfig.load(): BEGIN " if verbose
17
+ # trying default location
18
+ possible_locations = [ @@default_config_location , "./.storazzo.yaml"]
19
+ if config_path
20
+ possible_locations =possible_locations.append(config_path)
21
+ end
22
+ puts "[VERBOSE] Searching these paths in order: #{possible_locations}" if verbose
23
+ possible_locations.each do |possible_path|
24
+ paz = File.expand_path(possible_path)
25
+ #puts "DEB paz:#{paz}"
26
+ if File.exists?(paz)
27
+ @config_file = paz
28
+ @config = YAML.load(File.read paz) # YAML.load(File.read("file_path"))
29
+ #pp @config if verbose
30
+ #config_ver = @config[:ConfigVersion]
31
+ #puts @config[:ConfigVersion]
32
+ puts "Storazzo::RicDiskConfig v#{config_ver} parsed correctly"
33
+ puts "RicDiskConfig.to_s: #{self}" if verbose
34
+ return self.config
35
+ end
36
+ end
37
+ # only get here if nothing is found
38
+ raise "No config found across these locations: #{possible_locations}. Consider copying and editing: #{RicDiskConfig.gem_default_config_path}"
39
+ # @config = 42
40
+ # puts "[VERBOSE] Storazzo::RicDiskConfig.load(): END " if verbose
41
+ end
42
+
43
+ def config_ver
44
+ #self.
45
+ @config['ConfigVersion']
46
+ end
47
+ def config_default_folder
48
+ #self.
49
+ @config['Config']['DefaultFolder'] #rescue "Unknown config_default_folder: #{$!}"
50
+ end
51
+
52
+ def to_s
53
+ size = File.size @config_file
54
+ "RicDiskConfig(v#{config_ver}, file=#{ @config_file}) with #{size} bytes" # - config_default_folder=#{self.config_default_folder}"
55
+ end
56
+
57
+ def get_config(opts={})
58
+ return load(opts) if @config.nil?
59
+ @config
60
+ end
61
+
62
+ def self.gem_default_config_path
63
+ Storazzo.root + "/etc/storazzo_config.sample.yaml"
64
+ end
65
+
66
+ # UGLY CODE, copipasted from binary for ARGV
67
+ def iterate_through_file_list_for_disks(files_list=[])
68
+ if files_list == [] # or files_list.nil? # empty -> ALL
69
+ deb "iterate_through_file_list_for_disks(): no args provided"
70
+ dirs = RicDisk.find_active_dirs()
71
+ puts "DEB find_active_dirs: #{green dirs}"
72
+ dirs.each {|dir|
73
+ RicDisk.write_config_yaml_to_disk(dir)
74
+ RicDisk.calculate_stats_files(dir) # dir is inutile
75
+ } # TODO refactor in option sbrodola_afterwards=true. :)
76
+ else
77
+ deb "iterate_through_file_list_for_disks(): I consider files_list as a list of directories to parse :)"
78
+ dirs = RicDisk.find_active_dirs()
79
+ files_list.each do |dir|
80
+ dir = File.expand_path(dir)
81
+ if dirs.include?(dir)
82
+ deb "Legit dir: #{green dir}"
83
+ RicDisk.write_config_yaml_to_disk(dir)
84
+ RicDisk.calculate_stats_files(dir) # dir is inutile
85
+ else
86
+ deb "Figghiu ri buttana: doesnt exist #{red dir}"
87
+ end
88
+ end
89
+ end
90
+ end #/iterate_through_file_list_for_disks
91
+
92
+ end
93
+ end
@@ -0,0 +1,10 @@
1
+ # This class wraps the RDS file: we're going to write this RDS file
2
+ # directly in the disk: /mount/
3
+ module Storazzo
4
+ class Storazzo::RicDiskStatsFile
5
+ @@default_name = "ricdisk_stats_v11.rds" # => RicDiskStatsFile
6
+
7
+
8
+
9
+ end
10
+ end