class Chef::Knife::OciServerCreate
Server Create Command: Launch an instance and bootstrap it.
Constants
- DEFAULT_WAIT_FOR_SSH_MAX_SECONDS
- DEFAULT_WAIT_TO_STABILIZE_SECONDS
- SSH_PORT
Port for SSH - might want to parameterize this in the future.
- WAIT_FOR_SSH_INTERVAL_SECONDS
Public Instance Methods
bootstrap(name)
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 159 def bootstrap(name) bootstrap = Chef::Knife::Bootstrap.new bootstrap.name_args = [name] bootstrap.config[:chef_node_name] = config[:chef_node_name] bootstrap.config[:ssh_user] = config[:ssh_user] bootstrap.config[:ssh_password] = config[:ssh_password] bootstrap.config[:identity_file] = config[:identity_file] bootstrap.config[:use_sudo] = true bootstrap.config[:run_list] = config[:run_list] bootstrap.config[:yes] = true if config[:yes] bootstrap.run end
can_ssh(hostname, ssh_port)
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 214 def can_ssh(hostname, ssh_port) socket = TCPSocket.new(hostname, ssh_port) # Wait up to 5 seconds. readable = IO.select([socket], nil, nil, 5) if readable content = socket.gets # Make sure some content was actually returned. return true unless content.nil? || content.empty? else false end rescue SocketError, IOError, Errno::ETIMEDOUT, Errno::EPERM, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::ECONNRESET, Errno::ENOTCONN false ensure socket && socket.close end
end_progress_indicator()
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 300 def end_progress_indicator print ui.color("done\n", :magenta) end
get_file_content(file_name_param)
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 304 def get_file_content(file_name_param) file_name = config[file_name_param] return if file_name.nil? file_name = File.expand_path(file_name) File.open(file_name, 'r').read end
get_vnic(instance_id, compartment)
click to toggle source
Return the first VNIC found (which should be the only VNIC).
# File lib/chef/knife/oci_server_create.rb, line 257 def get_vnic(instance_id, compartment) compute_client.list_vnic_attachments(compartment, instance_id: instance_id).each do |response| response.data.each do |vnic_attachment| return network_client.get_vnic(vnic_attachment.vnic_id).data end end end
merge_metadata()
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 265 def merge_metadata metadata = config[:metadata] if metadata begin metadata = JSON.parse(metadata) rescue JSON::ParserError error_and_exit('Metadata value must be in JSON format. Example: \'{"key1":"value1", "key2":"value2"}\'') end else metadata = {} end ssh_authorized_keys = get_file_content(:ssh_authorized_keys_file) user_data = get_file_content(:user_data_file) user_data = Base64.strict_encode64(user_data) if user_data if ssh_authorized_keys error_and_exit('Cannot specify ssh-authorized-keys as part of both --ssh-authorized-keys-file and --metadata.') if metadata.key? 'ssh_authorized_keys' metadata['ssh_authorized_keys'] = ssh_authorized_keys end if user_data error_and_exit('Cannot specify CloudInit user-data as part of both --user-data-file and --metadata.') if metadata.key? 'user_data' metadata['user_data'] = user_data end metadata end
run()
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 110 def run $stdout.sync = true validate_required_params(%i[availability_domain image_id shape subnet_id identity_file ssh_authorized_keys_file], config) validate_wait_options metadata = merge_metadata error_and_exit 'SSH authorized keys must be specified.' unless metadata['ssh_authorized_keys'] request = OCI::Core::Models::LaunchInstanceDetails.new request.availability_domain = config[:availability_domain] request.compartment_id = compartment_id request.display_name = config[:display_name] request.hostname_label = config[:hostname_label] request.image_id = config[:image_id] request.metadata = metadata request.shape = config[:shape] request.subnet_id = config[:subnet_id] response = compute_client.launch_instance(request) instance = response.data ui.msg "Launched instance '#{instance.display_name}' [#{instance.id}]" instance = wait_for_instance_running(instance.id) ui.msg "Instance '#{instance.display_name}' is now running." vnic = get_vnic(instance.id, instance.compartment_id) unless wait_for_ssh(vnic.public_ip, SSH_PORT, WAIT_FOR_SSH_INTERVAL_SECONDS, config[:wait_for_ssh_max]) error_and_exit 'Timed out while waiting for SSH access.' end wait_to_stabilize config[:chef_node_name] = instance.display_name unless config[:chef_node_name] ui.msg "Bootstrapping with node name '#{config[:chef_node_name]}'." # TODO: Consider adding a use_private_ip option. bootstrap(vnic.public_ip) ui.msg "Created and bootstrapped node '#{config[:chef_node_name]}'." ui.msg "\n" add_vnic_details(vnic) add_server_details(instance, vnic.vcn_id) display_server_info(config, instance, [vnic]) end
show_progress()
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 295 def show_progress print ui.color('.', :magenta) $stdout.flush end
validate_wait_option(p, default)
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 175 def validate_wait_option(p, default) arg_name = "--#{p.to_s.tr('_', '-')}" config[p] = config[p].to_s.empty? ? default : Integer(config[p]) error_and_exit "#{arg_name} must be 0 or greater" if config[p] < 0 rescue error_and_exit "#{arg_name} must be numeric" end
validate_wait_options()
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 183 def validate_wait_options validate_wait_option(:wait_to_stabilize, DEFAULT_WAIT_TO_STABILIZE_SECONDS) validate_wait_option(:wait_for_ssh_max, DEFAULT_WAIT_FOR_SSH_MAX_SECONDS) end
wait_for_instance_running(instance_id)
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 231 def wait_for_instance_running(instance_id) print ui.color('Waiting for instance to reach running state...', :magenta) begin response = compute_client.get_instance(instance_id).wait_until(:lifecycle_state, OCI::Core::Models::Instance::LIFECYCLE_STATE_RUNNING, max_interval_seconds: 3) do |poll_response| if poll_response.data.lifecycle_state == OCI::Core::Models::Instance::LIFECYCLE_STATE_TERMINATED || poll_response.data.lifecycle_state == OCI::Core::Models::Instance::LIFECYCLE_STATE_TERMINATING throw :stop_succeed end show_progress end ensure end_progress_indicator end if response.data.lifecycle_state != OCI::Core::Models::Instance::LIFECYCLE_STATE_RUNNING error_and_exit 'Instance failed to provision.' end response.data end
wait_for_ssh(hostname, ssh_port, interval_seconds, max_time_seconds)
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 195 def wait_for_ssh(hostname, ssh_port, interval_seconds, max_time_seconds) print ui.color('Waiting for ssh access...', :magenta) end_time = Time.now + max_time_seconds begin while Time.now < end_time return true if can_ssh(hostname, ssh_port) show_progress sleep interval_seconds end ensure end_progress_indicator end false end
wait_to_stabilize()
click to toggle source
# File lib/chef/knife/oci_server_create.rb, line 188 def wait_to_stabilize # This extra sleep even after getting SSH access is necessary. It's not clear why, but without it we often get # errors about missing a password for ssh, or sometimes errors during bootstrapping. (Note that plugins for other # cloud providers have similar sleeps.) Kernel.sleep(config[:wait_to_stabilize]) end