vagrant-qemu 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +16 -0
- data/LICENSE +8 -0
- data/README.md +128 -0
- data/Rakefile +25 -0
- data/lib/vagrant-qemu/action/destroy.rb +19 -0
- data/lib/vagrant-qemu/action/import.rb +54 -0
- data/lib/vagrant-qemu/action/message_already_created.rb +16 -0
- data/lib/vagrant-qemu/action/message_not_created.rb +16 -0
- data/lib/vagrant-qemu/action/message_will_not_destroy.rb +16 -0
- data/lib/vagrant-qemu/action/read_state.rb +31 -0
- data/lib/vagrant-qemu/action/start_instance.rb +30 -0
- data/lib/vagrant-qemu/action/stop_instance.rb +18 -0
- data/lib/vagrant-qemu/action/warn_networks.rb +19 -0
- data/lib/vagrant-qemu/action.rb +174 -0
- data/lib/vagrant-qemu/config.rb +53 -0
- data/lib/vagrant-qemu/driver.rb +158 -0
- data/lib/vagrant-qemu/errors.rb +31 -0
- data/lib/vagrant-qemu/plugin.rb +73 -0
- data/lib/vagrant-qemu/provider.rb +76 -0
- data/lib/vagrant-qemu/util/timer.rb +17 -0
- data/lib/vagrant-qemu/version.rb +5 -0
- data/lib/vagrant-qemu.rb +18 -0
- data/locales/en.yml +54 -0
- data/vagrant-qemu.gemspec +52 -0
- metadata +68 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 56d15ffaaea610e07a3d494ef9935dc75469989a5c2b586106fcd9b0c75e41c4
|
|
4
|
+
data.tar.gz: d8ce98156eeff8fe8692ece6c0254db233bfcc3ea136dbd767b9acdd3f858f6d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7845ce71e9f0403ff35ebe4def750fef772a7736fb225262a71005fb1a944792b2bcc2ccec7f789b11b82a2b243f5b65bb833967155144bb7421ccb09d7730e3
|
|
7
|
+
data.tar.gz: 82272e1a35fa6ee973468040784d01d33a1d3354da89a784119c44350ace75161c9974d1de5f3ebd63247abe673232044f37b7ce203d3a723016797a1e78d7fd
|
data/.gitignore
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# OS-specific
|
|
2
|
+
.DS_Store
|
|
3
|
+
|
|
4
|
+
# editors
|
|
5
|
+
*.swp
|
|
6
|
+
|
|
7
|
+
# Bundler/Rubygems
|
|
8
|
+
*.gem
|
|
9
|
+
.bundle
|
|
10
|
+
pkg/*
|
|
11
|
+
tags
|
|
12
|
+
Gemfile.lock
|
|
13
|
+
vendor
|
|
14
|
+
|
|
15
|
+
# Vagrant
|
|
16
|
+
.vagrant
|
|
17
|
+
Vagrantfile
|
|
18
|
+
!example_box/Vagrantfile
|
|
19
|
+
|
|
20
|
+
# RVM files for gemset/ruby setting
|
|
21
|
+
.ruby-*
|
|
22
|
+
.rvmrc
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
|
|
3
|
+
group :development do
|
|
4
|
+
# We depend on Vagrant for development, but we don't add it as a
|
|
5
|
+
# gem dependency because we expect to be installed within the
|
|
6
|
+
# Vagrant environment itself using `vagrant plugin`.
|
|
7
|
+
gem "vagrant", :git => "https://github.com/mitchellh/vagrant.git"
|
|
8
|
+
|
|
9
|
+
gem "rake"
|
|
10
|
+
gem "rspec", "~> 3.4"
|
|
11
|
+
gem "rspec-its"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
group :plugins do
|
|
15
|
+
gem "vagrant-qemu" , path: "."
|
|
16
|
+
end
|
data/LICENSE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
Copyright (c) 2021 ppggff
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
5
|
+
|
|
6
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
7
|
+
|
|
8
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Vagrant QEMU Provider
|
|
2
|
+
|
|
3
|
+
This is a Vagrant plugin that adds a simple QEMU provider to Vagrant, allowing Vagrant
|
|
4
|
+
to control and provision machines using QEMU.
|
|
5
|
+
|
|
6
|
+
**Notes: test with Apple Silicon / M1 and CentOS aarch64 image only**
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
* Import from a Libvirt vagrant box or qcow2 image
|
|
11
|
+
* Start VM without GUI
|
|
12
|
+
* SSH into VM
|
|
13
|
+
* Provision the instances with any built-in Vagrant provisioner
|
|
14
|
+
* Synced folder support via SMB
|
|
15
|
+
* Basic operation: up, ssh, halt, destroy
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
Make sure QEMU is installed, if not:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
brew install qemu
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Install plugin:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
vagrant plugin install vagrant-qemu-x.x.x.gem
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Prepare a `Vagrantfile`, and start:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
vagrant up --provider qemu
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Notes:
|
|
38
|
+
* may need password to setup SMB on Mac,
|
|
39
|
+
see [vagrant doc](https://www.vagrantup.com/docs/synced-folders/smb) for details
|
|
40
|
+
* need username/password to access shared folder
|
|
41
|
+
|
|
42
|
+
## Box format
|
|
43
|
+
|
|
44
|
+
Same as [vagrant-libvirt version-1](https://github.com/vagrant-libvirt/vagrant-libvirt#version-1):
|
|
45
|
+
|
|
46
|
+
* qcow2 image file named `box.img`
|
|
47
|
+
* `metadata.json` file describing box image (provider, virtual_size, format)
|
|
48
|
+
* `Vagrantfile` that does default settings
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
This provider exposes a few provider-specific configuration options:
|
|
53
|
+
|
|
54
|
+
* `ssh_port` - The SSH port number used to access VM (IP is 127.0.0.1),
|
|
55
|
+
default: `50022`
|
|
56
|
+
* `arch` - The architecture of VM, default: `aarch64`
|
|
57
|
+
* `machine` - The machine type of VM, default: `virt,accel=hvf,highmem=off`
|
|
58
|
+
* `cpu` - The cpu model of VM, default: `cortex-a72`
|
|
59
|
+
* `smp` - The smp setting (Simulate an SMP system with n CPUs) of VM, default: `2`
|
|
60
|
+
* `memory` - The memory setting of VM, default: `4G`
|
|
61
|
+
* `image_path` - The path to qcow2 image for box-less VM, default is nil value
|
|
62
|
+
* `qemu_dir` - The path to QEMU's install dir, default: `/opt/homebrew/share/qemu`
|
|
63
|
+
|
|
64
|
+
These can be set like typical provider-specific configuration:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
# Basic Vagrant config (API version 2)
|
|
68
|
+
Vagrant.configure(2) do |config|
|
|
69
|
+
# ... other stuff
|
|
70
|
+
|
|
71
|
+
config.vm.provider "qemu" do |qe|
|
|
72
|
+
qe.memory = "8G"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Example
|
|
78
|
+
|
|
79
|
+
1. With a local box
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
# Basic Vagrant config (API version 2)
|
|
83
|
+
Vagrant.configure(2) do |config|
|
|
84
|
+
config.vm.box = "test-box"
|
|
85
|
+
config.vm.box_url = "file:///Users/xxx/test.box"
|
|
86
|
+
config.vm.box_check_update = false
|
|
87
|
+
end
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
2. With a local qcow2
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
# Basic Vagrant config (API version 2)
|
|
94
|
+
Vagrant.configure(2) do |config|
|
|
95
|
+
config.vm.provider "qemu" do |qe, override|
|
|
96
|
+
override.ssh.username = "xxx"
|
|
97
|
+
override.ssh.password = "vagrant"
|
|
98
|
+
|
|
99
|
+
qe.image_path = "/Users/xxx/test.qcow2"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Build
|
|
105
|
+
|
|
106
|
+
To build the `vagrant-qemu` plugin, clone this repository out, and use
|
|
107
|
+
[Bundler](http://gembundler.com) to get the dependencies:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
bundle
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Once you have the dependencies, build with `rake`:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
bundle exec rake build
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## TODO
|
|
120
|
+
|
|
121
|
+
* Support example image
|
|
122
|
+
* Support NFS shared folder
|
|
123
|
+
* Support package VM to box
|
|
124
|
+
* Test on more architectures
|
|
125
|
+
* More configures
|
|
126
|
+
* Better error messages
|
|
127
|
+
* Network
|
|
128
|
+
* GUI mode
|
data/Rakefile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
# require 'rspec/core/rake_task'
|
|
4
|
+
|
|
5
|
+
# Immediately sync all stdout so that tools like buildbot can
|
|
6
|
+
# immediately load in the output.
|
|
7
|
+
$stdout.sync = true
|
|
8
|
+
$stderr.sync = true
|
|
9
|
+
|
|
10
|
+
# Change to the directory of this file.
|
|
11
|
+
Dir.chdir(File.expand_path("../", __FILE__))
|
|
12
|
+
|
|
13
|
+
# This installs the tasks that help with gem creation and
|
|
14
|
+
# publishing.
|
|
15
|
+
Bundler::GemHelper.install_tasks
|
|
16
|
+
|
|
17
|
+
# Install the `spec` task so that we can run tests.
|
|
18
|
+
# RSpec::Core::RakeTask.new(:spec) do |t|
|
|
19
|
+
# t.rspec_opts = "--order defined"
|
|
20
|
+
# end
|
|
21
|
+
# Default task is to run the unit tests
|
|
22
|
+
# task :default => :spec
|
|
23
|
+
|
|
24
|
+
# build
|
|
25
|
+
task :default => :build
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module VagrantPlugins
|
|
2
|
+
module QEMU
|
|
3
|
+
module Action
|
|
4
|
+
class Destroy
|
|
5
|
+
def initialize(app, env)
|
|
6
|
+
@app = app
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def call(env)
|
|
10
|
+
env[:ui].info(I18n.t("vagrant_qemu.destroying"))
|
|
11
|
+
env[:machine].provider.driver.delete
|
|
12
|
+
env[:machine].id = nil
|
|
13
|
+
|
|
14
|
+
@app.call(env)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require "log4r"
|
|
2
|
+
require "pathname"
|
|
3
|
+
|
|
4
|
+
module VagrantPlugins
|
|
5
|
+
module QEMU
|
|
6
|
+
module Action
|
|
7
|
+
class Import
|
|
8
|
+
|
|
9
|
+
def initialize(app, env)
|
|
10
|
+
@app = app
|
|
11
|
+
@logger = Log4r::Logger.new("vagrant_qemu::action::import")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call(env)
|
|
15
|
+
image_path = nil
|
|
16
|
+
if env[:machine].provider_config.image_path
|
|
17
|
+
image_path = Pathname.new(env[:machine].provider_config.image_path)
|
|
18
|
+
elsif env[:machine].box
|
|
19
|
+
image_path = env[:machine].box.directory.join("box.img")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if !image_path || !image_path.file?
|
|
23
|
+
@logger.error("Invalid box image path: #{image_path}")
|
|
24
|
+
raise Errors::BoxInvalid, name: env[:machine].name
|
|
25
|
+
else
|
|
26
|
+
@logger.info("Found box image path: #{image_path}")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
qemu_dir = Pathname.new(env[:machine].provider_config.qemu_dir)
|
|
30
|
+
if !qemu_dir.directory?
|
|
31
|
+
@logger.error("Invalid qemu dir: #{qemu_dir}")
|
|
32
|
+
raise Errors::BoxInvalid, name: env[:machine].name
|
|
33
|
+
else
|
|
34
|
+
@logger.info("Found qemu dir: #{qemu_dir}")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
env[:ui].output("Importing a QEMU instance")
|
|
38
|
+
|
|
39
|
+
options = {
|
|
40
|
+
:image_path => image_path,
|
|
41
|
+
:qemu_dir => qemu_dir,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
env[:ui].detail("Creating and registering the VM...")
|
|
45
|
+
server = env[:machine].provider.driver.import(options)
|
|
46
|
+
|
|
47
|
+
env[:ui].detail("Successfully imported VM")
|
|
48
|
+
env[:machine].id = server[:id]
|
|
49
|
+
@app.call(env)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module VagrantPlugins
|
|
2
|
+
module QEMU
|
|
3
|
+
module Action
|
|
4
|
+
class MessageAlreadyCreated
|
|
5
|
+
def initialize(app, env)
|
|
6
|
+
@app = app
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def call(env)
|
|
10
|
+
env[:ui].info(I18n.t("vagrant_qemu.already_status", :status => "created"))
|
|
11
|
+
@app.call(env)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module VagrantPlugins
|
|
2
|
+
module QEMU
|
|
3
|
+
module Action
|
|
4
|
+
class MessageWillNotDestroy
|
|
5
|
+
def initialize(app, env)
|
|
6
|
+
@app = app
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def call(env)
|
|
10
|
+
env[:ui].info(I18n.t("vagrant_qemu.will_not_destroy", name: env[:machine].name))
|
|
11
|
+
@app.call(env)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require "log4r"
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module QEMU
|
|
5
|
+
module Action
|
|
6
|
+
# This action reads the state of the machine and puts it in the
|
|
7
|
+
# `:machine_state_id` key in the environment.
|
|
8
|
+
class ReadState
|
|
9
|
+
def initialize(app, env)
|
|
10
|
+
@app = app
|
|
11
|
+
@logger = Log4r::Logger.new("vagrant_qemu::action::read_state")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call(env)
|
|
15
|
+
if env[:machine].id
|
|
16
|
+
env[:machine_state_id] = env[:machine].provider.driver.get_current_state
|
|
17
|
+
|
|
18
|
+
# If the machine isn't created, then our ID is stale, so just
|
|
19
|
+
# mark it as not created.
|
|
20
|
+
if env[:machine_state_id] == :not_created
|
|
21
|
+
env[:machine].id = nil
|
|
22
|
+
end
|
|
23
|
+
else
|
|
24
|
+
env[:machine_state_id] = :not_created
|
|
25
|
+
end
|
|
26
|
+
@app.call(env)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require "log4r"
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module QEMU
|
|
5
|
+
module Action
|
|
6
|
+
# This starts a stopped instance.
|
|
7
|
+
class StartInstance
|
|
8
|
+
def initialize(app, env)
|
|
9
|
+
@app = app
|
|
10
|
+
@logger = Log4r::Logger.new("vagrant_qemu::action::start_instance")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call(env)
|
|
14
|
+
options = {
|
|
15
|
+
:ssh_port => env[:machine].provider_config.ssh_port,
|
|
16
|
+
:arch => env[:machine].provider_config.arch,
|
|
17
|
+
:machine => env[:machine].provider_config.machine,
|
|
18
|
+
:cpu => env[:machine].provider_config.cpu,
|
|
19
|
+
:smp => env[:machine].provider_config.smp,
|
|
20
|
+
:memory => env[:machine].provider_config.memory,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
env[:ui].output(I18n.t("vagrant_qemu.starting"))
|
|
24
|
+
env[:machine].provider.driver.start(options)
|
|
25
|
+
@app.call(env)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module VagrantPlugins
|
|
2
|
+
module QEMU
|
|
3
|
+
module Action
|
|
4
|
+
# This stops the running instance.
|
|
5
|
+
class StopInstance
|
|
6
|
+
def initialize(app, env)
|
|
7
|
+
@app = app
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def call(env)
|
|
11
|
+
env[:ui].info(I18n.t("vagrant_qemu.stopping"))
|
|
12
|
+
env[:machine].provider.driver.stop
|
|
13
|
+
@app.call(env)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module VagrantPlugins
|
|
2
|
+
module QEMU
|
|
3
|
+
module Action
|
|
4
|
+
class WarnNetworks
|
|
5
|
+
def initialize(app, env)
|
|
6
|
+
@app = app
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def call(env)
|
|
10
|
+
if env[:machine].config.vm.networks.length > 0
|
|
11
|
+
env[:ui].warn(I18n.t("vagrant_qemu.warn_networks"))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
@app.call(env)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
require "pathname"
|
|
2
|
+
|
|
3
|
+
require "vagrant/action/builder"
|
|
4
|
+
|
|
5
|
+
module VagrantPlugins
|
|
6
|
+
module QEMU
|
|
7
|
+
module Action
|
|
8
|
+
# Include the built-in modules so we can use them as top-level things.
|
|
9
|
+
include Vagrant::Action::Builtin
|
|
10
|
+
|
|
11
|
+
def self.action_package
|
|
12
|
+
lambda do |env|
|
|
13
|
+
raise Errors::NotSupportedError
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# This action is called to halt the remote machine.
|
|
18
|
+
def self.action_halt
|
|
19
|
+
Vagrant::Action::Builder.new.tap do |b|
|
|
20
|
+
b.use ConfigValidate
|
|
21
|
+
b.use Call, IsState, :not_created do |env, b2|
|
|
22
|
+
if env[:result]
|
|
23
|
+
b2.use MessageNotCreated
|
|
24
|
+
next
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
b2.use StopInstance
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# This action is called to terminate the remote machine.
|
|
33
|
+
def self.action_destroy
|
|
34
|
+
Vagrant::Action::Builder.new.tap do |b|
|
|
35
|
+
b.use Call, DestroyConfirm do |env, b2|
|
|
36
|
+
if env[:result]
|
|
37
|
+
b2.use ConfigValidate
|
|
38
|
+
b2.use Call, IsState, :not_created do |env2, b3|
|
|
39
|
+
if env2[:result]
|
|
40
|
+
b3.use MessageNotCreated
|
|
41
|
+
next
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
b3.use ProvisionerCleanup, :before if defined?(ProvisionerCleanup)
|
|
45
|
+
b3.use StopInstance
|
|
46
|
+
b3.use Destroy
|
|
47
|
+
b3.use SyncedFolderCleanup
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
b2.use MessageWillNotDestroy
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# This action is called when `vagrant provision` is called.
|
|
57
|
+
def self.action_provision
|
|
58
|
+
Vagrant::Action::Builder.new.tap do |b|
|
|
59
|
+
b.use ConfigValidate
|
|
60
|
+
b.use Call, IsState, :not_created do |env, b2|
|
|
61
|
+
if env[:result]
|
|
62
|
+
b2.use MessageNotCreated
|
|
63
|
+
next
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
b2.use Provision
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# This action is called to read the state of the machine. The
|
|
72
|
+
# resulting state is expected to be put into the `:machine_state_id`
|
|
73
|
+
# key.
|
|
74
|
+
def self.action_read_state
|
|
75
|
+
Vagrant::Action::Builder.new.tap do |b|
|
|
76
|
+
b.use ConfigValidate
|
|
77
|
+
b.use ReadState
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# This action is called to SSH into the machine.
|
|
82
|
+
def self.action_ssh
|
|
83
|
+
Vagrant::Action::Builder.new.tap do |b|
|
|
84
|
+
b.use ConfigValidate
|
|
85
|
+
b.use Call, IsState, :not_created do |env, b2|
|
|
86
|
+
if env[:result]
|
|
87
|
+
b2.use MessageNotCreated
|
|
88
|
+
next
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
b2.use SSHExec
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def self.action_ssh_run
|
|
97
|
+
Vagrant::Action::Builder.new.tap do |b|
|
|
98
|
+
b.use ConfigValidate
|
|
99
|
+
b.use Call, IsState, :not_created do |env, b2|
|
|
100
|
+
if env[:result]
|
|
101
|
+
b2.use MessageNotCreated
|
|
102
|
+
next
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
b2.use SSHRun
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def self.action_start
|
|
111
|
+
Vagrant::Action::Builder.new.tap do |b|
|
|
112
|
+
b.use Call, IsState, :running do |env1, b1|
|
|
113
|
+
if env1[:result]
|
|
114
|
+
b1.use action_provision
|
|
115
|
+
next
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
b1.use Provision
|
|
119
|
+
b1.use SyncedFolderCleanup
|
|
120
|
+
b1.use SyncedFolders
|
|
121
|
+
b1.use WarnNetworks
|
|
122
|
+
b1.use SetHostname
|
|
123
|
+
b1.use StartInstance
|
|
124
|
+
b1.use WaitForCommunicator, [:running]
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# This action is called to bring the box up from nothing.
|
|
130
|
+
def self.action_up
|
|
131
|
+
Vagrant::Action::Builder.new.tap do |b|
|
|
132
|
+
b.use HandleBox
|
|
133
|
+
b.use ConfigValidate
|
|
134
|
+
b.use BoxCheckOutdated
|
|
135
|
+
b.use Call, IsState, :not_created do |env1, b1|
|
|
136
|
+
if env1[:result]
|
|
137
|
+
b1.use Import
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
b1.use action_start
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def self.action_reload
|
|
146
|
+
Vagrant::Action::Builder.new.tap do |b|
|
|
147
|
+
b.use ConfigValidate
|
|
148
|
+
b.use Call, IsState, :not_created do |env, b2|
|
|
149
|
+
if env[:result]
|
|
150
|
+
b2.use MessageNotCreated
|
|
151
|
+
next
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
b2.use action_halt
|
|
155
|
+
b2.use action_start
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# The autoload farm
|
|
161
|
+
action_root = Pathname.new(File.expand_path("../action", __FILE__))
|
|
162
|
+
autoload :MessageAlreadyCreated, action_root.join("message_already_created")
|
|
163
|
+
autoload :MessageNotCreated, action_root.join("message_not_created")
|
|
164
|
+
autoload :MessageWillNotDestroy, action_root.join("message_will_not_destroy")
|
|
165
|
+
autoload :ReadState, action_root.join("read_state")
|
|
166
|
+
autoload :Import, action_root.join("import")
|
|
167
|
+
autoload :StartInstance, action_root.join("start_instance")
|
|
168
|
+
autoload :StopInstance, action_root.join("stop_instance")
|
|
169
|
+
autoload :Destroy, action_root.join("destroy")
|
|
170
|
+
autoload :TimedProvision, action_root.join("timed_provision") # some plugins now expect this action to exist
|
|
171
|
+
autoload :WarnNetworks, action_root.join("warn_networks")
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require "vagrant"
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module QEMU
|
|
5
|
+
class Config < Vagrant.plugin("2", :config)
|
|
6
|
+
attr_accessor :ssh_port
|
|
7
|
+
attr_accessor :arch
|
|
8
|
+
attr_accessor :machine
|
|
9
|
+
attr_accessor :cpu
|
|
10
|
+
attr_accessor :smp
|
|
11
|
+
attr_accessor :memory
|
|
12
|
+
attr_accessor :image_path
|
|
13
|
+
attr_accessor :qemu_dir
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@ssh_port = UNSET_VALUE
|
|
17
|
+
@arch = UNSET_VALUE
|
|
18
|
+
@machine = UNSET_VALUE
|
|
19
|
+
@cpu = UNSET_VALUE
|
|
20
|
+
@smp = UNSET_VALUE
|
|
21
|
+
@memory = UNSET_VALUE
|
|
22
|
+
@image_path = UNSET_VALUE
|
|
23
|
+
@qemu_dir = UNSET_VALUE
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
#-------------------------------------------------------------------
|
|
27
|
+
# Internal methods.
|
|
28
|
+
#-------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
def merge(other)
|
|
31
|
+
super.tap do |result|
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def finalize!
|
|
36
|
+
@ssh_port = 50022 if @ssh_port == UNSET_VALUE
|
|
37
|
+
@arch = "aarch64" if @arch == UNSET_VALUE
|
|
38
|
+
@machine = "virt,accel=hvf,highmem=off" if @machine == UNSET_VALUE
|
|
39
|
+
@cpu = "cortex-a72" if @cpu == UNSET_VALUE
|
|
40
|
+
@smp = "2" if @smp == UNSET_VALUE
|
|
41
|
+
@memory = "4G" if @memory == UNSET_VALUE
|
|
42
|
+
@image_path = nil if @image_path == UNSET_VALUE
|
|
43
|
+
@qemu_dir = "/opt/homebrew/share/qemu" if @qemu_dir == UNSET_VALUE
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def validate(machine)
|
|
47
|
+
# errors = _detected_errors
|
|
48
|
+
errors = []
|
|
49
|
+
{ "QEMU Provider" => errors }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
|
|
3
|
+
require "vagrant/util/busy"
|
|
4
|
+
require "vagrant/util/subprocess"
|
|
5
|
+
|
|
6
|
+
require_relative "plugin"
|
|
7
|
+
|
|
8
|
+
module VagrantPlugins
|
|
9
|
+
module QEMU
|
|
10
|
+
class Driver
|
|
11
|
+
# @return [String] VM ID
|
|
12
|
+
attr_reader :vm_id
|
|
13
|
+
attr_reader :data_dir
|
|
14
|
+
|
|
15
|
+
def initialize(id, dir)
|
|
16
|
+
@vm_id = id
|
|
17
|
+
@data_dir = dir
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def get_current_state
|
|
21
|
+
case
|
|
22
|
+
when running?
|
|
23
|
+
:running
|
|
24
|
+
when created?
|
|
25
|
+
:stopped
|
|
26
|
+
else
|
|
27
|
+
:not_created
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def delete
|
|
32
|
+
if created?
|
|
33
|
+
id_dir = @data_dir.join(@vm_id)
|
|
34
|
+
FileUtils.rm_rf(id_dir)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def start(options)
|
|
39
|
+
if !running?
|
|
40
|
+
id_dir = @data_dir.join(@vm_id)
|
|
41
|
+
image_path = id_dir.join("linked-box.img").to_s
|
|
42
|
+
unix_socket_path = id_dir.join("qemu_socket").to_s
|
|
43
|
+
pid_file = id_dir.join("qemu.pid").to_s
|
|
44
|
+
|
|
45
|
+
cmd = []
|
|
46
|
+
cmd += %W(qemu-system-#{options[:arch]})
|
|
47
|
+
|
|
48
|
+
# basic
|
|
49
|
+
cmd += %W(-machine #{options[:machine]})
|
|
50
|
+
cmd += %W(-cpu #{options[:cpu]})
|
|
51
|
+
cmd += %W(-smp #{options[:smp]})
|
|
52
|
+
cmd += %W(-m #{options[:memory]})
|
|
53
|
+
cmd += %W(-device virtio-net-device,netdev=net0)
|
|
54
|
+
cmd += %W(-netdev user,id=net0,hostfwd=tcp::#{options[:ssh_port]}-:22)
|
|
55
|
+
|
|
56
|
+
# drive
|
|
57
|
+
cmd += %W(-drive if=virtio,format=qcow2,file=#{image_path})
|
|
58
|
+
if options[:arch] == "aarch64"
|
|
59
|
+
fm1_path = id_dir.join("edk2-aarch64-code.fd").to_s
|
|
60
|
+
fm2_path = id_dir.join("edk2-arm-vars.fd").to_s
|
|
61
|
+
cmd += %W(-drive if=pflash,format=raw,file=#{fm1_path},readonly=on)
|
|
62
|
+
cmd += %W(-drive if=pflash,format=raw,file=#{fm2_path})
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# control
|
|
66
|
+
cmd += %W(-chardev socket,id=mon0,path=#{unix_socket_path},server=on,wait=off)
|
|
67
|
+
cmd += %W(-mon chardev=mon0,mode=readline)
|
|
68
|
+
cmd += %W(-pidfile #{pid_file})
|
|
69
|
+
cmd += %W(-serial null -parallel null -monitor none -display none -vga none)
|
|
70
|
+
cmd += %W(-daemonize)
|
|
71
|
+
|
|
72
|
+
execute(*cmd)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def stop
|
|
77
|
+
if running?
|
|
78
|
+
id_dir = @data_dir.join(@vm_id)
|
|
79
|
+
unix_socket_path = id_dir.join("qemu_socket").to_s
|
|
80
|
+
sent = false
|
|
81
|
+
execute("nc", "-w", "5", "-U", unix_socket_path) do |type, data|
|
|
82
|
+
case type
|
|
83
|
+
when :stdin
|
|
84
|
+
if !sent
|
|
85
|
+
data.write("system_powerdown\n")
|
|
86
|
+
sent = true
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def import(options)
|
|
94
|
+
new_id = SecureRandom.urlsafe_base64(8)
|
|
95
|
+
|
|
96
|
+
# Make dir
|
|
97
|
+
id_dir = @data_dir.join(new_id)
|
|
98
|
+
FileUtils.mkdir_p(id_dir)
|
|
99
|
+
|
|
100
|
+
# Prepare firmware
|
|
101
|
+
execute("cp", options[:qemu_dir].join("edk2-aarch64-code.fd").to_s, id_dir.join("edk2-aarch64-code.fd").to_s)
|
|
102
|
+
execute("cp", options[:qemu_dir].join("edk2-arm-vars.fd").to_s, id_dir.join("edk2-arm-vars.fd").to_s)
|
|
103
|
+
|
|
104
|
+
# Create image
|
|
105
|
+
execute("qemu-img", "create", "-f", "qcow2", "-F", "qcow2", "-b", options[:image_path].to_s, id_dir.join("linked-box.img").to_s)
|
|
106
|
+
|
|
107
|
+
server = {
|
|
108
|
+
:id => new_id,
|
|
109
|
+
}
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def created?
|
|
113
|
+
result = @data_dir.join(@vm_id).directory?
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def running?
|
|
117
|
+
pid_file = @data_dir.join(@vm_id).join("qemu.pid")
|
|
118
|
+
return false if !pid_file.file?
|
|
119
|
+
|
|
120
|
+
begin
|
|
121
|
+
Process.getpgid(File.read(pid_file).to_i)
|
|
122
|
+
true
|
|
123
|
+
rescue Errno::ESRCH
|
|
124
|
+
false
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def execute(*cmd, **opts, &block)
|
|
129
|
+
# Append in the options for subprocess
|
|
130
|
+
cmd << { notify: [:stdout, :stderr, :stdin] }
|
|
131
|
+
|
|
132
|
+
interrupted = false
|
|
133
|
+
int_callback = ->{ interrupted = true }
|
|
134
|
+
result = ::Vagrant::Util::Busy.busy(int_callback) do
|
|
135
|
+
::Vagrant::Util::Subprocess.execute(*cmd, &block)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
result.stderr.gsub!("\r\n", "\n")
|
|
139
|
+
result.stdout.gsub!("\r\n", "\n")
|
|
140
|
+
|
|
141
|
+
if result.exit_code != 0 && !interrupted
|
|
142
|
+
raise Errors::ExecuteError,
|
|
143
|
+
command: cmd.inspect,
|
|
144
|
+
stderr: result.stderr,
|
|
145
|
+
stdout: result.stdout
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
if opts
|
|
149
|
+
if opts[:with_stderr]
|
|
150
|
+
return result.stdout + " " + result.stderr
|
|
151
|
+
else
|
|
152
|
+
return result.stdout
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require "vagrant"
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module QEMU
|
|
5
|
+
module Errors
|
|
6
|
+
class VagrantQEMUError < Vagrant::Errors::VagrantError
|
|
7
|
+
error_namespace("vagrant_qemu.errors")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class RsyncError < VagrantQEMUError
|
|
11
|
+
error_key(:rsync_error)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class MkdirError < VagrantQEMUError
|
|
15
|
+
error_key(:mkdir_error)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class NotSupportedError < VagrantQEMUError
|
|
19
|
+
error_key(:not_supported)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class BoxInvalid < VagrantQEMUError
|
|
23
|
+
error_key(:box_invalid)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class ExecuteError < VagrantQEMUError
|
|
27
|
+
error_key(:execute_error)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require "vagrant"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
raise "The Vagrant QEMU plugin must be run within Vagrant."
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# This is a sanity check to make sure no one is attempting to install
|
|
8
|
+
# this into an early Vagrant version.
|
|
9
|
+
if Vagrant::VERSION < "1.2.0"
|
|
10
|
+
raise "The Vagrant QEMU plugin is only compatible with Vagrant 1.2+"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module VagrantPlugins
|
|
14
|
+
module QEMU
|
|
15
|
+
class Plugin < Vagrant.plugin("2")
|
|
16
|
+
name "QEMU"
|
|
17
|
+
description <<-DESC
|
|
18
|
+
This plugin installs a provider that allows Vagrant to manage
|
|
19
|
+
machines in QEMU.
|
|
20
|
+
DESC
|
|
21
|
+
|
|
22
|
+
config(:qemu, :provider) do
|
|
23
|
+
require_relative "config"
|
|
24
|
+
Config
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
provider(:qemu, box_format: "libvirt", box_optional: true, parallel: true) do
|
|
28
|
+
# Setup logging and i18n
|
|
29
|
+
setup_logging
|
|
30
|
+
setup_i18n
|
|
31
|
+
|
|
32
|
+
# Return the provider
|
|
33
|
+
require_relative "provider"
|
|
34
|
+
Provider
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# This initializes the internationalization strings.
|
|
38
|
+
def self.setup_i18n
|
|
39
|
+
I18n.load_path << File.expand_path("locales/en.yml", QEMU.source_root)
|
|
40
|
+
I18n.reload!
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# This sets up our log level to be whatever VAGRANT_LOG is.
|
|
44
|
+
def self.setup_logging
|
|
45
|
+
require "log4r"
|
|
46
|
+
|
|
47
|
+
level = nil
|
|
48
|
+
begin
|
|
49
|
+
level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
|
|
50
|
+
rescue NameError
|
|
51
|
+
# This means that the logging constant wasn't found,
|
|
52
|
+
# which is fine. We just keep `level` as `nil`. But
|
|
53
|
+
# we tell the user.
|
|
54
|
+
level = nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Some constants, such as "true" resolve to booleans, so the
|
|
58
|
+
# above error checking doesn't catch it. This will check to make
|
|
59
|
+
# sure that the log level is an integer, as Log4r requires.
|
|
60
|
+
level = nil if !level.is_a?(Integer)
|
|
61
|
+
|
|
62
|
+
# Set the logging level on all "vagrant" namespaced
|
|
63
|
+
# logs as long as we have a valid level.
|
|
64
|
+
if level
|
|
65
|
+
logger = Log4r::Logger.new("vagrant_qemu")
|
|
66
|
+
logger.outputters = Log4r::Outputter.stderr
|
|
67
|
+
logger.level = level
|
|
68
|
+
logger = nil
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require "log4r"
|
|
2
|
+
require "vagrant"
|
|
3
|
+
|
|
4
|
+
require_relative "driver"
|
|
5
|
+
|
|
6
|
+
module VagrantPlugins
|
|
7
|
+
module QEMU
|
|
8
|
+
class Provider < Vagrant.plugin("2", :provider)
|
|
9
|
+
attr_reader :driver
|
|
10
|
+
|
|
11
|
+
def initialize(machine)
|
|
12
|
+
@machine = machine
|
|
13
|
+
|
|
14
|
+
# TODO support NFS
|
|
15
|
+
@machine.config.nfs.functional = false
|
|
16
|
+
|
|
17
|
+
# This method will load in our driver, so we call it now to
|
|
18
|
+
# initialize it.
|
|
19
|
+
machine_id_changed
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def action(name)
|
|
23
|
+
# Attempt to get the action method from the Action class if it
|
|
24
|
+
# exists, otherwise return nil to show that we don't support the
|
|
25
|
+
# given action.
|
|
26
|
+
action_method = "action_#{name}"
|
|
27
|
+
return Action.send(action_method) if Action.respond_to?(action_method)
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def machine_id_changed
|
|
32
|
+
@driver = Driver.new(@machine.id, @machine.data_dir)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def ssh_info
|
|
36
|
+
# If the VM is not running that we can't possibly SSH into it
|
|
37
|
+
return nil if state.id != :running
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
host: "127.0.0.1",
|
|
41
|
+
port: @machine.provider_config.ssh_port
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def state
|
|
46
|
+
state_id = nil
|
|
47
|
+
state_id = :not_created if !@machine.id
|
|
48
|
+
|
|
49
|
+
if !state_id
|
|
50
|
+
# Run a custom action we define called "read_state" which does
|
|
51
|
+
# what it says. It puts the state in the `:machine_state_id`
|
|
52
|
+
# key in the environment.
|
|
53
|
+
env = @machine.action(:read_state)
|
|
54
|
+
state_id = env[:machine_state_id]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Get the short and long description
|
|
58
|
+
short = state_id.to_s
|
|
59
|
+
long = ""
|
|
60
|
+
|
|
61
|
+
# If we're not created, then specify the special ID flag
|
|
62
|
+
if state_id == :not_created
|
|
63
|
+
state_id = Vagrant::MachineState::NOT_CREATED_ID
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Return the MachineState object
|
|
67
|
+
Vagrant::MachineState.new(state_id, short, long)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def to_s
|
|
71
|
+
id = @machine.id.nil? ? "new" : @machine.id
|
|
72
|
+
"QEMU (#{id})"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module VagrantPlugins
|
|
2
|
+
module QEMU
|
|
3
|
+
module Util
|
|
4
|
+
class Timer
|
|
5
|
+
# A basic utility method that times the execution of the given
|
|
6
|
+
# block and returns it.
|
|
7
|
+
def self.time
|
|
8
|
+
start_time = Time.now.to_f
|
|
9
|
+
yield
|
|
10
|
+
end_time = Time.now.to_f
|
|
11
|
+
|
|
12
|
+
end_time - start_time
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/vagrant-qemu.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require "pathname"
|
|
2
|
+
|
|
3
|
+
require "vagrant-qemu/plugin"
|
|
4
|
+
|
|
5
|
+
module VagrantPlugins
|
|
6
|
+
module QEMU
|
|
7
|
+
lib_path = Pathname.new(File.expand_path("../vagrant-qemu", __FILE__))
|
|
8
|
+
autoload :Action, lib_path.join("action")
|
|
9
|
+
autoload :Errors, lib_path.join("errors")
|
|
10
|
+
|
|
11
|
+
# This returns the path to the source of this plugin.
|
|
12
|
+
#
|
|
13
|
+
# @return [Pathname]
|
|
14
|
+
def self.source_root
|
|
15
|
+
@source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/locales/en.yml
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
en:
|
|
2
|
+
vagrant_qemu:
|
|
3
|
+
already_status: |-
|
|
4
|
+
The machine is already %{status}.
|
|
5
|
+
not_created: |-
|
|
6
|
+
Instance is not created. Please run `vagrant up` first.
|
|
7
|
+
rsync_not_found_warning: |-
|
|
8
|
+
Warning! Folder sync disabled because the rsync binary is missing in the %{side}.
|
|
9
|
+
Make sure rsync is installed and the binary can be found in the PATH.
|
|
10
|
+
rsync_folder: |-
|
|
11
|
+
Rsyncing folder: %{hostpath} => %{guestpath}
|
|
12
|
+
starting: |-
|
|
13
|
+
Starting the instance...
|
|
14
|
+
stopping: |-
|
|
15
|
+
Stopping the instance...
|
|
16
|
+
destroying: |-
|
|
17
|
+
Destroying the instance...
|
|
18
|
+
warn_networks: |-
|
|
19
|
+
Warning! The QEMU provider doesn't support any of the Vagrant
|
|
20
|
+
high-level network configurations (`config.vm.network`). They
|
|
21
|
+
will be silently ignored.
|
|
22
|
+
will_not_destroy: |-
|
|
23
|
+
The instance '%{name}' will not be destroyed, since the confirmation
|
|
24
|
+
was declined.
|
|
25
|
+
|
|
26
|
+
errors:
|
|
27
|
+
not_supported: |-
|
|
28
|
+
Function not supported.
|
|
29
|
+
rsync_error: |-
|
|
30
|
+
There was an error when attempting to rsync a shared folder.
|
|
31
|
+
Please inspect the error message below for more info.
|
|
32
|
+
|
|
33
|
+
Host path: %{hostpath}
|
|
34
|
+
Guest path: %{guestpath}
|
|
35
|
+
Error: %{stderr}
|
|
36
|
+
mkdir_error: |-
|
|
37
|
+
There was an error when attempting to create a shared host folder.
|
|
38
|
+
Please inspect the error message below for more info.
|
|
39
|
+
|
|
40
|
+
Host path: %{hostpath}
|
|
41
|
+
Error: %{err}
|
|
42
|
+
box_invalid: |-
|
|
43
|
+
The box you're using with the QEMU provider ('%{name}')
|
|
44
|
+
is invalid.
|
|
45
|
+
execute_error: |-
|
|
46
|
+
A command executed by Vagrant didn't complete successfully!
|
|
47
|
+
The command run along with the output from the command is shown
|
|
48
|
+
below.
|
|
49
|
+
|
|
50
|
+
Command: %{command}
|
|
51
|
+
|
|
52
|
+
Stderr: %{stderr}
|
|
53
|
+
|
|
54
|
+
Stdout: %{stdout}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
|
2
|
+
require "vagrant-qemu/version"
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |s|
|
|
5
|
+
s.name = "vagrant-qemu"
|
|
6
|
+
s.version = VagrantPlugins::QEMU::VERSION
|
|
7
|
+
s.platform = Gem::Platform::RUBY
|
|
8
|
+
s.license = "MIT"
|
|
9
|
+
s.authors = "ppggff"
|
|
10
|
+
s.email = "pgf00a@gmail.com.com"
|
|
11
|
+
s.homepage = ""
|
|
12
|
+
s.summary = "Enables Vagrant to manage machines with QEMU."
|
|
13
|
+
s.description = "Enables Vagrant to manage machines with QEMU."
|
|
14
|
+
|
|
15
|
+
s.required_rubygems_version = ">= 1.3.6"
|
|
16
|
+
s.rubyforge_project = "vagrant-qemu"
|
|
17
|
+
|
|
18
|
+
# The following block of code determines the files that should be included
|
|
19
|
+
# in the gem. It does this by reading all the files in the directory where
|
|
20
|
+
# this gemspec is, and parsing out the ignored files from the gitignore.
|
|
21
|
+
# Note that the entire gitignore(5) syntax is not supported, specifically
|
|
22
|
+
# the "!" syntax, but it should mostly work correctly.
|
|
23
|
+
root_path = File.dirname(__FILE__)
|
|
24
|
+
all_files = Dir.chdir(root_path) { Dir.glob("**/{*,.*}") }
|
|
25
|
+
all_files.reject! { |file| [".", ".."].include?(File.basename(file)) }
|
|
26
|
+
gitignore_path = File.join(root_path, ".gitignore")
|
|
27
|
+
gitignore = File.readlines(gitignore_path)
|
|
28
|
+
gitignore.map! { |line| line.chomp.strip }
|
|
29
|
+
gitignore.reject! { |line| line.empty? || line =~ /^(#|!)/ }
|
|
30
|
+
|
|
31
|
+
unignored_files = all_files.reject do |file|
|
|
32
|
+
# Ignore any directories, the gemspec only cares about files
|
|
33
|
+
next true if File.directory?(file)
|
|
34
|
+
|
|
35
|
+
# Ignore any paths that match anything in the gitignore. We do
|
|
36
|
+
# two tests here:
|
|
37
|
+
#
|
|
38
|
+
# - First, test to see if the entire path matches the gitignore.
|
|
39
|
+
# - Second, match if the basename does, this makes it so that things
|
|
40
|
+
# like '.DS_Store' will match sub-directories too (same behavior
|
|
41
|
+
# as git).
|
|
42
|
+
#
|
|
43
|
+
gitignore.any? do |ignore|
|
|
44
|
+
File.fnmatch(ignore, file, File::FNM_PATHNAME) ||
|
|
45
|
+
File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
s.files = unignored_files
|
|
50
|
+
s.executables = unignored_files.map { |f| f[/^bin\/(.*)/, 1] }.compact
|
|
51
|
+
s.require_path = 'lib'
|
|
52
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: vagrant-qemu
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- ppggff
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2022-01-06 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Enables Vagrant to manage machines with QEMU.
|
|
14
|
+
email: pgf00a@gmail.com.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- ".gitignore"
|
|
20
|
+
- CHANGELOG.md
|
|
21
|
+
- Gemfile
|
|
22
|
+
- LICENSE
|
|
23
|
+
- README.md
|
|
24
|
+
- Rakefile
|
|
25
|
+
- lib/vagrant-qemu.rb
|
|
26
|
+
- lib/vagrant-qemu/action.rb
|
|
27
|
+
- lib/vagrant-qemu/action/destroy.rb
|
|
28
|
+
- lib/vagrant-qemu/action/import.rb
|
|
29
|
+
- lib/vagrant-qemu/action/message_already_created.rb
|
|
30
|
+
- lib/vagrant-qemu/action/message_not_created.rb
|
|
31
|
+
- lib/vagrant-qemu/action/message_will_not_destroy.rb
|
|
32
|
+
- lib/vagrant-qemu/action/read_state.rb
|
|
33
|
+
- lib/vagrant-qemu/action/start_instance.rb
|
|
34
|
+
- lib/vagrant-qemu/action/stop_instance.rb
|
|
35
|
+
- lib/vagrant-qemu/action/warn_networks.rb
|
|
36
|
+
- lib/vagrant-qemu/config.rb
|
|
37
|
+
- lib/vagrant-qemu/driver.rb
|
|
38
|
+
- lib/vagrant-qemu/errors.rb
|
|
39
|
+
- lib/vagrant-qemu/plugin.rb
|
|
40
|
+
- lib/vagrant-qemu/provider.rb
|
|
41
|
+
- lib/vagrant-qemu/util/timer.rb
|
|
42
|
+
- lib/vagrant-qemu/version.rb
|
|
43
|
+
- locales/en.yml
|
|
44
|
+
- vagrant-qemu.gemspec
|
|
45
|
+
homepage: ''
|
|
46
|
+
licenses:
|
|
47
|
+
- MIT
|
|
48
|
+
metadata: {}
|
|
49
|
+
post_install_message:
|
|
50
|
+
rdoc_options: []
|
|
51
|
+
require_paths:
|
|
52
|
+
- lib
|
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
|
+
requirements:
|
|
55
|
+
- - ">="
|
|
56
|
+
- !ruby/object:Gem::Version
|
|
57
|
+
version: '0'
|
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: 1.3.6
|
|
63
|
+
requirements: []
|
|
64
|
+
rubygems_version: 3.0.3
|
|
65
|
+
signing_key:
|
|
66
|
+
specification_version: 4
|
|
67
|
+
summary: Enables Vagrant to manage machines with QEMU.
|
|
68
|
+
test_files: []
|