zygote 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e95ff9db7b9ed9bf04815b47d7fbc3dd8e96ea1
4
- data.tar.gz: 154a5dfd45af2c06da4b6e479483ee9520fb8d1e
3
+ metadata.gz: 6453638ec4693e43b0a13c53933f4f8e2f7e2273
4
+ data.tar.gz: 998e036ab3605422f0d3efd18b36e722f06c5ba9
5
5
  SHA512:
6
- metadata.gz: d537064fa1d974cae1d02f5a535d32b6da73a8963b1282ff295291226f85df3f8df53f6b2585d75832df5a147ad07483150f4831895bc04b43cd66fb2e01efc3
7
- data.tar.gz: 1b81bad1b0c4e4f96f45a708dbe8e73eef2f59ff42ede695de88d1ad525694fba2d53b6a2c823205e44319fe98933d712ef12ef2b86242ebd7d8c14ad2bcbbbc
6
+ metadata.gz: cca8f9c8f57e42fceb778d7f5e1ee79f64255c28ad92c32ea2e0a33fc657ba0e57d7ad769ae17c4fb3f68952a028285044bb2b0a964e6369d84ce36e111834bd
7
+ data.tar.gz: 56d20bf591b3dd195762c9a4e3151e8e8837b924703c94a95cf879c21b584c3b7744a765e8c8afc931ed7b74bc90b5a29391002d71169fad64b2acfe1524afd2
data/lib/zygote.rb ADDED
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
2
+
3
+ require 'zygote/version'
4
+ require 'zygote/http'
@@ -1,4 +1,4 @@
1
- require 'memory'
1
+ require 'zygote/memory'
2
2
 
3
3
  # An entry into the queue
4
4
  class CellQueueEntry < SuperModel::Base
@@ -42,4 +42,8 @@ module CellQueue
42
42
  entry.data = [] if entry
43
43
  entry.save if entry
44
44
  end
45
+
46
+ def all()
47
+ CellQueueEntry.all
48
+ end
45
49
  end
@@ -4,14 +4,12 @@ require 'genesisreactor'
4
4
  require 'genesis/protocol/http'
5
5
  require 'active_support/all'
6
6
 
7
- require 'util'
8
- require 'cell_queue'
9
- require 'chef'
7
+ require 'zygote/util'
8
+ require 'zygote/cell_queue'
10
9
 
11
10
  # Main HTTP class, handles routing methods
12
11
  # Uses sinatra format (all sinatra docs on routing methods apply)
13
12
  class ZygoteWeb < Genesis::Http::Handler
14
- CELL_CONFIG = YAML.load(File.read(File.expand_path('../../config/cells.yml', __FILE__))).freeze
15
13
 
16
14
  # Requested by iPXE on boot, chains into /boot.
17
15
  # This enables us to customize what details we want iPXE to send us
@@ -35,35 +33,56 @@ class ZygoteWeb < Genesis::Http::Handler
35
33
  queued_data = CellQueue.shift(sku)
36
34
  cleaned.merge!(queued_data) if queued_data
37
35
  @channel << cleaned
38
- body { erb :menu, locals: { opts: CELL_CONFIG.merge('params' => cleaned || {}) } }
36
+ body { erb :menu, locals: { opts: ZygoteWeb::cell_config.merge('params' => cleaned || {}) } }
39
37
  end
40
38
 
41
39
  # Render an action for a particular cell
42
- get %r{/cell/(?<cell>\S*)/(?<action>\S*)} do
40
+ get %r{/cell/(?<cell>\S*)/(?<action>\S*)$} do
43
41
  # Clean params into a simple hash
44
42
  cleaned = clean_params(params.to_h)
45
43
  # Add the cell to the parameters
46
44
  cell = cleaned['cell']
47
45
  # Merge the cleaned params in with any cell options
48
- cell_opts = CELL_CONFIG['index']['cells'][cell] || {}
46
+ cell_opts = ZygoteWeb::cell_config['index']['cells'][cell] || {}
49
47
  opts = cell_opts.merge('params' => cleaned || {})
50
48
  @channel << opts # for debugging
51
49
  body { erb :"#{cell}/#{cleaned['action']}".to_sym, locals: { opts: opts } }
