Hyperkit is a flat API wrapper for LXD, the next-generation hypervisor. It is shamelessly based on the design of Octokit, the popular wrapper for the GitHub API.
Add this line to your application's Gemfile:
And then execute:
Or install it yourself as:
$ gem install hyperkit
require 'hyperkit' lxd = Hyperkit::Client.new(api_endpoint: "https://lxd.example.com", verify_ssl: false) # Create a new container and start it lxd.create_container("test-container", alias: "ubuntu/trusty/amd64") lxd.start_container("test-container") # Execute a command in a container lxd.execute_command("test-container", "bash -c 'echo hello > /tmp/test.txt'") # Create an image from a container and assign an alias to it response = lxd.create_image_from_container("test-container") lxd.create_image_alias(response..fingerprint, "ubuntu/custom") # Take a snapshot of a container (note that CRIU must be installed to snapshot # a running container) lxd.create_snapshot("test-container", "test-snapshot") # Migrate a container (or a snapshot) from one server to another # Note that CRIU must be installed on both LXD servers to migrate a running # container. lxd2 = Hyperkit::Client.new(api_endpoint: "https://lxd2.example.com") source = lxd2.init_migration("remote-container") lxd.migrate(source, "migrated-container")
Each method in the API documentation has at least one example of its usage. Please see the documentation for the following modules:
Hyperkit supports LXD 2.0.0 and above, and Ruby 2.0 and above.
To get started, you'll need to first enable the HTTPS API on your LXD server:
$ lxc config set core.https_address 127.0.0.1
To listen on all interfaces, replace
Being based on Octokit, API methods are available as module methods (consuming module-level configuration) or as client instance methods.
Hyperkit.configure do |c| c.api_endpoint = 'https://lxd.example.com:8443' c.verify_ssl = false end # Create an Ubuntu 14.04 container Hyperkit.create_container("test-container", alias: "ubuntu/trusty/amd64")
client = Octokit::Client.new(api_endpoint: 'https://lxd.example.com:8443', verify_ssl: false) # Create an Ubuntu 14.04 container client.create_container("test-container", alias: "ubuntu/trusty/amd64")
The LXD API uses client-side certificates to authenticate clients. By default, Hyperkit uses the following files:
- Private key:
To specify alternate files:
client = Hyperkit::Client.new(client_cert: '/path/to/crt/file', client_key: '/path/to/key/file')
or, to configure all new instances of Hyperkit:
Hyperkit.configure do |c| c.client_cert = '/path/to/crt/file' c.client_key = '/path/to/key/file' end
If you're running Hyperkit on your LXD host, the
lxc tool should have
already generated your certificate and private key for you, and placed them in
If you are running Hyperkit on a different host, you'll need to generate a certificate and private key. To do this, install OpenSSL and issue the following commands:
mkdir -p ~/.config/lxc openssl req -x509 -newkey rsa:2048 -keyout ~/.config/lxc/client.key.secure -out ~/.config/lxc/client.crt -days 3650 openssl rsa -in ~/.config/lxc/client.key.secure -out ~/.config/lxc/client.key
You will then need to tell LXD to trust your certificate. You can do this in two ways:
Option 1: Trusting your certificate using a trust password
If you have configured your LXD server with a trust password, you can use Hyperkit to get your certificate trusted:
require 'hyperkit' Hyperkit.api_endpoint = 'https://lxd.example.com:8443' Hyperkit.verify_ssl = false # Needed if you're using a self-signed certificate on the server Hyperkit.create_certificate(File.read("/path/to/your/client.crt"), password: "server-trust-password")
Option 2: Trusting your certificate using the
Alternatively, you can simply copy your certificate file to the LXD server and
lxc tool to trust it:
$ lxc config trust add my-new-cert.crt
Hyperkit supports the entirety of version 1.0 of the LXD
API, but does not
support any of the Websocket API calls (e.g.
A good deal of the LXD API calls are asynchronous: you issue the call, and you receive an operation ID. You must then wait on the operation to complete. Each asynchronous method is marked as such in the Hyperkit documentation.
By default, Hyperkit provides auto-synchronization. When you initiate an asynchronous operation, Hyperkit will automatically wait for the operation to complete before returning.
# By default, this will block until the container is created Hyperkit.create_container("test-container", alias: "ubuntu/trusty/amd64")
If you wish to override this functionality, there are two ways to do this.
First, you can pass
sync: false to any of the asynchronous methods:
# Initiates the operation and immediately returns an operation ID op = Hyperkit.create_container("test-container", alias: "ubuntu/trusty/amd64", sync: false) # Blocks until the operation is complete Hyperkit.wait_for_operation(op.id)
Alternatively, you can disable auto-synchronization at the module or class level:
Hyperkit.auto_sync = false # or client = Hyperkit::Client.new(auto_sync: false)
Any asynchronous calls you issue after setting
immediately return an operation ID instead of blocking. To ensure that an
operation is complete, you will need to call
Hyperkit.auto_sync = false op = Hyperkit.create_container("test-container", alias: "ubuntu/trusty/amd64") Hyperkit.wait_for_operation(op.id)
Note that, after an operation completes, LXD keeps it around for only 5
seconds, so if you wait too long to call
wait_for_operation, you'll get an
exception when you eventually do call it.
Most users will likely want to keep
auto_sync enabled for convenience.
Configuration and defaults
Hyperkit allows you to configure a new
Hyperkit::Client instance by passing
options to its constructor.
As in Octokit, you also have the option of setting configuration at the module level. If you need to create a number of client instances which will share certain options, this ability will be useful.
When you change options at the module level, only new
instances will be affected -- any existing instances that you have created
will retain their existing configuration.
Configuring module defaults
Every writable attribute in Hyperkit::Configurable can be set one at a time:
Hyperkit.api_endpoint = 'https://lxd.example.com:8443' Hyperkit.verify_ssl = false Hyperkit.client_cert = '/home/user/client.crt' Hyperkit.client_key = '/home/user/client.key'
or in batch:
Hyperkit.configure do |c| c.api_endpoint = 'https://lxd.example.com:8443' c.verify_ssl = false c.client_cert = '/home/user/client.crt' c.client_key = '/home/user/client.key' end
Using ENV variables
Default configuration values are specified in Hyperkit::Default. Many
attributes will look for a default value from the
ENV before returning
# Given $HYPERKIT_API_ENDPOINT is "https://lxd.example.com:8443" Hyperkit.api_endpoint # => "https://lxd.example.com:8443"
Supported Ruby Versions
This library aims to support and is tested against the following Ruby implementations:
- Ruby 2.0
- Ruby 2.1
- Ruby 2.2
- Ruby 2.3
- Ruby 2.4
If something doesn't work on one of these interpreters, it's a bug. This library may inadvertently work (or seem to work) on other Ruby implementations, however support will only be provided for the versions listed above.
If you would like this library to support another Ruby version, you may volunteer to be a maintainer. Being a maintainer entails making sure all tests run and pass on that implementation. When something breaks on your implementation, you will be responsible for providing patches in a timely fashion. If critical issues for a particular implementation exist at the time of a major release, support for that Ruby version may be dropped.
This library aims to adhere to Semantic Versioning 2.0.0. Violations of this scheme should be reported as bugs. Specifically, if a minor or patch version is released that breaks backward compatibility, that version should be immediately yanked and/or a new version should be immediately released that restores compatibility. Breaking changes to the public API will only be introduced with new major versions. As a result of this policy, you can (and should) specify a dependency on this gem using the Pessimistic Version Constraint with two digits of precision. For example:
spec.add_dependency 'hyperkit', '~> 1.0'
After checking out the repo, run
bin/setup to install dependencies. Then,
rake spec to run the tests. You can also run
bin/console for an
interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run
bundle exec rake install.
To release a new version, update the version number in
version.rb, and then
bundle exec rake release, which will create a git tag for the version,
push git commits and tags, and push the
.gem file to
Bug reports and pull requests are welcome on GitHub at https://github.com/jeffshantz/hyperkit. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT
License. Its design is based on Octokit,
also licensed under the MIT license. See the file
LICENSE.txt for more