Class: OsCtld::IdRange

Inherits:
Object
  • Object
show all
Includes:
Assets::Definition, Lockable, Manipulable
Defined in:
lib/osctld/id_range.rb

Defined Under Namespace

Classes: AllocationError, AllocationTable

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Assets::Definition

#define_assets

Methods included from Manipulable

#acquire_manipulation_lock, #init_manipulable, #is_being_manipulated?, #manipulate, #manipulated_by, #release_manipulation_lock

Methods included from Lockable

#exclusively, included, #inclusively, #init_lock, #lock, #unlock

Constructor Details

#initialize(pool, name, load: true) ⇒ IdRange

Returns a new instance of IdRange.



16
17
18
19
20
21
22
23
# File 'lib/osctld/id_range.rb', line 16

def initialize(pool, name, load: true)
  init_lock
  init_manipulable
  @pool = pool
  @name = name
  @attrs = Attributes.new
  load_config if load
end

Instance Attribute Details

#allocationsObject (readonly, protected)

Returns the value of attribute allocations.



186
187
188
# File 'lib/osctld/id_range.rb', line 186

def allocations
  @allocations
end

#attrsObject (readonly)

Returns the value of attribute attrs.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def attrs
  @attrs
end

#block_countObject (readonly)

Returns the value of attribute block_count.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def block_count
  @block_count
end

#block_sizeObject (readonly)

Returns the value of attribute block_size.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def block_size
  @block_size
end

#nameObject (readonly)

Returns the value of attribute name.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def name
  @name
end

#poolObject (readonly)

Returns the value of attribute pool.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def pool
  @pool
end

#start_idObject (readonly)

Returns the value of attribute start_id.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def start_id
  @start_id
end

Instance Method Details

#add_block_ids(block) ⇒ Object (protected)



188
189
190
191
192
193
194
195
# File 'lib/osctld/id_range.rb', line 188

def add_block_ids(block)
  first_id = start_id + (block[:block_index] * block_size)
  block.merge(
    first_id:,
    last_id: first_id + (block_size * block[:block_count]) - 1,
    id_count: block_size * block[:block_count]
  )
end

#allocate(block_count, opts = {}) ⇒ Hash

Parameters:

  • block_count (Integer)

    number of blocks to allocate

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :block_index (Integer)

    optional starting block_index

  • :owner (String)

Returns:

  • (Hash)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/osctld/id_range.rb', line 44

def allocate(block_count, opts = {})
  ret = nil

  exclusively do
    if opts[:block_index]
      begin
        ret = allocations.allocate_at(opts[:block_index], block_count, opts[:owner])
      rescue ArgumentError => e
        raise AllocationError, e.message
      end
    else
      unless (ret = allocations.allocate(block_count, opts[:owner]))
        raise AllocationError, 'no free space found'
      end
    end
    save_config
  end

  add_block_ids(ret)
end

#assetsObject



88
89
90
91
92
93
94
95
96
97
98
# File 'lib/osctld/id_range.rb', line 88

def assets
  define_assets do |add|
    add.file(
      config_path,
      desc: 'Configuration file',
      user: 0,
      group: 0,
      mode: 0o400
    )
  end
end

#can_delete?Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/osctld/id_range.rb', line 84

def can_delete?
  allocations.empty?
end

#config_pathObject



176
177
178
# File 'lib/osctld/id_range.rb', line 176

def config_path
  File.join(pool.conf_path, 'id-range', "#{name}.yml")
end

#configure(start_id, block_size, block_count) ⇒ Object



29
30
31
32
33
34
35
36
37
# File 'lib/osctld/id_range.rb', line 29

def configure(start_id, block_size, block_count)
  exclusively do
    @start_id = start_id
    @block_size = block_size
    @block_count = block_count
    @allocations = AllocationTable.new(block_count)
    save_config
  end
end

#exportObject



136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/osctld/id_range.rb', line 136

