Class Dsadmin::System
In: lib/dsadmin/system.rb
Parent: Object

System abstraction class

Singleton with convenience methods for all kinds of system-specific stuff. If something is covered here, don‘t even think of doing it manually — that would mess up the testing environment and probably also the system as such.

See also:SystemCommand
See also:SystemPath
See also:CoreClient

Methods

Included Modules

Contractor Singleton

Constants

OS_UNKNOWN = 0
OS_LINUX = 1
OS_SOLARIS = 2
OS_FREEBSD = 3

Attributes

disable_uid_change  [RW] 
original_uid  [R] 
os_type  [R] 

Public Class methods

[Source]

     # File lib/dsadmin/system.rb, line 175
175:   def initialize
176:         @euid_mutex   = Mutex.new
177:         @original_uid = nil
178:         @os_type      = getOSType
179:   end

Public Instance methods

Drop our EUID/EGID to safe values (nobody/nogroup)

[Source]

    # File lib/dsadmin/system.rb, line 58
58:   def dropPrivileges
59:         setuidgid('nobody', 'nogroup')
60:   end

Get the hostname of the computer. Only works on unices so far!

[Source]

     # File lib/dsadmin/system.rb, line 151
151:   def hostname
152:     Socket.gethostname.strip[/^[^.]+/]
153:   end

Kill a child process.

First tries a SIGTERM, and if that does not help a SIGKILL

aChildOrThread:Either the PID of the child process, or the thread object that spawned the child
aTimeout:Seconds to wait for termination (total time for both signale)

[Source]

     # File lib/dsadmin/system.rb, line 98
 98:   def killChild(aChildOrThread = Thread.current, aTimeout = 5)
 99:         if(aChildOrThread.kind_of?(Thread))
100:                 pid = aChildOrThread[:exec_pid]
101:         else
102:                 pid = aChildOrThread
103:         end
104: 
105:         return unless(pid)
106: 
107:         ['SIGTERM', 'SIGKILL'].each { |sig|
108:                 runAs('root') {
109:                         Process.kill(sig, pid)
110:                 }
111: 
112:                 begin
113:                         timeout(aTimeout / 2.0) { #/
114:                                 Process.waitpid(pid)
115:                         }
116:                 rescue TimeoutError
117:                         next  # try next signal
118:                 else
119:                         break # success => no more killing
120:                 end
121:         }
122: 
123:         aChildOrThread[:exec_pid] = nil if(aChildOrThread.kind_of?(Thread))
124:   end

Get the current time (as per Time.now).

Abstraction to allow for easier testing. Use it !!

[Source]

     # File lib/dsadmin/system.rb, line 159
159:   def now
160:         Time.now
161:   end

Run the given block (always give a block) as the specified user/group.

Both numerical IDs and Names (Strings) can be used for aUserID and aGroupID.

[Source]

    # File lib/dsadmin/system.rb, line 73
73:   def runAs(aUserID, aGroupID = Process.egid)
74:         assertTrue(block_given?)
75: 
76:         begin
77:                 # We make sure that no other thread can be executed
78:                 # as long as the process has a privileged (E)UID
79:                 Thread.critical = true
80: 
81:                 setuidgid(aUserID, aGroupID)
82:                 yield
83:         ensure
84:                 dropPrivileges
85:                 Thread.critical = false
86:         end
87:   end

Determine the current load average of the system (returns a Float).

[Source]

     # File lib/dsadmin/system.rb, line 128
128:   def sysload
129:         stat = File.stat('/proc/loadavg')
130:         tmp = nil
131: 
132:         if(stat.readable?)
133:                 crit = Thread.critical
134:                 begin
135:                         Thread.critical = true
136:                         tmp = File.read('/proc/loadavg')
137:                 ensure
138:                         Thread.critical = crit
139:                 end
140:         else
141:                 tmp = `uptime`
142:                 tmp = tmp[/load average:\s*(\d+\.\d+)/]
143:         end
144: 
145:         tmp = tmp[/(\d+\.\d+)/]
146:         return tmp.to_f
147:   end

Get a human-readable and canonical string representation of the given time

[Source]

     # File lib/dsadmin/system.rb, line 165
165:   def time2string(aTime = now)
166:         aTime.gmtime.strftime('%Y-%m-%d %H:%M:%S +0000')
167:   end

Get the username (String) we are currently running as (matching the EUID)

[Source]

    # File lib/dsadmin/system.rb, line 64
64:   def username
65:         Etc.getpwuid(Process.euid).name
66:   end

Private Instance methods

[Source]

     # File lib/dsadmin/system.rb, line 211
211:   def getOSType
212:         case(Config::CONFIG['host'])
213:           when /linux/   : return OS_LINUX
214:           when /solaris/ : return OS_SOLARIS
215:           when /freebsd/ : return OS_FREEBSD
216:           else
217:                 log.warning("Found unrecognizes OS type '#{Config::CONFIG['host']}'")
218:                 return OS_UNKNOWN
219:         end
220:   end

[Source]

     # File lib/dsadmin/system.rb, line 182
182:   def setuidgid(aUserID, aGroupID)
183:         @original_uid ||= Process.uid
184:         return if disable_uid_change
185:         requireTrue((Process.uid == 0) || (@original_uid == 0))
186: 
187: #        puts "setuidgid: #{Process.uid}:#{Process.gid} => #{aUserID}:#{aGroupID}"
188:         @euid_mutex.synchronize {
189:                 Process.uid  = 0 if(os_type == OS_LINUX)
190:                 Process.euid = 0
191: 
192:                 if(aGroupID.kind_of?(Integer))
193:                         Process.egid = aGroupID
194:                         Process.gid  = aGroupID if(os_type == OS_LINUX)
195:                 else
196:                         Process.egid = Etc.getgrnam(aGroupID).gid
197:                         Process.gid  = Etc.getgrnam(aGroupID).gid if(os_type == OS_LINUX)
198:                 end
199: 
200:                 if(aUserID.kind_of?(Integer))
201:                         Process.euid = aUserID
202:                         Process.uid  = aUserID if(os_type == OS_LINUX)
203:                 else
204:                         Process.euid = Etc.getpwnam(aUserID).uid
205:                         Process.uid  = Etc.getpwnam(aUserID).uid if(os_type == OS_LINUX)
206:                 end
207:         }
208:   end

[Validate]