lib/chef/knife/openstack_server_create.rb in knife-openstack-0.10.0 vs lib/chef/knife/openstack_server_create.rb in knife-openstack-1.0.0.rc1

- old
+ new

@@ -16,502 +16,216 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # -require 'chef/knife/openstack_base' -require 'chef/knife/winrm_base' +require 'chef/knife/cloud/server/create_command' +require 'chef/knife/openstack_helpers' +require 'chef/knife/cloud/openstack_server_create_options' +require 'chef/knife/cloud/openstack_service' +require 'chef/knife/cloud/openstack_service_options' +require 'chef/knife/cloud/exceptions' class Chef class Knife - class OpenstackServerCreate < Knife - include Knife::OpenstackBase - include Chef::Knife::WinrmBase + class Cloud + class OpenstackServerCreate < ServerCreateCommand + include OpenstackHelpers + include OpenstackServerCreateOptions + include OpenstackServiceOptions - deps do - require 'fog' - require 'readline' - require 'chef/json_compat' - require 'chef/knife/bootstrap' - Chef::Knife::Bootstrap.load_deps - end - banner "knife openstack server create (options)" + banner "knife openstack server create (options)" - attr_accessor :initial_sleep_delay + def before_exec_command + super + # setup the create options + @create_options = { + :server_def => { + #servers require a name, knife-cloud generates the chef_node_name + :name => config[:chef_node_name], + :image_ref => service.get_image(locate_config_value(:image)).id, + :flavor_ref => service.get_flavor(locate_config_value(:flavor)).id, + :security_groups => locate_config_value(:openstack_security_groups), + :availability_zone => locate_config_value(:availability_zone), + :metadata => locate_config_value(:metadata), + :key_name => locate_config_value(:openstack_ssh_key_id) + }, + :server_create_timeout => locate_config_value(:server_create_timeout) + } - option :flavor, - :short => "-f FLAVOR", - :long => "--flavor FLAVOR", - :description => "The flavor name or ID of server (m1.small, m1.medium, etc)", - :proc => Proc.new { |f| Chef::Config[:knife][:flavor] = f } + @create_options[:server_def].merge!({:user_data => locate_config_value(:user_data)}) if locate_config_value(:user_data) + @create_options[:server_def].merge!({:nics => locate_config_value(:network_ids).map { |nic| nic_id = { 'net_id' => nic }}}) if locate_config_value(:network_ids) - option :image, - :short => "-I IMAGE", - :long => "--image IMAGE", - :description => "A regexp matching an image name or an image ID for the server", - :proc => Proc.new { |i| Chef::Config[:knife][:image] = i } + Chef::Log.debug("Create server params - server_def = #{@create_options[:server_def]}") + #set columns_with_info map + @columns_with_info = [ + {:label => 'Instance ID', :key => 'id'}, + {:label => 'Name', :key => 'name'}, + {:label => 'Public IP', :key => 'addresses', :value_callback => method(:primary_public_ip_address)}, + {:label => 'Private IP', :key => 'addresses', :value_callback => method(:primary_private_ip_address)}, + {:label => 'Flavor', :key => 'flavor', :value_callback => method(:get_id)}, + {:label => 'Image', :key => 'image', :value_callback => method(:get_id)}, + {:label => 'Keypair', :key => 'key_name'}, + {:label => 'State', :key => 'state'}, + {:label => 'Availability Zone', :key => 'availability_zone'} + ] + end - option :security_groups, - :short => "-G X,Y,Z", - :long => "--groups X,Y,Z", - :description => "The security groups for this server", - :default => ["default"], - :proc => Proc.new { |groups| groups.split(',') } + def get_id(value) + value['id'] + end - md = {} - option :metadata, - :short => "-M X=1", - :long => "--metadata X=1", - :description => "Metadata information for this server (may pass multiple times)", - :proc => Proc.new { |data| md.merge!({data.split('=')[0]=>data.split('=')[1]}) } + # Setup the floating ip after server creation. + def after_exec_command + Chef::Log.debug("Addresses #{server.addresses}") + msg_pair("Public IP Address", primary_public_ip_address(server.addresses)) if primary_public_ip_address(server.addresses) + msg_pair("Private IP Address", primary_private_ip_address(server.addresses)) if primary_private_ip_address(server.addresses) - option :chef_node_name, - :short => "-N NAME", - :long => "--node-name NAME", - :description => "The Chef node name for your new node" + floating_address = locate_config_value(:openstack_floating_ip) + bind_ip = primary_network_ip_address(server.addresses,server.addresses.keys[0]) + Chef::Log.debug("Floating IP Address requested #{floating_address}") + unless (floating_address == '-1') #no floating IP requested + addresses = service.connection.addresses + #floating requested without value + if floating_address.nil? + free_floating = addresses.find_index {|a| a.fixed_ip.nil?} + begin + if free_floating.nil? #no free floating IP found + error_message = "Unable to assign a Floating IP from allocated IPs." + ui.fatal(error_message) + raise CloudExceptions::ServerSetupError, error_message + else + floating_address = addresses[free_floating].ip + end + rescue CloudExceptions::ServerSetupError => e + cleanup_on_failure + raise e + end + end - option :network_ids, - :long => "--network-ids NETWORK_ID_1,NETWORK_ID_2,NETWORK_ID_3", - :description => "Comma separated list of the UUID(s) of the network(s) for the server to attach", - :proc => Proc.new { |networks| networks.split(',') } + # Pull the port_id for the associate_floating_ip + port_id = @service.network.list_ports[:body].flatten.flatten[1]["id"] + fixed_ip_address = @service.network.list_ports[:body].flatten.flatten[1]["fixed_ips"].flatten[0]["ip_address"] - option :floating_ip, - :short => "-a [IP]", - :long => "--floating-ip [IP]", - :default => "-1", - :description => "Request to associate a floating IP address to the new OpenStack node. Assumes IPs have been allocated to the project. Specific IP is optional." + floating_ip_id = get_floating_ip_id(floating_address) + # Associate the floating ip via the neutron/network api + @service.network.associate_floating_ip(floating_ip_id, port_id, options = {:fixed_ip_address => fixed_ip_address }) - option :bootstrap_network, - :long => '--bootstrap-network NAME', - :default => 'public', - :description => "Specify network for bootstrapping. Default is 'public'." + #a bit of a hack, but server.reload takes a long time + (server.addresses['public'] ||= []) << {"version"=>4,"addr"=>floating_address} + msg_pair("Floating IP Address", floating_address) + end - option :network, - :long => "--no-network", - :boolean => true, - :default => true, - :description => "Use first available network for bootstrapping if 'public' and 'private' are unavailable." + Chef::Log.debug("Addresses #{server.addresses}") + Chef::Log.debug("Public IP Address actual: #{primary_public_ip_address(server.addresses)}") if primary_public_ip_address(server.addresses) - option :private_network, - :long => "--private-network", - :description => "Use the private IP for bootstrapping rather than the public IP", - :boolean => true, - :default => false - - option :ssh_key_name, - :short => "-S KEY", - :long => "--ssh-key KEY", - :description => "The OpenStack SSH keypair id", - :proc => Proc.new { |key| Chef::Config[:knife][:openstack_ssh_key_id] = key } - - option :ssh_port, - :short => "-p PORT", - :long => "--ssh-port PORT", - :description => "The ssh port", - :default => "22", - :proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key } - - option :ssh_user, - :short => "-x USERNAME", - :long => "--ssh-user USERNAME", - :description => "The ssh username", - :default => "root" - - option :ssh_password, - :short => "-P PASSWORD", - :long => "--ssh-password PASSWORD", - :description => "The ssh password" - - option :identity_file, - :short => "-i IDENTITY_FILE", - :long => "--identity-file IDENTITY_FILE", - :description => "The SSH identity file used for authentication" - - option :prerelease, - :long => "--prerelease", - :description => "Install the pre-release chef gems" - - option :bootstrap_version, - :long => "--bootstrap-version VERSION", - :description => "The version of Chef to install", - :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v } - - option :distro, - :short => "-d DISTRO", - :long => "--distro DISTRO", - :description => "Bootstrap a distro using a template; default is 'chef-full'", - :proc => Proc.new { |d| Chef::Config[:knife][:distro] = d }, - :default => "chef-full" - - option :template_file, - :long => "--template-file TEMPLATE", - :description => "Full path to location of template to use", - :proc => Proc.new { |t| Chef::Config[:knife][:template_file] = t }, - :default => false - - option :run_list, - :short => "-r RUN_LIST", - :long => "--run-list RUN_LIST", - :description => "Comma separated list of roles/recipes to apply", - :proc => lambda { |o| o.split(/[\s,]+/) }, - :default => [] - - option :host_key_verify, - :long => "--[no-]host-key-verify", - :description => "Verify host key, enabled by default", - :boolean => true, - :default => true - - option :bootstrap_protocol, - :long => "--bootstrap-protocol protocol", - :description => "Protocol to bootstrap Windows servers. options: winrm", - :default => nil - - option :bootstrap_proxy, - :long => "--bootstrap-proxy PROXY_URL", - :description => "The proxy server for the node being bootstrapped", - :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_proxy] = v } - - option :server_create_timeout, - :long => "--server-create-timeout timeout", - :description => "How long to wait until the server is ready; default is 600 seconds", - :default => 600, - :proc => Proc.new { |v| Chef::Config[:knife][:server_create_timeouts] = v } - - option :first_boot_attributes, - :short => "-j JSON_ATTRIBS", - :long => "--json-attributes JSON_ATTRIBS", - :description => "A JSON string to be added to the first run of chef-client", - :proc => lambda { |o| JSON.parse(o) }, - :default => {} - - option :user_data, - :long => "--user-data USER_DATA", - :description => "The file path containing user data information for this server", - :proc => Proc.new { |user_data| open(user_data) { |f| f.read } } - - def tcp_test_ssh(hostname, port) - tcp_socket = TCPSocket.new(hostname, port) - readable = IO.select([tcp_socket], nil, nil, 5) - if readable - Chef::Log.debug("sshd accepting connections on #{hostname} port #{port}, banner is #{tcp_socket.gets}") - yield - true - else - false + msg_pair("Private IP Address", primary_private_ip_address(server.addresses)) if primary_private_ip_address(server.addresses) + super end - rescue Errno::ETIMEDOUT - false - rescue Errno::EPERM - false - rescue Errno::ECONNREFUSED - sleep 2 - false - rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH - sleep 2 - false - rescue Errno::ENETUNREACH - sleep 2 - false - ensure - tcp_socket && tcp_socket.close - end - def tcp_test_winrm(hostname, port) - TCPSocket.new(hostname, port) - return true - rescue SocketError - sleep 2 - false - rescue Errno::ETIMEDOUT - false - rescue Errno::EPERM - false - rescue Errno::ECONNREFUSED - sleep 2 - false - rescue Errno::EHOSTUNREACH - sleep 2 - false - rescue Errno::ENETUNREACH - sleep 2 - false - end + def before_bootstrap + super - def load_winrm_deps - require 'winrm' - require 'em-winrm' - require 'chef/knife/bootstrap_windows_winrm' - require 'chef/knife/core/windows_bootstrap_context' - require 'chef/knife/winrm' - end - def run - $stdout.sync = true + # Use SSH password either specified from command line or from openstack server instance + config[:ssh_password] = locate_config_value(:ssh_password) || server.password unless config[:openstack_ssh_key_id] - validate! - if locate_config_value(:bootstrap_protocol) == 'winrm' - load_winrm_deps - else - # workaround for KNIFE-296 winrm values stomping on ssh values - # unchanged ssh_user and changed winrm_user, override ssh_user - if locate_config_value(:ssh_user).eql?(options[:ssh_user][:default]) && - !locate_config_value(:winrm_user).eql?(options[:winrm_user][:default]) - config[:ssh_user] = locate_config_value(:winrm_user) - end - # unchanged ssh_port and changed winrm_port, override ssh_port - if locate_config_value(:ssh_port).eql?(options[:ssh_port][:default]) && - !locate_config_value(:winrm_port).eql?(options[:winrm_port][:default]) - config[:ssh_port] = locate_config_value(:winrm_port) - end - # unset ssh_password and set winrm_password, override ssh_password - if locate_config_value(:ssh_password).nil? && - !locate_config_value(:winrm_password).nil? - config[:ssh_password] = locate_config_value(:winrm_password) - end - # unset identity_file and set kerberos_keytab_file, override identity_file - if locate_config_value(:identity_file).nil? && - !locate_config_value(:kerberos_keytab_file).nil? - config[:identity_file] = locate_config_value(:kerberos_keytab_file) - end - end - # servers require a name, generate one if not passed - node_name = get_node_name(config[:chef_node_name]) + # private_network means bootstrap_network = 'private' + config[:bootstrap_network] = 'private' if config[:private_network] - # define the server to be created - server_def = { - :name => node_name, - :image_ref => image.id, - :flavor_ref => flavor.id, - :security_groups => locate_config_value(:security_groups), - :availability_zone => locate_config_value(:availability_zone), - :metadata => locate_config_value(:metadata), - :key_name => locate_config_value(:openstack_ssh_key_id) - } - server_def[:user_data] = locate_config_value(:user_data) unless locate_config_value(:user_data).nil? - unless locate_config_value(:network_ids).nil? - server_def[:nics] = locate_config_value(:network_ids).map do |nic| - nic_id = { 'net_id' => nic } - nic_id + # Which IP address to bootstrap + unless config[:network] # --no-network + bootstrap_ip_address = primary_public_ip_address(server.addresses) || + primary_private_ip_address(server.addresses) || + server.addresses.first[1][0]['addr'] + Chef::Log.debug("No Bootstrap Network: #{config[:bootstrap_network]}") + else + bootstrap_ip_address = primary_network_ip_address(server.addresses, config[:bootstrap_network]) + Chef::Log.debug("Bootstrap Network: #{config[:bootstrap_network]}") end - end - Chef::Log.debug("server_def is: #{server_def}") - Chef::Log.debug("Name #{node_name}") - Chef::Log.debug("Availability Zone #{locate_config_value(:availability_zone)}") - Chef::Log.debug("Image #{locate_config_value(:image)}") - Chef::Log.debug("Flavor #{locate_config_value(:flavor)}") - Chef::Log.debug("Requested Floating IP #{locate_config_value(:floating_ip)}") - Chef::Log.debug("Security Groups #{locate_config_value(:security_groups)}") - Chef::Log.debug("User Data #{locate_config_value(:user_data)}") - Chef::Log.debug("Metadata #{locate_config_value(:metadata)}") - Chef::Log.debug("Creating server #{server_def}") - - begin - server = connection.servers.create(server_def) - rescue Excon::Errors::BadRequest => e - response = Chef::JSONCompat.from_json(e.response.body) - if response['badRequest']['code'] == 400 - if response['badRequest']['message'] =~ /Invalid flavorRef/ - ui.fatal("Bad request (400): Invalid flavor specified: #{server_def[:flavor_ref]}") - exit 1 - else - ui.fatal("Bad request (400): #{response['badRequest']['message']}") - exit 1 - end - else - ui.fatal("Unknown server error (#{response['badRequest']['code']}): #{response['badRequest']['message']}") - raise e + Chef::Log.debug("Bootstrap IP Address: #{bootstrap_ip_address}") + if bootstrap_ip_address.nil? + error_message = "No IP address available for bootstrapping." + ui.error(error_message) + raise CloudExceptions::BootstrapError, error_message end + config[:bootstrap_ip_address] = bootstrap_ip_address end - msg_pair("Instance Name", server.name) - msg_pair("Instance ID", server.id) - msg_pair("Availability zone", server.availability_zone) + def validate_params! + # set param vm_name to a random value if the name is not set by the user (plugin) + config[:chef_node_name] = get_node_name(locate_config_value(:chef_node_name), locate_config_value(:chef_node_name_prefix)) - print "\n#{ui.color("Waiting for server", :magenta)}" + errors = [] - # wait for it to be ready to do stuff - server.wait_for(Integer(locate_config_value(:server_create_timeout))) { print "."; ready? } - - puts("\n") - - msg_pair("Flavor", server.flavor['id']) - msg_pair("Image", server.image['id']) - msg_pair("SSH Identity File", config[:identity_file]) - msg_pair("SSH Keypair", server.key_name) if server.key_name - msg_pair("SSH Password", server.password) if (server.password && !server.key_name) - - Chef::Log.debug("Addresses #{server.addresses}") - msg_pair("Public IP Address", primary_public_ip_address(server.addresses)) if primary_public_ip_address(server.addresses) - msg_pair("Private IP Address", primary_private_ip_address(server.addresses)) if primary_private_ip_address(server.addresses) - - floating_address = locate_config_value(:floating_ip) - Chef::Log.debug("Floating IP Address requested #{floating_address}") - unless (floating_address == '-1') # no floating IP requested - addresses = connection.addresses - # floating requested without value - if floating_address.nil? - free_floating = addresses.find_index { |a| a.fixed_ip.nil? } - if free_floating.nil? # no free floating IP found - ui.error("Unable to assign a Floating IP from allocated IPs.") - exit 1 - else - floating_address = addresses[free_floating].ip + if locate_config_value(:bootstrap_protocol) == 'winrm' + if locate_config_value(:winrm_password).nil? + errors << "You must provide Winrm Password." end + elsif locate_config_value(:bootstrap_protocol) != 'ssh' + errors << "You must provide a valid bootstrap protocol. options [ssh/winrm]. For linux type images, options [ssh]" end - server.associate_address(floating_address) - # bit of a hack, but server.reload takes a long time - (server.addresses['public'] ||= []) << { "version" => 4, "addr" => floating_address } - msg_pair("Floating IP Address", floating_address) - end - Chef::Log.debug("Addresses #{server.addresses}") - Chef::Log.debug("Public IP Address actual: #{primary_public_ip_address(server.addresses)}") if primary_public_ip_address(server.addresses) - - # private_network means bootstrap_network = 'private' - config[:bootstrap_network] = 'private' if config[:private_network] - - unless config[:network] # --no-network - bootstrap_ip_address = primary_public_ip_address(server.addresses) || - primary_private_ip_address(server.addresses) || - server.addresses[1][0]['addr'] - Chef::Log.debug("No Bootstrap Network: #{config[:bootstrap_network]}") - else - bootstrap_ip_address = primary_network_ip_address(server.addresses, config[:bootstrap_network]) - Chef::Log.debug("Bootstrap Network: #{config[:bootstrap_network]}") + errors << "You must provide --image-os-type option [windows/linux]" if ! (%w(windows linux).include?(locate_config_value(:image_os_type))) + error_message = "" + raise CloudExceptions::ValidationError, error_message if errors.each{|e| ui.error(e); error_message = "#{error_message} #{e}."}.any? end - Chef::Log.debug("Bootstrap IP Address: #{bootstrap_ip_address}") - if bootstrap_ip_address.nil? - ui.error("No IP address available for bootstrapping.") - exit 1 + def is_image_valid? + service.get_image(locate_config_value(:image)).nil? ? false : true end - if locate_config_value(:bootstrap_protocol) == 'winrm' - print "\n#{ui.color("Waiting for winrm", :magenta)}" - print(".") until tcp_test_winrm(bootstrap_ip_address, locate_config_value(:winrm_port)) - bootstrap_for_windows_node(server, bootstrap_ip_address).run - else - Chef::Log.debug("Waiting for sshd on IP address: #{bootstrap_ip_address} and port: #{locate_config_value(:ssh_port)}") - print "\n#{ui.color("Waiting for sshd", :magenta)}" - print(".") until tcp_test_ssh(bootstrap_ip_address, locate_config_value(:ssh_port)) { - sleep @initial_sleep_delay ||= 10 - puts("done") - } - bootstrap_for_node(server, bootstrap_ip_address).run + def is_flavor_valid? + service.get_flavor(locate_config_value(:flavor)).nil? ? false : true end - puts "\n" - msg_pair("Instance Name", server.name) - msg_pair("Instance ID", server.id) - msg_pair("Flavor", server.flavor['id']) - msg_pair("Image", server.image['id']) - msg_pair("SSH Keypair", server.key_name) if server.key_name - msg_pair("SSH Password", server.password) if (server.password && !server.key_name) - server.addresses.each do |name,addr| - msg_pair("Network", name) - msg_pair(" IP Address", addr[0]['addr']) - end - msg_pair("Environment", config[:environment] || '_default') - msg_pair("Run List", config[:run_list].join(', ')) - end - def bootstrap_for_windows_node(server, bootstrap_ip_address) - bootstrap = Chef::Knife::BootstrapWindowsWinrm.new - bootstrap.name_args = [bootstrap_ip_address] - bootstrap.config[:winrm_user] = locate_config_value(:winrm_user) || 'Administrator' - bootstrap.config[:winrm_password] = locate_config_value(:winrm_password) - bootstrap.config[:winrm_transport] = locate_config_value(:winrm_transport) - bootstrap.config[:winrm_port] = locate_config_value(:winrm_port) - bootstrap_common_params(bootstrap, server.name) - end + def is_floating_ip_valid? + address = locate_config_value(:openstack_floating_ip) - def bootstrap_common_params(bootstrap, server_name) - bootstrap.config[:chef_node_name] = config[:chef_node_name] || server_name - bootstrap.config[:run_list] = config[:run_list] - bootstrap.config[:first_boot_attributes] = config[:first_boot_attributes] - bootstrap.config[:prerelease] = config[:prerelease] - bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version) - bootstrap.config[:distro] = locate_config_value(:distro) - bootstrap.config[:template_file] = locate_config_value(:template_file) - bootstrap.config[:bootstrap_proxy] = locate_config_value(:bootstrap_proxy) - bootstrap.config[:environment] = config[:environment] - bootstrap.config[:encrypted_data_bag_secret] = config[:encrypted_data_bag_secret] - bootstrap.config[:encrypted_data_bag_secret_file] = config[:encrypted_data_bag_secret_file] - # let ohai know we're using OpenStack - Chef::Config[:knife][:hints] ||= {} - Chef::Config[:knife][:hints]['openstack'] ||= {} - bootstrap - end - - def bootstrap_for_node(server, bootstrap_ip_address) - bootstrap = Chef::Knife::Bootstrap.new - bootstrap.name_args = [bootstrap_ip_address] - bootstrap.config[:ssh_user] = config[:ssh_user] - bootstrap.config[:ssh_password] = config[:ssh_password] || server.password unless config[:ssh_key_name] - bootstrap.config[:ssh_port] = config[:ssh_port] - bootstrap.config[:identity_file] = config[:identity_file] - bootstrap.config[:host_key_verify] = config[:host_key_verify] - bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root' - bootstrap_common_params(bootstrap, server.name) - end - - def flavor - @flavor ||= connection.flavors.find{|f| f.name == locate_config_value(:flavor) || f.id == locate_config_value(:flavor) } - end - - def image - @image ||= connection.images.find{|img| img.name =~ /#{locate_config_value(:image)}/ || img.id == locate_config_value(:image) } - end - - def is_floating_ip_valid - address = locate_config_value(:floating_ip) - if address == '-1' # no floating IP requested - return true - end - addresses = connection.addresses - return false if addresses.empty? # no floating IPs - # floating requested without value - if address.nil? - if addresses.find_index { |a| a.fixed_ip.nil? } + if address == '-1' # no floating IP requested return true - else - return false # no floating IPs available end - else - # floating requested with value - if addresses.find_index { |a| a.ip == address } - return true + + addresses = service.connection.addresses + return false if addresses.empty? # no floating IPs + # floating requested without value + if address.nil? + if addresses.find_index { |a| a.fixed_ip.nil? } + return true + else + return false # no floating IPs available + end else - return false # requested floating IP does not exist + # floating requested with value + if addresses.find_index { |a| a.ip == address } + return true + else + return false # requested floating IP does not exist + end end end - end - def validate! - super([:image, :openstack_username, :openstack_password, :openstack_auth_url]) - - if flavor.nil? - ui.error("You have not provided a valid flavor ID. Please note the options for this value are -f or --flavor.") - exit 1 + def post_connection_validations + errors = [] + errors << "You have not provided a valid image ID. Please note the options for this value are -I or --image." if !is_image_valid? + errors << "You have not provided a valid flavor ID. Please note the options for this value are -f or --flavor." if !is_flavor_valid? + errors << "You have either requested an invalid floating IP address or none are available." if !is_floating_ip_valid? + error_message = "" + raise CloudExceptions::ValidationError, error_message if errors.each{|e| ui.error(e); error_message = "#{error_message} #{e}."}.any? end - if image.nil? - ui.error("You have not provided a valid image ID. Please note the options for this value are -I or --image.") - exit 1 + def get_floating_ip_id(floating_address) + # required for this method to work + floating_ip_id = -1 + # Figure out the id for the port that the floating ip you requested + @service.network.list_floating_ips[:body]["floatingips"].each do |x| + if x["floating_ip_address"] == floating_address + floating_ip_id = x["id"] + end + end + return floating_ip_id end - - if !is_floating_ip_valid - ui.error("You have either requested an invalid floating IP address or none are available.") - exit 1 - end - end - - # generate a random name if chef_node_name is empty - def get_node_name(chef_node_name) - return chef_node_name unless chef_node_name.nil? - # lazy uuids - chef_node_name = "os-" + rand.to_s.split('.')[1] end end end end