ironfan 4.8.7 → 4.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|