beaker-hostgenerator 0.5.0 → 0.6.0

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.
Files changed (185) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +4 -0
  3. data/HISTORY.md +233 -2
  4. data/README.md +50 -11
  5. data/beaker-hostgenerator.gemspec +2 -2
  6. data/lib/beaker-hostgenerator.rb +0 -1
  7. data/lib/beaker-hostgenerator/cli.rb +38 -26
  8. data/lib/beaker-hostgenerator/data.rb +960 -35
  9. data/lib/beaker-hostgenerator/generator.rb +57 -97
  10. data/lib/beaker-hostgenerator/hypervisor.rb +97 -0
  11. data/lib/beaker-hostgenerator/hypervisor/none.rb +17 -0
  12. data/lib/beaker-hostgenerator/hypervisor/vmpooler.rb +32 -0
  13. data/lib/beaker-hostgenerator/parser.rb +199 -0
  14. data/lib/beaker-hostgenerator/roles.rb +21 -14
  15. data/lib/beaker-hostgenerator/util.rb +10 -29
  16. data/lib/beaker-hostgenerator/version.rb +1 -1
  17. data/spec/beaker-hostgenerator/generator_spec.rb +73 -109
  18. data/spec/beaker-hostgenerator/parser_spec.rb +84 -0
  19. data/test/fixtures/default/cisconx-64a +1 -1
  20. data/test/fixtures/default/windows10ent-32d +22 -0
  21. data/test/fixtures/default/windows10ent-64f +22 -0
  22. data/test/fixtures/default/windows10pro-64m +22 -0
  23. data/test/fixtures/default/windows2003-6432d +22 -0
  24. data/test/fixtures/default/windows2003-64c +22 -0
  25. data/test/fixtures/default/windows2003r2-32f +22 -0
  26. data/test/fixtures/default/windows2003r2-6432aulcdfm +27 -0
  27. data/test/fixtures/default/windows2003r2-64m +22 -0
  28. data/test/fixtures/default/windows2008-6432u +22 -0
  29. data/test/fixtures/default/windows2008-64a +21 -0
  30. data/test/fixtures/default/windows2008r2-6432c +22 -0
  31. data/test/fixtures/default/windows2008r2-64l +22 -0
  32. data/test/fixtures/default/windows2012-6432f +22 -0
  33. data/test/fixtures/default/windows2012-64d +22 -0
  34. data/test/fixtures/default/windows2012r2-6432aulcdfm +27 -0
  35. data/test/fixtures/default/windows2012r2-64m +22 -0
  36. data/test/fixtures/default/windows7-64a +21 -0
  37. data/test/fixtures/default/windows8-64u +22 -0
  38. data/test/fixtures/default/windows81-64l +22 -0
  39. data/test/fixtures/default/windowsvista-64c +22 -0
  40. data/test/fixtures/multiplatform/arista4-32a-windows10pro-64-arista4-32aulcdfm +47 -0
  41. data/test/fixtures/multiplatform/centos4-32u-windows10ent-64-centos4-32m +43 -0
  42. data/test/fixtures/multiplatform/centos4-64l-windows10ent-32-centos4-64f +43 -0
  43. data/test/fixtures/multiplatform/centos5-32c-windowsvista-64-centos5-32d +43 -0
  44. data/test/fixtures/multiplatform/centos5-64d-windows81-64-centos5-64c +43 -0
  45. data/test/fixtures/multiplatform/centos6-32f-windows8-64-centos6-32l +43 -0
  46. data/test/fixtures/multiplatform/centos6-64m-windows7-64-centos6-64u +43 -0
  47. data/test/fixtures/multiplatform/centos7-64aulcdfm-windows2012r2-6432-centos7-64a +47 -0
  48. data/test/fixtures/multiplatform/cisconx-64a-windows2012r2-64-cisconx-64aulcdfm +53 -0
  49. data/test/fixtures/multiplatform/ciscoxr-64u-windows2012-6432-ciscoxr-64m +43 -0
  50. data/test/fixtures/multiplatform/cumulus25-64l-windows2012-64-cumulus25-64f +43 -0
  51. data/test/fixtures/multiplatform/debian6-32c-windows2008r2-6432-debian6-32d +43 -0
  52. data/test/fixtures/multiplatform/debian6-64d-windows2008r2-64-debian6-64c +43 -0
  53. data/test/fixtures/multiplatform/debian7-32f-windows2008-6432-debian7-32l +43 -0
  54. data/test/fixtures/multiplatform/debian7-64m-windows2008-64-debian7-64u +43 -0
  55. data/test/fixtures/multiplatform/debian8-32aulcdfm-windows2003r2-6432-debian8-32a +47 -0
  56. data/test/fixtures/multiplatform/debian8-64a-windows2003r2-64-debian8-64aulcdfm +47 -0
  57. data/test/fixtures/multiplatform/debian9-32u-windows2003r2-32-debian9-32m +43 -0
  58. data/test/fixtures/multiplatform/debian9-64l-windows2003-6432-debian9-64f +43 -0
  59. data/test/fixtures/multiplatform/fedora14-32l-solaris11-64-fedora14-32f +42 -0
  60. data/test/fixtures/multiplatform/fedora19-32c-solaris11-32-fedora19-32d +42 -0
  61. data/test/fixtures/multiplatform/fedora19-64d-solaris10-64-fedora19-64c +42 -0
  62. data/test/fixtures/multiplatform/fedora20-32f-solaris10-32-fedora20-32l +42 -0
  63. data/test/fixtures/multiplatform/fedora20-64m-sles12-64-fedora20-64u +42 -0
  64. data/test/fixtures/multiplatform/fedora21-32aulcdfm-sles11-64-fedora21-32a +46 -0
  65. data/test/fixtures/multiplatform/fedora21-64a-sles11-32-fedora21-64aulcdfm +46 -0
  66. data/test/fixtures/multiplatform/fedora22-32u-sles10-64-fedora22-32m +42 -0
  67. data/test/fixtures/multiplatform/fedora22-64l-sles10-32-fedora22-64f +42 -0
  68. data/test/fixtures/multiplatform/fedora23-32c-scientific7-64-fedora23-32d +42 -0
  69. data/test/fixtures/multiplatform/fedora23-64d-scientific6-64-fedora23-64c +42 -0
  70. data/test/fixtures/multiplatform/opensuse11-32f-scientific6-32-opensuse11-32l +42 -0
  71. data/test/fixtures/multiplatform/opensuse11-64m-scientific5-64-opensuse11-64u +42 -0
  72. data/test/fixtures/multiplatform/oracle5-32c-windows2003-64-oracle5-32d +43 -0
  73. data/test/fixtures/multiplatform/oracle5-64d-ubuntu1604-64-oracle5-64c +42 -0
  74. data/test/fixtures/multiplatform/oracle6-32f-ubuntu1604-32-oracle6-32l +42 -0
  75. data/test/fixtures/multiplatform/oracle6-64m-ubuntu1510-64-oracle6-64u +42 -0
  76. data/test/fixtures/multiplatform/oracle7-64aulcdfm-ubuntu1510-32-oracle7-64a +46 -0
  77. data/test/fixtures/multiplatform/osx1010-64u-ubuntu1504-32-osx1010-64m +42 -0
  78. data/test/fixtures/multiplatform/osx1011-64l-ubuntu1404-64-osx1011-64f +42 -0
  79. data/test/fixtures/multiplatform/osx109-64a-ubuntu1504-64-osx109-64aulcdfm +46 -0
  80. data/test/fixtures/multiplatform/redhat4-32c-ubuntu1404-32-redhat4-32d +42 -0
  81. data/test/fixtures/multiplatform/redhat4-64d-ubuntu1204-64-redhat4-64c +42 -0
  82. data/test/fixtures/multiplatform/redhat5-32f-ubuntu1204-32-redhat5-32l +42 -0
  83. data/test/fixtures/multiplatform/redhat5-64m-ubuntu1004-64-redhat5-64u +42 -0
  84. data/test/fixtures/multiplatform/redhat6-32aulcdfm-ubuntu1004-32-redhat6-32a +46 -0
  85. data/test/fixtures/multiplatform/redhat6-64a-solaris112-64-redhat6-64aulcdfm +46 -0
  86. data/test/fixtures/multiplatform/redhat7-64u-solaris112-32-redhat7-64m +42 -0
  87. data/test/fixtures/multiplatform/scientific5-32aulcdfm-scientific5-32-scientific5-32a +46 -0
  88. data/test/fixtures/multiplatform/scientific5-64a-opensuse11-64-scientific5-64aulcdfm +46 -0
  89. data/test/fixtures/multiplatform/scientific6-32u-opensuse11-32-scientific6-32m +42 -0
  90. data/test/fixtures/multiplatform/scientific6-64l-fedora23-64-scientific6-64f +42 -0
  91. data/test/fixtures/multiplatform/scientific7-64c-fedora23-32-scientific7-64d +42 -0
  92. data/test/fixtures/multiplatform/sles10-32d-fedora22-64-sles10-32c +42 -0
  93. data/test/fixtures/multiplatform/sles10-64f-fedora22-32-sles10-64l +42 -0
  94. data/test/fixtures/multiplatform/sles11-32m-fedora21-64-sles11-32u +42 -0
  95. data/test/fixtures/multiplatform/sles11-64aulcdfm-fedora21-32-sles11-64a +46 -0
  96. data/test/fixtures/multiplatform/sles12-64a-fedora20-64-sles12-64aulcdfm +46 -0
  97. data/test/fixtures/multiplatform/solaris10-32u-fedora20-32-solaris10-32m +42 -0
  98. data/test/fixtures/multiplatform/solaris10-64l-fedora19-64-solaris10-64f +42 -0
  99. data/test/fixtures/multiplatform/solaris11-32c-fedora19-32-solaris11-32d +42 -0
  100. data/test/fixtures/multiplatform/solaris11-64d-fedora14-32-solaris11-64c +42 -0
  101. data/test/fixtures/multiplatform/solaris112-32f-redhat7-64-solaris112-32l +42 -0
  102. data/test/fixtures/multiplatform/solaris112-64m-redhat6-64-solaris112-64u +42 -0
  103. data/test/fixtures/multiplatform/ubuntu1004-32aulcdfm-redhat6-32-ubuntu1004-32a +46 -0
  104. data/test/fixtures/multiplatform/ubuntu1004-64a-redhat5-64-ubuntu1004-64aulcdfm +46 -0
  105. data/test/fixtures/multiplatform/ubuntu1204-32u-redhat5-32-ubuntu1204-32m +42 -0
  106. data/test/fixtures/multiplatform/ubuntu1204-64l-redhat4-64-ubuntu1204-64f +42 -0
  107. data/test/fixtures/multiplatform/ubuntu1404-32c-redhat4-32-ubuntu1404-32d +42 -0
  108. data/test/fixtures/multiplatform/ubuntu1404-64d-osx1011-64-ubuntu1404-64c +42 -0
  109. data/test/fixtures/multiplatform/ubuntu1504-32f-osx1010-64-ubuntu1504-32l +42 -0
  110. data/test/fixtures/multiplatform/ubuntu1504-64m-osx109-64-ubuntu1504-64u +42 -0
  111. data/test/fixtures/multiplatform/ubuntu1510-32aulcdfm-oracle7-64-ubuntu1510-32a +46 -0
  112. data/test/fixtures/multiplatform/ubuntu1510-64a-oracle6-64-ubuntu1510-64aulcdfm +46 -0
  113. data/test/fixtures/multiplatform/ubuntu1604-32u-oracle6-32-ubuntu1604-32m +42 -0
  114. data/test/fixtures/multiplatform/ubuntu1604-64l-oracle5-64-ubuntu1604-64f +42 -0
  115. data/test/fixtures/multiplatform/windows10ent-32d-centos4-64-windows10ent-32c +44 -0
  116. data/test/fixtures/multiplatform/windows10ent-64f-centos4-32-windows10ent-64l +44 -0
  117. data/test/fixtures/multiplatform/windows10pro-64m-arista4-32-windows10pro-64u +44 -0
  118. data/test/fixtures/multiplatform/windows2003-6432d-debian9-64-windows2003-6432c +44 -0
  119. data/test/fixtures/multiplatform/windows2003-64c-oracle5-32-windows2003-64d +44 -0
  120. data/test/fixtures/multiplatform/windows2003r2-32f-debian9-32-windows2003r2-32l +44 -0
  121. data/test/fixtures/multiplatform/windows2003r2-6432aulcdfm-debian8-32-windows2003r2-6432a +48 -0
  122. data/test/fixtures/multiplatform/windows2003r2-64m-debian8-64-windows2003r2-64u +44 -0
  123. data/test/fixtures/multiplatform/windows2008-6432u-debian7-32-windows2008-6432m +44 -0
  124. data/test/fixtures/multiplatform/windows2008-64a-debian7-64-windows2008-64aulcdfm +48 -0
  125. data/test/fixtures/multiplatform/windows2008r2-6432c-debian6-32-windows2008r2-6432d +44 -0
  126. data/test/fixtures/multiplatform/windows2008r2-64l-debian6-64-windows2008r2-64f +44 -0
  127. data/test/fixtures/multiplatform/windows2012-6432f-ciscoxr-64-windows2012-6432l +44 -0
  128. data/test/fixtures/multiplatform/windows2012-64d-cumulus25-64-windows2012-64c +44 -0
  129. data/test/fixtures/multiplatform/windows2012r2-6432aulcdfm-centos7-64-windows2012r2-6432a +48 -0
  130. data/test/fixtures/multiplatform/windows2012r2-64m-cisconx-64-windows2012r2-64u +47 -0
  131. data/test/fixtures/multiplatform/windows7-64a-centos6-64-windows7-64aulcdfm +48 -0
  132. data/test/fixtures/multiplatform/windows8-64u-centos6-32-windows8-64m +44 -0
  133. data/test/fixtures/multiplatform/windows81-64l-centos5-64-windows81-64f +44 -0
  134. data/test/fixtures/multiplatform/windowsvista-64c-centos5-32-windowsvista-64d +44 -0
  135. data/test/fixtures/osinfo-version-0/cisconx-64a +1 -1
  136. data/test/fixtures/osinfo-version-0/windows10ent-32d +22 -0
  137. data/test/fixtures/osinfo-version-0/windows10ent-64f +22 -0
  138. data/test/fixtures/osinfo-version-0/windows10pro-64m +22 -0
  139. data/test/fixtures/osinfo-version-0/windows2003-6432d +22 -0
  140. data/test/fixtures/osinfo-version-0/windows2003-64c +22 -0
  141. data/test/fixtures/osinfo-version-0/windows2003r2-32f +22 -0
  142. data/test/fixtures/osinfo-version-0/windows2003r2-6432aulcdfm +27 -0
  143. data/test/fixtures/osinfo-version-0/windows2003r2-64m +22 -0
  144. data/test/fixtures/osinfo-version-0/windows2008-6432u +22 -0
  145. data/test/fixtures/osinfo-version-0/windows2008-64a +21 -0
  146. data/test/fixtures/osinfo-version-0/windows2008r2-6432c +22 -0
  147. data/test/fixtures/osinfo-version-0/windows2008r2-64l +22 -0
  148. data/test/fixtures/osinfo-version-0/windows2012-6432f +22 -0
  149. data/test/fixtures/osinfo-version-0/windows2012-64d +22 -0
  150. data/test/fixtures/osinfo-version-0/windows2012r2-6432aulcdfm +27 -0
  151. data/test/fixtures/osinfo-version-0/windows2012r2-64m +22 -0
  152. data/test/fixtures/osinfo-version-0/windows7-64a +21 -0
  153. data/test/fixtures/osinfo-version-0/windows8-64u +22 -0
  154. data/test/fixtures/osinfo-version-0/windows81-64l +22 -0
  155. data/test/fixtures/osinfo-version-0/windowsvista-64c +22 -0
  156. data/test/fixtures/osinfo-version-1/cisconx-64a +1 -1
  157. data/test/fixtures/osinfo-version-1/windows10ent-32d +22 -0
  158. data/test/fixtures/osinfo-version-1/windows10ent-64f +22 -0
  159. data/test/fixtures/osinfo-version-1/windows10pro-64m +22 -0
  160. data/test/fixtures/osinfo-version-1/windows2003-6432d +22 -0
  161. data/test/fixtures/osinfo-version-1/windows2003-64c +22 -0
  162. data/test/fixtures/osinfo-version-1/windows2003r2-32f +22 -0
  163. data/test/fixtures/osinfo-version-1/windows2003r2-6432aulcdfm +27 -0
  164. data/test/fixtures/osinfo-version-1/windows2003r2-64m +22 -0
  165. data/test/fixtures/osinfo-version-1/windows2008-6432u +22 -0
  166. data/test/fixtures/osinfo-version-1/windows2008-64a +21 -0
  167. data/test/fixtures/osinfo-version-1/windows2008r2-6432c +22 -0
  168. data/test/fixtures/osinfo-version-1/windows2008r2-64l +22 -0
  169. data/test/fixtures/osinfo-version-1/windows2012-6432f +22 -0
  170. data/test/fixtures/osinfo-version-1/windows2012-64d +22 -0
  171. data/test/fixtures/osinfo-version-1/windows2012r2-6432aulcdfm +27 -0
  172. data/test/fixtures/osinfo-version-1/windows2012r2-64m +22 -0
  173. data/test/fixtures/osinfo-version-1/windows7-64a +21 -0
  174. data/test/fixtures/osinfo-version-1/windows8-64u +22 -0
  175. data/test/fixtures/osinfo-version-1/windows81-64l +22 -0
  176. data/test/fixtures/osinfo-version-1/windowsvista-64c +22 -0
  177. data/test/fixtures/per-host-settings/arbitrary-settings.yaml +57 -0
  178. data/test/fixtures/per-host-settings/every-hypervisor.yaml +30 -0
  179. data/test/fixtures/per-host-settings/malformed-input.yaml +5 -0
  180. data/test/test_stdout.rb +2 -2
  181. data/test/util/generator_helpers.rb +12 -4
  182. metadata +167 -6
  183. data/lib/beaker-hostgenerator/data/vmpooler.rb +0 -467
  184. data/lib/beaker-hostgenerator/generator/vmpooler.rb +0 -59
  185. data/test/test_util.rb +0 -26
