def manage_volume_device_assignment(mapping)

      # only managed volumes should be in an attached state ready for assignment.
      unless 'attached' == mapping[:management_status]
        raise VolumeManagement::UnexpectedState.new("The volume #{mapping[:volume_id]} was in an unexpected managed state: #{mapping.inspect}")
      end

      # check for changes in disks.
      last_disks = InstanceState.planned_volume_state.disks
      last_volumes = InstanceState.planned_volume_state.volumes
      vm = RightScale::Platform.volume_manager
      current_disks = vm.disks
      current_volumes = vm.volumes

      # correctly managing device assignment requires expecting precise changes
      # to disks and volumes. any deviation from this requires a retry.
      succeeded = false
      if new_disk = find_distinct_item(current_disks, last_disks, :index)
        # if the new disk as no partitions, then we will format and assign device.
        if vm.partitions(new_disk[:index]).empty?
          # FIX: ignore multiple mount points for simplicity and only only create
          # a single primary partition for the first mount point.
          # if we had the UI for it, then the user would probably specify
          # partition sizes as a percentage of disk size and associate those with
          # mount points formatted optionally specifying file system, label, etc.
          @audit.append_info("Creating primary partition and formatting \"#{mapping[:mount_points].first}\".")
          vm.format_disk(new_disk[:index], mapping[:mount_points].first)
          succeeded = true
        else
          # FIX: ignoring multiple existing partitiions on a disk (which should
          # result in multiple new volumes appearing when the disk comes online)
          # for simplicity until we have a UI supporting multiple mount points.
          @audit.append_info("Preparing \"#{mapping[:mount_points].first}\" for use.")
          new_volume = find_distinct_item(current_volumes, last_volumes, :device)
          unless new_volume
            vm.online_disk(new_disk[:index])
            current_volumes = vm.volumes
            new_volume = find_distinct_item(current_volumes, last_volumes, :device)
          end
          if new_volume
            # prefer selection by existing device because it is more reliable in Windows 2003 case.
            unless new_volume[:device] && (0 == new_volume[:device].casecmp(mapping[:mount_points].first))
              device_or_index_to_select = new_volume[:device] || new_volume[:index]
              vm.assign_device(device_or_index_to_select, mapping[:mount_points].first)
            end
            succeeded = true
          end
        end
      end

      # retry only if still not assigned.
      if succeeded
        # volume is (finally!) assigned to correct device name.
        mapping[:management_status] = 'assigned'
        mapping[:attempts] = nil

        # reset cached volumes/disks for next attempt (to attach), if any.
        InstanceState.planned_volume_state.disks = nil
        InstanceState.planned_volume_state.volumes = nil

        # continue.
        yield if block_given?
      else
        mapping[:attempts] ||= 0
        mapping[:attempts] += 1
        if mapping[:attempts] >= VolumeManagement::MAX_VOLUME_ATTEMPTS
          strand("Exceeded maximum of #{VolumeManagement::MAX_VOLUME_ATTEMPTS} attempts waiting for volume #{mapping[:volume_id]} to be in a managable state.")
        else
          yield if block_given?
        end
      end
    rescue Exception => e
      strand(e)
    end
def manage_volume_device_assignment(mapping)

      # only managed volumes should be in an attached state ready for assignment.
      unless 'attached' == mapping[:management_status]
        raise VolumeManagement::UnexpectedState.new("The volume #{mapping[:volume_id]} was in an unexpected managed state: #{mapping.inspect}")
      end

      # check for changes in disks.
      last_disks = InstanceState.planned_volume_state.disks
      last_volumes = InstanceState.planned_volume_state.volumes
      vm = RightScale::Platform.volume_manager
      current_disks = vm.disks
      current_volumes = vm.volumes

      # correctly managing device assignment requires expecting precise changes
      # to disks and volumes. any deviation from this requires a retry.
      succeeded = false
      if new_disk = find_distinct_item(current_disks, last_disks, :index)
        # if the new disk as no partitions, then we will format and assign device.
        if vm.partitions(new_disk[:index]).empty?
          # FIX: ignore multiple mount points for simplicity and only only create
          # a single primary partition for the first mount point.
          # if we had the UI for it, then the user would probably specify
          # partition sizes as a percentage of disk size and associate those with
          # mount points formatted optionally specifying file system, label, etc.
          @audit.append_info("Creating primary partition and formatting \"#{mapping[:mount_points].first}\".")
          vm.format_disk(new_disk[:index], mapping[:mount_points].first)
          succeeded = true
        else
          # FIX: ignoring multiple existing partitiions on a disk (which should
          # result in multiple new volumes appearing when the disk comes online)
          # for simplicity until we have a UI supporting multiple mount points.
          @audit.append_info("Preparing \"#{mapping[:mount_points].first}\" for use.")
          new_volume = find_distinct_item(current_volumes, last_volumes, :device)
          unless new_volume
            vm.online_disk(new_disk[:index])
            current_volumes = vm.volumes
            new_volume = find_distinct_item(current_volumes, last_volumes, :device)
          end
          if new_volume
            # prefer selection by existing device because it is more reliable in Windows 2003 case.
            unless new_volume[:device] && (0 == new_volume[:device].casecmp(mapping[:mount_points].first))
              device_or_index_to_select = new_volume[:device] || new_volume[:index]
              vm.assign_device(device_or_index_to_select, mapping[:mount_points].first)
            end
            succeeded = true
          end
        end
      end

      # retry only if still not assigned.
      if succeeded
        # volume is (finally!) assigned to correct device name.
        mapping[:management_status] = 'assigned'
        mapping[:attempts] = nil

        # reset cached volumes/disks for next attempt (to attach), if any.
        InstanceState.planned_volume_state.disks = nil
        InstanceState.planned_volume_state.volumes = nil

        # continue.
        yield if block_given?
      else
        mapping[:attempts] ||= 0
        mapping[:attempts] += 1
        if mapping[:attempts] >= VolumeManagement::MAX_VOLUME_ATTEMPTS
          strand("Exceeded maximum of #{VolumeManagement::MAX_VOLUME_ATTEMPTS} attempts waiting for volume #{mapping[:volume_id]} to be in a managable state.")
        else
          yield if block_given?
        end
      end
    rescue Exception => e
      strand(e)
    end
Manages device assignment for volumes with considerations for formatting
 blank attached volumes.

 === Parameters
 mapping(Hash):: details of planned volume