bosh-director 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.
- data/CHANGELOG +34 -0
- data/bin/bosh-director +36 -0
- data/bin/bosh-director-console +84 -0
- data/bin/bosh-director-drain-workers +42 -0
- data/bin/bosh-director-migrate +58 -0
- data/bin/bosh-director-scheduler +27 -0
- data/bin/bosh-director-worker +76 -0
- data/db/migrations/README +1 -0
- data/db/migrations/director/20110209010747_initial.rb +118 -0
- data/db/migrations/director/20110406055800_add_task_user.rb +9 -0
- data/db/migrations/director/20110518225809_remove_cid_constrain.rb +13 -0
- data/db/migrations/director/20110617211923_add_deployments_release_versions.rb +32 -0
- data/db/migrations/director/20110622212607_add_task_checkpoint_timestamp.rb +9 -0
- data/db/migrations/director/20110628023039_add_state_to_instances.rb +21 -0
- data/db/migrations/director/20110709012332_add_disk_size_to_instances.rb +9 -0
- data/db/migrations/director/20110906183441_add_log_bundles.rb +11 -0
- data/db/migrations/director/20110907194830_add_logs_json_to_templates.rb +9 -0
- data/db/migrations/director/20110915205610_add_persistent_disks.rb +51 -0
- data/db/migrations/director/20111005180929_add_properties.rb +14 -0
- data/db/migrations/director/20111110024617_add_deployment_problems.rb +24 -0
- data/db/migrations/director/20111216214145_recreate_support_for_vms.rb +9 -0
- data/db/migrations/director/20120102084027_add_credentials_to_vms.rb +7 -0
- data/db/migrations/director/20120427235217_allow_multiple_releases_per_deployment.rb +36 -0
- data/db/migrations/director/20120524175805_add_task_type.rb +44 -0
- data/db/migrations/director/20120614001930_delete_redundant_deployment_release_relation.rb +34 -0
- data/db/migrations/director/20120822004528_add_fingerprint_to_templates_and_packages.rb +17 -0
- data/db/migrations/director/20120830191244_add_properties_to_templates.rb +9 -0
- data/db/migrations/director/20121106190739_persist_vm_env.rb +9 -0
- data/db/migrations/director/20130222232131_add_sha1_to_stemcells.rb +9 -0
- data/db/migrations/director/20130312211407_add_commit_hash_to_release_versions.rb +19 -0
- data/db/migrations/director/20130409235338_snapshot.rb +15 -0
- data/db/migrations/director/20130530164918_add_paused_flag_to_instance.rb +14 -0
- data/db/migrations/director/20130531172604_add_director_attributes.rb +13 -0
- data/db/migrations/dns/20120123234908_initial.rb +27 -0
- data/lib/bosh/director.rb +133 -0
- data/lib/bosh/director/agent_client.rb +78 -0
- data/lib/bosh/director/api.rb +29 -0
- data/lib/bosh/director/api/api_helper.rb +81 -0
- data/lib/bosh/director/api/backup_manager.rb +15 -0
- data/lib/bosh/director/api/controller.rb +639 -0
- data/lib/bosh/director/api/controller_helpers.rb +34 -0
- data/lib/bosh/director/api/deployment_lookup.rb +13 -0
- data/lib/bosh/director/api/deployment_manager.rb +60 -0
- data/lib/bosh/director/api/http_constants.rb +16 -0
- data/lib/bosh/director/api/instance_lookup.rb +44 -0
- data/lib/bosh/director/api/instance_manager.rb +63 -0
- data/lib/bosh/director/api/problem_manager.rb +40 -0
- data/lib/bosh/director/api/property_manager.rb +69 -0
- data/lib/bosh/director/api/release_manager.rb +59 -0
- data/lib/bosh/director/api/resource_manager.rb +69 -0
- data/lib/bosh/director/api/resurrector_manager.rb +15 -0
- data/lib/bosh/director/api/snapshot_manager.rb +94 -0
- data/lib/bosh/director/api/stemcell_manager.rb +50 -0
- data/lib/bosh/director/api/task_helper.rb +46 -0
- data/lib/bosh/director/api/task_manager.rb +64 -0
- data/lib/bosh/director/api/user_manager.rb +72 -0
- data/lib/bosh/director/api/vm_state_manager.rb +11 -0
- data/lib/bosh/director/app.rb +35 -0
- data/lib/bosh/director/blob_util.rb +87 -0
- data/lib/bosh/director/blobstores.rb +29 -0
- data/lib/bosh/director/client.rb +156 -0
- data/lib/bosh/director/cloudcheck_helper.rb +204 -0
- data/lib/bosh/director/compile_task.rb +157 -0
- data/lib/bosh/director/config.rb +370 -0
- data/lib/bosh/director/configuration_hasher.rb +114 -0
- data/lib/bosh/director/cycle_helper.rb +36 -0
- data/lib/bosh/director/db_backup.rb +22 -0
- data/lib/bosh/director/db_backup/adapter.rb +3 -0
- data/lib/bosh/director/db_backup/adapter/mysql2.rb +27 -0
- data/lib/bosh/director/db_backup/adapter/postgres.rb +36 -0
- data/lib/bosh/director/db_backup/adapter/sqlite.rb +17 -0
- data/lib/bosh/director/db_backup/error.rb +10 -0
- data/lib/bosh/director/deployment_plan.rb +26 -0
- data/lib/bosh/director/deployment_plan/assembler.rb +430 -0
- data/lib/bosh/director/deployment_plan/compilation_config.rb +54 -0
- data/lib/bosh/director/deployment_plan/compiled_package.rb +35 -0
- data/lib/bosh/director/deployment_plan/dynamic_network.rb +91 -0
- data/lib/bosh/director/deployment_plan/idle_vm.rb +109 -0
- data/lib/bosh/director/deployment_plan/instance.rb +413 -0
- data/lib/bosh/director/deployment_plan/job.rb +470 -0
- data/lib/bosh/director/deployment_plan/manual_network.rb +137 -0
- data/lib/bosh/director/deployment_plan/network.rb +74 -0
- data/lib/bosh/director/deployment_plan/network_subnet.rb +167 -0
- data/lib/bosh/director/deployment_plan/planner.rb +288 -0
- data/lib/bosh/director/deployment_plan/preparer.rb +52 -0
- data/lib/bosh/director/deployment_plan/release.rb +126 -0
- data/lib/bosh/director/deployment_plan/resource_pool.rb +143 -0
- data/lib/bosh/director/deployment_plan/resource_pools.rb +68 -0
- data/lib/bosh/director/deployment_plan/stemcell.rb +56 -0
- data/lib/bosh/director/deployment_plan/template.rb +94 -0
- data/lib/bosh/director/deployment_plan/update_config.rb +80 -0
- data/lib/bosh/director/deployment_plan/updater.rb +55 -0
- data/lib/bosh/director/deployment_plan/vip_network.rb +79 -0
- data/lib/bosh/director/dns_helper.rb +204 -0
- data/lib/bosh/director/download_helper.rb +44 -0
- data/lib/bosh/director/duration.rb +36 -0
- data/lib/bosh/director/encryption_helper.rb +10 -0
- data/lib/bosh/director/errors.rb +198 -0
- data/lib/bosh/director/event_log.rb +136 -0
- data/lib/bosh/director/ext.rb +64 -0
- data/lib/bosh/director/hash_string_vals.rb +13 -0
- data/lib/bosh/director/instance_deleter.rb +109 -0
- data/lib/bosh/director/instance_updater.rb +506 -0
- data/lib/bosh/director/ip_util.rb +67 -0
- data/lib/bosh/director/job_queue.rb +16 -0
- data/lib/bosh/director/job_runner.rb +162 -0
- data/lib/bosh/director/job_updater.rb +121 -0
- data/lib/bosh/director/jobs/backup.rb +86 -0
- data/lib/bosh/director/jobs/base_job.rb +66 -0
- data/lib/bosh/director/jobs/cloud_check/apply_resolutions.rb +46 -0
- data/lib/bosh/director/jobs/cloud_check/scan.rb +38 -0
- data/lib/bosh/director/jobs/cloud_check/scan_and_fix.rb +73 -0
- data/lib/bosh/director/jobs/create_snapshot.rb +23 -0
- data/lib/bosh/director/jobs/delete_deployment.rb +183 -0
- data/lib/bosh/director/jobs/delete_deployment_snapshots.rb +34 -0
- data/lib/bosh/director/jobs/delete_release.rb +219 -0
- data/lib/bosh/director/jobs/delete_snapshots.rb +23 -0
- data/lib/bosh/director/jobs/delete_stemcell.rb +102 -0
- data/lib/bosh/director/jobs/fetch_logs.rb +99 -0
- data/lib/bosh/director/jobs/scheduled_backup.rb +38 -0
- data/lib/bosh/director/jobs/snapshot_deployment.rb +61 -0
- data/lib/bosh/director/jobs/snapshot_deployments.rb +23 -0
- data/lib/bosh/director/jobs/snapshot_self.rb +43 -0
- data/lib/bosh/director/jobs/ssh.rb +59 -0
- data/lib/bosh/director/jobs/update_deployment.rb +110 -0
- data/lib/bosh/director/jobs/update_release.rb +672 -0
- data/lib/bosh/director/jobs/update_stemcell.rb +109 -0
- data/lib/bosh/director/jobs/vm_state.rb +89 -0
- data/lib/bosh/director/lock.rb +133 -0
- data/lib/bosh/director/lock_helper.rb +92 -0
- data/lib/bosh/director/models.rb +29 -0
- data/lib/bosh/director/models/compiled_package.rb +33 -0
- data/lib/bosh/director/models/deployment.rb +22 -0
- data/lib/bosh/director/models/deployment_problem.rb +49 -0
- data/lib/bosh/director/models/deployment_property.rb +21 -0
- data/lib/bosh/director/models/director_attribute.rb +9 -0
- data/lib/bosh/director/models/dns.rb +9 -0
- data/lib/bosh/director/models/dns/domain.rb +9 -0
- data/lib/bosh/director/models/dns/record.rb +7 -0
- data/lib/bosh/director/models/helpers/model_helper.rb +7 -0
- data/lib/bosh/director/models/instance.rb +28 -0
- data/lib/bosh/director/models/log_bundle.rb +10 -0
- data/lib/bosh/director/models/package.rb +30 -0
- data/lib/bosh/director/models/persistent_disk.rb +13 -0
- data/lib/bosh/director/models/release.rb +17 -0
- data/lib/bosh/director/models/release_version.rb +16 -0
- data/lib/bosh/director/models/snapshot.rb +13 -0
- data/lib/bosh/director/models/stemcell.rb +18 -0
- data/lib/bosh/director/models/task.rb +10 -0
- data/lib/bosh/director/models/template.rb +44 -0
- data/lib/bosh/director/models/user.rb +11 -0
- data/lib/bosh/director/models/vm.rb +42 -0
- data/lib/bosh/director/nats_rpc.rb +54 -0
- data/lib/bosh/director/network_reservation.rb +121 -0
- data/lib/bosh/director/next_rebase_version.rb +20 -0
- data/lib/bosh/director/package_compiler.rb +423 -0
- data/lib/bosh/director/problem_handlers/base.rb +153 -0
- data/lib/bosh/director/problem_handlers/inactive_disk.rb +112 -0
- data/lib/bosh/director/problem_handlers/invalid_problem.rb +28 -0
- data/lib/bosh/director/problem_handlers/missing_vm.rb +34 -0
- data/lib/bosh/director/problem_handlers/mount_info_mismatch.rb +62 -0
- data/lib/bosh/director/problem_handlers/out_of_sync_vm.rb +64 -0
- data/lib/bosh/director/problem_handlers/unbound_instance_vm.rb +85 -0
- data/lib/bosh/director/problem_handlers/unresponsive_agent.rb +78 -0
- data/lib/bosh/director/problem_resolver.rb +103 -0
- data/lib/bosh/director/problem_scanner.rb +268 -0
- data/lib/bosh/director/resource_pool_updater.rb +216 -0
- data/lib/bosh/director/scheduler.rb +57 -0
- data/lib/bosh/director/sequel.rb +13 -0
- data/lib/bosh/director/tar_gzipper.rb +47 -0
- data/lib/bosh/director/task_result_file.rb +19 -0
- data/lib/bosh/director/thread_pool.rb +8 -0
- data/lib/bosh/director/validation_helper.rb +55 -0
- data/lib/bosh/director/version.rb +7 -0
- data/lib/bosh/director/vm_creator.rb +80 -0
- data/lib/bosh/director/vm_data.rb +63 -0
- data/lib/bosh/director/vm_metadata_updater.rb +29 -0
- data/lib/bosh/director/vm_reuser.rb +63 -0
- data/lib/cloud/dummy.rb +149 -0
- metadata +664 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
module DeploymentPlan
|
|
5
|
+
##
|
|
6
|
+
# Represents the deployment compilation worker configuration.
|
|
7
|
+
class CompilationConfig
|
|
8
|
+
include ValidationHelper
|
|
9
|
+
|
|
10
|
+
# @return [DeploymentPlan] associated deployment
|
|
11
|
+
attr_accessor :deployment
|
|
12
|
+
|
|
13
|
+
# @return [Integer] number of worker VMs to use
|
|
14
|
+
attr_accessor :workers
|
|
15
|
+
|
|
16
|
+
# @return [DeploymentPlan::Network] network used by compilation workers
|
|
17
|
+
attr_accessor :network
|
|
18
|
+
|
|
19
|
+
# @return [Hash] cloud properties to use when creating VMs. (optional)
|
|
20
|
+
attr_accessor :cloud_properties
|
|
21
|
+
|
|
22
|
+
# @return [Hash] environment to use when creating VMs. (optional)
|
|
23
|
+
attr_accessor :env
|
|
24
|
+
|
|
25
|
+
# @return [Bool] if VMs should be reused for compilation tasks. (optional)
|
|
26
|
+
attr_accessor :reuse_compilation_vms
|
|
27
|
+
|
|
28
|
+
# Creates compilation configuration spec from the deployment manifest.
|
|
29
|
+
# @param [DeploymentPlan] deployment
|
|
30
|
+
# @param [Hash] compilation_config parsed compilation config YAML section
|
|
31
|
+
def initialize(deployment, compilation_config)
|
|
32
|
+
@deployment = deployment
|
|
33
|
+
@workers = safe_property(compilation_config, "workers",
|
|
34
|
+
:class => Integer, :min => 1)
|
|
35
|
+
network_name = safe_property(compilation_config, "network",
|
|
36
|
+
:class => String)
|
|
37
|
+
@reuse_compilation_vms = safe_property(compilation_config,
|
|
38
|
+
"reuse_compilation_vms",
|
|
39
|
+
:class => :boolean,
|
|
40
|
+
:optional => true)
|
|
41
|
+
@network = deployment.network(network_name)
|
|
42
|
+
if @network.nil?
|
|
43
|
+
raise CompilationConfigUnknownNetwork,
|
|
44
|
+
"Compilation config references an unknown " +
|
|
45
|
+
"network `#{network_name}'"
|
|
46
|
+
end
|
|
47
|
+
@cloud_properties = safe_property(
|
|
48
|
+
compilation_config, "cloud_properties", :class => Hash)
|
|
49
|
+
@env = safe_property(compilation_config, "env", :class => Hash,
|
|
50
|
+
:optional => true, :default => {})
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
module DeploymentPlan
|
|
5
|
+
class CompiledPackage
|
|
6
|
+
|
|
7
|
+
# @return [Models::CompiledPackage] Compiled package DB model
|
|
8
|
+
attr_reader :model
|
|
9
|
+
|
|
10
|
+
# @return [String] Package name
|
|
11
|
+
attr_reader :name
|
|
12
|
+
|
|
13
|
+
# @return [String] Package version
|
|
14
|
+
attr_reader :version
|
|
15
|
+
|
|
16
|
+
# @param [Models::CompiledPackage]
|
|
17
|
+
def initialize(model)
|
|
18
|
+
@model = model
|
|
19
|
+
|
|
20
|
+
@name = model.package.name
|
|
21
|
+
@version = model.package.version
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [Hash<String,Object>] Hash representation
|
|
25
|
+
def spec
|
|
26
|
+
{
|
|
27
|
+
"name" => @name,
|
|
28
|
+
"version" => "#{@version}.#{@model.build}",
|
|
29
|
+
"sha1" => @model.sha1,
|
|
30
|
+
"blobstore_id" => @model.blobstore_id
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
module DeploymentPlan
|
|
5
|
+
class DynamicNetwork < Network
|
|
6
|
+
include DnsHelper
|
|
7
|
+
|
|
8
|
+
DYNAMIC_IP = NetAddr::CIDR.create("255.255.255.255").to_i
|
|
9
|
+
|
|
10
|
+
# @!attribute [rw] cloud_properties
|
|
11
|
+
# @return [Hash] Network cloud properties
|
|
12
|
+
attr_accessor :cloud_properties
|
|
13
|
+
|
|
14
|
+
# @!attribute [rw] dns
|
|
15
|
+
# @return [Array] an array of DNS servers
|
|
16
|
+
attr_accessor :dns
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# Creates a new network.
|
|
20
|
+
#
|
|
21
|
+
# @param [DeploymentPlan] deployment associated deployment plan
|
|
22
|
+
# @param [Hash] network_spec parsed deployment manifest network section
|
|
23
|
+
def initialize(deployment, network_spec)
|
|
24
|
+
super
|
|
25
|
+
@cloud_properties =
|
|
26
|
+
safe_property(network_spec, "cloud_properties", :class => Hash)
|
|
27
|
+
|
|
28
|
+
@dns = dns_servers(network_spec["name"], network_spec)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Reserves a network resource.
|
|
33
|
+
#
|
|
34
|
+
# This is either an already used reservation being verified or a new one
|
|
35
|
+
# waiting to be fulfilled.
|
|
36
|
+
# @param [NetworkReservation] reservation
|
|
37
|
+
# @return [Boolean] true if the reservation was fulfilled
|
|
38
|
+
def reserve(reservation)
|
|
39
|
+
reservation.reserved = false
|
|
40
|
+
if reservation.static?
|
|
41
|
+
reservation.error = NetworkReservation::WRONG_TYPE
|
|
42
|
+
else
|
|
43
|
+
reservation.ip = DYNAMIC_IP
|
|
44
|
+
reservation.reserved = true
|
|
45
|
+
reservation.type = NetworkReservation::DYNAMIC
|
|
46
|
+
end
|
|
47
|
+
reservation.reserved?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
##
|
|
51
|
+
# Releases a previous reservation that had been fulfilled.
|
|
52
|
+
# @param [NetworkReservation] reservation
|
|
53
|
+
# @return [void]
|
|
54
|
+
def release(reservation)
|
|
55
|
+
validate_ip(reservation)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
##
|
|
59
|
+
# Returns the network settings for the specific reservation.
|
|
60
|
+
#
|
|
61
|
+
# @param [NetworkReservation] reservation
|
|
62
|
+
# @param [Array<String>] default_properties
|
|
63
|
+
# @return [Hash] network settings that will be passed to the BOSH Agent
|
|
64
|
+
def network_settings(reservation, default_properties = VALID_DEFAULTS)
|
|
65
|
+
validate_ip(reservation)
|
|
66
|
+
|
|
67
|
+
config = {
|
|
68
|
+
"type" => "dynamic",
|
|
69
|
+
"cloud_properties" => @cloud_properties
|
|
70
|
+
}
|
|
71
|
+
config["dns"] = @dns if @dns
|
|
72
|
+
|
|
73
|
+
if default_properties
|
|
74
|
+
config["default"] = default_properties.sort
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
config
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def validate_ip(reservation)
|
|
83
|
+
unless reservation.ip == DYNAMIC_IP
|
|
84
|
+
raise NetworkReservationInvalidIp,
|
|
85
|
+
"Invalid IP: `%s', did not match magic DYNAMIC IP" % [
|
|
86
|
+
reservation.ip]
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
module DeploymentPlan
|
|
5
|
+
##
|
|
6
|
+
# Represents a resource pool VM.
|
|
7
|
+
#
|
|
8
|
+
# It represents a VM until it's officially bound to an instance. It can be
|
|
9
|
+
# reserved for an instance to minimize the number of CPI operations
|
|
10
|
+
# (network & storage) required for the VM to match the instance
|
|
11
|
+
# requirements.
|
|
12
|
+
class IdleVm
|
|
13
|
+
# @return [DeploymentPlan::ResourcePool] Associated resource pool
|
|
14
|
+
attr_reader :resource_pool
|
|
15
|
+
|
|
16
|
+
# @return [NetworkReservation] VM network reservation
|
|
17
|
+
attr_accessor :network_reservation
|
|
18
|
+
|
|
19
|
+
# @return [Models::Vm] Associated model
|
|
20
|
+
attr_accessor :vm
|
|
21
|
+
|
|
22
|
+
# @return [Hash] Current state as provided by the BOSH Agent
|
|
23
|
+
attr_accessor :current_state
|
|
24
|
+
|
|
25
|
+
# @return [DeploymentPlan::Instance, nil] Instance that reserved this VM
|
|
26
|
+
attr_accessor :bound_instance
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# Creates a new idle VM reference for the specific resource pool
|
|
30
|
+
# @param [DeploymentPlan::ResourcePool] resource_pool Resource pool
|
|
31
|
+
def initialize(resource_pool)
|
|
32
|
+
@resource_pool = resource_pool
|
|
33
|
+
@current_state = nil
|
|
34
|
+
@bound_instance = nil
|
|
35
|
+
@network_reservation = nil
|
|
36
|
+
@vm = nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# @return [Boolean] Does this VM have a network reservation?
|
|
41
|
+
def has_network_reservation?
|
|
42
|
+
!@network_reservation.nil?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# Uses provided network reservation
|
|
47
|
+
# @param [NetworkReservation] reservation Network reservation
|
|
48
|
+
def use_reservation(reservation)
|
|
49
|
+
@network_reservation = reservation
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
#
|
|
53
|
+
# Releases current network reservation (if any)
|
|
54
|
+
# @return [void]
|
|
55
|
+
def release_reservation
|
|
56
|
+
if has_network_reservation?
|
|
57
|
+
@resource_pool.network.release(@network_reservation)
|
|
58
|
+
@network_reservation = nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
##
|
|
63
|
+
# @return [Hash] BOSH network settings used for Agent apply call
|
|
64
|
+
def network_settings
|
|
65
|
+
# use the instance network settings if bound, otherwise use the one
|
|
66
|
+
# provided by the resource pool
|
|
67
|
+
if @bound_instance
|
|
68
|
+
@bound_instance.network_settings
|
|
69
|
+
else
|
|
70
|
+
unless @network_reservation
|
|
71
|
+
raise NetworkReservationMissing,
|
|
72
|
+
"Missing network reservation for resource pool VM"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
network_settings = {}
|
|
76
|
+
network = @resource_pool.network
|
|
77
|
+
network_settings[network.name] = network.network_settings(
|
|
78
|
+
@network_reservation)
|
|
79
|
+
network_settings
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
##
|
|
84
|
+
# @return [Boolean] returns true if the expected network configuration
|
|
85
|
+
# differs from the one provided by the VM
|
|
86
|
+
def networks_changed?
|
|
87
|
+
network_settings != @current_state["networks"]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
##
|
|
91
|
+
# @return [Boolean] returns true if the expected resource pool
|
|
92
|
+
# specification differs from the one provided by the VM
|
|
93
|
+
def resource_pool_changed?
|
|
94
|
+
return true if resource_pool.spec != @current_state["resource_pool"]
|
|
95
|
+
return true if resource_pool.deployment_plan.recreate
|
|
96
|
+
return true if @vm && @vm.env != resource_pool.env
|
|
97
|
+
|
|
98
|
+
false
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
##
|
|
102
|
+
# @return [Boolean] returns true if the any of the expected specifications
|
|
103
|
+
# differ from the ones provided by the VM
|
|
104
|
+
def changed?
|
|
105
|
+
resource_pool_changed? || networks_changed?
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
module DeploymentPlan
|
|
5
|
+
##
|
|
6
|
+
# Represents a single job instance.
|
|
7
|
+
class Instance
|
|
8
|
+
include DnsHelper
|
|
9
|
+
|
|
10
|
+
# @return [DeploymentPlan::Job] Associated job
|
|
11
|
+
attr_reader :job
|
|
12
|
+
|
|
13
|
+
# @return [Integer] Instance index
|
|
14
|
+
attr_reader :index
|
|
15
|
+
|
|
16
|
+
# @return [Models::Instance] Instance model
|
|
17
|
+
attr_reader :model
|
|
18
|
+
|
|
19
|
+
# @return [String] Checksum all of the configuration templates
|
|
20
|
+
attr_accessor :configuration_hash
|
|
21
|
+
|
|
22
|
+
# @return [Hash] A hash of template SHA1 hashes.
|
|
23
|
+
attr_accessor :template_hashes
|
|
24
|
+
|
|
25
|
+
# @return [Hash<String, NetworkReservation>] network reservations
|
|
26
|
+
attr_accessor :network_reservations
|
|
27
|
+
|
|
28
|
+
# @return [String] job state
|
|
29
|
+
attr_accessor :state
|
|
30
|
+
|
|
31
|
+
# @return [Hash] current state as provided by the BOSH Agent
|
|
32
|
+
attr_accessor :current_state
|
|
33
|
+
|
|
34
|
+
# @return [DeploymentPlan::IdleVm] Associated resource pool VM
|
|
35
|
+
attr_reader :idle_vm
|
|
36
|
+
|
|
37
|
+
# @return [Boolean] true if this instance needs to be recreated
|
|
38
|
+
attr_accessor :recreate
|
|
39
|
+
|
|
40
|
+
# @return [Boolean] true if this instance needs to be restarted
|
|
41
|
+
attr_accessor :restart
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# Creates a new instance specification based on the job and index.
|
|
45
|
+
#
|
|
46
|
+
# @param [DeploymentPlan::Job] job associated job
|
|
47
|
+
# @param [Integer] index index for this instance
|
|
48
|
+
def initialize(job, index)
|
|
49
|
+
@job = job
|
|
50
|
+
@index = index
|
|
51
|
+
@model = nil
|
|
52
|
+
@configuration_hash = nil
|
|
53
|
+
@template_hashes = nil
|
|
54
|
+
@idle_vm = nil
|
|
55
|
+
@current_state = nil
|
|
56
|
+
|
|
57
|
+
@network_reservations = {}
|
|
58
|
+
@state = job.instance_state(@index)
|
|
59
|
+
|
|
60
|
+
# Expanding virtual states
|
|
61
|
+
case @state
|
|
62
|
+
when "recreate"
|
|
63
|
+
@recreate = true
|
|
64
|
+
@state = "started"
|
|
65
|
+
when "restart"
|
|
66
|
+
@restart = true
|
|
67
|
+
@state = "started"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def to_s
|
|
72
|
+
"#{@job.name}/#{@index}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @param [Models::Instance] model Instance DB model
|
|
76
|
+
# @return [void]
|
|
77
|
+
def use_model(model)
|
|
78
|
+
if @model
|
|
79
|
+
raise DirectorError, "Instance model is already bound"
|
|
80
|
+
end
|
|
81
|
+
@model = model
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Looks up a DB model for this instance, creates one if doesn't exist
|
|
85
|
+
# yet.
|
|
86
|
+
# @return [void]
|
|
87
|
+
def bind_model
|
|
88
|
+
@model ||= find_or_create_model
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Looks up instance model in DB and binds it to this instance spec.
|
|
92
|
+
# Instance model is created if it's not found in DB. New idle VM is
|
|
93
|
+
# allocated if instance DB record doesn't reference one.
|
|
94
|
+
# @return [void]
|
|
95
|
+
def bind_unallocated_vm
|
|
96
|
+
bind_model
|
|
97
|
+
if @model.vm.nil?
|
|
98
|
+
allocate_idle_vm
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Syncs instance state with instance model in DB. This is needed because
|
|
103
|
+
# not all instance states are available in the deployment manifest and we
|
|
104
|
+
# we cannot really persist this data in the agent state (as VM might be
|
|
105
|
+
# stopped or detached).
|
|
106
|
+
# @return [void]
|
|
107
|
+
def sync_state_with_db
|
|
108
|
+
if @model.nil?
|
|
109
|
+
raise DirectorError, "Instance `#{self}' model is not bound"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
if @state
|
|
113
|
+
# Deployment plan explicitly sets state for this instance
|
|
114
|
+
@model.update(:state => @state)
|
|
115
|
+
elsif @model.state
|
|
116
|
+
# Instance has its state persisted from the previous deployment
|
|
117
|
+
@state = @model.state
|
|
118
|
+
else
|
|
119
|
+
# Target instance state should either be persisted in DB or provided
|
|
120
|
+
# via deployment plan, otherwise something is really wrong
|
|
121
|
+
raise InstanceTargetStateUndefined,
|
|
122
|
+
"Instance `#{self}' target state cannot be determined"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
##
|
|
127
|
+
# Adds a new network to this instance
|
|
128
|
+
# @param [String] name network name
|
|
129
|
+
# @param [NetworkReservation] reservation
|
|
130
|
+
def add_network_reservation(name, reservation)
|
|
131
|
+
old_reservation = @network_reservations[name]
|
|
132
|
+
|
|
133
|
+
if old_reservation
|
|
134
|
+
raise NetworkReservationAlreadyExists,
|
|
135
|
+
"`#{self}' already has reservation " +
|
|
136
|
+
"for network `#{name}', IP #{old_reservation.ip}"
|
|
137
|
+
end
|
|
138
|
+
@network_reservations[name] = reservation
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
##
|
|
142
|
+
# Take any existing valid network reservations
|
|
143
|
+
#
|
|
144
|
+
# @param [Hash<String, NetworkReservation] reservations
|
|
145
|
+
# @return [void]
|
|
146
|
+
def take_network_reservations(reservations)
|
|
147
|
+
reservations.each do |name, provided_reservation|
|
|
148
|
+
reservation = @network_reservations[name]
|
|
149
|
+
reservation.take(provided_reservation) if reservation
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
##
|
|
154
|
+
# @return [Hash] BOSH network settings used for Agent apply call
|
|
155
|
+
def network_settings
|
|
156
|
+
default_properties = {}
|
|
157
|
+
@job.default_network.each do |key, value|
|
|
158
|
+
(default_properties[value] ||= []) << key
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
network_settings = {}
|
|
162
|
+
@network_reservations.each do |name, reservation|
|
|
163
|
+
network = @job.deployment.network(name)
|
|
164
|
+
network_settings[name] = network.network_settings(reservation, default_properties[name])
|
|
165
|
+
network_settings[name]['dns_record_name'] = dns_record_name(name)
|
|
166
|
+
|
|
167
|
+
# Somewhat of a hack: for dynamic networks we might know IP address, Netmask & Gateway
|
|
168
|
+
# if they're featured in agent state, in that case we put them into network spec to satisfy
|
|
169
|
+
# ConfigurationHasher in both agent and director.
|
|
170
|
+
if @current_state.is_a?(Hash) &&
|
|
171
|
+
@current_state['networks'].is_a?(Hash) &&
|
|
172
|
+
@current_state['networks'][name].is_a?(Hash) &&
|
|
173
|
+
network_settings[name]['type'] == 'dynamic'
|
|
174
|
+
%w(ip netmask gateway).each do |key|
|
|
175
|
+
network_settings[name][key] = @current_state['networks'][name][key]
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
network_settings
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
##
|
|
183
|
+
# @return [Integer] persistent disk size
|
|
184
|
+
def disk_size
|
|
185
|
+
if @model.nil?
|
|
186
|
+
current_state["persistent_disk"].to_i
|
|
187
|
+
elsif @model.persistent_disk
|
|
188
|
+
@model.persistent_disk.size
|
|
189
|
+
else
|
|
190
|
+
0
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
##
|
|
195
|
+
# @return [Hash<String, String>] dns record hash of dns name and IP
|
|
196
|
+
def dns_record_info
|
|
197
|
+
dns_record_info = {}
|
|
198
|
+
network_settings.each do |network_name, network|
|
|
199
|
+
name = dns_record_name(network_name)
|
|
200
|
+
dns_record_info[name] = network["ip"]
|
|
201
|
+
end
|
|
202
|
+
dns_record_info
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
##
|
|
206
|
+
# @return [String] dns record name
|
|
207
|
+
def dns_record_name(network_name)
|
|
208
|
+
[index, job.canonical_name, canonical(network_name), job.deployment.canonical_name, dns_domain_name].join(".")
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
##
|
|
212
|
+
# @return [Boolean] returns true if the persistent disk is attached to the
|
|
213
|
+
# VM
|
|
214
|
+
def disk_currently_attached?
|
|
215
|
+
current_state["persistent_disk"].to_i > 0
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
##
|
|
219
|
+
# @return [Boolean] returns true if the network configuration changed
|
|
220
|
+
def networks_changed?
|
|
221
|
+
network_settings != @current_state["networks"]
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
##
|
|
225
|
+
# @return [Boolean] returns true if the expected resource pool differs
|
|
226
|
+
# from the one provided by the VM
|
|
227
|
+
def resource_pool_changed?
|
|
228
|
+
if @recreate || @job.deployment.recreate
|
|
229
|
+
return true
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
if @job.resource_pool.spec != @current_state["resource_pool"]
|
|
233
|
+
return true
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# env is not a part of a resource pool spec but rather gets persisted
|
|
237
|
+
# in director DB, hence the check below
|
|
238
|
+
# NOTE: we only update VMs that have env persisted to avoid recreating
|
|
239
|
+
# everything, so if the director gets updated from the version that
|
|
240
|
+
# doesn't persist VM env to the version that does, there needs to
|
|
241
|
+
# be at least one deployment that recreates all VMs before the following
|
|
242
|
+
# code path gets exercised.
|
|
243
|
+
if @model && @model.vm && @model.vm.env &&
|
|
244
|
+
@job.resource_pool.env != @model.vm.env
|
|
245
|
+
return true
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
false
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
##
|
|
252
|
+
# @return [Boolean] returns true if the expected configuration hash
|
|
253
|
+
# differs from the one provided by the VM
|
|
254
|
+
def configuration_changed?
|
|
255
|
+
configuration_hash != @current_state["configuration_hash"]
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
##
|
|
259
|
+
# @return [Boolean] returns true if the expected job configuration differs
|
|
260
|
+
# from the one provided by the VM
|
|
261
|
+
def job_changed?
|
|
262
|
+
job_spec = @job.spec
|
|
263
|
+
if job_spec != @current_state["job"]
|
|
264
|
+
# The agent job spec could be in legacy form. job_spec cannot be,
|
|
265
|
+
# though, because we got it from the spec function in job.rb which
|
|
266
|
+
# automatically makes it non-legacy.
|
|
267
|
+
return job_spec != Job.convert_from_legacy_spec(@current_state["job"])
|
|
268
|
+
end
|
|
269
|
+
return false
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
##
|
|
273
|
+
# @return [Boolean] returns true if the expected packaged of the running
|
|
274
|
+
# instance differ from the ones provided by the VM
|
|
275
|
+
def packages_changed?
|
|
276
|
+
@job.package_spec != @current_state["packages"]
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
##
|
|
280
|
+
# @return [Boolean] returns true if the expected persistent disk differs
|
|
281
|
+
# from the one currently configured on the VM
|
|
282
|
+
def persistent_disk_changed?
|
|
283
|
+
@job.persistent_disk != disk_size
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
##
|
|
287
|
+
# @return [Boolean] returns true if the DNS records configured for the
|
|
288
|
+
# instance differ from the ones configured on the DNS server
|
|
289
|
+
def dns_changed?
|
|
290
|
+
if Config.dns_enabled?
|
|
291
|
+
dns_record_info.any? do |name, ip|
|
|
292
|
+
Models::Dns::Record.find(:name => name, :type => "A",
|
|
293
|
+
:content => ip).nil?
|
|
294
|
+
end
|
|
295
|
+
else
|
|
296
|
+
false
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
##
|
|
301
|
+
# Checks if agent view of the instance state is consistent with target
|
|
302
|
+
# instance state.
|
|
303
|
+
#
|
|
304
|
+
# In case the instance current state is 'detached' we should never get to
|
|
305
|
+
# this method call.
|
|
306
|
+
# @return [Boolean] returns true if the expected job state differs from
|
|
307
|
+
# the one provided by the VM
|
|
308
|
+
def state_changed?
|
|
309
|
+
@state == "detached" ||
|
|
310
|
+
@state == "started" && @current_state["job_state"] != "running" ||
|
|
311
|
+
@state == "stopped" && @current_state["job_state"] == "running"
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
##
|
|
315
|
+
# @return [Boolean] returns true if the any of the expected specifications
|
|
316
|
+
# differ from the ones provided by the VM
|
|
317
|
+
def changed?
|
|
318
|
+
!changes.empty?
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
##
|
|
322
|
+
# @return [Set<Symbol>] returns a set of all of the specification
|
|
323
|
+
# differences
|
|
324
|
+
def changes
|
|
325
|
+
changes = Set.new
|
|
326
|
+
unless @state == "detached" && @current_state.nil?
|
|
327
|
+
changes << :restart if @restart
|
|
328
|
+
changes << :resource_pool if resource_pool_changed?
|
|
329
|
+
changes << :network if networks_changed?
|
|
330
|
+
changes << :packages if packages_changed?
|
|
331
|
+
changes << :persistent_disk if persistent_disk_changed?
|
|
332
|
+
changes << :configuration if configuration_changed?
|
|
333
|
+
changes << :job if job_changed?
|
|
334
|
+
changes << :state if state_changed?
|
|
335
|
+
changes << :dns if dns_changed?
|
|
336
|
+
end
|
|
337
|
+
changes
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
##
|
|
341
|
+
# Instance spec that's passed to the VM during the BOSH Agent apply call.
|
|
342
|
+
# It's what's used for comparing the expected vs the actual state.
|
|
343
|
+
#
|
|
344
|
+
# @return [Hash<String, Object>] instance spec
|
|
345
|
+
def spec
|
|
346
|
+
spec = {
|
|
347
|
+
"deployment" => @job.deployment.name,
|
|
348
|
+
"release" => job.release.spec,
|
|
349
|
+
"job" => job.spec,
|
|
350
|
+
"index" => index,
|
|
351
|
+
"networks" => network_settings,
|
|
352
|
+
"resource_pool" => job.resource_pool.spec,
|
|
353
|
+
"packages" => job.package_spec,
|
|
354
|
+
"persistent_disk" => job.persistent_disk,
|
|
355
|
+
"configuration_hash" => configuration_hash,
|
|
356
|
+
"properties" => job.properties,
|
|
357
|
+
"dns_domain_name" => dns_domain_name
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if template_hashes
|
|
361
|
+
spec["template_hashes"] = template_hashes
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
spec
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# Looks up instance model in DB
|
|
368
|
+
# @return [Models::Instance]
|
|
369
|
+
def find_or_create_model
|
|
370
|
+
if @job.deployment.model.nil?
|
|
371
|
+
raise DirectorError, "Deployment model is not bound"
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
conditions = {
|
|
375
|
+
:deployment_id => @job.deployment.model.id,
|
|
376
|
+
:job => @job.name,
|
|
377
|
+
:index => @index
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
Models::Instance.find_or_create(conditions) do |model|
|
|
381
|
+
model.state = "started"
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
# Allocates an idle VM in this job resource pool and binds current
|
|
386
|
+
# instance to that idle VM.
|
|
387
|
+
# @return [void]
|
|
388
|
+
def allocate_idle_vm
|
|
389
|
+
resource_pool = @job.resource_pool
|
|
390
|
+
idle_vm = resource_pool.allocate_vm
|
|
391
|
+
network = resource_pool.network
|
|
392
|
+
|
|
393
|
+
if idle_vm.vm
|
|
394
|
+
# There's already a resource pool VM that can become our instance,
|
|
395
|
+
# so we can try to reuse its reservation
|
|
396
|
+
instance_reservation = @network_reservations[network.name]
|
|
397
|
+
if instance_reservation
|
|
398
|
+
instance_reservation.take(idle_vm.network_reservation)
|
|
399
|
+
end
|
|
400
|
+
else
|
|
401
|
+
# VM is not created yet: let's just make it reference this instance
|
|
402
|
+
# so later it knows what it needs to become
|
|
403
|
+
idle_vm.bound_instance = self
|
|
404
|
+
# this also means we no longer need previous VM network reservation
|
|
405
|
+
# (instance has its own)
|
|
406
|
+
idle_vm.release_reservation
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
@idle_vm = idle_vm
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
end
|