lib/judo/server.rb in judo-0.4.4 vs lib/judo/server.rb in judo-0.5.0

- old
+ new

@@ -1,79 +1,64 @@ module Judo class Server - attr_accessor :id + attr_accessor :base, :id, :group_name - def initialize(base, id, group, version = nil) + def initialize(base, id, group_name, version = nil) @base = base @id = id - @group = group - @judo_domain = base.domain + @group_name = group_name end def create(name, options) raise JudoError, "group '#{group_name}' does not exists" unless group - - options[:virgin] = true if options[:virgin].nil? - - snapshots = options[:snapshots] - metadata = options[:metadata] - ip = options[:elastic_ip] ## if the ip was allocated beforehand - virgin = options[:virgin] ## should the server init? - clone = options[:clone] ## if it was cloned from a snapshot - - version = options[:version] - version ||= group.version - raise JudoError, "there is already a server named #{name}" if @base.servers.detect { |s| s.name == name and s != self} raise JudoError, "there is already a server with id #{id}" if @base.servers.detect { |s| s.id == id and s != self} + virgin = !(options[:virgin] == false) + snapshots = options[:snapshots] + metadata = options[:metadata] + ip = options[:elastic_ip] + clone = options[:clone] + instance_type = options[:instance_type] + version = options[:version] || group.version + task("Creating server #{name}") do update("name" => name, "group" => group_name, "virgin" => virgin, "elastic_ip" => ip, - "secret" => new_secret, "version" => version, - "clone" => clone, "created_at" => Time.now.to_i) + "version" => version, "clone" => clone, + "instance_type" => instance_type, + "created_at" => Time.now.to_i) set_metadata(metadata) if metadata - @base.sdb.put_attributes(@base.base_domain, "groups", group_name => id) end allocate_disk(snapshots) allocate_ip self end def set_metadata(new_metadata) - puts new_metadata.inspect - clean_metadata = new_metadata.inject({}) { |buf,(k,v)| - puts [ buf, k , v ].inspect - buf[k.to_s] = v.to_s; buf } - puts clean_metadata.inspect - keys_to_remove = clean_metadata.keys - clean_metadata.keys - @metadata = clean_metadata - update encode_metadata(clean_metadata) unless clean_metadata.empty? - keys_to_remove.each { |key| remove key } + new_metadata_json = new_metadata.to_json + if (new_metadata_json.size > 1000) + raise "metadata json too big: '#{new_metadata_json}'" + else + @metadata = new_metadata + update("metadata_json" => new_metadata_json) + end end - def encode_metadata(data) - data.inject({}) { |buf,(key,value)| buf["metadata_#{key.to_s}"] = [value].to_json; buf } - end - def metadata @metadata ||= get_metadata end def get_metadata - state.inject({}) do |buf,(key,value)| - if key =~ /^metadata_(.*)/ - buf[$1] = JSON.load(value.first) - end - buf - end + metadata_json = get("metadata_json") + JSON.load(metadata_json) if metadata_json end def group - @group_obj ||= @base.groups.detect { |g| g.name == @group } + @group ||= @base.groups.detect { |g| g.name == @group_name } end def fetch_state @base.sdb.get_attributes(@base.server_domain, id)[:attributes] end @@ -96,14 +81,10 @@ def name get "name" end - def data - get "data" - end - def instance_id get "instance_id" end def elastic_ip @@ -136,14 +117,10 @@ else "start" end end - def note - get("note") - end - def clone get("clone") end def cloned? @@ -156,14 +133,10 @@ def virgin? get("virgin").to_s == "true" ## I'm going to set it to true and it will come back from the db as "true" -> could be "false" or false or nil also end - def secret - get "secret" - end - def snapshots @base.snapshots.select { |s| s.server == self } end def volumes @@ -195,19 +168,17 @@ state.delete(key) end end def delete - group.delete_server(self) if group @base.sdb.delete_attributes(@base.server_domain, id) end ######## end simple DB access ####### def instance_type - ## need instance_size to be backward compatible - needed for configs made before v 0.3.0 - get("instance_type") || config["instance_type"] || config["instance_size"] || "m1.small" + get("instance_type") end def config group.config(version) end @@ -243,11 +214,10 @@ device = volume_config["device"] if volume_config["media"] == "ebs" size = volume_config["size"] if not volumes[device] task("Creating EC2 Volume #{device} #{size}") do - ### EC2 create_volume volume_id = @base.ec2.create_volume(nil, size, config["availability_zone"])[:aws_id] add_volume(volume_id, device) end else puts "Volume #{device} already exists." @@ -260,11 +230,10 @@ end def allocate_ip begin if config["elastic_ip"] and not elastic_ip - ### EC2 allocate_address task("Adding an elastic ip") do ip = @base.ec2.allocate_address add_ip(ip) end end @@ -311,32 +280,30 @@ remove "elastic_ip" end def destroy stop if running? - ### EC2 release_address task("Deleting Elastic Ip") { remove_ip } if has_ip? volumes.each { |dev,v| remove_volume(v,dev) } task("Destroying server #{name}") { delete } end def ec2_state - ec2_instance[:aws_state] rescue "offline" + ec2_instance[:aws_state] end def ec2_instance - ### EC2 describe_instances @base.ec2_instances.detect { |e| e[:aws_instance_id] == instance_id } or {} end def running? ## other options are "terminated" and "nil" ["pending", "running", "shutting_down", "degraded"].include?(ec2_state) end def start(options = {}) - @boot= options[:boot] + @boot = options[:boot] new_version = options[:version] set_instance_type(options[:instance_type]) if options[:instance_type] invalid "Already running" if running? invalid "No config has been commited yet, type 'judo commit'" unless group.version > 0 @@ -383,19 +350,16 @@ remove "instance_id" update "stopped_at" => Time.now.to_i end def launch_ec2 -# validate - - ## EC2 launch_instances ud = user_data debug(ud) result = @base.ec2.launch_instances(ami, :instance_type => instance_type, :availability_zone => config["availability_zone"], - :key_name => @base.key_name, + :key_name => "judo", :group_ids => security_groups, :user_data => ud).first update "instance_id" => result[:aws_instance_id], "virgin" => false, "started_at" => Time.now.to_i end @@ -470,32 +434,35 @@ break if ec2_instance[:aws_state] == "terminated" sleep 1 end end + def ssh? + begin + Timeout::timeout(2) do + TCPSocket.new(hostname, 22) + true + end + rescue SocketError, Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH + false + end + end + def wait_for_ssh invalid "not running" unless running? loop do - begin - reload - Timeout::timeout(4) do - TCPSocket.new(hostname, 22) - return - end - rescue SocketError, Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH - end + ssh? ? return : sleep(1) end end def add_ip(public_ip) update "elastic_ip" => public_ip attach_ip end def attach_ip return unless running? and elastic_ip - ### EC2 associate_address @base.ec2.associate_address(instance_id, elastic_ip) end def dns_name return nil unless elastic_ip @@ -506,18 +473,16 @@ ## /Library/Ruby/Gems/1.8/gems/aws-2.3.8/lib/awsbase/right_awsbase.rb:696:in `request_info_impl': VolumeInUse: vol-09c44760 is already attached to an instance (Aws::AwsError) def attach_volumes return unless running? volumes.each do |device,volume_id| - ### EC2 attach_volume @base.ec2.attach_volume(volume_id, instance_id, device) end end def remove_volume(volume_id, device) task("Deleting #{device} #{volume_id}") do - ### EC2 delete_volume @base.ec2.delete_volume(volume_id) remove "volumes", "#{device}:#{volume_id}" end end @@ -532,18 +497,18 @@ end def ssh_command(cmd) wait_for_ssh @base.keypair_file do |file| - system "ssh -i #{file} #{config["user"]}@#{hostname} '#{cmd}'" + system "ssh -q -i #{file} #{config["user"]}@#{hostname} '#{cmd}'" end end def connect_ssh wait_for_ssh @base.keypair_file do |file| - system "ssh -i #{file} #{config["user"]}@#{hostname}" + system "ssh -q -i #{file} #{config["user"]}@#{hostname}" end end def ec2_instance_type ec2_instance[:aws_instance_type] rescue nil @@ -566,30 +531,10 @@ def url group.s3_url(version) end - def domain - @base.domain - end - - def validate - ### EC2 create_security_group - @base.create_security_group - - ### EC2 desctibe_key_pairs - k = @base.ec2.describe_key_pairs.detect { |kp| kp[:aws_key_name] == config["key_name"] } - - if k.nil? - if config["key_name"] == "judo" - @base.create_keypair - else - raise "cannot use key_pair #{config["key_name"]} b/c it does not exist" - end - end - end - def snapshot(name) snap = @base.new_snapshot(name, id) snap.create snap end @@ -626,17 +571,9 @@ end end def <=>(s) [group.to_s, name.to_s] <=> [s.group.to_s, s.name.to_s] - end - - def new_secret - rand(2 ** 128).to_s(36) - end - - def group_name - @group end def boot @boot || {} end