lib/rudy/metadata/disk.rb in rudy-0.8.5 vs lib/rudy/metadata/disk.rb in rudy-0.9.0

- old
+ new

@@ -1,177 +1,160 @@ -module Rudy::MetaData -class Disk < Storable - include Rudy::MetaData::ObjectBase - - - field :rtype - field :awsid - field :status - field :instid - - field :region - field :zone - field :environment - field :role - field :position - field :path - - field :device - field :size - #field :backups => Array - - # Is the associated volume formatted? One of: true, false, [empty]. - # [empty] means we don't know and it's the default. - field :raw - - field :fstype - field :mounted - - field :created - - def init(path=nil, size=1, device='/dev/sdh', position=nil) - @path, @size, @device = path, size, device - @rtype = 'disk' - @region = @@global.region - @zone = @@global.zone - @environment = @@global.environment - @role = @@global.role - @position = position || @@global.position - @mounted = false + + +module Rudy + class Disk < Storable + include Rudy::Metadata + include Gibbler::Complex - now = Time.now.utc - datetime = Backup.format_timestamp(now).split(Rudy::DELIM) - @created = now.to_i + field :rtype + field :volid + field :status + field :instid + + field :path + + field :device + field :size + field :fstype - postprocess - end - - def postprocess - @size &&= @size.to_i - @mounted = true if @mounted == "true" - end - - def to_s(with_titles=true) - update - mtd = @mounted == true ? "mounted" : @status - if @size && @device - "%s; %3sGB; %s; %s" % [liner_note, @size, @device, mtd] - else - liner_note + #field :backups => Array + + # Is the associated volume formatted? One of: true, false + field :raw + field :mounted + field :created => Time + + # If one argument is supplied: + # * +path+ is a an absolute filesystem path + # * +opts+ is a hash of disk options. + # + # If two arguments are supplied: + # * +position+ + # * +path+ is a an absolute filesystem path + # * +opts+ is a hash of disk options. + # + # Valid options are: + # * +:path+ is a an absolute filesystem path (overridden by +path+ arg) + # * +:position+ (overridden by +position+ arg) + # * +:size+ + # * +:device+ + # + def initialize(position=nil, path=nil, opts={}) + # Swap arg values if only one is supplied. + path, position = position, nil if !position.nil? && path.nil? + position ||= '01' + + opts = { + :size => 1, + :device => '/dev/sdh' + }.merge opts + + super Rudy::Disks::RTYPE, opts # Rudy::Metadata#initialize + + @position, @path = position, path + + # Defaults: + #datetime = Backup.format_timestamp(now).split(Rudy::DELIM) + @created = Time.now.utc + @mounted = false + postprocess + end - end - - def inspect - lines = [] - lines << liner_note - field_names.each do |key| - next unless self.respond_to?(key) - val = self.send(key) - lines << sprintf(" %22s: %s", key, (val.is_a?(Array) ? val.join(', ') : val)) + + # sdb values are stored as strings. Some quick conversion. + def postprocess + @position &&= @position.to_s.rjust(2, '0') + @size &&= @size.to_i + @raw = true if @raw == "true" unless @raw.is_a?(TrueClass) + @mounted = (@mounted == "true") unless @mounted.is_a?(TrueClass) end - lines.join($/) - end - - def name - sep=File::SEPARATOR - dirs = @path.split sep if @path && !@path.empty? - dirs.shift while dirs && (dirs[0].nil? || dirs[0].empty?) - super("disk", @zone, @environment, @role, @position, *dirs) - end - - def create(size=nil, zone=nil, snapshot=nil) - raise "#{name} already exists" if exists? - vol = @rvol.create(size || @size, zone || @zone, snapshot) - @awsid = vol.awsid - @raw = true - self.save - self - end - - def backup - raise "No volume to backup" unless @awsid - bup = Rudy::MetaData::Backup.new(@awsid, @path, @position) - bup.size = @size || 1 - bup.fstype = @fstype || 'ext3' - bup.create - end - - def list_backups - rback = Rudy::Backups.new - props = { - :environment => @environment, - :role => @role, - :zone => @zone, - :region => @region, - :position => @position - } - rback.list([], [], props) - end - - def attach(instid) - raise "No volume id" unless exists? - vol = @rvol.attach(@awsid, instid, @device) - end - - def detach - raise "No volume id" unless exists? - vol = @rvol.detach(@awsid) - end - - def destroy(force=false) - if @awsid && !deleting? - if !force - raise Rudy::AWS::EC2::VolumeNotAvailable, @awsid if attached? - else - detach if exists? && attached? - sleep 0.1 + + def to_s(with_titles=true) + self.name + end + + def name + sep = File::SEPARATOR + dirs = @path.split sep if @path && !@path.empty? + unless @path == File::SEPARATOR + dirs.shift while dirs && (dirs[0].nil? || dirs[0].empty?) end - raise Rudy::AWS::EC2::VolumeNotAvailable, @awsid if in_use? - @rvol.destroy(@awsid) if exists? && available? + # Calls Rudy::Metadata#name with disk specific components + super *dirs end - super() # quotes, otherwise Ruby will send this method's args - end - - def update - @awsid = nil if @awsid && @awsid.empty? - @volume = @rvol.get(@awsid) if @awsid - if @volume.is_a?(Rudy::AWS::EC2::Volume) - @status = @volume.status - @instid = @volume.instid - save - else - @awsid, @status, @instid = nil, nil, nil - @mounted = false # I don't like having to set this - # Don't save it b/c it's possible the EC2 server is just down + + def create(size=nil, zone=nil, snapshot=nil) + raise DuplicateRecord, self.name if exists? + vol = Rudy::AWS::EC2::Volumes.create(size || @size, zone || @zone, snapshot) + #vol = Rudy::AWS::EC2::Volumes.list(:available).first # debugging + @volid, @raw = vol.awsid, true + self.save :replace + self end - end - - def to_query(more=[], less=[]) - super([:path, *more], less) # Add path to the default fields - end - - def to_select(more=[], less=[]) - super([:path, *more], less) - end - - # Does this disk have enough info to be saved or used? - # The test is based on the same criteria for building - # SimpleDB queries. - def valid? - criteria = build_criteria([:path]).flatten - criteria.size == criteria.compact.size - end - - def mounted? - @mounted && @mounted == true - end - - - %w[exists? deleting? available? attached? in_use?].each do |state| - define_method(state) do - return false if @awsid.nil? || @awsid.empty? - @rvol.send(state, @awsid) rescue false # deleting?, available?, etc... + + def archive + raise Rudy::AWS::EC2::VolumeNotAvailable, @volid unless volume_attached? + back = Rudy::Backup.new @position, @path, self.descriptors + back.create + back.size, back.fstype = @size, @fstype + back.save :replace + back end + + def backups + Rudy::Backups.list self.descriptors + end + + + def destroy(force=false) + if @volid && !volume_deleting? + if !force + raise Rudy::AWS::EC2::VolumeNotAvailable, @volid if volume_attached? + else + volume_detach if volume_exists? && volume_attached? + sleep 0.1 + end + raise Rudy::AWS::EC2::VolumeNotAvailable, @volid if volume_in_use? + Rudy::AWS::EC2::Volumes.destroy(@volid) if volume_exists? && volume_available? + end + super() # quotes, otherwise Ruby will send this method's args + end + + def descriptors + super :position, :path + end + + + + def valid? + !@path.nil? && !@path.empty? + end + + + def volume_attach(instid) + raise Rudy::Error, "No volume id" unless volume_exists? + vol = Rudy::AWS::EC2::Volumes.attach(@volid, instid, @device) + end + + def volume_detach + raise Rudy::Error, "No volume id" unless volume_exists? + vol = Rudy::AWS::EC2::Volumes.detach(@volid) + end + + def raw? + @raw == true + end + + def mounted? + @mounted == true + end + + # Create volume_*? methods + %w[exists? deleting? available? attached? in_use?].each do |state| + define_method("volume_#{state}") do + return false if @volid.nil? || @volid.empty? + Rudy::AWS::EC2::Volumes.send(state, @volid) rescue false # deleting?, available?, etc... + end + end + end - -end -end +end \ No newline at end of file