Class: Vagrant::MachineIndex
- Inherits:
-
Object
- Object
- Vagrant::MachineIndex
- Includes:
- Enumerable
- Defined in:
- lib/vagrant/machine_index.rb
Overview
MachineIndex is able to manage the index of created Vagrant environments in a central location.
The MachineIndex stores a mapping of UUIDs to basic information about a machine. The UUIDs are stored with the Vagrant environment and are looked up in the machine index.
The MachineIndex stores information such as the name of a machine, the directory it was last seen at, its last known state, etc. Using this information, we can load the entire Machine object for a machine, or we can just display metadata if needed.
The internal format of the data file is currently JSON in the following structure:
{ "version": 1, "machines": { "uuid": { "name": "foo", "provider": "vmware_fusion", "data_path": "/path/to/data/dir", "vagrantfile_path": "/path/to/Vagrantfile", "state": "running", "updated_at": "2014-03-02 11:11:44 +0100" } } }
Defined Under Namespace
Classes: Entry
Instance Method Summary collapse
-
#delete(entry) ⇒ Boolean
Deletes a machine by UUID.
-
#each(reload = false) ⇒ Object
Iterate over every machine in the index.
-
#get(uuid) ⇒ MachineIndex::Entry
Accesses a machine by UUID and returns a Entry.
-
#include?(uuid) ⇒ Boolean
Tests if the index has the given UUID.
-
#initialize(data_dir) ⇒ MachineIndex
constructor
Initializes a MachineIndex at the given file location.
-
#release(entry) ⇒ Object
Releases an entry, unlocking it.
-
#set(entry) ⇒ Entry
Creates/updates an entry object and returns the resulting entry.
Constructor Details
#initialize(data_dir) ⇒ MachineIndex
Initializes a MachineIndex at the given file location.
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/vagrant/machine_index.rb', line 45 def initialize(data_dir) @data_dir = data_dir @index_file = data_dir.join("index") @lock = Monitor.new @machines = {} @machine_locks = {} with_index_lock do unlocked_reload end end |
Instance Method Details
#delete(entry) ⇒ Boolean
Deletes a machine by UUID.
The machine being deleted with this UUID must either be locked by this index or must be unlocked.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/vagrant/machine_index.rb', line 64 def delete(entry) return true if !entry.id @lock.synchronize do with_index_lock do return true if !@machines[entry.id] # If we don't have the lock, then we need to acquire it. if !@machine_locks[entry.id] raise "Unlocked delete on machine: #{entry.id}" end # Reload so we have the latest data, then delete and save unlocked_reload @machines.delete(entry.id) unlocked_save # Release access on this machine unlocked_release(entry.id) end end true end |
#each(reload = false) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/vagrant/machine_index.rb', line 92 def each(reload=false) if reload @lock.synchronize do with_index_lock do unlocked_reload end end end @machines.each do |uuid, data| yield Entry.new(uuid, data.merge("id" => uuid)) end end |
#get(uuid) ⇒ MachineIndex::Entry
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/vagrant/machine_index.rb', line 116 def get(uuid) entry = nil @lock.synchronize do with_index_lock do # Reload the data unlocked_reload data = find_by_prefix(uuid) return nil if !data uuid = data["id"] entry = Entry.new(uuid, data) # Lock this machine lock_file = lock_machine(uuid) if !lock_file raise Errors::MachineLocked, name: entry.name, provider: entry.provider end @machine_locks[uuid] = lock_file end end entry end |
#include?(uuid) ⇒ Boolean
Tests if the index has the given UUID.
149 150 151 152 153 154 155 156 |
# File 'lib/vagrant/machine_index.rb', line 149 def include?(uuid) @lock.synchronize do with_index_lock do unlocked_reload return !!find_by_prefix(uuid) end end end |
#release(entry) ⇒ Object
Releases an entry, unlocking it.
This is an idempotent operation. It is safe to call this even if you're unsure if an entry is locked or not.
After calling this, the previous entry should no longer be used.
166 167 168 169 170 |
# File 'lib/vagrant/machine_index.rb', line 166 def release(entry) @lock.synchronize do unlocked_release(entry.id) end end |
#set(entry) ⇒ Entry
Creates/updates an entry object and returns the resulting entry.
If the entry was new (no UUID), then the UUID will be set on the resulting entry and can be used. Additionally, the a lock will be created for the resulting entry, so you must #release it if you want others to be able to access it.
If the entry isn't new (has a UUID). then this process must hold that entry's lock or else this set will fail.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/vagrant/machine_index.rb', line 184 def set(entry) # Get the struct and update the updated_at attribute struct = entry.to_json_struct # Set an ID if there isn't one already set id = entry.id @lock.synchronize do with_index_lock do # Reload so we have the latest machine data. This allows other # processes to update their own machines without conflicting # with our own. unlocked_reload # If we don't have a machine ID, try to look one up if !id self.each do |other| if entry.name == other.name && entry.provider == other.provider && entry.vagrantfile_path.to_s == other.vagrantfile_path.to_s id = other.id break end end # If we still don't have an ID, generate a random one id = SecureRandom.uuid.gsub("-", "") if !id # Get a lock on this machine lock_file = lock_machine(id) if !lock_file raise "Failed to lock new machine: #{entry.name}" end @machine_locks[id] = lock_file end if !@machine_locks[id] raise "Unlocked write on machine: #{id}" end # Set our machine and save @machines[id] = struct unlocked_save end end Entry.new(id, struct) end |