52
50
  end
53
51
 
54
52
  # Show the queue for a SKU
55
- get %r{/queue/(?<sku>\S*)} do
53
+ get %r{/queue/(?<sku>\S*)$} do
56
54
  body { JSON.pretty_generate(CellQueue.show(params['sku'])) }
57
55
  end
58
56
 
57
+ get %r{/queue} do
58
+ response = {}
59
+ CellQueue.all.each do |queue_entry|
60
+ response[queue_entry.name] = queue_entry.data
61
+ end
62
+ body { JSON.pretty_generate(response)}
63
+ end
64
+
59
65
  # Delete the queue for a SKU
60
- delete '/queue' do
66
+ delete %r{/queue$} do
61
67
  CellQueue.purge(params['sku'])
62
68
  body { JSON.pretty_generate(CellQueue.show(params['sku'])) }
63
69
  end
64
70
 
71
+ post %r{/queue/bulk$} do
72
+
73
+ bulk_queue = JSON.parse(request.body.read)
74
+ bulk_queue.each do |asset, queue|
75
+ queue = [queue] unless queue.is_a?(Array)
76
+ queue.each do |action|
77
+ CellQueue.push(asset, action)
78
+ end
79
+ end
80
+
81
+ 200
82
+ end
83
+
65
84
  # Enable push cells (with optional data) to the cell queue for a SKU
66
- post %r{/queue/(?<sku>\S*)/(?<cell>\S*)} do
85
+ post %r{/queue/(?<sku>\S*)/(?<selected_cell>\S*)$} do
67
86
  # Clean params into a simple hash
68
87
  cleaned = clean_params(params.to_h)
69
88
  # Enqueue some data for this sku
@@ -75,22 +94,33 @@ class ZygoteWeb < Genesis::Http::Handler
75
94
  subscribe do |args|
76
95
  puts args if ENV['DEBUG']
77
96
  end
97
+
98
+ def ZygoteWeb::cell_config
99
+ @@cell_config
100
+ end
101
+
102
+ def ZygoteWeb::cell_config= (value)
103
+ @@cell_config = value
104
+ end
78
105
  end
79
106
 
80
- def zygote
107
+ def zygote(port: 7000, threads:1000, config_path: nil, cells: [], debug:false)
108
+ debug ||= ENV['DEBUG']
109
+
110
+ cell_config= YAML.load(File.read(config_path || File.join(Dir.pwd, 'config', 'cells.yml')))
111
+ ZygoteWeb::cell_config = cell_config
81
112
  zygote = Genesis::Reactor.new(
82
- threads: 1000,
113
+ threads: threads,
83
114
  protocols: {
84
- Genesis::Http::Protocol => 7000
115
+ Genesis::Http::Protocol => port
85
116
  },
86
117
  handlers: [ZygoteWeb],
87
- views: [File.join(Dir.pwd, 'views'), File.join(Dir.pwd, 'cells')],
88
- debug: ENV['DEBUG']
118
+ views: [File.expand_path('../../../views', __FILE__), cells ].flatten,
119
+ debug: debug
89
120
  )
121
+ if debug
122
+ $stdout.sync = true
123
+ $stderr.sync = true
124
+ end
90
125
  zygote
91
126
  end
