openvz 1.5 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,115 @@
1
+ OpenVZ API
2
+ ==========
3
+
4
+ OpenVZ is a container based virtualization for Linux. This API will allow you
5
+ to easily write tools to manipulate containers on a host.
6
+
7
+ USAGE
8
+ =====
9
+
10
+ Here are some examples on how you can use the API.
11
+
12
+ <pre>
13
+ container = OpenVZ::Container.new('110')
14
+ container.start
15
+ </pre>
16
+
17
+ UBC Access
18
+ ----------
19
+
20
+ To get the current value of privvmpages you can use the config accessor.
21
+
22
+ <pre>
23
+ container = OpenVZ::Container.new('110')
24
+ puts container.config.privvmpages
25
+ </pre>
26
+
27
+ Also in case you would like to update a UBC, use the same config accessor.
28
+
29
+ <pre>
30
+ container = OpenVZ::Container.new('110')
31
+ container.config.kmemsize = '5505024:5872024'
32
+ </pre>
33
+
34
+ Inventory
35
+ ---------
36
+
37
+ <pre>
38
+ # Create an inventoy of all containers
39
+ inventory = OpenVZ::Inventory.new()
40
+ inventory.load
41
+ # Print a certain containers configuration option
42
+ inventory['110'].config.privvmpages
43
+ # Restart
44
+ inventory['110'].restart
45
+ </pre>
46
+
47
+
48
+ Provisioning
49
+ ============
50
+
51
+ You can as well use the build in functions to provision a new container.
52
+
53
+ <pre>
54
+ container = OpenVZ::Container.new('110')
55
+
56
+ container.create( :ostemplate => 'centos-5-x86_64-minimal',
57
+ :config => 'vps.basic' )
58
+
59
+ container.start
60
+ </pre>
61
+
62
+
63
+ Debootstrapping Containers
64
+ -------------------------
65
+
66
+ If your host is running Debian and you want to bootstrap a new Debian container,
67
+ you do not have to use a template, just use debootstrap.
68
+
69
+ <pre>
70
+ container = OpenVZ::Container.new('110')
71
+
72
+ container.create( :ostemplate => 'debain-6.0-bootstrap',
73
+ :config => 'vps.basic' )
74
+
75
+ container.debootstrap( :dist => 'squeeze',
76
+ :mirror => 'http://cdn.debian.net/debian' )
77
+
78
+ container.set( :nameserver => '8.8.8.8',
79
+ :ipadd => '10.0.0.2',
80
+ :hostname => 'mia.ono.at' )
81
+
82
+ container.start
83
+
84
+ # Update the system
85
+ container.command('aptitude update ; aptitude -y upgrade ; apt-key update')
86
+
87
+ # Install puppet
88
+ container.command('aptitude -o Aptitude::Cmdline::ignore-trust-violations=true -y install puppet')
89
+ </pre>
90
+
91
+ NOTE: You need to create an empty template for this to work. Here is how
92
+ you do that:
93
+
94
+ <pre>
95
+ mkdir /tmp/empty-template
96
+ # We need a file in the tarball since vzcreate barfs on empty tarballs
97
+ touch /tmp/empty-template/BOOSTRAPPED
98
+ tar -zc -C /tmp/empty-template . -f debian-6.0-bootstrap.tar
99
+ gzip debian-6.0-bootstrap.tar
100
+ mv debian-6.0-bootstrap.tar.gz /var/lib/vz/template/cache
101
+ </pre>
102
+
103
+
104
+ BUGS
105
+ ====
106
+
107
+ For bugs or feature requests, please use the GitHub issue tracker.
108
+
109
+ https://github.com/sts/ruby-openvz/issues
110
+
111
+
112
+ WHO
113
+ ===
114
+
115
+ Stefan Schlesinger / sts@ono.at / @stsonoat / http://sts.ono.at
@@ -37,6 +37,7 @@ module OpenVZ
37
37
  def initialize(ctid=false)
38
38
  @ctid = ctid
39
39
  @vzctl = "/usr/sbin/vzctl"
40
+ @vzmigrate = "/usr/sbin/vzmigrate"
40
41
  @configfile = "/etc/vz/conf/#{ctid}.conf"
41
42
 
42
43
  @config = Config.new(load_config_file)
@@ -106,6 +107,13 @@ module OpenVZ
106
107
  cmd = "#{@vzctl} restore #{@ctid} --dumpfile #{snapshot_path}"
107
108
  execute(cmd)
108
109
  end