@@ -1,43 +1,35 @@
1
- require 'beaker-hostgenerator/util'
2
1
  require 'beaker-hostgenerator/data'
3
- require 'beaker-hostgenerator/exceptions'
4
2
  require 'beaker-hostgenerator/roles'
3
+ require 'beaker-hostgenerator/hypervisor'
4
+ require 'beaker-hostgenerator/parser'
5
5
 
6
6
  require 'yaml'
7
7
 
8
8
  module BeakerHostGenerator
9
9
  class Generator
10
10
  include BeakerHostGenerator::Data
11
- include BeakerHostGenerator::Exceptions
12
- include BeakerHostGenerator::Utils
13
-
14
- attr_reader :options
15
-
16
- def initialize options
17
- @options = options
18
- end
19
-
20
- def self.create( options )
21
- hypervisor_type = options[:hypervisor]
22
-
23
- hclass = case hypervisor_type
24
- when /vmpooler/
25
- BeakerHostGenerator::Vmpooler
26
- when /vagrant/
27
- BeakerHostGenerator::Vagrant
28
- else
29
- raise "Invalid hypervisor #{type}"
30
- end
31
-
32
- return hclass.new(options)
33
- end
34
-
35
- def generate tokens
11
+ include BeakerHostGenerator::Parser
12
+ include BeakerHostGenerator::Roles
13
+
14
+ # Main host generation entry point, returns a YAML map as a string for the
15
+ # given host specification and optional configuration.
16
+ #
17
+ # @param layout [String] The raw hosts specification user input.
18
+ # For example `"centos6-64m-redhat7-64a"`.
19
+ # @param options [Hash] Global, optional configuration such as the default
20
+ # hypervisor or OS info version.
21
+ #
22
+ # @returns [String] A complete YAML map as a string defining the HOSTS and
23
+ # CONFIG sections as required by Beaker.
24
+ def generate(layout, options)
25
+ tokens = tokenize_layout(layout)
26
+ config = {}.deep_merge(BASE_CONFIG)
36
27
  nodeid = Hash.new(1)
