Skip to content
This repository has been archived by the owner on Dec 8, 2020. It is now read-only.

Commit

Permalink
Version 0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
frapposelli committed Oct 12, 2013
2 parents a486050 + e1f2f1c commit 4a0edf2
Show file tree
Hide file tree
Showing 41 changed files with 2,329 additions and 424 deletions.
92 changes: 88 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,91 @@
# vagrant-vcloud
[Vagrant](http://www.vagrantup.com) provider for VMware vCloud Director®
=============

Vagrant provider for VMware vCloud Director®
[Version 0.1.0](https://github.com/frapposelli/vagrant-vcloud/releases/tag/v0.1.0) has been released!
-------------

Please note that this is NOT WORKING yet but You can now head over to the [develop](https://github.com/frapposelli/vagrant-vcloud/tree/develop) branch and lend us a hand :-)
Please note that this software is still Alpha/Beta quality and is not recommended for production usage.

TODO has been moved to the develop branch.
Right now a [Precise32](http://vagrant.tsugliani.fr/precise32.box) is available for use, or you can roll your own as you please, make sure to install VMware tools in it.

Features of Version 0.1.0 are:

- Basic Create/Provision/Destroy lifecycle.
- Rsync-based provisioning (working on alternatives for that).
- Use a single vApp as a container for Multi-VM Vagrantfiles.
- Use a vApp vShield Edge to perform DNAT/SNAT on a single IP for Multi-VM Vagrantfiles.
- Automatically create NAT rules on a fronting Organization Edge.
- Automatic upload of the Vagrant box to the specified catalog.
- Works on [vCloud® Hybrid Service™](http://www.vmware.com/products/vcloud-hybrid-service)!

What is still missing:

- TEST SUITES! (working on that).
- Speed, the code is definitely not optimized.
- Permission checks, make sure you have at least Catalog Admin privileges if you want to upload boxes to vCloud.
- Thorough testing.
- Error checking is absymal.
- Some spaghetti code here and there.
- Bugs, bugs and BUGS!.

If you're a developer and want to lend us a hand, head over to our ```develop``` branch and get busy!

Install
-------------

Version 0.1.0 can be easily installed by running:

```vagrant plugin install vagrant-vcloud```

Vagrant will download all the required gems during the installation process.

After the install has completed a ```vagrant up --provider=vcloud``` will trigger the newly installed provider.

Here's a sample Multi-VM Vagrantfile, please note that ```vcloud.vdc_edge_gateway``` and ```vcloud.vdc_edge_gateway_ip``` are required only when you cannot access ```vcloud.vdc_network_name``` directly and there's an Organization Edge between your workstation and the vCloud Network.

```ruby
precise32_vm_box_url = "http://vagrant.tsugliani.fr/precise32.box"

nodes = [
{ :hostname => "web-vm", :box => "precise32", :box_url => precise32_vm_box_url},
{ :hostname => "ssh-vm", :box => "precise32" , :box_url => precise32_vm_box_url},
{ :hostname => "sql-vm", :box => "precise32", :box_url => precise32_vm_box_url },
{ :hostname => "lb-vm", :box => "precise64", :box_url => precise32_vm_box_url },
{ :hostname => "app-vm", :box => "precise32", :box_url => precise32_vm_box_url },
]

Vagrant.configure("2") do |config|

# vCloud Director provider settings
config.vm.provider :vcloud do |vcloud|
vcloud.hostname = "https://my.cloudprovider.com"
vcloud.username = "MyUserName"
vcloud.password = "MySup3rS3cr3tPassw0rd!"

vcloud.org_name = "OrganizationName"
vcloud.vdc_name = "vDC_Name"

vcloud.catalog_name = "Vagrant"
vcloud.ip_subnet = "172.16.32.125/255.255.255.240"

vcloud.vdc_network_name = "MyNetwork"

vcloud.vdc_edge_gateway = "MyOrgEdgeGateway"
vcloud.vdc_edge_gateway_ip = "10.10.10.10"
end

nodes.each do |node|
config.vm.define node[:hostname] do |node_config|
node_config.vm.box = node[:box]
node_config.vm.hostname = node[:hostname]
node_config.vm.box_url = node[:box_url]
node_config.vm.network :forwarded_port, guest: 80, host: 8080, auto_correct: true
# node_config.vm.provision :puppet do |puppet|
# puppet.manifests_path = 'puppet/manifests'
# puppet.manifest_file = 'site.pp'
# puppet.module_path = 'puppet/modules'
# end
end
end
end
```
48 changes: 48 additions & 0 deletions lib/vagrant-vcloud.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,51 @@ def self.source_root
end
end
end

module Vagrant
class Machine

attr_reader :vappid

def vappid=(value)
@logger.info("New vApp ID: #{value.inspect}")

# The file that will store the id if we have one. This allows the
# ID to persist across Vagrant runs.

id_file = @data_dir.join("../../../vcloud_vappid")

### this should be ./.vagrant/vcloud_vappid

if value
# Write the "id" file with the id given.
id_file.open("w+") do |f|
f.write(value)
end
else
# Delete the file, since the machine is now destroyed
id_file.delete if id_file.file?
end

# Store the ID locally
@vappid = value

# Notify the provider that the ID changed in case it needs to do
# any accounting from it.
#@provider.machine_id_changed
end

# This returns the vCloud Director vApp ID.
#
# @return [vAppId]
def get_vapp_id
vappid_file = @data_dir.join("../../../vcloud_vappid")
if vappid_file.file?
@vappid = vappid_file.read
else
nil
end
end

end
end
143 changes: 120 additions & 23 deletions lib/vagrant-vcloud/action.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "vagrant"
require "pathname"
require "vagrant/action/builder"

module VagrantPlugins
Expand All @@ -7,14 +7,103 @@ module Action
include Vagrant::Action::Builtin

# Vagrant commands
# This action boots the VM, assuming the VM is in a state that requires
# a bootup (i.e. not saved).
def self.action_boot
Vagrant::Action::Builder.new.tap do |b|
b.use PowerOn
b.use HandleNATPortCollisions
b.use ForwardPorts
b.use Provision
b.use SyncFolders
end
end

def self.action_reload
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
b.use Call, IsCreated do |env, b2|
if !env[:result]
b2.use MessageNotCreated
next
end
b2.use action_halt
b2.use action_start
b2.use DisconnectVCloud
end
end
end

# This action starts a VM, assuming it is already imported and exists.
# A precondition of this action is that the VM exists.
def self.action_start
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
b.use ConnectVCloud
b.use Call, IsRunning do |env, b2|
# If the VM is running, then our work here is done, exit
if env[:result]
b2.use MessageAlreadyRunning
next
end
b2.use Call, IsPaused do |env2, b3|
if env2[:result]
b3.use Resume
next
end
b3.use action_boot
end
end
end
end

def self.action_halt
Vagrant::Action::Builder.new.tap do |b|
b.use ConnectVCloud
b.use Call, IsPaused do |env, b2|
if env[:result]
b2.use Resume
end
b2.use UnmapPortForwardings
b2.use PowerOff
end
end
end

def self.action_suspend
Vagrant::Action::Builder.new.tap do |b|
b.use ConnectVCloud
b.use Call, IsRunning do |env, b2|
# If the VM is stopped, can't suspend
if !env[:result]
b2.use MessageCannotSuspend
else
b2.use Suspend
end
end
end
end

def self.action_resume
Vagrant::Action::Builder.new.tap do |b|
b.use ConnectVCloud
b.use Resume
end
end

def self.action_destroy
Vagrant::Action::Builder.new.tap do |b|
b.use Call, DestroyConfirm do |env, b2|
if env[:result]
b2.use ConfigValidate
b2.use ConnectVCloud
b2.use PowerOff
b2.use Destroy
b2.use Call, IsRunning do |env2, b3|
# If the VM is running, must power off
if env2[:result]
b3.use action_halt
end
b3.use Destroy
end
else
b2.use MessageWillNotDestroy
end
Expand All @@ -30,9 +119,7 @@ def self.action_provision
b2.use MessageNotCreated
next
end

b2.use Provision
### TODO --- explore UNISON!
b2.use SyncFolders
end
end
Expand Down Expand Up @@ -68,8 +155,9 @@ def self.action_ssh
b2.use MessageNotCreated
next
end

b2.use SSHExec
# This calls our helper that announces the IP used to connect
# to the VM, either directly to the vApp vShield or to the Org Edge.
b2.use AnnounceSSHExec
end
end
end
Expand All @@ -91,39 +179,48 @@ def self.action_ssh_run
def self.action_up
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
b.use HandleBoxUrl #### THIS IS A BUILTIN FUNCTION TO HANDLE THE BOX DOWNLOAD, MUST BE USED!!!
b.use Call, IsCreated do |env, b2|
if !env[:result]
b2.use HandleBoxUrl
end
end
b.use ConnectVCloud
b.use Call, IsCreated do |env, b2|
if env[:result]
#puts "DUMPING STUFF: " + env.inspect
b2.use MessageAlreadyCreated
next
if !env[:result]
b2.use InventoryCheck
b2.use BuildVApp
end

b2.use Clone
# TODO: provision
b2.use TimedProvision
# TODO: sync folders
b2.use SyncFolders
end
b.use action_start
b.use DisconnectVCloud
end
end

# The autoload farm
action_root = Pathname.new(File.expand_path("../action", __FILE__))
autoload :AnnounceSSHExec, action_root.join("announce_ssh_exec")
autoload :BuildVApp, action_root.join("build_vapp")
autoload :ConnectVCloud, action_root.join("connect_vcloud")
autoload :Destroy, action_root.join("destroy")
autoload :DisconnectVCloud, action_root.join("disconnect_vcloud")
autoload :ForwardPorts, action_root.join("forward_ports")
autoload :HandleNATPortCollisions, action_root.join("handle_nat_port_collisions")
autoload :InventoryCheck, action_root.join("inventory_check")
autoload :IsCreated, action_root.join("is_created")
autoload :MessageAlreadyCreated, action_root.join("message_already_created")
autoload :IsPaused, action_root.join("is_paused")
autoload :IsRunning, action_root.join("is_running")
autoload :MessageAlreadyRunning, action_root.join("message_already_running")
autoload :MessageCannotSuspend, action_root.join("message_cannot_suspend")
autoload :MessageNotCreated, action_root.join("message_not_created")
autoload :MessageWillNotDestroy, action_root.join("message_will_not_destroy")
autoload :PowerOff, action_root.join("power_off")
autoload :PowerOn, action_root.join("power_on")
autoload :ReadSSHInfo, action_root.join("read_ssh_info")
autoload :ReadState, action_root.join("read_state")
autoload :RunInstance, action_root.join("run_instance")
autoload :Resume, action_root.join("resume")
autoload :Suspend, action_root.join("suspend")
autoload :SyncFolders, action_root.join("sync_folders")
autoload :TimedProvision, action_root.join("timed_provision")
autoload :UnmapPortForwardings, action_root.join("unmap_port_forwardings")
end
end
end

end
17 changes: 17 additions & 0 deletions lib/vagrant-vcloud/action/announce_ssh_exec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module VagrantPlugins
module VCloud
module Action
class AnnounceSSHExec < Vagrant::Action::Builtin::SSHExec
def initialize(app, env)
@app = app
end

def call(env)
sshInfo = env[:machine].ssh_info
env[:ui].success("External IP for #{env[:machine].name}: #{sshInfo[:host]}")
super
end
end
end
end
end
Loading

0 comments on commit 4a0edf2

Please sign in to comment.