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,137 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
module DeploymentPlan
|
|
5
|
+
##
|
|
6
|
+
# Represents a explicitly configured network.
|
|
7
|
+
class ManualNetwork < Network
|
|
8
|
+
include IpUtil
|
|
9
|
+
include DnsHelper
|
|
10
|
+
include ValidationHelper
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Creates a new network.
|
|
14
|
+
#
|
|
15
|
+
# @param [DeploymentPlan] deployment associated deployment plan
|
|
16
|
+
# @param [Hash] network_spec parsed deployment manifest network section
|
|
17
|
+
def initialize(deployment, network_spec)
|
|
18
|
+
super
|
|
19
|
+
|
|
20
|
+
@subnets = []
|
|
21
|
+
subnets = safe_property(network_spec, "subnets", :class => Array)
|
|
22
|
+
|
|
23
|
+
subnets.each do |subnet_spec|
|
|
24
|
+
new_subnet = NetworkSubnet.new(self, subnet_spec)
|
|
25
|
+
@subnets.each do |subnet|
|
|
26
|
+
if subnet.overlaps?(new_subnet)
|
|
27
|
+
raise NetworkOverlappingSubnets,
|
|
28
|
+
"Network `#{name}' has overlapping subnets"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
@subnets << new_subnet
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Uncomment line below when integration tests is fixed
|
|
35
|
+
# raise "Must specify at least one subnet" if @subnets.empty?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# Reserves a network resource.
|
|
40
|
+
#
|
|
41
|
+
# This is either an already used reservation being verified or a new one
|
|
42
|
+
# waiting to be fulfilled.
|
|
43
|
+
# @param [NetworkReservation] reservation
|
|
44
|
+
# @return [Boolean] true if the reservation was fulfilled
|
|
45
|
+
def reserve(reservation)
|
|
46
|
+
reservation.reserved = false
|
|
47
|
+
if reservation.ip
|
|
48
|
+
find_subnet(reservation.ip) do |subnet|
|
|
49
|
+
type = subnet.reserve_ip(reservation.ip)
|
|
50
|
+
if type.nil?
|
|
51
|
+
reservation.error = NetworkReservation::USED
|
|
52
|
+
elsif reservation.type && reservation.type != type
|
|
53
|
+
reservation.error = NetworkReservation::WRONG_TYPE
|
|
54
|
+
else
|
|
55
|
+
reservation.type = type
|
|
56
|
+
reservation.reserved = true
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
unless reservation.dynamic?
|
|
61
|
+
raise NetworkReservationInvalidType,
|
|
62
|
+
"New reservations without IPs must be dynamic"
|
|
63
|
+
end
|
|
64
|
+
@subnets.each do |subnet|
|
|
65
|
+
reservation.ip = subnet.allocate_dynamic_ip
|
|
66
|
+
if reservation.ip
|
|
67
|
+
reservation.reserved = true
|
|
68
|
+
break
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
unless reservation.reserved?
|
|
72
|
+
reservation.error = NetworkReservation::CAPACITY
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
reservation.reserved?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Releases a previous reservation that had been fulfilled.
|
|
80
|
+
# @param [NetworkReservation] reservation
|
|
81
|
+
# @return [void]
|
|
82
|
+
def release(reservation)
|
|
83
|
+
unless reservation.ip
|
|
84
|
+
raise NetworkReservationIpMissing,
|
|
85
|
+
"Can't release reservation without an IP"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
find_subnet(reservation.ip) do |subnet|
|
|
89
|
+
subnet.release_ip(reservation.ip)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
##
|
|
94
|
+
# Returns the network settings for the specific reservation.
|
|
95
|
+
#
|
|
96
|
+
# @param [NetworkReservation] reservation
|
|
97
|
+
# @param [Array<String>] default_properties
|
|
98
|
+
# @return [Hash] network settings that will be passed to the BOSH Agent
|
|
99
|
+
def network_settings(reservation, default_properties = VALID_DEFAULTS)
|
|
100
|
+
unless reservation.ip
|
|
101
|
+
raise NetworkReservationIpMissing,
|
|
102
|
+
"Can't generate network settings without an IP"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
config = nil
|
|
106
|
+
find_subnet(reservation.ip) do |subnet|
|
|
107
|
+
ip = ip_to_netaddr(reservation.ip)
|
|
108
|
+
config = {
|
|
109
|
+
"ip" => ip.ip,
|
|
110
|
+
"netmask" => subnet.netmask,
|
|
111
|
+
"cloud_properties" => subnet.cloud_properties
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if default_properties
|
|
115
|
+
config["default"] = default_properties.sort
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
config["dns"] = subnet.dns if subnet.dns
|
|
119
|
+
config["gateway"] = subnet.gateway.ip if subnet.gateway
|
|
120
|
+
end
|
|
121
|
+
config
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
##
|
|
125
|
+
# @param [Integer, NetAddr::CIDR, String] ip
|
|
126
|
+
# @yield the subnet that contains the IP.
|
|
127
|
+
def find_subnet(ip)
|
|
128
|
+
@subnets.each do |subnet|
|
|
129
|
+
if subnet.range.contains?(ip)
|
|
130
|
+
yield subnet
|
|
131
|
+
break
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
module DeploymentPlan
|
|
5
|
+
##
|
|
6
|
+
# Represents a logical deployment network.
|
|
7
|
+
class Network
|
|
8
|
+
include DnsHelper
|
|
9
|
+
include ValidationHelper
|
|
10
|
+
|
|
11
|
+
VALID_DEFAULTS = %w(dns gateway).sort
|
|
12
|
+
|
|
13
|
+
# @return [DeploymentPlan] associated deployment
|
|
14
|
+
attr_accessor :deployment
|
|
15
|
+
|
|
16
|
+
# @return [String] network name
|
|
17
|
+
attr_accessor :name
|
|
18
|
+
|
|
19
|
+
# @return [String] canonical network name
|
|
20
|
+
attr_accessor :canonical_name
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Creates a new network.
|
|
24
|
+
#
|
|
25
|
+
# @param [DeploymentPlan] deployment associated deployment plan
|
|
26
|
+
# @param [Hash] network_spec parsed deployment manifest network section
|
|
27
|
+
def initialize(deployment, network_spec)
|
|
28
|
+
@deployment = deployment
|
|
29
|
+
@name = safe_property(network_spec, "name", :class => String)
|
|
30
|
+
@canonical_name = canonical(@name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# Reserves a network resource, raises an error if reservation failed
|
|
35
|
+
# @param [NetworkReservation] reservation Network reservation
|
|
36
|
+
# @param [String] origin Whoever is reserving
|
|
37
|
+
def reserve!(reservation, origin)
|
|
38
|
+
reserve(reservation)
|
|
39
|
+
unless reservation.reserved?
|
|
40
|
+
reservation.handle_error(origin)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
##
|
|
45
|
+
# Reserves a network resource.
|
|
46
|
+
#
|
|
47
|
+
# Will update the passed in reservation if it can be fulfilled.
|
|
48
|
+
# @param [NetworkReservation] reservation
|
|
49
|
+
# @return [Boolean] true if the reservation was fulfilled
|
|
50
|
+
def reserve(reservation)
|
|
51
|
+
raise NotImplementedError, "#reserve not implemented for #{self.class}"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# Releases a previous reservation that had been fulfilled.
|
|
56
|
+
# @param [NetworkReservation] reservation
|
|
57
|
+
# @return [void]
|
|
58
|
+
def release(reservation)
|
|
59
|
+
raise NotImplementedError, "#release not implemented for #{self.class}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
##
|
|
63
|
+
# Returns the network settings for the specific reservation.
|
|
64
|
+
#
|
|
65
|
+
# @param [NetworkReservation] reservation
|
|
66
|
+
# @param [Array<String>] default_properties
|
|
67
|
+
# @return [Hash] network settings that will be passed to the BOSH Agent
|
|
68
|
+
def network_settings(reservation, default_properties = VALID_DEFAULTS)
|
|
69
|
+
raise NotImplementedError,
|
|
70
|
+
"#network_settings not implemented for #{self.class}"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
module DeploymentPlan
|
|
5
|
+
class NetworkSubnet
|
|
6
|
+
include DnsHelper
|
|
7
|
+
include IpUtil
|
|
8
|
+
include ValidationHelper
|
|
9
|
+
|
|
10
|
+
# @return [DeploymentPlan::Network] Network this subnet belongs to
|
|
11
|
+
attr_reader :network
|
|
12
|
+
|
|
13
|
+
# @return [NetAddr::CIDR] Subnet range
|
|
14
|
+
attr_reader :range
|
|
15
|
+
|
|
16
|
+
# @return [NetAddr::CIDR] Subnet gateway IP address
|
|
17
|
+
attr_reader :gateway
|
|
18
|
+
|
|
19
|
+
# @return [Array<String>] Subnet DNS IP addresses
|
|
20
|
+
attr_reader :dns
|
|
21
|
+
|
|
22
|
+
# @return [Hash] Subnet cloud properties (VLAN etc.)
|
|
23
|
+
attr_reader :cloud_properties
|
|
24
|
+
|
|
25
|
+
# @return [String] Subnet netmask
|
|
26
|
+
attr_reader :netmask
|
|
27
|
+
|
|
28
|
+
# @param [DeploymentPlan::Network] network Network
|
|
29
|
+
# @param [Hash] subnet_spec Raw subnet spec from deployment manifest
|
|
30
|
+
def initialize(network, subnet_spec)
|
|
31
|
+
@network = network
|
|
32
|
+
|
|
33
|
+
range_property = safe_property(subnet_spec, "range", :class => String)
|
|
34
|
+
@range = NetAddr::CIDR.create(range_property)
|
|
35
|
+
|
|
36
|
+
if @range.size <= 1
|
|
37
|
+
raise NetworkInvalidRange,
|
|
38
|
+
"Invalid network range `#{range_property}', " +
|
|
39
|
+
"should include at least 2 IPs"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
@netmask = @range.wildcard_mask
|
|
43
|
+
network_id = @range.network(:Objectify => true)
|
|
44
|
+
broadcast = @range.broadcast(:Objectify => true)
|
|
45
|
+
|
|
46
|
+
gateway_property = safe_property(subnet_spec, "gateway",
|
|
47
|
+
:class => String, :optional => true)
|
|
48
|
+
if gateway_property
|
|
49
|
+
@gateway = NetAddr::CIDR.create(gateway_property)
|
|
50
|
+
unless @gateway.size == 1
|
|
51
|
+
invalid_gateway("must be a single IP")
|
|
52
|
+
end
|
|
53
|
+
unless @range.contains?(@gateway)
|
|
54
|
+
invalid_gateway("must be inside the range")
|
|
55
|
+
end
|
|
56
|
+
if @gateway == network_id
|
|
57
|
+
invalid_gateway("can't be the network id")
|
|
58
|
+
end
|
|
59
|
+
if @gateway == broadcast
|
|
60
|
+
invalid_gateway("can't be the broadcast IP")
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
@dns = dns_servers(@network.name, subnet_spec)
|
|
65
|
+
|
|
66
|
+
@cloud_properties = safe_property(subnet_spec, "cloud_properties",
|
|
67
|
+
:class => Hash)
|
|
68
|
+
|
|
69
|
+
@available_dynamic_ips = Set.new
|
|
70
|
+
@available_static_ips = Set.new
|
|
71
|
+
|
|
72
|
+
first_ip = @range.first(:Objectify => true)
|
|
73
|
+
last_ip = @range.last(:Objectify => true)
|
|
74
|
+
|
|
75
|
+
(first_ip.to_i .. last_ip.to_i).each do |ip|
|
|
76
|
+
@available_dynamic_ips << ip
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
@available_dynamic_ips.delete(@gateway.to_i) if @gateway
|
|
80
|
+
@available_dynamic_ips.delete(network_id.to_i)
|
|
81
|
+
@available_dynamic_ips.delete(broadcast.to_i)
|
|
82
|
+
|
|
83
|
+
reserved_ips = safe_property(subnet_spec, "reserved", :optional => true)
|
|
84
|
+
static_ips = safe_property(subnet_spec, "static", :optional => true)
|
|
85
|
+
|
|
86
|
+
each_ip(reserved_ips) do |ip|
|
|
87
|
+
unless @available_dynamic_ips.delete?(ip)
|
|
88
|
+
raise NetworkReservedIpOutOfRange,
|
|
89
|
+
"Reserved IP `#{format_ip(ip)}' is out of " +
|
|
90
|
+
"network `#{@network.name}' range"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
each_ip(static_ips) do |ip|
|
|
95
|
+
unless @available_dynamic_ips.delete?(ip)
|
|
96
|
+
raise NetworkStaticIpOutOfRange,
|
|
97
|
+
"Static IP `#{format_ip(ip)}' is out of " +
|
|
98
|
+
"network `#{@network.name}' range"
|
|
99
|
+
end
|
|
100
|
+
@available_static_ips.add(ip)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Keeping track of initial pools to understand
|
|
104
|
+
# where to release no longer needed IPs
|
|
105
|
+
@dynamic_ip_pool = @available_dynamic_ips.dup
|
|
106
|
+
@static_ip_pool = @available_static_ips.dup
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def overlaps?(subnet)
|
|
110
|
+
@range == subnet.range ||
|
|
111
|
+
@range.contains?(subnet.range) ||
|
|
112
|
+
subnet.range.contains?(@range)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def reserve_ip(ip)
|
|
116
|
+
ip = ip.to_i
|
|
117
|
+
if @available_static_ips.delete?(ip)
|
|
118
|
+
:static
|
|
119
|
+
elsif @available_dynamic_ips.delete?(ip)
|
|
120
|
+
:dynamic
|
|
121
|
+
else
|
|
122
|
+
nil
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def release_ip(ip)
|
|
127
|
+
ip = ip.to_i
|
|
128
|
+
if @dynamic_ip_pool.include?(ip)
|
|
129
|
+
@available_dynamic_ips.add(ip)
|
|
130
|
+
elsif @static_ip_pool.include?(ip)
|
|
131
|
+
@available_static_ips.add(ip)
|
|
132
|
+
else
|
|
133
|
+
raise NetworkReservationIpNotOwned,
|
|
134
|
+
"Can't release IP `#{format_ip(ip)}' " +
|
|
135
|
+
"back to `#{@network.name}' network: " +
|
|
136
|
+
"it's' neither in dynamic nor in static pool"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def allocate_dynamic_ip
|
|
141
|
+
ip = @available_dynamic_ips.first
|
|
142
|
+
if ip
|
|
143
|
+
@available_dynamic_ips.delete(ip)
|
|
144
|
+
end
|
|
145
|
+
ip
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def dynamic_ips_count
|
|
149
|
+
@available_dynamic_ips.size
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def static_ips_count
|
|
153
|
+
@available_static_ips.size
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
private
|
|
157
|
+
|
|
158
|
+
# @param [String] reason
|
|
159
|
+
# @raise NetworkInvalidGateway
|
|
160
|
+
def invalid_gateway(reason)
|
|
161
|
+
raise NetworkInvalidGateway,
|
|
162
|
+
"Invalid gateway for network `#{@network.name}': #{reason}"
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
module Bosh::Director
|
|
2
|
+
# Encapsulates essential director data structures retrieved
|
|
3
|
+
# from the deployment manifest and the running environment.
|
|
4
|
+
module DeploymentPlan
|
|
5
|
+
class Planner
|
|
6
|
+
include DnsHelper
|
|
7
|
+
include ValidationHelper
|
|
8
|
+
|
|
9
|
+
# @return [String] Deployment name
|
|
10
|
+
attr_reader :name
|
|
11
|
+
# @return [String] Deployment canonical name (for DNS)
|
|
12
|
+
attr_reader :canonical_name
|
|
13
|
+
# @return [Models::Deployment] Deployment DB model
|
|
14
|
+
attr_reader :model
|
|
15
|
+
|
|
16
|
+
attr_accessor :properties
|
|
17
|
+
attr_accessor :compilation
|
|
18
|
+
attr_accessor :update
|
|
19
|
+
attr_accessor :unneeded_instances
|
|
20
|
+
attr_accessor :unneeded_vms
|
|
21
|
+
attr_accessor :dns_domain
|
|
22
|
+
|
|
23
|
+
attr_reader :jobs
|
|
24
|
+
attr_reader :job_rename
|
|
25
|
+
attr_reader :recreate
|
|
26
|
+
|
|
27
|
+
def initialize(manifest, options = {})
|
|
28
|
+
@manifest = manifest
|
|
29
|
+
@recreate = !!options['recreate']
|
|
30
|
+
@job_states = safe_property(options, 'job_states',
|
|
31
|
+
:class => Hash, :default => {})
|
|
32
|
+
|
|
33
|
+
@job_rename = safe_property(options, 'job_rename',
|
|
34
|
+
:class => Hash, :default => {})
|
|
35
|
+
@unneeded_vms = []
|
|
36
|
+
@unneeded_instances = []
|
|
37
|
+
@dns_domain = nil
|
|
38
|
+
|
|
39
|
+
@name = nil
|
|
40
|
+
@canonical_name = nil
|
|
41
|
+
@model = nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def parse
|
|
45
|
+
parse_name
|
|
46
|
+
parse_properties
|
|
47
|
+
parse_releases
|
|
48
|
+
parse_networks
|
|
49
|
+
parse_compilation
|
|
50
|
+
parse_update
|
|
51
|
+
parse_resource_pools
|
|
52
|
+
parse_jobs
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Looks up deployment model in DB or creates one if needed
|
|
56
|
+
# @return [void]
|
|
57
|
+
def bind_model
|
|
58
|
+
if @name.nil? || @canonical_name.nil?
|
|
59
|
+
raise DirectorError,
|
|
60
|
+
'Unable to bind model, name and/or canonical name unknown'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
attrs = {:name => @name}
|
|
64
|
+
|
|
65
|
+
Models::Deployment.db.transaction do
|
|
66
|
+
deployment = Models::Deployment.find(attrs)
|
|
67
|
+
# Canonical uniqueness is not enforced in the DB
|
|
68
|
+
if deployment.nil?
|
|
69
|
+
Models::Deployment.each do |other|
|
|
70
|
+
if canonical(other.name) == @canonical_name
|
|
71
|
+
raise DeploymentCanonicalNameTaken,
|
|
72
|
+
"Invalid deployment name `#{@name}', " +
|
|
73
|
+
'canonical name already taken'
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
deployment = Models::Deployment.create(attrs)
|
|
77
|
+
end
|
|
78
|
+
@model = deployment
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Returns a list of VMs in the deployment (according to DB)
|
|
83
|
+
# @return [Array<Models::Vm>]
|
|
84
|
+
def vms
|
|
85
|
+
if @model.nil?
|
|
86
|
+
raise DirectorError, "Can't get VMs list, deployment model is unbound"
|
|
87
|
+
end
|
|
88
|
+
@model.vms
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Returns a named job
|
|
92
|
+
# @param [String] name Job name
|
|
93
|
+
# @return [Bosh::Director::DeploymentPlan::Job] Job
|
|
94
|
+
def job(name)
|
|
95
|
+
@jobs_name_index[name]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Returns all networks in a deployment plan
|
|
99
|
+
# @return [Array<Bosh::Director::DeploymentPlan::Network>]
|
|
100
|
+
def networks
|
|
101
|
+
@networks.values
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Returns a named network
|
|
105
|
+
# @param [String] name
|
|
106
|
+
# @return [Bosh::Director::DeploymentPlan::Network]
|
|
107
|
+
def network(name)
|
|
108
|
+
@networks[name]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Returns all resource pools in a deployment plan
|
|
112
|
+
# @return [Array<Bosh::Director::DeploymentPlan::ResourcePool>]
|
|
113
|
+
def resource_pools
|
|
114
|
+
@resource_pools.values
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Returns a named resource pool spec
|
|
118
|
+
# @param [String] name Resource pool name
|
|
119
|
+
# @return [Bosh::Director::DeploymentPlan::ResourcePool]
|
|
120
|
+
def resource_pool(name)
|
|
121
|
+
@resource_pools[name]
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Returns all releases in a deployment plan
|
|
125
|
+
# @return [Array<Bosh::Director::DeploymentPlan::Release>]
|
|
126
|
+
def releases
|
|
127
|
+
@releases.values
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Returns a named release
|
|
131
|
+
# @return [Bosh::Director::DeploymentPlan::Release]
|
|
132
|
+
def release(name)
|
|
133
|
+
@releases[name]
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Adds a VM to deletion queue
|
|
137
|
+
# @param [Bosh::Director::Models::Vm] vm VM DB model
|
|
138
|
+
#
|
|
139
|
+
def delete_vm(vm)
|
|
140
|
+
@unneeded_vms << vm
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Adds instance to deletion queue
|
|
144
|
+
# @param [Bosh::Director::Models::Instance] instance Instance DB model
|
|
145
|
+
def delete_instance(instance)
|
|
146
|
+
if @jobs_name_index.has_key?(instance.job)
|
|
147
|
+
@jobs_name_index[instance.job].unneeded_instances << instance
|
|
148
|
+
else
|
|
149
|
+
@unneeded_instances << instance
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def rename_in_progress?
|
|
154
|
+
@job_rename['old_name'] && @job_rename['new_name']
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def parse_name
|
|
158
|
+
@name = safe_property(@manifest, 'name', :class => String)
|
|
159
|
+
@canonical_name = canonical(@name)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def parse_properties
|
|
163
|
+
@properties = safe_property(@manifest, 'properties',
|
|
164
|
+
:class => Hash, :default => {})
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def parse_releases
|
|
168
|
+
release_specs = []
|
|
169
|
+
|
|
170
|
+
if @manifest.has_key?('release')
|
|
171
|
+
if @manifest.has_key?('releases')
|
|
172
|
+
raise DeploymentAmbiguousReleaseSpec,
|
|
173
|
+
"Deployment manifest contains both 'release' and 'releases' " +
|
|
174
|
+
'sections, please use one of the two.'
|
|
175
|
+
end
|
|
176
|
+
release_specs << @manifest['release']
|
|
177
|
+
else
|
|
178
|
+
safe_property(@manifest, 'releases', :class => Array).each do |release|
|
|
179
|
+
release_specs << release
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
@releases = {}
|
|
184
|
+
release_specs.each do |release_spec|
|
|
185
|
+
release = Release.new(self, release_spec)
|
|
186
|
+
if @releases.has_key?(release.name)
|
|
187
|
+
raise DeploymentDuplicateReleaseName,
|
|
188
|
+
"Duplicate release name `#{release.name}'"
|
|
189
|
+
end
|
|
190
|
+
@releases[release.name] = release
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def parse_resource_pools
|
|
195
|
+
@resource_pools = {}
|
|
196
|
+
resource_pools = safe_property(@manifest, 'resource_pools',
|
|
197
|
+
:class => Array)
|
|
198
|
+
resource_pools.each do |spec|
|
|
199
|
+
resource_pool = ResourcePool.new(self, spec)
|
|
200
|
+
if @resource_pools[resource_pool.name]
|
|
201
|
+
raise DeploymentDuplicateResourcePoolName,
|
|
202
|
+
"Duplicate resource pool name `#{resource_pool.name}'"
|
|
203
|
+
end
|
|
204
|
+
@resource_pools[resource_pool.name] = resource_pool
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Uncomment when integration test fixed
|
|
208
|
+
# raise "No resource pools specified." if @resource_pools.empty?
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def parse_jobs
|
|
212
|
+
@jobs = []
|
|
213
|
+
@jobs_name_index = {}
|
|
214
|
+
@jobs_canonical_name_index = Set.new
|
|
215
|
+
|
|
216
|
+
jobs = safe_property(@manifest, 'jobs', :class => Array, :default => [])
|
|
217
|
+
|
|
218
|
+
jobs.each do |job|
|
|
219
|
+
state_overrides = @job_states[job['name']]
|
|
220
|
+
|
|
221
|
+
if state_overrides
|
|
222
|
+
job.recursive_merge!(state_overrides)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
if rename_in_progress? && @job_rename['old_name'] == job['name']
|
|
226
|
+
raise DeploymentRenamedJobNameStillUsed,
|
|
227
|
+
"Renamed job `#{job['name']}' is still referenced in " +
|
|
228
|
+
'deployment manifest'
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
job = Job.parse(self, job)
|
|
232
|
+
|
|
233
|
+
if @jobs_canonical_name_index.include?(job.canonical_name)
|
|
234
|
+
raise DeploymentCanonicalJobNameTaken,
|
|
235
|
+
"Invalid job name `#{job.name}', canonical name already taken"
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
@jobs << job
|
|
239
|
+
@jobs_name_index[job.name] = job
|
|
240
|
+
@jobs_canonical_name_index << job.canonical_name
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def parse_networks
|
|
245
|
+
@networks = {}
|
|
246
|
+
@networks_canonical_name_index = Set.new
|
|
247
|
+
networks = safe_property(@manifest, 'networks', :class => Array)
|
|
248
|
+
networks.each do |network_spec|
|
|
249
|
+
type = safe_property(network_spec, 'type', :class => String,
|
|
250
|
+
:default => 'manual')
|
|
251
|
+
case type
|
|
252
|
+
when 'manual'
|
|
253
|
+
network = ManualNetwork.new(self, network_spec)
|
|
254
|
+
when 'dynamic'
|
|
255
|
+
network = DynamicNetwork.new(self, network_spec)
|
|
256
|
+
when 'vip'
|
|
257
|
+
network = VipNetwork.new(self, network_spec)
|
|
258
|
+
else
|
|
259
|
+
raise DeploymentInvalidNetworkType,
|
|
260
|
+
"Invalid network type `#{type}'"
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
if @networks_canonical_name_index.include?(network.canonical_name)
|
|
264
|
+
raise DeploymentCanonicalNetworkNameTaken,
|
|
265
|
+
"Invalid network name `#{network.name}', " +
|
|
266
|
+
'canonical name already taken'
|
|
267
|
+
end
|
|
268
|
+
@networks[network.name] = network
|
|
269
|
+
@networks_canonical_name_index << network.canonical_name
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
if @networks.empty?
|
|
273
|
+
raise DeploymentNoNetworks, 'No networks specified'
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def parse_update
|
|
278
|
+
@update = UpdateConfig.new(
|
|
279
|
+
safe_property(@manifest, 'update', :class => Hash))
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def parse_compilation
|
|
283
|
+
@compilation = CompilationConfig.new(self, safe_property(
|
|
284
|
+
@manifest, 'compilation', :class => Hash))
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|