def export
  inclusively do
    {
      pool: pool.name,
      name:,
      start_id:,
      last_id:,
      block_size:,
      block_count:,
      allocated: allocations.count_allocated_blocks,
      free: allocations.count_free_blocks
    }.merge!(attrs.export)
  end
end

#export_allObject



151
152
153
154
155
# File 'lib/osctld/id_range.rb', line 151

def export_all
  inclusively do
    allocations.export_all.map { |v| add_block_ids(v) }
  end
end

#export_allocatedObject



157
158
159
160
161
# File 'lib/osctld/id_range.rb', line 157

def export_allocated
  inclusively do
    allocations.export_allocated.map { |v| add_block_ids(v) }
  end
end

#export_at(block_index) ⇒ Object

Parameters:

  • block_index (Integer)


170
171
172
173
174
# File 'lib/osctld/id_range.rb', line 170

def export_at(block_index)
  inclusively do
    add_block_ids(allocations.export_at(block_index))
  end
end

#export_freeObject



163
164
165
166
167
# File 'lib/osctld/id_range.rb', line 163

def export_free
  inclusively do
    allocations.export_free.map { |v| add_block_ids(v) }
  end
end

#free_at(block_index) ⇒ Object

Parameters:

  • block_index (Integer)


66
67
68
69
70
71
72
73
74
# File 'lib/osctld/id_range.rb', line 66

def free_at(block_index)
  exclusively do
    unless allocations.free_at(block_index)
      raise AllocationError, "block at index #{block_index} not found"
    end

    save_config
  end
end

#free_by(owner) ⇒ Object

Parameters:

  • owner (String)


77
78
79
80
81
82
# File 'lib/osctld/id_range.rb', line 77

def free_by(owner)
  exclusively do
    allocations.free_by(owner)
    save_config
  end
end

#idObject



25
26
27
# File 'lib/osctld/id_range.rb', line 25

def id
  name
end

#last_idObject



132
133
134
# File 'lib/osctld/id_range.rb', line 132

def last_id
  start_id + (block_size * block_count) - 1
end

#load_configObject (protected)



197
198
199
200
201
202
203
204
205
# File 'lib/osctld/id_range.rb', line 197

def load_config
  cfg = OsCtl::Lib::ConfigFile.load_yaml_file(config_path)

  @start_id = cfg['start_id']
  @block_size = cfg['block_size']
  @block_count = cfg['block_count']
  @allocations = AllocationTable.load(block_count, cfg['allocations'])
  @attrs = Attributes.load(cfg['attrs'] || {})
end

#manipulation_resourceObject



180
181
182
# File 'lib/osctld/id_range.rb', line 180

def manipulation_resource
  ['id-range', "#{pool.name}:#{name}"]
end

#save_configObject (protected)



207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/osctld/id_range.rb', line 207

def save_config
  File.open(config_path, 'w', 0o400) do |f|
    f.write(OsCtl::Lib::ConfigFile.dump_yaml({
      'start_id' => start_id,
      'block_size' => block_size,
      'block_count' => block_count,
      'allocations' => allocations.dump,
      'attrs' => attrs.dump
    }))
  end

  File.chown(0, 0, config_path)
end

#set(opts) ⇒ Object

Parameters:

  • opts (Hash)

Options Hash (opts):

  • :attrs (Hash)


102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/osctld/id_range.rb', line 102

def set(opts)
  opts.each do |k, v|
    case k
    when :attrs
      attrs.update(v)

    else
      raise "unsupported option '#{k}'"
    end
  end

  save_config
end

#unset(opts) ⇒ Object

Parameters:

  • opts (Hash)

Options Hash (opts):

  • :attrs (Array<String>)


118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/osctld/id_range.rb', line 118

def unset(opts)
  opts.each do |k, v|
    case k
    when :attrs
      v.each { |attr| attrs.unset(attr) }

    else
      raise "unsupported option '#{k}'"
    end
  end

  save_config
end