<commit_before>module Fog
  module Compute
    class Vsphere

      class Volume < Fog::Model
        DISK_SIZE_TO_GB = 1048576
        identity :id

        attribute :datastore
        attribute :mode
        attribute :size
        attribute :thin
        attribute :eager_zero
        attribute :name
        attribute :filename
        attribute :size_gb
        attribute :key
        attribute :unit_number
        attribute :server_id

        def initialize(attributes={} )
          # Assign server first to prevent race condition with persisted?
          self.server_id = attributes.delete(:server_id)

          super defaults.merge(attributes)
        end

        def size_gb
          attributes[:size_gb] ||= attributes[:size].to_i / DISK_SIZE_TO_GB if attributes[:size]
        end

        def size_gb= s
          attributes[:size] = s.to_i * DISK_SIZE_TO_GB if s
        end

        def to_s
          name
        end

        def destroy
          requires :server_id, :key, :unit_number

          service.destroy_vm_volume(self)
          true
        end

        def save
          raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted?
          requires :server_id, :size, :datastore

          if unit_number.nil?
            self.unit_number = server.volumes.size
          end

          service.add_vm_volume(self)

          true
        end

        def server
          requires :server_id
          service.servers.get(server_id)
        end<commit_msg>[vsphere|compute] Be more intelligent about auto-picking a unit number for a volume.<commit_after>module Fog
  module Compute
    class Vsphere

      class Volume < Fog::Model
        DISK_SIZE_TO_GB = 1048576
        identity :id

        attribute :datastore
        attribute :mode
        attribute :size
        attribute :thin
        attribute :eager_zero
        attribute :name
        attribute :filename
        attribute :size_gb
        attribute :key
        attribute :unit_number
        attribute :server_id

        def initialize(attributes={} )
          # Assign server first to prevent race condition with persisted?
          self.server_id = attributes.delete(:server_id)

          super defaults.merge(attributes)
        end

        def size_gb
          attributes[:size_gb] ||= attributes[:size].to_i / DISK_SIZE_TO_GB if attributes[:size]
        end

        def size_gb= s
          attributes[:size] = s.to_i * DISK_SIZE_TO_GB if s
        end

        def to_s
          name
        end

        def destroy
          requires :server_id, :key, :unit_number

          service.destroy_vm_volume(self)
          true
        end

        def save
          raise Fog::Errors::Error.new('Resaving an existing object may create a duplicate') if persisted?
          requires :server_id, :size, :datastore

          if unit_number.nil?
            used_unit_numbers = server.volumes.collect { |volume| volume.unit_number }
            max_unit_number = used_unit_numbers.max

            if max_unit_number > server.volumes.size
              # If the max ID exceeds the number of volumes, there must be a hole in the range. Find a hole and use it.
              self.unit_number = max_unit_number.times.to_a.find { |i| used_unit_numbers.exclude?(i) }
            else
              self.unit_number = max_unit_number + 1
            end
          else
            if server.volumes.any? { |volume| volume.unit_number == self.unit_number && volume.id != self.id }
              raise "A volume already exists with that unit_number, so we can't save the new volume"
            end
          end

          service.add_vm_volume(self)

          true
        end

        def server
          requires :server_id
          service.servers.get(server_id)
        end
{'fraction_non_alphanumeric': 0.06290785695640824, 'fraction_numerical': 0.003915426781519186, 'mean_word_length': 1.8011695906432748, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5203821', 'n_tokens_mistral': 1069, 'n_tokens_neox': 1014, 'n_words': 297}