bosh_cli_plugin_micro 1.5.0.pre.1113

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,181 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::Deployer
4
+ class InstanceManager
5
+
6
+ class Aws < InstanceManager
7
+
8
+ def update_spec(spec)
9
+ properties = spec.properties
10
+
11
+ # pick from micro_bosh.yml the aws settings in `apply_spec` section (apply_spec.properties.aws),
12
+ # and if it doesn't exist, use the bosh deployer aws properties (cloud.properties.aws)
13
+ properties["aws"] = Config.spec_properties["aws"] || Config.cloud_options["properties"]["aws"].dup
14
+
15
+ properties["aws"]["registry"] = Config.cloud_options["properties"]["registry"]
16
+ properties["aws"]["stemcell"] = Config.cloud_options["properties"]["stemcell"]
17
+
18
+ spec.delete("networks")
19
+ end
20
+
21
+ def configure
22
+ properties = Config.cloud_options["properties"]
23
+ @ssh_user = properties["aws"]["ssh_user"]
24
+ @ssh_port = properties["aws"]["ssh_port"] || 22
25
+ @ssh_wait = properties["aws"]["ssh_wait"] || 60
26
+
27
+ key = properties["aws"]["ec2_private_key"]
28
+ err "Missing properties.aws.ec2_private_key" unless key
29
+ @ssh_key = File.expand_path(key)
30
+ unless File.exists?(@ssh_key)
31
+ err "properties.aws.ec2_private_key '#{key}' does not exist"
32
+ end
33
+
34
+ uri = URI.parse(properties["registry"]["endpoint"])
35
+ user, password = uri.userinfo.split(":", 2)
36
+ @registry_port = uri.port
37
+
38
+ @registry_db = Tempfile.new("bosh_registry_db")
39
+
40
+ @registry_connection_settings = {
41
+ 'adapter' => 'sqlite',
42
+ 'database' => @registry_db.path
43
+ }
44
+
45
+ registry_config = {
46
+ "logfile" => "./bosh-registry.log",
47
+ "http" => {
48
+ "port" => uri.port,
49
+ "user" => user,
50
+ "password" => password
51
+ },
52
+ "db" => @registry_connection_settings,
53
+ "cloud" => {
54
+ "plugin" => "aws",
55
+ "aws" => properties["aws"]
56
+ }
57
+ }
58
+
59
+ @registry_config = Tempfile.new("bosh_registry_yml")
60
+ @registry_config.write(Psych.dump(registry_config))
61
+ @registry_config.close
62
+ end
63
+
64
+ def start
65
+ configure()
66
+
67
+ Sequel.connect(@registry_connection_settings) do |db|
68
+ migrate(db)
69
+ instances = @deployments["registry_instances"]
70
+ db[:registry_instances].insert_multiple(instances) if instances
71
+ end
72
+
73
+ unless has_bosh_registry?
74
+ err "bosh-registry command not found - " +
75
+ "run 'gem install bosh-registry'"
76
+ end
77
+
78
+ cmd = "bosh-registry -c #{@registry_config.path}"
79
+
80
+ @registry_pid = spawn(cmd)
81
+
82
+ 5.times do
83
+ sleep 0.5
84
+ if Process.waitpid(@registry_pid, Process::WNOHANG)
85
+ err "`#{cmd}` failed, exit status=#{$?.exitstatus}"
86
+ end
87
+ end
88
+
89
+ timeout_time = Time.now.to_f + (60 * 5)
90
+ http_client = HTTPClient.new()
91
+ begin
92
+ http_client.head("http://127.0.0.1:#{@registry_port}")
93
+ sleep 0.5
94
+ rescue URI::Error, SocketError, Errno::ECONNREFUSED, HTTPClient::ReceiveTimeoutError => e
95
+ if timeout_time - Time.now.to_f > 0
96
+ retry
97
+ else
98
+ err "Cannot access bosh-registry: #{e.message}"
99
+ end
100
+ end
101
+
102
+ logger.info("bosh-registry is ready on port #{@registry_port}")
103
+ ensure
104
+ @registry_config.unlink if @registry_config
105
+ end
106
+
107
+ def stop
108
+ if @registry_pid && process_exists?(@registry_pid)
109
+ Process.kill("INT", @registry_pid)
110
+ Process.waitpid(@registry_pid)
111
+ end
112
+
113
+ return unless @registry_connection_settings
114
+
115
+ Sequel.connect(@registry_connection_settings) do |db|
116
+ @deployments["registry_instances"] = db[:registry_instances].map {|row| row}
117
+ end
118
+
119
+ save_state
120
+ @registry_db.unlink if @registry_db
121
+ end
122
+
123
+ def discover_bosh_ip
124
+ if exists?
125
+ # choose elastic IP over public, as any agent connecting to the
126
+ # deployed micro bosh will be cut off from the public IP when
127
+ # we re-deploy micro bosh
128
+ if cloud.ec2.instances[state.vm_cid].has_elastic_ip?
129
+ ip = cloud.ec2.instances[state.vm_cid].elastic_ip.public_ip
130
+ else
131
+ ip = cloud.ec2.instances[state.vm_cid].public_ip_address
132
+ end
133
+
134
+ if ip && ip != Config.bosh_ip
135
+ Config.bosh_ip = ip
136
+ logger.info("discovered bosh ip=#{Config.bosh_ip}")
137
+ end
138
+ end
139
+
140
+ super
141
+ end
142
+
143
+ def service_ip
144
+ cloud.ec2.instances[state.vm_cid].private_ip_address
145
+ end
146
+
147
+ # @return [Integer] size in MiB
148
+ def disk_size(cid)
149
+ # AWS stores disk size in GiB but the CPI uses MiB
150
+ cloud.ec2.volumes[cid].size * 1024
151
+ end
152
+
153
+ def persistent_disk_changed?
154
+ # since AWS stores disk size in GiB and the CPI uses MiB there
155
+ # is a risk of conversion errors which lead to an unnecessary
156
+ # disk migration, so we need to do a double conversion
157
+ # here to avoid that
158
+ requested = (Config.resources['persistent_disk'] / 1024.0).ceil * 1024
159
+ requested != disk_size(state.disk_cid)
160
+ end
161
+
162
+ private
163
+
164
+ def has_bosh_registry?(path=ENV['PATH'])
165
+ path.split(":").each do |dir|
166
+ return true if File.exist?(File.join(dir, "bosh-registry"))
167
+ end
168
+ false
169
+ end
170
+
171
+ def migrate(db)
172
+ db.create_table :registry_instances do
173
+ primary_key :id
174
+ column :instance_id, :text, :unique => true, :null => false
175
+ column :settings, :text, :null => false
176
+ end
177
+ end
178
+
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,174 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::Deployer
4
+ class InstanceManager
5
+
6
+ class Openstack < InstanceManager
7
+
8
+ def update_spec(spec)
9
+ properties = spec.properties
10
+
11
+ properties["openstack"] =
12
+ Config.spec_properties["openstack"] ||
13
+ Config.cloud_options["properties"]["openstack"].dup
14
+
15
+ properties["openstack"]["registry"] = Config.cloud_options["properties"]["registry"]
16
+ properties["openstack"]["stemcell"] = Config.cloud_options["properties"]["stemcell"]
17
+
18
+ spec.delete("networks")
19
+ end
20
+
21
+ def configure
22
+ properties = Config.cloud_options["properties"]
23
+ @ssh_user = properties["openstack"]["ssh_user"]
24
+ @ssh_port = properties["openstack"]["ssh_port"] || 22
25
+ @ssh_wait = properties["openstack"]["ssh_wait"] || 60
26
+
27
+ key = properties["openstack"]["private_key"]
28
+ err "Missing properties.openstack.private_key" unless key
29
+ @ssh_key = File.expand_path(key)
30
+ unless File.exists?(@ssh_key)
31
+ err "properties.openstack.private_key '#{key}' does not exist"
32
+ end
33
+
34
+ uri = URI.parse(properties["registry"]["endpoint"])
35
+ user, password = uri.userinfo.split(":", 2)
36
+ @registry_port = uri.port
37
+
38
+ @registry_db = Tempfile.new("bosh_registry_db")
39
+ @registry_connection_settings = {
40
+ 'adapter' => 'sqlite',
41
+ 'database' => @registry_db.path
42
+ }
43
+
44
+ registry_config = {
45
+ "logfile" => "./bosh-registry.log",
46
+ "http" => {
47
+ "port" => uri.port,
48
+ "user" => user,
49
+ "password" => password
50
+ },
51
+ "db" => @registry_connection_settings,
52
+ "cloud" => {
53
+ "plugin" => "openstack",
54
+ "openstack" => properties["openstack"]
55
+ }
56
+ }
57
+
58
+ @registry_config = Tempfile.new("bosh_registry_yml")
59
+ @registry_config.write(Psych.dump(registry_config))
60
+ @registry_config.close
61
+ end
62
+
63
+ def start
64
+ configure()
65
+
66
+ Sequel.connect(@registry_connection_settings) do |db|
67
+ migrate(db)
68
+ instances = @deployments["registry_instances"]
69
+ db[:registry_instances].insert_multiple(instances) if instances
70
+ end
71
+
72
+ unless has_bosh_registry?
73
+ err "bosh-registry command not found - " +
74
+ "run 'gem install bosh-registry'"
75
+ end
76
+
77
+ cmd = "bosh-registry -c #{@registry_config.path}"
78
+
79
+ @registry_pid = spawn(cmd)
80
+
81
+ 5.times do
82
+ sleep 0.5
83
+ if Process.waitpid(@registry_pid, Process::WNOHANG)
84
+ err "`#{cmd}` failed, exit status=#{$?.exitstatus}"
85
+ end
86
+ end
87
+
88
+ timeout_time = Time.now.to_f + (60 * 5)
89
+ http_client = HTTPClient.new()
90
+ begin
91
+ http_client.head("http://127.0.0.1:#{@registry_port}")
92
+ sleep 0.5
93
+ rescue URI::Error, SocketError, Errno::ECONNREFUSED, HTTPClient::ReceiveTimeoutError => e
94
+ if timeout_time - Time.now.to_f > 0
95
+ retry
96
+ else
97
+ err "Cannot access bosh-registry: #{e.message}"
98
+ end
99
+ end
100
+
101
+ logger.info("bosh-registry is ready on port #{@registry_port}")
102
+ ensure
103
+ @registry_config.unlink if @registry_config
104
+ end
105
+
106
+ def stop
107
+ if @registry_pid && process_exists?(@registry_pid)
108
+ Process.kill("INT", @registry_pid)
109
+ Process.waitpid(@registry_pid)
110
+ end
111
+
112
+ return unless @registry_connection_settings
113
+
114
+ Sequel.connect(@registry_connection_settings) do |db|
115
+ @deployments["registry_instances"] = db[:registry_instances].map {|row| row}
116
+ end
117
+
118
+ save_state
119
+ @registry_db.unlink if @registry_db
120
+ end
121
+
122
+ def discover_bosh_ip
123
+ if exists?
124
+ floating_ip = cloud.openstack.servers.get(state.vm_cid).floating_ip_address
125
+ ip = floating_ip || service_ip
126
+
127
+ if ip != Config.bosh_ip
128
+ Config.bosh_ip = ip
129
+ logger.info("discovered bosh ip=#{Config.bosh_ip}")
130
+ end
131
+ end
132
+
133
+ super
134
+ end
135
+
136
+ def service_ip
137
+ cloud.openstack.servers.get(state.vm_cid).private_ip_address
138
+ end
139
+
140
+ # @return [Integer] size in MiB
141
+ def disk_size(cid)
142
+ # OpenStack stores disk size in GiB but we work with MiB
143
+ cloud.openstack.volumes.get(cid).size * 1024
144
+ end
145
+
146
+ def persistent_disk_changed?
147
+ # since OpenStack stores disk size in GiB and we use MiB there
148
+ # is a risk of conversion errors which lead to an unnecessary
149
+ # disk migration, so we need to do a double conversion
150
+ # here to avoid that
151
+ requested = (Config.resources['persistent_disk'] / 1024.0).ceil * 1024
152
+ requested != disk_size(state.disk_cid)
153
+ end
154
+
155
+ private
156
+
157
+ def has_bosh_registry?(path=ENV['PATH'])
158
+ path.split(":").each do |dir|
159
+ return true if File.exist?(File.join(dir, "bosh-registry"))
160
+ end
161
+ false
162
+ end
163
+
164
+ def migrate(db)
165
+ db.create_table :registry_instances do
166
+ primary_key :id
167
+ column :instance_id, :text, :unique => true, :null => false
168
+ column :settings, :text, :null => false
169
+ end
170
+ end
171
+
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::Deployer
4
+ class InstanceManager
5
+
6
+ class Vcloud < InstanceManager
7
+
8
+
9
+ def remote_tunnel(port)
10
+ # VCloud / vsphere does not use bosh-registry so no remote_tunnel
11
+ # to bosh-registry is required
12
+ end
13
+
14
+ def update_spec(spec)
15
+ properties = spec.properties
16
+
17
+ properties["vcd"] =
18
+ Config.spec_properties["vcd"] ||
19
+ Config.cloud_options["properties"]["vcds"].first.dup
20
+
21
+ properties["vcd"]["address"] ||= properties["vcd"]["url"]
22
+ end
23
+
24
+ # @return [Integer] size in MiB
25
+ def disk_size(cid)
26
+ cloud.get_disk_size_mb(cid)
27
+ end
28
+
29
+ def persistent_disk_changed?
30
+ Config.resources['persistent_disk'] != disk_size(state.disk_cid)
31
+ end
32
+
33
+ def check_dependencies
34
+ if Bosh::Common.which(%w[genisoimage mkisofs]).nil?
35
+ err("either of 'genisoimage' or 'mkisofs' commands must be present")
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module Bosh::Deployer
4
+ class InstanceManager
5
+
6
+ class Vsphere < InstanceManager
7
+
8
+ def remote_tunnel(port)
9
+ end
10
+
11
+ def disk_model
12
+ if @disk_model.nil?
13
+ require "cloud/vsphere"
14
+ @disk_model = VSphereCloud::Models::Disk
15
+ end
16
+ @disk_model
17
+ end
18
+
19
+ def update_spec(spec)
20
+ properties = spec.properties
21
+
22
+ properties["vcenter"] =
23
+ Config.spec_properties["vcenter"] ||
24
+ Config.cloud_options["properties"]["vcenters"].first.dup
25
+
26
+ properties["vcenter"]["address"] ||= properties["vcenter"]["host"]
27
+ end
28
+ end
29
+
30
+ # @return [Integer] size in MiB
31
+ def disk_size(cid)
32
+ disk_model.first(:uuid => cid).size
33
+ end
34
+
35
+ def persistent_disk_changed?
36
+ Config.resources["persistent_disk"] != disk_size(state.disk_cid)
37
+ end
38
+
39
+ def check_dependencies
40
+ if Bosh::Common.which(%w[genisoimage mkisofs]).nil?
41
+ err("either of 'genisoimage' or 'mkisofs' commands must be present")
42
+ end
43
+ end
44
+
45
+ end
46
+ end