ec2_amitools 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +54 -0
  3. data/bin/console +14 -0
  4. data/bin/ec2-ami-tools-version +6 -0
  5. data/bin/ec2-bundle-image +6 -0
  6. data/bin/ec2-bundle-vol +6 -0
  7. data/bin/ec2-delete-bundle +6 -0
  8. data/bin/ec2-download-bundle +6 -0
  9. data/bin/ec2-migrate-bundle +6 -0
  10. data/bin/ec2-migrate-manifest +6 -0
  11. data/bin/ec2-unbundle +6 -0
  12. data/bin/ec2-upload-bundle +6 -0
  13. data/bin/setup +8 -0
  14. data/etc/ec2/amitools/cert-ec2-cn-north-1.pem +28 -0
  15. data/etc/ec2/amitools/cert-ec2-gov.pem +17 -0
  16. data/etc/ec2/amitools/cert-ec2.pem +23 -0
  17. data/etc/ec2/amitools/mappings.csv +9 -0
  18. data/lib/ec2/amitools/bundle.rb +251 -0
  19. data/lib/ec2/amitools/bundle_base.rb +58 -0
  20. data/lib/ec2/amitools/bundleimage.rb +94 -0
  21. data/lib/ec2/amitools/bundleimageparameters.rb +42 -0
  22. data/lib/ec2/amitools/bundlemachineparameters.rb +60 -0
  23. data/lib/ec2/amitools/bundleparameters.rb +120 -0
  24. data/lib/ec2/amitools/bundlevol.rb +240 -0
  25. data/lib/ec2/amitools/bundlevolparameters.rb +164 -0
  26. data/lib/ec2/amitools/crypto.rb +379 -0
  27. data/lib/ec2/amitools/decryptmanifest.rb +20 -0
  28. data/lib/ec2/amitools/defaults.rb +12 -0
  29. data/lib/ec2/amitools/deletebundle.rb +212 -0
  30. data/lib/ec2/amitools/deletebundleparameters.rb +78 -0
  31. data/lib/ec2/amitools/downloadbundle.rb +161 -0
  32. data/lib/ec2/amitools/downloadbundleparameters.rb +84 -0
  33. data/lib/ec2/amitools/exception.rb +86 -0
  34. data/lib/ec2/amitools/fileutil.rb +219 -0
  35. data/lib/ec2/amitools/format.rb +127 -0
  36. data/lib/ec2/amitools/instance-data.rb +97 -0
  37. data/lib/ec2/amitools/manifest_wrapper.rb +132 -0
  38. data/lib/ec2/amitools/manifestv20070829.rb +361 -0
  39. data/lib/ec2/amitools/manifestv20071010.rb +403 -0
  40. data/lib/ec2/amitools/manifestv3.rb +331 -0
  41. data/lib/ec2/amitools/mapids.rb +148 -0
  42. data/lib/ec2/amitools/migratebundle.rb +222 -0
  43. data/lib/ec2/amitools/migratebundleparameters.rb +173 -0
  44. data/lib/ec2/amitools/migratemanifest.rb +225 -0
  45. data/lib/ec2/amitools/migratemanifestparameters.rb +118 -0
  46. data/lib/ec2/amitools/minimalec2.rb +116 -0
  47. data/lib/ec2/amitools/parameter_exceptions.rb +34 -0
  48. data/lib/ec2/amitools/parameters_base.rb +168 -0
  49. data/lib/ec2/amitools/region.rb +93 -0
  50. data/lib/ec2/amitools/s3toolparameters.rb +183 -0
  51. data/lib/ec2/amitools/showversion.rb +12 -0
  52. data/lib/ec2/amitools/syschecks.rb +27 -0
  53. data/lib/ec2/amitools/tool_base.rb +224 -0
  54. data/lib/ec2/amitools/unbundle.rb +107 -0
  55. data/lib/ec2/amitools/unbundleparameters.rb +65 -0
  56. data/lib/ec2/amitools/uploadbundle.rb +361 -0
  57. data/lib/ec2/amitools/uploadbundleparameters.rb +108 -0
  58. data/lib/ec2/amitools/util.rb +532 -0
  59. data/lib/ec2/amitools/version.rb +33 -0
  60. data/lib/ec2/amitools/xmlbuilder.rb +237 -0
  61. data/lib/ec2/amitools/xmlutil.rb +55 -0
  62. data/lib/ec2/common/constants.rb +16 -0
  63. data/lib/ec2/common/curl.rb +110 -0
  64. data/lib/ec2/common/headers.rb +95 -0
  65. data/lib/ec2/common/headersv4.rb +173 -0
  66. data/lib/ec2/common/http.rb +333 -0
  67. data/lib/ec2/common/s3support.rb +231 -0
  68. data/lib/ec2/common/signature.rb +68 -0
  69. data/lib/ec2/oem/LICENSE.txt +58 -0
  70. data/lib/ec2/oem/open4.rb +399 -0
  71. data/lib/ec2/platform/base/architecture.rb +26 -0
  72. data/lib/ec2/platform/base/constants.rb +54 -0
  73. data/lib/ec2/platform/base/pipeline.rb +181 -0
  74. data/lib/ec2/platform/base.rb +57 -0
  75. data/lib/ec2/platform/current.rb +55 -0
  76. data/lib/ec2/platform/linux/architecture.rb +35 -0
  77. data/lib/ec2/platform/linux/constants.rb +23 -0
  78. data/lib/ec2/platform/linux/fstab.rb +99 -0
  79. data/lib/ec2/platform/linux/identity.rb +16 -0
  80. data/lib/ec2/platform/linux/image.rb +811 -0
  81. data/lib/ec2/platform/linux/mtab.rb +74 -0
  82. data/lib/ec2/platform/linux/pipeline.rb +40 -0
  83. data/lib/ec2/platform/linux/rsync.rb +114 -0
  84. data/lib/ec2/platform/linux/tar.rb +124 -0
  85. data/lib/ec2/platform/linux/uname.rb +50 -0
  86. data/lib/ec2/platform/linux.rb +83 -0
  87. data/lib/ec2/platform/solaris/architecture.rb +28 -0
  88. data/lib/ec2/platform/solaris/constants.rb +30 -0
  89. data/lib/ec2/platform/solaris/fstab.rb +43 -0
  90. data/lib/ec2/platform/solaris/identity.rb +16 -0
  91. data/lib/ec2/platform/solaris/image.rb +327 -0
  92. data/lib/ec2/platform/solaris/mtab.rb +29 -0
  93. data/lib/ec2/platform/solaris/pipeline.rb +40 -0
  94. data/lib/ec2/platform/solaris/rsync.rb +24 -0
  95. data/lib/ec2/platform/solaris/tar.rb +36 -0
  96. data/lib/ec2/platform/solaris/uname.rb +21 -0
  97. data/lib/ec2/platform/solaris.rb +38 -0
  98. data/lib/ec2/platform.rb +69 -0
  99. data/lib/ec2/version.rb +8 -0
  100. data/lib/ec2_amitools +1 -0
  101. data/lib/ec2_amitools.rb +7 -0
  102. metadata +184 -0