37
28
  ostype = nil
29
+ bhg_version = options[:osinfo_version] || 0
38
30
 
39
31
  tokens.each do |token|
40
- if is_ostype_token?(token, @options[:osinfo_version])
32
+ if is_ostype_token?(token, bhg_version)
41
33
  if nodeid[ostype] == 1 and ostype != nil
42
34
  raise "Error: no nodes generated for #{ostype}"
43
35
  end
@@ -45,85 +37,45 @@ module BeakerHostGenerator
45
37
  next
46
38
  end
47
39
 
48
- node_info = __parse_node_info_token(token)
40
+ node_info = parse_node_info_token(token)
49
41
 
42
+ # Build node host name
43
+ platform = "#{ostype}-#{node_info['bits']}"
44
+ host_name = "#{platform}-#{nodeid[ostype]}"
45
+
46
+ node_info['platform'] = platform
50
47
  node_info['ostype'] = ostype
51
48
  node_info['nodeid'] = nodeid[ostype]
52
49
 
53
- config = {
54
- 'pe_dir' => pe_dir(pe_version, pe_family),
55
- 'pe_ver' => pe_version,
56
- 'pe_upgrade_dir' => pe_dir(pe_upgrade_version, pe_upgrade_family),
57
- 'pe_upgrade_ver' => pe_upgrade_version,
58
- }
50
+ host_config = base_host_config(options)
59
51
 
