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,109 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
module Jobs
|
|
5
|
+
class UpdateStemcell < BaseJob
|
|
6
|
+
include ValidationHelper
|
|
7
|
+
include DownloadHelper
|
|
8
|
+
|
|
9
|
+
UPDATE_STEPS = 5
|
|
10
|
+
|
|
11
|
+
@queue = :normal
|
|
12
|
+
|
|
13
|
+
def self.job_type
|
|
14
|
+
:update_stemcell
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @param [String] stemcell_file Stemcell tarball path
|
|
18
|
+
def initialize(stemcell_file, options = {})
|
|
19
|
+
@stemcell_file = stemcell_file
|
|
20
|
+
@cloud = Config.cloud
|
|
21
|
+
@stemcell_manager = Api::StemcellManager.new
|
|
22
|
+
@remote_stemcell = options['remote'] || false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def perform
|
|
26
|
+
logger.info("Processing update stemcell")
|
|
27
|
+
event_log.begin_stage("Update stemcell", update_steps)
|
|
28
|
+
|
|
29
|
+
if @remote_stemcell
|
|
30
|
+
downloaded_stemcell_dir = Dir.mktmpdir("downloaded-stemcell")
|
|
31
|
+
download_remote_stemcell(downloaded_stemcell_dir)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
stemcell_dir = Dir.mktmpdir("stemcell")
|
|
35
|
+
|
|
36
|
+
track_and_log("Extracting stemcell archive") do
|
|
37
|
+
result = Bosh::Exec.sh("tar -C #{stemcell_dir} -xzf #{@stemcell_file} 2>&1", :on_error => :return)
|
|
38
|
+
if result.failed?
|
|
39
|
+
logger.error("Extracting stemcell archive failed in dir #{stemcell_dir}, " +
|
|
40
|
+
"tar returned #{result.exit_status}, " +
|
|
41
|
+
"output: #{result.output}")
|
|
42
|
+
raise StemcellInvalidArchive, "Extracting stemcell archive failed. Check task debug log for details."
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
track_and_log("Verifying stemcell manifest") do
|
|
47
|
+
stemcell_manifest_file = File.join(stemcell_dir, "stemcell.MF")
|
|
48
|
+
stemcell_manifest = Psych.load_file(stemcell_manifest_file)
|
|
49
|
+
|
|
50
|
+
@name = safe_property(stemcell_manifest, "name", :class => String)
|
|
51
|
+
@version = safe_property(stemcell_manifest, "version", :class => String)
|
|
52
|
+
@cloud_properties = safe_property(stemcell_manifest, "cloud_properties", :class => Hash, :optional => true)
|
|
53
|
+
@sha1 = safe_property(stemcell_manifest, "sha1", :class => String)
|
|
54
|
+
|
|
55
|
+
logger.info("Found stemcell image `#{@name}/#{@version}', " +
|
|
56
|
+
"cloud properties are #{@cloud_properties.inspect}")
|
|
57
|
+
|
|
58
|
+
logger.info("Verifying stemcell image")
|
|
59
|
+
@stemcell_image = File.join(stemcell_dir, "image")
|
|
60
|
+
unless File.file?(@stemcell_image)
|
|
61
|
+
raise StemcellImageNotFound, "Stemcell image not found"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
track_and_log("Checking if this stemcell already exists") do
|
|
66
|
+
if @stemcell_manager.stemcell_exists?(@name, @version)
|
|
67
|
+
raise StemcellAlreadyExists,
|
|
68
|
+
"Stemcell `#{@name}/#{@version}' already exists"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
stemcell = Models::Stemcell.new
|
|
73
|
+
stemcell.name = @name
|
|
74
|
+
stemcell.version = @version
|
|
75
|
+
stemcell.sha1 = @sha1
|
|
76
|
+
|
|
77
|
+
track_and_log("Uploading stemcell #{@name}/#{@version} to the cloud") do
|
|
78
|
+
stemcell.cid =
|
|
79
|
+
@cloud.create_stemcell(@stemcell_image, @cloud_properties)
|
|
80
|
+
logger.info("Cloud created stemcell: #{stemcell.cid}")
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
track_and_log("Save stemcell #{@name}/#{@version} (#{stemcell.cid})") do
|
|
84
|
+
stemcell.save
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
"/stemcells/#{stemcell.name}/#{stemcell.version}"
|
|
88
|
+
ensure
|
|
89
|
+
FileUtils.rm_rf(stemcell_dir) if stemcell_dir
|
|
90
|
+
FileUtils.rm_rf(downloaded_stemcell_dir) if downloaded_stemcell_dir
|
|
91
|
+
FileUtils.rm_rf(@stemcell_file) if @stemcell_file
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def download_remote_stemcell(downloaded_stemcell_dir)
|
|
95
|
+
track_and_log("Downloading remote stemcell") do
|
|
96
|
+
downloaded_stemcell_file = File.join(downloaded_stemcell_dir, "stemcell-#{SecureRandom.uuid}")
|
|
97
|
+
download_remote_file('stemcell', @stemcell_file, downloaded_stemcell_file)
|
|
98
|
+
@stemcell_file = downloaded_stemcell_file
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def update_steps
|
|
105
|
+
@remote_stemcell ? UPDATE_STEPS + 1 : UPDATE_STEPS
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
module Jobs
|
|
5
|
+
class VmState < BaseJob
|
|
6
|
+
TIMEOUT = 5
|
|
7
|
+
|
|
8
|
+
@queue = :normal
|
|
9
|
+
|
|
10
|
+
def self.job_type
|
|
11
|
+
:vms
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @param [Integer] deployment_id Deployment id
|
|
15
|
+
def initialize(deployment_id, format)
|
|
16
|
+
@deployment_id = deployment_id
|
|
17
|
+
@format = format
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def perform
|
|
21
|
+
@domain = Models::Dns::Domain.find(name: Config.dns_domain_name, type: "NATIVE") if Config.dns_enabled?
|
|
22
|
+
|
|
23
|
+
vms = Models::Vm.filter(:deployment_id => @deployment_id)
|
|
24
|
+
ThreadPool.new(:max_threads => Config.max_threads).wrap do |pool|
|
|
25
|
+
vms.each do |vm|
|
|
26
|
+
pool.process do
|
|
27
|
+
vm_state = process_vm(vm)
|
|
28
|
+
result_file.write(vm_state.to_json + "\n")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# task result
|
|
34
|
+
nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def process_vm(vm)
|
|
38
|
+
ips = []
|
|
39
|
+
dns_records = []
|
|
40
|
+
job_name = nil
|
|
41
|
+
job_state = nil
|
|
42
|
+
resource_pool = nil
|
|
43
|
+
job_vitals = nil
|
|
44
|
+
index = nil
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
agent = AgentClient.new(vm.agent_id, :timeout => TIMEOUT)
|
|
48
|
+
agent_state = agent.get_state(@format)
|
|
49
|
+
agent_state["networks"].each_value do |network|
|
|
50
|
+
ips << network["ip"]
|
|
51
|
+
end
|
|
52
|
+
index = agent_state["index"]
|
|
53
|
+
job_name = agent_state["job"]["name"] if agent_state["job"]
|
|
54
|
+
job_state = agent_state["job_state"]
|
|
55
|
+
if agent_state["resource_pool"]
|
|
56
|
+
resource_pool = agent_state["resource_pool"]["name"]
|
|
57
|
+
end
|
|
58
|
+
if agent_state["vitals"]
|
|
59
|
+
job_vitals = agent_state["vitals"]
|
|
60
|
+
end
|
|
61
|
+
rescue Bosh::Director::RpcTimeout
|
|
62
|
+
job_state = "unresponsive agent"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
instance = Models::Instance.find(deployment_id: @deployment_id, job: job_name, index: index)
|
|
66
|
+
|
|
67
|
+
if @domain
|
|
68
|
+
ips.each do |ip|
|
|
69
|
+
records = Models::Dns::Record.filter(domain_id: @domain.id, type: "A", content: ip)
|
|
70
|
+
dns_records << records.collect { |record| record.name } unless records.empty?
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
{
|
|
75
|
+
:vm_cid => vm.cid,
|
|
76
|
+
:ips => ips,
|
|
77
|
+
:dns => dns_records.flatten,
|
|
78
|
+
:agent_id => vm.agent_id,
|
|
79
|
+
:job_name => job_name,
|
|
80
|
+
:index => index,
|
|
81
|
+
:job_state => job_state,
|
|
82
|
+
:resource_pool => resource_pool,
|
|
83
|
+
:vitals => job_vitals,
|
|
84
|
+
:resurrection_paused => instance ? instance.resurrection_paused : nil,
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Director
|
|
4
|
+
|
|
5
|
+
# Distributed lock backed by Redis.
|
|
6
|
+
class Lock
|
|
7
|
+
|
|
8
|
+
# Error returned when Lock could not be acquired.
|
|
9
|
+
class TimeoutError < StandardError; end
|
|
10
|
+
|
|
11
|
+
# Creates new lock with the given name.
|
|
12
|
+
#
|
|
13
|
+
# @param name lock name
|
|
14
|
+
# @option opts [Number] timeout how long to wait before giving up
|
|
15
|
+
# @option opts [Number] expiration how long to wait before expiring an old
|
|
16
|
+
# lock
|
|
17
|
+
def initialize(name, opts = {})
|
|
18
|
+
@name = name
|
|
19
|
+
@id = SecureRandom.uuid
|
|
20
|
+
@timeout = opts[:timeout] || 1.0
|
|
21
|
+
@expiration = opts[:expiration] || 10.0
|
|
22
|
+
@logger = Config.logger
|
|
23
|
+
@refresh_thread = nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Acquire a lock.
|
|
27
|
+
#
|
|
28
|
+
# @yield [void] optional block to do work before automatically releasing
|
|
29
|
+
# the lock.
|
|
30
|
+
# @return [void]
|
|
31
|
+
def lock
|
|
32
|
+
acquire
|
|
33
|
+
|
|
34
|
+
@refresh_thread = Thread.new do
|
|
35
|
+
redis = Config.redis
|
|
36
|
+
sleep_interval = [1.0, @expiration/2].max
|
|
37
|
+
begin
|
|
38
|
+
loop do
|
|
39
|
+
@logger.debug("Renewing lock: #@name")
|
|
40
|
+
redis.watch(@name)
|
|
41
|
+
existing_lock = redis.get(@name)
|
|
42
|
+
lock_id = existing_lock.split(":")[1]
|
|
43
|
+
break if lock_id != @id
|
|
44
|
+
lock_expiration = Time.now.to_f + @expiration + 1
|
|
45
|
+
redis.multi do
|
|
46
|
+
redis.set(@name, "#{lock_expiration}:#@id")
|
|
47
|
+
end
|
|
48
|
+
sleep(sleep_interval)
|
|
49
|
+
end
|
|
50
|
+
ensure
|
|
51
|
+
@logger.debug("Lock renewal thread exiting")
|
|
52
|
+
redis.quit
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if block_given?
|
|
57
|
+
begin
|
|
58
|
+
yield
|
|
59
|
+
ensure
|
|
60
|
+
release
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Release a lock that was not auto released by the lock method.
|
|
66
|
+
#
|
|
67
|
+
# @return [void]
|
|
68
|
+
def release
|
|
69
|
+
@refresh_thread.exit if @refresh_thread
|
|
70
|
+
delete
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def acquire
|
|
76
|
+
@logger.debug("Acquiring lock: #@name")
|
|
77
|
+
redis = Config.redis
|
|
78
|
+
started = Time.now
|
|
79
|
+
|
|
80
|
+
lock_expiration = Time.now.to_f + @expiration + 1
|
|
81
|
+
until redis.setnx(@name, "#{lock_expiration}:#@id")
|
|
82
|
+
existing_lock = redis.get(@name)
|
|
83
|
+
@logger.debug("Lock #@name is already locked by someone " +
|
|
84
|
+
"else: #{existing_lock}")
|
|
85
|
+
if lock_expired?(existing_lock)
|
|
86
|
+
@logger.debug("Lock #@name is already expired, " +
|
|
87
|
+
"trying to take it back")
|
|
88
|
+
replaced_lock = redis.getset(@name, "#{lock_expiration}:#@id")
|
|
89
|
+
if replaced_lock == existing_lock
|
|
90
|
+
@logger.debug("Lock #@name was revoked and relocked")
|
|
91
|
+
break
|
|
92
|
+
else
|
|
93
|
+
@logger.debug("Lock #@name was acquired by someone else, " +
|
|
94
|
+
"trying again")
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
raise TimeoutError if Time.now - started > @timeout
|
|
99
|
+
|
|
100
|
+
sleep(0.5)
|
|
101
|
+
|
|
102
|
+
lock_expiration = Time.now.to_f + @expiration + 1
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
@lock_expiration = lock_expiration
|
|
106
|
+
@logger.debug("Acquired lock: #@name")
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def delete
|
|
110
|
+
@logger.debug("Deleting lock: #@name")
|
|
111
|
+
redis = Config.redis
|
|
112
|
+
|
|
113
|
+
redis.watch(@name)
|
|
114
|
+
existing_lock = redis.get(@name)
|
|
115
|
+
lock_id = existing_lock.split(":")[1]
|
|
116
|
+
if lock_id == @id
|
|
117
|
+
redis.multi do
|
|
118
|
+
redis.del(@name)
|
|
119
|
+
end
|
|
120
|
+
else
|
|
121
|
+
redis.unwatch
|
|
122
|
+
end
|
|
123
|
+
@logger.debug("Deleted lock: #@name")
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def lock_expired?(lock)
|
|
127
|
+
existing_lock_expiration = lock.split(":")[0].to_f
|
|
128
|
+
lock_time_left = existing_lock_expiration - Time.now.to_f
|
|
129
|
+
@logger.info("Lock: #{lock} expires in #{lock_time_left} seconds")
|
|
130
|
+
lock_time_left < 0
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
module Bosh::Director
|
|
2
|
+
# Helper for managing BOSH locks.
|
|
3
|
+
module LockHelper
|
|
4
|
+
|
|
5
|
+
# Surround with deployment lock.
|
|
6
|
+
#
|
|
7
|
+
# @param [DeploymentPlan|String] deployment plan or name.
|
|
8
|
+
# @option opts [Number] timeout how long to wait before giving up
|
|
9
|
+
# @return [void]
|
|
10
|
+
# @yield [void] block to surround
|
|
11
|
+
def with_deployment_lock(deployment, opts = {})
|
|
12
|
+
if deployment.respond_to?(:name)
|
|
13
|
+
name = deployment.name
|
|
14
|
+
elsif deployment.kind_of?(String)
|
|
15
|
+
name = deployment
|
|
16
|
+
else
|
|
17
|
+
raise ArgumentError, "invalid deployment: #{deployment}"
|
|
18
|
+
end
|
|
19
|
+
timeout = opts[:timeout] || 10
|
|
20
|
+
Config.logger.info("Acquiring deployment lock on #{name}")
|
|
21
|
+
Lock.new("lock:deployment:#{name}", :timeout => timeout).lock { yield }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Surround with stemcell lock.
|
|
25
|
+
#
|
|
26
|
+
# @param [String] name stemcell name.
|
|
27
|
+
# @param [String] version stemcell version.
|
|
28
|
+
# @option opts [Number] timeout how long to wait before giving up
|
|
29
|
+
# @return [void]
|
|
30
|
+
# @yield [void] block to surround
|
|
31
|
+
def with_stemcell_lock(name, version, opts = {})
|
|
32
|
+
timeout = opts[:timeout] || 10
|
|
33
|
+
Config.logger.info("Acquiring deployment lock on #{name}:#{version}")
|
|
34
|
+
Lock.new("lock:stemcells:#{name}:#{version}", :timeout => timeout).
|
|
35
|
+
lock { yield }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Surround with release lock.
|
|
39
|
+
#
|
|
40
|
+
# @param [String] release name.
|
|
41
|
+
# @option opts [Number] timeout how long to wait before giving up
|
|
42
|
+
# @return [void]
|
|
43
|
+
# @yield [void] block to surround
|
|
44
|
+
def with_release_lock(release, opts = {})
|
|
45
|
+
timeout = opts[:timeout] || 10
|
|
46
|
+
Config.logger.info("Acquiring deployment lock on #{release}")
|
|
47
|
+
Lock.new("lock:release:#{release}", :timeout => timeout).lock { yield }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Surround with deployment releases lock.
|
|
51
|
+
#
|
|
52
|
+
# @param [DeploymentPlan] deployment plan.
|
|
53
|
+
# @option opts [Number] timeout how long to wait before giving up
|
|
54
|
+
# @return [void]
|
|
55
|
+
# @yield [void] block to surround
|
|
56
|
+
def with_release_locks(deployment_plan, opts = {})
|
|
57
|
+
timeout = opts[:timeout] || 10
|
|
58
|
+
release_names = deployment_plan.releases.map do |release|
|
|
59
|
+
release.name
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Sorting to enforce lock order to avoid deadlocks
|
|
63
|
+
locks = release_names.sort.map do |release_name|
|
|
64
|
+
Config.logger.info("Acquiring release lock: #{release_name}")
|
|
65
|
+
Lock.new("lock:release:#{release_name}", :timeout => timeout)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
begin
|
|
69
|
+
locks.each { |lock| lock.lock }
|
|
70
|
+
yield
|
|
71
|
+
ensure
|
|
72
|
+
locks.reverse_each { |lock| lock.release }
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Surround with compile lock.
|
|
77
|
+
#
|
|
78
|
+
# @param [String|Number] package_id package id.
|
|
79
|
+
# @param [String|Number] stemcell_id stemcell id.
|
|
80
|
+
# @option opts [Number] timeout how long to wait before giving up
|
|
81
|
+
# @return [void]
|
|
82
|
+
# @yield [void] block to surround
|
|
83
|
+
def with_compile_lock(package_id, stemcell_id, opts = {})
|
|
84
|
+
timeout = opts[:timeout] || 15 * 60 # 15 minutes
|
|
85
|
+
|
|
86
|
+
Config.logger.info("Acquiring compile lock on " +
|
|
87
|
+
"#{package_id} #{stemcell_id}")
|
|
88
|
+
Lock.new("lock:compile:#{package_id}:#{stemcell_id}",
|
|
89
|
+
:timeout => timeout).lock { yield }
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
require 'bosh/director/models/compiled_package'
|
|
5
|
+
require 'bosh/director/models/deployment'
|
|
6
|
+
require 'bosh/director/models/deployment_problem'
|
|
7
|
+
require 'bosh/director/models/deployment_property'
|
|
8
|
+
require 'bosh/director/models/instance'
|
|
9
|
+
require 'bosh/director/models/log_bundle'
|
|
10
|
+
require 'bosh/director/models/package'
|
|
11
|
+
require 'bosh/director/models/release'
|
|
12
|
+
require 'bosh/director/models/release_version'
|
|
13
|
+
require 'bosh/director/models/stemcell'
|
|
14
|
+
require 'bosh/director/models/snapshot'
|
|
15
|
+
require 'bosh/director/models/task'
|
|
16
|
+
require 'bosh/director/models/template'
|
|
17
|
+
require 'bosh/director/models/user'
|
|
18
|
+
require 'bosh/director/models/vm'
|
|
19
|
+
require 'bosh/director/models/persistent_disk'
|
|
20
|
+
require 'bosh/director/models/director_attribute'
|
|
21
|
+
|
|
22
|
+
module Bosh::Director
|
|
23
|
+
module Models
|
|
24
|
+
VALID_ID = /^[-a-z0-9_.]+$/i
|
|
25
|
+
|
|
26
|
+
autoload :Dns, 'bosh/director/models/dns'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|