92
-
93
- if ENV['DEBUG']
94
- $stdout.sync = true
95
- $stderr.sync = true
96
- end
File without changes
File without changes
@@ -0,0 +1,4 @@
1
+ # Namespace for our gem
2
+ module Zygote
3
+ VERSION = '0.0.1'
4
+ end
data/views/boot.erb ADDED
@@ -0,0 +1,14 @@
1
+ #!ipxe
2
+ # see http://etherboot.org/wiki/commandline for details on smbios strings
3
+ set boot-url http://${dhcp-server}/chain
4
+
5
+ set uri-params mac=${mac}
6
+ set uri-params ${uri-params}&serial=${serial}
7
+ set uri-params ${uri-params}&product=${product}
8
+ set uri-params ${uri-params}&manufacturer=${manufacturer}
9
+ set uri-params ${uri-params}&board-serial=${board-serial}
10
+ set uri-params ${uri-params}&board-product=${smbios/2.5.0}
11
+ set uri-params ${uri-params}&dhcp-server=${dhcp-server}
12
+
13
+ set boot-uri ${boot-url}?${uri-params}
14
+ chain --replace --autofree ${boot-uri} ||
data/views/menu.erb ADDED
@@ -0,0 +1,118 @@
1
+ #!ipxe
2
+
3
+ # This template is shamelessly ripped off from https://gist.github.com/robinsmidsrod/2234639
4
+ # The most notable change is that we are of course dynamically generating the menu using cells.
5
+
6
+ <% index = opts['index'] %>
7
+ <% params = opts['params'] %>
8
+ <% cells = index['cells'] %>
9
+
10
+ # Allow bypassing the menu entirely by calling a specific target cell
11
+ <% if selected_cell = params['selected_cell'] %>
12
+ goto <%= selected_cell %>
13
+ <% end %>
14
+
15
+ ###################### MAIN MENU ####################################
16
+
17
+ set menu-timeout <%= (params['menu_timout'] || index['timeout']) * 1000 %> # timeout is in milliseconds, so let's take seconds instead.
18
+ set submenu-timeout ${menu-timeout}
19
+ set menu-default exit
20
+
21
+ # This menu should be dynamically generated from cells, probably just make a metadata format
22
+
23
+ :start
24
+ menu iPXE boot menu for <%= params['sku'] || 'unknown' %> from <%= params['ip'] || 'unknown' %>
25
+ <% os_entries = cells.select{ |_,d| d['menu']['class'] == 'os'} %>
26
+ <% util_entries = cells.select{ |_,d| d['menu']['class'] == 'util'} %>
27
+ item --gap -- ------------------------- OS Installation --------------------------------
28
+ <% os_entries.each do | cell, data | %>
29
+ <% menu = data['menu'] %>
30
+ item --key <%= cell[0] %> <%= menu['submenu'] ? "submenu-#{cell}" : cell %> <%= menu['label'] %>
31
+ <% end %>
32
+ item --gap -- ------------------------- Tools and utilities ----------------------------
33
+ <% util_entries.each do | cell, data | %>
34
+ <% menu = data['menu'] %>
35
+ item --key <%= cell[0] %> <%= cell %> <%= menu['label'] %>
36
+ <% end %>
37
+ item --gap -- ------------------------- Advanced opts -------------------------------
38
+ item --key c config Configure settings
39
+ item shell Drop to iPXE shell
40
+ item reboot Reboot computer
41
+ item
42
+ item --key x exit Exit iPXE and continue BIOS boot
43
+ choose --timeout ${menu-timeout} --default ${menu-default} selected || goto cancel
44
+ set menu-timeout 0
45
+ goto ${selected}
46
+
47
+ # Generated menu entries for each cell
48
+ <% cells.each do | cell, _ | %>
49
+ <%= partial("#{cell}/menu".to_sym, :opts => opts) %>
50
+ <% end %>
51
+
52
+ # Render any submenus
53
+ <% submenus = cells.select{ |_,d| d['menu']['submenu'] } %>
54
+ <% submenus.each do |cell, data| %>
55
+
56
+ # Create the main submenu entry to render the submenu
57
+ :submenu-<%= cell %>
58
+ menu <%= data['menu']['label'] %>
59
+
60
+ # Add each entry to the submenu
61
+ <% data['menu']['submenu'].each do |entry, data| %>
62
+ item <%= cell %>-<%= entry %> <%= data['label'] %>
63
+ <% end %>
64
+
65
+ # Toss in the boilerplate footer
66
+ item
67
+ item --key 0x08 back Back to top menu...
68
+ choose --timeout ${submenu-timeout} --default ${submenu-default} selected || goto start
69
+ set submenu-timeout 0
70
+ goto ${selected}
71
+
72
+ # Now generate the boot entries for each submenu label
73
+ <% data['menu']['submenu'].each do |entry, data| %>
74
+ <% local_params = (data['params'] || {}).merge(params) %>
75
+ <% parmstr = {entry: entry}.merge(local_params).map{ |k,v| "#{k}=#{v}"}.join('&').gsub('?','').gsub(' ','') %>
76
+ :<%= cell %>-<%= entry %>
77
+ # FIXME: allow overriding the boot action here, but leave it as default
78
+ chain --replace --autofree http://${dhcp-server}/cell/<%= cell %>/boot<%= parmstr.empty? ? "" : "?#{parmstr}" %>
79
+ <% end %>
80
+ <% end %>
81
+
82
+ ##########################################
83
+
84
+ :cancel
85
+ echo You cancelled the menu, dropping you to a shell
86
+
87
+ :shell
88
+ echo Type 'exit' to get the back to the menu
89
+ shell
90
+ set menu-timeout 0
91
+ set submenu-timeout 0
92
+ goto start
93
+
94
+ :failed
95
+ echo Booting failed, dropping to shell
96
+ goto shell
97
+
98
+ :reboot
99
+ reboot
100
+
101
+ :exit
102
+ # On dell servers exit causes a PXE boot loop.
103
+ # This tells the server to boot from first drive instead
104
+ # http://ipxe.org/cmd/sanboot
105
+ # http://ipxe.org/appnote/work_around_bios_halting_on_ipxe_exit
106
+
107
+ sanboot --no-describe --drive 0x80
108
+ #exit
109
+
110
+ :config
111
+ config
112
+ goto start
113
+
114
+ :back
115
+ set submenu-timeout 0
116
+ clear submenu-default
117
+ goto start
118
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zygote
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Hamel
@@ -9,18 +9,147 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2015-11-24 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: chef-provisioner
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.8
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.8
27
+ - !ruby/object:Gem::Dependency
28
+ name: genesisreactor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.4
41
+ - !ruby/object:Gem::Dependency
42
+ name: supermodel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.6
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.6
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.10.3
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.10.3
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 3.3.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 3.3.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: em-http-request
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 1.1.2
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 1.1.2
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 10.4.2
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 10.4.2
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 0.10.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '='
123
+ - !ruby/object:Gem::Version
124
+ version: 0.10.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '='
130
+ - !ruby/object:Gem::Version
131
+ version: 3.2.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '='
137
+ - !ruby/object:Gem::Version
138
+ version: 3.2.0
13
139
  description: Automate baremetal server actions with iPXE
