boxgrinder-build 0.2.0 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|