PackerFiles 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/PackerFiles.gemspec +36 -0
- data/README.md +32 -0
- data/Rakefile +21 -0
- data/bin/pkf +5 -0
- data/lib/PackerFiles/CLI/OS.rb +44 -0
- data/lib/PackerFiles/CLI/Root.rb +41 -0
- data/lib/PackerFiles/Core/Base.rb +23 -0
- data/lib/PackerFiles/Core/CDImage.rb +185 -0
- data/lib/PackerFiles/Core/Disk.rb +135 -0
- data/lib/PackerFiles/Core/Exceptions.rb +65 -0
- data/lib/PackerFiles/Core/Hypervisor.rb +96 -0
- data/lib/PackerFiles/Core/Keyboard.rb +38 -0
- data/lib/PackerFiles/Core/Locale.rb +62 -0
- data/lib/PackerFiles/Core/LogicalVolume.rb +41 -0
- data/lib/PackerFiles/Core/Network.rb +67 -0
- data/lib/PackerFiles/Core/Packages.rb +30 -0
- data/lib/PackerFiles/Core/Partition.rb +41 -0
- data/lib/PackerFiles/Core/TimeZone.rb +45 -0
- data/lib/PackerFiles/Core/User.rb +46 -0
- data/lib/PackerFiles/Core/VolumeGroup.rb +50 -0
- data/lib/PackerFiles/Core/example/CDImage.txt +75 -0
- data/lib/PackerFiles/Core/example/Disk.txt +29 -0
- data/lib/PackerFiles/Core/example/Hypervisor.txt +111 -0
- data/lib/PackerFiles/Core/example/Keyboard.txt +28 -0
- data/lib/PackerFiles/Core/example/Locale.txt +31 -0
- data/lib/PackerFiles/Core/example/Network.txt +68 -0
- data/lib/PackerFiles/Core/example/Packages.txt +22 -0
- data/lib/PackerFiles/Core/example/TimeZone.txt +36 -0
- data/lib/PackerFiles/Core/example/User.txt +48 -0
- data/lib/PackerFiles/OS/Builder.rb +116 -0
- data/lib/PackerFiles/OS/CentOS/CD.rb +81 -0
- data/lib/PackerFiles/OS/CentOS/Kickstart.rb +64 -0
- data/lib/PackerFiles/OS/CentOS/Server.rb +170 -0
- data/lib/PackerFiles/OS/CentOS/Templates/Base_erb.rb +4 -0
- data/lib/PackerFiles/OS/CentOS/Templates/Disk_erb.rb +35 -0
- data/lib/PackerFiles/OS/CentOS/Templates/Keyboard_erb.rb +4 -0
- data/lib/PackerFiles/OS/CentOS/Templates/Locale_erb.rb +4 -0
- data/lib/PackerFiles/OS/CentOS/Templates/Network_erb.rb +17 -0
- data/lib/PackerFiles/OS/CentOS/Templates/Packages_erb.rb +34 -0
- data/lib/PackerFiles/OS/CentOS/Templates/Tail_erb.rb +15 -0
- data/lib/PackerFiles/OS/CentOS/Templates/TimeZone_erb.rb +10 -0
- data/lib/PackerFiles/OS/CentOS/Templates/User_erb.rb +20 -0
- data/lib/PackerFiles/OS/CentOS/Templates/boot_command_erb.rb +16 -0
- data/lib/PackerFiles/OS/CentOS/Templates/command_as_root_erb.rb +1 -0
- data/lib/PackerFiles/OS/CentOS/Templates/disable_root_erb.rb +1 -0
- data/lib/PackerFiles/OS/CentOS/Templates/enable_root_erb.rb +1 -0
- data/lib/PackerFiles/OS/CentOS/Templates/shutdown_command_erb.rb +1 -0
- data/lib/PackerFiles/OS/Debian/Apt.rb +42 -0
- data/lib/PackerFiles/OS/Debian/CD.rb +65 -0
- data/lib/PackerFiles/OS/Debian/Mirrors.rb +73 -0
- data/lib/PackerFiles/OS/Debian/Preseed.rb +64 -0
- data/lib/PackerFiles/OS/Debian/Server.rb +169 -0
- data/lib/PackerFiles/OS/Debian/Templates/Apt_erb.rb +18 -0
- data/lib/PackerFiles/OS/Debian/Templates/Disk_erb.rb +69 -0
- data/lib/PackerFiles/OS/Debian/Templates/Keyboard_erb.rb +5 -0
- data/lib/PackerFiles/OS/Debian/Templates/Locale_erb.rb +7 -0
- data/lib/PackerFiles/OS/Debian/Templates/Mirrors_erb.rb +9 -0
- data/lib/PackerFiles/OS/Debian/Templates/Network_erb.rb +19 -0
- data/lib/PackerFiles/OS/Debian/Templates/Packages_erb.rb +6 -0
- data/lib/PackerFiles/OS/Debian/Templates/TimeZone_erb.rb +6 -0
- data/lib/PackerFiles/OS/Debian/Templates/User_erb.rb +14 -0
- data/lib/PackerFiles/OS/Debian/Templates/boot_command_erb.rb +24 -0
- data/lib/PackerFiles/OS/Debian/Templates/command_as_root_erb.rb +1 -0
- data/lib/PackerFiles/OS/Debian/Templates/disable_root_erb.rb +5 -0
- data/lib/PackerFiles/OS/Debian/Templates/enable_root_erb.rb +1 -0
- data/lib/PackerFiles/OS/Debian/Templates/shutdown_command_erb.rb +1 -0
- data/lib/PackerFiles/OS/Debian/example/Apt.txt +55 -0
- data/lib/PackerFiles/OS/DocGenerator.rb +51 -0
- data/lib/PackerFiles/OS/Finder.rb +96 -0
- data/lib/PackerFiles/OS/RHEL/CD.rb +32 -0
- data/lib/PackerFiles/OS/RHEL/Fedora.rb +59 -0
- data/lib/PackerFiles/OS/RHEL/FedoraCD.rb +68 -0
- data/lib/PackerFiles/OS/RHEL/Server.rb +32 -0
- data/lib/PackerFiles/OS/RHEL/Templates/Fedora_Tail_erb.rb +14 -0
- data/lib/PackerFiles/OS/RHEL/Templates/boot_command_fedora_erb.rb +16 -0
- data/lib/PackerFiles/OS/SUSE/Templates/Base_erb.xml +32 -0
- data/lib/PackerFiles/OS/SUSE/Templates/Disk_erb.xml +110 -0
- data/lib/PackerFiles/OS/SUSE/Templates/Keyboard_erb.xml +7 -0
- data/lib/PackerFiles/OS/SUSE/Templates/Locale_erb.xml +18 -0
- data/lib/PackerFiles/OS/SUSE/Templates/Network_erb.xml +143 -0
- data/lib/PackerFiles/OS/SUSE/Templates/Packages_erb.xml +29 -0
- data/lib/PackerFiles/OS/SUSE/Templates/Tail_erb.xml +4 -0
- data/lib/PackerFiles/OS/SUSE/Templates/TimeZone_erb.xml +15 -0
- data/lib/PackerFiles/OS/SUSE/Templates/User_erb.xml +57 -0
- data/lib/PackerFiles/OS/SUSE/Templates/boot_command_erb.rb +23 -0
- data/lib/PackerFiles/OS/SUSE/Templates/command_as_root_erb.rb +1 -0
- data/lib/PackerFiles/OS/SUSE/Templates/disable_root_erb.rb +1 -0
- data/lib/PackerFiles/OS/SUSE/Templates/enable_root_erb.rb +1 -0
- data/lib/PackerFiles/OS/SUSE/Templates/shutdown_command_erb.rb +1 -0
- data/lib/PackerFiles/OS/Ubuntu/CD.rb +81 -0
- data/lib/PackerFiles/OS/Ubuntu/Desktop.rb +50 -0
- data/lib/PackerFiles/OS/Ubuntu/DesktopCD.rb +16 -0
- data/lib/PackerFiles/OS/Ubuntu/Mirrors.rb +103 -0
- data/lib/PackerFiles/OS/Ubuntu/Server.rb +78 -0
- data/lib/PackerFiles/OS/Ubuntu/Templates/Apt_erb.rb +18 -0
- data/lib/PackerFiles/OS/Ubuntu/Templates/boot_command_desktop_erb.rb +36 -0
- data/lib/PackerFiles/OS/Ubuntu/Templates/boot_command_erb.rb +30 -0
- data/lib/PackerFiles/OS/Ubuntu/Templates/ubiquity_erb.rb +8 -0
- data/lib/PackerFiles/OS/example/Doc.txt +8 -0
- data/lib/PackerFiles/Provision/Base.rb +20 -0
- data/lib/PackerFiles/Provision/ChefSolo.rb +90 -0
- data/lib/PackerFiles/Provision/ChefSoloHelper.rb +72 -0
- data/lib/PackerFiles/Provision/Copy.rb +22 -0
- data/lib/PackerFiles/Provision/ExternalScript.rb +43 -0
- data/lib/PackerFiles/Provision/InlineScript.rb +37 -0
- data/lib/PackerFiles/Provision/Provisioners.rb +87 -0
- data/lib/PackerFiles/Provision/example/Provisioners.txt +21 -0
- data/lib/PackerFiles/Utils/AutoZone.rb +96 -0
- data/lib/PackerFiles/Utils/FastestURL.rb +73 -0
- data/lib/PackerFiles/Utils/Generator.rb +34 -0
- data/lib/PackerFiles/Utils/HashSerializer.rb +110 -0
- data/lib/PackerFiles/Utils/Size.rb +44 -0
- data/lib/PackerFiles/Utils/TypeAccessor.rb +71 -0
- data/lib/PackerFiles/Virtual/Hypervisors.rb +72 -0
- data/lib/PackerFiles/Virtual/KVM.rb +119 -0
- data/lib/PackerFiles/Virtual/KVMConverter.rb +79 -0
- data/lib/PackerFiles/Virtual/VMWare.rb +108 -0
- data/lib/PackerFiles/Virtual/VMWareConverter.rb +78 -0
- data/lib/PackerFiles/Virtual/VirtualBox.rb +98 -0
- data/lib/PackerFiles/Virtual/VirtualBoxConverter.rb +75 -0
- data/lib/PackerFiles/Virtual/example/Hypervisors.txt +23 -0
- data/lib/PackerFiles/version.rb +3 -0
- data/lib/PackerFiles.rb +44 -0
- data/spec/core/builder_spec.rb +84 -0
- data/spec/core/cdimage_spec.rb +159 -0
- data/spec/core/disk_spec.rb +191 -0
- data/spec/core/keyboard_spec.rb +36 -0
- data/spec/core/locale_spec.rb +73 -0
- data/spec/core/network_spec.rb +96 -0
- data/spec/core/packages_spec.rb +18 -0
- data/spec/core/timezone_spec.rb +43 -0
- data/spec/core/user_spec.rb +44 -0
- data/spec/core/volume_group_spec.rb +53 -0
- data/spec/os/centos/cd_spec.rb +12 -0
- data/spec/os/centos/data/Server-Script-Provisioner.rb +57 -0
- data/spec/os/centos/data/Server.rb +55 -0
- data/spec/os/centos/data/chef-solo-provisioner.rb +58 -0
- data/spec/os/centos/finder_spec.rb +22 -0
- data/spec/os/centos/templates/boot_command_spec.rb +57 -0
- data/spec/os/centos/templates/disk_spec.rb +79 -0
- data/spec/os/centos/templates/keyboard_spec.rb +18 -0
- data/spec/os/centos/templates/locale_spec.rb +26 -0
- data/spec/os/centos/templates/network_spec.rb +38 -0
- data/spec/os/centos/templates/packages_spec.rb +18 -0
- data/spec/os/centos/templates/timezone_spec.rb +37 -0
- data/spec/os/centos/templates/user_spec.rb +24 -0
- data/spec/os/debian/apt_spec.rb +50 -0
- data/spec/os/debian/cd_spec.rb +30 -0
- data/spec/os/debian/data/7zip.tar.gz +0 -0
- data/spec/os/debian/data/All-sections.rb +60 -0
- data/spec/os/debian/data/Chef-Solo-Provisioner.rb +60 -0
- data/spec/os/debian/data/Copy-Provisioner.rb +61 -0
- data/spec/os/debian/data/External-Script-Provisioner.rb +69 -0
- data/spec/os/debian/data/Missing-CDImage.rb +53 -0
- data/spec/os/debian/data/Missing-VMWare-KVM-sections.rb +51 -0
- data/spec/os/debian/data/Missing-sections.rb +53 -0
- data/spec/os/debian/data/Script-Provisioner.rb +62 -0
- data/spec/os/debian/data/chef-solo-cookbooks/git_setup/Berksfile.lock +32 -0
- data/spec/os/debian/data/chef-solo-cookbooks/git_setup/README.md +81 -0
- data/spec/os/debian/data/chef-solo-cookbooks/git_setup/attributes/default.rb +3 -0
- data/spec/os/debian/data/chef-solo-cookbooks/git_setup/metadata.rb +11 -0
- data/spec/os/debian/data/chef-solo-cookbooks/git_setup/recipes/default.rb +30 -0
- data/spec/os/debian/data/chef-solo.json +5 -0
- data/spec/os/debian/data/test-script.sh +4 -0
- data/spec/os/debian/finder_spec.rb +59 -0
- data/spec/os/debian/mirrors_spec.rb +18 -0
- data/spec/os/debian/preseed_spec.rb +56 -0
- data/spec/os/debian/server_spec.rb +59 -0
- data/spec/os/debian/templates/apt_spec.rb +20 -0
- data/spec/os/debian/templates/boot_command_spec.rb +56 -0
- data/spec/os/debian/templates/disk_spec.rb +81 -0
- data/spec/os/debian/templates/keyboard_spec.rb +18 -0
- data/spec/os/debian/templates/locale_spec.rb +36 -0
- data/spec/os/debian/templates/mirrors_spec.rb +16 -0
- data/spec/os/debian/templates/network_spec.rb +38 -0
- data/spec/os/debian/templates/packages_spec.rb +17 -0
- data/spec/os/debian/templates/timezone_spec.rb +36 -0
- data/spec/os/debian/templates/user_spec.rb +25 -0
- data/spec/os/finder_spec.rb +21 -0
- data/spec/os/rhel/data/Fedora.rb +45 -0
- data/spec/os/rhel/data/Server-Custom.rb +54 -0
- data/spec/os/rhel/data/Server.rb +45 -0
- data/spec/os/rhel/finder_spec.rb +21 -0
- data/spec/os/ubuntu/cd_spec.rb +28 -0
- data/spec/os/ubuntu/data/Desktop.rb +61 -0
- data/spec/os/ubuntu/data/Server.rb +61 -0
- data/spec/os/ubuntu/finder_spec.rb +17 -0
- data/spec/os/ubuntu/mirrors_spec.rb +18 -0
- data/spec/utils/autozone_spec.rb +33 -0
- data/spec/virtual/virtual_box_spec.rb +16 -0
- metadata +405 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Requires
|
|
2
|
+
require_relative 'Copy'
|
|
3
|
+
require_relative 'InlineScript'
|
|
4
|
+
require_relative 'ExternalScript'
|
|
5
|
+
require_relative 'ChefSolo'
|
|
6
|
+
|
|
7
|
+
# Top level class for managing Provisioners in a OS Spec file
|
|
8
|
+
module PackerFiles
|
|
9
|
+
class Provisioners
|
|
10
|
+
|
|
11
|
+
# Documentation for this class
|
|
12
|
+
def self.doc_file
|
|
13
|
+
PackerFiles.DirPath('Provision/example/Provisioners.txt').first
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# List of registered provisioners
|
|
17
|
+
attr_accessor :list
|
|
18
|
+
|
|
19
|
+
# Constructor just yields self for further initialization
|
|
20
|
+
def initialize(&block)
|
|
21
|
+
@list = []
|
|
22
|
+
yield self if block_given?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Enable File Copy Provisioner to be called multiple times
|
|
26
|
+
# with order preservation.
|
|
27
|
+
def Copy(&block)
|
|
28
|
+
@list.push(Provision::Copy.new(&block))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Enable Inline Script Provisioner to be called multiple times
|
|
32
|
+
# with order preservation.
|
|
33
|
+
def InlineScript(&block)
|
|
34
|
+
@list.push(Provision::InlineScript.new(&block))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Enable External Script Provisioner to be called multiple times
|
|
38
|
+
# with order preservation.
|
|
39
|
+
def ExternalScript(&block)
|
|
40
|
+
@list.push(Provision::ExternalScript.new(&block))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Enable Chef Solo Provisioner to be called multiple times
|
|
44
|
+
# with order preservation.
|
|
45
|
+
def ChefSolo(&block)
|
|
46
|
+
@list.push(Provision::ChefSolo.new(&block))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Convert self into Packer JSON format.
|
|
50
|
+
def convert(gen, os)
|
|
51
|
+
@list.unshift(EnableRootLoginScript(os))
|
|
52
|
+
@list.push(DisableRootLoginScript(os))
|
|
53
|
+
@list.compact.each do |prov|
|
|
54
|
+
prov.os = os
|
|
55
|
+
hash = prov.to_hash(os)
|
|
56
|
+
gen.provisioners.push(hash) if !hash.nil?
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Create a inline script command to enable root logins
|
|
61
|
+
private
|
|
62
|
+
def EnableRootLoginScript(os)
|
|
63
|
+
cmd = os.run_command_as_root
|
|
64
|
+
enable = os.enable_root_for_user
|
|
65
|
+
if !cmd.nil? && !enable.nil?
|
|
66
|
+
return Provision::InlineScript.new do |script|
|
|
67
|
+
script.execute_command = cmd
|
|
68
|
+
script.inline = enable
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Create a inline script command to disable root logins
|
|
74
|
+
private
|
|
75
|
+
def DisableRootLoginScript(os)
|
|
76
|
+
cmd = os.run_command_as_root
|
|
77
|
+
disable = os.disable_root_for_user
|
|
78
|
+
if !cmd.nil? && !disable.nil?
|
|
79
|
+
return Provision::InlineScript.new do |script|
|
|
80
|
+
script.execute_command = cmd
|
|
81
|
+
script.inline = disable
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
# Define Provisioners for this OS
|
|
3
|
+
<% if @obj.nil? -%>
|
|
4
|
+
#os.<%= @name -%> do |prov|
|
|
5
|
+
<% else -%>
|
|
6
|
+
os.<%= @name -%> do |prov|
|
|
7
|
+
<% end -%>
|
|
8
|
+
|
|
9
|
+
# The Copy provisioner is used for Copying files.
|
|
10
|
+
# Multiple files or folders can be copied by using the same
|
|
11
|
+
# construct many times.
|
|
12
|
+
# prov.Copy do |cp|
|
|
13
|
+
# cp.source = 'source'
|
|
14
|
+
# cp.destination = 'destination'
|
|
15
|
+
# end
|
|
16
|
+
|
|
17
|
+
<% if @obj.nil? -%>
|
|
18
|
+
#end
|
|
19
|
+
<% else -%>
|
|
20
|
+
end
|
|
21
|
+
<% end -%>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Requires
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'open-uri'
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
6
|
+
module PackerFiles
|
|
7
|
+
|
|
8
|
+
module Utils
|
|
9
|
+
|
|
10
|
+
# AutoZone handles the automatic detection of a time zone via
|
|
11
|
+
# web based GEO Lookups.
|
|
12
|
+
class AutoZone
|
|
13
|
+
|
|
14
|
+
# URL for maxmind timezone specifier
|
|
15
|
+
@@url = 'https://raw.githubusercontent.com/maxmind/geoip-api-c/master/timezone/timezone.txt'
|
|
16
|
+
|
|
17
|
+
# List of URLs for Geo-IP lookup
|
|
18
|
+
@@geo = [
|
|
19
|
+
'http://www.telize.com/geoip',
|
|
20
|
+
'http://freegeoip.net/json'
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
# JSON object cache to prevent multiple internet lookups.
|
|
24
|
+
@@cache = nil
|
|
25
|
+
|
|
26
|
+
# Return back the Cached JSON
|
|
27
|
+
def self.Cache
|
|
28
|
+
@@cache
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Return the JSON from the web services, to do what ever.
|
|
32
|
+
def JSON
|
|
33
|
+
|
|
34
|
+
# Return the cache if it is populated already
|
|
35
|
+
return @@cache if !@@cache.nil?
|
|
36
|
+
|
|
37
|
+
# Cache Miss! Let us get it from Internet.
|
|
38
|
+
@@geo.each do |url|
|
|
39
|
+
begin
|
|
40
|
+
contents = open(url) {|f| f.read }
|
|
41
|
+
@@cache = JSON.parse(contents)
|
|
42
|
+
break
|
|
43
|
+
rescue
|
|
44
|
+
next
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
return @@cache
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Sugar coated country code
|
|
51
|
+
def country_code
|
|
52
|
+
return self.JSON['country_code']
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Sugar coated country_area code
|
|
56
|
+
def country_area_code
|
|
57
|
+
json = self.JSON
|
|
58
|
+
return json['country_code'], json['area_code']
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Sugar coated perfect time zone look-up
|
|
62
|
+
def time_zone
|
|
63
|
+
|
|
64
|
+
# Get the RAW JSON
|
|
65
|
+
json = self.JSON
|
|
66
|
+
|
|
67
|
+
# If it already contains a timezone, good enough and move on.
|
|
68
|
+
return json['timezone'] if json.has_key?('timezone')
|
|
69
|
+
|
|
70
|
+
# If not need more lookups with max-mind DB. Cache it for further
|
|
71
|
+
# use.
|
|
72
|
+
country = json['country_code']
|
|
73
|
+
area = json['area_code']
|
|
74
|
+
open(@@url) {|f|
|
|
75
|
+
f.each_line do |line|
|
|
76
|
+
arr = line.split("\t")
|
|
77
|
+
# Return the Time Zone if there is an exact match of country and area
|
|
78
|
+
if (arr[0] == country && arr[1] == area)
|
|
79
|
+
@@cache['timezone'] = arr[2]
|
|
80
|
+
break
|
|
81
|
+
# Return the Time Zone if there is an exact match of country and if
|
|
82
|
+
# area cannot be determined reliably.
|
|
83
|
+
elsif (arr[0] == country && (arr[1].empty? || area.empty?))
|
|
84
|
+
@@cache['timezone'] = arr[2]
|
|
85
|
+
break
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
}
|
|
89
|
+
return @@cache['timezone']
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end # AutoZone
|
|
93
|
+
|
|
94
|
+
end # Utils
|
|
95
|
+
|
|
96
|
+
end # PackerFiles
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Requires
|
|
2
|
+
require 'open-uri'
|
|
3
|
+
require 'benchmark'
|
|
4
|
+
require 'uri'
|
|
5
|
+
|
|
6
|
+
module PackerFiles
|
|
7
|
+
|
|
8
|
+
module Utils
|
|
9
|
+
|
|
10
|
+
# Given a list of URL, returns the fastest URL (to access) among them.
|
|
11
|
+
# This is done by launching several threads in parallel and estimating
|
|
12
|
+
# the time taken to access the contents of these URLs.
|
|
13
|
+
class FastestURL
|
|
14
|
+
|
|
15
|
+
# Error URL
|
|
16
|
+
@@error = 25000
|
|
17
|
+
|
|
18
|
+
# Creates a new object of type FastestURL. slow_limit is used for
|
|
19
|
+
# signalling the response time (in seconds) of a web URL to be
|
|
20
|
+
# categorized as slow. Trials specifies the # of attempts the web
|
|
21
|
+
# URLs must be opened and closed.
|
|
22
|
+
def initialize(slow_limit = 0.5 , trials = 1)
|
|
23
|
+
@limit = slow_limit
|
|
24
|
+
@trials = trials
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Returns URLs sorted in terms of best access times from a list of
|
|
28
|
+
# input URLs.
|
|
29
|
+
def best_urls(url_list)
|
|
30
|
+
threads = url_list.map { |h| Thread.new {speed_trials(h) }}
|
|
31
|
+
speeds = threads.map { |t| t.join; t.value }
|
|
32
|
+
hash = Hash.new
|
|
33
|
+
url_list.each_with_index do |url, index|
|
|
34
|
+
hash[url] = speeds.at(index) if speeds.at(index) != @@error
|
|
35
|
+
end
|
|
36
|
+
hash.sort_by {|url, speed| speed}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Compute the latency of a web url, multiple times via independent
|
|
40
|
+
# trials. This is called in thread context only.
|
|
41
|
+
private
|
|
42
|
+
def speed_trials(url)
|
|
43
|
+
total = 0.0
|
|
44
|
+
@trials.times do
|
|
45
|
+
speed = estimate_speed(url)
|
|
46
|
+
if speed >= @limit
|
|
47
|
+
return @@error
|
|
48
|
+
else
|
|
49
|
+
total += speed
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
return (total / @trials)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# This function is called in thread context only. It computes
|
|
56
|
+
# the time it takes for the various mirrors to return the index
|
|
57
|
+
# as a proxy for measuring it's speed.
|
|
58
|
+
private
|
|
59
|
+
def estimate_speed(url)
|
|
60
|
+
Benchmark.realtime do
|
|
61
|
+
begin
|
|
62
|
+
open(url) {|f| f.read}
|
|
63
|
+
rescue Exception => e
|
|
64
|
+
return @@error
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end # FastestURL
|
|
70
|
+
|
|
71
|
+
end # Utils
|
|
72
|
+
|
|
73
|
+
end # PackerFiles
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Requires
|
|
2
|
+
require 'Utils/HashSerializer'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module PackerFiles
|
|
6
|
+
module Utils
|
|
7
|
+
|
|
8
|
+
# Generates the top level JSON file for Packer to operate upon.
|
|
9
|
+
class Generator < HashSerializer
|
|
10
|
+
|
|
11
|
+
# List of Hash Serializers
|
|
12
|
+
hash_variable :variables, Hash
|
|
13
|
+
hash_variable :builders, Array
|
|
14
|
+
hash_variable :provisioners, Array
|
|
15
|
+
|
|
16
|
+
# Constructor
|
|
17
|
+
def initialize
|
|
18
|
+
self.builders = Array.new
|
|
19
|
+
self.variables = Hash.new
|
|
20
|
+
self.provisioners = Array.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Create the JSON file in the given directory
|
|
24
|
+
def create_json(filename)
|
|
25
|
+
hash = self.to_hash
|
|
26
|
+
content = JSON.pretty_generate(hash) + "\n"
|
|
27
|
+
File.write(filename, content)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end # Generator
|
|
31
|
+
|
|
32
|
+
end # Utils
|
|
33
|
+
|
|
34
|
+
end # PackerFiles
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Requires
|
|
2
|
+
|
|
3
|
+
module PackerFiles
|
|
4
|
+
|
|
5
|
+
module Utils
|
|
6
|
+
|
|
7
|
+
# The Hash serializer is a meta-class that allows tracking of objects
|
|
8
|
+
# that needs to be converted into Hash objects, w/o having to hand-write
|
|
9
|
+
# lot of code.
|
|
10
|
+
class HashSerializer
|
|
11
|
+
|
|
12
|
+
# The Meta-class Idiom. All functions within this block are meta-class
|
|
13
|
+
# functions that cannot be invoked on the object, but can be invoked
|
|
14
|
+
# on the class.
|
|
15
|
+
class << self
|
|
16
|
+
|
|
17
|
+
# Specify that a list of methods are tracked for serialization.
|
|
18
|
+
# Name is the attribute name, Type is the object type that it
|
|
19
|
+
# belongs to. Method is the name of the conversion function that
|
|
20
|
+
# returns the value of the object serialized for JSON.
|
|
21
|
+
def hash_variable(name, type = String, method = nil, nil_emit=false)
|
|
22
|
+
@attrs ||= []
|
|
23
|
+
@attrs += [Hash["name", name, "type", type,
|
|
24
|
+
"method", method, "nil_emit", nil_emit]
|
|
25
|
+
]
|
|
26
|
+
self.class_eval do
|
|
27
|
+
|
|
28
|
+
# Read accessor
|
|
29
|
+
define_method(name) do
|
|
30
|
+
instance_variable_get("@#{name}")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Write accessor
|
|
34
|
+
define_method("#{name}=") do |value|
|
|
35
|
+
if value.is_a? type
|
|
36
|
+
instance_variable_set("@#{name}", value)
|
|
37
|
+
else
|
|
38
|
+
raise ArgumentError.new("Invalid Type")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Converter function. We need to first get the
|
|
43
|
+
# variable and then call a function on it by binding
|
|
44
|
+
# first. (See Module::instance_method example in Ruby man page)
|
|
45
|
+
define_method("to_hash_value_#{name}") do
|
|
46
|
+
var = instance_variable_get("@#{name}")
|
|
47
|
+
if (method.nil? || var.nil?)
|
|
48
|
+
var
|
|
49
|
+
else
|
|
50
|
+
self.method(method).call
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Return the attributes that are tracked so that it can be
|
|
58
|
+
# used for serialization.
|
|
59
|
+
def hash_attributes
|
|
60
|
+
@attrs
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Merge a hash serializer object with the current object.
|
|
66
|
+
def merge_hs(other)
|
|
67
|
+
|
|
68
|
+
# Do nothing if the other is not a Hash Serializer
|
|
69
|
+
return unless other.kind_of?(HashSerializer)
|
|
70
|
+
|
|
71
|
+
# Get the attributes set in other and if the same attribute
|
|
72
|
+
# is not set in self, then replace it. Otherwise ignore
|
|
73
|
+
other.class.hash_attributes.each do |attr|
|
|
74
|
+
name = attr['name']
|
|
75
|
+
other_value = other.method(name).call
|
|
76
|
+
self_value = self.method(name).call
|
|
77
|
+
if !other_value.nil? && self_value.nil?
|
|
78
|
+
self.method("#{name}=").call(other_value)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Hash Converter which iterates through all the tracked objects
|
|
84
|
+
# and outputs the hash. This function is *NOT* a meta-class function
|
|
85
|
+
# but instead operates on the object level.
|
|
86
|
+
def to_hash(*args)
|
|
87
|
+
|
|
88
|
+
# Return value
|
|
89
|
+
hash = Hash.new
|
|
90
|
+
|
|
91
|
+
# Get all classes in the class hierarchy until HashSerializer
|
|
92
|
+
index = self.class.ancestors.index(HashSerializer)
|
|
93
|
+
cl_list = self.class.ancestors.slice(0, index)
|
|
94
|
+
cl_list.each do |klass|
|
|
95
|
+
next if !klass.respond_to?(:hash_attributes)
|
|
96
|
+
klass.hash_attributes.each do |attr|
|
|
97
|
+
name = attr['name']
|
|
98
|
+
nil_emit = attr['nil_emit']
|
|
99
|
+
value = method("to_hash_value_#{name}").call
|
|
100
|
+
hash[name] = value if (!value.nil? || (value.nil? && nil_emit))
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
return hash
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end # HashSerializer
|
|
107
|
+
|
|
108
|
+
end # Utils
|
|
109
|
+
|
|
110
|
+
end # PackerFiles
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
module PackerFiles
|
|
3
|
+
|
|
4
|
+
module Utils
|
|
5
|
+
|
|
6
|
+
# Contains utility functions to manage size conversions
|
|
7
|
+
module Size
|
|
8
|
+
|
|
9
|
+
# Array of regular expressions to match size and their
|
|
10
|
+
# corresponding lambda functions to return size in number. It is
|
|
11
|
+
# easy to understand the constants if we remember that Packer always
|
|
12
|
+
# accepts size in MiB [Power of 2].
|
|
13
|
+
@@regex = {
|
|
14
|
+
/([0-9]+)GiB/ => lambda {|n| 1024 * n},
|
|
15
|
+
/([0-9]+)GB/ => lambda {|n| (953.67 * n).round},
|
|
16
|
+
/([0-9]+)MB/ => lambda {|n| (0.95367 * n).round},
|
|
17
|
+
/([0-9]+)MiB/ => lambda {|n| n},
|
|
18
|
+
/([0-9]+)TiB/ => lambda {|n| 1048576 * n},
|
|
19
|
+
/([0-9]+)TB/ => lambda {|n| (909486.46 * n).round},
|
|
20
|
+
/([0-9]+)GHz/ => lambda {|n| 1024 * n},
|
|
21
|
+
/([0-9]+)MHz/ => lambda {|n| n}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Convert a text 'size' into a units of MiB. This is done
|
|
25
|
+
# calling the appropriate lambda function, whenever the
|
|
26
|
+
# regex is matched.
|
|
27
|
+
def MiB(size)
|
|
28
|
+
@@regex.each_pair do |r, l|
|
|
29
|
+
if m = r.match(size)
|
|
30
|
+
return l.call(m[1].to_i)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Convert MiB Size into Bytes
|
|
36
|
+
def Bytes(size)
|
|
37
|
+
size * 1024 * 1024
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end # Size
|
|
41
|
+
|
|
42
|
+
end # Utils
|
|
43
|
+
|
|
44
|
+
end # PackerFiles
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Requires
|
|
2
|
+
require_relative "../Core/Exceptions"
|
|
3
|
+
|
|
4
|
+
module PackerFiles
|
|
5
|
+
|
|
6
|
+
module Utils
|
|
7
|
+
|
|
8
|
+
# Exception class used to indicate that a required type accessor is
|
|
9
|
+
# missing.
|
|
10
|
+
class MissingAccessor < Core::Error
|
|
11
|
+
def initialize(accessor_name, class_name)
|
|
12
|
+
self.message = "Missing #{accessor_name} Section for #{class_name}"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# The Type accessor class is used as a meta-class for any class.
|
|
17
|
+
class TypeAccessor
|
|
18
|
+
|
|
19
|
+
# The Meta-class Idiom. All functions within this block are meta-class
|
|
20
|
+
# functions that cannot be invoked on the object, but can be invoked
|
|
21
|
+
# on the class.
|
|
22
|
+
class << self
|
|
23
|
+
|
|
24
|
+
# Custom accessor to create accessors from type name. It is also
|
|
25
|
+
# Possible to set the name of the accessor. By default it is the
|
|
26
|
+
# name of the type.
|
|
27
|
+
def type_accessor(type, name = type.name.gsub(/.*::/, ''),
|
|
28
|
+
optional = false)
|
|
29
|
+
|
|
30
|
+
# Save the type and name in a array hash, which will be used later.
|
|
31
|
+
@types ||= Hash.new
|
|
32
|
+
@types[name] = [type, optional]
|
|
33
|
+
|
|
34
|
+
# Doing a class_eval creates a new method of "name"
|
|
35
|
+
class_eval do
|
|
36
|
+
|
|
37
|
+
# Read/Write accessor which accepts blocks for initialization.
|
|
38
|
+
define_method("#{name}") do |arg = nil, &block|
|
|
39
|
+
if (self.class.proc_from(&block).nil?)
|
|
40
|
+
instance_variable_get("@#{name}")
|
|
41
|
+
else
|
|
42
|
+
obj = type.new(&block)
|
|
43
|
+
instance_variable_set("@#{name}", obj)
|
|
44
|
+
end
|
|
45
|
+
end # define_method
|
|
46
|
+
end # class_eval
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Return the Hash that is used to track registered type accessors
|
|
51
|
+
def type_accessors
|
|
52
|
+
@types
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Given a block, convert it into a proc. if no block is given
|
|
56
|
+
# then it is a nil object that is returned
|
|
57
|
+
def proc_from(&block)
|
|
58
|
+
if block_given?
|
|
59
|
+
Proc.new
|
|
60
|
+
else
|
|
61
|
+
nil
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end # class << self
|
|
66
|
+
|
|
67
|
+
end # TypeAccessor
|
|
68
|
+
|
|
69
|
+
end # Utils
|
|
70
|
+
|
|
71
|
+
end # PackerFiles
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Requires
|
|
2
|
+
require 'Utils/TypeAccessor'
|
|
3
|
+
require 'Core/Hypervisor'
|
|
4
|
+
|
|
5
|
+
module PackerFiles
|
|
6
|
+
|
|
7
|
+
module Virtual
|
|
8
|
+
|
|
9
|
+
# Internal List of Hypervisors that are supported. All of them Just override
|
|
10
|
+
# the Custom Object call.
|
|
11
|
+
class I_VirtualBox < Core::Hypervisor
|
|
12
|
+
def Custom(&block)
|
|
13
|
+
@custom = VirtualBox.new(&block)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class I_VMWare < Core::Hypervisor
|
|
18
|
+
def Custom(&block)
|
|
19
|
+
@custom = VMWare.new(&block)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class I_KVM < Core::Hypervisor
|
|
24
|
+
def Custom(&block)
|
|
25
|
+
@custom = KVM.new(&block)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Top level class for managing hypervisors in a OS Spec file
|
|
30
|
+
class Hypervisors < Utils::TypeAccessor
|
|
31
|
+
|
|
32
|
+
# Documentation for this class
|
|
33
|
+
def self.doc_file
|
|
34
|
+
PackerFiles.DirPath('Virtual/example/Hypervisors.txt').first
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Specify accessors for various supported Hypervisors
|
|
38
|
+
type_accessor I_VirtualBox, :VirtualBox
|
|
39
|
+
type_accessor I_VMWare, :VMWare
|
|
40
|
+
type_accessor I_KVM, :KVM
|
|
41
|
+
|
|
42
|
+
# Constructor just yields self for further initialization
|
|
43
|
+
def initialize(&block)
|
|
44
|
+
yield self if block_given?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Given a generator and a OS class derived from builder, convert
|
|
48
|
+
# it into hashes suitable for packer json file generation
|
|
49
|
+
def convert(gen, builder)
|
|
50
|
+
|
|
51
|
+
# Convert parameters into hash for registered Hypervisors
|
|
52
|
+
if !self.VirtualBox.nil?
|
|
53
|
+
hash = builder.vbox_converter_hook(gen)
|
|
54
|
+
gen.builders.push(hash) if !hash.nil?
|
|
55
|
+
end
|
|
56
|
+
if !self.VMWare.nil?
|
|
57
|
+
hash = builder.vmware_converter_hook(gen)
|
|
58
|
+
gen.builders.push(hash) if !hash.nil?
|
|
59
|
+
end
|
|
60
|
+
if !self.KVM.nil?
|
|
61
|
+
hash = builder.kvm_converter_hook(gen)
|
|
62
|
+
gen.builders.push(hash) if !hash.nil?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end # Hypervisors
|
|
68
|
+
|
|
69
|
+
end # Virtual
|
|
70
|
+
|
|
71
|
+
end # PackerFiles
|
|
72
|
+
|