60
- [:pe_dir, :pe_ver, :pe_upgrade_dir, :pe_upgrade_ver].each do |option|
61
- if @options[option]
62
- config[option.to_s] = @options[option]
63
- end
64
- end
52
+ # Delegate to the hypervisor
53
+ hypervisor = BeakerHostGenerator::Hypervisor.create(node_info, options)
54
+ host_config = hypervisor.generate_node(node_info, host_config, bhg_version)
55
+ config['CONFIG'].deep_merge!(hypervisor.global_config())
65
56
 
66
- host_name, host_config = generate_node(
67
- node_info, config, bhg_version=@options[:osinfo_version])
57
+ # Merge in any arbitrary key-value host settings. Treat the 'hostname'
58
+ # setting specially, and don't merge it in as an arbitrary setting.
59
+ arbitrary_settings = node_info['host_settings']
60
+ host_name = arbitrary_settings.delete('hostname') if
61
+ arbitrary_settings.has_key?('hostname')
62
+ host_config.merge!(arbitrary_settings)
68
63
 
69
64
  if PE_USE_WIN32 && ostype =~ /windows/ && node_info['bits'] == "64"
70
65
  host_config['ruby_arch'] = 'x86'
71
66
  host_config['install_32'] = true
72
67
  end
73
68
 
