beaker-hostgenerator 0.5.0 → 0.6.0

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