Last active
January 21, 2019 11:09
-
-
Save chirauki/a8c9dc382a544d42816ca3daf8c9d364 to your computer and use it in GitHub Desktop.
Capture script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'csv' | |
require 'trollop' | |
require 'rubygems' | |
require 'abiquo-api' | |
opts = Trollop::options do | |
opt :endpoint, "API endpoint", :type => :string | |
opt :username, "API username", :type => :string, :default => "admin" | |
opt :password, "API password", :type => :string, :default => "xabiquo" | |
opt :mode , "Authmode", :type => :string, :default => "basic" | |
opt :key , "API key", :type => :string | |
opt :secret , "API secret", :type => :string | |
opt :tkey , "Token key" , :type => :string | |
opt :tsecret , "Token secret", :type => :string | |
opt :file , "CVS file", :type => :string | |
end | |
Trollop::die :file, "must be provided" unless opts[:file] | |
Trollop::die :file, "must exists" unless File.exist?(opts[:file]) if opts[:file] | |
$vms = [] | |
$client = case opts[:mode] | |
when "oauth" then | |
AbiquoAPI.new( | |
:connection_options => { :ssl => { :verify => false } }, | |
:abiquo_api_url => opts[:endpoint], | |
:abiquo_api_key => opts[:key], | |
:abiquo_api_secret => opts[:secret], | |
:abiquo_token_key => opts[:tkey], | |
:abiquo_token_secret => opts[:tsecret]) | |
else | |
AbiquoAPI.new( | |
:abiquo_api_url => opts[:endpoint], | |
:abiquo_username => opts[:username], | |
:abiquo_password => opts[:password]) | |
end | |
def find(enum, name) | |
return enum.select {|o| o.name == name}.first | |
end | |
def link(href, accept) | |
AbiquoAPI::Link.new( | |
:href => href, | |
:type => "application/vnd.abiquo.#{accept}+json", | |
:client => $client) | |
end | |
# Capture a NOT_MANAGED VM | |
# | |
# This mimics the UI behavior as it is in Abiquo 3.6 | |
# | |
# enterprise : Enterprise name the VM will be captured for | |
# vdatacenter : Virtual datacenter name the VM will be captured in | |
# vappliance : Virtual appliance name the VM will be captured in. It will be created if it doesn't not exist | |
# vmachine : Virtual machine name as reported by the HV | |
# nics : Network interfaces configuration in the form [VLAN0,ADDR0,...,VLANn,ADDRn] | |
# : VLANx must be the name of an existing network | |
# : ADDRx will be created if it doesn't not exist | |
def capture(enterprise, vdatacenter, vappliance, vmachine, nics) | |
# Validate enterprise | |
ent = find($enterprises, enterprise) | |
ent or raise "Enterprise not found" | |
# Validate vdc | |
vdc = find(link("#{ent.url}/action/virtualdatacenters", "virtualdatacenters").get, vdatacenter) | |
vdc or raise "Virtual datacenter not found" | |
# Validate VM | |
# 1 Find the VM in the VM list | |
# 2 Get the flat VM object with all nics | |
# 3 Verify the VM is not already managed | |
vm = find($vms, vmachine) | |
vm or raise "VM not found" | |
vm = vm.link(:virtualmachine).get(:sync => true, :accept => "application/vnd.abiquo.virtualmachineflat+json") | |
vm or raise "VM could not be synchronyzed" | |
vm.type == "NOT_MANAGED" or raise "VM is already managed" | |
# Validate vapp | |
unless vapp = find(vdc.link(:virtualappliances).get, vappliance) | |
puts "- Creating virtual appliance" | |
vapp = $client.post(vdc.link(:virtualappliances), {:name => vappliance}, | |
:accept => "application/vnd.abiquo.virtualappliance+json", | |
:content => "application/vnd.abiquo.virtualappliance+json") | |
end | |
vapp or raise "Virtual appliance could not be created" | |
# Get networks | |
# This depends on the enterprise and the DC the VM is running in | |
dc = vm.link(:location).get.id | |
vlans = vdc.link(:privatenetworks).get.to_a | |
vlans += link(ent.url + "/action/publicnetworks", "vlans").get(:datacenterId => dc).to_a | |
vlans += link(ent.url + "/action/externalnetworks", "vlans").get(:datacenterId => dc).to_a | |
# Assign networks to each NIC | |
vm.nics["collection"].each_index do |n| | |
# Validate NIC data | |
nic = vm.nics["collection"][n] | |
network, address = nics[0], nics[1] | |
network and address or raise "Missing information for NIC #{n}" | |
# Validate network | |
vlan = find(vlans, network) | |
vlan or raise "Network #{network} not found" | |
# Validate IP | |
unless ip = vlan.link(:ips).get.select { |i| i.ip == address }.first | |
puts "- Creating IP #{address} in #{vlan.name}" | |
ip = $client.post(vlan.link(:ips), { | |
:ip => address, | |
:available => true, | |
:ipv6 => false, | |
:numips => 1, | |
:quarantine => false}, | |
:content => "application/vnd.abiquo.ipsbulkcreation+json") | |
end | |
ip or raise "IP #{address} could not be created" | |
# Add nic configuration to VM nic | |
nic["ip"] = address | |
nic["links"] = [{ | |
:title => vlan.name, | |
:href => vlan.url, | |
:type => "application/vnd.abiquo.vlan+json", | |
:rel => "vlan"}] | |
# Next interface | |
nics.shift(2) | |
end | |
# Insert imported link | |
link = vm.link(:edit) | |
link.rel = "imported" | |
vm.links.push({:imported => vm.link(:edit)}) | |
# Capture VM | |
#vm = $client.post(link(vapp.link(:virtualmachines).href, "virtualmachineflat"), vm) | |
vm = $client.post(vapp.link(:virtualmachines), vm.to_json, :content => 'application/vnd.abiquo.virtualmachineflat+json', | |
:accept => 'application/vnd.abiquo.virtualmachineflat+json') | |
vm or raise "Could not capture VM" | |
end | |
puts "Retrieving platform information" | |
begin | |
$enterprises = link("/api/admin/enterprises", "enterprises").get | |
link("/api/admin/datacenters", "datacenters").get.each do |d| | |
d.link(:racks).get.each do |r| | |
r.link(:machines).get.each do |m| | |
$vms += m.link(:virtualmachines).get(:sync => true).to_a | |
end | |
end | |
end | |
rescue => e | |
puts "Could not retrieve platform information" | |
exit -1 | |
end | |
puts "Retrieved platform information" | |
puts "" | |
# enterprise,vdc,vapp,vm,nic0_vlan,nic0_ip...nicN_vlan,nicN_ip | |
CSV.foreach(opts[:file]) do |row| | |
# Ignore empty lines and comments | |
next if row.length < 6 or row[0].start_with? '#' | |
# Start capture | |
puts "Capturing " + row[0..3].join(",") | |
# Validate input | |
row.size > 5 or raise "Incomplete row" | |
capture(row[0],row[1],row[2], row[3], row[4..-1]) | |
puts "Captured " + row[0..3].join(",") | |
puts "" | |
end | |
puts "Finished capturing VMs" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment