bosh-director 1.5.0.pre.1113

Sign up to get free protection for your applications and to get access to all the features.
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