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.
Files changed (180) hide show
  1. data/CHANGELOG +34 -0
  2. data/bin/bosh-director +36 -0
  3. data/bin/bosh-director-console +84 -0
  4. data/bin/bosh-director-drain-workers +42 -0
  5. data/bin/bosh-director-migrate +58 -0
  6. data/bin/bosh-director-scheduler +27 -0
  7. data/bin/bosh-director-worker +76 -0
  8. data/db/migrations/README +1 -0
  9. data/db/migrations/director/20110209010747_initial.rb +118 -0
  10. data/db/migrations/director/20110406055800_add_task_user.rb +9 -0
  11. data/db/migrations/director/20110518225809_remove_cid_constrain.rb +13 -0
  12. data/db/migrations/director/20110617211923_add_deployments_release_versions.rb +32 -0
  13. data/db/migrations/director/20110622212607_add_task_checkpoint_timestamp.rb +9 -0
  14. data/db/migrations/director/20110628023039_add_state_to_instances.rb +21 -0
  15. data/db/migrations/director/20110709012332_add_disk_size_to_instances.rb +9 -0
  16. data/db/migrations/director/20110906183441_add_log_bundles.rb +11 -0
  17. data/db/migrations/director/20110907194830_add_logs_json_to_templates.rb +9 -0
  18. data/db/migrations/director/20110915205610_add_persistent_disks.rb +51 -0
  19. data/db/migrations/director/20111005180929_add_properties.rb +14 -0
  20. data/db/migrations/director/20111110024617_add_deployment_problems.rb +24 -0
  21. data/db/migrations/director/20111216214145_recreate_support_for_vms.rb +9 -0
  22. data/db/migrations/director/20120102084027_add_credentials_to_vms.rb +7 -0
  23. data/db/migrations/director/20120427235217_allow_multiple_releases_per_deployment.rb +36 -0
  24. data/db/migrations/director/20120524175805_add_task_type.rb +44 -0
  25. data/db/migrations/director/20120614001930_delete_redundant_deployment_release_relation.rb +34 -0
  26. data/db/migrations/director/20120822004528_add_fingerprint_to_templates_and_packages.rb +17 -0
  27. data/db/migrations/director/20120830191244_add_properties_to_templates.rb +9 -0
  28. data/db/migrations/director/20121106190739_persist_vm_env.rb +9 -0
  29. data/db/migrations/director/20130222232131_add_sha1_to_stemcells.rb +9 -0
  30. data/db/migrations/director/20130312211407_add_commit_hash_to_release_versions.rb +19 -0
  31. data/db/migrations/director/20130409235338_snapshot.rb +15 -0
  32. data/db/migrations/director/20130530164918_add_paused_flag_to_instance.rb +14 -0
  33. data/db/migrations/director/20130531172604_add_director_attributes.rb +13 -0
  34. data/db/migrations/dns/20120123234908_initial.rb +27 -0
  35. data/lib/bosh/director.rb +133 -0
  36. data/lib/bosh/director/agent_client.rb +78 -0
  37. data/lib/bosh/director/api.rb +29 -0
  38. data/lib/bosh/director/api/api_helper.rb +81 -0
  39. data/lib/bosh/director/api/backup_manager.rb +15 -0
  40. data/lib/bosh/director/api/controller.rb +639 -0
  41. data/lib/bosh/director/api/controller_helpers.rb +34 -0
  42. data/lib/bosh/director/api/deployment_lookup.rb +13 -0
  43. data/lib/bosh/director/api/deployment_manager.rb +60 -0
  44. data/lib/bosh/director/api/http_constants.rb +16 -0
  45. data/lib/bosh/director/api/instance_lookup.rb +44 -0
  46. data/lib/bosh/director/api/instance_manager.rb +63 -0
  47. data/lib/bosh/director/api/problem_manager.rb +40 -0
  48. data/lib/bosh/director/api/property_manager.rb +69 -0
  49. data/lib/bosh/director/api/release_manager.rb +59 -0
  50. data/lib/bosh/director/api/resource_manager.rb +69 -0
  51. data/lib/bosh/director/api/resurrector_manager.rb +15 -0
  52. data/lib/bosh/director/api/snapshot_manager.rb +94 -0
  53. data/lib/bosh/director/api/stemcell_manager.rb +50 -0
  54. data/lib/bosh/director/api/task_helper.rb +46 -0
  55. data/lib/bosh/director/api/task_manager.rb +64 -0
  56. data/lib/bosh/director/api/user_manager.rb +72 -0
  57. data/lib/bosh/director/api/vm_state_manager.rb +11 -0
  58. data/lib/bosh/director/app.rb +35 -0
  59. data/lib/bosh/director/blob_util.rb +87 -0
  60. data/lib/bosh/director/blobstores.rb +29 -0
  61. data/lib/bosh/director/client.rb +156 -0
  62. data/lib/bosh/director/cloudcheck_helper.rb +204 -0
  63. data/lib/bosh/director/compile_task.rb +157 -0
  64. data/lib/bosh/director/config.rb +370 -0
  65. data/lib/bosh/director/configuration_hasher.rb +114 -0
  66. data/lib/bosh/director/cycle_helper.rb +36 -0
  67. data/lib/bosh/director/db_backup.rb +22 -0
  68. data/lib/bosh/director/db_backup/adapter.rb +3 -0
  69. data/lib/bosh/director/db_backup/adapter/mysql2.rb +27 -0
  70. data/lib/bosh/director/db_backup/adapter/postgres.rb +36 -0
  71. data/lib/bosh/director/db_backup/adapter/sqlite.rb +17 -0
  72. data/lib/bosh/director/db_backup/error.rb +10 -0
  73. data/lib/bosh/director/deployment_plan.rb +26 -0
  74. data/lib/bosh/director/deployment_plan/assembler.rb +430 -0
  75. data/lib/bosh/director/deployment_plan/compilation_config.rb +54 -0
  76. data/lib/bosh/director/deployment_plan/compiled_package.rb +35 -0
  77. data/lib/bosh/director/deployment_plan/dynamic_network.rb +91 -0
  78. data/lib/bosh/director/deployment_plan/idle_vm.rb +109 -0
  79. data/lib/bosh/director/deployment_plan/instance.rb +413 -0
  80. data/lib/bosh/director/deployment_plan/job.rb +470 -0
  81. data/lib/bosh/director/deployment_plan/manual_network.rb +137 -0
  82. data/lib/bosh/director/deployment_plan/network.rb +74 -0
  83. data/lib/bosh/director/deployment_plan/network_subnet.rb +167 -0
  84. data/lib/bosh/director/deployment_plan/planner.rb +288 -0
  85. data/lib/bosh/director/deployment_plan/preparer.rb +52 -0
  86. data/lib/bosh/director/deployment_plan/release.rb +126 -0
  87. data/lib/bosh/director/deployment_plan/resource_pool.rb +143 -0
  88. data/lib/bosh/director/deployment_plan/resource_pools.rb +68 -0
  89. data/lib/bosh/director/deployment_plan/stemcell.rb +56 -0
  90. data/lib/bosh/director/deployment_plan/template.rb +94 -0
  91. data/lib/bosh/director/deployment_plan/update_config.rb +80 -0
  92. data/lib/bosh/director/deployment_plan/updater.rb +55 -0
  93. data/lib/bosh/director/deployment_plan/vip_network.rb +79 -0
  94. data/lib/bosh/director/dns_helper.rb +204 -0
  95. data/lib/bosh/director/download_helper.rb +44 -0
  96. data/lib/bosh/director/duration.rb +36 -0
  97. data/lib/bosh/director/encryption_helper.rb +10 -0
  98. data/lib/bosh/director/errors.rb +198 -0
  99. data/lib/bosh/director/event_log.rb +136 -0
  100. data/lib/bosh/director/ext.rb +64 -0
  101. data/lib/bosh/director/hash_string_vals.rb +13 -0
  102. data/lib/bosh/director/instance_deleter.rb +109 -0
  103. data/lib/bosh/director/instance_updater.rb +506 -0
  104. data/lib/bosh/director/ip_util.rb +67 -0
  105. data/lib/bosh/director/job_queue.rb +16 -0
  106. data/lib/bosh/director/job_runner.rb +162 -0
  107. data/lib/bosh/director/job_updater.rb +121 -0
  108. data/lib/bosh/director/jobs/backup.rb +86 -0
  109. data/lib/bosh/director/jobs/base_job.rb +66 -0
  110. data/lib/bosh/director/jobs/cloud_check/apply_resolutions.rb +46 -0
  111. data/lib/bosh/director/jobs/cloud_check/scan.rb +38 -0
  112. data/lib/bosh/director/jobs/cloud_check/scan_and_fix.rb +73 -0
  113. data/lib/bosh/director/jobs/create_snapshot.rb +23 -0
  114. data/lib/bosh/director/jobs/delete_deployment.rb +183 -0
  115. data/lib/bosh/director/jobs/delete_deployment_snapshots.rb +34 -0
  116. data/lib/bosh/director/jobs/delete_release.rb +219 -0
  117. data/lib/bosh/director/jobs/delete_snapshots.rb +23 -0
  118. data/lib/bosh/director/jobs/delete_stemcell.rb +102 -0
  119. data/lib/bosh/director/jobs/fetch_logs.rb +99 -0
  120. data/lib/bosh/director/jobs/scheduled_backup.rb +38 -0
  121. data/lib/bosh/director/jobs/snapshot_deployment.rb +61 -0
  122. data/lib/bosh/director/jobs/snapshot_deployments.rb +23 -0
  123. data/lib/bosh/director/jobs/snapshot_self.rb +43 -0
  124. data/lib/bosh/director/jobs/ssh.rb +59 -0
  125. data/lib/bosh/director/jobs/update_deployment.rb +110 -0
  126. data/lib/bosh/director/jobs/update_release.rb +672 -0
  127. data/lib/bosh/director/jobs/update_stemcell.rb +109 -0
  128. data/lib/bosh/director/jobs/vm_state.rb +89 -0
  129. data/lib/bosh/director/lock.rb +133 -0
  130. data/lib/bosh/director/lock_helper.rb +92 -0
  131. data/lib/bosh/director/models.rb +29 -0
  132. data/lib/bosh/director/models/compiled_package.rb +33 -0
  133. data/lib/bosh/director/models/deployment.rb +22 -0
  134. data/lib/bosh/director/models/deployment_problem.rb +49 -0
  135. data/lib/bosh/director/models/deployment_property.rb +21 -0
  136. data/lib/bosh/director/models/director_attribute.rb +9 -0
  137. data/lib/bosh/director/models/dns.rb +9 -0
  138. data/lib/bosh/director/models/dns/domain.rb +9 -0
  139. data/lib/bosh/director/models/dns/record.rb +7 -0
  140. data/lib/bosh/director/models/helpers/model_helper.rb +7 -0
  141. data/lib/bosh/director/models/instance.rb +28 -0
  142. data/lib/bosh/director/models/log_bundle.rb +10 -0
  143. data/lib/bosh/director/models/package.rb +30 -0
  144. data/lib/bosh/director/models/persistent_disk.rb +13 -0
  145. data/lib/bosh/director/models/release.rb +17 -0
  146. data/lib/bosh/director/models/release_version.rb +16 -0
  147. data/lib/bosh/director/models/snapshot.rb +13 -0
  148. data/lib/bosh/director/models/stemcell.rb +18 -0
  149. data/lib/bosh/director/models/task.rb +10 -0
  150. data/lib/bosh/director/models/template.rb +44 -0
  151. data/lib/bosh/director/models/user.rb +11 -0
  152. data/lib/bosh/director/models/vm.rb +42 -0
  153. data/lib/bosh/director/nats_rpc.rb +54 -0
  154. data/lib/bosh/director/network_reservation.rb +121 -0
  155. data/lib/bosh/director/next_rebase_version.rb +20 -0
  156. data/lib/bosh/director/package_compiler.rb +423 -0
  157. data/lib/bosh/director/problem_handlers/base.rb +153 -0
  158. data/lib/bosh/director/problem_handlers/inactive_disk.rb +112 -0
  159. data/lib/bosh/director/problem_handlers/invalid_problem.rb +28 -0
  160. data/lib/bosh/director/problem_handlers/missing_vm.rb +34 -0
  161. data/lib/bosh/director/problem_handlers/mount_info_mismatch.rb +62 -0
  162. data/lib/bosh/director/problem_handlers/out_of_sync_vm.rb +64 -0
  163. data/lib/bosh/director/problem_handlers/unbound_instance_vm.rb +85 -0
  164. data/lib/bosh/director/problem_handlers/unresponsive_agent.rb +78 -0
  165. data/lib/bosh/director/problem_resolver.rb +103 -0
  166. data/lib/bosh/director/problem_scanner.rb +268 -0
  167. data/lib/bosh/director/resource_pool_updater.rb +216 -0
  168. data/lib/bosh/director/scheduler.rb +57 -0
  169. data/lib/bosh/director/sequel.rb +13 -0
  170. data/lib/bosh/director/tar_gzipper.rb +47 -0
  171. data/lib/bosh/director/task_result_file.rb +19 -0
  172. data/lib/bosh/director/thread_pool.rb +8 -0
  173. data/lib/bosh/director/validation_helper.rb +55 -0
  174. data/lib/bosh/director/version.rb +7 -0
  175. data/lib/bosh/director/vm_creator.rb +80 -0
  176. data/lib/bosh/director/vm_data.rb +63 -0
  177. data/lib/bosh/director/vm_metadata_updater.rb +29 -0
  178. data/lib/bosh/director/vm_reuser.rb +63 -0
  179. data/lib/cloud/dummy.rb +149 -0
  180. 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