Module: Hyperkit::Client::Containers
- Included in:
- Hyperkit::Client
- Defined in:
- lib/hyperkit/client/containers.rb
Overview
Methods for the containers API
Retrieval collapse
-
#container(name) ⇒ Sawyer::Resource
Get information on a container.
-
#containers ⇒ Array<String>
List of containers on the server (public or private).
Creation collapse
-
#copy_container(source_name, target_name, options = {}) ⇒ Sawyer::Resource
Create a copy of an existing local container.
-
#create_container(name, options = {}) ⇒ Sawyer::Resource
Create a container from an image (local or remote).
Editing collapse
-
#rename_container(old_name, new_name, options = {}) ⇒ Sawyer::Resource
Rename a container.
-
#update_container(name, config, options = {}) ⇒ Sawyer::Resource
Update the configuration of a container.
Commands collapse
-
#execute_command(container, command, options = {}) ⇒ Sawyer::Resource
(also: #run_command)
Execute a command in a container.
Deletion collapse
-
#delete_container(name, options = {}) ⇒ Sawyer::Resource
Delete a container.
State collapse
-
#container_state(name) ⇒ Sawyer::Resource
Retrieve the current state of a container.
-
#freeze_container(name, options = {}) ⇒ Sawyer::Resource
(also: #pause_container, #suspend_container)
Freeze (suspend) a running container.
-
#restart_container(name, options = {}) ⇒ Sawyer::Resource
Restart a running container.
-
#start_container(name, options = {}) ⇒ Sawyer::Resource
Start a container.
-
#stop_container(name, options = {}) ⇒ Sawyer::Resource
Stop a container.
-
#unfreeze_container(name, options = {}) ⇒ Sawyer::Resource
(also: #resume_container)
Unfreeze (resume) a frozen container.
Migration collapse
-
#init_migration(container, snapshot = nil) ⇒ Sawyer::Resource
Prepare to migrate a container or snapshot.
-
#migrate(source, dest_name, options = {}) ⇒ Sawyer::Resource
Migrate a remote container or snapshot to the server.
Snapshots collapse
-
#create_snapshot(container, snapshot, options = {}) ⇒ Sawyer::Resource
Create a snapshot of a container.
-
#delete_snapshot(container, snapshot, options = {}) ⇒ Sawyer::Resource
Delete a snapshot.
-
#rename_snapshot(container, old_name, new_name, options = {}) ⇒ Sawyer::Resource
Rename a snapshot.
-
#restore_snapshot(container, snapshot, options = {}) ⇒ Sawyer::Resource
(also: #revert_to_snapshot)
Restore a snapshot.
-
#snapshot(container, snapshot) ⇒ Sawyer::Resource
Get information on a snapshot.
-
#snapshots(container) ⇒ Array<String>
List of snapshots for a container.
Files collapse
-
#pull_file(container, source_file, dest_file) ⇒ String
Copy a file from a container to the local system.
-
#push_file(source_file, container, dest_file, options = {}) ⇒ Sawyer::Resource
Copy a file from the local system to container.
-
#read_file(container, file) ⇒ String
Read the contents of a file in a container.
-
#write_file(container, dest_file, options = {}) {|io| ... } ⇒ Sawyer::Resource
Write to a file in a container.
Logs collapse
-
#delete_log(container, log) ⇒ Object
Delete a container's log.
-
#log(container, log) ⇒ String
Retrieve the contents of a log for a container.
-
#logs(container) ⇒ Array<String>
Retrieve a list of logs for a container.
Instance Method Details
#container(name) ⇒ Sawyer::Resource
Get information on a container
64 65 66 |
# File 'lib/hyperkit/client/containers.rb', line 64 def container(name) get(container_path(name)). end |
#container_state(name) ⇒ Sawyer::Resource
Retrieve the current state of a container
358 359 360 |
# File 'lib/hyperkit/client/containers.rb', line 358 def container_state(name) get(container_state_path(name)). end |
#containers ⇒ Array<String>
List of containers on the server (public or private)
22 23 24 25 |
# File 'lib/hyperkit/client/containers.rb', line 22 def containers response = get(containers_path) response..map { |path| path.split('/').last } end |
#copy_container(source_name, target_name, options = {}) ⇒ Sawyer::Resource
Create a copy of an existing local container.
190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/hyperkit/client/containers.rb', line 190 def copy_container(source_name, target_name, ={}) opts = { source: { type: "copy", source: source_name } }.merge((target_name, )) response = post(containers_path, opts). handle_async(response, [:sync]) end |
#create_container(name, options = {}) ⇒ Sawyer::Resource
Create a container from an image (local or remote). The container will be
created in the Stopped
state.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/hyperkit/client/containers.rb', line 137 def create_container(name, ={}) source = container_source_attribute() opts = .except(:sync) if ! opts[:empty] && source.empty? raise Hyperkit::ImageIdentifierRequired.new("Specify source image by alias, fingerprint, or properties, or create an empty container with 'empty: true'") end if opts[:empty] opts = (name, opts) elsif [:server] opts = (name, source, opts) else opts = (name, source, opts) end response = post(containers_path, opts). handle_async(response, [:sync]) end |
#create_snapshot(container, snapshot, options = {}) ⇒ Sawyer::Resource
Create a snapshot of a container
If stateful: true
is passed when creating a snapshot of a
running container, the container's runtime state will be stored in the
snapshot. Note that CRIU must be installed on the server to create a
stateful snapshot, or LXD will return a 500 error. On Ubuntu, you can
install it with sudo apt-get install criu
.
752 753 754 755 756 757 |
# File 'lib/hyperkit/client/containers.rb', line 752 def create_snapshot(container, snapshot, ={}) opts = .slice(:stateful) opts[:name] = snapshot response = post(snapshots_path(container), opts). handle_async(response, [:sync]) end |
#delete_container(name, options = {}) ⇒ Sawyer::Resource
Delete a container. Throws an error if the container is running.
341 342 343 344 |
# File 'lib/hyperkit/client/containers.rb', line 341 def delete_container(name, ={}) response = delete(container_path(name)). handle_async(response, [:sync]) end |
#delete_log(container, log) ⇒ Object
Delete a container's log
973 974 975 |
# File 'lib/hyperkit/client/containers.rb', line 973 def delete_log(container, log) delete(log_path(container, log)) end |
#delete_snapshot(container, snapshot, options = {}) ⇒ Sawyer::Resource
Delete a snapshot
772 773 774 775 |
# File 'lib/hyperkit/client/containers.rb', line 772 def delete_snapshot(container, snapshot, ={}) response = delete(snapshot_path(container, snapshot)). handle_async(response, [:sync]) end |
#execute_command(container, command, options = {}) ⇒ Sawyer::Resource Also known as: run_command
Execute a command in a container
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'lib/hyperkit/client/containers.rb', line 305 def execute_command(container, command, ={}) opts = .slice(:environment) command = Shellwords.shellsplit(command) if command.is_a?(String) opts[:environment] = stringify_hash(opts[:environment]) if opts[:environment] response = post(File.join(container_path(container), "exec"), { command: command, environment: opts[:environment] || {}, "wait-for-websocket" => false, interactive: false }). handle_async(response, [:sync]) end |
#freeze_container(name, options = {}) ⇒ Sawyer::Resource Also known as: pause_container, suspend_container
Freeze (suspend) a running container
461 462 463 464 465 |
# File 'lib/hyperkit/client/containers.rb', line 461 def freeze_container(name, ={}) opts = .slice(:timeout) response = put(container_state_path(name), opts.merge(action: "freeze")). handle_async(response, [:sync]) end |
#init_migration(container, snapshot = nil) ⇒ Sawyer::Resource
Prepare to migrate a container or snapshot. Generates source data to be passed to #migrate.
Note that CRIU must be installed on the server to migrate a running
container, or LXD will return a 500 error. On Ubuntu, you can install it
with sudo apt-get install criu
.
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 |
# File 'lib/hyperkit/client/containers.rb', line 548 def init_migration(container, snapshot=nil) if snapshot url = snapshot_path(container, snapshot) source = snapshot(container, snapshot) else url = container_path(container) source = container(container) end response = post(url, { migration: true }) agent = response.agent source_data = { architecture: source.architecture, config: source.config.to_hash, profiles: source.profiles, websocket: { url: File.join(api_endpoint, response.operation), secrets: response...to_hash, }, certificate: get("/1.0")..environment.certificate, snapshot: ! snapshot.nil? } Sawyer::Resource.new(response.agent, source_data) end |
#log(container, log) ⇒ String
Retrieve the contents of a log for a container
962 963 964 |
# File 'lib/hyperkit/client/containers.rb', line 962 def log(container, log) get(log_path(container, log)) end |
#logs(container) ⇒ Array<String>
Retrieve a list of logs for a container
949 950 951 952 |
# File 'lib/hyperkit/client/containers.rb', line 949 def logs(container) response = get(logs_path(container)) response..map { |path| path.sub(logs_path(container) + '/', '') } end |
#migrate(source, dest_name, options = {}) ⇒ Sawyer::Resource
Migrate a remote container or snapshot to the server
Note that CRIU must be installed on the server to migrate a running
container, or LXD will return a 500 error. On Ubuntu, you can install it
with sudo apt-get install criu
.
Also note that, unless overridden with the profiles
parameter,
if the source container has profiles applied to it that do not exist on the
target LXD instance, this method will throw an exception.
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 |
# File 'lib/hyperkit/client/containers.rb', line 619 def migrate(source, dest_name, ={}) opts = { name: dest_name, architecture: [:architecture] || source.architecture, source: { type: "migration", mode: "pull", operation: source.websocket.url, certificate: [:certificate] || source.certificate, secrets: source.websocket.secrets.to_hash } } if ! source.snapshot opts["base-image"] = source.config["volatile.base_image"] opts[:config] = [:config] || source.config.to_hash # If we're only copying the container, and configuration was explicitly # overridden, then remove the volatile entries if ! [:move] && ! .has_key?(:config) opts[:config].delete_if { |k,v| k.to_s.start_with?("volatile") } end else opts[:config] = [:config] || {} end if .has_key?(:profiles) opts[:profiles] = [:profiles] else dest_profiles = profiles() if (source.profiles - dest_profiles).empty? opts[:profiles] = source.profiles else raise Hyperkit::MissingProfiles.new("Not all profiles applied to source container exist on the target LXD instance") end end if .has_key?(:ephemeral) opts[:ephemeral] = [:ephemeral] else opts[:ephemeral] = !! source.ephemeral end response = post(containers_path, opts). handle_async(response, [:sync]) end |
#pull_file(container, source_file, dest_file) ⇒ String
Copy a file from a container to the local system. The file will be written with the same permissions assigned to it in the container.
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 |
# File 'lib/hyperkit/client/containers.rb', line 840 def pull_file(container, source_file, dest_file) contents = get(file_path(container, source_file), url_encode: false) headers = last_response.headers File.open(dest_file, "wb") do |f| f.write(contents) end if headers["x-lxd-mode"] File.chmod(headers["x-lxd-mode"].to_i(8), dest_file) end dest_file end |
#push_file(source_file, container, dest_file, options = {}) ⇒ Sawyer::Resource
Copy a file from the local system to container
930 931 932 933 934 935 936 |
# File 'lib/hyperkit/client/containers.rb', line 930 def push_file(source_file, container, dest_file, ={}) write_file(container, dest_file, ) do |f| f.write File.read(source_file) end end |
#read_file(container, file) ⇒ String
Read the contents of a file in a container
826 827 828 |
# File 'lib/hyperkit/client/containers.rb', line 826 def read_file(container, file) get(file_path(container, file), url_encode: false) end |
#rename_container(old_name, new_name, options = {}) ⇒ Sawyer::Resource
Rename a container
269 270 271 272 |
# File 'lib/hyperkit/client/containers.rb', line 269 def rename_container(old_name, new_name, ={}) response = post(container_path(old_name), { name: new_name }). handle_async(response, [:sync]) end |
#rename_snapshot(container, old_name, new_name, options = {}) ⇒ Sawyer::Resource
Rename a snapshot
790 791 792 793 |
# File 'lib/hyperkit/client/containers.rb', line 790 def rename_snapshot(container, old_name, new_name, ={}) response = post(snapshot_path(container, old_name), { name: new_name }). handle_async(response, [:sync]) end |
#restart_container(name, options = {}) ⇒ Sawyer::Resource
Restart a running container
440 441 442 443 444 |
# File 'lib/hyperkit/client/containers.rb', line 440 def restart_container(name, ={}) opts = .slice(:force, :timeout) response = put(container_state_path(name), opts.merge(action: "restart")). handle_async(response, [:sync]) end |
#restore_snapshot(container, snapshot, options = {}) ⇒ Sawyer::Resource Also known as: revert_to_snapshot
Restore a snapshot
807 808 809 810 |
# File 'lib/hyperkit/client/containers.rb', line 807 def restore_snapshot(container, snapshot, ={}) response = put(container_path(container), { restore: snapshot }). handle_async(response, [:sync]) end |
#snapshot(container, snapshot) ⇒ Sawyer::Resource
Get information on a snapshot
725 726 727 |
# File 'lib/hyperkit/client/containers.rb', line 725 def snapshot(container, snapshot) get(snapshot_path(container, snapshot)). end |
#snapshots(container) ⇒ Array<String>
List of snapshots for a container
682 683 684 685 |
# File 'lib/hyperkit/client/containers.rb', line 682 def snapshots(container) response = get snapshots_path(container) response..map { |path| path.split('/').last } end |
#start_container(name, options = {}) ⇒ Sawyer::Resource
Start a container
385 386 387 388 389 |
# File 'lib/hyperkit/client/containers.rb', line 385 def start_container(name, ={}) opts = .slice(:stateful, :timeout) response = put(container_state_path(name), opts.merge(action: "start")). handle_async(response, [:sync]) end |
#stop_container(name, options = {}) ⇒ Sawyer::Resource
Stop a container
415 416 417 418 419 |
# File 'lib/hyperkit/client/containers.rb', line 415 def stop_container(name, ={}) opts = .slice(:force, :stateful, :timeout) response = put(container_state_path(name), opts.merge(action: "stop")). handle_async(response, [:sync]) end |
#unfreeze_container(name, options = {}) ⇒ Sawyer::Resource Also known as: resume_container
Unfreeze (resume) a frozen container
485 486 487 488 489 |
# File 'lib/hyperkit/client/containers.rb', line 485 def unfreeze_container(name, ={}) opts = .slice(:timeout) response = put(container_state_path(name), opts.merge(action: "unfreeze")). handle_async(response, [:sync]) end |
#update_container(name, config, options = {}) ⇒ Sawyer::Resource
Update the configuration of a container.
Configuration is overwritten, not merged. Accordingly, clients should first call container to obtain the current configuration of a container. The resulting object should be modified and then passed to update_container.
Note that LXD does not allow certain attributes to be changed (e.g.
status
, status_code
, stateful
,
name
, etc.) through this call.
248 249 250 251 252 253 254 255 |
# File 'lib/hyperkit/client/containers.rb', line 248 def update_container(name, config, ={}) config = config.to_hash config[:config] = stringify_hash(config[:config]) if config[:config] response = put(container_path(name), config). handle_async(response, [:sync]) end |
#write_file(container, dest_file, options = {}) {|io| ... } ⇒ Sawyer::Resource
Write to a file in a container
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 |
# File 'lib/hyperkit/client/containers.rb', line 885 def write_file(container, dest_file, ={}, &block) headers = { "Content-Type" => "application/octet-stream" } headers["X-LXD-uid"] = [:uid].to_s if [:uid] headers["X-LXD-gid"] = [:gid].to_s if [:gid] headers["X-LXD-mode"] = [:mode].to_s(8).rjust(4, "0") if [:mode] if ! block_given? content = [:content].to_s else io = StringIO.new yield io io.rewind content = io.read end post(file_path(container, dest_file), { raw_body: content, headers: headers }) end |