Giter Club home page Giter Club logo

zygote-gem's Introduction

travis ci

Zygote

When any system boots, Zygote's job is to tell it what to do.

Zygote leverages ERB templates empower complex decision making where systems are otherwise limited to simple protocols.

Using iPXE, Zygote can direct servers to bootstrap, run recovery scripts, perform system burnin, or other task that might normally be manual.

For switches, Zygote may be used to render switch configurations, and relay them back via Zero Touch Provisioning.

Zygote can control any DHCP-capable device.

Usage

Cells

Cells are zygote's concept of modules and name-spacing. Cells with ERB templates are exposed as endpoints, and provide the interface to zygote.

A cell can call back to other cells during its operation, enabling zygote to proxy requests so that the client machine doesn't to authenticate.

Cells can also be used to logically group common functionality, so that cells can share logic server-side by leveraging ERB partials.

Each cell can also specify static configuration values in cells.yml. These values will be available in the render-time context of the cell.

Getting started

require 'zygote'

Zygote::Server.new(
  cells: File.expand_path('../cells', __FILE__)
).run

Where 'cells' is a path to cells containing erb templates describing how to boot your system - shown in greater detail below.

Additionally, create a configuration file at 'config/cells.yml' of the following structure:

index:
  timeout: 0 # timeout in seconds, 0 for none
  cells:
    installers:
      delegate: live
      menu: # A menu with submenu entries
        class: os
        label: "Install an operating system"
        submenu:
          ubuntu:
            label: "Install Ubuntu"
            args:
              arbitrary: data
    memtest:
      menu:
        class: util
        label: "Run Memtest86"
      args:
        kernel_params: console=ttyS1,115200n8
        passes: 5

iPXE

Zygote supports bootstrapping servers through generating iPXE scripted menus

It's probably necessary to gain a basic understanding of the iPXE scripting commands to generate meaningful scripts.

Menu generation

Zygote reads cells.yml, and generates menus and submenus. Every menu entry has a top-level iPXE symbol, and every submenu has a symbol formed by joining the top-level menu grouping with the specific menu entry.

For instance, a top-level menu item called 'memtest' would tagged in iPXE with:

:memtest

This symbol would be called (via an iPXE goto) if the memtest menu item is selected.

Likewise, a submenu called 'utility' with the entry 'rescue' would be tagged as:

:utility-rescue

Each menu and submenu can have a user-friendly description using the 'label' field. Additional arguments or parameters are allowed nested under the 'args' field. Any URI parameters are merged with this, as is any JSON encoded post data.

Each entry may invoke an action, by default the action is called 'boot', but this can be overriden with the 'action' field.

Each entry will by default correspond to rendering an erb file at:

cell/<entry>/<action>

Where this corresponds to a file on disk called:

cells/<entry>/<action>.erb

So, if you have an entry called 'memtest', and you want to use the default action of 'boot', create the file with the necessary iPXE directives to boot it at:

cells/memtest/boot.erb

If you want to use the boot logic of another cell, you can delegate to it using the 'delegate' field. So we could have memtest delegate to using another cell's named 'default' to boot it if we chose to. This can be useful if your boot logic is shared between cells.

If you want to share code within any erb file, you may use a partial. All partials are relative to the cells directory, and strings or symbols are accepted.

For instance, adding:

<%= partial('util/common', {some: 'optional', variables: 'to help render'}) %>

The template at cells/util/common.erb will be rendered in the current template.

Automation

Zygote supports automation through a simple queuing mechanism.

Enqueuing cells to a sku

Let's say we have the asset SKU-1234567, as identified by iPXE, and we want to run the cell 'ubuntu-automatic'

curl -X POST localhost:7000/queue/SKU-1234567/ubuntu-automatic

The next time the asset boots, the boot menu will be bypassed entirely and the ubuntu-automatic entry will be loaded.

Any post parameters provided will be merged into the options hash at boot time, which allows for fairly dynamic behaviour.

