ironfan 4.8.7 → 4.9.0
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/CHANGELOG.md +3 -0
- data/Gemfile.lock +25 -26
- data/VERSION +1 -1
- data/config/ubuntu12.04-ironfan.erb +1 -1
- data/ironfan.gemspec +7 -3
- data/lib/chef/knife/bootstrap/ubuntu12.04-ironfan.erb +1 -1
- data/lib/chef/knife/ironfan_knife_common.rb +1 -0
- data/lib/ironfan/dsl/cloud.rb +1 -0
- data/lib/ironfan/dsl/vsphere.rb +89 -0
- data/lib/ironfan/headers.rb +6 -0
- data/lib/ironfan/provider/vsphere/keypair.rb +74 -0
- data/lib/ironfan/provider/vsphere/machine.rb +343 -0
- data/lib/ironfan/provider/vsphere.rb +79 -0
- data/lib/ironfan/provider.rb +1 -0
- data/lib/ironfan/requirements.rb +5 -0
- metadata +154 -99
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -27,16 +27,16 @@ GEM
|
|
|
27
27
|
configliere (0.4.18)
|
|
28
28
|
highline (>= 1.5.2)
|
|
29
29
|
multi_json (>= 1.1)
|
|
30
|
-
diff-lcs (1.2.
|
|
30
|
+
diff-lcs (1.2.2)
|
|
31
31
|
erubis (2.7.0)
|
|
32
|
-
excon (0.
|
|
33
|
-
fog (1.
|
|
32
|
+
excon (0.20.1)
|
|
33
|
+
fog (1.10.1)
|
|
34
34
|
builder
|
|
35
|
-
excon (~> 0.
|
|
35
|
+
excon (~> 0.20)
|
|
36
36
|
formatador (~> 0.2.0)
|
|
37
37
|
mime-types
|
|
38
38
|
multi_json (~> 1.0)
|
|
39
|
-
net-scp (~> 1.
|
|
39
|
+
net-scp (~> 1.1)
|
|
40
40
|
net-ssh (>= 2.1.3)
|
|
41
41
|
nokogiri (~> 1.5.0)
|
|
42
42
|
ruby-hmac
|
|
@@ -46,19 +46,19 @@ GEM
|
|
|
46
46
|
configliere (>= 0.4.13)
|
|
47
47
|
json
|
|
48
48
|
multi_json (>= 1.1)
|
|
49
|
-
guard (1.
|
|
49
|
+
guard (1.7.0)
|
|
50
|
+
formatador (>= 0.2.4)
|
|
50
51
|
listen (>= 0.6.0)
|
|
51
52
|
lumberjack (>= 1.0.2)
|
|
52
53
|
pry (>= 0.9.10)
|
|
53
|
-
terminal-table (>= 1.4.3)
|
|
54
54
|
thor (>= 0.14.6)
|
|
55
|
-
guard-rspec (2.
|
|
55
|
+
guard-rspec (2.5.2)
|
|
56
56
|
guard (>= 1.1)
|
|
57
57
|
rspec (~> 2.11)
|
|
58
|
-
guard-yard (2.0
|
|
58
|
+
guard-yard (2.1.0)
|
|
59
59
|
guard (>= 1.1.0)
|
|
60
60
|
yard (>= 0.7.0)
|
|
61
|
-
highline (1.6.
|
|
61
|
+
highline (1.6.16)
|
|
62
62
|
ipaddress (0.8.0)
|
|
63
63
|
jeweler (1.8.4)
|
|
64
64
|
bundler (~> 1.0)
|
|
@@ -69,26 +69,26 @@ GEM
|
|
|
69
69
|
linecache19 (0.5.12)
|
|
70
70
|
ruby_core_source (>= 0.1.4)
|
|
71
71
|
listen (0.7.3)
|
|
72
|
-
lumberjack (1.0.
|
|
72
|
+
lumberjack (1.0.3)
|
|
73
73
|
method_source (0.8.1)
|
|
74
|
-
mime-types (1.
|
|
74
|
+
mime-types (1.22)
|
|
75
75
|
mixlib-authentication (1.3.0)
|
|
76
76
|
mixlib-log
|
|
77
77
|
mixlib-cli (1.3.0)
|
|
78
78
|
mixlib-config (1.1.2)
|
|
79
|
-
mixlib-log (1.
|
|
79
|
+
mixlib-log (1.6.0)
|
|
80
80
|
mixlib-shellout (1.1.0)
|
|
81
81
|
moneta (0.6.0)
|
|
82
|
-
multi_json (1.
|
|
83
|
-
net-scp (1.0
|
|
84
|
-
net-ssh (>=
|
|
85
|
-
net-ssh (2.6.
|
|
82
|
+
multi_json (1.7.2)
|
|
83
|
+
net-scp (1.1.0)
|
|
84
|
+
net-ssh (>= 2.6.5)
|
|
85
|
+
net-ssh (2.6.6)
|
|
86
86
|
net-ssh-gateway (1.2.0)
|
|
87
87
|
net-ssh (>= 2.6.5)
|
|
88
88
|
net-ssh-multi (1.1)
|
|
89
89
|
net-ssh (>= 2.1.4)
|
|
90
90
|
net-ssh-gateway (>= 0.99.0)
|
|
91
|
-
nokogiri (1.5.
|
|
91
|
+
nokogiri (1.5.9)
|
|
92
92
|
ohai (6.16.0)
|
|
93
93
|
ipaddress
|
|
94
94
|
mixlib-cli
|
|
@@ -97,14 +97,14 @@ GEM
|
|
|
97
97
|
mixlib-shellout
|
|
98
98
|
systemu
|
|
99
99
|
yajl-ruby
|
|
100
|
-
oj (2.0.
|
|
100
|
+
oj (2.0.10)
|
|
101
101
|
polyglot (0.3.3)
|
|
102
102
|
pry (0.9.12)
|
|
103
103
|
coderay (~> 1.0.5)
|
|
104
104
|
method_source (~> 0.8)
|
|
105
105
|
slop (~> 3.4)
|
|
106
|
-
rake (10.0.
|
|
107
|
-
rdoc (4.0.
|
|
106
|
+
rake (10.0.4)
|
|
107
|
+
rdoc (4.0.1)
|
|
108
108
|
json (~> 1.4)
|
|
109
109
|
redcarpet (2.2.2)
|
|
110
110
|
rest-client (1.6.7)
|
|
@@ -113,10 +113,10 @@ GEM
|
|
|
113
113
|
rspec-core (~> 2.13.0)
|
|
114
114
|
rspec-expectations (~> 2.13.0)
|
|
115
115
|
rspec-mocks (~> 2.13.0)
|
|
116
|
-
rspec-core (2.13.
|
|
116
|
+
rspec-core (2.13.1)
|
|
117
117
|
rspec-expectations (2.13.0)
|
|
118
118
|
diff-lcs (>= 1.1.3, < 2.0)
|
|
119
|
-
rspec-mocks (2.13.
|
|
119
|
+
rspec-mocks (2.13.1)
|
|
120
120
|
ruby-debug-base19 (0.11.25)
|
|
121
121
|
columnize (>= 0.3.1)
|
|
122
122
|
linecache19 (>= 0.5.11)
|
|
@@ -133,10 +133,9 @@ GEM
|
|
|
133
133
|
multi_json (~> 1.0)
|
|
134
134
|
simplecov-html (~> 0.7.1)
|
|
135
135
|
simplecov-html (0.7.1)
|
|
136
|
-
slop (3.4.
|
|
136
|
+
slop (3.4.4)
|
|
137
137
|
systemu (2.5.2)
|
|
138
|
-
|
|
139
|
-
thor (0.17.0)
|
|
138
|
+
thor (0.18.1)
|
|
140
139
|
treetop (1.4.12)
|
|
141
140
|
polyglot
|
|
142
141
|
polyglot (>= 0.3.1)
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.9.0
|
data/ironfan.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = "ironfan"
|
|
8
|
-
s.version = "4.
|
|
8
|
+
s.version = "4.9.0"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Infochimps"]
|
|
12
|
-
s.date = "2013-
|
|
12
|
+
s.date = "2013-04-09"
|
|
13
13
|
s.description = "Ironfan allows you to orchestrate not just systems but clusters of machines. It includes a powerful layer on top of knife and a collection of cloud cookbooks."
|
|
14
14
|
s.email = "coders@infochimps.com"
|
|
15
15
|
s.extra_rdoc_files = [
|
|
@@ -73,6 +73,7 @@ Gem::Specification.new do |s|
|
|
|
73
73
|
"lib/ironfan/dsl/server.rb",
|
|
74
74
|
"lib/ironfan/dsl/virtualbox.rb",
|
|
75
75
|
"lib/ironfan/dsl/volume.rb",
|
|
76
|
+
"lib/ironfan/dsl/vsphere.rb",
|
|
76
77
|
"lib/ironfan/headers.rb",
|
|
77
78
|
"lib/ironfan/provider.rb",
|
|
78
79
|
"lib/ironfan/provider/chef.rb",
|
|
@@ -90,6 +91,9 @@ Gem::Specification.new do |s|
|
|
|
90
91
|
"lib/ironfan/provider/ec2/security_group.rb",
|
|
91
92
|
"lib/ironfan/provider/virtualbox.rb",
|
|
92
93
|
"lib/ironfan/provider/virtualbox/machine.rb",
|
|
94
|
+
"lib/ironfan/provider/vsphere.rb",
|
|
95
|
+
"lib/ironfan/provider/vsphere/keypair.rb",
|
|
96
|
+
"lib/ironfan/provider/vsphere/machine.rb",
|
|
93
97
|
"lib/ironfan/requirements.rb",
|
|
94
98
|
"notes/Future-development-proposals.md",
|
|
95
99
|
"notes/Home.md",
|
|
@@ -149,7 +153,7 @@ Gem::Specification.new do |s|
|
|
|
149
153
|
s.homepage = "http://infochimps.com/labs"
|
|
150
154
|
s.licenses = ["apachev2"]
|
|
151
155
|
s.require_paths = ["lib"]
|
|
152
|
-
s.rubygems_version = "1.8.
|
|
156
|
+
s.rubygems_version = "1.8.23"
|
|
153
157
|
s.summary = "Infochimps' lightweight cloud orchestration toolkit, built on top of Chef."
|
|
154
158
|
s.test_files = ["spec/spec_helper/dummy_chef.rb", "spec/integration/spec_helper/launch_cluster.rb", "spec/integration/minimal-chef-repo/roles/systemwide.rb", "spec/integration/minimal-chef-repo/environments/_default.json", "spec/integration/minimal-chef-repo/chefignore", "spec/integration/minimal-chef-repo/knife/knife.rb", "spec/integration/minimal-chef-repo/knife/credentials/knife-org.rb", "spec/integration/spec/simple_cluster_spec.rb", "spec/integration/spec/elb_build_spec.rb", "spec/integration/spec_helper.rb", "spec/ironfan/cluster_spec.rb", "spec/ironfan/ec2/cloud_provider_spec.rb", "spec/ironfan/ec2/elb_spec.rb", "spec/ironfan/ec2/security_group_spec.rb", "spec/chef/cluster_launch_spec.rb", "spec/chef/cluster_bootstrap_spec.rb", "spec/fixtures/gunbai_slice.json", "spec/fixtures/ec2/elb/snakeoil.key", "spec/fixtures/ec2/elb/snakeoil.crt", "spec/fixtures/gunbai.rb", "spec/spec_helper.rb", "spec/test_config.rb"]
|
|
155
159
|
|
data/lib/ironfan/dsl/cloud.rb
CHANGED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
module Ironfan
|
|
2
|
+
class Dsl
|
|
3
|
+
|
|
4
|
+
class Compute < Ironfan::Dsl
|
|
5
|
+
def vsphere(*attrs,&block)
|
|
6
|
+
cloud(:vsphere, *attrs,&block)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class Vsphere < Cloud
|
|
11
|
+
magic :backing, String, :default => ''
|
|
12
|
+
magic :bits, Integer, :default => "64"
|
|
13
|
+
magic :bootstrap_distro, String, :default => 'ubuntu12.04-gems'
|
|
14
|
+
magic :chef_client_script, String
|
|
15
|
+
magic :cluster, String
|
|
16
|
+
magic :cpus, String, :default => "1"
|
|
17
|
+
magic :datacenter, String, :default => ->{ default_datacenter }
|
|
18
|
+
magic :datastore, String
|
|
19
|
+
magic :dns_servers, Array
|
|
20
|
+
magic :domain, String
|
|
21
|
+
magic :default_datacenter, String, :default => ->{ vsphere_datacenters.first }
|
|
22
|
+
magic :gateway, Array
|
|
23
|
+
magic :image_name, String
|
|
24
|
+
magic :ip, String
|
|
25
|
+
magic :memory, String, :default => "4" # Gigabytes
|
|
26
|
+
magic :provider, Whatever, :default => Ironfan::Provider::Vsphere
|
|
27
|
+
magic :ssh_identity_dir, String, :default => ->{ Chef::Config.vsphere_key_dir }
|
|
28
|
+
magic :ssh_user, String, :default => "root"
|
|
29
|
+
magic :subnet, String
|
|
30
|
+
magic :template, String
|
|
31
|
+
magic :validation_key, String, :default => ->{ IO.read(Chef::Config.validation_key) rescue '' }
|
|
32
|
+
magic :virtual_disks, Array, :default => []
|
|
33
|
+
magic :vsphere_datacenters, Array, :default => ['New Datacenter']
|
|
34
|
+
magic :network, String, :default => "VM Network"
|
|
35
|
+
|
|
36
|
+
def image_info
|
|
37
|
+
bit_str = "#{self.bits.to_i}-bit" # correct for legacy image info.
|
|
38
|
+
keys = [datacenter, bit_str, image_name]
|
|
39
|
+
# info = Chef::Config[:vsphere_image_info][ keys ]
|
|
40
|
+
info = nil
|
|
41
|
+
ui.warn("Can't find image for #{[datacenter, bit_str, image_name].inspect}") if info.blank?
|
|
42
|
+
return info || {}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def implied_volumes
|
|
46
|
+
result = []
|
|
47
|
+
# FIXME : This is really making assumptions
|
|
48
|
+
result << Ironfan::Dsl::Volume.new(:name => 'root') do
|
|
49
|
+
device '/dev/sda1'
|
|
50
|
+
fstype 'ext4'
|
|
51
|
+
keep false
|
|
52
|
+
mount_point '/'
|
|
53
|
+
end
|
|
54
|
+
return result unless virtual_disks.length > 0
|
|
55
|
+
|
|
56
|
+
virtual_disks.each_with_index do |vd, idx|
|
|
57
|
+
dev, mnt = ["/dev/sd%s" %[(66 + idx).chr.downcase], idx == 0 ? "/mnt" : "/mnt#{idx}"] # WHAAAaaa 0 o ???
|
|
58
|
+
virtualdisk = Ironfan::Dsl::Volume.new(:name => "virtualdisk#{idx}") do
|
|
59
|
+
attachable "VirtualDisk"
|
|
60
|
+
fstype vd[:fs]
|
|
61
|
+
device dev
|
|
62
|
+
mount_point vd[:mount_point] || mnt
|
|
63
|
+
formattable true
|
|
64
|
+
create_at_launch true
|
|
65
|
+
mount_options 'defaults,noatime'
|
|
66
|
+
tags vd[:tags]
|
|
67
|
+
end
|
|
68
|
+
result << virtualdisk
|
|
69
|
+
end
|
|
70
|
+
result
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def ssh_identity_file(computer)
|
|
74
|
+
cluster = computer.server.cluster_name
|
|
75
|
+
"%s/%s.pem" %[ssh_identity_dir, cluster]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def to_display(style,values={})
|
|
79
|
+
return values if style == :minimal
|
|
80
|
+
|
|
81
|
+
values["Datacenter"] = datacenter
|
|
82
|
+
return values if style == :default
|
|
83
|
+
|
|
84
|
+
values
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
data/lib/ironfan/headers.rb
CHANGED
|
@@ -30,6 +30,7 @@ module Ironfan
|
|
|
30
30
|
class IamServerCertificate < Ironfan::Dsl; end
|
|
31
31
|
end
|
|
32
32
|
class VirtualBox < Cloud; end
|
|
33
|
+
class Vsphere < Cloud; end
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
class Provider < Builder
|
|
@@ -57,6 +58,11 @@ module Ironfan
|
|
|
57
58
|
class VirtualBox < Ironfan::IaasProvider
|
|
58
59
|
class Machine < Ironfan::IaasProvider::Machine; end
|
|
59
60
|
end
|
|
61
|
+
class Vsphere < Ironfan::IaasProvider
|
|
62
|
+
class Machine < Ironfan::IaasProvider::Machine; end
|
|
63
|
+
class Keypair < Ironfan::Provider::Resource; end
|
|
64
|
+
end
|
|
65
|
+
|
|
60
66
|
end
|
|
61
67
|
|
|
62
68
|
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module Ironfan
|
|
2
|
+
class Provider
|
|
3
|
+
class Vsphere
|
|
4
|
+
|
|
5
|
+
class Keypair < Ironfan::Provider::Resource
|
|
6
|
+
delegate :connection, :connection=, :name, :private_key,
|
|
7
|
+
:to => :adaptee
|
|
8
|
+
# delegate :_dump, :collection, :collection=, :connection,
|
|
9
|
+
# :connection=, :destroy, :fingerprint, :fingerprint=, :identity,
|
|
10
|
+
# :identity=, :name, :name=, :new_record?, :public_key,
|
|
11
|
+
# :public_key=, :reload, :requires, :requires_one, :save,
|
|
12
|
+
# :symbolize_keys, :wait_for, :writable?, :write,
|
|
13
|
+
# :to => :adaptee
|
|
14
|
+
|
|
15
|
+
field :key_filename, String, :default => ->{ "#{Keypair.key_dir}/#{name}.pem" }
|
|
16
|
+
|
|
17
|
+
def self.shared? ; true ; end
|
|
18
|
+
def self.multiple? ; false ; end
|
|
19
|
+
def self.resource_type ; :keypair ; end
|
|
20
|
+
|
|
21
|
+
def self.expected_ids(computer)
|
|
22
|
+
[computer.server.cluster_name]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def private_key
|
|
26
|
+
puts "pkey"
|
|
27
|
+
File.open(key_filename, "rb").read
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.public_key(computer)
|
|
31
|
+
key_filename = "%s/%s.pem" %[key_dir, computer.server.cluster_name]
|
|
32
|
+
key = OpenSSL::PKey::RSA.new(File.open(key_filename, "rb").read)
|
|
33
|
+
data = [ key.to_blob ].pack('m0')
|
|
34
|
+
"#{key.ssh_type} #{data}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.create_private_key(key, name)
|
|
38
|
+
key_filename = "%s/%s.pem" %[key_dir, name]
|
|
39
|
+
File.open(key_filename, "w", 0600){|f| f.print( key.to_s ) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def to_s
|
|
43
|
+
"<%-15s %-12s>" % [self.class.handle, name]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# Manipulation
|
|
48
|
+
#
|
|
49
|
+
|
|
50
|
+
def self.prepare!(computers)
|
|
51
|
+
return if computers.empty?
|
|
52
|
+
name = computers.values[0].server.cluster_name
|
|
53
|
+
return if recall? name
|
|
54
|
+
return if File.exists?("%s/%s.pem" %[key_dir, name])
|
|
55
|
+
Ironfan.step(name, "creating key pair for #{name}", :blue)
|
|
56
|
+
Dir.mkdir(key_dir) if !FileTest::directory?(key_dir)
|
|
57
|
+
create_private_key(OpenSSL::PKey::RSA.new(2048), name)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
#
|
|
61
|
+
# Utility
|
|
62
|
+
#
|
|
63
|
+
|
|
64
|
+
def self.key_dir
|
|
65
|
+
return Chef::Config.vsphere_key_dir if Chef::Config.vsphere_key_dir
|
|
66
|
+
dir = "#{ENV['HOME']}/.chef/credentials/vshere_keys"
|
|
67
|
+
warn "Please set 'vsphere_key_dir' in your knife.rb. Will use #{dir} as a default"
|
|
68
|
+
dir
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
module Ironfan
|
|
2
|
+
class Provider
|
|
3
|
+
class Vsphere
|
|
4
|
+
|
|
5
|
+
class Machine < Ironfan::IaasProvider::Machine
|
|
6
|
+
delegate :config, :connection, :connection=, :disks, :Destroy_Task, :guest, :PowerOffVM_Task,
|
|
7
|
+
:PowerOnVM_Task, :powerState, :ReconfigVM_Task, :runtime,
|
|
8
|
+
:to => :adaptee
|
|
9
|
+
|
|
10
|
+
def self.shared?() false; end
|
|
11
|
+
def self.multiple?() false; end
|
|
12
|
+
def self.resource_type() :machine; end
|
|
13
|
+
def self.expected_ids(computer) [computer.server.full_name]; end
|
|
14
|
+
|
|
15
|
+
def name
|
|
16
|
+
return adaptee.config.name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def keypair
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def vpc_id
|
|
23
|
+
return true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def dns_name
|
|
27
|
+
host = adaptee.guest.hostName
|
|
28
|
+
domain = adaptee.guest.domainName
|
|
29
|
+
return host unless domain
|
|
30
|
+
return "%s.%s" %[host, domain]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def public_ip_address
|
|
34
|
+
# FIXME
|
|
35
|
+
return adaptee.guest.ipAddress
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def private_ip_address
|
|
39
|
+
return adaptee.guest.ipAddress
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def public_hostname
|
|
43
|
+
# FIXME
|
|
44
|
+
return nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def destroy
|
|
48
|
+
adaptee.PowerOffVM_Task.wait_for_completion unless adaptee.runtime.powerState == "poweredOff"
|
|
49
|
+
adaptee.Destroy_Task.wait_for_completion
|
|
50
|
+
state = "destroyed"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def created?
|
|
54
|
+
["poweredOn", "poweredOff"].include? adaptee.runtime.powerState
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def wait_for
|
|
58
|
+
return true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def running?
|
|
62
|
+
adaptee.runtime.powerState == "poweredOn"
|
|
63
|
+
state = "poweredOn"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def stopped?
|
|
67
|
+
adaptee.runtime.powerState == "poweredOff"
|
|
68
|
+
state = "poweredOff"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def start
|
|
72
|
+
adaptee.PowerOnVM_Task.wait_for_completion
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def stop
|
|
76
|
+
# TODO: Gracefully shutdown guest using adatee.ShutdownGuest ?
|
|
77
|
+
# There is no "wait_for_completion" with this however...
|
|
78
|
+
adaptee.PowerOffVM_Task.wait_for_completion
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.ip_settings(settings, hostname)
|
|
82
|
+
# FIXME: A lot of this is required if using a static IP
|
|
83
|
+
# Heavily referenced Serengeti's FOG here
|
|
84
|
+
|
|
85
|
+
ip_settings = RbVmomi::VIM::CustomizationIPSettings.new(:ip =>
|
|
86
|
+
RbVmomi::VIM::CustomizationFixedIp(:ipAddress => settings[:ip]), :gateway => settings[:gateway], :subnetMask => settings[:subnet]) if settings[:ip]
|
|
87
|
+
ip_settings ||= RbVmomi::VIM::CustomizationIPSettings.new("ip" => RbVmomi::VIM::CustomizationDhcpIpGenerator.new())
|
|
88
|
+
ip_settings.dnsDomain = settings[:domain]
|
|
89
|
+
global_ip_settings = RbVmomi::VIM.CustomizationGlobalIPSettings
|
|
90
|
+
global_ip_settings.dnsServerList = settings[:dnsServers]
|
|
91
|
+
global_ip_settings.dnsSuffixList = [settings[:domain]]
|
|
92
|
+
hostname = RbVmomi::VIM::CustomizationFixedName.new(:name => hostname)
|
|
93
|
+
linux_prep = RbVmomi::VIM::CustomizationLinuxPrep.new( :domain => settings[:domain], :hostName => hostname )
|
|
94
|
+
adapter_mapping = [RbVmomi::VIM::CustomizationAdapterMapping.new("adapter" => ip_settings)]
|
|
95
|
+
spec = RbVmomi::VIM::CustomizationSpec.new( :identity => linux_prep,
|
|
96
|
+
:globalIPSettings => global_ip_settings,
|
|
97
|
+
:nicSettingMap => adapter_mapping )
|
|
98
|
+
|
|
99
|
+
return spec
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def self.generate_clone_spec(src_config, dc, cpus, memory, datastore, virtual_disks, network, cluster)
|
|
104
|
+
# TODO : A lot of this should be moved to utilities in providers/vsphere.rb
|
|
105
|
+
rspec = Vsphere.get_rspec(dc, cluster)
|
|
106
|
+
rspec.datastore = datastore
|
|
107
|
+
|
|
108
|
+
clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => rspec, :template => false, :powerOn => true)
|
|
109
|
+
clone_spec.config = RbVmomi::VIM.VirtualMachineConfigSpec(:deviceChange => Array.new, :extraConfig => nil)
|
|
110
|
+
|
|
111
|
+
network = Vsphere.find_network(network, dc)
|
|
112
|
+
card = src_config.hardware.device.find { |d| d.deviceInfo.label == "Network adapter 1" }
|
|
113
|
+
begin
|
|
114
|
+
switch_port = RbVmomi::VIM.DistributedVirtualSwitchPortConnection(
|
|
115
|
+
:switchUuid => network.config.distributedVirtualSwitch.uuid,
|
|
116
|
+
:portgroupKey => network.key
|
|
117
|
+
)
|
|
118
|
+
card.backing.port = switch_port
|
|
119
|
+
rescue
|
|
120
|
+
card.backing.deviceName = network.name
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
network_spec = RbVmomi::VIM.VirtualDeviceConfigSpec(:device => card, :operation => "edit")
|
|
124
|
+
clone_spec.config.deviceChange.push network_spec
|
|
125
|
+
|
|
126
|
+
virtual_disks.each_with_index do |vd, idx|
|
|
127
|
+
size = vd[:size].to_i
|
|
128
|
+
label = vd[:label].to_i
|
|
129
|
+
key = 2001 + idx # key 2000 -> SCSI0, 2001 -> SCSI1...
|
|
130
|
+
filename = vd[:datastore] || datastore.name
|
|
131
|
+
|
|
132
|
+
disk = RbVmomi::VIM.VirtualDisk(
|
|
133
|
+
:key => key,
|
|
134
|
+
:capacityInKB => size * 1024 * 1024,
|
|
135
|
+
:controllerKey => 1000, # SCSI controller
|
|
136
|
+
:unitNumber => idx + 1,
|
|
137
|
+
:backing => RbVmomi::VIM.VirtualDiskFlatVer2BackingInfo(
|
|
138
|
+
:fileName => "[#{filename}]",
|
|
139
|
+
:diskMode => :persistent,
|
|
140
|
+
:thinProvisioned => true,
|
|
141
|
+
:datastore => Vsphere.find_ds(dc, vd[:datastore]) || datastore
|
|
142
|
+
),
|
|
143
|
+
:deviceInfo => RbVmomi::VIM.Description(
|
|
144
|
+
:label => label,
|
|
145
|
+
:summary => "%sGB" %[size]
|
|
146
|
+
),
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
disk_spec = {:operation => :add, :fileOperation => :create, :device => disk }
|
|
150
|
+
clone_spec.config.deviceChange.push disk_spec
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
clone_spec.config.numCPUs = Integer(cpus)
|
|
154
|
+
clone_spec.config.memoryMB = Integer(memory) * 1024
|
|
155
|
+
|
|
156
|
+
clone_spec
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def self.create!(computer)
|
|
160
|
+
return if computer.machine? and computer.machine.created?
|
|
161
|
+
Ironfan.step(computer.name,"creating cloud machine", :green)
|
|
162
|
+
|
|
163
|
+
errors = lint(computer)
|
|
164
|
+
if errors.present? then raise ArgumentError, "Failed validation: #{errors.inspect}" ; end
|
|
165
|
+
|
|
166
|
+
# TODO: Pass launch_desc to a single function and let it do the rest... like fog does
|
|
167
|
+
launch_desc = launch_description(computer)
|
|
168
|
+
cpus = launch_desc[:cpus]
|
|
169
|
+
datacenter = launch_desc[:datacenter]
|
|
170
|
+
memory = launch_desc[:memory]
|
|
171
|
+
template = launch_desc[:template]
|
|
172
|
+
user_data = launch_desc[:user_data]
|
|
173
|
+
virtual_disks = launch_desc[:virtual_disks]
|
|
174
|
+
network = launch_desc[:network]
|
|
175
|
+
ip_settings = launch_desc[:ip_settings]
|
|
176
|
+
|
|
177
|
+
datacenter = Vsphere.find_dc(launch_desc[:datacenter])
|
|
178
|
+
raise "Couldn't find #{launch_desc[:datacenter]} datacenter" unless datacenter
|
|
179
|
+
cluster = Vsphere.find_in_folder(datacenter.hostFolder, RbVmomi::VIM::ClusterComputeResource, launch_desc[:cluster])
|
|
180
|
+
raise "Couldn't find #{launch_desc[:cluster]} cluster in #{datacenter}" unless cluster
|
|
181
|
+
datastore = Vsphere.find_ds(datacenter, launch_desc[:datastore]) # FIXME: add in round robin choosing?
|
|
182
|
+
raise "Couldn't find #{launch_desc[:datastore]} datastore in #{datacenter}" unless datastore
|
|
183
|
+
src_folder = datacenter.vmFolder
|
|
184
|
+
src_vm = Vsphere.find_in_folder(src_folder, RbVmomi::VIM::VirtualMachine, template)
|
|
185
|
+
raise "Couldn't find template #{template} in #{datacenter}:#{cluster}" unless src_vm
|
|
186
|
+
|
|
187
|
+
Ironfan.safely do
|
|
188
|
+
clone_spec = generate_clone_spec(src_vm.config, datacenter, cpus, memory, datastore, virtual_disks, network, cluster)
|
|
189
|
+
clone_spec.customization = ip_settings(ip_settings, computer.name) if ip_settings[:ip]
|
|
190
|
+
|
|
191
|
+
vsphere_server = src_vm.CloneVM_Task(:folder => src_vm.parent, :name => computer.name, :spec => clone_spec)
|
|
192
|
+
|
|
193
|
+
state = vsphere_server.info.state # RbVmomi wait_for_completion stops world...
|
|
194
|
+
while (state != 'error') and (state != 'success')
|
|
195
|
+
sleep 2
|
|
196
|
+
state = vsphere_server.info.state
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Will break if the VM isn't finished building.
|
|
200
|
+
new_vm = Vsphere.find_in_folder(src_folder, RbVmomi::VIM::VirtualMachine, computer.name)
|
|
201
|
+
machine = Machine.new(:adaptee => new_vm)
|
|
202
|
+
computer.machine = machine
|
|
203
|
+
remember machine, :id => machine.name
|
|
204
|
+
|
|
205
|
+
Ironfan.step(computer.name,"pushing keypair", :green)
|
|
206
|
+
public_key = Vsphere::Keypair.public_key(computer)
|
|
207
|
+
# TODO - This probably belongs somewhere else. This is how we'll enject the pubkey as well as any user information we may want
|
|
208
|
+
# This data is not persistent across reboots...
|
|
209
|
+
extraConfig = [{:key => 'guestinfo.pubkey', :value => public_key}, {:key => "guestinfo.user_data", :value => user_data}]
|
|
210
|
+
machine.ReconfigVM_Task(:spec => RbVmomi::VIM::VirtualMachineConfigSpec(:extraConfig => extraConfig)).wait_for_completion
|
|
211
|
+
|
|
212
|
+
# FIXME: This is extremelty fragile right now
|
|
213
|
+
if ip_settings[:ip]
|
|
214
|
+
Ironfan.step(computer.name,"waiting for ip customizations to complete", :green)
|
|
215
|
+
while machine.guest.ipAddress != ip_settings[:ip]
|
|
216
|
+
sleep 2
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
#
|
|
224
|
+
# Discovery
|
|
225
|
+
#
|
|
226
|
+
def self.load!(cluster=nil)
|
|
227
|
+
# FIXME: Fix this one day when we have multiple "datacenters".
|
|
228
|
+
cloud = cluster.servers.values[0].cloud(:vsphere)
|
|
229
|
+
vm_folder = Vsphere.find_dc(cloud.datacenter).vmFolder
|
|
230
|
+
Vsphere.find_all_in_folder(vm_folder, RbVmomi::VIM::VirtualMachine).each do |fs|
|
|
231
|
+
machine = new(:adaptee => fs)
|
|
232
|
+
if recall? machine.name
|
|
233
|
+
machine.bogus << :duplicate_machines
|
|
234
|
+
recall(machine.name).bogus << :duplicate_machines
|
|
235
|
+
remember machine, :append_id => "duplicate:#{machine.config.uuid}"
|
|
236
|
+
else # never seen it
|
|
237
|
+
remember machine
|
|
238
|
+
end
|
|
239
|
+
Chef::Log.debug("Loaded #{machine}")
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def self.destroy!(computer)
|
|
244
|
+
return unless computer.machine?
|
|
245
|
+
forget computer.machine.name
|
|
246
|
+
computer.machine.destroy
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def self.launch_description(computer)
|
|
250
|
+
cloud = computer.server.cloud(:vsphere)
|
|
251
|
+
user_data_hsh = {
|
|
252
|
+
:chef_server => Chef::Config[:chef_server_url],
|
|
253
|
+
:client_key => computer.private_key,
|
|
254
|
+
:cluster_name => computer.server.cluster_name,
|
|
255
|
+
:facet_index => computer.server.index,
|
|
256
|
+
:facet_name => computer.server.facet_name,
|
|
257
|
+
:node_name => computer.name,
|
|
258
|
+
:organization => Chef::Config[:organization],
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
ip_settings = {
|
|
262
|
+
:dnsServers => cloud.dns_servers,
|
|
263
|
+
:domain => cloud.domain,
|
|
264
|
+
:gateway => cloud.gateway,
|
|
265
|
+
:ip => cloud.ip,
|
|
266
|
+
:subnet => cloud.subnet,
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
description = {
|
|
270
|
+
:cpus => cloud.cpus,
|
|
271
|
+
:cluster => cloud.cluster,
|
|
272
|
+
:datacenter => cloud.datacenter,
|
|
273
|
+
:datastore => cloud.datastore,
|
|
274
|
+
:memory => cloud.memory,
|
|
275
|
+
:network => cloud.network,
|
|
276
|
+
:template => cloud.template,
|
|
277
|
+
:user_data => JSON.pretty_generate(user_data_hsh),
|
|
278
|
+
:virtual_disks => cloud.virtual_disks,
|
|
279
|
+
:ip_settings => ip_settings
|
|
280
|
+
}
|
|
281
|
+
description
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# @returns [Hash{String, Array}] of 'what you did wrong' => [relevant, info]
|
|
285
|
+
def self.lint(computer)
|
|
286
|
+
cloud = computer.server.cloud(:vsphere)
|
|
287
|
+
info = [computer.name, cloud.inspect]
|
|
288
|
+
errors = {}
|
|
289
|
+
server_errors = computer.server.lint
|
|
290
|
+
errors["Unhappy Server"] = server_errors if server_errors.present?
|
|
291
|
+
errors["Datacenter"] = info if cloud.datacenter.blank?
|
|
292
|
+
errors["Template"] = info if cloud.template.blank?
|
|
293
|
+
errors["Datastore"] = info if cloud.datastore.blank?
|
|
294
|
+
errors['Missing client'] = info unless computer.client?
|
|
295
|
+
errors['Missing private_key'] = computer.client unless computer.private_key
|
|
296
|
+
#
|
|
297
|
+
errors
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def to_display(style,values={})
|
|
301
|
+
# style == :minimal
|
|
302
|
+
values["State"] = runtime.powerState rescue "Terminated"
|
|
303
|
+
values["MachineID"] = config.uuid rescue ""
|
|
304
|
+
# values["Public IP"] = public_ip_address
|
|
305
|
+
values["Private IP"] = guest.ipAddress rescue ""
|
|
306
|
+
# values["Created On"] = created_at.to_date
|
|
307
|
+
return values if style == :minimal
|
|
308
|
+
|
|
309
|
+
# style == :default
|
|
310
|
+
# values["Flavor"] = flavor_id
|
|
311
|
+
# values["AZ"] = availability_zone
|
|
312
|
+
return values if style == :default
|
|
313
|
+
|
|
314
|
+
# style == :expanded
|
|
315
|
+
# values["Image"] = image_id
|
|
316
|
+
values["Virtual Disks"] = disks.map { |d| d.backing.fileName }.join(', ')
|
|
317
|
+
# values["SSH Key"] = key_name
|
|
318
|
+
values
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def ssh_key
|
|
322
|
+
keypair = cloud.keypair || computer.server.cluster_name
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def self.validate_resources!(computers)
|
|
326
|
+
recall.each_value do |machine|
|
|
327
|
+
next unless machine.users.empty? and machine.name
|
|
328
|
+
if machine.name.match("^#{computers.cluster.name}-")
|
|
329
|
+
machine.bogus << :unexpected_machine
|
|
330
|
+
end
|
|
331
|
+
next unless machine.bogus?
|
|
332
|
+
fake = Ironfan::Broker::Computer.new
|
|
333
|
+
fake[:machine] = machine
|
|
334
|
+
fake.name = machine.name
|
|
335
|
+
machine.users << fake
|
|
336
|
+
computers << fake
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module Ironfan
|
|
2
|
+
class Provider
|
|
3
|
+
|
|
4
|
+
class Vsphere < Ironfan::IaasProvider
|
|
5
|
+
self.handle = :vsphere
|
|
6
|
+
|
|
7
|
+
def self.resources()
|
|
8
|
+
[ Machine, Keypair]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
#
|
|
12
|
+
# Utility functions
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
# Some methods cribbed and modified from https://github.com/ezrapagel/knife-vsphere, Ezra Pagel, Jesse Campbell
|
|
16
|
+
def self.connection
|
|
17
|
+
@@connection ||= RbVmomi::VIM.connect(self.vsphere_credentials)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.find_ds(vsphere_dc, name = nil)
|
|
21
|
+
ds = vsphere_dc.datastore
|
|
22
|
+
return ds.grep(RbVmomi::VIM::Datastore).find { |d| d.name == name } if !name.nil?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.find_dc(vsphere_dc)
|
|
26
|
+
connection.serviceInstance.find_datacenter(vsphere_dc)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.find_in_folder(folder, type, name)
|
|
30
|
+
folder.childEntity.grep(type).find { |o| o.name == name }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.get_rspec(dc, cluster)
|
|
34
|
+
if cluster
|
|
35
|
+
resource_pool = cluster.resourcePool
|
|
36
|
+
else
|
|
37
|
+
hosts = find_all_in_folder(dc.hostFolder, RbVmomi::VIM::ComputeResource).find { |o| o.class == RbVmomi::VIM::ComputeResource }
|
|
38
|
+
resource_pool = hosts.resourcePool || hosts.first.resourcePool
|
|
39
|
+
end
|
|
40
|
+
RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => resource_pool)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.find_all_in_folder(folder, type)
|
|
44
|
+
if folder.instance_of?(RbVmomi::VIM::ClusterComputeResource)
|
|
45
|
+
folder = folder.resourcePool
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
if folder.instance_of?(RbVmomi::VIM::ResourcePool)
|
|
49
|
+
folder.resourcePool.grep(type)
|
|
50
|
+
elsif folder.instance_of?(RbVmomi::VIM::Folder)
|
|
51
|
+
folder.childEntity.grep(type)
|
|
52
|
+
else
|
|
53
|
+
puts "Unknown type #{folder.class}, not enumerating"
|
|
54
|
+
nil
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.find_network(network, dc)
|
|
59
|
+
baseEntity = dc.network
|
|
60
|
+
baseEntity.find { |f| f.name == network }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.get_pub_key(cluster)
|
|
64
|
+
puts Keypair.private_key
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
def self.vsphere_credentials
|
|
69
|
+
return {
|
|
70
|
+
:user => Chef::Config[:knife][:vsphere_username],
|
|
71
|
+
:port => Chef::Config[:knife][:vsphere_port] || 443,
|
|
72
|
+
:password => Chef::Config[:knife][:vsphere_password],
|
|
73
|
+
:host => Chef::Config[:knife][:vsphere_server],
|
|
74
|
+
:insecure => Chef::Config[:knife][:vsphere_insecure] || true
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
data/lib/ironfan/provider.rb
CHANGED
data/lib/ironfan/requirements.rb
CHANGED
|
@@ -19,6 +19,7 @@ require 'ironfan/dsl/volume'
|
|
|
19
19
|
|
|
20
20
|
require 'ironfan/dsl/cloud'
|
|
21
21
|
require 'ironfan/dsl/ec2'
|
|
22
|
+
require 'ironfan/dsl/vsphere'
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
# Providers for specific resources
|
|
@@ -42,6 +43,10 @@ require 'ironfan/provider/ec2/iam_server_certificate'
|
|
|
42
43
|
require 'ironfan/provider/virtualbox'
|
|
43
44
|
require 'ironfan/provider/virtualbox/machine'
|
|
44
45
|
|
|
46
|
+
require 'ironfan/provider/vsphere'
|
|
47
|
+
require 'ironfan/provider/vsphere/machine'
|
|
48
|
+
require 'ironfan/provider/vsphere/keypair'
|
|
49
|
+
|
|
45
50
|
|
|
46
51
|
# Broker classes to coordinate DSL expectations and provider resources
|
|
47
52
|
require 'ironfan/broker'
|
metadata
CHANGED
|
@@ -1,148 +1,201 @@
|
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ironfan
|
|
3
|
-
version: !ruby/object:Gem::Version
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 4.9.0
|
|
4
5
|
prerelease:
|
|
5
|
-
version: 4.8.7
|
|
6
6
|
platform: ruby
|
|
7
|
-
authors:
|
|
7
|
+
authors:
|
|
8
8
|
- Infochimps
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- !ruby/object:Gem::Dependency
|
|
12
|
+
date: 2013-04-09 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
16
15
|
name: chef
|
|
17
|
-
requirement:
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
18
17
|
none: false
|
|
19
|
-
requirements:
|
|
18
|
+
requirements:
|
|
20
19
|
- - ~>
|
|
21
|
-
- !ruby/object:Gem::Version
|
|
22
|
-
version:
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '10.16'
|
|
23
22
|
type: :runtime
|
|
24
23
|
prerelease: false
|
|
25
|
-
version_requirements:
|
|
26
|
-
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ~>
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '10.16'
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
27
31
|
name: fog
|
|
28
|
-
requirement:
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
33
|
none: false
|
|
30
|
-
requirements:
|
|
34
|
+
requirements:
|
|
31
35
|
- - ~>
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '1.2'
|
|
34
38
|
type: :runtime
|
|
35
39
|
prerelease: false
|
|
36
|
-
version_requirements:
|
|
37
|
-
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ~>
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '1.2'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
38
47
|
name: formatador
|
|
39
|
-
requirement:
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
40
49
|
none: false
|
|
41
|
-
requirements:
|
|
50
|
+
requirements:
|
|
42
51
|
- - ~>
|
|
43
|
-
- !ruby/object:Gem::Version
|
|
44
|
-
version:
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0.2'
|
|
45
54
|
type: :runtime
|
|
46
55
|
prerelease: false
|
|
47
|
-
version_requirements:
|
|
48
|
-
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0.2'
|
|
62
|
+
- !ruby/object:Gem::Dependency
|
|
49
63
|
name: gorillib
|
|
50
|
-
requirement:
|
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
|
51
65
|
none: false
|
|
52
|
-
requirements:
|
|
66
|
+
requirements:
|
|
53
67
|
- - ~>
|
|
54
|
-
- !ruby/object:Gem::Version
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
55
69
|
version: 0.4.2
|
|
56
70
|
type: :runtime
|
|
57
71
|
prerelease: false
|
|
58
|
-
version_requirements:
|
|
59
|
-
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ~>
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: 0.4.2
|
|
78
|
+
- !ruby/object:Gem::Dependency
|
|
60
79
|
name: json
|
|
61
|
-
requirement:
|
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
|
62
81
|
none: false
|
|
63
|
-
requirements:
|
|
64
|
-
- -
|
|
65
|
-
- !ruby/object:Gem::Version
|
|
82
|
+
requirements:
|
|
83
|
+
- - '='
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
66
85
|
version: 1.5.4
|
|
67
86
|
type: :runtime
|
|
68
87
|
prerelease: false
|
|
69
|
-
version_requirements:
|
|
70
|
-
|
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
+
none: false
|
|
90
|
+
requirements:
|
|
91
|
+
- - '='
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: 1.5.4
|
|
94
|
+
- !ruby/object:Gem::Dependency
|
|
71
95
|
name: bundler
|
|
72
|
-
requirement:
|
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
|
73
97
|
none: false
|
|
74
|
-
requirements:
|
|
98
|
+
requirements:
|
|
75
99
|
- - ~>
|
|
76
|
-
- !ruby/object:Gem::Version
|
|
77
|
-
version:
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '1.0'
|
|
78
102
|
type: :development
|
|
79
103
|
prerelease: false
|
|
80
|
-
version_requirements:
|
|
81
|
-
|
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
105
|
+
none: false
|
|
106
|
+
requirements:
|
|
107
|
+
- - ~>
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '1.0'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
82
111
|
name: rake
|
|
83
|
-
requirement:
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
84
113
|
none: false
|
|
85
|
-
requirements:
|
|
86
|
-
- -
|
|
87
|
-
- !ruby/object:Gem::Version
|
|
88
|
-
version:
|
|
114
|
+
requirements:
|
|
115
|
+
- - ! '>='
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
89
118
|
type: :development
|
|
90
119
|
prerelease: false
|
|
91
|
-
version_requirements:
|
|
92
|
-
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
none: false
|
|
122
|
+
requirements:
|
|
123
|
+
- - ! '>='
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: '0'
|
|
126
|
+
- !ruby/object:Gem::Dependency
|
|
93
127
|
name: rspec
|
|
94
|
-
requirement:
|
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
|
95
129
|
none: false
|
|
96
|
-
requirements:
|
|
130
|
+
requirements:
|
|
97
131
|
- - ~>
|
|
98
|
-
- !ruby/object:Gem::Version
|
|
99
|
-
version:
|
|
132
|
+
- !ruby/object:Gem::Version
|
|
133
|
+
version: '2.8'
|
|
100
134
|
type: :development
|
|
101
135
|
prerelease: false
|
|
102
|
-
version_requirements:
|
|
103
|
-
|
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
137
|
+
none: false
|
|
138
|
+
requirements:
|
|
139
|
+
- - ~>
|
|
140
|
+
- !ruby/object:Gem::Version
|
|
141
|
+
version: '2.8'
|
|
142
|
+
- !ruby/object:Gem::Dependency
|
|
104
143
|
name: yard
|
|
105
|
-
requirement:
|
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
|
106
145
|
none: false
|
|
107
|
-
requirements:
|
|
108
|
-
- -
|
|
109
|
-
- !ruby/object:Gem::Version
|
|
110
|
-
version:
|
|
146
|
+
requirements:
|
|
147
|
+
- - ! '>='
|
|
148
|
+
- !ruby/object:Gem::Version
|
|
149
|
+
version: '0.7'
|
|
111
150
|
type: :development
|
|
112
151
|
prerelease: false
|
|
113
|
-
version_requirements:
|
|
114
|
-
|
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
153
|
+
none: false
|
|
154
|
+
requirements:
|
|
155
|
+
- - ! '>='
|
|
156
|
+
- !ruby/object:Gem::Version
|
|
157
|
+
version: '0.7'
|
|
158
|
+
- !ruby/object:Gem::Dependency
|
|
115
159
|
name: redcarpet
|
|
116
|
-
requirement:
|
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
|
117
161
|
none: false
|
|
118
|
-
requirements:
|
|
119
|
-
- -
|
|
120
|
-
- !ruby/object:Gem::Version
|
|
121
|
-
version:
|
|
162
|
+
requirements:
|
|
163
|
+
- - ! '>='
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '2.1'
|
|
122
166
|
type: :development
|
|
123
167
|
prerelease: false
|
|
124
|
-
version_requirements:
|
|
125
|
-
|
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
169
|
+
none: false
|
|
170
|
+
requirements:
|
|
171
|
+
- - ! '>='
|
|
172
|
+
- !ruby/object:Gem::Version
|
|
173
|
+
version: '2.1'
|
|
174
|
+
- !ruby/object:Gem::Dependency
|
|
126
175
|
name: oj
|
|
127
|
-
requirement:
|
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
177
|
none: false
|
|
129
|
-
requirements:
|
|
130
|
-
- -
|
|
131
|
-
- !ruby/object:Gem::Version
|
|
132
|
-
version:
|
|
178
|
+
requirements:
|
|
179
|
+
- - ! '>='
|
|
180
|
+
- !ruby/object:Gem::Version
|
|
181
|
+
version: '1.2'
|
|
133
182
|
type: :development
|
|
134
183
|
prerelease: false
|
|
135
|
-
version_requirements:
|
|
136
|
-
|
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
185
|
+
none: false
|
|
186
|
+
requirements:
|
|
187
|
+
- - ! '>='
|
|
188
|
+
- !ruby/object:Gem::Version
|
|
189
|
+
version: '1.2'
|
|
190
|
+
description: Ironfan allows you to orchestrate not just systems but clusters of machines.
|
|
191
|
+
It includes a powerful layer on top of knife and a collection of cloud cookbooks.
|
|
137
192
|
email: coders@infochimps.com
|
|
138
193
|
executables: []
|
|
139
|
-
|
|
140
194
|
extensions: []
|
|
141
|
-
|
|
142
|
-
extra_rdoc_files:
|
|
195
|
+
extra_rdoc_files:
|
|
143
196
|
- LICENSE.md
|
|
144
197
|
- README.md
|
|
145
|
-
files:
|
|
198
|
+
files:
|
|
146
199
|
- .gitignore
|
|
147
200
|
- .rspec
|
|
148
201
|
- .yardopts
|
|
@@ -199,6 +252,7 @@ files:
|
|
|
199
252
|
- lib/ironfan/dsl/server.rb
|
|
200
253
|
- lib/ironfan/dsl/virtualbox.rb
|
|
201
254
|
- lib/ironfan/dsl/volume.rb
|
|
255
|
+
- lib/ironfan/dsl/vsphere.rb
|
|
202
256
|
- lib/ironfan/headers.rb
|
|
203
257
|
- lib/ironfan/provider.rb
|
|
204
258
|
- lib/ironfan/provider/chef.rb
|
|
@@ -216,6 +270,9 @@ files:
|
|
|
216
270
|
- lib/ironfan/provider/ec2/security_group.rb
|
|
217
271
|
- lib/ironfan/provider/virtualbox.rb
|
|
218
272
|
- lib/ironfan/provider/virtualbox/machine.rb
|
|
273
|
+
- lib/ironfan/provider/vsphere.rb
|
|
274
|
+
- lib/ironfan/provider/vsphere/keypair.rb
|
|
275
|
+
- lib/ironfan/provider/vsphere/machine.rb
|
|
219
276
|
- lib/ironfan/requirements.rb
|
|
220
277
|
- notes/Future-development-proposals.md
|
|
221
278
|
- notes/Home.md
|
|
@@ -272,36 +329,34 @@ files:
|
|
|
272
329
|
- spec/test_config.rb
|
|
273
330
|
- tasks/chef_config.rake
|
|
274
331
|
homepage: http://infochimps.com/labs
|
|
275
|
-
licenses:
|
|
332
|
+
licenses:
|
|
276
333
|
- apachev2
|
|
277
334
|
post_install_message:
|
|
278
335
|
rdoc_options: []
|
|
279
|
-
|
|
280
|
-
require_paths:
|
|
336
|
+
require_paths:
|
|
281
337
|
- lib
|
|
282
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
|
338
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
283
339
|
none: false
|
|
284
|
-
requirements:
|
|
285
|
-
- -
|
|
286
|
-
- !ruby/object:Gem::Version
|
|
287
|
-
|
|
288
|
-
segments:
|
|
340
|
+
requirements:
|
|
341
|
+
- - ! '>='
|
|
342
|
+
- !ruby/object:Gem::Version
|
|
343
|
+
version: '0'
|
|
344
|
+
segments:
|
|
289
345
|
- 0
|
|
290
|
-
|
|
291
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
346
|
+
hash: 3090386787638060354
|
|
347
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
292
348
|
none: false
|
|
293
|
-
requirements:
|
|
294
|
-
- -
|
|
295
|
-
- !ruby/object:Gem::Version
|
|
296
|
-
version:
|
|
349
|
+
requirements:
|
|
350
|
+
- - ! '>='
|
|
351
|
+
- !ruby/object:Gem::Version
|
|
352
|
+
version: '0'
|
|
297
353
|
requirements: []
|
|
298
|
-
|
|
299
354
|
rubyforge_project:
|
|
300
|
-
rubygems_version: 1.8.
|
|
355
|
+
rubygems_version: 1.8.23
|
|
301
356
|
signing_key:
|
|
302
357
|
specification_version: 3
|
|
303
358
|
summary: Infochimps' lightweight cloud orchestration toolkit, built on top of Chef.
|
|
304
|
-
test_files:
|
|
359
|
+
test_files:
|
|
305
360
|
- spec/spec_helper/dummy_chef.rb
|
|
306
361
|
- spec/integration/spec_helper/launch_cluster.rb
|
|
307
362
|
- spec/integration/minimal-chef-repo/roles/systemwide.rb
|