openvz 1.5 → 1.5.3

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.
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