110
+
111
+ # Migrate container to another node
112
+ #
113
+ def migrate(destination_address, options=%w(--remove-area yes --online --rsync=-az))
114
+ cmd = "#{@vzmigrate} #{options.join ' '} #{destination_address} #{@ctid}"
115
+ execute(cmd)
116
+ end
109
117
 
110
118
 
111
119
  # Update one or multiple Container properties and keep the configration
@@ -197,8 +205,53 @@ module OpenVZ
197
205
  # '#\1')
198
206
  end
199
207
 
208
+ # Write into or copy a file into a container
209
+ #
210
+ # The destination file will be prepended with the containers private directory. If
211
+ # you specify a source, this is relative to the virtualization hosts root directory.
212
+ #
213
+ #
214
+ # @example Create /etc/hostname
215
+ #
216
+ # container.file('/etc/hostname', :content => 'vm01')
217
+ #
218
+ # @example Copy a file from /etc/vz/template.conf/hosts (host) to /etc/hosts (container)
219
+ #
220
+ # container.file('/etc/hosts', :source => '/etc/hosts'
221
+ #
222
+ #
223
+ # @param filename Destination filename, relative to the containers root
224
+ # @param :source The source filename, relative to the virtualization hosts root directory
225
+ # @param :content Pass a string which will be written to the file.
226
+ # @param :mode Specify the file mode.
227
+ def file(filename, options={})
228
+ unless filename
229
+ raise ArgumentError, "file requires destination filename as first argument."
230
+ end
231
+
232
+ if options[:source] and options[:content]
233
+ raise ArgumentError, "file can either take :source or :content as an argument."
234
+ end
235
+
236
+ destination ="#{@config.ve_private}/#{filename}"
237
+
238
+ if options[:source]
239
+ FileUtils.cp(options[:source], destination)
240
+ end
241
+
242
+ if options[:content]
243
+ File.open(destination, 'w') { |file|
244
+ file.write(options[:content])
245
+ }
246
+ end
247
+
248
+ if options[:mode]
249
+ FileUtils.chmod options[:mode], destination
250
+ end
251
+ end
252
+
200
253
 
201
- # Copy a file from the hardware node into the container.
254
+ # Copy a file from the hardware node into the container. (OBSOLETE)
202
255
  #
203
256
  # @example Copy resolv.conf
204
257
  # container.cp_into(
@@ -252,6 +305,16 @@ module OpenVZ
252
305
  raw.split(/\W/).first.to_i
253
306
  end
254
307
 
308
+ # Add veth to a CT
309
+ # vzctl set <CTID> --netif_add <ifname>[,<mac>,<host_ifname>,<host_mac>,<bridge>]
310
+ #
311
+ # @param [Hash] interface settings (keys as listed above)
312
+ def add_veth veth
313
+ cmd = "#{@vzctl} set #{@ctid} --netif_add #{veth[:ifname]},#{veth[:mac]},#{veth[:host_ifname]}," \
314
+ "#{veth[:host_mac]}, #{veth[:bridge]}"
315
+ execute(cmd)
316
+ end
317
+
255
318
 
256
319
  ####
257
320
  #### Helper methods
@@ -357,15 +420,7 @@ module OpenVZ
357
420
 
358
421
  # Execute a System Command
359
422
  def execute(cmd)
360
-
361
- Log.debug("#{cmd}")
362
-
363
- s = Shell.new("#{cmd}", :cwd => "/tmp")
364
- s.runcommand
365
- if s.status.exitstatus != 0
366
- raise "Cannot execute: '#{cmd}'. Return code: #{s.status.exitstatus}. Stderr: #{s.stderr}"
367
- end
368
- s.stdout
423
+ Util.execute(cmd)
369
424
  end
370
425
  end
371
426
  end
@@ -1,24 +1,25 @@
1
1
  module OpenVZ
2
2
  class Inventory < ConfigHash
3
+ def initialize()
4
+ @vzlist = "/usr/sbin/vzlist"
5
+ end
6
+
3
7
  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|
8
+ Util.execute("#{@vzlist} -a").each { |l|
13
9
  # inventarize a container object for each avaiable container.
14
10
  if l =~ /^\s+(\d+)\s+(.*)\s+(running|stopped)\s+(.*)\s\s(.*)$/
15
11
  self[$1] = Container.new($1)
16
12
  end
17
13
  }
18
14
  end
15
+
16
+ # Returns cotainers' id as a array of strings
17
+ def ids
18
+ Util.execute("#{@vzlist} -a1").split
19
+ end
19
20
 
