rubynas 0.1.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +196 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +7 -0
- data/Procfile +2 -0
- data/README.md +151 -0
- data/Rakefile +14 -0
- data/Vagrantfile +99 -0
- data/bin/rubynas +63 -0
- data/config.ru +5 -0
- data/doc/README_FOR_APP +2 -0
- data/doc/macosx_shares.png +0 -0
- data/doc/shares_overview.png +0 -0
- data/lib/rubynas.rb +35 -0
- data/lib/rubynas/apis/group_api.rb +51 -0
- data/lib/rubynas/apis/system_information_api.rb +13 -0
- data/lib/rubynas/apis/user_api.rb +85 -0
- data/lib/rubynas/apis/volume_api.rb +50 -0
- data/lib/rubynas/config.rb +63 -0
- data/lib/rubynas/db/migrate/20130302164415_devise_create_users.rb +46 -0
- data/lib/rubynas/db/migrate/20130322143040_create_volumes.rb +10 -0
- data/lib/rubynas/db/migrate/20130331102556_create_shared_folders.rb +10 -0
- data/lib/rubynas/db/migrate/20130331103034_create_shared_folder_services.rb +11 -0
- data/lib/rubynas/installers/base_installer.rb +70 -0
- data/lib/rubynas/installers/debian_installer.rb +199 -0
- data/lib/rubynas/installers/ubuntu_installer.rb +2 -0
- data/lib/rubynas/installers/ubuntu_precise_installer.rb +2 -0
- data/lib/rubynas/models/.gitkeep +0 -0
- data/lib/rubynas/models/ldap_group.rb +21 -0
- data/lib/rubynas/models/ldap_org_unit.rb +13 -0
- data/lib/rubynas/models/ldap_user.rb +31 -0
- data/lib/rubynas/models/shared_folder.rb +32 -0
- data/lib/rubynas/models/shared_folder_service.rb +15 -0
- data/lib/rubynas/models/volume.rb +16 -0
- data/lib/rubynas/services/afp_share_service.rb +9 -0
- data/lib/rubynas/services/service.rb +4 -0
- data/lib/rubynas/services/share_service.rb +3 -0
- data/lib/rubynas/version.rb +3 -0
- data/rubynas.gemspec +69 -0
- data/rubynas.ini +24 -0
- data/sandbox/ldap/base.ldif +50 -0
- data/sandbox/ldap/data/.gitkeep +0 -0
- data/sandbox/ldap/data/dc=rubynas,dc=com.ldif +14 -0
- data/sandbox/ldap/local.schema +6 -0
- data/sandbox/ldap/schema/README +80 -0
- data/sandbox/ldap/schema/apple.schema +1727 -0
- data/sandbox/ldap/schema/apple_auxillary.schema +20 -0
- data/sandbox/ldap/schema/collective.ldif +48 -0
- data/sandbox/ldap/schema/collective.schema +190 -0
- data/sandbox/ldap/schema/corba.ldif +42 -0
- data/sandbox/ldap/schema/corba.schema +239 -0
- data/sandbox/ldap/schema/core.ldif +591 -0
- data/sandbox/ldap/schema/core.schema +610 -0
- data/sandbox/ldap/schema/cosine.ldif +200 -0
- data/sandbox/ldap/schema/cosine.schema +2571 -0
- data/sandbox/ldap/schema/duaconf.ldif +83 -0
- data/sandbox/ldap/schema/duaconf.schema +261 -0
- data/sandbox/ldap/schema/dyngroup.ldif +71 -0
- data/sandbox/ldap/schema/dyngroup.schema +91 -0
- data/sandbox/ldap/schema/fmserver.schema +60 -0
- data/sandbox/ldap/schema/inetorgperson.ldif +69 -0
- data/sandbox/ldap/schema/inetorgperson.schema +155 -0
- data/sandbox/ldap/schema/java.ldif +59 -0
- data/sandbox/ldap/schema/java.schema +403 -0
- data/sandbox/ldap/schema/krb5-kdc.schema +134 -0
- data/sandbox/ldap/schema/microsoft.ext.schema +5383 -0
- data/sandbox/ldap/schema/microsoft.schema +4835 -0
- data/sandbox/ldap/schema/microsoft.std.schema +480 -0
- data/sandbox/ldap/schema/misc.ldif +45 -0
- data/sandbox/ldap/schema/misc.schema +75 -0
- data/sandbox/ldap/schema/netinfo.schema +240 -0
- data/sandbox/ldap/schema/nis.ldif +120 -0
- data/sandbox/ldap/schema/nis.schema +241 -0
- data/sandbox/ldap/schema/openldap.ldif +88 -0
- data/sandbox/ldap/schema/openldap.schema +54 -0
- data/sandbox/ldap/schema/pmi.ldif +123 -0
- data/sandbox/ldap/schema/pmi.schema +464 -0
- data/sandbox/ldap/schema/ppolicy.ldif +75 -0
- data/sandbox/ldap/schema/ppolicy.schema +531 -0
- data/sandbox/ldap/schema/samba.schema +179 -0
- data/sandbox/ldap/slapd.conf +99 -0
- data/spec/apis/group_api_spec.rb +97 -0
- data/spec/apis/system_information_api_spec.rb +27 -0
- data/spec/apis/user_api_spec.rb +113 -0
- data/spec/apis/volume_api_spec.rb +98 -0
- data/spec/factories/ldap_group.rb +16 -0
- data/spec/factories/ldap_users.rb +24 -0
- data/spec/factories/shared_folder_services.rb +9 -0
- data/spec/factories/shared_folders.rb +15 -0
- data/spec/factories/users.rb +8 -0
- data/spec/factories/volumes.rb +10 -0
- data/spec/installer/base_installer_spec.rb +35 -0
- data/spec/installer/debian_installer_spec.rb +86 -0
- data/spec/models/ldap_group_spec.rb +21 -0
- data/spec/models/ldap_org_unit_spec.rb +19 -0
- data/spec/models/ldap_user_spec.rb +19 -0
- data/spec/models/shared_folder_service_spec.rb +25 -0
- data/spec/models/shared_folder_spec.rb +27 -0
- data/spec/models/volume_spec.rb +5 -0
- data/spec/services/afp_share_service_spec.rb +5 -0
- data/spec/services/service_spec.rb +5 -0
- data/spec/services/share_service_spec.rb +5 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/db_cleaner.rb +16 -0
- data/spec/support/factory_girl.rb +7 -0
- data/spec/support/logger.rb +1 -0
- data/spec/support/rack-test.rb +6 -0
- metadata +633 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'resolv'
|
2
|
+
require 'foreman'
|
3
|
+
require 'foreman/cli'
|
4
|
+
|
5
|
+
class BaseInstaller
|
6
|
+
ROOT_USER_ID = 0
|
7
|
+
|
8
|
+
class InstallError < StandardError; end
|
9
|
+
class ConfigurationError < InstallError; end
|
10
|
+
class PackageError < InstallError; end
|
11
|
+
|
12
|
+
INSTALL_ORDER = [ :prepare_install, :configure_ldap, :install_ldap,
|
13
|
+
:configure_pam_auth, :install_pam_auth, :configure_app,
|
14
|
+
:install_app ]
|
15
|
+
|
16
|
+
attr_reader :domain, :admin, :password
|
17
|
+
|
18
|
+
# @param [String] domain the domain for the rubynas like 'rubynas.com'
|
19
|
+
# @param [String] admin the admin user for the ldap
|
20
|
+
# @param [String] password the admin user password
|
21
|
+
def initialize(domain, admin, password)
|
22
|
+
@domain = domain
|
23
|
+
@admin = admin
|
24
|
+
@password = password
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Array<String>] a list of domain parts
|
28
|
+
def domain_parts
|
29
|
+
@domain_parts ||= Resolv::DNS::Name.create(domain).to_a.map(&:to_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [String]
|
33
|
+
def ldap_base
|
34
|
+
domain_parts.map { |s| "dc=#{s}" }.join(",")
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return [String]
|
38
|
+
def admin_ldap_dn
|
39
|
+
"cn=#{admin},#{ldap_base}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Boolean] if the current user is root
|
43
|
+
def root?
|
44
|
+
Process.uid == ROOT_USER_ID
|
45
|
+
end
|
46
|
+
|
47
|
+
def log(line)
|
48
|
+
STDOUT.puts line
|
49
|
+
Rubynas.logger.info "[#{self.class.name}] #{line}"
|
50
|
+
end
|
51
|
+
|
52
|
+
# Path to the rubynas executable
|
53
|
+
# @return [String]
|
54
|
+
def rubynas
|
55
|
+
File.expand_path('../../../../bin/rubynas', __FILE__)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Executes the installation
|
59
|
+
def run
|
60
|
+
log "Start install of #{Rubynas::VERSION}"
|
61
|
+
INSTALL_ORDER.each do |method|
|
62
|
+
send(method) if respond_to? method
|
63
|
+
end
|
64
|
+
rescue InstallError => ex
|
65
|
+
log "Error: #{ex}"
|
66
|
+
raise ex
|
67
|
+
ensure
|
68
|
+
log "Installation ended"
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'etc'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
class DebianInstaller < BaseInstaller
|
6
|
+
include FileUtils
|
7
|
+
|
8
|
+
def prepare_install
|
9
|
+
log "Updating the package repository"
|
10
|
+
unless system('apt-get update')
|
11
|
+
raise InstallError, "Failed to update the package repository"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def install(*packages)
|
16
|
+
log "Installing #{packages.join(', ')}"
|
17
|
+
ENV['DEBIAN_FRONTEND'] = 'noninteractive'
|
18
|
+
unless system("apt-get install -y #{packages.join(' ')}")
|
19
|
+
raise PackageError, "Failed to install packages #{packages.join(", ")}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def restart_service(service)
|
24
|
+
log "Start service rubynas"
|
25
|
+
unless system('service rubynas restart')
|
26
|
+
raise InstallError, "Failed to start service"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def debconf(category, key, type, value)
|
31
|
+
case type
|
32
|
+
when :password, :string, :select
|
33
|
+
value = value.to_s
|
34
|
+
when :boolean
|
35
|
+
value = value ? true : false
|
36
|
+
when :multiselect
|
37
|
+
value = value.join(', ')
|
38
|
+
end
|
39
|
+
|
40
|
+
IO.popen("debconf-set-selections", 'w') do |io|
|
41
|
+
io.write "'#{category}' '#{key}' #{type} '#{value}'"
|
42
|
+
end
|
43
|
+
log "Configuring #{category} - #{key}"
|
44
|
+
unless $?.exited?
|
45
|
+
raise ConfigurationError, "Failed to configure #{category} (#{key})"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the ruby executable
|
50
|
+
def ruby
|
51
|
+
"ruby1.9.3 -S"
|
52
|
+
end
|
53
|
+
|
54
|
+
def configure_ldap
|
55
|
+
log 'Configure LDAP'
|
56
|
+
debconf 'slapd', 'slapd/internal/generated_adminpw', :password, @password
|
57
|
+
debconf 'slapd', 'slapd/password2', :password, @password
|
58
|
+
debconf 'slapd', 'slapd/internal/adminpw', :password, @password
|
59
|
+
debconf 'slapd', 'slapd/password1', :password, @password
|
60
|
+
debconf 'slapd', 'slapd/allow_ldap_v2', :boolean, true
|
61
|
+
debconf 'slapd', 'slapd/invalid_config', :boolean, true
|
62
|
+
debconf 'slapd', 'shared/organization', :string, @domain
|
63
|
+
debconf 'slapd', 'slapd/no_configuration', :boolean, false
|
64
|
+
debconf 'slapd', 'slapd/move_old_database', :boolean, true
|
65
|
+
debconf 'slapd', 'slapd/dump_database_destdir', :string,
|
66
|
+
'/var/backups/slapd-VERSION'
|
67
|
+
debconf 'slapd', 'slapd/purge_database', :boolean, true
|
68
|
+
debconf 'slapd', 'slapd/domain', :string, @domain
|
69
|
+
debconf 'slapd', 'slapd/backend', :string, 'HDB'
|
70
|
+
end
|
71
|
+
|
72
|
+
def install_ldap
|
73
|
+
install 'ldap-utils', 'slapd'
|
74
|
+
end
|
75
|
+
|
76
|
+
def configure_pam_auth
|
77
|
+
log 'Configure ldap with pam (authentication)'
|
78
|
+
debconf 'libnss-ldapd', 'libnss-ldapd/nsswitch', :multiselect,
|
79
|
+
[:passwd, :group, :shadow]
|
80
|
+
debconf 'libpam-ldapd', 'libpam-ldapd/enable_shadow', :boolean, true
|
81
|
+
debconf 'libnss-ldapd', 'libnss-ldapd/clean_nsswitch', :boolean, false
|
82
|
+
|
83
|
+
log 'Configure the authentication daemon for ldap and pam auth'
|
84
|
+
debconf 'nslcd', 'nslcd/ldap-starttls', :boolean, false
|
85
|
+
debconf 'nslcd', 'nslcd/ldap-sasl-krb5-ccname', :string,
|
86
|
+
'/var/run/nslcd/nslcd.tkt'
|
87
|
+
debconf 'nslcd', 'nslcd/ldap-auth-type', :select, 'none'
|
88
|
+
debconf 'nslcd', 'nslcd/ldap-uris', :string, 'ldapi:///'
|
89
|
+
debconf 'nslcd', 'nslcd/ldap-base', :string, ldap_base
|
90
|
+
debconf 'nslcd', 'nslcd/ldap-binddn', :string, admin_ldap_dn
|
91
|
+
debconf 'nslcd', 'nslcd/ldap-bindpw', :password, @password
|
92
|
+
end
|
93
|
+
|
94
|
+
def install_pam_auth
|
95
|
+
install 'libnss-ldapd', 'libpam-ldapd', 'nslcd'
|
96
|
+
end
|
97
|
+
|
98
|
+
def install_app
|
99
|
+
create_rubynas_user
|
100
|
+
create_directories
|
101
|
+
create_configuration
|
102
|
+
create_upstart_script
|
103
|
+
migrate_database
|
104
|
+
restart_service :rubynas
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def create_rubynas_user
|
110
|
+
begin
|
111
|
+
Etc.getpwnam('rubynas')
|
112
|
+
rescue ArgumentError => ex
|
113
|
+
log "Create rubynas user"
|
114
|
+
system 'useradd rubynas --system --no-create-home'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def create_directories
|
119
|
+
log "Create directories"
|
120
|
+
mkdir_p '/var/lib/rubynas/'
|
121
|
+
end
|
122
|
+
|
123
|
+
def create_configuration
|
124
|
+
if File.exist? '/etc/rubynas.ini'
|
125
|
+
log "The configuration rubynas.ini already exist!"
|
126
|
+
else
|
127
|
+
log "Create rubynas.ini"
|
128
|
+
File.open('/etc/rubynas.ini', 'w') do |f|
|
129
|
+
config = <<-CONF
|
130
|
+
;
|
131
|
+
; This is the configuration file for local development and testing.
|
132
|
+
;
|
133
|
+
|
134
|
+
; Configuration for the sqlite3 database
|
135
|
+
[Database]
|
136
|
+
path = %s
|
137
|
+
timeout = 5000
|
138
|
+
pool = 5
|
139
|
+
|
140
|
+
; Configuration for the ldap server that is used for authentication,
|
141
|
+
; user and group management
|
142
|
+
[Ldap]
|
143
|
+
host = 127.0.0.1
|
144
|
+
port = 389
|
145
|
+
base = "%s"
|
146
|
+
bind_dn = "%s"
|
147
|
+
password = %s
|
148
|
+
|
149
|
+
; Server related configuration
|
150
|
+
[Server]
|
151
|
+
; if syslog set to false it will be logged to stdout
|
152
|
+
syslog = true
|
153
|
+
; NOTHING HERE YET
|
154
|
+
CONF
|
155
|
+
f.puts config.gsub(/^\s+/, "") % [
|
156
|
+
db_path,
|
157
|
+
ldap_base,
|
158
|
+
admin_ldap_dn,
|
159
|
+
password
|
160
|
+
]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def create_upstart_script
|
166
|
+
# Create a rubynas upstart script
|
167
|
+
Tempfile.open('env') do |fe|
|
168
|
+
%w(GEM_HOME GEM_PATH PATH).each do |name|
|
169
|
+
fe.puts "#{name}=#{ENV[name]}" if ENV[name]
|
170
|
+
end
|
171
|
+
fe.flush
|
172
|
+
|
173
|
+
Tempfile.open('Procfile') do |fp|
|
174
|
+
fp.puts "api: exec #{ruby} #{rubynas} server"
|
175
|
+
fp.close
|
176
|
+
|
177
|
+
Foreman::CLI.start [
|
178
|
+
'export', '--app', 'rubynas', '--env', fe.path,
|
179
|
+
'--procfile', fp.path, 'upstart', '/etc/init'
|
180
|
+
]
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def migrate_database
|
186
|
+
log "Migrate the database"
|
187
|
+
unless system("#{ruby} #{rubynas} migrate")
|
188
|
+
raise InstallError, "Failed to migrate the database"
|
189
|
+
end
|
190
|
+
|
191
|
+
log "Allow access to database by rubynas user"
|
192
|
+
user = Etc.getpwnam('rubynas')
|
193
|
+
chown user.uid, user.gid, db_path
|
194
|
+
end
|
195
|
+
|
196
|
+
def db_path
|
197
|
+
'/var/lib/rubynas/sqlite3.db'
|
198
|
+
end
|
199
|
+
end
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class LdapGroup < ActiveLdap::Base
|
2
|
+
ldap_mapping :dn_attribute => 'cn', :prefix => 'ou=groups',
|
3
|
+
:classes => ['top', 'posixGroup']
|
4
|
+
|
5
|
+
# Associate with primary belonged users
|
6
|
+
has_many :primary_members, :foreign_key => 'gidNumber',
|
7
|
+
:class_name => "LdapUser", :primary_key => 'gidNumber'
|
8
|
+
|
9
|
+
# Associate with all belonged users
|
10
|
+
has_many :members, :wrap => "memberUid",
|
11
|
+
:class_name => "LdapUser", :primary_key => 'uid'
|
12
|
+
|
13
|
+
# Creates or finds the admin group. The common name has to be 'Administrators'
|
14
|
+
# @return [LdapGroup]
|
15
|
+
def self.find_or_create_administrators
|
16
|
+
group = LdapGroup.find('Administrators') rescue nil
|
17
|
+
group ||= LdapGroup.create :common_name => "Administrators",
|
18
|
+
:gid_number => 0
|
19
|
+
group
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class LdapOrgUnit < ActiveLdap::Base
|
2
|
+
ldap_mapping dn_attribute: "ou", :classes => ['organizationalUnit'],
|
3
|
+
:scope => :sub, :prefix => ""
|
4
|
+
|
5
|
+
# Creates or finds a unit by name
|
6
|
+
# @param [String] name the name of the unit (ou) to find or create
|
7
|
+
# @return [LdapOrgUnit]
|
8
|
+
def self.find_or_create(name)
|
9
|
+
unit = LdapOrgUnit.find(name) rescue nil
|
10
|
+
unit ||= LdapOrgUnit.create(:ou => name)
|
11
|
+
unit
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class LdapUser < ActiveLdap::Base
|
2
|
+
ldap_mapping :dn_attribute => 'cn', :scope => :one,
|
3
|
+
:prefix => 'ou=users', :classes => [
|
4
|
+
'inetOrgPerson', 'organizationalPerson', 'person',
|
5
|
+
'posixAccount', 'top'
|
6
|
+
]
|
7
|
+
|
8
|
+
# Associate with primary belonged group
|
9
|
+
belongs_to :primary_group, :primary_key => 'gidNumber',
|
10
|
+
:class_name => 'LdapGroup'
|
11
|
+
|
12
|
+
# Associate with all belonged groups
|
13
|
+
belongs_to :groups, :primary_key => 'uid', :many => 'memberUid',
|
14
|
+
:class_name => 'LdapGroup'
|
15
|
+
|
16
|
+
# Creates or finds the admin user. The common name has to be 'Admin'
|
17
|
+
# @return [LdapUser]
|
18
|
+
def self.find_or_create_admin
|
19
|
+
user = LdapUser.find('Admin') rescue nil
|
20
|
+
user ||= LdapUser.create(
|
21
|
+
:common_name => "Admin",
|
22
|
+
:mail => "admin@rubynas.com",
|
23
|
+
:home_directory => "/root",
|
24
|
+
:uid => "admin",
|
25
|
+
:surname => "Admin",
|
26
|
+
:uid_number => 0,
|
27
|
+
:gid_number => 0,
|
28
|
+
:user_password => ActiveLdap::UserPassword.sha("secret"))
|
29
|
+
user
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class SharedFolder < ActiveRecord::Base
|
2
|
+
attr_accessible :name, :path
|
3
|
+
has_many :shared_folder_services
|
4
|
+
validates_presence_of :name, :path
|
5
|
+
|
6
|
+
validate :path_exists
|
7
|
+
|
8
|
+
# Converts the shared folder path to path object
|
9
|
+
# @returns [Pathname]
|
10
|
+
def pathname
|
11
|
+
Pathname.new(path)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Validate if the path is given and is really a directory
|
15
|
+
def path_exists
|
16
|
+
if path
|
17
|
+
errors.add(:path, "Path dosn't exist") unless pathname.exist?
|
18
|
+
errors.add(:path, "Path isn't a directory") unless pathname.directory?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Searches for the shared folder service that is identified by the given
|
23
|
+
# service class.
|
24
|
+
# @param [Class, String] service_class a klass like AfpShareService
|
25
|
+
# @return [SharedFolderService, nil] the service configuration or nil if
|
26
|
+
# no confiuration was found
|
27
|
+
def [](service_class)
|
28
|
+
if service = shared_folder_services.where(service_class: service_class).first
|
29
|
+
service.options
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class SharedFolderService < ActiveRecord::Base
|
2
|
+
attr_accessible :options, :service_class, :shared_folder
|
3
|
+
belongs_to :shared_folder
|
4
|
+
serialize :options
|
5
|
+
|
6
|
+
validates_presence_of :service_class, :shared_folder_id
|
7
|
+
|
8
|
+
# @return [Class] a service class
|
9
|
+
def service_class
|
10
|
+
if service_class = read_attribute("service_class")
|
11
|
+
service_class = service_class.constantize if service_class.is_a?(String)
|
12
|
+
service_class
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Volume < ActiveRecord::Base
|
2
|
+
attr_accessible :name, :path
|
3
|
+
|
4
|
+
def capacity
|
5
|
+
disk.block_size * disk.total_blocks
|
6
|
+
end
|
7
|
+
|
8
|
+
def usage
|
9
|
+
used_bytes = (disk.total_blocks - disk.free_blocks) * disk.block_size
|
10
|
+
used_bytes / capacity.to_f * 100
|
11
|
+
end
|
12
|
+
|
13
|
+
def disk
|
14
|
+
Vmstat.disk(path)
|
15
|
+
end
|
16
|
+
end
|