mirror of
https://github.com/vagrant-libvirt/vagrant-libvirt.git
synced 2025-02-25 18:55:27 -06:00
merged in the upstream changes correctly (I hope)
This commit is contained in:
commit
1a8e457960
20
.travis.yml
Normal file
20
.travis.yml
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
language: ruby
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -y libvirt-dev
|
||||
- gem install bundler --version $BUNDLER_VERSION
|
||||
install: bundle _${BUNDLER_VERSION}_ install
|
||||
script: bundle _${BUNDLER_VERSION}_ exec rspec --color --format documentation
|
||||
notifications:
|
||||
email: false
|
||||
rvm:
|
||||
- 2.0.0
|
||||
env:
|
||||
global:
|
||||
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
|
||||
matrix:
|
||||
- VAGRANT_VERSION=v1.5.4 BUNDLER_VERSION=1.5.3
|
||||
- VAGRANT_VERSION=v1.6.5 BUNDLER_VERSION=1.6.9
|
||||
- VAGRANT_VERSION=v1.7.0 BUNDLER_VERSION=1.7.9
|
||||
- VAGRANT_VERSION= BUNDLER_VERSION=1.7.9
|
10
Gemfile
10
Gemfile
@ -7,10 +7,16 @@ group :development do
|
||||
# We depend on Vagrant for development, but we don't add it as a
|
||||
# gem dependency because we expect to be installed within the
|
||||
# Vagrant environment itself using `vagrant plugin`.
|
||||
gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
|
||||
if ENV['VAGRANT_VERSION']
|
||||
gem 'vagrant', :git => 'https://github.com/mitchellh/vagrant.git',
|
||||
tag: ENV['VAGRANT_VERSION']
|
||||
else
|
||||
gem 'vagrant', :git => 'https://github.com/mitchellh/vagrant.git'
|
||||
end
|
||||
gem 'pry'
|
||||
end
|
||||
|
||||
group :plugins do
|
||||
gem "vagrant-libvirt", :path => '.'
|
||||
gem 'vagrant-libvirt', :path => '.'
|
||||
end
|
||||
|
||||
|
112
README.md
112
README.md
@ -10,7 +10,7 @@ welcome and can help a lot :-)
|
||||
## Features
|
||||
|
||||
* Control local Libvirt hypervisors.
|
||||
* Vagrant `up`, `destroy`, `suspend`, `resume`, `halt`, `ssh`, `reload` and `provision` commands.
|
||||
* Vagrant `up`, `destroy`, `suspend`, `resume`, `halt`, `ssh`, `reload`, `package` and `provision` commands.
|
||||
* Upload box image (qcow2 format) to Libvirt storage pool.
|
||||
* Create volume as COW diff image for domains.
|
||||
* Create private networks.
|
||||
@ -46,12 +46,19 @@ missing development libraries for libxslt, libxml2 and libvirt.
|
||||
|
||||
In Ubuntu, Debian, ...
|
||||
```
|
||||
$ sudo apt-get install libxslt-dev libxml2-dev libvirt-dev
|
||||
$ sudo apt-get install libxslt-dev libxml2-dev libvirt-dev zlib1g-dev
|
||||
```
|
||||
|
||||
In RedHat, Centos, Fedora, ...
|
||||
```
|
||||
# yum install libxslt-devel libxml2-devel libvirt-devel
|
||||
# yum install libxslt-devel libxml2-devel libvirt-devel libguestfs-tools-c
|
||||
```
|
||||
|
||||
If have problem with installation - check your linker. It should be ld.gold:
|
||||
```
|
||||
sudo alternatives --set ld /usr/bin/ld.gold
|
||||
# OR
|
||||
sudo ln -fs /usr/bin/ld.gold /usr/bin/ld
|
||||
```
|
||||
|
||||
## Vagrant Project Preparation
|
||||
@ -64,10 +71,8 @@ a `config.vm.provider` block. So first, add Libvirt box using any name you
|
||||
want. This is just an example of Libvirt CentOS 6.4 box available:
|
||||
|
||||
```
|
||||
vagrant box add centos64 http://kwok.cz/centos64.box
|
||||
```
|
||||
or
|
||||
```
|
||||
vagrant box add fedora21 http://citozin.com/fedora21.box
|
||||
# or
|
||||
vagrant box add centos64 http://citozin.com/centos64.box
|
||||
```
|
||||
|
||||
@ -96,6 +101,7 @@ $ vagrant up --provider=libvirt
|
||||
Vagrant needs to know that we want to use Libvirt and not default VirtualBox.
|
||||
That's why there is `--provider=libvirt` option specified. Other way to tell
|
||||
Vagrant to use Libvirt provider is to setup environment variable
|
||||
|
||||
`export VAGRANT_DEFAULT_PROVIDER=libvirt`.
|
||||
|
||||
### How Project Is Created
|
||||
@ -124,7 +130,7 @@ Although it should work without any configuration for most people, this provider
|
||||
* `connect_via_ssh` - If use ssh tunnel to connect to Libvirt.
|
||||
* `username` - Username and password to access Libvirt.
|
||||
* `password` - Password to access Libvirt.
|
||||
* `id_ssh_key_file` - The id ssh key file name to access Libvirt (eg: id_dsa or id_rsa or ... in the user .ssh directory)
|
||||
* `id_ssh_key_file` - If not nil, uses this ssh private key to access Libvirt. Default is $HOME/.ssh/id_rsa. Prepends $HOME/.ssh/ if no directory.
|
||||
* `socket` - Path to the libvirt unix socket (eg: /var/run/libvirt/libvirt-sock)
|
||||
* `uri` - For advanced usage. Directly specifies what libvirt connection URI vagrant-libvirt should use. Overrides all other connection configuration options.
|
||||
|
||||
@ -155,7 +161,7 @@ end
|
||||
* `initrd` - To specify the initramfs/initrd to use for the guest. Equivalent to qemu `-initrd`.
|
||||
* `random_hostname` - To create a domain name with extra information on the end to prevent hostname conflicts.
|
||||
* `cmd_line` - Arguments passed on to the guest kernel initramfs or initrd to use. Equivalent to qemu `-append`.
|
||||
* `graphics_type` - Sets the protocol used to expose the guest display. Defaults to `vnc`. Possible values are "sdl", "curses", "none", "gtk", or "vnc".
|
||||
* `graphics_type` - Sets the protocol used to expose the guest display. Defaults to `vnc`. Possible values are "sdl", "curses", "none", "gtk", "vnc" or "spice".
|
||||
* `graphics_port` - Sets the port for the display protocol to bind to. Defaults to 5900.
|
||||
* `graphics_ip` - Sets the IP for the display protocol to bind to. Defaults to "127.0.0.0.1".
|
||||
* `graphics_passwd` - Sets the password for the display protocol. Working for vnc and spice. by default working without passsword.
|
||||
@ -163,6 +169,10 @@ end
|
||||
* `keymap` - Set keymap for vm. default: en-us
|
||||
* `video_vram` - Used by some graphics card types to vary the amount of RAM dedicated to video. Defaults to 9216.
|
||||
* `machine` - Sets machine type. Equivalent to qemu `-machine`. Use `qemu-system-x86_64 -machine help` to get a list of supported machines.
|
||||
* `machine_arch` - Sets machine architecture. This helps libvirt to determine the correct emulator type. Possible values depend on your version of qemu. For possible values, see which emulator executable `qemu-system-*` your system provides. Common examples are `aarch64`, `alpha`, `arm`, `cris`, `i386`, `lm32`, `m68k`, `microblaze`, `microblazeel`, `mips`, `mips64`, `mips64el`, `mipsel`, `moxie`, `or32`, `ppc`, `ppc64`, `ppcemb`, `s390x`, `sh4`, `sh4eb`, `sparc`, `sparc64`, `tricore`, `unicore32`, `x86_64`, `xtensa`, `xtensaeb`.
|
||||
* `machine_virtual_size` - Sets the disk size in GB for the machine overriding the default specified in the box. Allows boxes to defined with a minimal size disk by default and to be grown to a larger size at creation time. Will ignore sizes smaller than the size specified by the box metadata. Note that currently there is no support for automatically resizing the filesystem to take advantage of the larger disk.
|
||||
* `boot` - Change the boot order and enables the boot menu. Possible options are "hd" or "network". Defaults to "hd" with boot menu disabled. When "network" is set first, *all* NICs will be tried before the first disk is tried.
|
||||
* `nic_adapter_count` - Defaults to '8'. Only use case for increasing this count is for VMs that virtualize switches such as Cumulus Linux. Max value for Cumulus Linux VMs is 33.
|
||||
|
||||
|
||||
Specific domain settings can be set for each domain separately in multi-VM
|
||||
@ -184,10 +194,31 @@ Vagrant.configure("2") do |config|
|
||||
# ...
|
||||
```
|
||||
|
||||
The following example shows part of a Vagrantfile that enables the VM to
|
||||
boot from a network interface first and a hard disk second. This could be
|
||||
used to run VMs that are meant to be a PXE booted machines.
|
||||
|
||||
```ruby
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.define :pxeclient do |pxeclient|
|
||||
pxeclient.vm.box = "centos64"
|
||||
pxeclient.vm.provider :libvirt do |domain|
|
||||
domain.boot 'network'
|
||||
domain.boot 'hd'
|
||||
end
|
||||
end
|
||||
|
||||
# ...
|
||||
```
|
||||
|
||||
## Networks
|
||||
|
||||
Networking features in the form of `config.vm.network` support private networks
|
||||
concept.
|
||||
concept. It supports both the virtual network switch routing types and the point to
|
||||
point Guest OS to Guest OS setting using TCP tunnel interfaces.
|
||||
|
||||
http://wiki.libvirt.org/page/VirtualNetworking
|
||||
https://libvirt.org/formatdomain.html#elementsNICSTCP
|
||||
|
||||
Public Network interfaces are currently implemented using the macvtap driver. The macvtap
|
||||
driver is only available with the Linux Kernel version >= 2.6.24. See the following libvirt
|
||||
@ -195,14 +226,33 @@ documentation for the details of the macvtap usage.
|
||||
|
||||
http://www.libvirt.org/formatdomain.html#elementsNICSDirect
|
||||
|
||||
|
||||
An examples of network interface definitions:
|
||||
|
||||
```ruby
|
||||
# Private network
|
||||
# Private network using virtual network switching
|
||||
config.vm.define :test_vm1 do |test_vm1|
|
||||
test_vm1.vm.network :private_network, :ip => "10.20.30.40"
|
||||
end
|
||||
|
||||
# Private network. Point to Point between 2 Guest OS using a TCP tunnel
|
||||
# Guest 1
|
||||
config.vm.define :test_vm1 do |test_vm1|
|
||||
test_vm1.vm.network :private_network,
|
||||
:libvirt__tcp_tunnel_type => 'server',
|
||||
# default is 127.0.0.1 if omitted
|
||||
# :libvirt__tcp_tunnel_ip => '127.0.0.1',
|
||||
:libvirt__tcp_tunnel_port => '11111'
|
||||
|
||||
# Guest 2
|
||||
config.vm.define :test_vm2 do |test_vm2|
|
||||
test_vm2.vm.network :private_network,
|
||||
:libvirt__tcp_tunnel_type => 'client',
|
||||
# default is 127.0.0.1 if omitted
|
||||
# :libvirt__tcp_tunnel_ip => '127.0.0.1',
|
||||
:libvirt__tcp_tunnel_port => '11111'
|
||||
|
||||
|
||||
# Public Network
|
||||
config.vm.define :test_vm1 do |test_vm1|
|
||||
test_vm1.vm.network :public_network,
|
||||
@ -241,8 +291,18 @@ starts with 'libvirt__' string. Here is a list of those options:
|
||||
network 'default' is used.
|
||||
* `:libvirt__netmask` - Used only together with `:ip` option. Default is
|
||||
'255.255.255.0'.
|
||||
* `:libvirt__host_ip` - Adress to use for the host (not guest).
|
||||
Default is first possible address (after network address).
|
||||
* `:libvirt__dhcp_enabled` - If DHCP will offer addresses, or not. Used only
|
||||
when creating new network. Default is true.
|
||||
* `:libvirt__dhcp_start` - First address given out via DHCP.
|
||||
Default is third address in range (after network name and gateway).
|
||||
* `:libvirt__dhcp_stop` - Last address given out via DHCP.
|
||||
Default is last possible address in range (before broadcast address).
|
||||
* `:libvirt__dhcp_bootp_file` - The file to be used for the boot image.
|
||||
Used only when dhcp is enabled.
|
||||
* `:libvirt__dhcp_bootp_server` - The server that runs the DHCP server.
|
||||
Used only when dhcp is enabled.By default is the same host that runs the DHCP server.
|
||||
* `:libvirt__adapter` - Number specifiyng sequence number of interface.
|
||||
* `:libvirt__forward_mode` - Specify one of `veryisolated`, `none`, `nat` or `route` options.
|
||||
This option is used only when creating new network. Mode `none` will create
|
||||
@ -254,8 +314,18 @@ starts with 'libvirt__' string. Here is a list of those options:
|
||||
* `:libvirt__forward_device` - Name of interface/device, where network should
|
||||
be forwarded (NATed or routed). Used only when creating new network. By
|
||||
default, all physical interfaces are used.
|
||||
* `:libvirt_tcp_tunnel_type` - Set it to "server" or "client" to enable TCP
|
||||
tunnel interface configuration. This configuration type uses TCP tunnels to
|
||||
generate point to point connections between Guests. Useful for Switch VMs like
|
||||
Cumulus Linux. No virtual switch setting like "libvirt__network_name" applies with TCP
|
||||
tunnel interfaces and will be ignored if configured.
|
||||
* `:libvirt_tcp_tunnel_ip` - Sets the source IP of the TCP Tunnel interface. By
|
||||
default this is `127.0.0.1`
|
||||
* `:libvirt_tcp_tunnel_port` - Sets the TCP Tunnel interface port that either
|
||||
the client will connect to, or the server will listen on.
|
||||
* `:mac` - MAC address for the interface.
|
||||
* `model_type` - parameter specifies the model of the network adapter when you create a domain value by default virtio KVM believe possible values, see the documentation for libvirt
|
||||
* `:model_type` - parameter specifies the model of the network adapter when you create a domain value by default virtio KVM believe possible values, see the documentation for libvirt
|
||||
|
||||
|
||||
When the option `:libvirt__dhcp_enabled` is to to 'false' it shouldn't matter
|
||||
whether the virtual network contains a DHCP server or not and vagrant-libvirt
|
||||
@ -301,6 +371,7 @@ You can create and attach additional disks to a VM via `libvirt.storage :file`.
|
||||
* `type` - Type of disk image to create. Defaults to *qcow2*.
|
||||
* `bus` - Type of bus to connect device to. Defaults to *virtio*.
|
||||
* `cache` - Cache mode to use, e.g. `none`, `writeback`, `writethrough` (see the [libvirt documentation for possible values](http://libvirt.org/formatdomain.html#elementsDisks) or [here](https://www.suse.com/documentation/sles11/book_kvm/data/sect1_chapter_book_kvm.html) for a fuller explanation). Defaults to *default*.
|
||||
* `allow_existing` - Set to true if you want to allow the VM to use a pre-existing disk. This is useful for sharing disks between VMs, e.g. in order to simulate shared SAN storage. Shared disks removed only manualy.If not exists - will created. If exists - using existed.
|
||||
|
||||
The following example creates two additional disks.
|
||||
|
||||
@ -379,6 +450,13 @@ it an setting the type, e.g.
|
||||
|
||||
config.vm.synced_folder './', '/vagrant', type: 'rsync'
|
||||
|
||||
or
|
||||
|
||||
config.vm.synced_folder './', '/vagrant', type: '9p', disabled: false, accessmode: "squash", owner: "vagrant"
|
||||
|
||||
**SECURITY NOTE:** for remote libvirt, nfs synced folders requires a bridged public network interface and you must connect to libvirt via ssh.
|
||||
|
||||
|
||||
## Customized Graphics
|
||||
|
||||
vagrant-libvirt supports customizing the display and video settings of the
|
||||
@ -408,12 +486,13 @@ The box is a tarball containing:
|
||||
* `Vagrantfile` that does default settings for the provider-specific configuration for this provider.
|
||||
|
||||
## Create Box
|
||||
This script creates a vagrant-libvirt box from a qcow2 file:
|
||||
To create a vagrant-libvirt box from a qcow2 image, run `create_box.sh` (located in the tools directory):
|
||||
|
||||
Usage:
|
||||
```$ create_box.sh ubuntu14.qcow2```
|
||||
|
||||
```create_box.sh ubuntu14.qcow2```
|
||||
Used Packer to create the qcow2 images, templates available at https://github.com/jakobadam/packer-qemu-templates
|
||||
You can also create a box by using [Packer](https://packer.io). Packer templates for use with vagrant-libvirt are available at https://github.com/jakobadam/packer-qemu-templates. After cloning that project you can build a vagrant-libvirt box by running:
|
||||
|
||||
``` ~/packer-qemu-templates/ubuntu$ packer build ubuntu-14.04-server-amd64-vagrant.json```
|
||||
|
||||
## Development
|
||||
|
||||
@ -457,4 +536,3 @@ IMPORTANT NOTE: bundle is crucial. You need to use bundled vagrant.
|
||||
3. Commit your changes (`git commit -am 'Add some feature'`).
|
||||
4. Push to the branch (`git push origin my-new-feature`).
|
||||
5. Create new Pull Request.
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
require 'pathname'
|
||||
require 'vagrant-libvirt/plugin'
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
@ -27,3 +26,6 @@ module VagrantPlugins
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# make sure base module class defined before loading plugin
|
||||
require 'vagrant-libvirt/plugin'
|
||||
|
@ -8,6 +8,13 @@ module VagrantPlugins
|
||||
include Vagrant::Action::Builtin
|
||||
@logger = Log4r::Logger.new('vagrant_libvirt::action')
|
||||
|
||||
# remove image from libvirt storage pool
|
||||
def self.remove_libvirt_image
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use RemoveLibvirtImage
|
||||
end
|
||||
end
|
||||
|
||||
# This action is called to bring the box up from nothing.
|
||||
def self.action_up
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
@ -24,27 +31,18 @@ module VagrantPlugins
|
||||
b2.use CreateDomain
|
||||
|
||||
b2.use Provision
|
||||
b2.use CreateNetworks
|
||||
b2.use CreateNetworkInterfaces
|
||||
|
||||
|
||||
b2.use PrepareNFSValidIds
|
||||
b2.use SyncedFolderCleanup
|
||||
b2.use SyncedFolders
|
||||
|
||||
b2.use StartDomain
|
||||
b2.use WaitTillUp
|
||||
|
||||
b2.use StartDomain
|
||||
b2.use WaitTillUp
|
||||
|
||||
|
||||
|
||||
|
||||
b2.use ForwardPorts
|
||||
|
||||
b2.use PrepareNFSSettings
|
||||
b2.use ShareFolders
|
||||
b2.use CreateNetworks
|
||||
b2.use CreateNetworkInterfaces
|
||||
|
||||
b2.use StartDomain
|
||||
b2.use WaitTillUp
|
||||
|
||||
b2.use ForwardPorts
|
||||
b2.use SetHostname
|
||||
# b2.use SyncFolders
|
||||
else
|
||||
@ -83,7 +81,6 @@ module VagrantPlugins
|
||||
b3.use SyncedFolderCleanup
|
||||
b3.use SyncedFolders
|
||||
|
||||
|
||||
# Start it..
|
||||
b3.use StartDomain
|
||||
|
||||
@ -91,11 +88,9 @@ module VagrantPlugins
|
||||
# so wait for dhcp lease and store IP into machines data_dir.
|
||||
b3.use WaitTillUp
|
||||
|
||||
|
||||
b3.use ForwardPorts
|
||||
b3.use PrepareNFSSettings
|
||||
b3.use ShareFolders
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -147,8 +142,10 @@ module VagrantPlugins
|
||||
|
||||
# not implemented and looks like not require
|
||||
def self.action_package
|
||||
lambda do |env|
|
||||
raise Errors::PackageNotSupported
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use ConfigValidate
|
||||
b.use ConnectLibvirt
|
||||
b.use PackageDomain
|
||||
end
|
||||
end
|
||||
|
||||
@ -159,7 +156,14 @@ module VagrantPlugins
|
||||
b.use ConfigValidate
|
||||
b.use Call, IsCreated do |env, b2|
|
||||
if !env[:result]
|
||||
b2.use MessageNotCreated
|
||||
# Try to remove stale volumes anyway
|
||||
b2.use ConnectLibvirt
|
||||
b2.use SetNameOfDomain
|
||||
b2.use RemoveStaleVolume
|
||||
if !env[:result]
|
||||
b2.use MessageNotCreated
|
||||
end
|
||||
|
||||
next
|
||||
end
|
||||
|
||||
@ -168,6 +172,7 @@ module VagrantPlugins
|
||||
# b2.use PruneNFSExports
|
||||
b2.use DestroyDomain
|
||||
b2.use DestroyNetworks
|
||||
b2.use ProvisionerCleanup
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -320,6 +325,7 @@ module VagrantPlugins
|
||||
|
||||
action_root = Pathname.new(File.expand_path('../action', __FILE__))
|
||||
autoload :ConnectLibvirt, action_root.join('connect_libvirt')
|
||||
autoload :PackageDomain, action_root.join('package_domain')
|
||||
autoload :CreateDomain, action_root.join('create_domain')
|
||||
autoload :CreateDomainVolume, action_root.join('create_domain_volume')
|
||||
autoload :CreateNetworkInterfaces, action_root.join('create_network_interfaces')
|
||||
@ -331,6 +337,7 @@ module VagrantPlugins
|
||||
autoload :HaltDomain, action_root.join('halt_domain')
|
||||
autoload :HandleBoxImage, action_root.join('handle_box_image')
|
||||
autoload :HandleStoragePool, action_root.join('handle_storage_pool')
|
||||
autoload :RemoveLibvirtImage, action_root.join('remove_libvirt_image')
|
||||
autoload :IsCreated, action_root.join('is_created')
|
||||
autoload :IsRunning, action_root.join('is_running')
|
||||
autoload :IsSuspended, action_root.join('is_suspended')
|
||||
@ -339,6 +346,8 @@ module VagrantPlugins
|
||||
autoload :MessageNotRunning, action_root.join('message_not_running')
|
||||
autoload :MessageNotSuspended, action_root.join('message_not_suspended')
|
||||
|
||||
autoload :RemoveStaleVolume, action_root.join('remove_stale_volume')
|
||||
|
||||
autoload :PrepareNFSSettings, action_root.join('prepare_nfs_settings')
|
||||
autoload :PrepareNFSValidIds, action_root.join('prepare_nfs_valid_ids')
|
||||
autoload :PruneNFSExports, action_root.join('prune_nfs_exports')
|
||||
@ -362,6 +371,7 @@ module VagrantPlugins
|
||||
autoload :HandleBox, 'vagrant/action/builtin/handle_box'
|
||||
autoload :SyncedFolders, 'vagrant/action/builtin/synced_folders'
|
||||
autoload :SyncedFolderCleanup, 'vagrant/action/builtin/synced_folder_cleanup'
|
||||
autoload :ProvisionerCleanup, 'vagrant/action/builtin/provisioner_cleanup'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
require 'fog'
|
||||
require 'fog/libvirt'
|
||||
require 'log4r'
|
||||
|
||||
module VagrantPlugins
|
||||
|
@ -3,7 +3,6 @@ require 'log4r'
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Action
|
||||
|
||||
class CreateDomain
|
||||
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
||||
|
||||
@ -13,15 +12,17 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def _disk_name(name, disk)
|
||||
return "#{name}-#{disk[:device]}.#{disk[:type]}" # disk name
|
||||
"#{name}-#{disk[:device]}.#{disk[:type]}" # disk name
|
||||
end
|
||||
|
||||
def _disks_print(disks)
|
||||
return disks.collect{ |x| x[:device]+'('+x[:type]+','+x[:size]+')' }.join(', ')
|
||||
disks.collect do |x|
|
||||
"#{x[:device]}(#{x[:type]},#{x[:size]})"
|
||||
end.join(', ')
|
||||
end
|
||||
|
||||
def _cdroms_print(cdroms)
|
||||
return cdroms.collect{ |x| x[:dev] }.join(', ')
|
||||
cdroms.collect { |x| x[:dev] }.join(', ')
|
||||
end
|
||||
|
||||
def call(env)
|
||||
@ -33,9 +34,10 @@ module VagrantPlugins
|
||||
@cpus = config.cpus.to_i
|
||||
@cpu_mode = config.cpu_mode
|
||||
@machine_type = config.machine_type
|
||||
@machine_arch = config.machine_arch
|
||||
@disk_bus = config.disk_bus
|
||||
@nested = config.nested
|
||||
@memory_size = config.memory.to_i*1024
|
||||
@memory_size = config.memory.to_i * 1024
|
||||
@domain_volume_cache = config.volume_cache
|
||||
@kernel = config.kernel
|
||||
@cmd_line = config.cmd_line
|
||||
@ -52,6 +54,9 @@ module VagrantPlugins
|
||||
@video_type = config.video_type
|
||||
@video_vram = config.video_vram
|
||||
@keymap = config.keymap
|
||||
|
||||
# Boot order
|
||||
@boot_order = config.boot_order
|
||||
|
||||
# Storage
|
||||
@storage_pool_name = config.storage_pool_name
|
||||
@ -66,17 +71,19 @@ module VagrantPlugins
|
||||
|
||||
@os_type = 'hvm'
|
||||
|
||||
# Get path to domain image.
|
||||
# Get path to domain image from the storage pool selected.
|
||||
actual_volumes = env[:libvirt_compute].volumes.all.select do |x|
|
||||
x.pool_name == @storage_pool_name
|
||||
end
|
||||
domain_volume = ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].volumes.all, "#{@name}.img")
|
||||
actual_volumes,"#{@name}.img")
|
||||
raise Errors::DomainVolumeExists if domain_volume.nil?
|
||||
@domain_volume_path = domain_volume.path
|
||||
|
||||
# the default storage prefix is typically: /var/lib/libvirt/images/
|
||||
storage_prefix = File.dirname(@domain_volume_path)+'/' # steal
|
||||
storage_prefix = File.dirname(@domain_volume_path) + '/' # steal
|
||||
|
||||
@disks.each do |disk|
|
||||
|
||||
disk[:path] ||= _disk_name(@name, disk)
|
||||
|
||||
# On volume creation, the <path> element inside <target>
|
||||
@ -87,19 +94,24 @@ module VagrantPlugins
|
||||
|
||||
disk[:absolute_path] = storage_prefix + disk[:path]
|
||||
|
||||
# make the disk. equivalent to:
|
||||
# qemu-img create -f qcow2 <path> 5g
|
||||
begin
|
||||
domain_volume_disk = env[:libvirt_compute].volumes.create(
|
||||
:name => disk[:name],
|
||||
:format_type => disk[:type],
|
||||
:path => disk[:absolute_path],
|
||||
:capacity => disk[:size],
|
||||
#:allocation => ?,
|
||||
:pool_name => @storage_pool_name)
|
||||
rescue Fog::Errors::Error => e
|
||||
raise Errors::FogDomainVolumeCreateError,
|
||||
:error_message => e.message
|
||||
if env[:libvirt_compute].volumes.select {
|
||||
|x| x.name == disk[:name] and x.pool_name == @storage_pool_name}.empty?
|
||||
# make the disk. equivalent to:
|
||||
# qemu-img create -f qcow2 <path> 5g
|
||||
begin
|
||||
env[:libvirt_compute].volumes.create(
|
||||
name: disk[:name],
|
||||
format_type: disk[:type],
|
||||
path: disk[:absolute_path],
|
||||
capacity: disk[:size],
|
||||
#:allocation => ?,
|
||||
pool_name: @storage_pool_name)
|
||||
rescue Fog::Errors::Error => e
|
||||
raise Errors::FogDomainVolumeCreateError,
|
||||
error_message: e.message
|
||||
end
|
||||
else
|
||||
disk[:preexisting] = true
|
||||
end
|
||||
end
|
||||
|
||||
@ -108,31 +120,40 @@ module VagrantPlugins
|
||||
env[:ui].info(" -- Name: #{@name}")
|
||||
env[:ui].info(" -- Domain type: #{@domain_type}")
|
||||
env[:ui].info(" -- Cpus: #{@cpus}")
|
||||
env[:ui].info(" -- Memory: #{@memory_size/1024}M")
|
||||
env[:ui].info(" -- Memory: #{@memory_size / 1024}M")
|
||||
env[:ui].info(" -- Base box: #{env[:machine].box.name}")
|
||||
env[:ui].info(" -- Storage pool: #{@storage_pool_name}")
|
||||
env[:ui].info(" -- Image: #{@domain_volume_path}")
|
||||
env[:ui].info(" -- Image: #{@domain_volume_path} (#{env[:box_virtual_size]}G)")
|
||||
env[:ui].info(" -- Volume Cache: #{@domain_volume_cache}")
|
||||
env[:ui].info(" -- Kernel: #{@kernel}")
|
||||
env[:ui].info(" -- Initrd: #{@initrd}")
|
||||
env[:ui].info(" -- Graphics Type: #{@graphics_type}")
|
||||
env[:ui].info(" -- Graphics Port: #{@graphics_port}")
|
||||
env[:ui].info(" -- Graphics IP: #{@graphics_ip}")
|
||||
env[:ui].info(" -- Graphics Password: #{@graphics_passwd.empty? ? 'Not defined': 'Defined'}")
|
||||
env[:ui].info(" -- Graphics Password: #{@graphics_passwd.empty? ? 'Not defined' : 'Defined'}")
|
||||
env[:ui].info(" -- Video Type: #{@video_type}")
|
||||
env[:ui].info(" -- Video VRAM: #{@video_vram}")
|
||||
env[:ui].info(" -- Keymap: #{@keymap}")
|
||||
|
||||
@boot_order.each do |device|
|
||||
env[:ui].info(" -- Boot device: #{device}")
|
||||
end
|
||||
|
||||
if @disks.length > 0
|
||||
env[:ui].info(" -- Disks: #{_disks_print(@disks)}")
|
||||
end
|
||||
|
||||
@disks.each do |disk|
|
||||
env[:ui].info(" -- Disk(#{disk[:device]}): #{disk[:absolute_path]}")
|
||||
msg = " -- Disk(#{disk[:device]}): #{disk[:absolute_path]}"
|
||||
msg += " (shared. Remove only manualy)" if disk[:allow_existing]
|
||||
msg += " Not created - using existed." if disk[:preexisting]
|
||||
env[:ui].info(msg)
|
||||
end
|
||||
|
||||
if @cdroms.length > 0
|
||||
env[:ui].info(" -- CDROMS: #{_cdroms_print(@cdroms)}")
|
||||
end
|
||||
|
||||
@cdroms.each do |cdrom|
|
||||
env[:ui].info(" -- CDROM(#{cdrom[:dev]}): #{cdrom[:path]}")
|
||||
end
|
||||
@ -146,10 +167,9 @@ module VagrantPlugins
|
||||
# existing volume? Use domain creation from template..
|
||||
begin
|
||||
server = env[:libvirt_compute].servers.create(
|
||||
:xml => to_xml('domain'))
|
||||
xml: to_xml('domain'))
|
||||
rescue Fog::Errors::Error => e
|
||||
raise Errors::FogCreateServerError,
|
||||
:error_message => e.message
|
||||
raise Errors::FogCreateServerError, error_message: e.message
|
||||
end
|
||||
|
||||
# Immediately save the ID since it is created at this point.
|
||||
@ -158,7 +178,6 @@ module VagrantPlugins
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -34,8 +34,8 @@ module VagrantPlugins
|
||||
env[:libvirt_compute].volumes.all, env[:box_volume_name])
|
||||
@backing_file = box_volume.path
|
||||
|
||||
# Virtual size of image. Same as box image size.
|
||||
@capacity = env[:machine].box.metadata['virtual_size'] #G
|
||||
# Virtual size of image. Take value worked out by HandleBoxImage
|
||||
@capacity = env[:box_virtual_size] #G
|
||||
|
||||
# Create new volume from xml template. Fog currently doesn't support
|
||||
# volume snapshots directly.
|
||||
|
@ -19,6 +19,8 @@ module VagrantPlugins
|
||||
@management_network_name = env[:machine].provider_config.management_network_name
|
||||
config = env[:machine].provider_config
|
||||
@nic_model_type = config.nic_model_type
|
||||
@nic_adapter_count = config.nic_adapter_count
|
||||
@boot_order = config.boot_order
|
||||
@app = app
|
||||
end
|
||||
|
||||
@ -36,7 +38,6 @@ module VagrantPlugins
|
||||
adapters = []
|
||||
|
||||
# Vagrant gives you adapter 0 by default
|
||||
|
||||
# Assign interfaces to slots.
|
||||
configured_networks(env, @logger).each do |options|
|
||||
|
||||
@ -70,7 +71,6 @@ module VagrantPlugins
|
||||
@mac = iface_configuration.fetch(:mac, false)
|
||||
@model_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
||||
template_name = 'interface'
|
||||
|
||||
# Configuration for public interfaces which use the macvtap driver
|
||||
if iface_configuration[:iface_type] == :public_network
|
||||
@device = iface_configuration.fetch(:dev, 'eth0')
|
||||
@ -80,8 +80,18 @@ module VagrantPlugins
|
||||
template_name = 'public_interface'
|
||||
@logger.info("Setting up public interface using device #{@device} in mode #{@mode}")
|
||||
@ovs = iface_configuration.fetch(:ovs, false)
|
||||
# configuration for tcp tunnel interfaces (p2p conn btwn guest OSes)
|
||||
elsif iface_configuration.fetch(:tcp_tunnel_type, nil)
|
||||
@tcp_tunnel_port = iface_configuration.fetch(:tcp_tunnel_port, nil)
|
||||
raise Errors::TcpTunnelPortNotDefined if @tcp_tunnel_port.nil?
|
||||
@tcp_tunnel_ip = iface_configuration.fetch(:tcp_tunnel_address, '127.0.0.1')
|
||||
@type = iface_configuration.fetch(:tcp_tunnel_type)
|
||||
@model_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
||||
template_name = 'tcp_tunnel_interface'
|
||||
@logger.info("Setting up #{@type} tunnel interface using #{@tcp_tunnel_ip} port #{@tcp_tunnel_port}")
|
||||
end
|
||||
|
||||
|
||||
message = "Creating network interface eth#{@iface_number}"
|
||||
message << " connected to network #{@network_name}."
|
||||
if @mac
|
||||
@ -96,6 +106,21 @@ module VagrantPlugins
|
||||
raise Errors::AttachDeviceError,
|
||||
:error_message => e.message
|
||||
end
|
||||
|
||||
# Re-read the network configuration and grab the MAC address
|
||||
if !@mac
|
||||
xml = Nokogiri::XML(domain.xml_desc)
|
||||
if iface_configuration[:iface_type] == :public_network
|
||||
if @type == 'direct'
|
||||
@mac = xml.xpath("/domain/devices/interface[source[@dev='#{@device}']]/mac/@address")
|
||||
else
|
||||
@mac = xml.xpath("/domain/devices/interface[source[@bridge='#{@device}']]/mac/@address")
|
||||
end
|
||||
else
|
||||
@mac = xml.xpath("/domain/devices/interface[source[@network='#{@network_name}']]/mac/@address")
|
||||
end
|
||||
iface_configuration[:mac] = @mac.to_s
|
||||
end
|
||||
end
|
||||
|
||||
# Continue the middleware chain.
|
||||
@ -116,7 +141,7 @@ module VagrantPlugins
|
||||
network = {
|
||||
:interface => slot_number,
|
||||
:use_dhcp_assigned_default_route => options[:use_dhcp_assigned_default_route],
|
||||
#:mac => ...,
|
||||
:mac_address => options[:mac],
|
||||
}
|
||||
|
||||
if options[:ip]
|
||||
@ -129,6 +154,9 @@ module VagrantPlugins
|
||||
network[:type] = :dhcp
|
||||
end
|
||||
|
||||
# do not run configure_networks for tcp tunnel interfaces
|
||||
next if options.fetch(:tcp_tunnel_type, nil)
|
||||
|
||||
networks_to_configure << network
|
||||
end
|
||||
|
||||
@ -139,7 +167,7 @@ module VagrantPlugins
|
||||
|
||||
private
|
||||
|
||||
def find_empty(array, start=0, stop=8)
|
||||
def find_empty(array, start=0, stop=@nic_adapter_count)
|
||||
(start..stop).each do |i|
|
||||
return i if !array[i]
|
||||
end
|
||||
@ -148,6 +176,9 @@ module VagrantPlugins
|
||||
|
||||
# Return network name according to interface options.
|
||||
def interface_network(libvirt_client, options)
|
||||
# no need to get interface network for tcp tunnel config
|
||||
return 'tcp_tunnel' if options.fetch(:tcp_tunnel_type, nil)
|
||||
|
||||
if options[:network_name]
|
||||
@logger.debug "Found network by name"
|
||||
return options[:network_name]
|
||||
|
@ -35,7 +35,8 @@ module VagrantPlugins
|
||||
# available, create it if possible. Otherwise raise an error.
|
||||
configured_networks(env, @logger).each do |options|
|
||||
# Only need to create private networks
|
||||
next if options[:iface_type] != :private_network
|
||||
next if options[:iface_type] != :private_network or
|
||||
options.fetch(:tcp_tunnel_type, nil)
|
||||
@logger.debug "Searching for network with options #{options}"
|
||||
|
||||
# should fix other methods so this doesn't have to be instance var
|
||||
@ -44,7 +45,8 @@ module VagrantPlugins
|
||||
# Get a list of all (active and inactive) libvirt networks. This
|
||||
# list is used throughout this class and should be easier to
|
||||
# process than libvirt API calls.
|
||||
@available_networks = libvirt_networks(env[:libvirt_compute].client)
|
||||
@available_networks = libvirt_networks(
|
||||
env[:libvirt_compute].client)
|
||||
|
||||
# Prepare a hash describing network for this specific interface.
|
||||
@interface_network = {
|
||||
@ -56,19 +58,16 @@ module VagrantPlugins
|
||||
created: false,
|
||||
active: false,
|
||||
autostart: false,
|
||||
libvirt_network: nil,
|
||||
libvirt_network: nil
|
||||
}
|
||||
|
||||
if @options[:ip]
|
||||
handle_ip_option(env)
|
||||
# in vagrant 1.2.3 and later it is not possible to take this branch
|
||||
# because cannot have name without ip
|
||||
# https://github.com/mitchellh/vagrant/commit/cf2f6da4dbcb4f57c9cdb3b94dcd0bba62c5f5fd
|
||||
elsif @options[:network_name]
|
||||
handle_network_name_option
|
||||
handle_network_name_option(env)
|
||||
end
|
||||
|
||||
autostart_network if !@interface_network[:autostart]
|
||||
autostart_network if @interface_network[:autostart]
|
||||
activate_network if !@interface_network[:active]
|
||||
end
|
||||
end
|
||||
@ -78,11 +77,25 @@ module VagrantPlugins
|
||||
|
||||
private
|
||||
|
||||
def lookup_network_by_ip(ip)
|
||||
@logger.debug "looking up network with ip == #{ip}"
|
||||
@available_networks.each do |network|
|
||||
if network[:network_address] == ip
|
||||
@logger.debug "found existing network by ip: #{network}"
|
||||
return network
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
# Return hash of network for specified name, or nil if not found.
|
||||
def lookup_network_by_name(network_name)
|
||||
@logger.debug "looking up network named #{network_name}"
|
||||
@available_networks.each do |network|
|
||||
return network if network[:name] == network_name
|
||||
if network[:name] == network_name
|
||||
@logger.debug "found existing network by name: #{network}"
|
||||
return network
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
@ -114,31 +127,38 @@ module VagrantPlugins
|
||||
# @available_networks should be filled before calling this function.
|
||||
def handle_ip_option(env)
|
||||
return if !@options[:ip]
|
||||
net_address = nil
|
||||
if @options[:forward_mode] != 'veryisolated'
|
||||
net_address = network_address(@options[:ip], @options[:netmask])
|
||||
# Set IP address of network (actually bridge). It will be used as
|
||||
# gateway address for machines connected to this network.
|
||||
net = IPAddr.new(net_address)
|
||||
|
||||
# Default to first address (after network name)
|
||||
@interface_network[:ip_address] = @options[:host_ip].nil? ? \
|
||||
net.to_range.begin.succ : \
|
||||
IPAddr.new(@options[:host_ip])
|
||||
end
|
||||
|
||||
net_address = network_address(@options[:ip], @options[:netmask])
|
||||
@interface_network[:network_address] = net_address
|
||||
|
||||
# Set IP address of network (actually bridge). It will be used as
|
||||
# gateway address for machines connected to this network.
|
||||
net = IPAddr.new(net_address)
|
||||
@interface_network[:ip_address] = net.to_range.begin.succ
|
||||
|
||||
# Is there an available network matching to configured ip
|
||||
# address?
|
||||
@available_networks.each do |available_network|
|
||||
if available_network[:network_address] == \
|
||||
@interface_network[:network_address]
|
||||
@interface_network = available_network
|
||||
@logger.debug "found existing network by ip, values are"
|
||||
@logger.debug @interface_network
|
||||
break
|
||||
end
|
||||
# if network is veryisolated, search by name
|
||||
if @options[:libvirt__forward_mode] == "veryisolated"
|
||||
network = lookup_network_by_name(@options[:network_name])
|
||||
elsif net_address
|
||||
# otherwise, search by ip (if set)
|
||||
network = lookup_network_by_ip(net_address)
|
||||
else
|
||||
# leaving this here to mimic prior behavior. If we get
|
||||
# here, something's probably broken.
|
||||
network = lookup_network_by_name(@options[:network_name])
|
||||
end
|
||||
@interface_network = network if network
|
||||
|
||||
if @interface_network[:created]
|
||||
verify_dhcp
|
||||
end
|
||||
|
||||
|
||||
if @options[:network_name]
|
||||
@logger.debug "Checking that network name does not clash with ip"
|
||||
if @interface_network[:created]
|
||||
@ -157,13 +177,13 @@ module VagrantPlugins
|
||||
ip_address: @options[:ip],
|
||||
network_name: @options[:network_name]
|
||||
end
|
||||
|
||||
|
||||
# Network with 'name' doesn't exist. Set it as name for new
|
||||
# network.
|
||||
@interface_network[:name] = @options[:network_name]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Do we need to create new network?
|
||||
if !@interface_network[:created]
|
||||
|
||||
@ -206,15 +226,39 @@ module VagrantPlugins
|
||||
# Handle network_name option, if ip was not specified. Variables
|
||||
# @options and @available_networks should be filled before calling this
|
||||
# function.
|
||||
def handle_network_name_option
|
||||
return if @options[:ip] || !@options[:network_name]
|
||||
def handle_network_name_option(env)
|
||||
return if @options[:ip] || \
|
||||
!@options[:network_name] || \
|
||||
!@options[:libvirt__forward_mode] == "veryisolated"
|
||||
|
||||
@interface_network = lookup_network_by_name(@options[:network_name])
|
||||
if !@interface_network
|
||||
network = lookup_network_by_name(@options[:network_name])
|
||||
@interface_network = network if network
|
||||
|
||||
# if this interface has a network address, something's wrong.
|
||||
if @interface_network[:network_address]
|
||||
raise Errors::NetworkNotAvailableError,
|
||||
network_name: @options[:network_name]
|
||||
else
|
||||
verify_dhcp
|
||||
end
|
||||
|
||||
# Do we need to create new network?
|
||||
if !@interface_network[:created]
|
||||
@interface_network[:name] = @options[:network_name]
|
||||
|
||||
# Generate a unique name for network bridge.
|
||||
count = 0
|
||||
while @interface_network[:bridge_name].nil?
|
||||
@logger.debug "generating name for bridge"
|
||||
bridge_name = 'virbr'
|
||||
bridge_name << count.to_s
|
||||
count += 1
|
||||
|
||||
next if lookup_bridge_by_name(bridge_name)
|
||||
|
||||
@interface_network[:bridge_name] = bridge_name
|
||||
end
|
||||
|
||||
# Create a private network.
|
||||
create_private_network(env)
|
||||
end
|
||||
end
|
||||
|
||||
@ -233,18 +277,19 @@ module VagrantPlugins
|
||||
# Find out DHCP addresses pool range.
|
||||
network_address = "#{@interface_network[:network_address]}/"
|
||||
network_address << "#{@interface_network[:netmask]}"
|
||||
net = IPAddr.new(network_address)
|
||||
net = @interface_network[:network_address] ? IPAddr.new(network_address) : nil
|
||||
|
||||
# First is address of network, second is gateway.
|
||||
# Start the range two
|
||||
# addresses after network address.
|
||||
# First is address of network, second is gateway (by default).
|
||||
# So start the range two addresses after network address by default.
|
||||
# TODO: Detect if this IP is not set on the interface.
|
||||
start_address = net.to_range.begin.succ.succ
|
||||
start_address = @options[:dhcp_start] || net.to_range.begin.succ
|
||||
|
||||
# Stop address must not be broadcast.
|
||||
stop_address = net.to_range.end & IPAddr.new('255.255.255.254')
|
||||
# Default to last possible address. (Stop address must not be broadcast address.)
|
||||
stop_address = @options[:dhcp_stop] || (net.to_range.end & IPAddr.new('255.255.255.254'))
|
||||
|
||||
@network_dhcp_enabled = true
|
||||
@network_dhcp_bootp_file = @options[:dhcp_bootp_file]
|
||||
@network_dhcp_bootp_server = @options[:dhcp_bootp_server]
|
||||
@network_range_start = start_address
|
||||
@network_range_stop = stop_address
|
||||
else
|
||||
|
@ -4,7 +4,7 @@ module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Action
|
||||
class DestroyDomain
|
||||
def initialize(app, env)
|
||||
def initialize(app, _env)
|
||||
@logger = Log4r::Logger.new('vagrant_libvirt::action::destroy_domain')
|
||||
@app = app
|
||||
end
|
||||
@ -17,7 +17,8 @@ module VagrantPlugins
|
||||
# Fog libvirt currently doesn't support snapshots. Use
|
||||
# ruby-libvirt client directly. Note this is racy, see
|
||||
# http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotListNames
|
||||
libvirt_domain = env[:libvirt_compute].client.lookup_domain_by_uuid(env[:machine].id)
|
||||
libvirt_domain = env[:libvirt_compute].client.lookup_domain_by_uuid(
|
||||
env[:machine].id)
|
||||
libvirt_domain.list_snapshots.each do |name|
|
||||
@logger.info("Deleting snapshot '#{name}'")
|
||||
begin
|
||||
@ -28,7 +29,39 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
domain.destroy(destroy_volumes: true)
|
||||
|
||||
if env[:machine].provider_config.disks.empty?
|
||||
# if using default configuration of disks
|
||||
domain.destroy(destroy_volumes: true)
|
||||
else
|
||||
domain.destroy(destroy_volumes: false)
|
||||
|
||||
env[:machine].provider_config.disks.each do |disk|
|
||||
# shared disks remove only manualy or ???
|
||||
next if disk[:allow_existing]
|
||||
diskname = libvirt_domain.name + '-' + disk[:device] + '.' + disk[:type].to_s
|
||||
# diskname is uniq
|
||||
libvirt_disk = domain.volumes.select do |x|
|
||||
x.name == diskname
|
||||
end.first
|
||||
if libvirt_disk
|
||||
libvirt_disk.destroy
|
||||
elsif disk[:path]
|
||||
poolname = env[:machine].provider_config.storage_pool_name
|
||||
libvirt_disk = domain.volumes.select do |x|
|
||||
# FIXME can remove pool/target.img and pool/123/target.img
|
||||
x.path =~ /\/#{disk[:path]}$/ && x.pool_name == poolname
|
||||
end.first
|
||||
libvirt_disk.destroy if libvirt_disk
|
||||
end
|
||||
end
|
||||
|
||||
# remove root storage
|
||||
root_disk = domain.volumes.select do |x|
|
||||
x.name == libvirt_domain.name + '.img'
|
||||
end.first
|
||||
root_disk.destroy if root_disk
|
||||
end
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
|
@ -37,9 +37,29 @@ module VagrantPlugins
|
||||
env[:box_volume_name] = env[:machine].box.name.to_s.dup.gsub("/", "-VAGRANTSLASH-")
|
||||
env[:box_volume_name] << "_vagrant_box_image_#{env[:machine].box.version.to_s rescue ''}.img"
|
||||
|
||||
# Override box_virtual_size
|
||||
if config.machine_virtual_size
|
||||
if config.machine_virtual_size < box_virtual_size
|
||||
# Warn that a virtual size less than the box metadata size
|
||||
# is not supported and will be ignored
|
||||
env[:ui].warn I18n.t(
|
||||
'vagrant_libvirt.warnings.ignoring_virtual_size_too_small',
|
||||
requested: config.machine_virtual_size, minimum: box_virtual_size
|
||||
)
|
||||
else
|
||||
env[:ui].info I18n.t('vagrant_libvirt.manual_resize_required')
|
||||
box_virtual_size = config.machine_virtual_size
|
||||
end
|
||||
end
|
||||
# save for use by later actions
|
||||
env[:box_virtual_size] = box_virtual_size
|
||||
|
||||
# while inside the synchronize block take care not to call the next
|
||||
# action in the chain, as must exit this block first to prevent
|
||||
# locking all subsequent actions as well.
|
||||
@@lock.synchronize do
|
||||
# Don't continue if image already exists in storage pool.
|
||||
return @app.call(env) if ProviderLibvirt::Util::Collection.find_matching(
|
||||
break if ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].volumes.all, env[:box_volume_name])
|
||||
|
||||
# Box is not available as a storage pool volume. Create and upload
|
||||
@ -123,11 +143,7 @@ module VagrantPlugins
|
||||
:error_message => e.message
|
||||
end
|
||||
|
||||
if progress == image_size
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
return progress == image_size
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -14,14 +14,16 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def call(env)
|
||||
@@lock.synchronize do
|
||||
# Get config options.
|
||||
config = env[:machine].provider_config
|
||||
# Get config options.
|
||||
config = env[:machine].provider_config
|
||||
|
||||
# while inside the synchronize block take care not to call the next
|
||||
# action in the chain, as must exit this block first to prevent
|
||||
# locking all subsequent actions as well.
|
||||
@@lock.synchronize do
|
||||
# Check for storage pool, where box image should be created
|
||||
fog_pool = ProviderLibvirt::Util::Collection.find_matching(
|
||||
break if ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].pools.all, config.storage_pool_name)
|
||||
return @app.call(env) if fog_pool
|
||||
|
||||
@logger.info("No storage pool '#{config.storage_pool_name}' is available.")
|
||||
|
||||
|
83
lib/vagrant-libvirt/action/package_domain.rb
Normal file
83
lib/vagrant-libvirt/action/package_domain.rb
Normal file
@ -0,0 +1,83 @@
|
||||
require 'log4r'
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Action
|
||||
# Action for create new box for libvirt provider
|
||||
class PackageDomain
|
||||
def initialize(app, env)
|
||||
@logger = Log4r::Logger.new('vagrant_libvirt::action::package_domain')
|
||||
@app = app
|
||||
env['package.files'] ||= {}
|
||||
env['package.output'] ||= 'package.box'
|
||||
end
|
||||
|
||||
def call(env)
|
||||
env[:ui].info(I18n.t('vagrant_libvirt.package_domain'))
|
||||
libvirt_domain = env[:libvirt_compute].client.lookup_domain_by_uuid(
|
||||
env[:machine].id)
|
||||
domain = env[:libvirt_compute].servers.get(env[:machine].id.to_s)
|
||||
root_disk = domain.volumes.select do |x|
|
||||
x.name == libvirt_domain.name + '.img'
|
||||
end.first
|
||||
boxname = env['package.output']
|
||||
raise "#{boxname}: Already exists" if File.exists?(boxname)
|
||||
@tmp_dir = Dir.pwd + '/_tmp_package'
|
||||
@tmp_img = @tmp_dir + '/box.img'
|
||||
Dir.mkdir(@tmp_dir)
|
||||
if File.readable?(root_disk.path)
|
||||
backing = `qemu-img info "#{root_disk.path}" | grep 'backing file:' | cut -d ':' -f2`.chomp
|
||||
else
|
||||
env[:ui].error("Require set read access to #{root_disk.path}. sudo chmod a+r #{root_disk.path}")
|
||||
FileUtils.rm_rf(@tmp_dir)
|
||||
raise 'Have no access'
|
||||
end
|
||||
env[:ui].info('Image has backing image, copying image and rebasing ...')
|
||||
FileUtils.cp(root_disk.path, @tmp_img)
|
||||
`qemu-img rebase -p -b "" #{@tmp_img}`
|
||||
# remove hw association with interface
|
||||
# working for centos with lvs default disks
|
||||
`virt-sysprep --no-logfile --operations defaults,-ssh-userdir -a #{@tmp_img} `
|
||||
Dir.chdir(@tmp_dir)
|
||||
img_size = `qemu-img info #{@tmp_img} | grep 'virtual size' | awk '{print $3;}' | tr -d 'G'`.chomp
|
||||
File.write(@tmp_dir + '/metadata.json', metadata_content(img_size))
|
||||
File.write(@tmp_dir + '/Vagrantfile',vagrantfile_content)
|
||||
assebmle_box(boxname)
|
||||
FileUtils.mv(@tmp_dir + '/' + boxname, '../' + boxname)
|
||||
FileUtils.rm_rf(@tmp_dir)
|
||||
env[:ui].info('Box created')
|
||||
env[:ui].info('You can now add the box:')
|
||||
env[:ui].info("vagrant box add #{boxname} --name any_comfortable_name")
|
||||
@app.call(env)
|
||||
end
|
||||
|
||||
def assebmle_box(boxname)
|
||||
`tar cvzf "#{boxname}" --totals ./metadata.json ./Vagrantfile ./box.img`
|
||||
end
|
||||
|
||||
def vagrantfile_content
|
||||
<<-EOF
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.provider :libvirt do |libvirt|
|
||||
libvirt.driver = "kvm"
|
||||
libvirt.host = ""
|
||||
libvirt.connect_via_ssh = false
|
||||
libvirt.storage_pool_name = "default"
|
||||
end
|
||||
end
|
||||
EOF
|
||||
end
|
||||
|
||||
def metadata_content(filesize)
|
||||
<<-EOF
|
||||
{
|
||||
"provider": "libvirt",
|
||||
"format": "qcow2",
|
||||
"virtual_size": #{filesize}
|
||||
}
|
||||
EOF
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,10 +1,13 @@
|
||||
require 'nokogiri'
|
||||
require 'socket'
|
||||
require 'timeout'
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Action
|
||||
class PrepareNFSSettings
|
||||
include Vagrant::Action::Builtin::MixinSyncedFolders
|
||||
|
||||
|
||||
def initialize(app,env)
|
||||
@app = app
|
||||
@logger = Log4r::Logger.new("vagrant::action::vm::nfs")
|
||||
@ -16,8 +19,8 @@ module VagrantPlugins
|
||||
|
||||
if using_nfs?
|
||||
@logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP")
|
||||
env[:nfs_host_ip] = read_host_ip(env[:machine],env)
|
||||
env[:nfs_machine_ip] = env[:machine].ssh_info[:host]
|
||||
env[:nfs_machine_ip] = read_machine_ip(env[:machine])
|
||||
env[:nfs_host_ip] = read_host_ip(env[:nfs_machine_ip])
|
||||
|
||||
@logger.info("host IP: #{env[:nfs_host_ip]} machine IP: #{env[:nfs_machine_ip]}")
|
||||
|
||||
@ -32,37 +35,59 @@ module VagrantPlugins
|
||||
!!synced_folders(@machine)[:nfs]
|
||||
end
|
||||
|
||||
# Returns the IP address of the first host only network adapter
|
||||
# Returns the IP address of the host
|
||||
#
|
||||
# @param [Machine] machine
|
||||
# @return [String]
|
||||
def read_host_ip(machine,env)
|
||||
nets = env[:libvirt_compute].list_networks
|
||||
if nets.size == 1
|
||||
net = nets.first
|
||||
else
|
||||
domain = env[:libvirt_compute].servers.get(machine.id.to_s)
|
||||
xml=Nokogiri::XML(domain.to_xml)
|
||||
networkname = xml.xpath('/domain/devices/interface/source').first.attributes['network'].value.to_s
|
||||
@logger.info("Using network named #{networkname}")
|
||||
net = env[:libvirt_compute].list_networks.find {|netw| netw[:name] == networkname}
|
||||
def read_host_ip(ip)
|
||||
UDPSocket.open do |s|
|
||||
@logger.info("!!!! ALL IPs #{ip} #{ip.kind_of?(Array)}" )
|
||||
if ip.kind_of?(Array)
|
||||
s.connect(ip[0], 1)
|
||||
else
|
||||
s.connect(ip, 1)
|
||||
end
|
||||
s.addr.last
|
||||
end
|
||||
# FIXME better implement by libvirt xml parsing
|
||||
`ip addr show | grep -A 2 #{net[:bridge_name]} | grep -i 'inet ' | tr -s ' ' | cut -d' ' -f3 | cut -d'/' -f 1`.chomp
|
||||
end
|
||||
|
||||
# Returns the IP address of the guest by looking at the first
|
||||
# enabled host only network.
|
||||
# Returns the IP address of the guest
|
||||
#
|
||||
# @param [Machine] machine
|
||||
# @return [String]
|
||||
def read_machine_ip(machine)
|
||||
machine.config.vm.networks.each do |type, options|
|
||||
if type == :private_network && options[:ip].is_a?(String)
|
||||
return options[:ip]
|
||||
end
|
||||
# check host only ip
|
||||
ssh_host = machine.ssh_info[:host]
|
||||
return ssh_host if ping(ssh_host)
|
||||
|
||||
# check other ips
|
||||
command = "ip addr show | grep -i 'inet ' | grep -v '127.0.0.1' | tr -s ' ' | cut -d' ' -f3 | cut -d'/' -f 1"
|
||||
result = ""
|
||||
machine.communicate.execute(command) do |type, data|
|
||||
result << data if type == :stdout
|
||||
end
|
||||
|
||||
nil
|
||||
ips = result.chomp.split("\n")
|
||||
@logger.info("guest IPs: #{ips.join(', ')}")
|
||||
ips.each do |ip|
|
||||
next if ip == ssh_host
|
||||
return ip if ping(ip)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Check if we can open a connection to the host
|
||||
def ping(host, timeout = 3)
|
||||
timeout(timeout) do
|
||||
s = TCPSocket.new(host, 'echo')
|
||||
s.close
|
||||
end
|
||||
true
|
||||
rescue Errno::ECONNREFUSED
|
||||
true
|
||||
rescue Timeout::Error, StandardError
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -20,6 +20,7 @@ module VagrantPlugins
|
||||
|
||||
def read_ssh_info(libvirt, machine)
|
||||
return nil if machine.id.nil?
|
||||
return nil if machine.state.id != :running
|
||||
|
||||
# Find the machine
|
||||
domain = libvirt.servers.get(machine.id)
|
||||
@ -32,13 +33,23 @@ module VagrantPlugins
|
||||
|
||||
# Get IP address from dnsmasq lease file.
|
||||
ip_address = nil
|
||||
domain.wait_for(2) {
|
||||
addresses.each_pair do |type, ip|
|
||||
ip_address = ip[0] if ip[0] != nil
|
||||
begin
|
||||
domain.wait_for(2) do
|
||||
addresses.each_pair do |type, ip|
|
||||
# Multiple leases are separated with a newline, return only
|
||||
# the most recent address
|
||||
ip_address = ip[0].split("\n").first if ip[0] != nil
|
||||
end
|
||||
ip_address != nil
|
||||
end
|
||||
ip_address != nil
|
||||
}
|
||||
raise Errors::NoIpAddressError if not ip_address
|
||||
rescue Fog::Errors::TimeoutError
|
||||
@logger.info("Timeout at waiting for an ip address for machine %s" % machine.name)
|
||||
end
|
||||
|
||||
if not ip_address
|
||||
@logger.info("No lease found for machine %s" % machine.name)
|
||||
return nil
|
||||
end
|
||||
|
||||
ssh_info = {
|
||||
:host => ip_address,
|
||||
@ -46,8 +57,8 @@ module VagrantPlugins
|
||||
:forward_agent => machine.config.ssh.forward_agent,
|
||||
:forward_x11 => machine.config.ssh.forward_x11,
|
||||
}
|
||||
|
||||
ssh_info[:proxy_command] = "ssh '#{machine.provider_config.host}' -l '#{machine.provider_config.username}' nc %h %p" if machine.provider_config.connect_via_ssh
|
||||
|
||||
ssh_info[:proxy_command] = "ssh '#{machine.provider_config.host}' -l '#{machine.provider_config.username}' -i '#{machine.provider_config.id_ssh_key_file}' nc %h %p" if machine.provider_config.connect_via_ssh
|
||||
|
||||
ssh_info
|
||||
end
|
||||
|
@ -27,10 +27,17 @@ module VagrantPlugins
|
||||
end
|
||||
# Find the machine
|
||||
begin
|
||||
# Wait for libvirt to shutdown the domain
|
||||
while libvirt.servers.get(machine.id).state.to_sym == :'shutting-down' do
|
||||
@logger.info('Waiting on the machine to shut down...')
|
||||
sleep 1
|
||||
end
|
||||
|
||||
server = libvirt.servers.get(machine.id)
|
||||
if server.nil? || [:'shutting-down', :terminated].include?(server.state.to_sym)
|
||||
|
||||
if server.nil? || server.state.to_sym == :terminated
|
||||
# The machine can't be found
|
||||
@logger.info('Machine shutting down or terminated, assuming it got destroyed.')
|
||||
@logger.info('Machine terminated, assuming it got destroyed.')
|
||||
machine.id = nil
|
||||
return :not_created
|
||||
end
|
||||
|
20
lib/vagrant-libvirt/action/remove_libvirt_image.rb
Normal file
20
lib/vagrant-libvirt/action/remove_libvirt_image.rb
Normal file
@ -0,0 +1,20 @@
|
||||
require 'log4r'
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Action
|
||||
class RemoveLibvirtImage
|
||||
def initialize(app, env)
|
||||
@logger = Log4r::Logger.new("vagrant_libvirt::action::remove_libvirt_image")
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
env[:ui].info("Vagrant-libvirt plugin removed box only from you LOCAL ~/.vagrant/boxes directory")
|
||||
env[:ui].info("From libvirt storage pool you have to delete image manualy(virsh, virt-manager or by any other tool)")
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
49
lib/vagrant-libvirt/action/remove_stale_volume.rb
Normal file
49
lib/vagrant-libvirt/action/remove_stale_volume.rb
Normal file
@ -0,0 +1,49 @@
|
||||
require 'log4r'
|
||||
#require 'log4r/yamlconfigurator'
|
||||
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
module Action
|
||||
class RemoveStaleVolume
|
||||
def initialize(app, _env)
|
||||
|
||||
# log4r_config= YAML.load_file(File.join(File.dirname(__FILE__),"log4r.yaml"))
|
||||
# log_cfg = Log4r::YamlConfigurator
|
||||
# log_cfg.decode_yaml( log4r_config['log4r_config'] )
|
||||
|
||||
@logger = Log4r::Logger.new('vagrant_libvirt::action::remove_stale_volume')
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
# Remove stale server volume
|
||||
env[:ui].info(I18n.t('vagrant_libvirt.remove_stale_volume'))
|
||||
|
||||
config = env[:machine].provider_config
|
||||
# Check for storage pool, where box image should be created
|
||||
fog_pool = ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].pools.all, config.storage_pool_name)
|
||||
@logger.debug("**** Pool #{fog_pool.name}")
|
||||
|
||||
# This is name of newly created image for vm.
|
||||
name = "#{env[:domain_name]}.img"
|
||||
@logger.debug("**** Volume name #{name}")
|
||||
|
||||
# remove root storage
|
||||
box_volume = ProviderLibvirt::Util::Collection.find_matching(
|
||||
env[:libvirt_compute].volumes.all, name)
|
||||
if box_volume && box_volume.pool_name == fog_pool.name
|
||||
@logger.info("Deleting volume #{box_volume.key}")
|
||||
box_volume.destroy
|
||||
env[:result] = box_volume
|
||||
else
|
||||
env[:result] = nil
|
||||
end
|
||||
|
||||
# Continue the middleware chain.
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -43,7 +43,7 @@ module VagrantPlugins
|
||||
# @return [String] libvirt domain name
|
||||
def build_domain_name(env)
|
||||
config = env[:machine].provider_config
|
||||
domain_name =
|
||||
domain_name =
|
||||
if config.default_prefix.nil?
|
||||
env[:root_path].basename.to_s.dup
|
||||
else
|
||||
|
@ -1,3 +1,4 @@
|
||||
require "digest/md5"
|
||||
require "vagrant/util/retryable"
|
||||
|
||||
module VagrantPlugins
|
||||
@ -16,7 +17,7 @@ module VagrantPlugins
|
||||
machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
|
||||
|
||||
# Mount
|
||||
mount_tag = name.dup
|
||||
mount_tag = Digest::MD5.new.update(opts[:hostpath]).to_s[0,31]
|
||||
|
||||
mount_opts="-o trans=virtio"
|
||||
mount_opts += ",access=#{opts[:owner]}" if opts[:owner]
|
||||
|
@ -1,74 +1,71 @@
|
||||
require "log4r"
|
||||
require 'log4r'
|
||||
require 'ostruct'
|
||||
require 'nokogiri'
|
||||
require "digest/md5"
|
||||
|
||||
|
||||
require "vagrant/util/subprocess"
|
||||
require "vagrant/errors"
|
||||
require "vagrant-libvirt/errors"
|
||||
require 'vagrant/util/subprocess'
|
||||
require 'vagrant/errors'
|
||||
require 'vagrant-libvirt/errors'
|
||||
# require_relative "helper"
|
||||
|
||||
module VagrantPlugins
|
||||
module SyncedFolder9p
|
||||
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
||||
class SyncedFolder < Vagrant.plugin('2', :synced_folder)
|
||||
include Vagrant::Util
|
||||
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
||||
|
||||
def initialize(*args)
|
||||
super
|
||||
|
||||
@logger = Log4r::Logger.new("vagrant_libvirt::synced_folders::9p")
|
||||
@logger = Log4r::Logger.new('vagrant_libvirt::synced_folders::9p')
|
||||
end
|
||||
|
||||
def usable?(machine, raise_error=false)
|
||||
def usable?(machine, raise_error = false)
|
||||
# bail now if not using libvirt since checking version would throw error
|
||||
return false unless machine.provider_name == :libvirt
|
||||
|
||||
# <filesystem/> support in device attach/detach introduced in 1.2.2
|
||||
# version number format is major * 1,000,000 + minor * 1,000 + release
|
||||
libvirt_version = ProviderLibvirt.libvirt_connection.client.libversion
|
||||
if libvirt_version >= 1002002
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
libvirt_version >= 1_002_002
|
||||
end
|
||||
|
||||
def prepare(machine, folders, opts)
|
||||
|
||||
raise Vagrant::Errors::Error("No libvirt connection") if ProviderLibvirt.libvirt_connection.nil?
|
||||
|
||||
def prepare(machine, folders, _opts)
|
||||
raise Vagrant::Errors::Error('No libvirt connection') if ProviderLibvirt.libvirt_connection.nil?
|
||||
@conn = ProviderLibvirt.libvirt_connection.client
|
||||
|
||||
begin
|
||||
# loop through folders
|
||||
folders.each do |id, folder_opts|
|
||||
folder_opts.merge!({ :accessmode => "passthrough",
|
||||
:readonly => nil }) { |_k, ov, _nv| ov }
|
||||
machine.ui.info "================\nMachine id: #{machine.id}\nShould be mounting folders\n #{id}, opts: #{folder_opts}"
|
||||
folder_opts.merge!({ target: id,
|
||||
accessmode: 'passthrough',
|
||||
readonly: nil }) { |_k, ov, _nv| ov }
|
||||
|
||||
xml = to_xml('filesystem', folder_opts )
|
||||
mount_tag = Digest::MD5.new.update(folder_opts[:hostpath]).to_s[0,31]
|
||||
folder_opts[:mount_tag] = mount_tag
|
||||
|
||||
machine.ui.info "================\nMachine id: #{machine.id}\nShould be mounting folders\n #{id}, opts: #{folder_opts}"
|
||||
|
||||
xml = to_xml('filesystem', folder_opts)
|
||||
# puts "<<<<< XML:\n #{xml}\n >>>>>"
|
||||
@conn.lookup_domain_by_uuid(machine.id).attach_device(xml, 0)
|
||||
|
||||
end
|
||||
end
|
||||
rescue => e
|
||||
machine.ui.error("could not attach device because: #{e}")
|
||||
raise VagrantPlugins::ProviderLibvirt::Errors::AttachDeviceError,:error_message => e.message
|
||||
raise VagrantPlugins::ProviderLibvirt::Errors::AttachDeviceError,
|
||||
error_message: e.message
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# TODO once up, mount folders
|
||||
def enable(machine, folders, _opts)
|
||||
# Go through each folder and mount
|
||||
machine.ui.info("mounting p9 share in guest")
|
||||
machine.ui.info('mounting p9 share in guest')
|
||||
# Only mount folders that have a guest path specified.
|
||||
mount_folders = {}
|
||||
folders.each do |id, opts|
|
||||
mount_folders[id] = opts.dup if opts[:guestpath]
|
||||
# merge common options if not given
|
||||
mount_folders[id].merge!(:version => '9p2000.L') { |_k, ov, _nv| ov }
|
||||
mount_folders[id].merge!(version: '9p2000.L') { |_k, ov, _nv| ov }
|
||||
end
|
||||
# Mount the actual folder
|
||||
machine.guest.capability(
|
||||
@ -76,27 +73,25 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
def cleanup(machine, _opts)
|
||||
|
||||
raise Vagrant::Errors::Error("No libvirt connection") if ProviderLibvirt.libvirt_connection.nil?
|
||||
|
||||
if ProviderLibvirt.libvirt_connection.nil?
|
||||
raise Vagrant::Errors::Error('No libvirt connection')
|
||||
end
|
||||
@conn = ProviderLibvirt.libvirt_connection.client
|
||||
|
||||
begin
|
||||
if machine.id && machine.id != ""
|
||||
if machine.id && machine.id != ''
|
||||
dom = @conn.lookup_domain_by_uuid(machine.id)
|
||||
Nokogiri::XML(dom.xml_desc).xpath('/domain/devices/filesystem').each do |xml|
|
||||
Nokogiri::XML(dom.xml_desc).xpath(
|
||||
'/domain/devices/filesystem').each do |xml|
|
||||
dom.detach_device(xml.to_s)
|
||||
|
||||
machine.ui.info "Cleaned up shared folders"
|
||||
machine.ui.info 'Cleaned up shared folders'
|
||||
end
|
||||
end
|
||||
rescue => e
|
||||
machine.ui.error("could not detach device because: #{e}")
|
||||
raise VagrantPlugins::ProviderLibvirt::Errors::DetachDeviceError,:error_message => e.message
|
||||
raise VagrantPlugins::ProviderLibvirt::Errors::DetachDeviceError,
|
||||
error_message: e.message
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -55,7 +55,10 @@ module VagrantPlugins
|
||||
attr_accessor :memory
|
||||
attr_accessor :cpus
|
||||
attr_accessor :cpu_mode
|
||||
attr_accessor :boot_order
|
||||
attr_accessor :machine_type
|
||||
attr_accessor :machine_arch
|
||||
attr_accessor :machine_virtual_size
|
||||
attr_accessor :disk_bus
|
||||
attr_accessor :nic_model_type
|
||||
attr_accessor :nested
|
||||
@ -72,6 +75,11 @@ module VagrantPlugins
|
||||
attr_accessor :video_vram
|
||||
attr_accessor :keymap
|
||||
|
||||
# Sets the max number of NICs that can be created
|
||||
# Default set to 8. Don't change the default unless you know
|
||||
# what are doing
|
||||
attr_accessor :nic_adapter_count
|
||||
|
||||
# Storage
|
||||
attr_accessor :disks
|
||||
attr_accessor :cdroms
|
||||
@ -98,6 +106,8 @@ module VagrantPlugins
|
||||
@cpus = UNSET_VALUE
|
||||
@cpu_mode = UNSET_VALUE
|
||||
@machine_type = UNSET_VALUE
|
||||
@machine_arch = UNSET_VALUE
|
||||
@machine_virtual_size = UNSET_VALUE
|
||||
@disk_bus = UNSET_VALUE
|
||||
@nic_model_type = UNSET_VALUE
|
||||
@nested = UNSET_VALUE
|
||||
@ -114,6 +124,10 @@ module VagrantPlugins
|
||||
@video_vram = UNSET_VALUE
|
||||
@keymap = UNSET_VALUE
|
||||
|
||||
@nic_adapter_count = UNSET_VALUE
|
||||
|
||||
# Boot order
|
||||
@boot_order = []
|
||||
# Storage
|
||||
@disks = []
|
||||
@cdroms = []
|
||||
@ -122,6 +136,10 @@ module VagrantPlugins
|
||||
@inputs = UNSET_VALUE
|
||||
end
|
||||
|
||||
def boot(device)
|
||||
@boot_order << device # append
|
||||
end
|
||||
|
||||
def _get_device(disks)
|
||||
# skip existing devices and also the first one (vda)
|
||||
exist = disks.collect {|x| x[:device]}+[1.vdev.to_s]
|
||||
@ -221,6 +239,7 @@ module VagrantPlugins
|
||||
:path => options[:path],
|
||||
:bus => options[:bus],
|
||||
:cache => options[:cache] || 'default',
|
||||
:allow_existing => options[:allow_existing],
|
||||
}
|
||||
|
||||
@disks << disk # append
|
||||
@ -266,8 +285,10 @@ module VagrantPlugins
|
||||
|
||||
if @id_ssh_key_file
|
||||
# set ssh key for access to libvirt host
|
||||
home_dir = `echo ${HOME}`.chomp
|
||||
uri << "\&keyfile=#{home_dir}/.ssh/"+@id_ssh_key_file
|
||||
uri << "\&keyfile="
|
||||
# if no slash, prepend $HOME/.ssh/
|
||||
@id_ssh_key_file.prepend("#{`echo ${HOME}`.chomp}/.ssh/") if @id_ssh_key_file !~ /\A\//
|
||||
uri << @id_ssh_key_file
|
||||
end
|
||||
# set path to libvirt socket
|
||||
uri << "\&socket="+@socket if @socket
|
||||
@ -295,6 +316,8 @@ module VagrantPlugins
|
||||
@cpus = 1 if @cpus == UNSET_VALUE
|
||||
@cpu_mode = 'host-model' if @cpu_mode == UNSET_VALUE
|
||||
@machine_type = nil if @machine_type == UNSET_VALUE
|
||||
@machine_arch = nil if @machine_arch == UNSET_VALUE
|
||||
@machine_virtual_size = nil if @machine_virtual_size == UNSET_VALUE
|
||||
@disk_bus = 'virtio' if @disk_bus == UNSET_VALUE
|
||||
@nic_model_type = 'virtio' if @nic_model_type == UNSET_VALUE
|
||||
@nested = false if @nested == UNSET_VALUE
|
||||
@ -305,7 +328,7 @@ module VagrantPlugins
|
||||
@graphics_type = 'vnc' if @graphics_type == UNSET_VALUE
|
||||
@graphics_autoport = 'yes' if @graphics_port == UNSET_VALUE
|
||||
@graphics_autoport = 'no' if @graphics_port != UNSET_VALUE
|
||||
if (@graphics_type != 'vnc' && @graphics_port != 'spice') ||
|
||||
if (@graphics_type != 'vnc' && @graphics_type != 'spice') ||
|
||||
@graphics_passwd == UNSET_VALUE
|
||||
@graphics_passwd = nil
|
||||
end
|
||||
@ -314,6 +337,10 @@ module VagrantPlugins
|
||||
@video_type = 'cirrus' if @video_type == UNSET_VALUE
|
||||
@video_vram = 9216 if @video_vram == UNSET_VALUE
|
||||
@keymap = 'en-us' if @keymap == UNSET_VALUE
|
||||
@nic_adapter_count = 8 if @nic_adapter_count == UNSET_VALUE
|
||||
|
||||
# Boot order
|
||||
@boot_order = [] if @boot_order == UNSET_VALUE
|
||||
|
||||
# Storage
|
||||
@disks = [] if @disks == UNSET_VALUE
|
||||
|
@ -106,6 +106,10 @@ module VagrantPlugins
|
||||
error_key(:activate_network_error)
|
||||
end
|
||||
|
||||
class TcpTunnelPortNotDefined < VagrantLibvirtError
|
||||
error_key(:tcp_tunnel_port_not_defined)
|
||||
end
|
||||
|
||||
# Other exceptions
|
||||
class InterfaceSlotNotAvailable < VagrantLibvirtError
|
||||
error_key(:interface_slot_not_available)
|
||||
|
@ -24,14 +24,15 @@ module VagrantPlugins
|
||||
end
|
||||
|
||||
provider('libvirt', parallel: true) do
|
||||
# Setup logging and i18n
|
||||
setup_logging
|
||||
setup_i18n
|
||||
|
||||
require_relative 'provider'
|
||||
Provider
|
||||
end
|
||||
|
||||
action_hook(:remove_libvirt_image) do |hook|
|
||||
hook.after Vagrant::Action::Builtin::BoxRemove, Action.remove_libvirt_image
|
||||
end
|
||||
|
||||
|
||||
guest_capability('linux', 'mount_p9_shared_folder') do
|
||||
require_relative 'cap/mount_p9'
|
||||
Cap::MountP9
|
||||
@ -85,7 +86,12 @@ module VagrantPlugins
|
||||
end
|
||||
end
|
||||
|
||||
# Setup logging and i18n before any autoloading loads other classes
|
||||
# with logging configured as this prevents inheritance of the log level
|
||||
# from the parent logger.
|
||||
setup_logging
|
||||
setup_i18n
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -45,7 +45,7 @@ module VagrantPlugins
|
||||
# :username => "mitchellh",
|
||||
# :private_key_path => "/path/to/my/key"
|
||||
#}
|
||||
env = @machine.action('read_ssh_info')
|
||||
env = @machine.action('read_ssh_info', :lock => false)
|
||||
env[:machine_ssh_info]
|
||||
end
|
||||
|
||||
@ -67,7 +67,7 @@ module VagrantPlugins
|
||||
# Run a custom action we define called "read_state" which does
|
||||
# what it says. It puts the state in the `:machine_state_id`
|
||||
# key in the environment.
|
||||
env = @machine.action('read_state')
|
||||
env = @machine.action('read_state', :lock => false)
|
||||
|
||||
state_id = env[:machine_state_id]
|
||||
|
||||
|
@ -14,12 +14,22 @@
|
||||
<% end %>
|
||||
|
||||
<os>
|
||||
<% if @machine_type %>
|
||||
<type machine='<%= @machine_type %>'>hvm</type>
|
||||
<% else %>
|
||||
<type>hvm</type>
|
||||
<% end %>
|
||||
<boot dev='hd'/>
|
||||
<% if @machine_type %>
|
||||
<% if @machine_arch %>
|
||||
<type arch='<%= @machine_arch %>' machine='<%= @machine_type %>'>hvm</type>
|
||||
<% else %>
|
||||
<type machine='<%= @machine_type %>'>hvm</type>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<% if @machine_arch %>
|
||||
<type arch='<%= @machine_arch %>'>hvm</type>
|
||||
<% else %>
|
||||
<type>hvm</type>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if @boot_order.count >= 1 %>
|
||||
<bootmenu enable='yes'/>
|
||||
<% end %>
|
||||
<kernel><%= @kernel %></kernel>
|
||||
<initrd><%= @initrd %></initrd>
|
||||
<cmdline><%= @cmd_line %></cmdline>
|
||||
@ -36,6 +46,11 @@
|
||||
<source file='<%= @domain_volume_path %>'/>
|
||||
<%# we need to ensure a unique target dev -%>
|
||||
<target dev='vda' bus='<%= @disk_bus %>'/>
|
||||
<% if @boot_order[0] == 'hd' %>
|
||||
<boot order='1'/>
|
||||
<% elsif @boot_order.count >= 1 %>
|
||||
<boot order='9'/>
|
||||
<% end %>
|
||||
</disk>
|
||||
<%# additional disks -%>
|
||||
<% @disks.each do |d| -%>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<filesystem type='mount' accessmode='<%= accessmode %>'>
|
||||
<driver type='path' wrpolicy='immediate'/>
|
||||
<source dir='<%= hostpath %>'/>
|
||||
<target dir='<%= guestpath %>'/>
|
||||
<target dir='<%= mount_tag %>'/>
|
||||
<% unless readonly.nil? %>
|
||||
<readonly />
|
||||
<% end %>
|
||||
</filesystem>
|
||||
</filesystem>
|
||||
|
@ -6,5 +6,10 @@
|
||||
<target dev='vnet<%= @iface_number %>'/>
|
||||
<alias name='net<%= @iface_number %>'/>
|
||||
<model type='<%=@model_type%>'/>
|
||||
<% if @boot_order[0] == 'network' %>
|
||||
<boot order='<%= @iface_number+1 %>'/>
|
||||
<% elsif @boot_order.include?('network') %>
|
||||
<boot order='<%= @iface_number+2 %>'/>
|
||||
<% end %>
|
||||
</interface>
|
||||
|
||||
|
@ -15,6 +15,13 @@
|
||||
<% if @network_dhcp_enabled %>
|
||||
<dhcp>
|
||||
<range start="<%= @network_range_start %>" end="<%= @network_range_stop %>" />
|
||||
<% if @network_dhcp_bootp_file %>
|
||||
<% if @network_dhcp_bootp_server %>
|
||||
<bootp file="<%= @network_dhcp_bootp_file %>" server="<%= @network_dhcp_bootp_server %>" />
|
||||
<% else %>
|
||||
<bootp file="<%= @network_dhcp_bootp_file %>" />
|
||||
<% end %>
|
||||
<% end %>
|
||||
</dhcp>
|
||||
<% end %>
|
||||
</ip>
|
||||
|
@ -0,0 +1,7 @@
|
||||
<interface type='<%= @type %>'>
|
||||
<% if @mac %>
|
||||
<mac address='<%= @mac %>'/>
|
||||
<% end %>
|
||||
<source address='<%=@tcp_tunnel_ip%>' port='<%= @tcp_tunnel_port %>'/>
|
||||
<model type='<%=@model_type%>'/>
|
||||
</interface>
|
@ -1,5 +1,5 @@
|
||||
module VagrantPlugins
|
||||
module ProviderLibvirt
|
||||
VERSION = '0.0.25'
|
||||
VERSION = '0.0.30'
|
||||
end
|
||||
end
|
||||
|
@ -12,6 +12,9 @@ en:
|
||||
Checking if volume is available.
|
||||
creating_domain: |-
|
||||
Creating domain with the following settings...
|
||||
manual_resize_required: |-
|
||||
Created volume larger than box defaults, will require manual resizing of
|
||||
filesystems to utilize.
|
||||
uploading_volume: |-
|
||||
Uploading base box image as volume into libvirt storage...
|
||||
creating_domain_volume: |-
|
||||
@ -44,6 +47,13 @@ en:
|
||||
Rsyncing folder: %{hostpath} => %{guestpath}
|
||||
ready: |-
|
||||
Machine is booted and ready for use!
|
||||
remove_stale_volume: |-
|
||||
Remove stale volume...
|
||||
|
||||
warnings:
|
||||
ignoring_virtual_size_too_small: |-
|
||||
Ignoring requested virtual disk size of '%{requested}' as it is below
|
||||
the minimum box image size of '%{box_virtual_size}'.
|
||||
|
||||
errors:
|
||||
package_not_supported: Not support package for libvirt. Create box manualy.
|
||||
@ -125,6 +135,8 @@ en:
|
||||
Error while removing network %{network_name}. %{error_message}.
|
||||
delete_snapshot_error: |-
|
||||
Error while deleting snapshot: %{error_message}.
|
||||
tcp_tunnel_port_not_defined: |-
|
||||
TCP tunnel port not defined.
|
||||
|
||||
states:
|
||||
short_paused: |-
|
||||
|
@ -11,6 +11,20 @@ class EnvironmentHelper
|
||||
self.send(value.to_sym)
|
||||
end
|
||||
|
||||
def cpus
|
||||
4
|
||||
end
|
||||
|
||||
def memory
|
||||
1024
|
||||
end
|
||||
|
||||
%w(cpus cpu_mode boot_order machine_type disk_bus nested volume_cache kernel cmd_line initrd graphics_type graphics_autoport graphics_port graphics_ip graphics_passwd video_type video_vram keymap storage_pool_name disks cdroms driver).each do |name|
|
||||
define_method(name.to_sym) do
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def machine
|
||||
self
|
||||
end
|
||||
|
@ -10,12 +10,12 @@ describe VagrantPlugins::ProviderLibvirt::Action::SetNameOfDomain do
|
||||
dmn = VagrantPlugins::ProviderLibvirt::Action::SetNameOfDomain.new(Object.new, @env)
|
||||
first = dmn.build_domain_name(@env)
|
||||
second = dmn.build_domain_name(@env)
|
||||
first.should_not eq(second)
|
||||
first.should_not eq(second)
|
||||
end
|
||||
|
||||
it "builds simple domain name" do
|
||||
@env.default_prefix= 'pre'
|
||||
dmn = VagrantPlugins::ProviderLibvirt::Action::SetNameOfDomain.new(Object.new, @env)
|
||||
dmn.build_domain_name(@env).should eq('pre_')
|
||||
dmn.build_domain_name(@env).should eq('pre_')
|
||||
end
|
||||
end
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
error() {
|
||||
local msg="${1}"
|
||||
echo "==> ${msg}"
|
||||
echo "==> ERROR: ${msg}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ TMP_IMG="$TMP_DIR/box.img"
|
||||
|
||||
mkdir -p "$TMP_DIR"
|
||||
|
||||
[[ ! -w "$IMG" ]] && error "'$IMG': Permission denied"
|
||||
[[ ! -r "$IMG" ]] && error "'$IMG': Permission denied"
|
||||
|
||||
# We move / copy (when the image has master) the image to the tempdir
|
||||
# ensure that it's moved back / removed again
|
||||
@ -70,6 +70,10 @@ if [[ -n $(backing "$IMG") ]]; then
|
||||
cp "$IMG" "$TMP_IMG"
|
||||
rebase "$TMP_IMG"
|
||||
else
|
||||
if fuser -s "$IMG"; then
|
||||
error "Image '$IMG_BASENAME' is used by another process"
|
||||
fi
|
||||
|
||||
# move the image to get a speed-up and use less space on disk
|
||||
trap 'mv "$TMP_IMG" "$IMG"; rm -rf "$TMP_DIR"' EXIT
|
||||
mv "$IMG" "$TMP_IMG"
|
||||
|
@ -20,10 +20,8 @@ Gem::Specification.new do |gem|
|
||||
gem.add_development_dependency "rspec-expectations", "~> 2.12.1"
|
||||
gem.add_development_dependency "rspec-mocks", "~> 2.12.1"
|
||||
|
||||
gem.add_runtime_dependency 'fog', '~> 1.15'
|
||||
gem.add_runtime_dependency 'ruby-libvirt', '~> 0.4'
|
||||
gem.add_runtime_dependency 'fog-libvirt', '~> 0.0.1'
|
||||
gem.add_runtime_dependency 'nokogiri', '~> 1.6.0'
|
||||
|
||||
gem.add_development_dependency 'rake'
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user