openvz 1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +202 -0
- data/lib/openvz.rb +21 -0
- data/lib/openvz/confighash.rb +45 -0
- data/lib/openvz/container.rb +341 -0
- data/lib/openvz/inventory.rb +20 -0
- data/lib/openvz/log.rb +67 -0
- data/lib/openvz/shell.rb +90 -0
- data/lib/openvz/util.rb +39 -0
- data/lib/openvz/vendor.rb +41 -0
- data/lib/openvz/vendor/load_systemu.rb +1 -0
- data/lib/openvz/vendor/require_vendored.rb +1 -0
- data/lib/openvz/vendor/systemu/README +160 -0
- data/lib/openvz/vendor/systemu/README.tmpl +30 -0
- data/lib/openvz/vendor/systemu/a.rb +6 -0
- data/lib/openvz/vendor/systemu/gemspec.rb +23 -0
- data/lib/openvz/vendor/systemu/gen_readme.rb +32 -0
- data/lib/openvz/vendor/systemu/install.rb +206 -0
- data/lib/openvz/vendor/systemu/lib/systemu.rb +299 -0
- data/lib/openvz/vendor/systemu/samples/a.rb +11 -0
- data/lib/openvz/vendor/systemu/samples/b.rb +12 -0
- data/lib/openvz/vendor/systemu/samples/c.rb +10 -0
- data/lib/openvz/vendor/systemu/samples/d.rb +11 -0
- data/lib/openvz/vendor/systemu/samples/e.rb +9 -0
- data/lib/openvz/vendor/systemu/samples/f.rb +18 -0
- data/openvz.gemspec +48 -0
- metadata +90 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
module OpenVZ
|
2
|
+
class Inventory < ConfigHash
|
3
|
+
def load
|
4
|
+
s = Shell.new("/usr/sbin/vzlist -a", :cwd => "/tmp")
|
5
|
+
s.runcommand
|
6
|
+
|
7
|
+
ret_code = s.status
|
8
|
+
if ret_code != 0
|
9
|
+
raise StandardError, "Execution of shell command failed. Command: #{s.command} RC: #{ret_code} Error: #{s.stderr}\n\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
s.stdout.each { |l|
|
13
|
+
# inventarize a container object for each avaiable container.
|
14
|
+
if l =~ /^\s+(\d+)\s+(.*)\s+(running|stopped)\s+(.*)\s\s(.*)$/
|
15
|
+
self[$1] = Container.new($1)
|
16
|
+
end
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/openvz/log.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module OpenVZ
|
2
|
+
# A simple class that allows logging at various levels.
|
3
|
+
class Log
|
4
|
+
class << self
|
5
|
+
@logger = nil
|
6
|
+
|
7
|
+
# Obtain the class name of the currently configured logger
|
8
|
+
def logger
|
9
|
+
@logger.class
|
10
|
+
end
|
11
|
+
|
12
|
+
# Logs at info level
|
13
|
+
def info(msg)
|
14
|
+
log(:info, msg)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Logs at warn level
|
18
|
+
def warn(msg)
|
19
|
+
log(:warn, msg)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Logs at debug level
|
23
|
+
def debug(msg)
|
24
|
+
log(:debug, msg)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Logs at fatal level
|
28
|
+
def fatal(msg)
|
29
|
+
log(:fatal, msg)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Logs at error level
|
33
|
+
def error(msg)
|
34
|
+
log(:error, msg)
|
35
|
+
end
|
36
|
+
|
37
|
+
# handle old code that relied on this class being a singleton
|
38
|
+
def instance
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# increments the active log level
|
43
|
+
def cycle_level
|
44
|
+
@logger.cycle_level if @configured
|
45
|
+
end
|
46
|
+
|
47
|
+
# logs a message at a certain level
|
48
|
+
def log(level, msg)
|
49
|
+
t = Time.new.strftime("%H:%M:%S")
|
50
|
+
STDERR.puts "#{t}: #{level}: #{from}: #{msg}"
|
51
|
+
end
|
52
|
+
|
53
|
+
# sets the logger class to use
|
54
|
+
def set_logger(logger)
|
55
|
+
@logger = logger
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# figures out the filename that called us
|
60
|
+
def from
|
61
|
+
from = File.basename(caller[2])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# vi:tabstop=4:expandtab:ai:filetype=ruby
|
data/lib/openvz/shell.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
module OpenVZ
|
2
|
+
#
|
3
|
+
# This code is completely borrowed from marionette-collective.
|
4
|
+
#
|
5
|
+
# Wrapper around systemu that handles executing of system commands
|
6
|
+
# in a way that makes stdout, stderr and status available. Supports
|
7
|
+
# timeouts and sets a default sane environment.
|
8
|
+
#
|
9
|
+
# s = Shell.new("date", opts)
|
10
|
+
# s.runcommand
|
11
|
+
# puts s.stdout
|
12
|
+
# puts s.stderr
|
13
|
+
# puts s.status.exitcode
|
14
|
+
#
|
15
|
+
# Options hash can have:
|
16
|
+
#
|
17
|
+
# cwd - the working directory the command will be run from
|
18
|
+
# stdin - a string that will be sent to stdin of the program
|
19
|
+
# stdout - a variable that will receive stdout, must support <<
|
20
|
+
# stderr - a variable that will receive stdin, must support <<
|
21
|
+
# environment - the shell environment, defaults to include LC_ALL=C
|
22
|
+
# set to nil to clear the environment even of LC_ALL
|
23
|
+
#
|
24
|
+
class Shell
|
25
|
+
attr_reader :environment, :command, :status, :stdout, :stderr, :stdin, :cwd
|
26
|
+
|
27
|
+
def initialize(command, options={})
|
28
|
+
@environment = {"LC_ALL" => "C"}
|
29
|
+
@command = command
|
30
|
+
@status = nil
|
31
|
+
@stdout = ""
|
32
|
+
@stderr = ""
|
33
|
+
@stdin = nil
|
34
|
+
@cwd = "/tmp"
|
35
|
+
|
36
|
+
options.each do |opt, val|
|
37
|
+
case opt.to_s
|
38
|
+
when "stdout"
|
39
|
+
raise "stdout should support <<" unless val.respond_to?("<<")
|
40
|
+
@stdout = val
|
41
|
+
|
42
|
+
when "stderr"
|
43
|
+
raise "stderr should support <<" unless val.respond_to?("<<")
|
44
|
+
@stderr = val
|
45
|
+
|
46
|
+
when "stdin"
|
47
|
+
raise "stdin should be a String" unless val.is_a?(String)
|
48
|
+
@stdin = val
|
49
|
+
|
50
|
+
when "cwd"
|
51
|
+
raise "Directory #{val} does not exist" unless File.directory?(val)
|
52
|
+
@cwd = val
|
53
|
+
|
54
|
+
when "environment"
|
55
|
+
if val.nil?
|
56
|
+
@environment = {}
|
57
|
+
else
|
58
|
+
@environment.merge!(val.dup)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Actually does the systemu call passing in the correct environment, stdout and stderr
|
65
|
+
def runcommand
|
66
|
+
opts = {"env" => @environment,
|
67
|
+
"stdout" => @stdout,
|
68
|
+
"stderr" => @stderr,
|
69
|
+
"cwd" => @cwd}
|
70
|
+
|
71
|
+
opts["stdin"] = @stdin if @stdin
|
72
|
+
|
73
|
+
# Running waitpid on the cid here will start a thread
|
74
|
+
# with the waitpid in it, this way even if the thread
|
75
|
+
# that started this process gets killed due to agent
|
76
|
+
# timeout or such there will still be a waitpid waiting
|
77
|
+
# for the child to exit and not leave zombies.
|
78
|
+
@status = systemu(@command, opts) do |cid|
|
79
|
+
begin
|
80
|
+
sleep 1
|
81
|
+
Process::waitpid(cid)
|
82
|
+
rescue SystemExit
|
83
|
+
rescue Errno::ECHILD
|
84
|
+
rescue Exception => e
|
85
|
+
Log.info("Unexpected exception received while waiting for child process: #{e.class}: #{e}")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/openvz/util.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module OpenVZ
|
2
|
+
class Util
|
3
|
+
# Generate a mac address based upon three different variables
|
4
|
+
def generate_mac(ctid, vlanid, for_host)
|
5
|
+
ctid_str = '%06i' % ctid
|
6
|
+
vlanid_str = '%04i' % vlanid
|
7
|
+
|
8
|
+
bridgemac = [0,0,0,0,0,0]
|
9
|
+
bridgemac[1] = ctid_str[0..1]
|
10
|
+
bridgemac[2] = ctid_str[2..3]
|
11
|
+
bridgemac[3] = ctid_str[4..5]
|
12
|
+
bridgemac[4] = vlanid_str[0..1]
|
13
|
+
bridgemac[5] = vlanid_str[2..3]
|
14
|
+
|
15
|
+
if for_host
|
16
|
+
bridgemac[0] = '12'
|
17
|
+
else
|
18
|
+
bridgemac[0] = '02'
|
19
|
+
end
|
20
|
+
|
21
|
+
# assemble macstring
|
22
|
+
'%s:%s:%s:%s:%s:%s' % bridgemac[0,6]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Search for a specific pattern and replace it with string
|
26
|
+
# in file.
|
27
|
+
def searchandreplace(file, pattern, replace)
|
28
|
+
if File.writeable?(file)
|
29
|
+
File.open(file, 'w') do |f|
|
30
|
+
$<.each_line do |line|
|
31
|
+
f.puts line.gsub(Regexp.new(pattern), replace)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else
|
35
|
+
raise "File not writeable: #{file}."
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module OpenVZ
|
2
|
+
# Simple module to manage vendored code.
|
3
|
+
#
|
4
|
+
# To vendor a library simply download its whole git repo or untar
|
5
|
+
# into vendor/libraryname and create a load_libraryname.rb file
|
6
|
+
# to add its libdir into the $:.
|
7
|
+
#
|
8
|
+
# Once you have that file, add a require line in vendor/require_vendored.rb
|
9
|
+
# which will run after all the load_* files.
|
10
|
+
#
|
11
|
+
# The intention is to not change vendored libraries and to eventually
|
12
|
+
# make adding them in optional so that distros can simply adjust their
|
13
|
+
# packaging to exclude this directory and the various load_xxx.rb scripts
|
14
|
+
# if they wish to install these gems as native packages.
|
15
|
+
class Vendor
|
16
|
+
class << self
|
17
|
+
def vendor_dir
|
18
|
+
File.join([File.dirname(File.expand_path(__FILE__)), "vendor"])
|
19
|
+
end
|
20
|
+
|
21
|
+
def load_entry(entry)
|
22
|
+
Log.debug("Loading vendored #{$1}")
|
23
|
+
load "#{vendor_dir}/#{entry}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def require_libs
|
27
|
+
require 'openvz/vendor/require_vendored'
|
28
|
+
end
|
29
|
+
|
30
|
+
def load_vendored
|
31
|
+
Dir.entries(vendor_dir).each do |entry|
|
32
|
+
if entry.match(/load_(\w+?)\.rb$/)
|
33
|
+
load_entry entry
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
require_libs
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
$: << File.join([File.dirname(__FILE__), "systemu/lib"])
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'systemu'
|
@@ -0,0 +1,160 @@
|
|
1
|
+
NAME
|
2
|
+
|
3
|
+
systemu
|
4
|
+
|
5
|
+
SYNOPSIS
|
6
|
+
|
7
|
+
univeral capture of stdout and stderr and handling of child process pid for windows, *nix, etc.
|
8
|
+
|
9
|
+
URIS
|
10
|
+
|
11
|
+
http://rubyforge.org/projects/codeforpeople/
|
12
|
+
http://codeforpeople.com/lib/ruby/
|
13
|
+
http://codeforpeople.rubyforge.org/svn/
|
14
|
+
|
15
|
+
INSTALL
|
16
|
+
|
17
|
+
gem install systemu
|
18
|
+
|
19
|
+
HISTORY
|
20
|
+
|
21
|
+
1.2.0
|
22
|
+
|
23
|
+
- fixed handling of background thread management - needed
|
24
|
+
Thread.current.abort_on_exception = true
|
25
|
+
|
26
|
+
- fixed reporting of child pid, it was reported as the parent's pid before
|
27
|
+
|
28
|
+
SAMPLES
|
29
|
+
|
30
|
+
<========< samples/a.rb >========>
|
31
|
+
|
32
|
+
~ > cat samples/a.rb
|
33
|
+
|
34
|
+
#
|
35
|
+
# systemu can be used on any platform to return status, stdout, and stderr of
|
36
|
+
# any command. unlike other methods like open3/popen4 there is zero danger of
|
37
|
+
# full pipes or threading issues hanging your process or subprocess.
|
38
|
+
#
|
39
|
+
require 'systemu'
|
40
|
+
|
41
|
+
date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
|
42
|
+
|
43
|
+
status, stdout, stderr = systemu date
|
44
|
+
p [ status, stdout, stderr ]
|
45
|
+
|
46
|
+
~ > ruby samples/a.rb
|
47
|
+
|
48
|
+
[#<Process::Status: pid=987,exited(0)>, "Thu Dec 06 16:01:59 -0700 2007\n", "Thu Dec 06 16:01:59 -0700 2007\n"]
|
49
|
+
|
50
|
+
|
51
|
+
<========< samples/b.rb >========>
|
52
|
+
|
53
|
+
~ > cat samples/b.rb
|
54
|
+
|
55
|
+
#
|
56
|
+
# quite a few keys can be passed to the command to alter it's behaviour. if
|
57
|
+
# either stdout or stderr is supplied those objects should respond_to? '<<'
|
58
|
+
# and only status will be returned
|
59
|
+
#
|
60
|
+
require 'systemu'
|
61
|
+
|
62
|
+
date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
|
63
|
+
|
64
|
+
stdout, stderr = '', ''
|
65
|
+
status = systemu date, 'stdout' => stdout, 'stderr' => stderr
|
66
|
+
p [ status, stdout, stderr ]
|
67
|
+
|
68
|
+
~ > ruby samples/b.rb
|
69
|
+
|
70
|
+
[#<Process::Status: pid=992,exited(0)>, "Thu Dec 06 16:01:59 -0700 2007\n", "Thu Dec 06 16:01:59 -0700 2007\n"]
|
71
|
+
|
72
|
+
|
73
|
+
<========< samples/c.rb >========>
|
74
|
+
|
75
|
+
~ > cat samples/c.rb
|
76
|
+
|
77
|
+
#
|
78
|
+
# of course stdin can be supplied too. synonyms for 'stdin' include '0' and
|
79
|
+
# 0. the other stdio streams have similar shortcuts
|
80
|
+
#
|
81
|
+
require 'systemu'
|
82
|
+
|
83
|
+
cat = %q( ruby -e" ARGF.each{|line| puts line} " )
|
84
|
+
|
85
|
+
status = systemu cat, 0=>'the stdin for cat', 1=>stdout=''
|
86
|
+
puts stdout
|
87
|
+
|
88
|
+
~ > ruby samples/c.rb
|
89
|
+
|
90
|
+
the stdin for cat
|
91
|
+
|
92
|
+
|
93
|
+
<========< samples/d.rb >========>
|
94
|
+
|
95
|
+
~ > cat samples/d.rb
|
96
|
+
|
97
|
+
#
|
98
|
+
# the cwd can be supplied
|
99
|
+
#
|
100
|
+
require 'systemu'
|
101
|
+
require 'tmpdir'
|
102
|
+
|
103
|
+
pwd = %q( ruby -e" STDERR.puts Dir.pwd " )
|
104
|
+
|
105
|
+
status = systemu pwd, 2=>(stderr=''), :cwd=>Dir.tmpdir
|
106
|
+
puts stderr
|
107
|
+
|
108
|
+
|
109
|
+
~ > ruby samples/d.rb
|
110
|
+
|
111
|
+
/private/tmp
|
112
|
+
|
113
|
+
|
114
|
+
<========< samples/e.rb >========>
|
115
|
+
|
116
|
+
~ > cat samples/e.rb
|
117
|
+
|
118
|
+
#
|
119
|
+
# any environment vars specified are merged into the child's environment
|
120
|
+
#
|
121
|
+
require 'systemu'
|
122
|
+
|
123
|
+
env = %q( ruby -r yaml -e" puts ENV[ 'answer' ] " )
|
124
|
+
|
125
|
+
status = systemu env, 1=>stdout='', 'env'=>{ 'answer' => 0b101010 }
|
126
|
+
puts stdout
|
127
|
+
|
128
|
+
~ > ruby samples/e.rb
|
129
|
+
|
130
|
+
42
|
131
|
+
|
132
|
+
|
133
|
+
<========< samples/f.rb >========>
|
134
|
+
|
135
|
+
~ > cat samples/f.rb
|
136
|
+
|
137
|
+
#
|
138
|
+
# if a block is specified then it is passed the child pid and run in a
|
139
|
+
# background thread. note that this thread will __not__ be blocked during the
|
140
|
+
# execution of the command so it may do useful work such as killing the child
|
141
|
+
# if execution time passes a certain threshold
|
142
|
+
#
|
143
|
+
require 'systemu'
|
144
|
+
|
145
|
+
looper = %q( ruby -e" loop{ STDERR.puts Time.now.to_i; sleep 1 } " )
|
146
|
+
|
147
|
+
status, stdout, stderr =
|
148
|
+
systemu looper do |cid|
|
149
|
+
sleep 3
|
150
|
+
Process.kill 9, cid
|
151
|
+
end
|
152
|
+
|
153
|
+
p status
|
154
|
+
p stderr
|
155
|
+
|
156
|
+
~ > ruby samples/f.rb
|
157
|
+
|
158
|
+
#<Process::Status: pid=1012,signaled(SIGKILL=9)>
|
159
|
+
"1196982119\n1196982120\n1196982121\n"
|
160
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
NAME
|
2
|
+
|
3
|
+
systemu
|
4
|
+
|
5
|
+
SYNOPSIS
|
6
|
+
|
7
|
+
univeral capture of stdout and stderr and handling of child process pid for windows, *nix, etc.
|
8
|
+
|
9
|
+
URIS
|
10
|
+
|
11
|
+
http://rubyforge.org/projects/codeforpeople/
|
12
|
+
http://codeforpeople.com/lib/ruby/
|
13
|
+
http://codeforpeople.rubyforge.org/svn/
|
14
|
+
|
15
|
+
INSTALL
|
16
|
+
|
17
|
+
gem install systemu
|
18
|
+
|
19
|
+
HISTORY
|
20
|
+
|
21
|
+
1.2.0
|
22
|
+
|
23
|
+
- fixed handling of background thread management - needed
|
24
|
+
Thread.current.abort_on_exception = true
|
25
|
+
|
26
|
+
- fixed reporting of child pid, it was reported as the parent's pid before
|
27
|
+
|
28
|
+
SAMPLES
|
29
|
+
|
30
|
+
@samples
|