bosh_cli_plugin_micro 1.5.0.pre.1113

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.
@@ -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