@@ -0,0 +1,28 @@
1
+ # Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
2
+ # Reserved. Licensed under the Amazon Software License (the
3
+ # "License"). You may not use this file except in compliance with the
4
+ # License. A copy of the License is located at
5
+ # http://aws.amazon.com/asl or in the "license" file accompanying this
6
+ # file. This file is distributed on an "AS IS" BASIS, WITHOUT
7
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
8
+ # the License for the specific language governing permissions and
9
+ # limitations under the License.
10
+
11
+ #-------------------------------------------------------------------------------
12
+ # Solaris machine architectures as seen in EC2
13
+ require 'ec2/platform/base/architecture'
14
+ require 'ec2/platform/solaris/uname'
15
+ module EC2
16
+ module Platform
17
+ module Solaris
18
+ class Architecture < EC2::Platform::Base::Architecture
19
+ def self.bundling
20
+ processor = Uname.processor
21
+ return Architecture::I386 if processor =~ /^i\d86$/
22
+ return Architecture::X86_64 if processor =~ /^x86_64$/
23
+ return Architecture::UNKNOWN
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ # Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
2
+ # Reserved. Licensed under the Amazon Software License (the
3
+ # "License"). You may not use this file except in compliance with the
4
+ # License. A copy of the License is located at
5
+ # http://aws.amazon.com/asl or in the "license" file accompanying this
6
+ # file. This file is distributed on an "AS IS" BASIS, WITHOUT
7
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
8
+ # the License for the specific language governing permissions and
9
+ # limitations under the License.
10
+
11
+ #------------------------------------------------------------------------
12
+ # Solaris overrides for constants go here
13
+ #------------------------------------------------------------------------
14
+ require 'ec2/platform/base/constants'
15
+ module EC2
16
+ module Platform
17
+ module Solaris
18
+ module Constants
19
+ module Bundling
20
+ include EC2::Platform::Base::Constants::Bundling
21
+ DESTINATION = '/mnt'
22
+ end
23
+ module Utility
24
+ OPENSSL = '/usr/sfw/bin/openssl'
25
+ TAR = '/usr/sfw/bin/gtar'
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,43 @@
1
+ # Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
2
+ # Reserved. Licensed under the Amazon Software License (the
3
+ # "License"). You may not use this file except in compliance with the
4
+ # License. A copy of the License is located at
5
+ # http://aws.amazon.com/asl or in the "license" file accompanying this
6
+ # file. This file is distributed on an "AS IS" BASIS, WITHOUT
7
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
8
+ # the License for the specific language governing permissions and
9
+ # limitations under the License.
10
+
11
+ require 'ec2/platform/linux/fstab'
12
+
13
+ module EC2
14
+ module Platform
15
+ module Solaris
16
+ class Fstab < EC2::Platform::Linux::Fstab
17
+ LOCATION = '/etc/vfstab'
18
+ def initialize(filename = LOCATION)
19
+ super filename
20
+ end
21
+
22
+ DEFAULT = IO.read(File.join('/etc', 'vfstab')) rescue <<TEXT
23
+ # Default /etc/vfstab
24
+ # Supplied by: #{PKG_NAME}-#{PKG_VERSION}-#{PKG_RELEASE}
25
+ #device device mount FS fsck mount mount
26
+ #to mount to fsck point type pass at boot options
27
+ #
28
+ fd - /dev/fd fd - no -
29
+ /proc - /proc proc - no -
30
+ /dev/dsk/c0d0s1 - - swap - no -
31
+ /dev/dsk/c0d0s0 /dev/rdsk/c0d0s0 / ufs 1 no -
32
+ /dev/dsk/c0d1s0 /dev/rdsk/c0d1s0 /mnt ufs 2 no -
33
+ /devices - /devices devfs - no -
34
+ sharefs - /etc/dfs/sharetab sharefs - no -
35
+ ctfs - /system/contract ctfs - no -
36
+ objfs - /system/object objfs - no -
37
+ swap - /tmp tmpfs - yes -
38
+ TEXT
39
+ LEGACY = :legacy # here for compatibility reasons
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,16 @@
1
+ # Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
2
+ # Reserved. Licensed under the Amazon Software License (the
3
+ # "License"). You may not use this file except in compliance with the
4
+ # License. A copy of the License is located at
5
+ # http://aws.amazon.com/asl or in the "license" file accompanying this
6
+ # file. This file is distributed on an "AS IS" BASIS, WITHOUT
7
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
8
+ # the License for the specific language governing permissions and
9
+ # limitations under the License.
10
+
11
+ module EC2
12
+ module Platform
13
+ module Solaris; end
14
+ EC2::Platform::PEER = EC2::Platform::Solaris unless defined? EC2::Platform::PEER
15
+ end
16
+ end
@@ -0,0 +1,327 @@
1
+ # Copyright 2008-2014 Amazon.com, Inc. or its affiliates. All Rights
2
+ # Reserved. Licensed under the Amazon Software License (the
3
+ # "License"). You may not use this file except in compliance with the
4
+ # License. A copy of the License is located at
5
+ # http://aws.amazon.com/asl or in the "license" file accompanying this
6
+ # file. This file is distributed on an "AS IS" BASIS, WITHOUT
7
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
8
+ # the License for the specific language governing permissions and
9
+ # limitations under the License.
10
+
11
+ #---------------------------------------------------------------------#
12
+ # Create a Solaris EC2 Image as follows:
13
+ # - create a bootable file-system archive in the SUN flash format
14
+ # - create, format and mount a blank file-system image
15
+ # - replicate the archive section of the flash archive into the image
16
+ # - customize the image
17
+ #
18
+ # Fasten your seat-belts and grab a pillow; this is painfully slow.
19
+ # Initial tests show an average bundling time of a virgin OpenSolaris
20
+ # system using this algorithm to be about 85-90 minutes. Optimization
21
+ # involves rewriting flar to combine the "flar create" and "flar split"
22
+ # steps into a "flar replicate" step
23
+ #---------------------------------------------------------------------#
24
+
25
+ require 'fileutils'
26
+ require 'ec2/oem/open4'
27
+ require 'ec2/amitools/fileutil'
28
+ require 'ec2/amitools/syschecks'
29
+ require 'ec2/amitools/exception'
30
+ require 'ec2/platform/solaris/mtab'
31
+ require 'ec2/platform/solaris/fstab'
32
+ require 'ec2/platform/solaris/constants'
33
+
34
+ module EC2
35
+ module Platform
36
+ module Solaris
37
+
38
+ class ExecutionError < RuntimeError
39
+ end
40
+
41
+ # This class encapsulate functionality to create an file loopback image
42
+ # from a volume. The image is created using mkfile. Sub-directories of the
43
+ # volume, including mounts of local filesystems, are copied to the image.
44
+ # Symbolic links are preserved wherever possible.
45
+ class Image
46
+ EXCLUDES = [ '/mnt' ]
47
+ WORKSPACE = '/mnt/ec2-bundle-workspace'
48
+ MOUNT = File.join( WORKSPACE, 'mnt' )
49
+ ARCHIVE = File.join( WORKSPACE, 'archive' )
50
+ PROFILING = true
51
+ RETRIES = 5
52
+ DELAY = 10
53
+ #---------------------------------------------------------------------#
54
+ def initialize( volume, # path to volume to be bundled
55
+ filename, # name of image file to create
56
+ size, # size of image file in MB
57
+ exclude, # list of directories to exclude
58
+ includes, # This does absolutely nothing on solaris - warrenr
59
+ filter, # Same as above - warrenr
60
+ vfstab=nil, # file system table to use
61
+ part_type=nil, # Disk partition type: MBR/GPT etc
62
+ arch=nil, # Architecture of the bundled volume
63
+ script=nil, # Post-cloning customization script
64
+ debug = false )
65
+ @volume = volume
66
+ @filename = filename
67
+ @size = size
68
+ @exclude = exclude
69
+ @debug = debug
70
+ @arch = arch
71
+ @script = script
72
+ self.set_partition_type( part_type )
73
+ if vfstab.nil? or vfstab == :legacy
74
+ @vfstab = EC2::Platform::Solaris::Fstab::DEFAULT
75
+ elsif File.exists? vfstab
76
+ @vfstab = IO.read(vfstab)
77
+ else
78
+ @vfstab = vfstab
79
+ end
80
+
81
+ # Exclude the workspace if it is in the volume being bundled.
82
+ @exclude << WORKSPACE if( WORKSPACE.index(volume) == 0 )
83
+ end
84
+
85
+ #---------------------------------------------------------------------#
86
+ def set_partition_type( input )
87
+ input ||= EC2::Platform::PartitionType::NONE
88
+ if input == EC2::Platform::PartitionType::NONE
89
+ @part_type = EC2::Platform::PartitionType::NONE
90
+ else
91
+ raise NotImplementedError, "Disk images not supported for Solaris"
92
+ end
93
+ end
94
+
95
+ #---------------------------------------------------------------------#
96
+ # Clone a running volume into a bootable Amazon Machine Image.
97
+ def make
98
+ begin
99
+ announce( "Cloning #{@volume} into image file #{@filename}...", true)
100
+ announce( 'Excluding: ', true )
101
+ @exclude.each { |x| announce( "\t #{x}", true ) }
102
+ archive
103
+ prepare
104
+ replicate
105
+ ensure
106
+ cleanup
107
+ end
108
+ end
109
+
110
+ private
111
+
112
+
113
+ #---------------------------------------------------------------------#
114
+ # Create, format and mount the blank machine image file.
115
+ # TODO: investigate parallelizing prepare() with archive()
116
+ def prepare
117
+ FileUtils.mkdir_p( MOUNT )
118
+ announce( 'Creating and formatting file-system image...', true )
119
+ evaluate( "/usr/sbin/mkfile #{@size*1024*1024} #{@filename}" )
120
+
121
+ announce( 'Formatting file-system image...' )
122
+ execute( 'sync && devfsadm -C' )
123
+ @device = evaluate('/usr/sbin/lofiadm -a ' + @filename).strip
124
+ number = @device.split(/\//).last rescue nil
125
+ raise FatalError.new('Failed to attach image to a device' ) unless number
126
+ execute( "echo y | newfs /dev/rlofi/#{number} < /dev/null > /dev/null 2>&1", true )
127
+
128
+ execute( 'sync' )
129
+ mount( @device, MOUNT )
130
+ end
131
+
132
+ #---------------------------------------------------------------------#
133
+ # Create a flash archive of the system at the desired volume root.
134
+ def archive
135
+ FileUtils.mkdir_p( WORKSPACE )
136
+ announce( 'Creating flash archive of file system...', true )
137
+ exempt = []
138
+ @exclude.each do |item|
139
+ item = File.expand_path(item)
140
+ # Since flarcreate does not allow you to exclude a mount-point from
141
+ # a flash archive, we work around this by listing the files in that
142
+ # directory and excluding them individually.
143
+ if mounted? item
144
+ exempt.concat( evaluate( 'ls -A ' + item).split(/\s/).map{|i| File.join( item, i ) } )
145
+ else
146
+ exempt << item
147
+ end
148
+ end
149
+ exempt = exempt.join( ' -x ')
150
+
151
+ invocation = ['flar create -n ec2.archive -S -R ' + @volume ]
152
+ invocation << ( '-x ' + exempt ) unless exempt.empty?
153
+ invocation << ARCHIVE
154
+ evaluate( invocation.join( ' ' ) )
155
+ raise FatalError.new( "Archive creation failed" ) unless File.exist?( ARCHIVE )
156
+
157
+ asize = FileUtil.size( ARCHIVE ) / ( 1024 * 1024 )
158
+ raise FatalError.new( "Archive too small" ) unless asize > 0
159
+ raise FatalError.new( 'Archive exceeds target size' ) if asize > @size
160
+ end
161
+
162
+ #---------------------------------------------------------------------#
163
+ # Extract the archive into the file-system image.
164
+ def replicate
165
+ announce( 'Replicating archive to image (this will take a while)...', true )
166
+ # Extract flash archive into mounted image. The flar utility places
167
+ # the output in a folder called 'archive'. Since we cannot override
168
+ # this, we need to extract the content, move it to the image root
169
+ # and delete remove the cruft
170
+ extract = File.join( MOUNT, 'archive')
171
+ execute( "flar split -S archive -d #{MOUNT} -f #{ARCHIVE}" )
172
+ execute( "ls -A #{extract} | xargs -i mv #{extract}/'{}' #{MOUNT}" )
173
+ FileUtils.rm_rf( File.join(MOUNT, 'archive') )
174
+ FileUtils.rm_rf( File.join(MOUNT, 'identification') )
175
+
176
+ announce 'Saving system configuration...'
177
+ ['/boot/solaris/bootenv.rc', '/etc/vfstab', '/etc/path_to_inst'].each do |path|
178
+ file = File.join( MOUNT, path )
179
+ FileUtils.cp( file, file + '.phys' )
180
+ end
181
+
182
+ announce 'Fine-tuning system configuration...'
183
+ execute( '/usr/sbin/sys-unconfig -R ' + MOUNT )
184
+ bootenv = File.join( MOUNT, '/boot/solaris/bootenv.rc' )
185
+ execute( "sed '/setprop bootpath/,/setprop console/d' < #{bootenv}.phys > #{bootenv}" )
186
+ execute( "sed '/dsk/d' < #{MOUNT}/etc/vfstab.phys > #{MOUNT}/etc/vfstab" )
187
+
188
+ FileUtils.rm_f( File.join(MOUNT, '/etc/rc2.d/S99dtlogin') )
189
+
190
+ announce 'Creating missing image directories...'
191
+ [ '/dev/dsk', '/dev/rdsk', '/dev/fd', '/etc/mnttab', ].each do |item|
192
+ FileUtils.mkdir_p( File.join( MOUNT, item ) )
193
+ end
194
+
195
+ FileUtils.ln_s( '../../devices/xpvd/xdf@0:a', File.join( MOUNT, '/dev/dsk/c0d0s0' ) )
196
+ FileUtils.ln_s( '../../devices/xpvd/xdf@0:a,raw', File.join( MOUNT, '/dev/rdsk/c0d0s0' ) )
197
+
198
+ FileUtils.touch( File.join( MOUNT, Mtab::LOCATION ) )
199
+ fstab = File.join( MOUNT, Fstab::LOCATION )
200
+ File.open(fstab, 'w+') {|io| io << @vfstab }
201
+ announce( "--->/etc/vfstab<---:\n" + @vfstab , true )
202
+
203
+ execute( "bootadm update-archive -R #{MOUNT} > /dev/null 2>&1", true )
204
+
205
+ announce( 'Disable xen services' )
206
+ file = File.join( MOUNT, '/var/svc/profile/upgrade' )
207
+ execute( 'echo "/usr/sbin/svcadm disable svc:/system/xctl/xend:default" >> ' + file )
208
+
209
+ announce 'Setting up DHCP boot'
210
+ FileUtils.touch( File.join( MOUNT, '/etc/hostname.xnf0' ) )
211
+ FileUtils.touch( File.join( MOUNT, '/etc/dhcp.xnf0' ) )
212
+
213
+ announce 'Setting keyboard layout'
214
+ kbd = File.join( MOUNT, '/etc/default/kbd' )
215
+ execute( "egrep '^LAYOUT' #{kbd} || echo 'LAYOUT=US-English' >> #{kbd}" )
216
+
217
+ customize
218
+ end
219
+
220
+ def customize
221
+ return unless @script and File.executable?(@script)
222
+ announce 'Customizing replicated volume mounted at %s with script %s' % [MOUNT, @script]
223
+ output = evaluate('%s "%s"' % [@script, MOUNT])
224
+ STDERR.puts output if @debug
225
+ end
226
+
227
+ #---------------------------------------------------------------------#
228
+ # Mount the specified device. The mount point is created if necessary.
229
+ # We let mount guess the appropriate file system type.
230
+ def mount(device, mpoint)
231
+ FileUtils.mkdir_p(mpoint) if not FileUtil::exists?(mpoint)
232
+ raise FatalError.new("image already mounted") if mounted?(mpoint)
233
+ execute( 'sync' )
234
+ execute( 'mount ' + device + ' ' + mpoint )
235
+ end
236
+
237
+ #---------------------------------------------------------------------#
238
+
239
+ def unmount(mpoint, force=false)
240
+ GC.start
241
+ execute( 'sync && sync && sync' )
242
+ if mounted?( mpoint ) then
243
+ execute( 'umount ' + (force ? '-f ' : '') + mpoint )
244
+ end
245
+ end
246
+
247
+ #---------------------------------------------------------------------#
248
+
249
+ def mounted?(mpoint)
250
+ EC2::Platform::Solaris::Mtab.load.entries.keys.include? mpoint
251
+ end
252
+
253
+ #---------------------------------------------------------------------#
254
+ # Cleanup after self:
255
+ # - unmount relevant mount points.
256
+ # - release any device and resources attached to the image and mount-point
257
+ # - delete any intermediate files and directories.
258
+ def cleanup
259
+ attempts = 0
260
+ begin
261
+ unmount( MOUNT )
262
+ rescue ExecutionError
263
+ announce "Unable to unmount image. Retrying after a short sleep."
264
+ attempts += 1
265
+ if attempts < RETRIES
266
+ sleep DELAY
267
+ retry
268
+ else
269
+ announce( "Unable to unmount image after #{RETRIES} attempts. Baling out...", true )
270
+ unmount( MOUNT, true )
271
+ if File.exist?( @filename )
272
+ announce( "Deleting image file #{@filename}..." )
273
+ FileUtils.rm_f( @filename )
274
+ end
275
+ end
276
+ end
277
+ unless @device.nil?
278
+ devices = evaluate( 'lofiadm' ).split( /\n/ )
279
+ devices.each do |item|
280
+ execute( 'lofiadm -d' + @device ) if item.index( @device ) == 0
281
+ end
282
+ end
283
+ execute( 'devfsadm -C' )
284
+ FileUtils.rm_rf( WORKSPACE ) if File.directory?( WORKSPACE )
285
+ end
286
+
287
+ #---------------------------------------------------------------------#
288
+ # Output a message if running in debug mode
289
+ def announce(something, force=false)
290
+ STDOUT.puts( something ) if @debug or force
291
+ end
292
+
293
+ #---------------------------------------------------------------------#
294
+ # Execute the command line passed in.
295
+ def execute( cmd, verbattim = false )
296
+ verbattim ||= @debug
297
+ invocation = [ cmd ]
298
+ invocation << ' 2>&1 > /dev/null' unless verbattim
299
+ announce( "Executing: '#{cmd}' " )
300
+ time = Time.now
301
+ raise ExecutionError.new( "Failed to execute '#{cmd}'.") unless system( invocation.join )
302
+ announce( "Time: #{Time.now - time}s", PROFILING )
303
+ end
304
+
305
+ #---------------------------------------------------------------------#
306
+ # Execute command line passed in and return STDOUT output if successful.
307
+ def evaluate( cmd, success = 0, verbattim = false )
308
+ verbattim ||= @debug
309
+ cmd << ' 2> /dev/null' unless verbattim
310
+ announce( "Evaluating: '#{cmd}' " )
311
+ time = Time.now
312
+ pid, stdin, stdout, stderr = Open4::popen4( cmd )
313
+ ignore stdin
314
+ pid, status = Process::waitpid2 pid
315
+ unless status.exitstatus == success
316
+ raise ExecutionError.new( "Failed to evaluate '#{cmd }'. Reason: #{stderr.read}." )
317
+ end
318
+ announce( "Time: #{Time.now - time}s", PROFILING )
319
+ stdout.read
320
+ end
321
+
322
+ def ignore(stuff) stuff end
323
+
324
+ end
325
+ end
326
+ end
327
+ end