20
21
  def to_hash
21
22
  @data
22
23
  end
23
24
  end
24
- end
25
+ end
data/lib/openvz/util.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module OpenVZ
2
- class Util
2
+ class Util
3
3
  # Generate a mac address based upon three different variables
4
4
  def generate_mac(ctid, vlanid, for_host)
5
5
  ctid_str = '%06i' % ctid
@@ -35,5 +35,25 @@ module OpenVZ
35
35
  raise "File not writeable: #{file}."
36
36
  end
37
37
  end
38
+
39
+ class << self
40
+ # Class variable which denotes whether execute commands using sudo
41
+ # should be true or false
42
+ attr_accessor :enforce_sudo
43
+ end
44
+
45
+ # Execute a System Command
46
+ def self.execute(cmd, params = {:cwd => "/tmp"})
47
+ cmd = "sudo " + cmd if self.enforce_sudo
48
+
49
+ Log.debug("#{cmd}")
50
+
51
+ s = Shell.new("#{cmd}", params)
52
+ s.runcommand
53
+ if s.status.exitstatus != 0
54
+ raise "Cannot execute: '#{cmd}'. Return code: #{s.status.exitstatus}. Stderr: #{s.stderr}"
55
+ end
56
+ s.stdout
57
+ end
38
58
  end
39
59
  end
data/lib/openvz.rb CHANGED
@@ -11,7 +11,7 @@ module OpenVZ
11
11
  autoload :Util, "openvz/util"
12
12
  autoload :ConfigHash, "openvz/confighash"
13
13
 
14
- VERSION = "1.5"
14
+ VERSION = "1.5.3"
15
15
 
16
16
  def self.version
17
17
  VERSION
data/openvz.gemspec CHANGED
@@ -1,48 +1,24 @@
1
+ $: << File.expand_path('../lib', __FILE__)
2
+
3
+ require 'openvz'
4
+
1
5
  Gem::Specification.new do |s|
2
6
  s.name = 'openvz'
3
- s.version = '1.5'
4
- s.date = '2012-04-30'
7
+ s.version = OpenVZ::VERSION
8
+ s.date = '2012-10-09'
5
9
  s.authors = 'Stefan Schlesinger'
6
10
  s.email = 'sts@ono.at'
7
11
  s.homepage = 'http://github.com/sts/ruby-openvz'
8
12
 
9
13
  s.summary = 'OpenVZ API'
10
14
  s.description = 'OpenVZ is a container based virtualization for Linux. This API will
11
- allow you to easily write tools to manipulate containers on a host.'
15
+ allow you to easily write tools to manipulate containers on a host.'
16
+
17
+ s.has_rdoc = false
12
18
 
13
19
  s.extra_rdoc_files = %w[COPYING]
14
20
 
15
- # = MANIFEST =
16
- s.files = %w[
17
- openvz.gemspec
18
- lib/openvz.rb
19
- lib/openvz/vendor
20
- lib/openvz/vendor/systemu
21
- lib/openvz/vendor/systemu/README.tmpl
22
- lib/openvz/vendor/systemu/gemspec.rb
23
- lib/openvz/vendor/systemu/install.rb
24
- lib/openvz/vendor/systemu/samples
25
- lib/openvz/vendor/systemu/samples/e.rb
26
- lib/openvz/vendor/systemu/samples/b.rb
27
- lib/openvz/vendor/systemu/samples/d.rb
28
- lib/openvz/vendor/systemu/samples/c.rb
29
- lib/openvz/vendor/systemu/samples/a.rb
30
- lib/openvz/vendor/systemu/samples/f.rb
31
- lib/openvz/vendor/systemu/gen_readme.rb
32
- lib/openvz/vendor/systemu/lib
33
- lib/openvz/vendor/systemu/lib/systemu.rb
34
- lib/openvz/vendor/systemu/a.rb
35
- lib/openvz/vendor/systemu/README
36
- lib/openvz/vendor/require_vendored.rb
37
- lib/openvz/vendor/load_systemu.rb
38
- lib/openvz/log.rb
39
- lib/openvz/inventory.rb
40
- lib/openvz/util.rb
41
- lib/openvz/vendor.rb
42
- lib/openvz/confighash.rb
43
- lib/openvz/container.rb
44
- lib/openvz/shell.rb
45
- lib/openvz.rb
46
- ]
21
+ s.add_dependency 'systemu'
47
22
 
23
+ s.files = Dir.glob("{**/**/**/**/*}")
48
24
  end