74
- if not @options[:disable_default_role]
75
- host_config['roles'] = ['agent']
76
- else
77
- host_config['roles'] = []
78
- end
79
-
80
- host_config['roles'].concat __generate_host_roles(node_info)
81
- host_config['roles'].uniq!
69
+ generate_host_roles!(host_config, node_info, options)
82
70
 
83
- if not @options[:disable_role_config]
84
- host_config['roles'].each do |role|
85
- host_config.deep_merge! __get_role_config(role)
86
- end
87
- end
88
-
89
- @config['HOSTS'][host_name] = host_config
71
+ config['HOSTS'][host_name] = host_config
90
72
  nodeid[ostype] += 1
91
73
  end
92
74
 
93
- return @config.to_yaml
94
- end
95
-
96
- def __get_role_config role
97
- begin
98
- r = BeakerHostGenerator::Roles.new
99
- m = r.method(role)
100
- rescue NameError
101
- return {}
102
- end
103
-
104
- return m.call
105
- end
106
-
107
- def __parse_node_info_token token
108
- node_info = NODE_REGEX.match(token)
109
-
110
- if node_info
111
- node_info = Hash[ node_info.names.zip( node_info.captures ) ]
112
- else
113
- raise InvalidNodeSpecError.new, "Invalid node_info token: #{token}"
114
- end
115
-
116
- if node_info['arbitrary_roles']
117
- node_info['arbitrary_roles'] = node_info['arbitrary_roles'].split(',') || ''
118
- else
119
- # Default to empty list to avoid having to check for nil elsewhere
120
- node_info['arbitrary_roles'] = []
121
- end
122
-
123
- return node_info
75
+ return config.to_yaml
124
76
  end
125
77
 
126
- def __generate_host_roles node_info
78
+ def get_host_roles(node_info)
127
79
  roles = []
128
80
 
129
81
  node_info['roles'].each_char do |c|