14
140
  email: dale.hamel@srvthe.net
15
141
  executables: []
16
142
  extensions: []
17
143
  extra_rdoc_files: []
18
144
  files:
19
- - lib/cell_queue.rb
20
- - lib/chef.rb
21
- - lib/http.rb
22
- - lib/memory.rb
23
- - lib/util.rb
145
+ - lib/zygote.rb
146
+ - lib/zygote/cell_queue.rb
147
+ - lib/zygote/http.rb
148
+ - lib/zygote/memory.rb
149
+ - lib/zygote/util.rb
150
+ - lib/zygote/version.rb
151
+ - views/boot.erb
152
+ - views/menu.erb
24
153
  homepage: http://rubygems.org/gems/zygote
25
154
  licenses:
26
155
  - MIT
data/lib/chef.rb DELETED
@@ -1,24 +0,0 @@
1
- require 'chef-provisioner'
2
-
3
- module ChefConfig
4
- extend self
5
- CLIENT_KEY_PATH = File.expand_path('../../tmp/client.pem', __FILE__).freeze
6
- SECRETS_JSON_PATH = File.expand_path('../../config/secrets.json', __FILE__).freeze
7
- CHEF_CONFIG_DATA = YAML.load(File.read(File.expand_path('../../config/chef.yml', __FILE__)))['chef'].freeze
8
-
9
- def load
10
- make_client_pem
11
- ChefProvisioner::Chef.configure(endpoint: CHEF_CONFIG_DATA['endpoint'], key_path: CLIENT_KEY_PATH, client: CHEF_CONFIG_DATA['client'])
12
- end
13
-
14
- private
15
-
16
- def make_client_pem
17
- key_data = JSON.load(File.read(SECRETS_JSON_PATH))['chef_client']
18
- FileUtils.mkdir_p(File.dirname(CLIENT_KEY_PATH))
19
- File.write(CLIENT_KEY_PATH, key_data)
20
- end
21
-
22
- end
23
-
24
- ChefConfig.load unless ENV['TESTING']