mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
add ability for test pxe in private network
This commit is contained in:
parent
981ca18b5e
commit
b92b02b6d6
27
README.md
27
README.md
@ -83,14 +83,14 @@ kvm type virtual machines with `virsh` or `virt-manager`.
|
|||||||
|
|
||||||
Next, you must have [Vagrant
|
Next, you must have [Vagrant
|
||||||
installed](http://docs.vagrantup.com/v2/installation/index.html).
|
installed](http://docs.vagrantup.com/v2/installation/index.html).
|
||||||
Vagrant-libvirt supports Vagrant 1.5, 1.6, 1.7 and 1.8.
|
Vagrant-libvirt supports Vagrant 1.5, 1.6, 1.7 and 1.8.
|
||||||
*We only test with the upstream version!* If you decide to install your distros
|
*We only test with the upstream version!* If you decide to install your distros
|
||||||
version and you run into problems, as a first step you should switch to upstream.
|
version and you run into problems, as a first step you should switch to upstream.
|
||||||
|
|
||||||
Now you need to make sure your have all the build dependencies installed for
|
Now you need to make sure your have all the build dependencies installed for
|
||||||
vagrant-libvirt. This depends on your distro. An overview:
|
vagrant-libvirt. This depends on your distro. An overview:
|
||||||
|
|
||||||
* Ubuntu 12.04/14.04/16.04, Debian:
|
* Ubuntu 12.04/14.04/16.04, Debian:
|
||||||
```shell
|
```shell
|
||||||
apt-get build-dep vagrant ruby-libvirt
|
apt-get build-dep vagrant ruby-libvirt
|
||||||
apt-get install qemu libvirt-bin ebtables dnsmasq
|
apt-get install qemu libvirt-bin ebtables dnsmasq
|
||||||
@ -780,7 +780,7 @@ You can define filter for redirected devices. These filters can be positiv or ne
|
|||||||
You can extract that information from output of `lsusb` command. Every line contains the information in format `Bus [<bus>] Device [<device>]: ID [<vendor>:[<product>]`. The `version` can be extracted from the detailed output of the device using `lsusb -D /dev/usb/[<bus>]/[<device>]`. For example:
|
You can extract that information from output of `lsusb` command. Every line contains the information in format `Bus [<bus>] Device [<device>]: ID [<vendor>:[<product>]`. The `version` can be extracted from the detailed output of the device using `lsusb -D /dev/usb/[<bus>]/[<device>]`. For example:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# get bcdDevice from
|
# get bcdDevice from
|
||||||
$: lsusb
|
$: lsusb
|
||||||
Bus 001 Device 009: ID 08e6:3437 Gemalto (was Gemplus) GemPC Twin SmartCard Reader
|
Bus 001 Device 009: ID 08e6:3437 Gemalto (was Gemplus) GemPC Twin SmartCard Reader
|
||||||
|
|
||||||
@ -903,6 +903,25 @@ Vagrant.configure("2") do |config|
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Example for vm with 2 networks and only 1 is bootable and has dhcp server in this subnet, for example foreman with dhcp server
|
||||||
|
Name of network "foreman_managed" is key for define boot order
|
||||||
|
```ruby
|
||||||
|
config.vm.define :pxeclient do |pxeclient|
|
||||||
|
pxeclient.vm.network :private_network,ip: '10.0.0.5',
|
||||||
|
libvirt__network_name: "foreman_managed",
|
||||||
|
libvirt__dhcp_enabled: false,
|
||||||
|
libvirt__host_ip: '10.0.0.1'
|
||||||
|
|
||||||
|
pxeclient.vm.provider :libvirt do |domain|
|
||||||
|
domain.memory = 1000
|
||||||
|
boot_network = {'network' => 'foreman_managed'}
|
||||||
|
domain.storage :file, :size => '100G', :type => 'qcow2'
|
||||||
|
domain.boot boot_network
|
||||||
|
domain.boot 'hd'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
## SSH Access To VM
|
## SSH Access To VM
|
||||||
|
|
||||||
vagrant-libvirt supports vagrant's [standard ssh
|
vagrant-libvirt supports vagrant's [standard ssh
|
||||||
|
@ -227,6 +227,7 @@ module VagrantPlugins
|
|||||||
# Do we need to create new network?
|
# Do we need to create new network?
|
||||||
unless @interface_network[:created]
|
unless @interface_network[:created]
|
||||||
@interface_network[:name] = @options[:network_name]
|
@interface_network[:name] = @options[:network_name]
|
||||||
|
@interface_network[:ip_address] ||= @options[:host_ip]
|
||||||
|
|
||||||
# Generate a unique name for network bridge.
|
# Generate a unique name for network bridge.
|
||||||
@interface_network[:bridge_name] = generate_bridge_name
|
@interface_network[:bridge_name] = generate_bridge_name
|
||||||
|
@ -1,64 +1,107 @@
|
|||||||
require "log4r"
|
require 'log4r'
|
||||||
require 'nokogiri'
|
require 'nokogiri'
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module ProviderLibvirt
|
module ProviderLibvirt
|
||||||
module Action
|
module Action
|
||||||
|
# boot order useful for pxe in discovery workflow
|
||||||
class SetBootOrder
|
class SetBootOrder
|
||||||
def initialize(app, env)
|
def initialize(app, env)
|
||||||
@app = app
|
@app = app
|
||||||
@logger = Log4r::Logger.new("vagrant_libvirt::action::set_boot_order")
|
@logger = Log4r::Logger.new('vagrant_libvirt::action::set_boot_order')
|
||||||
config = env[:machine].provider_config
|
config = env[:machine].provider_config
|
||||||
@boot_order = config.boot_order
|
@boot_order = config.boot_order
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
# Get domain first
|
# Get domain first
|
||||||
begin
|
begin
|
||||||
domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
|
domain = env[:machine].provider
|
||||||
env[:machine].id.to_s)
|
.driver
|
||||||
|
.connection
|
||||||
|
.client
|
||||||
|
.lookup_domain_by_uuid(
|
||||||
|
env[:machine].id.to_s
|
||||||
|
)
|
||||||
rescue => e
|
rescue => e
|
||||||
raise Errors::NoDomainError,
|
raise Errors::NoDomainError,
|
||||||
:error_message => e.message
|
error_message: e.message
|
||||||
end
|
end
|
||||||
|
|
||||||
# Only execute specific boot ordering if this is defined in the Vagrant file
|
# Only execute specific boot ordering if this is defined
|
||||||
|
# in the Vagrant file
|
||||||
if @boot_order.count >= 1
|
if @boot_order.count >= 1
|
||||||
|
|
||||||
# If a domain is initially defined with no box or disk or with an explicit boot order, libvirt adds <boot dev="foo">
|
# If a domain is initially defined with no box or disk or
|
||||||
# This conflicts with an explicit boot_order configuration, so we need to remove it from the domain xml and feed it back.
|
# with an explicit boot order, libvirt adds <boot dev="foo">
|
||||||
# Also see https://bugzilla.redhat.com/show_bug.cgi?id=1248514 as to why we have to do this after all devices have been defined.
|
# This conflicts with an explicit boot_order configuration,
|
||||||
|
# so we need to remove it from the domain xml and feed it back.
|
||||||
|
# Also see https://bugzilla.redhat.com/show_bug.cgi?id=1248514
|
||||||
|
# as to why we have to do this after all devices have been defined.
|
||||||
xml = Nokogiri::XML(domain.xml_desc)
|
xml = Nokogiri::XML(domain.xml_desc)
|
||||||
xml.search("/domain/os/boot").each do |node|
|
xml.search('/domain/os/boot').each(&:remove)
|
||||||
node.remove
|
|
||||||
end
|
|
||||||
|
|
||||||
# Parse the XML and find each defined drive and network interfacee
|
# Parse the XML and find each defined drive and network interfacee
|
||||||
hd = xml.search("/domain/devices/disk[@device='disk']")
|
hd = xml.search("/domain/devices/disk[@device='disk']")
|
||||||
cdrom = xml.search("/domain/devices/disk[@device='cdrom']")
|
cdrom = xml.search("/domain/devices/disk[@device='cdrom']")
|
||||||
network = xml.search("/domain/devices/interface[@type='network' or @type='udp']")
|
# implemented only for 1 network
|
||||||
|
nets = @boot_order.flat_map do |x|
|
||||||
|
x.class == Hash ? x : nil
|
||||||
|
end.compact
|
||||||
|
raise 'Defined only for 1 network for boot' if nets.size > 1
|
||||||
|
network = search_network(nets, xml)
|
||||||
|
|
||||||
# Generate an array per device group and a flattened array from all of those
|
# Generate an array per device group and a flattened
|
||||||
devices = {"hd" => hd, "cdrom" => cdrom, "network" => network}
|
# array from all of those
|
||||||
final_boot_order = @boot_order.flat_map {|category| devices[category] }
|
devices = { 'hd' => hd,
|
||||||
|
'cdrom' => cdrom,
|
||||||
|
'network' => network }
|
||||||
|
|
||||||
# Loop over the entire defined boot order array and create boot order entries in the domain XML
|
final_boot_order = final_boot_order(@boot_order, devices)
|
||||||
|
# Loop over the entire defined boot order array and
|
||||||
|
# create boot order entries in the domain XML
|
||||||
final_boot_order.each_with_index do |node, index|
|
final_boot_order.each_with_index do |node, index|
|
||||||
boot = "<boot order='#{index+1}'/>"
|
boot = "<boot order='#{index + 1}'/>"
|
||||||
node.add_child(boot)
|
node.add_child(boot)
|
||||||
if node.name == 'disk'
|
logger_msg(node, index)
|
||||||
@logger.debug "Setting #{node['device']} to boot index #{index+1}"
|
|
||||||
elsif node.name == 'interface'
|
|
||||||
@logger.debug "Setting #{node.name} to boot index #{index+1}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Finally redefine the domain XML through libvirt to apply the boot ordering
|
# Finally redefine the domain XML through libvirt
|
||||||
env[:machine].provider.driver.connection.client.define_domain_xml(xml.to_s)
|
# to apply the boot ordering
|
||||||
|
env[:machine].provider
|
||||||
|
.driver
|
||||||
|
.connection
|
||||||
|
.client
|
||||||
|
.define_domain_xml(xml.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
|
end
|
||||||
|
|
||||||
|
def final_boot_order(boot_order, devices)
|
||||||
|
boot_order.flat_map do |category|
|
||||||
|
devices[category.class == Hash ? category.keys.first : category]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def search_network(nets, xml)
|
||||||
|
str = '/domain/devices/interface'
|
||||||
|
str += "[(@type='network' or @type='udp')"
|
||||||
|
unless nets.empty?
|
||||||
|
str += " and source[@network='#{nets.first['network']}']"
|
||||||
|
end
|
||||||
|
str += ']'
|
||||||
|
@logger.debug(str)
|
||||||
|
xml.search(str)
|
||||||
|
end
|
||||||
|
|
||||||
|
def logger_msg(node, index)
|
||||||
|
name = if node.name == 'disk'
|
||||||
|
node['device']
|
||||||
|
elsif node.name == 'interface'
|
||||||
|
node.name
|
||||||
|
end
|
||||||
|
@logger.debug "Setting #{name} to boot index #{index + 1}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user