PackerFiles 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|