@@ -137,15 +89,23 @@ module BeakerHostGenerator
137
89
  return roles
138
90
  end
139
91
 
140
- def is_ostype_token?
141
- raise "Method 'is_ostype_token?' not implemented!"
142
- end
92
+ private
143
93
 
144
- def generate_node
145
- raise "Method 'generate_node' not implemented!"
146
- end
94
+ def generate_host_roles!(host_config, node_info, options)
95
+ if not options[:disable_default_role]
96
+ host_config['roles'] = ['agent']
97
+ else
98
+ host_config['roles'] = []
99
+ end
100
+
101
+ host_config['roles'].concat get_host_roles(node_info)
102
+ host_config['roles'].uniq!
147
103
 
104
+ if not options[:disable_role_config]
105
+ host_config['roles'].each do |role|
106
+ host_config.deep_merge! get_role_config(role)
107
+ end
108
+ end
109
+ end
148
110
  end
149
111
  end
150
-
151
- require 'beaker-hostgenerator/generator/vmpooler'
@@ -0,0 +1,97 @@
1
+ module BeakerHostGenerator
2
+
3
+ # Defines an Interface for the implementation of a hypervisor, and provides
4
+ # a static module function `create(node_info, options)` for instantiating
5
+ # the appropriate hypervisor implementation.
6
+ #
7
+ # New hypervisor implementations must define the methods in the Interface
8
+ # class, and add a new element to the `supported_hypervisors` map.
9
+ #
10
+ # Any number of hypervisors are used by a single Generator during host
11
+ # generation in the `BeakerHostGenerator::Generator#generate` method.
12
+ # Whenever a host specifies a specific hypervisor implementation, the
13
+ # Generator will instantiate the appropriate hypervisor via
14
+ # `BeakerHostGenerator::Hypervisor.create`.
15
+ module Hypervisor
16
+
17
+ # Static factory method to instantiate the appropriate hypervisor for the
18
+ # given node. If no hypervisor is specified in the node info, then the
19
+ # hypervisor specified in the options will be created.
20
+ #
21
+ # @param node_info [Hash{String=>Object}] Node data parsed from the input
22
+ # spec string.
23
+ #
24
+ # @option options [String] :hypervisor The string name of the hypervisor to
25
+ # create. An exception will be thrown if the
26
+ # hypervisor is unrecognized.
27
+ def self.create(node_info, options)
28
+ name = node_info['host_settings']['hypervisor'] || options[:hypervisor]
29
+ hypervisor = supported_hypervisors[name]
30
+ if hypervisor
31
+ hypervisor.new
32
+ else
33
+ raise "Invalid hypervisor: #{name}"
34
+ end
35
+ end
36
+
37
+ # Returns a map of all valid hypervisor implementations, where the keys are
38
+ # the string names and the values are the implementation classes.
39
+ #
40
+ # The string names are part of the beaker-hostgenerator API as they are
41
+ # used for specifying the default or per-host hypervisor in the layout
42
+ # specification input string.
43
+ #
44
+ # @returns [Hash{String=>Hypervisor::Interface}] A map of hypervisor names
45
+ # and their implementations.
46
+ def self.supported_hypervisors()
47
+ {
48
+ 'none' => BeakerHostGenerator::Hypervisor::None,
49
+ 'vmpooler' => BeakerHostGenerator::Hypervisor::Vmpooler
50
+ }
51
+ end
52
+
53
+ class Interface
54
+ # Returns a map containing any general configuration required by this
55
+ # hypervisor. This map will be merged into the 'CONFIG' section of the
56
+ # final hosts configuration output.
57
+ #
58
+ # This will only be called if the hypervisor is used for a node, in which
59
+ # case the returned map will be merged in with global configuration from
60
+ # other hypervisors.
61
+ def global_config()
62
+ {}
63
+ end
64
+
65
+ # Returns a map of host configuration for a single node.
66
+ #
67
+ # This will be called for each individual node requested in the hosts
68
+ # specification input.
69
+ #
70
+ # Any configuration that is required by this hypervisor but is not
71
+ # specific to each node can be put in the `global_config` map.
72
+ #
73
+ # @param [Hash{String=>String}] node_info General info about the given
74
+ # node, such as the ostype, nodeid, and
75
+ # bits.
76
+ #
77
+ # @param [Hash{String=>Object}] base_config The node definition so far,
78
+ # which serves a starting point for this
79
+ # hypervisor to build upon. It is expected
80
+ # that this map will be merged into the map
81
+ # returned by this method.
82
+ #
83
+ # @param [Integer] bhg_version The version of OS info to use when building
84
+ # up the node definition.
85
+ def generate_node(node_info, base_config, bhg_version)
86
+ raise "Method 'generate_node' not implemented!"
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ # Require the hypervisor implementations so they can be referenced/instantiated
93
+ # in the `create` factory method. We need to put these require statements at the
94
+ # bottom of this file to avoid circular references between this file and the
95
+ # hypervisor implementation files.
96
+ require 'beaker-hostgenerator/hypervisor/vmpooler'
97
+ require 'beaker-hostgenerator/hypervisor/none'
@@ -0,0 +1,17 @@
1
+ require 'beaker-hostgenerator/hypervisor'
2
+ require 'beaker-hostgenerator/data'
3
+ require 'deep_merge'
4
+
5
+ module BeakerHostGenerator::Hypervisor
6
+ class None < BeakerHostGenerator::Hypervisor::Interface
7
+ include BeakerHostGenerator::Data
8
+
9
+ def generate_node(node_info, base_config, bhg_version)
10
+ platform = node_info['platform']
11
+ general_info = get_platform_info(bhg_version, platform, :general)
12
+ base_config.deep_merge! general_info
13
+ base_config['hypervisor'] = 'none'
14
+ return base_config
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,32 @@
1
+ require 'beaker-hostgenerator/data'
2
+ require 'beaker-hostgenerator/hypervisor'
3
+ require 'deep_merge'
4
+
5
+ module BeakerHostGenerator
6
+ module Hypervisor
7
+ class Vmpooler < BeakerHostGenerator::Hypervisor::Interface
8
+ include BeakerHostGenerator::Data
9
+
10
+ def global_config()
11
+ {
12
+ 'pooling_api' => 'http://vmpooler.delivery.puppetlabs.net/'
13
+ }
14
+ end
15
+
16
+ def generate_node(node_info, base_config, bhg_version)
17
+ # set hypervisor
18
+ base_config['hypervisor'] = 'vmpooler'
19
+
20
+ platform = node_info['platform']
21
+ platform_info = get_platform_info(bhg_version, platform, :vmpooler)
22
+ base_config.deep_merge! platform_info
23
+
24
+ # Some vmpooler/vsphere platforms have special requirements.
25
+ # We munge the node host config here if that is necessary.
26
+ fixup_node base_config
27
+
28
+ return base_config
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,199 @@
1
+ require 'beaker-hostgenerator/data'
2
+ require 'beaker-hostgenerator/exceptions'
3
+
4
+ module BeakerHostGenerator
5
+ # Functions for parsing the raw user input host layout string and turning
6
+ # them into proper data structures suitable for processing by the Generator.
7
+ #
8
+ # The functions mainly perform data type conversions, like splitting the
9
+ # single input string into a list of strings, each of which will be processed
10
+ # further by other functions in this module.
11
+ #
12
+ # For example, given the raw user input string that defines the host layout,
13
+ # you would first split it into tokens via `tokenize_layout`, and then for
14
+ # each token you would call `is_ostype_token?` and/or `parse_node_info_token`.
15
+ module Parser
16
+
17
+ # Capture role and bit width information about the node.
18
+ #
19
+ # See Ruby Regexp class for information on the capture groups used below.
20
+ # http://ruby-doc.org/core-2.2.0/Regexp.html#class-Regexp-label-Character+Classes
21
+ #
22
+ # Examples node specs and their resulting roles
23
+ #
24
+ # 64compile_master,zuul,meow.a
25
+ # * compile_master
26
+ # * zuul
27
+ # * meow
28
+ # * agent
29
+ #
30
+ # 32herp.cdma
31
+ # * herp
32
+ # * dashboard
33
+ # * database
34
+ # * master
35
+ # * agent
36
+ #
37
+ # 64dashboard,master,agent,database.
38
+ # * dashboard
39
+ # * master
40
+ # * agent
41
+ # * database
42
+ #
43
+ NODE_REGEX=/\A(?<bits>\d+)((?<arbitrary_roles>([[:lower:]_]*|\,)*)\.)?(?<roles>[uacldfm]*)(?<host_settings>\{[[:print:]]*\})?\Z/
44
+
45
+ module_function
46
+
47
+ # Breaks apart the host input string into chunks suitable for processing
48
+ # by the generator. Returns an array of substrings of the input spec string.
49
+ #
50
+ # The input string is expected to be properly formatted using the dash `-`
51
+ # character as a delimiter. Dashes may also be used within braces `{...}`,
52
+ # which are used to define arbitrary key-values on a node.
53
+ #
54
+ # @param spec [String] Well-formatted string specification of the hosts to
55
+ # generate. For example `"centos6-64m-debian8-32a"`.
56
+ # @returns [Array<String>] Input string split into substrings suitable for
57
+ # processing by the generator. For example
58
+ # `["centos6", "64m", "debian8", "32a"]`.
59
+ def tokenize_layout(layout_spec)
60
+ # Here we allow dashes in certain parts of the spec string
61
+ # i.e. "centos6-64m{hostname=foo-bar}-debian8-32"
62
+ # by first replacing all occurrences of - with | that exist within
63
+ # the braces {...}.
64
+ #
65
+ # So we'd end up with:
66
+ # "centos6-64m{hostname=foo|bar}-debian8-32"
67
+ #
68
+ # Which we can then simply split on - into:
69
+ # ["centos6", "64{hostname=foo|bar}", "debian8", "32"]
70
+ #
71
+ # And then finally turn the | back into - now that we've
72
+ # properly decomposed the spec string:
73
+ # ["centos6", "64{hostname=foo-bar}", "debian8", "32"]
74
+ #
75
+ # NOTE we've specifically chosen to use the pipe character |
76
+ # due to its unlikely occurrence in the user input string.
77
+ spec = String.new(layout_spec) # Copy so we can replace characters inline
78
+ within_braces = false
79
+ spec.chars.each_with_index do |char, index|
80
+ case char
81
+ when '{'
82
+ within_braces = true
83
+ when '}'
84
+ within_braces = false
85
+ when '-'
86
+ spec[index] = '|' if within_braces
87
+ end
88
+ end
89
+ tokens = spec.split('-')
90
+ tokens.map { |t| t.gsub('|', '-') }
91
+ end
92
+
93
+ # Tests if a string token represents an OS platform (i.e. "centos6" or
94
+ # "debian8") and not another part of the host specification like the
95
+ # architecture bit (i.e. "32" or "64").
96
+ #
97
+ # This is used when parsing the host generator input string to determine
98
+ # if we're introducing a host for a new platform or if we're adding another
99
+ # host for a current platform.
100
+ #
101
+ # @param [String] token A piece of the host generator input that might refer
102
+ # to an OS platform. For example `"centos6"` or `"debian8"`.
103
+ #
104
+ # @param [Integer] bhg_version The version of OS info to use when testing
105
+ # for whether the token represent an OS platform.
106
+ def is_ostype_token?(token, bhg_version)
107
+ BeakerHostGenerator::Data.get_platforms(bhg_version).each do |platform|
108
+ ostype = platform.split('-')[0]
109
+ if ostype == token
110
+ return true
111
+ end
112
+ end
113
+ return false
114
+ end
115
+
116
+ # Converts a string token that represents a node (and not an OS type) into
117
+ # a proper hash map with keys representing the various regex capture groups
118
+ # in `NODE_REGEX` and values being the captured text.
119
+ #
120
+ # Throws an exception if the token is not in the expected formatted, as
121
+ # determined by `NODE_REGEX.match`.
122
+ #
123
+ # It is expected that the `Generator` will have initimate knowledge about
124
+ # the keys and values in the returned map, as it may be adjusted and given
125
+ # to the hypervisors or other abstractions for processing.
126
+ #
127
+ # @param token [String] The portion of the user input layout specifiction
128
+ # that describes the node (and not the OS platform).
129
+ # For example `"64myrole.mdca"`.
130
+ #
131
+ # @returns [Hash{String=>Object}] A map containing the regex capture groups
132
+ # suitable for processing by the Generator
133
+ # and hypervisors.
134
+ def parse_node_info_token(token)
135
+ node_info = NODE_REGEX.match(token)
136
+
137
+ if node_info
138
+ node_info = Hash[ node_info.names.zip( node_info.captures ) ]
139
+ else
140
+ raise BeakerHostGenerator::Exceptions::InvalidNodeSpecError.new,
141
+ "Invalid node_info token: #{token}"
142
+ end
143
+
144
+ if node_info['arbitrary_roles']
145
+ node_info['arbitrary_roles'] =
146
+ node_info['arbitrary_roles'].split(',') || ''
147
+ else
148
+ # Default to empty list to avoid having to check for nil elsewhere
149
+ node_info['arbitrary_roles'] = []
150
+ end
151
+
152
+ if node_info['host_settings']
153
+ node_info['host_settings'] =
154
+ settings_string_to_map(node_info['host_settings'])
155
+ else
156
+ node_info['host_settings'] = {}
157
+ end
158
+
159
+ return node_info
160
+ end
161
+
162
+ # Transforms the arbitrary host settings map from a string representation
163
+ # to a proper hash map data structure for merging into the host
164
+ # configuration.
165
+ #
166
+ # The string is expected to be of the form "{key1=value1,key2=value2,...}".
167
+ # Any whitespace found in the string will be stripped and ignored.
168
+ #
169
+ # Throws an exception of the string is malformed in any way.
170
+ #
171
+ # @param host_settings [String] Non-nil user input string that defines host
172
+ # specific settings.
173
+ #
174
+ # @returns [Hash{String=>String}] The host_settings string as a map.
175
+ def settings_string_to_map(host_settings)
176
+ # Strip it down to a list of pairs
177
+ settings_pairs =
178
+ host_settings.
179
+ delete('{}').
180
+ gsub(' ', '').
181
+ split(',').
182
+ map { |keyvalue| keyvalue.split('=') }
183
+
184
+ # Validate they're actually pairs, and that all keys are non-empty
185
+ settings_pairs.each do |pair|
186
+ if pair.length != 2
187
+ raise BeakerHostGenerator::Exceptions::InvalidNodeSpecError,
188
+ "Malformed host settings: #{host_settings}"
189
+ end
190
+ if pair.first.nil? || pair.first.empty?
191
+ raise BeakerHostGenerator::Exceptions::InvalidNodeSpecError,
192
+ "Malformed host settings: #{host_settings}"
193
+ end
194
+ end
195
+
196
+ Hash[settings_pairs]
197
+ end
198
+ end
199
+ end