metadata CHANGED
@@ -6,7 +6,8 @@ version: !ruby/object:Gem::Version
6
6
  segments:
7
7
  - 1
8
8
  - 5
9
- version: "1.5"
9
+ - 3
10
+ version: 1.5.3
10
11
  platform: ruby
11
12
  authors:
12
13
  - Stefan Schlesinger
@@ -14,9 +15,22 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2012-04-30 00:00:00 Z
18
- dependencies: []
19
-
18
+ date: 2012-10-09 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: systemu
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
20
34
  description: |-
21
35
  OpenVZ is a container based virtualization for Linux. This API will
22
36
  allow you to easily write tools to manipulate containers on a host.
@@ -28,31 +42,18 @@ extensions: []
28
42
  extra_rdoc_files:
29
43
  - COPYING
30
44
  files:
31
- - openvz.gemspec
32
- - lib/openvz.rb
33
- - lib/openvz/vendor/systemu/README.tmpl
34
- - lib/openvz/vendor/systemu/gemspec.rb
35
- - lib/openvz/vendor/systemu/install.rb
36
- - lib/openvz/vendor/systemu/samples/e.rb
37
- - lib/openvz/vendor/systemu/samples/b.rb
38
- - lib/openvz/vendor/systemu/samples/d.rb
39
- - lib/openvz/vendor/systemu/samples/c.rb
40
- - lib/openvz/vendor/systemu/samples/a.rb
41
- - lib/openvz/vendor/systemu/samples/f.rb
42
- - lib/openvz/vendor/systemu/gen_readme.rb
43
- - lib/openvz/vendor/systemu/lib/systemu.rb
44
- - lib/openvz/vendor/systemu/a.rb
45
- - lib/openvz/vendor/systemu/README
46
- - lib/openvz/vendor/require_vendored.rb
47
- - lib/openvz/vendor/load_systemu.rb
48
- - lib/openvz/log.rb
49
- - lib/openvz/inventory.rb
50
- - lib/openvz/util.rb
51
- - lib/openvz/vendor.rb
45
+ - COPYING
52
46
  - lib/openvz/confighash.rb
53
47
  - lib/openvz/container.rb
48
+ - lib/openvz/inventory.rb
49
+ - lib/openvz/log.rb
54
50
  - lib/openvz/shell.rb
55
- - COPYING
51
+ - lib/openvz/util.rb
52
+ - lib/openvz/vendor/require_vendored.rb
53
+ - lib/openvz/vendor.rb
54
+ - lib/openvz.rb
55
+ - openvz.gemspec
56
+ - README.md
56
57
  homepage: http://github.com/sts/ruby-openvz
57
58
  licenses: []
58
59
 
