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) ⇒ String
Copy a file from a container to the local system.
-
#push_file(source, 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
362 363 364 |
# File 'lib/hyperkit/client/containers.rb', line 362 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
.
756 757 758 759 760 761 |
# File 'lib/hyperkit/client/containers.rb', line 756 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.
345 346 347 348 |
# File 'lib/hyperkit/client/containers.rb', line 345 def delete_container(name, ={}) response = delete(container_path(name)). handle_async(response, [:sync]) end |
#delete_log(container, log) ⇒ Object
Delete a container’s log
991 992 993 |
# File 'lib/hyperkit/client/containers.rb', line 991 def delete_log(container, log) delete(log_path(container, log)) end |
#delete_snapshot(container, snapshot, options = {}) ⇒ Sawyer::Resource
Delete a snapshot
776 777 778 779 |
# File 'lib/hyperkit/client/containers.rb', line 776 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
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/hyperkit/client/containers.rb', line 308 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" => [:wait_for_websocket] || false, interactive: [:interactive] || false, "record-output" => [:record_output] || false }). handle_async(response, [:sync]) end |
#freeze_container(name, options = {}) ⇒ Sawyer::Resource Also known as: pause_container, suspend_container
Freeze (suspend) a running container
465 466 467 468 469 |
# File 'lib/hyperkit/client/containers.rb', line 465 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
.
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 |
# File 'lib/hyperkit/client/containers.rb', line 552 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
980 981 982 |
# File 'lib/hyperkit/client/containers.rb', line 980 def log(container, log) get(log_path(container, log)) end |
#logs(container) ⇒ Array<String>
Retrieve a list of logs for a container
967 968 969 970 |
# File 'lib/hyperkit/client/containers.rb', line 967 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.
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 670 671 672 673 |
# File 'lib/hyperkit/client/containers.rb', line 623 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) ⇒ 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.
847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 |
# File 'lib/hyperkit/client/containers.rb', line 847 def pull_file(container, source_file, dest) contents = get(file_path(container, source_file), url_encode: false) headers = last_response.headers if dest.respond_to? :write dest.write(contents) else File.open(dest, "wb") do |f| f.write(contents) end if headers["x-lxd-mode"] File.chmod(headers["x-lxd-mode"].to_i(8), dest) end end dest end |
#push_file(source, container, dest_file, options = {}) ⇒ Sawyer::Resource
Copy a file from the local system to container
944 945 946 947 948 949 950 951 952 953 954 |
# File 'lib/hyperkit/client/containers.rb', line 944 def push_file(source, container, dest_file, ={}) write_file(container, dest_file, ) do |f| if source.respond_to? :read f.write source.read else f.write File.read(source) end end end |
#read_file(container, file) ⇒ String
Read the contents of a file in a container
830 831 832 |
# File 'lib/hyperkit/client/containers.rb', line 830 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
794 795 796 797 |
# File 'lib/hyperkit/client/containers.rb', line 794 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
444 445 446 447 448 |
# File 'lib/hyperkit/client/containers.rb', line 444 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
811 812 813 814 |
# File 'lib/hyperkit/client/containers.rb', line 811 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
729 730 731 |
# File 'lib/hyperkit/client/containers.rb', line 729 def snapshot(container, snapshot) get(snapshot_path(container, snapshot)). end |
#snapshots(container) ⇒ Array<String>
List of snapshots for a container
686 687 688 689 |
# File 'lib/hyperkit/client/containers.rb', line 686 def snapshots(container) response = get snapshots_path(container) response..map { |path| path.split('/').last } end |
#start_container(name, options = {}) ⇒ Sawyer::Resource
Start a container
389 390 391 392 393 |
# File 'lib/hyperkit/client/containers.rb', line 389 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
419 420 421 422 423 |
# File 'lib/hyperkit/client/containers.rb', line 419 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
489 490 491 492 493 |
# File 'lib/hyperkit/client/containers.rb', line 489 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
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 |
# File 'lib/hyperkit/client/containers.rb', line 896 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 |