Class: VagrantPlugins::Skytap::Action::ComposeEnvironment
- Defined in:
- lib/vagrant-skytap/action/compose_environment.rb
Overview
Creates a multi-VM Skytap environment, or adds VMs to an existing environment. The source VMs (analogous to “images”) may come from various other environments and templates. We can parallelize this somewhat by adding multiple VMs per REST call, subject to the restriction that all source VMs added in a single call must be unique and must belong to the same containing environment/template. If creating a new environment from scratch, write the environment URL into the project data directory.
Instance Attribute Summary collapse
-
#env ⇒ Object
readonly
Returns the value of attribute env.
Instance Method Summary collapse
-
#add_vms(environment, machines) ⇒ API::Environment
Create Skytap VMs for the given machines (if they do not exist) within the given Skytap environment.
- #call(env) ⇒ Object
-
#fetch_source_vms(machines) ⇒ Hash
Fetch the source VMs for the given machines.
-
#get_groupings(vms_map, options = {}) ⇒ Array
Group the machines to minimize calls to the REST API – unique VMs from the same environment or template can be added in a single call.
-
#initialize(app, env) ⇒ ComposeEnvironment
constructor
A new instance of ComposeEnvironment.
Constructor Details
#initialize(app, env) ⇒ ComposeEnvironment
Returns a new instance of ComposeEnvironment.
40 41 42 43 44 |
# File 'lib/vagrant-skytap/action/compose_environment.rb', line 40 def initialize(app, env) @app = app @env = env @logger = Log4r::Logger.new("vagrant_skytap::action::compose_environment") end |
Instance Attribute Details
#env ⇒ Object (readonly)
Returns the value of attribute env.
38 39 40 |
# File 'lib/vagrant-skytap/action/compose_environment.rb', line 38 def env @env end |
Instance Method Details
#add_vms(environment, machines) ⇒ API::Environment
Create Skytap VMs for the given machines (if they do not exist) within the given Skytap environment.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/vagrant-skytap/action/compose_environment.rb', line 70 def add_vms(environment, machines) source_vms_map = fetch_source_vms(machines) names_to_vm_ids = {} get_groupings(source_vms_map, parallel: @env[:parallel]).each do |names| vms_for_pass = names.collect{|name| source_vms_map[name]} if !environment @logger.debug("Creating environment from source vms: #{vms_for_pass.collect(&:id)}") environment = API::Environment.create!(env, vms_for_pass) environment.properties.write('url' => environment.url) vms = environment.vms else @logger.debug("Adding source vms: #{vms_for_pass.collect(&:id)}") vms = environment.add_vms(vms_for_pass) end vms.each_with_index {|vm, i| names_to_vm_ids[names[i]] = vm.id } end machines.each do |machine| machine.id = names_to_vm_ids[machine.name] end environment end |
#call(env) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/vagrant-skytap/action/compose_environment.rb', line 46 def call(env) environment = env[:environment] new_environment = !environment machines = env[:machines].reject(&:id) environment = add_vms(environment, machines) if new_environment env[:environment] = environment env[:ui].info(I18n.t("vagrant_skytap.environment_url", url: environment.url)) elsif machines.present? env[:ui].info("Added VMs to #{environment.url}.") else env[:ui].info("No new VMs added to #{environment.url}.") end @app.call(env) end |
#fetch_source_vms(machines) ⇒ Hash
Fetch the source VMs for the given machines.
101 102 103 104 105 106 |
# File 'lib/vagrant-skytap/action/compose_environment.rb', line 101 def fetch_source_vms(machines) machines.inject({}) do |acc, machine| acc[machine.name] = API::Vm.fetch(env, machine.provider_config.vm_url) acc end end |
#get_groupings(vms_map, options = {}) ⇒ Array
Group the machines to minimize calls to the REST API – unique VMs from the same environment or template can be added in a single call. The return value is a nested array of machine names, e.g.:
- [:vm1, :vm4, :vm5], [:vm3], [:vm2
-
]
However, if the :parallel option is false, just return one machine per grouping, e.g.:
- [:vm1], [:vm2], [:vm3], [:vm4], [:vm5
-
]
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/vagrant-skytap/action/compose_environment.rb', line 121 def get_groupings(vms_map, ={}) parallel = true parallel = [:parallel] if .has_key?(:parallel) return vms_map.keys.collect{|name| [name]} unless parallel # Produces nested hash, mapping configuration/template urls to # a map of machine names to the source VM id. (We discard the # parent urls -- they are just used to group the VMs.) groupings = vms_map.inject(Hash.new{|h,k| h[k] = {}}) do |acc, (name, vm)| acc[vm.parent_url][name] = vm.id acc end.values groupings2 = [] groupings.each_with_index do |grouping, i| if grouping.values.uniq.count == grouping.values.count # The new VMs in the API response will be sorted # by the source VM ids. Sort the machines within # each group to match. groupings2 << grouping.invert.sort.collect(&:last) else # If the same source VM appears more than once in a # group, we have to make multiple API calls. For # simplicity, handle this case by creating a single # group for each machine. groupings2.concat(grouping.keys.map{|v| [v]}) end end groupings2.sort_by{|grouping| grouping.count}.reverse end |