@@ -1 +0,0 @@
1
- $: << File.join([File.dirname(__FILE__), "systemu/lib"])
@@ -1,160 +0,0 @@
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
-
@@ -1,30 +0,0 @@
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
@@ -1,6 +0,0 @@
1
- require 'systemu'
2
-
3
-
4
- systemu 'date' do |cid|
5
- p cid
6
- end
@@ -1,23 +0,0 @@
1
- lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
2
-
3
- require 'rubygems'
4
-
5
- Gem::Specification::new do |spec|
6
- spec.name = lib
7
- spec.version = version
8
- spec.platform = Gem::Platform::RUBY
9
- spec.summary = lib
10
-
11
- spec.files = Dir::glob "**/**"
12
- spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
13
-
14
- spec.require_path = "lib"
15
- spec.autorequire = lib
16
-
17
- spec.has_rdoc = File::exist? "doc"
18
- spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
19
-
20
- spec.author = "Ara T. Howard"
21
- spec.email = "ara.t.howard@noaa.gov"
22
- spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
23
- end
@@ -1,32 +0,0 @@
1
- require 'pathname'
2
-
3
- $VERBOSE=nil
4
-
5
- def indent s, n = 2
6
- ws = ' ' * n
7
- s.gsub %r/^/, ws
8
- end
9
-
10
- template = IO::read 'README.tmpl'
11
-
12
- samples = ''
13
- prompt = '~ > '
14
-
15
- Dir['sample*/*'].sort.each do |sample|
16
- samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
17
-
18
- cmd = "cat #{ sample }"
19
- samples << indent(prompt + cmd, 2) << "\n\n"
20
- samples << indent(`#{ cmd }`, 4) << "\n"
21
-
22
- cmd = "ruby #{ sample }"
23
- samples << indent(prompt + cmd, 2) << "\n\n"
24
-
25
- cmd = "ruby -W0 -Ilib #{ sample }"
26
- samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
27
- end
28
-
29
- #samples.gsub! %r/^/, ' '
30
-
31
- readme = template.gsub %r/^\s*@samples\s*$/, samples
32
- print readme
@@ -1,206 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'rbconfig'
3
- require 'find'
4
- require 'ftools'
5
- require 'tempfile'
6
- include Config
7
-
8
- LIBDIR = "lib"
9
- LIBDIR_MODE = 0644
10
-
11
- BINDIR = "bin"
12
- BINDIR_MODE = 0755
13
-
14
-
15
- $srcdir = CONFIG["srcdir"]
16
- $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
17
- $libdir = File.join(CONFIG["libdir"], "ruby", $version)
18
- $archdir = File.join($libdir, CONFIG["arch"])
19
- $site_libdir = $:.find {|x| x =~ /site_ruby$/}
20
- $bindir = CONFIG["bindir"] || CONFIG['BINDIR']
21
- $ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
22
- $ruby_ext = CONFIG['EXEEXT'] || ''
23
- $ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
24
-
25
- if !$site_libdir
26
- $site_libdir = File.join($libdir, "site_ruby")
27
- elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
28
- $site_libdir = File.join($site_libdir, $version)
29
- end
30
-
31
- def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
32
- #{{{
33
- path = []
34
- dir = []
35
- Find.find(srcdir) do |f|
36
- next unless FileTest.file?(f)
37
- next if (f = f[srcdir.length+1..-1]) == nil
38
- next if (/CVS$/ =~ File.dirname(f))
39
- next if f =~ %r/\.lnk/
40
- path.push f
41
- dir |= [File.dirname(f)]
42
- end
43
- for f in dir
44
- next if f == "."
45
- next if f == "CVS"
46
- File::makedirs(File.join(destdir, f))
47
- end
48
- for f in path
49
- next if (/\~$/ =~ f)
50
- next if (/^\./ =~ File.basename(f))
51
- unless bin
52
- File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
53
- else
54
- from = File.join(srcdir, f)
55
- to = File.join(destdir, f)
56
- shebangify(from) do |sf|
57
- $deferr.print from, " -> ", File::catname(from, to), "\n"
58
- $deferr.printf "chmod %04o %s\n", mode, to
59
- File::install(sf, to, mode, false)
60
- end
61
- end
62
- end
63
- #}}}
64
- end
65
- def shebangify f
66
- #{{{
67
- open(f) do |fd|
68
- buf = fd.read 42
69
- if buf =~ %r/^\s*#\s*!.*ruby/o
70
- ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
71
- begin
72
- fd.rewind
73
- ftmp.puts "#!#{ $ruby }"
74
- while((buf = fd.read(8192)))
75
- ftmp.write buf
76
- end
77
- ftmp.close
78
- yield ftmp.path
79
- ensure
80
- ftmp.close!
81
- end
82
- else
83
- yield f
84
- end
85
- end
86
- #}}}
87
- end
88
- def ARGV.switch
89
- #{{{
90
- return nil if self.empty?
91
- arg = self.shift
92
- return nil if arg == '--'
93
- if arg =~ /^-(.)(.*)/
94
- return arg if $1 == '-'
95
- raise 'unknown switch "-"' if $2.index('-')
96
- self.unshift "-#{$2}" if $2.size > 0
97
- "-#{$1}"
98
- else
99
- self.unshift arg
100
- nil
101
- end
102
- #}}}
103
- end
104
- def ARGV.req_arg
105
- #{{{
106
- self.shift || raise('missing argument')
107
- #}}}
108
- end
109
- def linkify d, linked = []
110
- #--{{{
111
- if test ?d, d
112
- versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
113
- versioned.each do |v|
114
- src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
115
- lnk = nil
116
- begin
117
- if test ?l, dst
118
- lnk = "#{ dst }.lnk"
119
- puts "#{ dst } -> #{ lnk }"
120
- File::rename dst, lnk
121
- end
122
- unless test ?e, dst
123
- puts "#{ src } -> #{ dst }"
124
- File::copy src, dst
125
- linked << dst
126
- end
127
- ensure
128
- if lnk
129
- at_exit do
130
- puts "#{ lnk } -> #{ dst }"
131
- File::rename lnk, dst
132
- end
133
- end
134
- end
135
- end
136
- end
137
- linked
138
- #--}}}
139
- end
140
-
141
-
142
- #
143
- # main program
144
- #
145
-
146
- libdir = $site_libdir
147
- bindir = $bindir
148
- no_linkify = false
149
- linked = nil
150
- help = false
151
-
152
- usage = <<-usage
153
- #{ File::basename $0 }
154
- -d, --destdir <destdir>
155
- -l, --libdir <libdir>
156
- -b, --bindir <bindir>
157
- -r, --ruby <ruby>
158
- -n, --no_linkify
159
- -s, --sudo
160
- -h, --help
161
- usage
162
-
163
- begin
164
- while switch = ARGV.switch
165
- case switch
166
- when '-d', '--destdir'
167
- libdir = ARGV.req_arg
168
- when '-l', '--libdir'
169
- libdir = ARGV.req_arg
170
- when '-b', '--bindir'
171
- bindir = ARGV.req_arg
172
- when '-r', '--ruby'
173
- $ruby = ARGV.req_arg
174
- when '-n', '--no_linkify'
175
- no_linkify = true
176
- when '-s', '--sudo'
177
- sudo = 'sudo'
178
- when '-h', '--help'
179
- help = true
180
- else
181
- raise "unknown switch #{switch.dump}"
182
- end
183
- end
184
- rescue
185
- STDERR.puts $!.to_s
186
- STDERR.puts usage
187
- exit 1
188
- end
189
-
190
- if help
191
- STDOUT.puts usage
192
- exit
193
- end
194
-
195
- unless no_linkify
196
- linked = linkify('lib') + linkify('bin')
197
- end
198
-
199
- system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
200
-
201
- install_rb(LIBDIR, libdir, LIBDIR_MODE)
202
- install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
203
-
204
- if linked
205
- linked.each{|path| File::rm_f path}
206
- end
@@ -1,299 +0,0 @@
1
- # vim: ts=2:sw=2:sts=2:et:fdm=marker
2
- require 'tmpdir'
3
- require 'socket'
4
- require 'fileutils'
5
- require 'rbconfig'
6
- require 'thread'
7
- require 'yaml'
8
-
9
- class Object
10
- def systemu(*a, &b) SystemUniversal.new(*a, &b).systemu end
11
- end
12
-
13
- class SystemUniversal
14
- #
15
- # constants
16
- #
17
- SystemUniversal::VERSION = '1.2.0' unless defined? SystemUniversal::VERSION
18
- def version() SystemUniversal::VERSION end
19
- #
20
- # class methods
21
- #
22
-
23
- @host = Socket.gethostname
24
- @ppid = Process.ppid
25
- @pid = Process.pid
26
- @turd = ENV['SYSTEMU_TURD']
27
-
28
- c = ::Config::CONFIG
29
- ruby = File.join(c['bindir'], c['ruby_install_name']) << c['EXEEXT']
30
- @ruby = if system('%s -e 42' % ruby)
31
- ruby
32
- else
33
- system('%s -e 42' % 'ruby') ? 'ruby' : warn('no ruby in PATH/CONFIG')
34
- end
35
-
36
- class << self
37
- %w( host ppid pid ruby turd ).each{|a| attr_accessor a}
38
- end
39
-
40
- #
41
- # instance methods
42
- #
43
-
44
- def initialize argv, opts = {}, &block
45
- getopt = getopts opts
46
-
47
- @argv = argv
48
- @block = block
49
-
50
- @stdin = getopt[ ['stdin', 'in', '0', 0] ]
51
- @stdout = getopt[ ['stdout', 'out', '1', 1] ]
52
- @stderr = getopt[ ['stderr', 'err', '2', 2] ]
53
- @env = getopt[ 'env' ]
54
- @cwd = getopt[ 'cwd' ]
55
-
56
- @host = getopt[ 'host', self.class.host ]
57
- @ppid = getopt[ 'ppid', self.class.ppid ]
58
- @pid = getopt[ 'pid', self.class.pid ]
59
- @ruby = getopt[ 'ruby', self.class.ruby ]
60
- end
61
-
62
- def systemu
63
- tmpdir do |tmp|
64
- c = child_setup tmp
65
- status = nil
66
-
67
- begin
68
- thread = nil
69
-
70
- quietly{
71
- IO.popen "#{ @ruby } #{ c['program'] }", 'r+' do |pipe|
72
- line = pipe.gets
73
- case line
74
- when %r/^pid: \d+$/
75
- cid = Integer line[%r/\d+/]
76
- else
77
- begin
78
- buf = pipe.read
79
- buf = "#{ line }#{ buf }"
80
- e = Marshal.load buf
81
- raise unless Exception === e
82
- raise e
83
- rescue
84
- raise "wtf?\n#{ buf }\n"
85
- end
86
- end
87
- thread = new_thread cid, @block if @block
88
- pipe.read rescue nil
89
- end
90
- }
91
- status = $?
92
- ensure
93
- if thread
94
- begin
95
- class << status
96
- attr 'thread'
97
- end
98
- status.instance_eval{ @thread = thread }
99
- rescue
100
- 42
101
- end
102
- end
103
- end
104
-
105
- if @stdout or @stderr
106
- open(c['stdout']){|f| relay f => @stdout} if @stdout
107
- open(c['stderr']){|f| relay f => @stderr} if @stderr
108
- status
109
- else
110
- [status, IO.read(c['stdout']), IO.read(c['stderr'])]
111
- end
112
- end
113
- end
114
-
115
- def new_thread cid, block
116
- q = Queue.new
117
- Thread.new(cid) do |cid|
118
- current = Thread.current
119
- current.abort_on_exception = true
120
- q.push current
121
- block.call cid
122
- end
123
- q.pop
124
- end
125
-
126
- def child_setup tmp
127
- stdin = File.expand_path(File.join(tmp, 'stdin'))
128
- stdout = File.expand_path(File.join(tmp, 'stdout'))
129
- stderr = File.expand_path(File.join(tmp, 'stderr'))
130
- program = File.expand_path(File.join(tmp, 'program'))
131
- config = File.expand_path(File.join(tmp, 'config'))
132
-
133
- if @stdin
134
- open(stdin, 'w'){|f| relay @stdin => f}
135
- else
136
- FileUtils.touch stdin
137
- end
138
- FileUtils.touch stdout
139
- FileUtils.touch stderr
140
-
141
- c = {}
142
- c['argv'] = @argv
143
- c['env'] = @env
144
- c['cwd'] = @cwd
145
- c['stdin'] = stdin
146
- c['stdout'] = stdout
147
- c['stderr'] = stderr
148
- c['program'] = program
149
- open(config, 'w'){|f| YAML.dump c, f}
150
-
151
- open(program, 'w'){|f| f.write child_program(config)}
152
-
153
- c
154
- end
155
-
156
- def quietly
157
- v = $VERBOSE
158
- $VERBOSE = nil
159
- yield
160
- ensure
161
- $VERBOSE = v
162
- end
163
-
164
- def child_program config
165
- <<-program
166
- PIPE = STDOUT.dup
167
- begin
168
- require 'yaml'
169
-
170
- config = YAML.load(IO.read('#{ config }'))
171
-
172
- argv = config['argv']
173
- env = config['env']
174
- cwd = config['cwd']
175
- stdin = config['stdin']
176
- stdout = config['stdout']
177
- stderr = config['stderr']
178
-
179
- Dir.chdir cwd if cwd
180
- env.each{|k,v| ENV[k.to_s] = v.to_s} if env
181
-
182
- STDIN.reopen stdin
183
- STDOUT.reopen stdout
184
- STDERR.reopen stderr
185
-
186
- PIPE.puts "pid: \#{ Process.pid }"
187
- PIPE.flush ### the process is ready yo!
188
- PIPE.close
189
-
190
- exec *argv
191
- rescue Exception => e
192
- PIPE.write Marshal.dump(e) rescue nil
193
- exit 42
194
- end
195
- program
196
- end
197
-
198
- def relay srcdst
199
- src, dst, ignored = srcdst.to_a.first
200
- if src.respond_to? 'read'
201
- while((buf = src.read(8192))); dst << buf; end
202
- else
203
- src.each{|buf| dst << buf}
204
- end
205
- end
206
-
207
- def tmpdir d = Dir.tmpdir, max = 42, &b
208
- i = -1 and loop{
209
- i += 1
210
-
211
- tmp = File.join d, "systemu_#{ @host }_#{ @ppid }_#{ @pid }_#{ rand }_#{ i += 1 }"
212
-
213
- begin
214
- Dir.mkdir tmp
215
- rescue Errno::EEXIST
216
- raise if i >= max
217
- next
218
- end
219
-
220
- break(
221
- if b
222
- begin
223
- b.call tmp
224
- ensure
225
- FileUtils.rm_rf tmp unless SystemU.turd
226
- end
227
- else
228
- tmp
229
- end
230
- )
231
- }
232
- end
233
-
234
- def getopts opts = {}
235
- lambda do |*args|
236
- keys, default, ignored = args
237
- catch('opt') do
238
- [keys].flatten.each do |key|
239
- [key, key.to_s, key.to_s.intern].each do |key|
240
- throw 'opt', opts[key] if opts.has_key?(key)
241
- end
242
- end
243
- default
244
- end
245
- end
246
- end
247
- end
248
-
249
- SystemU = SystemUniversal unless defined? SystemU
250
-
251
-
252
-
253
-
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
- if $0 == __FILE__
264
- #
265
- # date
266
- #
267
- date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
268
-
269
- status, stdout, stderr = systemu date
270
- p [status, stdout, stderr]
271
-
272
- status = systemu date, 1=>(stdout = '')
273
- p [status, stdout]
274
-
275
- status = systemu date, 2=>(stderr = '')
276
- p [status, stderr]
277
- #
278
- # sleep
279
- #
280
- sleep = %q( ruby -e" p(sleep(1)) " )
281
- status, stdout, stderr = systemu sleep
282
- p [status, stdout, stderr]
283
-
284
- sleep = %q( ruby -e" p(sleep(42)) " )
285
- status, stdout, stderr = systemu(sleep){|cid| Process.kill 9, cid}
286
- p [status, stdout, stderr]
287
- #
288
- # env
289
- #
290
- env = %q( ruby -e" p ENV['A'] " )
291
- status, stdout, stderr = systemu env, :env => {'A' => 42}
292
- p [status, stdout, stderr]
293
- #
294
- # cwd
295
- #
296
- env = %q( ruby -e" p Dir.pwd " )
297
- status, stdout, stderr = systemu env, :cwd => Dir.tmpdir
298
- p [status, stdout, stderr]
299
- end
@@ -1,11 +0,0 @@
1
- #
2
- # systemu can be used on any platform to return status, stdout, and stderr of
3
- # any command. unlike other methods like open3/popen4 there is zero danger of
4
- # full pipes or threading issues hanging your process or subprocess.
5
- #
6
- require 'systemu'
7
-
8
- date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
9
-
10
- status, stdout, stderr = systemu date
11
- p [ status, stdout, stderr ]
@@ -1,12 +0,0 @@
1
- #
2
- # quite a few keys can be passed to the command to alter it's behaviour. if
3
- # either stdout or stderr is supplied those objects should respond_to? '<<'
4
- # and only status will be returned
5
- #
6
- require 'systemu'
7
-
8
- date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
9
-
10
- stdout, stderr = '', ''
11
- status = systemu date, 'stdout' => stdout, 'stderr' => stderr
12
- p [ status, stdout, stderr ]
@@ -1,10 +0,0 @@
1
- #
2
- # of course stdin can be supplied too. synonyms for 'stdin' include '0' and
3
- # 0. the other stdio streams have similar shortcuts
4
- #
5
- require 'systemu'
6
-
7
- cat = %q( ruby -e" ARGF.each{|line| puts line} " )
8
-
9
- status = systemu cat, 0=>'the stdin for cat', 1=>stdout=''
10
- puts stdout
@@ -1,11 +0,0 @@
1
- #
2
- # the cwd can be supplied
3
- #
4
- require 'systemu'
5
- require 'tmpdir'
6
-
7
- pwd = %q( ruby -e" STDERR.puts Dir.pwd " )
8
-
9
- status = systemu pwd, 2=>(stderr=''), :cwd=>Dir.tmpdir
10
- puts stderr
11
-
@@ -1,9 +0,0 @@
1
- #
2
- # any environment vars specified are merged into the child's environment
3
- #
4
- require 'systemu'
5
-
6
- env = %q( ruby -r yaml -e" puts ENV[ 'answer' ] " )
7
-
8
- status = systemu env, 1=>stdout='', 'env'=>{ 'answer' => 0b101010 }
9
- puts stdout
@@ -1,18 +0,0 @@
1
- #
2
- # if a block is specified then it is passed the child pid and run in a
3
- # background thread. note that this thread will __not__ be blocked during the
4
- # execution of the command so it may do useful work such as killing the child
5
- # if execution time passes a certain threshold
6
- #
7
- require 'systemu'
8
-
9
- looper = %q( ruby -e" loop{ STDERR.puts Time.now.to_i; sleep 1 } " )
10
-
11
- status, stdout, stderr =
12
- systemu looper do |cid|
13
- sleep 3
14
- Process.kill 9, cid
15
- end
16
-
17
- p status
18
- p stderr