boxgrinder-build 0.2.0 → 0.3.2
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/bin/boxgrinder-build +81 -0
- data/docs/examples/appliances/appliances.appl +5 -0
- data/docs/examples/appliances/minimal.appl +9 -0
- data/docs/examples/appliances/mix.appl +8 -0
- data/docs/examples/appliances/packages.appl +13 -0
- data/lib/boxgrinder-build/appliance.rb +85 -18
- data/lib/boxgrinder-build/helpers/appliance-customize-helper.rb +2 -2
- data/lib/boxgrinder-build/helpers/guestfs-helper.rb +18 -15
- data/lib/boxgrinder-build/helpers/package-helper.rb +65 -0
- data/lib/boxgrinder-build/helpers/plugin-helper.rb +89 -0
- data/lib/boxgrinder-build/{defaults.rb → managers/base-plugin-manager.rb} +41 -8
- data/lib/{boxgrinder-build.rb → boxgrinder-build/managers/delivery-plugin-manager.rb} +15 -18
- data/lib/boxgrinder-build/managers/operating-system-plugin-manager.rb +6 -0
- data/{bin/boxgrinder → lib/boxgrinder-build/managers/platform-plugin-manager.rb} +6 -3
- data/lib/boxgrinder-build/plugins/base-plugin.rb +98 -0
- data/lib/boxgrinder-build/plugins/delivery/base/base-delivery-plugin.rb +43 -0
- data/lib/boxgrinder-build/plugins/delivery/local/local-plugin.rb +57 -0
- data/lib/boxgrinder-build/{helpers → plugins/delivery/s3}/aws-helper.rb +0 -0
- data/lib/boxgrinder-build/plugins/delivery/s3/s3-plugin.rb +133 -0
- data/lib/boxgrinder-build/{helpers/ssh-helper.rb → plugins/delivery/sftp/sftp-plugin.rb} +61 -42
- data/lib/boxgrinder-build/{appliance-kickstart.rb → plugins/os/base/kickstart.rb} +45 -55
- data/lib/boxgrinder-build/{images/raw-image.rb → plugins/os/base/rpm-based-os-plugin.rb} +63 -60
- data/lib/boxgrinder-build/{erb → plugins/os/base/src}/appliance.ks.erb +2 -5
- data/{src → lib/boxgrinder-build/plugins/os/base/src}/base.repo +0 -0
- data/{src → lib/boxgrinder-build/plugins/os/base/src}/motd.init +0 -0
- data/lib/boxgrinder-build/{validators/appliance-dependency-validator.rb → plugins/os/base/validators/rpm-dependency-validator.rb} +1 -1
- data/lib/boxgrinder-build/{models/ssh-config.rb → plugins/os/base-operating-system-plugin.rb} +10 -17
- data/lib/boxgrinder-build/plugins/os/centos/centos-plugin.rb +72 -0
- data/lib/boxgrinder-build/plugins/os/fedora/fedora-plugin.rb +66 -0
- data/lib/boxgrinder-build/plugins/os/rhel/rhel-plugin.rb +38 -0
- data/lib/boxgrinder-build/plugins/platform/base-platform-plugin.rb +37 -0
- data/lib/boxgrinder-build/plugins/platform/ec2/ec2-plugin.rb +283 -0
- data/{src → lib/boxgrinder-build/plugins/platform/ec2/src}/f12/yum.conf +0 -0
- data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/f12-i386-boxgrinder.repo +0 -0
- data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/f12-x86_64-boxgrinder.repo +0 -0
- data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/fstab_32bit +0 -0
- data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/fstab_64bit +0 -0
- data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/ifcfg-eth0 +0 -0
- data/{src/ec2 → lib/boxgrinder-build/plugins/platform/ec2/src}/rc_local +1 -4
- data/{src/README.vmware → lib/boxgrinder-build/plugins/platform/vmware/src/README} +10 -10
- data/{src → lib/boxgrinder-build/plugins/platform/vmware/src}/base.vmdk +1 -1
- data/{src → lib/boxgrinder-build/plugins/platform/vmware/src}/base.vmx +0 -0
- data/lib/boxgrinder-build/plugins/platform/vmware/vmware-plugin.rb +181 -0
- data/lib/boxgrinder-build/validators/config-validator.rb +0 -19
- metadata +73 -44
- data/docs/examples/appliances/appliances-appliance/appliances-appliance.appl +0 -6
- data/docs/examples/appliances/appliances-appliance/appliances-appliance.pp +0 -16
- data/docs/examples/appliances/minimal-appliance/minimal-appliance.appl +0 -2
- data/docs/examples/appliances/minimal-appliance/minimal-appliance.pp +0 -16
- data/docs/examples/appliances/mix-appliance/mix-appliance.appl +0 -9
- data/docs/examples/appliances/mix-appliance/mix-appliance.pp +0 -16
- data/docs/examples/appliances/packages-appliance/packages-appliance.appl +0 -6
- data/docs/examples/appliances/packages-appliance/packages-appliance.pp +0 -16
- data/extras/sign-rpms +0 -12
- data/lib/boxgrinder-build/boxgrinder.rb +0 -93
- data/lib/boxgrinder-build/helpers/release-helper.rb +0 -136
- data/lib/boxgrinder-build/images/ec2-image.rb +0 -317
- data/lib/boxgrinder-build/images/vmware-image.rb +0 -214
- data/lib/boxgrinder-build/validators/appliance-definition-validator.rb +0 -89
- data/lib/progressbar/progressbar.rb +0 -236
- data/src/oddthesis/RPM-GPG-KEY-oddthesis +0 -30
- data/src/oddthesis/oddthesis.repo +0 -23
@@ -0,0 +1,98 @@
|
|
1
|
+
# JBoss, Home of Professional Open Source
|
2
|
+
# Copyright 2009, Red Hat Middleware LLC, and individual contributors
|
3
|
+
# by the @authors tag. See the copyright.txt in the distribution for a
|
4
|
+
# full listing of individual contributors.
|
5
|
+
#
|
6
|
+
# This is free software; you can redistribute it and/or modify it
|
7
|
+
# under the terms of the GNU Lesser General Public License as
|
8
|
+
# published by the Free Software Foundation; either version 2.1 of
|
9
|
+
# the License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This software is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public
|
17
|
+
# License along with this software; if not, write to the Free
|
18
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
19
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
20
|
+
|
21
|
+
require 'boxgrinder-core/helpers/exec-helper'
|
22
|
+
require 'boxgrinder-build/helpers/plugin-helper'
|
23
|
+
require 'logger'
|
24
|
+
|
25
|
+
module BoxGrinder
|
26
|
+
class BasePlugin
|
27
|
+
def init(config, appliance_config, options = {})
|
28
|
+
@config = config
|
29
|
+
@appliance_config = appliance_config
|
30
|
+
@options = options
|
31
|
+
|
32
|
+
@log = options[:log] || Logger.new(STDOUT)
|
33
|
+
@exec_helper = options[:exec_helper] || ExecHelper.new( :log => @log )
|
34
|
+
@plugin_helper = options[:plugin_helper] || PluginHelper.new( :log => @log )
|
35
|
+
|
36
|
+
@plugin_config = {}
|
37
|
+
|
38
|
+
if self.respond_to?(:info)
|
39
|
+
@config_file = "#{ENV['HOME']}/.boxgrinder/plugins/#{self.info[:name]}"
|
40
|
+
|
41
|
+
read_plugin_config
|
42
|
+
|
43
|
+
@deliverables = Hash.new({})
|
44
|
+
@deliverables[:disk] = nil
|
45
|
+
@deliverables[:platform] = self.info[:name]
|
46
|
+
end
|
47
|
+
|
48
|
+
after_init
|
49
|
+
|
50
|
+
@initialized = true
|
51
|
+
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_reader :deliverables
|
56
|
+
|
57
|
+
def validate_plugin_config(fields = [], doc = nil)
|
58
|
+
more_info = doc.nil? ? '' : "See #{doc} for more info"
|
59
|
+
|
60
|
+
raise "Not valid configuration file for #{info[:name]} plugin. Please create valid '#{@config_file}' file. #{more_info}" if @plugin_config.nil?
|
61
|
+
|
62
|
+
fields.each do |field|
|
63
|
+
raise "Please specify a valid #{field} in plugin configuration file: '#{@config_file}'. #{more_info}" if @plugin_config[field].nil?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def execute(args = nil)
|
68
|
+
raise "Execute operation for #{self.class} plugin is not implemented"
|
69
|
+
end
|
70
|
+
|
71
|
+
def after_init
|
72
|
+
end
|
73
|
+
|
74
|
+
def set_default_config_value(key, value)
|
75
|
+
@plugin_config[key] = @plugin_config[key].nil? ? value : @plugin_config[key]
|
76
|
+
end
|
77
|
+
|
78
|
+
def read_plugin_config
|
79
|
+
return unless File.exists?(@config_file)
|
80
|
+
|
81
|
+
@log.debug "Reading configuration file for #{self.class.name}."
|
82
|
+
|
83
|
+
begin
|
84
|
+
@plugin_config = YAML.load_file(@config_file)
|
85
|
+
rescue
|
86
|
+
raise "An error occurred while reading configuration file #{@config_file} for #{self.class.name}. It is a valid YAML file?"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def customize(disk_path)
|
91
|
+
raise "Customizing cannot be started until the plugin isn't initialized" if @initialized.nil?
|
92
|
+
|
93
|
+
ApplianceCustomizeHelper.new(@config, @appliance_config, disk_path, :log => @log).customize do |guestfs, guestfs_helper|
|
94
|
+
yield guestfs, guestfs_helper
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# JBoss, Home of Professional Open Source
|
2
|
+
# Copyright 2009, Red Hat Middleware LLC, and individual contributors
|
3
|
+
# by the @authors tag. See the copyright.txt in the distribution for a
|
4
|
+
# full listing of individual contributors.
|
5
|
+
#
|
6
|
+
# This is free software; you can redistribute it and/or modify it
|
7
|
+
# under the terms of the GNU Lesser General Public License as
|
8
|
+
# published by the Free Software Foundation; either version 2.1 of
|
9
|
+
# the License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This software is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public
|
17
|
+
# License along with this software; if not, write to the Free
|
18
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
19
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
20
|
+
|
21
|
+
require 'boxgrinder-build/managers/delivery-plugin-manager'
|
22
|
+
require 'boxgrinder-build/plugins/base-plugin'
|
23
|
+
|
24
|
+
module BoxGrinder
|
25
|
+
class BaseDeliveryPlugin < BasePlugin
|
26
|
+
alias_method :execute_original, :execute
|
27
|
+
|
28
|
+
def execute( deliverables, type)
|
29
|
+
raise "Delivery cannot be started before the plugin isn't initialized" if @initialized.nil?
|
30
|
+
raise "Not valid delivery type selected for #{info[:name]} plugin: #{type}. Available types: #{info[:type].join(" ")}" unless info[:type].include?(type)
|
31
|
+
|
32
|
+
execute_original( deliverables, type )
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.inherited(klass)
|
36
|
+
DeliveryPluginManager.instance << klass
|
37
|
+
end
|
38
|
+
|
39
|
+
def already_delivered?
|
40
|
+
false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'boxgrinder-build/plugins/delivery/base/base-delivery-plugin'
|
2
|
+
|
3
|
+
module BoxGrinder
|
4
|
+
class LocalPlugin < BaseDeliveryPlugin
|
5
|
+
def info
|
6
|
+
{
|
7
|
+
:name => :local,
|
8
|
+
:type => [:local],
|
9
|
+
:full_name => "Local file system"
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def after_init
|
14
|
+
set_default_config_value('overwrite', true)
|
15
|
+
set_default_config_value('package', true)
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute(deliverables, type = :local)
|
19
|
+
validate_plugin_config( [ 'path' ], 'http://community.jboss.org/docs/DOC-15216' )
|
20
|
+
|
21
|
+
files = []
|
22
|
+
|
23
|
+
if @plugin_config['package']
|
24
|
+
files << PackageHelper.new(@config, @appliance_config, {:log => @log, :exec_helper => @exec_helper}).package(deliverables)
|
25
|
+
else
|
26
|
+
files << deliverables[:disk]
|
27
|
+
|
28
|
+
[:metadata, :other].each do |deliverable_type|
|
29
|
+
deliverables[deliverable_type].each_value do |file|
|
30
|
+
files << file
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
if @plugin_config['overwrite'] or !already_delivered?(files)
|
36
|
+
FileUtils.mkdir_p @plugin_config['path']
|
37
|
+
|
38
|
+
@log.debug "Copying files to destination..."
|
39
|
+
|
40
|
+
files.each do |file|
|
41
|
+
@log.debug "Copying #{file}..."
|
42
|
+
FileUtils.cp(file, @plugin_config['path'])
|
43
|
+
end
|
44
|
+
@log.info "Appliance delivered to #{@plugin_config['path']}."
|
45
|
+
else
|
46
|
+
@log.info "Appliance already delivered to #{@plugin_config['path']}."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def already_delivered?(files)
|
51
|
+
files.each do |file|
|
52
|
+
return false unless File.exists?("#{@plugin_config['path']}/#{File.basename(file)}")
|
53
|
+
end
|
54
|
+
true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
File without changes
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# JBoss, Home of Professional Open Source
|
2
|
+
# Copyright 2009, Red Hat Middleware LLC, and individual contributors
|
3
|
+
# by the @authors tag. See the copyright.txt in the distribution for a
|
4
|
+
# full listing of individual contributors.
|
5
|
+
#
|
6
|
+
# This is free software; you can redistribute it and/or modify it
|
7
|
+
# under the terms of the GNU Lesser General Public License as
|
8
|
+
# published by the Free Software Foundation; either version 2.1 of
|
9
|
+
# the License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This software is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public
|
17
|
+
# License along with this software; if not, write to the Free
|
18
|
+
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
19
|
+
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
20
|
+
|
21
|
+
require 'boxgrinder-build/plugins/delivery/base/base-delivery-plugin'
|
22
|
+
require 'boxgrinder-build/plugins/delivery/s3/aws-helper'
|
23
|
+
require 'AWS'
|
24
|
+
require 'aws/s3'
|
25
|
+
include AWS::S3
|
26
|
+
|
27
|
+
module BoxGrinder
|
28
|
+
class S3Plugin < BaseDeliveryPlugin
|
29
|
+
|
30
|
+
def info
|
31
|
+
{
|
32
|
+
:name => :s3,
|
33
|
+
:type => [:cloudfront, :ami, :s3],
|
34
|
+
:full_name => "Amazon Simple Storage Service (Amazon S3)"
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def after_init
|
39
|
+
set_default_config_value('overwrite', false)
|
40
|
+
end
|
41
|
+
|
42
|
+
def execute(deliverables, type = :ami)
|
43
|
+
validate_plugin_config(['bucket', 'access_key', 'secret_access_key', 'path'])
|
44
|
+
|
45
|
+
case type
|
46
|
+
when :s3
|
47
|
+
upload_to_bucket(deliverables)
|
48
|
+
when :cloudfront
|
49
|
+
upload_to_bucket(deliverables, :public_read)
|
50
|
+
when :ami
|
51
|
+
raise "Not implemented!"
|
52
|
+
#bundle_image(deliverables)
|
53
|
+
#upload_image
|
54
|
+
#register_image
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def upload_to_bucket(deliverables, permissions = :private)
|
59
|
+
AWSHelper.new(@config, @appliance_config)
|
60
|
+
|
61
|
+
package = PackageHelper.new(@config, @appliance_config, {:log => @log, :exec_helper => @exec_helper}).package(deliverables)
|
62
|
+
|
63
|
+
@log.info "Uploading #{@appliance_config.name} appliance to S3 bucket '#{@plugin_config['bucket']}'..."
|
64
|
+
|
65
|
+
begin
|
66
|
+
AWS::S3::Bucket.find(@plugin_config['bucket'])
|
67
|
+
rescue AWS::S3::NoSuchBucket
|
68
|
+
AWS::S3::Bucket.create(@plugin_config['bucket'])
|
69
|
+
retry
|
70
|
+
end
|
71
|
+
|
72
|
+
remote_path = "#{@plugin_config['path']}/#{File.basename(package)}"
|
73
|
+
size_b = File.size(package)
|
74
|
+
|
75
|
+
unless S3Object.exists?(remote_path, @plugin_config['bucket']) or @plugin_config['overwrite']
|
76
|
+
@log.info "Uploading #{File.basename(package)} (#{size_b/1024/1024}MB)..."
|
77
|
+
AWS::S3::S3Object.store(remote_path, open(package), @plugin_config['bucket'], :access => permissions)
|
78
|
+
end
|
79
|
+
|
80
|
+
@log.info "Appliance #{@appliance_config.name} uploaded to S3."
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
def bundle_image(deliverables)
|
85
|
+
@log.info "Bundling AMI..."
|
86
|
+
|
87
|
+
@exec_helper.execute("ec2-bundle-image -i #{deliverables[:disk]} --kernel #{AWS_DEFAULTS[:kernel_id][@appliance_config.hardware.arch]} --ramdisk #{AWS_DEFAULTS[:ramdisk_id][@appliance_config.hardware.arch]} -c #{@aws_helper.aws_data['cert_file']} -k #{@aws_helper.aws_data['key_file']} -u #{@aws_helper.aws_data['account_number']} -r #{@appliance_config.hardware.arch} -d #{@appliance_config.path.dir.ec2.bundle}")
|
88
|
+
|
89
|
+
@log.info "Bundling AMI finished."
|
90
|
+
end
|
91
|
+
|
92
|
+
def appliance_already_uploaded?
|
93
|
+
begin
|
94
|
+
bucket = Bucket.find(@aws_helper.aws_data['bucket_name'])
|
95
|
+
rescue
|
96
|
+
return false
|
97
|
+
end
|
98
|
+
|
99
|
+
manifest_location = @aws_helper.bucket_manifest_key(@appliance_config.name)
|
100
|
+
manifest_location = manifest_location[manifest_location.index("/") + 1, manifest_location.length]
|
101
|
+
|
102
|
+
for object in bucket.objects do
|
103
|
+
return true if object.key.eql?(manifest_location)
|
104
|
+
end
|
105
|
+
|
106
|
+
false
|
107
|
+
end
|
108
|
+
|
109
|
+
def upload_image
|
110
|
+
if appliance_already_uploaded?
|
111
|
+
@log.debug "Image for #{@appliance_config.name} appliance is already uploaded, skipping..."
|
112
|
+
return
|
113
|
+
end
|
114
|
+
|
115
|
+
@log.info "Uploading #{@appliance_config.name} AMI to bucket '#{@aws_helper.aws_data['bucket_name']}'..."
|
116
|
+
|
117
|
+
@exec_helper.execute("ec2-upload-bundle -b #{@aws_helper.bucket_key(@appliance_config.name)} -m #{@appliance_config.path.file.ec2.manifest} -a #{@aws_helper.aws_data['access_key']} -s #{@aws_helper.aws_data['secret_access_key']} --retry")
|
118
|
+
end
|
119
|
+
|
120
|
+
def register_image
|
121
|
+
ami_info = @aws_helper.ami_info(@appliance_config.name)
|
122
|
+
|
123
|
+
if ami_info
|
124
|
+
@log.info "Image is registered under id: #{ami_info.imageId}"
|
125
|
+
return
|
126
|
+
else
|
127
|
+
ami_info = @aws_helper.ec2.register_image(:image_location => @aws_helper.bucket_manifest_key(@appliance_config.name))
|
128
|
+
@log.info "Image successfully registered under id: #{ami_info.imageId}."
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
@@ -20,21 +20,50 @@
|
|
20
20
|
|
21
21
|
require 'net/ssh'
|
22
22
|
require 'net/sftp'
|
23
|
-
require 'progressbar
|
24
|
-
require 'boxgrinder-
|
23
|
+
require 'progressbar'
|
24
|
+
require 'boxgrinder-build/plugins/delivery/base/base-delivery-plugin'
|
25
|
+
require 'boxgrinder-build/helpers/package-helper'
|
25
26
|
|
26
27
|
module BoxGrinder
|
27
|
-
class
|
28
|
-
def
|
29
|
-
|
28
|
+
class SFTPPlugin < BaseDeliveryPlugin
|
29
|
+
def info
|
30
|
+
{
|
31
|
+
:name => :sftp,
|
32
|
+
:type => [:sftp],
|
33
|
+
:full_name => "SSH File Transfer Protocol"
|
34
|
+
}
|
35
|
+
end
|
30
36
|
|
31
|
-
|
32
|
-
|
37
|
+
def after_init
|
38
|
+
set_default_config_value('overwrite', false)
|
39
|
+
set_default_config_value('default_permissions', 0644)
|
40
|
+
end
|
41
|
+
|
42
|
+
def execute(deliverables, type = :sftp)
|
43
|
+
validate_plugin_config(['path', 'username', 'host'], 'CHANGEME')
|
44
|
+
|
45
|
+
#SSHValidator.new( @config ).validate
|
46
|
+
|
47
|
+
package = PackageHelper.new(@config, @appliance_config, {:log => @log, :exec_helper => @exec_helper}).package(deliverables)
|
48
|
+
|
49
|
+
@log.info "Uploading #{@appliance_config.name} appliance via SSH..."
|
50
|
+
|
51
|
+
begin
|
52
|
+
#TODO move to a block
|
53
|
+
connect
|
54
|
+
upload_files(@plugin_config['path'], {File.basename(package) => package})
|
55
|
+
disconnect
|
56
|
+
|
57
|
+
@log.info "Appliance #{@appliance_config.name} uploaded."
|
58
|
+
rescue => e
|
59
|
+
@log.error e
|
60
|
+
@log.error "An error occurred while uploading files."
|
61
|
+
end
|
33
62
|
end
|
34
63
|
|
35
64
|
def connect
|
36
|
-
@log.info "Connecting to #{@
|
37
|
-
@ssh = Net::SSH.start(
|
65
|
+
@log.info "Connecting to #{@plugin_config['host']}..."
|
66
|
+
@ssh = Net::SSH.start(@plugin_config['host'], @plugin_config['username'], {:password => @plugin_config['password']})
|
38
67
|
end
|
39
68
|
|
40
69
|
def connected?
|
@@ -43,21 +72,26 @@ module BoxGrinder
|
|
43
72
|
end
|
44
73
|
|
45
74
|
def disconnect
|
46
|
-
@log.info "Disconnecting from #{@
|
75
|
+
@log.info "Disconnecting from #{@plugin_config['host']}..."
|
47
76
|
@ssh.close if connected?
|
48
77
|
@ssh = nil
|
49
78
|
end
|
50
79
|
|
51
|
-
def upload_files(
|
52
|
-
|
80
|
+
def upload_files(path, files = {})
|
53
81
|
return if files.size == 0
|
54
82
|
|
55
83
|
raise "You're not connected to server" unless connected?
|
56
84
|
|
85
|
+
@log.debug "Files to upload:"
|
86
|
+
|
87
|
+
files.each do |remote, local|
|
88
|
+
@log.debug "#{local} => #{remote}"
|
89
|
+
end
|
90
|
+
|
57
91
|
global_size = 0
|
58
92
|
|
59
93
|
files.each_value do |file|
|
60
|
-
global_size += File.size(
|
94
|
+
global_size += File.size(file)
|
61
95
|
end
|
62
96
|
|
63
97
|
global_size_kb = global_size / 1024
|
@@ -66,36 +100,31 @@ module BoxGrinder
|
|
66
100
|
@log.info "#{files.size} files to upload (#{global_size_mb > 0 ? global_size_mb.to_s + "MB" : global_size_kb > 0 ? global_size_kb.to_s + "kB" : global_size.to_s})"
|
67
101
|
|
68
102
|
@ssh.sftp.connect do |sftp|
|
69
|
-
|
70
103
|
begin
|
71
|
-
sftp.stat!(
|
104
|
+
sftp.stat!(path)
|
72
105
|
rescue Net::SFTP::StatusException => e
|
73
106
|
raise unless e.code == 2
|
74
|
-
|
75
|
-
@ssh.exec!( "mkdir -p #{path}" )
|
76
|
-
else
|
77
|
-
raise
|
78
|
-
end
|
107
|
+
@ssh.exec!("mkdir -p #{path}")
|
79
108
|
end
|
80
109
|
|
81
110
|
nb = 0
|
82
111
|
|
83
112
|
files.each do |key, local|
|
84
|
-
name = File.basename(
|
113
|
+
name = File.basename(local)
|
85
114
|
remote = "#{path}/#{key}"
|
86
|
-
size_b = File.size(
|
115
|
+
size_b = File.size(local)
|
87
116
|
size_kb = size_b / 1024
|
88
117
|
nb_of = "#{nb += 1}/#{files.size}"
|
89
118
|
|
90
119
|
begin
|
91
|
-
sftp.stat!(
|
120
|
+
sftp.stat!(remote)
|
92
121
|
|
93
|
-
unless @
|
122
|
+
unless @plugin_config['overwrite']
|
94
123
|
|
95
124
|
local_md5_sum = `md5sum #{local} | awk '{ print $1 }'`.strip
|
96
|
-
remote_md5_sum = @ssh.exec!(
|
125
|
+
remote_md5_sum = @ssh.exec!("md5sum #{remote} | awk '{ print $1 }'").strip
|
97
126
|
|
98
|
-
if (local_md5_sum.eql?(
|
127
|
+
if (local_md5_sum.eql?(remote_md5_sum))
|
99
128
|
@log.info "#{nb_of} #{name}: files are identical (md5sum: #{local_md5_sum}), skipping..."
|
100
129
|
next
|
101
130
|
end
|
@@ -105,16 +134,16 @@ module BoxGrinder
|
|
105
134
|
raise unless e.code == 2
|
106
135
|
end
|
107
136
|
|
108
|
-
@ssh.exec!(
|
137
|
+
@ssh.exec!("mkdir -p #{File.dirname(remote) }")
|
109
138
|
|
110
|
-
pbar = ProgressBar.new(
|
139
|
+
pbar = ProgressBar.new("#{nb_of} #{name}", size_b)
|
111
140
|
pbar.file_transfer_mode
|
112
141
|
|
113
|
-
sftp.upload!(
|
142
|
+
sftp.upload!(local, remote) do |event, uploader, * args|
|
114
143
|
case event
|
115
144
|
when :open then
|
116
145
|
when :put then
|
117
|
-
pbar.set(
|
146
|
+
pbar.set(args[1])
|
118
147
|
when :close then
|
119
148
|
when :mkdir then
|
120
149
|
when :finish then
|
@@ -122,19 +151,9 @@ module BoxGrinder
|
|
122
151
|
end
|
123
152
|
end
|
124
153
|
|
125
|
-
sftp.setstat(remote, :permissions => @
|
126
|
-
|
154
|
+
sftp.setstat(remote, :permissions => @plugin_config['default_permissions'])
|
127
155
|
end
|
128
156
|
end
|
129
157
|
end
|
130
|
-
|
131
|
-
def createrepo( path, directories = [] )
|
132
|
-
raise "You're not connected to server" unless connected?
|
133
|
-
|
134
|
-
directories.each do |directory|
|
135
|
-
@log.info "Refreshing repository information in #{directory}..."
|
136
|
-
@ssh.exec!( "createrepo #{path}/#{directory}" )
|
137
|
-
end
|
138
|
-
end
|
139
158
|
end
|
140
|
-
end
|
159
|
+
end
|
@@ -18,59 +18,75 @@
|
|
18
18
|
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
19
19
|
# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
20
20
|
|
21
|
-
require
|
22
|
-
require 'rake/tasklib'
|
21
|
+
require 'fileutils'
|
23
22
|
require 'yaml'
|
24
23
|
require 'erb'
|
25
24
|
|
26
25
|
module BoxGrinder
|
27
26
|
|
28
|
-
class
|
27
|
+
class Kickstart
|
29
28
|
|
30
|
-
def initialize(
|
29
|
+
def initialize(config, appliance_config, repos, options = {})
|
31
30
|
@config = config
|
31
|
+
@repos = repos
|
32
32
|
@appliance_config = appliance_config
|
33
33
|
@log = options[:log] || Logger.new(STDOUT)
|
34
|
+
end
|
35
|
+
|
36
|
+
def create
|
37
|
+
FileUtils.mkdir_p @appliance_config.path.dir.raw.build
|
34
38
|
|
35
|
-
|
39
|
+
template = "#{File.dirname(__FILE__)}/src/appliance.ks.erb"
|
40
|
+
kickstart = ERB.new(File.read(template)).result(build_definition.send(:binding))
|
41
|
+
File.open(@appliance_config.path.file.raw.kickstart, 'w') { |f| f.write(kickstart) }
|
36
42
|
end
|
37
43
|
|
38
44
|
def build_definition
|
39
|
-
definition = {
|
45
|
+
definition = {}
|
46
|
+
|
47
|
+
definition['appliance_config'] = @appliance_config
|
40
48
|
|
41
|
-
definition['partitions'] = @appliance_config.hardware.partitions.values
|
49
|
+
#definition['partitions'] = @appliance_config.hardware.partitions.values
|
42
50
|
definition['name'] = @appliance_config.name
|
43
51
|
definition['arch'] = @appliance_config.hardware.arch
|
44
52
|
definition['appliance_names'] = @appliance_config.appliances
|
45
53
|
definition['repos'] = []
|
46
54
|
|
47
|
-
appliance_definition = @
|
55
|
+
# appliance_definition = @image_config.definition
|
56
|
+
#
|
57
|
+
# if SUPPORTED_DESKTOP_TYPES.include?( appliance_definition['desktop'] )
|
58
|
+
# definition['graphical'] = true
|
59
|
+
#
|
60
|
+
# # default X package groups
|
61
|
+
# definition['packages'] = [ "@base-x", "@base", "@core", "@fonts", "@input-methods", "@admin-tools", "@dial-up", "@hardware-support", "@printing" ]
|
62
|
+
#
|
63
|
+
# #selected desktop environment
|
64
|
+
# definition['packages'] += [ "@#{appliance_definition['desktop']}-desktop" ]
|
65
|
+
# else
|
66
|
+
# definition['graphical'] = false
|
67
|
+
# definition['packages'] = []
|
68
|
+
# end
|
48
69
|
|
49
|
-
|
50
|
-
|
70
|
+
definition['graphical'] = false
|
71
|
+
definition['packages'] = []
|
51
72
|
|
52
|
-
|
53
|
-
definition['packages'] = [ "@base-x", "@base", "@core", "@fonts", "@input-methods", "@admin-tools", "@dial-up", "@hardware-support", "@printing" ]
|
73
|
+
definition['packages'] += @appliance_config.packages.includes
|
54
74
|
|
55
|
-
|
56
|
-
definition['packages']
|
57
|
-
else
|
58
|
-
definition['graphical'] = false
|
59
|
-
definition['packages'] = []
|
75
|
+
@appliance_config.packages.excludes do |package|
|
76
|
+
definition['packages'].push("-#{package}")
|
60
77
|
end
|
61
78
|
|
62
|
-
definition['packages'] += @appliance_config.packages
|
63
|
-
|
64
79
|
# defautlt filesystem
|
65
80
|
definition['fstype'] = "ext3"
|
66
81
|
|
67
82
|
# fix for F12; this is needed because of selinux management in appliance-creator
|
68
83
|
if @appliance_config.os.name.eql?("fedora")
|
84
|
+
definition['packages'].push("kernel", "passwd")
|
69
85
|
case @appliance_config.os.version.to_s
|
70
86
|
when "12" then
|
71
87
|
definition['packages'].push "system-config-firewall-base"
|
72
|
-
|
73
|
-
|
88
|
+
# default filesystem for fedora 12
|
89
|
+
#definition['fstype'] = "ext4"
|
74
90
|
when "11" then
|
75
91
|
definition['packages'].push "lokkit"
|
76
92
|
end
|
@@ -78,8 +94,8 @@ module BoxGrinder
|
|
78
94
|
|
79
95
|
definition['root_password'] = @appliance_config.os.password
|
80
96
|
|
81
|
-
def definition.method_missing(sym, *args)
|
82
|
-
self[
|
97
|
+
def definition.method_missing(sym, * args)
|
98
|
+
self[sym.to_s]
|
83
99
|
end
|
84
100
|
|
85
101
|
cost = 40
|
@@ -92,7 +108,7 @@ module BoxGrinder
|
|
92
108
|
urltype = 'baseurl'
|
93
109
|
end
|
94
110
|
|
95
|
-
url = repo[urltype].gsub(
|
111
|
+
url = repo[urltype].gsub(/#ARCH#/, @appliance_config.hardware.arch).gsub(/#OS_VERSION#/, @appliance_config.os.version).gsub(/#OS_NAME#/, @appliance_config.os.name)
|
96
112
|
|
97
113
|
repo_def = "repo --name=#{repo['name']} --cost=#{cost} --#{urltype}=#{url}"
|
98
114
|
repo_def += " --excludepkgs=#{repo['excludes'].join(',')}" unless repo['excludes'].nil? or repo['excludes'].empty?
|
@@ -105,39 +121,13 @@ module BoxGrinder
|
|
105
121
|
definition
|
106
122
|
end
|
107
123
|
|
108
|
-
def define_tasks
|
109
|
-
directory @appliance_config.path.dir.raw.build
|
110
|
-
|
111
|
-
file @appliance_config.path.file.raw.config => @appliance_config.path.dir.raw.build do
|
112
|
-
File.open( @appliance_config.path.file.raw.config, "w") {|f| f.write( @appliance_config.to_yaml ) } unless File.exists?( @appliance_config.path.file.raw.config )
|
113
|
-
end
|
114
|
-
|
115
|
-
task "appliance:#{@appliance_config.name}:config" do
|
116
|
-
if File.exists?( @appliance_config.path.file.raw.config )
|
117
|
-
unless @appliance_config.eql?( YAML.load_file( @appliance_config.path.file.raw.config ) )
|
118
|
-
FileUtils.rm_rf appliance_build_dir
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
file @appliance_config.path.file.raw.kickstart => [ @appliance_config.path.file.raw.config ] do
|
124
|
-
template = File.dirname( __FILE__ ) + "/erb/appliance.ks.erb"
|
125
|
-
kickstart = ERB.new( File.read( template ) ).result( build_definition.send( :binding ) )
|
126
|
-
File.open( @appliance_config.path.file.raw.kickstart, 'w' ) {|f| f.write( kickstart ) }
|
127
|
-
end
|
128
|
-
|
129
|
-
#desc "Build kickstart for #{File.basename( @appliance_config.name, '-appliance' )} appliance"
|
130
|
-
task "appliance:#{@appliance_config.name}:kickstart" => [ "appliance:#{@appliance_config.name}:config", @appliance_config.path.file.raw.kickstart ]
|
131
|
-
|
132
|
-
end
|
133
|
-
|
134
124
|
def valid_repos
|
135
|
-
os_repos =
|
125
|
+
os_repos = @repos[@appliance_config.os.version]
|
136
126
|
|
137
127
|
repos = Array.new
|
138
128
|
|
139
|
-
for type in [
|
140
|
-
unless os_repos[type].nil?
|
129
|
+
for type in ["base", "updates"]
|
130
|
+
unless os_repos.nil? or os_repos[type].nil?
|
141
131
|
|
142
132
|
mirrorlist = os_repos[type]['mirrorlist']
|
143
133
|
baseurl = os_repos[type]['baseurl']
|
@@ -145,9 +135,9 @@ module BoxGrinder
|
|
145
135
|
name = "#{@appliance_config.os.name}-#{@appliance_config.os.version}-#{type}"
|
146
136
|
|
147
137
|
if mirrorlist.nil?
|
148
|
-
repos.push({
|
138
|
+
repos.push({"name" => name, "baseurl" => baseurl})
|
149
139
|
else
|
150
|
-
repos.push({
|
140
|
+
repos.push({"name" => name, "mirrorlist" => mirrorlist})
|
151
141
|
end
|
152
142
|
end
|
153
143
|
end
|