You may of course push multiple cells to the queue for a given asset. This allows you to chain from one cell into another - assuming they each complete and reboot successfully.

Pre-selected cells

By adding the selected_cell parameter, you may jump directly to a particular cell to execute using an iPXE goto statement. This is quite powerful, as it prevents the need for human interaction. Combined with zygote's queueing, you can chain from one action into another by rebooting after each action.

So, if we set the URI parameter selected_cell=memtest, the menu will never be displayed, and we'll jump directly to the memtest label, and execute the memtest action.

Identifiers

Before the iPXE menu is rendered, an identifier may mutate the parameters used at boot time arbitrarily. This provides a means to hook in custom code to alter the boot behavior. By subclassing Zygote::Identifier you may shadow the identify method, to mutate the params hash as shown:

module Zygote
  class MyIdentifier < Zygote::Identifier
    def identify
      @params['selected_cell'] = MyCustomRubyCode.decide_what_to_do
      @params
    end
  end
end

Define this code after requiring the zygote gem.

Queue management

You may of course perform basic queue operations:

You may view the JSON of the queue:

curl -X GET localhost:7000/queue/SKU-1234567

You may purge the queue completely:

curl -X DELETE localhost:7000/queue?sku=1234567 # FIXME: this is orthogonal, figure out why DELETE collides with GET

Debugging

Setting DEBUG=true (or to anything) will cause zygote to print the fully body of all requests and responses.

Testing

Tested automatically using travis ci.

Most tests are fixture based, as the app primarily renders templates.

To regenerate fixtures, set FIXTURE_RECORD=true before running test.

zygote-gem's People

Contributors

dalehamel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zygote-gem's Issues

uninitialized constant ActiveModel::Serializers::Xml (NameError)

Running into an error when trying to get this running. Any idea on what I'm missing?

ruby 2.3.4p301 (2017-03-30 revision 58214) [x86_64-linux-musl]
/zygote # cat test.rb
require 'zygote'

Zygote::Server.new(
  cells: File.expand_path('cells', __FILE__)
).run
/zygote # ruby test.rb
/usr/local/bundle/gems/worsemodel-0.2.0/lib/supermodel/base.rb:322:in `<class:Base>': uninitialized constant ActiveModel::Serializers::Xml (NameError)
	from /usr/local/bundle/gems/worsemodel-0.2.0/lib/supermodel/base.rb:318:in `<module:SuperModel>'
	from /usr/local/bundle/gems/worsemodel-0.2.0/lib/supermodel/base.rb:1:in `<top (required)>'
	from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
	from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
	from /usr/local/bundle/gems/zygote-0.2.15/lib/zygote/cell_queue.rb:5:in `<module:Zygote>'
	from /usr/local/bundle/gems/zygote-0.2.15/lib/zygote/cell_queue.rb:3:in `<top (required)>'
	from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
	from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
	from /usr/local/bundle/gems/zygote-0.2.15/lib/zygote/http.rb:10:in `<top (required)>'
	from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
	from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
	from /usr/local/bundle/gems/zygote-0.2.15/lib/zygote.rb:4:in `<top (required)>'
	from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:133:in `require'
	from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:133:in `rescue in require'
	from /usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:40:in `require'
	from test.rb:1:in `<main>'

Issue for tracking pain points

Tracking issue to surface some of the issues I have been having while reimagining servers.

  1. Logging. Logging is not in the expected location. Was expected in /u/apps..../zygote/current/log but was in runit logs.
  2. Logging. The logs when not in debug mode are sparse and you are unable to go back and replay what happening during a reimaging of a node. Adding some helpful log messages which would allow you to trace the history of a node through the process would be awesome.
  3. Queues + Logging. I spent some time entering the wrong sku number. It was only after turning on DEBUG=true when running zygote that I was able to eventually ( after being told and looking through logs ) identify the proper sku Format. A warning about suspected improper sky formatting would be nice.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.