vagrant-openstack-plugin 0.1.1
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.
- data/.gitignore +19 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +23 -0
- data/README.md +160 -0
- data/Rakefile +21 -0
- data/dummy.box +0 -0
- data/example_box/README.md +13 -0
- data/example_box/metadata.json +3 -0
- data/lib/vagrant-openstack.rb +53 -0
- data/lib/vagrant-openstack/action.rb +110 -0
- data/lib/vagrant-openstack/action/connect_openstack.rb +36 -0
- data/lib/vagrant-openstack/action/create_server.rb +117 -0
- data/lib/vagrant-openstack/action/delete_server.rb +26 -0
- data/lib/vagrant-openstack/action/is_created.rb +16 -0
- data/lib/vagrant-openstack/action/message_already_created.rb +16 -0
- data/lib/vagrant-openstack/action/message_not_created.rb +16 -0
- data/lib/vagrant-openstack/action/read_ssh_info.rb +46 -0
- data/lib/vagrant-openstack/action/read_state.rb +38 -0
- data/lib/vagrant-openstack/action/sync_folders.rb +57 -0
- data/lib/vagrant-openstack/action/warn_networks.rb +19 -0
- data/lib/vagrant-openstack/config.rb +92 -0
- data/lib/vagrant-openstack/errors.rb +27 -0
- data/lib/vagrant-openstack/plugin.rb +37 -0
- data/lib/vagrant-openstack/provider.rb +50 -0
- data/lib/vagrant-openstack/version.rb +5 -0
- data/locales/en.yml +73 -0
- data/spec/vagrant-openstack/config_spec.rb +67 -0
- data/vagrant-openstack.gemspec +24 -0
- metadata +129 -0
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
# We depend on Vagrant for development, but we don't add it as a
|
7
|
+
# gem dependency because we expect to be installed within the
|
8
|
+
# Vagrant environment itself using `vagrant plugin`.
|
9
|
+
#gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
|
10
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2013 Mitchell Hashimoto
|
2
|
+
Copyright (c) 2013 cloudbau GmbH
|
3
|
+
|
4
|
+
MIT License
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
# Vagrant OpenStack Cloud Provider
|
2
|
+
|
3
|
+
This is a [Vagrant](http://www.vagrantup.com) 1.1+ plugin that adds a
|
4
|
+
[OpenStack Cloud](http://www.openstack.org) provider to Vagrant,
|
5
|
+
allowing Vagrant to control and provision machines within an OpenStack
|
6
|
+
cloud.
|
7
|
+
|
8
|
+
This plugin started as a fork of the Vagrant RackSpace provider.
|
9
|
+
|
10
|
+
**Note:** This plugin requires Vagrant 1.1+.
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
* Boot OpenStack Cloud instances.
|
15
|
+
* SSH into the instances.
|
16
|
+
* Provision the instances with any built-in Vagrant provisioner.
|
17
|
+
* Minimal synced folder support via `rsync`.
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Install using standard Vagrant 1.1+ plugin installation methods. After
|
22
|
+
installing, `vagrant up` and specify the `openstack` provider. An example is
|
23
|
+
shown below.
|
24
|
+
|
25
|
+
```
|
26
|
+
$ vagrant plugin install vagrant-openstack
|
27
|
+
...
|
28
|
+
$ vagrant up --provider=openstack
|
29
|
+
...
|
30
|
+
```
|
31
|
+
|
32
|
+
Of course prior to doing this, you'll need to obtain an OpenStack-compatible
|
33
|
+
box file for Vagrant.
|
34
|
+
|
35
|
+
## Quick Start
|
36
|
+
|
37
|
+
After installing the plugin (instructions above), the quickest way to get
|
38
|
+
started is to actually use a dummy OpenStack box and specify all the details
|
39
|
+
manually within a `config.vm.provider` block. So first, add the dummy
|
40
|
+
box using any name you want:
|
41
|
+
|
42
|
+
```
|
43
|
+
$ vagrant box add dummy https://github.com/cloudbau/vagrant-openstack/raw/master/dummy.box
|
44
|
+
...
|
45
|
+
```
|
46
|
+
|
47
|
+
And then make a Vagrantfile that looks like the following, filling in
|
48
|
+
your information where necessary.
|
49
|
+
|
50
|
+
```
|
51
|
+
require 'vagrant-openstack'
|
52
|
+
|
53
|
+
Vagrant.configure("2") do |config|
|
54
|
+
config.vm.box = "dummy"
|
55
|
+
|
56
|
+
config.vm.provider :openstack do |os| # e.g.
|
57
|
+
os.username = "YOUR USERNAME" # "#{ENV['OS_USERNAME']}"
|
58
|
+
os.api_key = "YOUR API KEY" # "#{ENV['OS_PASSWORD']}"
|
59
|
+
os.flavor = /m1.tiny/
|
60
|
+
os.image = /Ubuntu/
|
61
|
+
os.endpoint = "KEYSTONE AUTH URL" # "#{ENV['OS_AUTH_URL']}/tokens"
|
62
|
+
os.keypair_name = "YOUR KEYPAIR NAME"
|
63
|
+
os.ssh_username = "SSH USERNAME"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
And then run `vagrant up --provider=openstack`.
|
69
|
+
|
70
|
+
This will start a tiny Ubuntu instance in your OpenStack installation within
|
71
|
+
your tenant. And assuming your SSH information was filled in properly
|
72
|
+
within your Vagrantfile, SSH and provisioning will work as well.
|
73
|
+
|
74
|
+
Note that normally a lot of this boilerplate is encoded within the box
|
75
|
+
file, but the box file used for the quick start, the "dummy" box, has
|
76
|
+
no preconfigured defaults.
|
77
|
+
|
78
|
+
## Box Format
|
79
|
+
|
80
|
+
Every provider in Vagrant must introduce a custom box format. This
|
81
|
+
provider introduces `openstack` boxes. You can view an example box in
|
82
|
+
the [example_box/ directory](https://github.com/cloudbau/vagrant-openstack/tree/master/example_box).
|
83
|
+
That directory also contains instructions on how to build a box.
|
84
|
+
|
85
|
+
The box format is basically just the required `metadata.json` file
|
86
|
+
along with a `Vagrantfile` that does default settings for the
|
87
|
+
provider-specific configuration for this provider.
|
88
|
+
|
89
|
+
## Configuration
|
90
|
+
|
91
|
+
This provider exposes quite a few provider-specific configuration options:
|
92
|
+
|
93
|
+
* `api_key` - The API key for accessing OpenStack.
|
94
|
+
* `flavor` - The server flavor to boot. This can be a string matching
|
95
|
+
the exact ID or name of the server, or this can be a regular expression
|
96
|
+
to partially match some server flavor.
|
97
|
+
* `image` - The server image to boot. This can be a string matching the
|
98
|
+
exact ID or name of the image, or this can be a regular expression to
|
99
|
+
partially match some image.
|
100
|
+
* `endpoint` - The keystone authentication URL of your OpenStack installation.
|
101
|
+
* `server_name` - The name of the server within the OpenStack Cloud. This
|
102
|
+
defaults to the name of the Vagrant machine (via `config.vm.define`), but
|
103
|
+
can be overridden with this.
|
104
|
+
* `username` - The username with which to access OpenStack.
|
105
|
+
* `keypair_name` - The name of the keypair to access the machine.
|
106
|
+
* `ssh_username` - The username to access the machine.
|
107
|
+
|
108
|
+
These can be set like typical provider-specific configuration:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
Vagrant.configure("2") do |config|
|
112
|
+
# ... other stuff
|
113
|
+
|
114
|
+
config.vm.provider :openstack do |rs|
|
115
|
+
rs.username = "mitchellh"
|
116
|
+
rs.api_key = "foobarbaz"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
```
|
120
|
+
|
121
|
+
## Networks
|
122
|
+
|
123
|
+
Networking features in the form of `config.vm.network` are not
|
124
|
+
supported with `vagrant-openstack`, currently. If any of these are
|
125
|
+
specified, Vagrant will emit a warning, but will otherwise boot
|
126
|
+
the OpenStack server.
|
127
|
+
|
128
|
+
## Synced Folders
|
129
|
+
|
130
|
+
There is minimal support for synced folders. Upon `vagrant up`,
|
131
|
+
`vagrant reload`, and `vagrant provision`, the OpenStack provider will use
|
132
|
+
`rsync` (if available) to uni-directionally sync the folder to
|
133
|
+
the remote machine over SSH.
|
134
|
+
|
135
|
+
This is good enough for all built-in Vagrant provisioners (shell,
|
136
|
+
chef, and puppet) to work!
|
137
|
+
|
138
|
+
## Development
|
139
|
+
|
140
|
+
To work on the `vagrant-openstack` plugin, clone this repository out, and use
|
141
|
+
[Bundler](http://gembundler.com) to get the dependencies:
|
142
|
+
|
143
|
+
```
|
144
|
+
$ bundle
|
145
|
+
```
|
146
|
+
|
147
|
+
Once you have the dependencies, verify the unit tests pass with `rake`:
|
148
|
+
|
149
|
+
```
|
150
|
+
$ bundle exec rake
|
151
|
+
```
|
152
|
+
|
153
|
+
If those pass, you're ready to start developing the plugin. You can test
|
154
|
+
the plugin without installing it into your Vagrant environment by just
|
155
|
+
creating a `Vagrantfile` in the top level of this directory (it is gitignored)
|
156
|
+
that uses it, and uses bundler to execute Vagrant:
|
157
|
+
|
158
|
+
```
|
159
|
+
$ bundle exec vagrant up --provider=openstack
|
160
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
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
|
19
|
+
|
20
|
+
# Default task is to run the unit tests
|
21
|
+
task :default => "spec"
|
data/dummy.box
ADDED
Binary file
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Vagrant OpenStack Cloud Example Box
|
2
|
+
|
3
|
+
Vagrant providers each require a custom provider-specific box format.
|
4
|
+
This folder shows the example contents of a box for the `openstack` provider.
|
5
|
+
To turn this into a box:
|
6
|
+
|
7
|
+
```
|
8
|
+
$ tar cvzf openstack.box ./metadata.json ./Vagrantfile
|
9
|
+
```
|
10
|
+
|
11
|
+
This box works by using Vagrant's built-in Vagrantfile merging to setup
|
12
|
+
defaults for OpenStack. These defaults can easily be overwritten by higher-level
|
13
|
+
Vagrantfiles (such as project root Vagrantfiles).
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
require "vagrant-openstack/plugin"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module OpenStack
|
7
|
+
lib_path = Pathname.new(File.expand_path("../vagrant-openstack", __FILE__))
|
8
|
+
autoload :Errors, lib_path.join("errors")
|
9
|
+
|
10
|
+
# This initializes the i18n load path so that the plugin-specific
|
11
|
+
# translations work.
|
12
|
+
def self.init_i18n
|
13
|
+
I18n.load_path << File.expand_path("locales/en.yml", source_root)
|
14
|
+
I18n.reload!
|
15
|
+
end
|
16
|
+
|
17
|
+
# This initializes the logging so that our logs are outputted at
|
18
|
+
# the same level as Vagrant core logs.
|
19
|
+
def self.init_logging
|
20
|
+
# Initialize logging
|
21
|
+
level = nil
|
22
|
+
begin
|
23
|
+
level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
|
24
|
+
rescue NameError
|
25
|
+
# This means that the logging constant wasn't found,
|
26
|
+
# which is fine. We just keep `level` as `nil`. But
|
27
|
+
# we tell the user.
|
28
|
+
level = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Some constants, such as "true" resolve to booleans, so the
|
32
|
+
# above error checking doesn't catch it. This will check to make
|
33
|
+
# sure that the log level is an integer, as Log4r requires.
|
34
|
+
level = nil if !level.is_a?(Integer)
|
35
|
+
|
36
|
+
# Set the logging level on all "vagrant" namespaced
|
37
|
+
# logs as long as we have a valid level.
|
38
|
+
if level
|
39
|
+
logger = Log4r::Logger.new("vagrant_openstack")
|
40
|
+
logger.outputters = Log4r::Outputter.stderr
|
41
|
+
logger.level = level
|
42
|
+
logger = nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# This returns the path to the source of this plugin.
|
47
|
+
#
|
48
|
+
# @return [Pathname]
|
49
|
+
def self.source_root
|
50
|
+
@source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
require "vagrant/action/builder"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module OpenStack
|
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
|
+
# This action is called to destroy the remote machine.
|
12
|
+
def self.action_destroy
|
13
|
+
Vagrant::Action::Builder.new.tap do |b|
|
14
|
+
b.use ConfigValidate
|
15
|
+
b.use Call, IsCreated do |env, b2|
|
16
|
+
if !env[:result]
|
17
|
+
b2.use MessageNotCreated
|
18
|
+
next
|
19
|
+
end
|
20
|
+
|
21
|
+
b2.use ConnectOpenStack
|
22
|
+
b2.use DeleteServer
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# This action is called to read the SSH info of the machine. The
|
28
|
+
# resulting state is expected to be put into the `:machine_ssh_info`
|
29
|
+
# key.
|
30
|
+
def self.action_read_ssh_info
|
31
|
+
Vagrant::Action::Builder.new.tap do |b|
|
32
|
+
b.use ConfigValidate
|
33
|
+
b.use ConnectOpenStack
|
34
|
+
b.use ReadSSHInfo
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# This action is called to read the state of the machine. The
|
39
|
+
# resulting state is expected to be put into the `:machine_state_id`
|
40
|
+
# key.
|
41
|
+
def self.action_read_state
|
42
|
+
Vagrant::Action::Builder.new.tap do |b|
|
43
|
+
b.use ConfigValidate
|
44
|
+
b.use ConnectOpenStack
|
45
|
+
b.use ReadState
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.action_ssh
|
50
|
+
Vagrant::Action::Builder.new.tap do |b|
|
51
|
+
b.use ConfigValidate
|
52
|
+
b.use Call, IsCreated do |env, b2|
|
53
|
+
if !env[:result]
|
54
|
+
b2.use MessageNotCreated
|
55
|
+
next
|
56
|
+
end
|
57
|
+
|
58
|
+
b2.use SSHExec
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.action_up
|
64
|
+
Vagrant::Action::Builder.new.tap do |b|
|
65
|
+
b.use ConfigValidate
|
66
|
+
b.use Call, IsCreated do |env, b2|
|
67
|
+
if env[:result]
|
68
|
+
b2.use MessageAlreadyCreated
|
69
|
+
next
|
70
|
+
end
|
71
|
+
|
72
|
+
b2.use ConnectOpenStack
|
73
|
+
b2.use Provision
|
74
|
+
b2.use SyncFolders
|
75
|
+
b2.use WarnNetworks
|
76
|
+
b2.use CreateServer
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.action_provision
|
82
|
+
Vagrant::Action::Builder.new.tap do |b|
|
83
|
+
b.use ConfigValidate
|
84
|
+
b.use Call, IsCreated do |env, b2|
|
85
|
+
if !env[:result]
|
86
|
+
b2.use MessageNotCreated
|
87
|
+
next
|
88
|
+
end
|
89
|
+
|
90
|
+
b2.use Provision
|
91
|
+
b2.use SyncFolders
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# The autoload farm
|
97
|
+
action_root = Pathname.new(File.expand_path("../action", __FILE__))
|
98
|
+
autoload :ConnectOpenStack, action_root.join("connect_openstack")
|
99
|
+
autoload :CreateServer, action_root.join("create_server")
|
100
|
+
autoload :DeleteServer, action_root.join("delete_server")
|
101
|
+
autoload :IsCreated, action_root.join("is_created")
|
102
|
+
autoload :MessageAlreadyCreated, action_root.join("message_already_created")
|
103
|
+
autoload :MessageNotCreated, action_root.join("message_not_created")
|
104
|
+
autoload :ReadSSHInfo, action_root.join("read_ssh_info")
|
105
|
+
autoload :ReadState, action_root.join("read_state")
|
106
|
+
autoload :SyncFolders, action_root.join("sync_folders")
|
107
|
+
autoload :WarnNetworks, action_root.join("warn_networks")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "fog"
|
2
|
+
require "log4r"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module OpenStack
|
6
|
+
module Action
|
7
|
+
# This action connects to OpenStack, verifies credentials work, and
|
8
|
+
# puts the OpenStack connection object into the `:openstack_compute` key
|
9
|
+
# in the environment.
|
10
|
+
class ConnectOpenStack
|
11
|
+
def initialize(app, env)
|
12
|
+
@app = app
|
13
|
+
@logger = Log4r::Logger.new("vagrant_openstack::action::connect_openstack")
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# Get the configs
|
18
|
+
config = env[:machine].provider_config
|
19
|
+
api_key = config.api_key
|
20
|
+
endpoint = config.endpoint
|
21
|
+
username = config.username
|
22
|
+
|
23
|
+
@logger.info("Connecting to OpenStack...")
|
24
|
+
env[:openstack_compute] = Fog::Compute.new({
|
25
|
+
:provider => :openstack,
|
26
|
+
:openstack_username => username,
|
27
|
+
:openstack_api_key => api_key,
|
28
|
+
:openstack_auth_url => endpoint
|
29
|
+
})
|
30
|
+
|
31
|
+
@app.call(env)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require "fog"
|
2
|
+
require "log4r"
|
3
|
+
|
4
|
+
require 'vagrant/util/retryable'
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module OpenStack
|
8
|
+
module Action
|
9
|
+
# This creates the OpenStack server.
|
10
|
+
class CreateServer
|
11
|
+
include Vagrant::Util::Retryable
|
12
|
+
|
13
|
+
def initialize(app, env)
|
14
|
+
@app = app
|
15
|
+
@logger = Log4r::Logger.new("vagrant_openstack::action::create_server")
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
# Get the configs
|
20
|
+
config = env[:machine].provider_config
|
21
|
+
|
22
|
+
# Find the flavor
|
23
|
+
env[:ui].info(I18n.t("vagrant_openstack.finding_flavor"))
|
24
|
+
flavor = find_matching(env[:openstack_compute].flavors.all, config.flavor)
|
25
|
+
raise Errors::NoMatchingFlavor if !flavor
|
26
|
+
|
27
|
+
# Find the image
|
28
|
+
env[:ui].info(I18n.t("vagrant_openstack.finding_image"))
|
29
|
+
image = find_matching(env[:openstack_compute].images, config.image)
|
30
|
+
raise Errors::NoMatchingImage if !image
|
31
|
+
|
32
|
+
# Figure out the name for the server
|
33
|
+
server_name = config.server_name || env[:machine].name
|
34
|
+
|
35
|
+
# Output the settings we're going to use to the user
|
36
|
+
env[:ui].info(I18n.t("vagrant_openstack.launching_server"))
|
37
|
+
env[:ui].info(" -- Flavor: #{flavor.name}")
|
38
|
+
env[:ui].info(" -- Image: #{image.name}")
|
39
|
+
env[:ui].info(" -- Name: #{server_name}")
|
40
|
+
|
41
|
+
# Build the options for launching...
|
42
|
+
options = {
|
43
|
+
:flavor_ref => flavor.id,
|
44
|
+
:image_ref => image.id,
|
45
|
+
:name => server_name,
|
46
|
+
:key_name => config.keypair_name,
|
47
|
+
:user_data_encoded => Base64.encode64(config.user_data)
|
48
|
+
}
|
49
|
+
|
50
|
+
# Create the server
|
51
|
+
server = env[:openstack_compute].servers.create(options)
|
52
|
+
|
53
|
+
# Store the ID right away so we can track it
|
54
|
+
env[:machine].id = server.id
|
55
|
+
|
56
|
+
# Wait for the server to finish building
|
57
|
+
env[:ui].info(I18n.t("vagrant_openstack.waiting_for_build"))
|
58
|
+
retryable(:on => Timeout::Error, :tries => 200) do
|
59
|
+
# If we're interrupted don't worry about waiting
|
60
|
+
next if env[:interrupted]
|
61
|
+
|
62
|
+
# Set the progress
|
63
|
+
env[:ui].clear_line
|
64
|
+
env[:ui].report_progress(server.progress, 100, false)
|
65
|
+
|
66
|
+
# Wait for the server to be ready
|
67
|
+
begin
|
68
|
+
server.wait_for(5) { ready? }
|
69
|
+
rescue RuntimeError => e
|
70
|
+
# If we don't have an error about a state transition, then
|
71
|
+
# we just move on.
|
72
|
+
raise if e.message !~ /should have transitioned/
|
73
|
+
raise Errors::CreateBadState, :state => server.state
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
if !env[:interrupted]
|
78
|
+
# Clear the line one more time so the progress is removed
|
79
|
+
env[:ui].clear_line
|
80
|
+
|
81
|
+
# Wait for SSH to become available
|
82
|
+
env[:ui].info(I18n.t("vagrant_openstack.waiting_for_ssh"))
|
83
|
+
while true
|
84
|
+
begin
|
85
|
+
# If we're interrupted then just back out
|
86
|
+
break if env[:interrupted]
|
87
|
+
break if env[:machine].communicate.ready?
|
88
|
+
rescue Errno::ENETUNREACH
|
89
|
+
end
|
90
|
+
sleep 2
|
91
|
+
end
|
92
|
+
|
93
|
+
env[:ui].info(I18n.t("vagrant_openstack.ready"))
|
94
|
+
end
|
95
|
+
|
96
|
+
@app.call(env)
|
97
|
+
end
|
98
|
+
|
99
|
+
protected
|
100
|
+
|
101
|
+
# This method finds a matching _thing_ in a collection of
|
102
|
+
# _things_. This works matching if the ID or NAME equals to
|
103
|
+
# `name`. Or, if `name` is a regexp, a partial match is chosen
|
104
|
+
# as well.
|
105
|
+
def find_matching(collection, name)
|
106
|
+
collection.each do |single|
|
107
|
+
return single if single.id == name
|
108
|
+
return single if single.name == name
|
109
|
+
return single if name.is_a?(Regexp) && name =~ single.name
|
110
|
+
end
|
111
|
+
|
112
|
+
nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module OpenStack
|
5
|
+
module Action
|
6
|
+
# This deletes the running server, if there is one.
|
7
|
+
class DeleteServer
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new("vagrant_openstack::action::delete_server")
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
if env[:machine].id
|
15
|
+
env[:ui].info(I18n.t("vagrant_openstack.deleting_server"))
|
16
|
+
server = env[:openstack_compute].servers.get(env[:machine].id)
|
17
|
+
server.destroy
|
18
|
+
env[:machine].id = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
@app.call(env)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module OpenStack
|
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_openstack.already_created"))
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module OpenStack
|
3
|
+
module Action
|
4
|
+
class MessageNotCreated
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
env[:ui].info(I18n.t("vagrant_openstack.not_created"))
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module OpenStack
|
5
|
+
module Action
|
6
|
+
# This action reads the SSH info for the machine and puts it into the
|
7
|
+
# `:machine_ssh_info` key in the environment.
|
8
|
+
class ReadSSHInfo
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new("vagrant_openstack::action::read_ssh_info")
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
env[:machine_ssh_info] = read_ssh_info(env[:openstack_compute], env[:machine])
|
16
|
+
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
def read_ssh_info(openstack, machine)
|
21
|
+
return nil if machine.id.nil?
|
22
|
+
|
23
|
+
# Find the machine
|
24
|
+
server = openstack.servers.get(machine.id)
|
25
|
+
if server.nil?
|
26
|
+
# The machine can't be found
|
27
|
+
@logger.info("Machine couldn't be found, assuming it got destroyed.")
|
28
|
+
machine.id = nil
|
29
|
+
return nil
|
30
|
+
end
|
31
|
+
|
32
|
+
config = machine.provider_config
|
33
|
+
|
34
|
+
host = server.addresses['public'].last['addr'] rescue nil
|
35
|
+
# Read the DNS info
|
36
|
+
return {
|
37
|
+
# Usually there should only be one public IP
|
38
|
+
:host => host,
|
39
|
+
:port => 22,
|
40
|
+
:username => config.ssh_username
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module OpenStack
|
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_openstack::action::read_state")
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
env[:machine_state_id] = read_state(env[:openstack_compute], env[:machine])
|
16
|
+
|
17
|
+
@app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
def read_state(openstack, machine)
|
21
|
+
return :not_created if machine.id.nil?
|
22
|
+
|
23
|
+
# Find the machine
|
24
|
+
server = openstack.servers.get(machine.id)
|
25
|
+
if server.nil? || server.state == "DELETED"
|
26
|
+
# The machine can't be found
|
27
|
+
@logger.info("Machine not found or deleted, assuming it got destroyed.")
|
28
|
+
machine.id = nil
|
29
|
+
return :not_created
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return the state
|
33
|
+
return server.state.downcase.to_sym
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "log4r"
|
2
|
+
|
3
|
+
require "vagrant/util/subprocess"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module OpenStack
|
7
|
+
module Action
|
8
|
+
# This middleware uses `rsync` to sync the folders over to the
|
9
|
+
# remote instance.
|
10
|
+
class SyncFolders
|
11
|
+
def initialize(app, env)
|
12
|
+
@app = app
|
13
|
+
@logger = Log4r::Logger.new("vagrant_openstack::action::sync_folders")
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
@app.call(env)
|
18
|
+
|
19
|
+
ssh_info = env[:machine].ssh_info
|
20
|
+
|
21
|
+
env[:machine].config.vm.synced_folders.each do |id, data|
|
22
|
+
hostpath = File.expand_path(data[:hostpath], env[:root_path])
|
23
|
+
guestpath = data[:guestpath]
|
24
|
+
|
25
|
+
# Make sure there is a trailing slash on the host path to
|
26
|
+
# avoid creating an additional directory with rsync
|
27
|
+
hostpath = "#{hostpath}/" if hostpath !~ /\/$/
|
28
|
+
|
29
|
+
env[:ui].info(I18n.t("vagrant_openstack.rsync_folder",
|
30
|
+
:hostpath => hostpath,
|
31
|
+
:guestpath => guestpath))
|
32
|
+
|
33
|
+
# Create the guest path
|
34
|
+
env[:machine].communicate.sudo("mkdir -p '#{guestpath}'")
|
35
|
+
env[:machine].communicate.sudo(
|
36
|
+
"chown #{ssh_info[:username]} '#{guestpath}'")
|
37
|
+
|
38
|
+
# Rsync over to the guest path using the SSH info
|
39
|
+
command = [
|
40
|
+
"rsync", "--verbose", "--archive", "-z",
|
41
|
+
"-e", "ssh -p #{ssh_info[:port]} -i '#{ssh_info[:private_key_path]}'",
|
42
|
+
hostpath,
|
43
|
+
"#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
|
44
|
+
|
45
|
+
r = Vagrant::Util::Subprocess.execute(*command)
|
46
|
+
if r.exit_code != 0
|
47
|
+
raise Errors::RsyncError,
|
48
|
+
:guestpath => guestpath,
|
49
|
+
:hostpath => hostpath,
|
50
|
+
:stderr => r.stderr
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module OpenStack
|
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_openstack.warn_networks"))
|
12
|
+
end
|
13
|
+
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module OpenStack
|
5
|
+
class Config < Vagrant.plugin("2", :config)
|
6
|
+
# The API key to access OpenStack.
|
7
|
+
#
|
8
|
+
# @return [String]
|
9
|
+
attr_accessor :api_key
|
10
|
+
|
11
|
+
# The endpoint to access OpenStack. If nil, it will default
|
12
|
+
# to DFW.
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
attr_accessor :endpoint
|
16
|
+
|
17
|
+
# The flavor of server to launch, either the ID or name. This
|
18
|
+
# can also be a regular expression to partially match a name.
|
19
|
+
attr_accessor :flavor
|
20
|
+
|
21
|
+
# The name or ID of the image to use. This can also be a regular
|
22
|
+
# expression to partially match a name.
|
23
|
+
attr_accessor :image
|
24
|
+
|
25
|
+
# The name of the server. This defaults to the name of the machine
|
26
|
+
# defined by Vagrant (via `config.vm.define`), but can be overriden
|
27
|
+
# here.
|
28
|
+
attr_accessor :server_name
|
29
|
+
|
30
|
+
# The username to access OpenStack.
|
31
|
+
#
|
32
|
+
# @return [String]
|
33
|
+
attr_accessor :username
|
34
|
+
|
35
|
+
# The name of the keypair to use.
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
attr_accessor :keypair_name
|
39
|
+
|
40
|
+
# The SSH username to use with this OpenStack instance. This overrides
|
41
|
+
# the `config.ssh.username` variable.
|
42
|
+
#
|
43
|
+
# @return [String]
|
44
|
+
attr_accessor :ssh_username
|
45
|
+
|
46
|
+
# User data to be sent to the newly created OpenStack instance. Use this
|
47
|
+
# e.g. to inject a script at boot time.
|
48
|
+
#
|
49
|
+
# @return [String]
|
50
|
+
attr_accessor :user_data
|
51
|
+
|
52
|
+
def initialize
|
53
|
+
@api_key = UNSET_VALUE
|
54
|
+
@endpoint = UNSET_VALUE
|
55
|
+
@flavor = UNSET_VALUE
|
56
|
+
@image = UNSET_VALUE
|
57
|
+
@server_name = UNSET_VALUE
|
58
|
+
@username = UNSET_VALUE
|
59
|
+
@keypair_name = UNSET_VALUE
|
60
|
+
@ssh_username = UNSET_VALUE
|
61
|
+
@user_data = UNSET_VALUE
|
62
|
+
end
|
63
|
+
|
64
|
+
def finalize!
|
65
|
+
@api_key = nil if @api_key == UNSET_VALUE
|
66
|
+
@endpoint = nil if @endpoint == UNSET_VALUE
|
67
|
+
@flavor = /m1.tiny/ if @flavor == UNSET_VALUE
|
68
|
+
@image = /cirros/ if @image == UNSET_VALUE
|
69
|
+
@server_name = nil if @server_name == UNSET_VALUE
|
70
|
+
@username = nil if @username == UNSET_VALUE
|
71
|
+
|
72
|
+
# Keypair defaults to nil
|
73
|
+
@keypair_name = nil if @keypair_name == UNSET_VALUE
|
74
|
+
|
75
|
+
# The SSH values by default are nil, and the top-level config
|
76
|
+
# `config.ssh` values are used.
|
77
|
+
@ssh_username = nil if @ssh_username == UNSET_VALUE
|
78
|
+
|
79
|
+
@user_data = "" if @user_data == UNSET_VALUE
|
80
|
+
end
|
81
|
+
|
82
|
+
def validate(machine)
|
83
|
+
errors = []
|
84
|
+
|
85
|
+
errors << I18n.t("vagrant_openstack.config.api_key_required") if !@api_key
|
86
|
+
errors << I18n.t("vagrant_openstack.config.username_required") if !@username
|
87
|
+
|
88
|
+
{ "OpenStack Provider" => errors }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module OpenStack
|
5
|
+
module Errors
|
6
|
+
class VagrantOpenStackError < Vagrant::Errors::VagrantError
|
7
|
+
error_namespace("vagrant_openstack.errors")
|
8
|
+
end
|
9
|
+
|
10
|
+
class CreateBadState < VagrantOpenStackError
|
11
|
+
error_key(:create_bad_state)
|
12
|
+
end
|
13
|
+
|
14
|
+
class NoMatchingFlavor < VagrantOpenStackError
|
15
|
+
error_key(:no_matching_flavor)
|
16
|
+
end
|
17
|
+
|
18
|
+
class NoMatchingImage < VagrantOpenStackError
|
19
|
+
error_key(:no_matching_image)
|
20
|
+
end
|
21
|
+
|
22
|
+
class RsyncError < VagrantOpenStackError
|
23
|
+
error_key(:rsync_error)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
begin
|
2
|
+
require "vagrant"
|
3
|
+
rescue LoadError
|
4
|
+
raise "The OpenStack Cloud provider 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.1.0"
|
10
|
+
raise "OpenStack Cloud provider is only compatible with Vagrant 1.1+"
|
11
|
+
end
|
12
|
+
|
13
|
+
module VagrantPlugins
|
14
|
+
module OpenStack
|
15
|
+
class Plugin < Vagrant.plugin("2")
|
16
|
+
name "OpenStack Cloud"
|
17
|
+
description <<-DESC
|
18
|
+
This plugin enables Vagrant to manage machines in OpenStack Cloud.
|
19
|
+
DESC
|
20
|
+
|
21
|
+
config(:openstack, :provider) do
|
22
|
+
require_relative "config"
|
23
|
+
Config
|
24
|
+
end
|
25
|
+
|
26
|
+
provider(:openstack) do
|
27
|
+
# Setup some things
|
28
|
+
OpenStack.init_i18n
|
29
|
+
OpenStack.init_logging
|
30
|
+
|
31
|
+
# Load the actual provider
|
32
|
+
require_relative "provider"
|
33
|
+
Provider
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
require "vagrant-openstack/action"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module OpenStack
|
7
|
+
class Provider < Vagrant.plugin("2", :provider)
|
8
|
+
def initialize(machine)
|
9
|
+
@machine = machine
|
10
|
+
end
|
11
|
+
|
12
|
+
def action(name)
|
13
|
+
# Attempt to get the action method from the Action class if it
|
14
|
+
# exists, otherwise return nil to show that we don't support the
|
15
|
+
# given action.
|
16
|
+
action_method = "action_#{name}"
|
17
|
+
return Action.send(action_method) if Action.respond_to?(action_method)
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def ssh_info
|
22
|
+
# Run a custom action called "read_ssh_info" which does what it
|
23
|
+
# says and puts the resulting SSH info into the `:machine_ssh_info`
|
24
|
+
# key in the environment.
|
25
|
+
env = @machine.action("read_ssh_info")
|
26
|
+
env[:machine_ssh_info]
|
27
|
+
end
|
28
|
+
|
29
|
+
def state
|
30
|
+
# Run a custom action we define called "read_state" which does
|
31
|
+
# what it says. It puts the state in the `:machine_state_id`
|
32
|
+
# key in the environment.
|
33
|
+
env = @machine.action("read_state")
|
34
|
+
|
35
|
+
state_id = env[:machine_state_id]
|
36
|
+
|
37
|
+
# Get the short and long description
|
38
|
+
short = I18n.t("vagrant_openstack.states.short_#{state_id}")
|
39
|
+
long = I18n.t("vagrant_openstack.states.long_#{state_id}")
|
40
|
+
|
41
|
+
# Return the MachineState object
|
42
|
+
Vagrant::MachineState.new(state_id, short, long)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
"OpenStack Cloud"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/locales/en.yml
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
en:
|
2
|
+
vagrant_openstack:
|
3
|
+
already_created: |-
|
4
|
+
The server is already created.
|
5
|
+
deleting_server: |-
|
6
|
+
Deleting server...
|
7
|
+
finding_flavor: |-
|
8
|
+
Finding flavor for server...
|
9
|
+
finding_image: |-
|
10
|
+
Finding image for server...
|
11
|
+
launching_server: |-
|
12
|
+
Launching a server with the following settings...
|
13
|
+
not_created: |-
|
14
|
+
The server hasn't been created yet. Run `vagrant up` first.
|
15
|
+
ready: |-
|
16
|
+
The server is ready!
|
17
|
+
rsync_folder: |-
|
18
|
+
Rsyncing folder: %{hostpath} => %{guestpath}
|
19
|
+
waiting_for_build: |-
|
20
|
+
Waiting for the server to be built...
|
21
|
+
waiting_for_ssh: |-
|
22
|
+
Waiting for SSH to become available...
|
23
|
+
warn_networks: |-
|
24
|
+
Warning! The OpenStack provider doesn't support any of the Vagrant
|
25
|
+
high-level network configurations (`config.vm.network`). They
|
26
|
+
will be silently ignored.
|
27
|
+
|
28
|
+
config:
|
29
|
+
api_key_required: |-
|
30
|
+
An API key is required.
|
31
|
+
username_required: |-
|
32
|
+
A username is required.
|
33
|
+
|
34
|
+
errors:
|
35
|
+
create_bad_state: |-
|
36
|
+
While creating the server, it transitioned to an unexpected
|
37
|
+
state: '%{state}', instead of properly booting. Run `vagrant status`
|
38
|
+
to find out what can be done about this state, or `vagrant destroy`
|
39
|
+
if you want to start over.
|
40
|
+
no_matching_flavor: |-
|
41
|
+
No matching flavor was found! Please check your flavor setting
|
42
|
+
to make sure you have a valid flavor chosen.
|
43
|
+
no_matching_image: |-
|
44
|
+
No matching image was found! Please check your image setting to
|
45
|
+
make sure you have a valid image chosen.
|
46
|
+
rsync_error: |-
|
47
|
+
There was an error when attemping to rsync a share folder.
|
48
|
+
Please inspect the error message below for more info.
|
49
|
+
|
50
|
+
Host path: %{hostpath}
|
51
|
+
Guest path: %{guestpath}
|
52
|
+
Error: %{stderr}
|
53
|
+
|
54
|
+
states:
|
55
|
+
short_active: |-
|
56
|
+
active
|
57
|
+
long_active: |-
|
58
|
+
The server is up and running. Run `vagrant ssh` to access it.
|
59
|
+
short_build: |-
|
60
|
+
building
|
61
|
+
long_build: |-
|
62
|
+
The server is currently being built. You must wait for this to
|
63
|
+
complete before you can access it. You can delete the server, however,
|
64
|
+
by running `vagrant destroy`.
|
65
|
+
short_error: |-
|
66
|
+
error
|
67
|
+
long_error: |-
|
68
|
+
The server is in an erroneous state. Destroy the machine with
|
69
|
+
`vagrant destroy`.
|
70
|
+
short_not_created: |-
|
71
|
+
not created
|
72
|
+
long_not_created: |-
|
73
|
+
The server is not created. Run `vagrant up` to create it.
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "vagrant-openstack/config"
|
2
|
+
|
3
|
+
describe VagrantPlugins::OpenStack::Config do
|
4
|
+
describe "defaults" do
|
5
|
+
let(:vagrant_public_key) { Vagrant.source_root.join("keys/vagrant.pub") }
|
6
|
+
|
7
|
+
subject do
|
8
|
+
super().tap do |o|
|
9
|
+
o.finalize!
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
its(:api_key) { should be_nil }
|
14
|
+
its(:endpoint) { should be_nil }
|
15
|
+
its(:flavor) { should eq(/m1.tiny/) }
|
16
|
+
its(:image) { should eq(/cirros/) }
|
17
|
+
its(:server_name) { should be_nil }
|
18
|
+
its(:username) { should be_nil }
|
19
|
+
its(:keypair_name) { should be_nil }
|
20
|
+
its(:ssh_username) { should be_nil }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "overriding defaults" do
|
24
|
+
[:api_key,
|
25
|
+
:endpoint,
|
26
|
+
:flavor,
|
27
|
+
:image,
|
28
|
+
:server_name,
|
29
|
+
:username,
|
30
|
+
:keypair_name,
|
31
|
+
:ssh_username].each do |attribute|
|
32
|
+
it "should not default #{attribute} if overridden" do
|
33
|
+
subject.send("#{attribute}=".to_sym, "foo")
|
34
|
+
subject.finalize!
|
35
|
+
subject.send(attribute).should == "foo"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "validation" do
|
41
|
+
let(:machine) { double("machine") }
|
42
|
+
|
43
|
+
subject do
|
44
|
+
super().tap do |o|
|
45
|
+
o.finalize!
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "with good values" do
|
50
|
+
it "should validate"
|
51
|
+
end
|
52
|
+
|
53
|
+
context "the API key" do
|
54
|
+
it "should error if not given"
|
55
|
+
end
|
56
|
+
|
57
|
+
context "the public key path" do
|
58
|
+
it "should have errors if the key doesn't exist"
|
59
|
+
it "should not have errors if the key exists with an absolute path"
|
60
|
+
it "should not have errors if the key exists with a relative path"
|
61
|
+
end
|
62
|
+
|
63
|
+
context "the username" do
|
64
|
+
it "should error if not given"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'vagrant-openstack/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "vagrant-openstack-plugin"
|
8
|
+
gem.version = VagrantPlugins::OpenStack::VERSION
|
9
|
+
gem.authors = ["Mitchell Hashimoto"]
|
10
|
+
gem.email = ["mitchell@hashicorp.com"]
|
11
|
+
gem.description = "Enables Vagrant to manage machines in OpenStack Cloud."
|
12
|
+
gem.summary = "Enables Vagrant to manage machines in OpenStack Cloud."
|
13
|
+
gem.homepage = "http://www.vagrantup.com"
|
14
|
+
|
15
|
+
gem.add_runtime_dependency "fog", "~> 1.6.0"
|
16
|
+
|
17
|
+
gem.add_development_dependency "rake"
|
18
|
+
gem.add_development_dependency "rspec", "~> 2.13.0"
|
19
|
+
|
20
|
+
gem.files = `git ls-files`.split($/)
|
21
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
22
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
23
|
+
gem.require_paths = ["lib"]
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vagrant-openstack-plugin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mitchell Hashimoto
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: fog
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.6.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.6.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.13.0
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.13.0
|
62
|
+
description: Enables Vagrant to manage machines in OpenStack Cloud.
|
63
|
+
email:
|
64
|
+
- mitchell@hashicorp.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- CHANGELOG.md
|
71
|
+
- Gemfile
|
72
|
+
- LICENSE.txt
|
73
|
+
- README.md
|
74
|
+
- Rakefile
|
75
|
+
- dummy.box
|
76
|
+
- example_box/README.md
|
77
|
+
- example_box/metadata.json
|
78
|
+
- lib/vagrant-openstack.rb
|
79
|
+
- lib/vagrant-openstack/action.rb
|
80
|
+
- lib/vagrant-openstack/action/connect_openstack.rb
|
81
|
+
- lib/vagrant-openstack/action/create_server.rb
|
82
|
+
- lib/vagrant-openstack/action/delete_server.rb
|
83
|
+
- lib/vagrant-openstack/action/is_created.rb
|
84
|
+
- lib/vagrant-openstack/action/message_already_created.rb
|
85
|
+
- lib/vagrant-openstack/action/message_not_created.rb
|
86
|
+
- lib/vagrant-openstack/action/read_ssh_info.rb
|
87
|
+
- lib/vagrant-openstack/action/read_state.rb
|
88
|
+
- lib/vagrant-openstack/action/sync_folders.rb
|
89
|
+
- lib/vagrant-openstack/action/warn_networks.rb
|
90
|
+
- lib/vagrant-openstack/config.rb
|
91
|
+
- lib/vagrant-openstack/errors.rb
|
92
|
+
- lib/vagrant-openstack/plugin.rb
|
93
|
+
- lib/vagrant-openstack/provider.rb
|
94
|
+
- lib/vagrant-openstack/version.rb
|
95
|
+
- locales/en.yml
|
96
|
+
- spec/vagrant-openstack/config_spec.rb
|
97
|
+
- vagrant-openstack.gemspec
|
98
|
+
homepage: http://www.vagrantup.com
|
99
|
+
licenses: []
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
hash: -650629708573648818
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
segments:
|
120
|
+
- 0
|
121
|
+
hash: -650629708573648818
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 1.8.24
|
125
|
+
signing_key:
|
126
|
+
specification_version: 3
|
127
|
+
summary: Enables Vagrant to manage machines in OpenStack Cloud.
|
128
|
+
test_files:
|
129
|
+
- spec/vagrant-openstack/config_spec.rb
|