From b66218dc10a57f850b59b47670189df7005c6351 Mon Sep 17 00:00:00 2001 From: Samuel Beaulieu Date: Fri, 31 Dec 2021 09:35:29 -0600 Subject: [PATCH] replace dns zone entry if it already exists on the rare occasion where adding a dns record and we get teh error it already exists assume that it is stale and replace it with the new IP --- lib/vmpooler/providers/gce.rb | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/vmpooler/providers/gce.rb b/lib/vmpooler/providers/gce.rb index 3381471..3da189f 100644 --- a/lib/vmpooler/providers/gce.rb +++ b/lib/vmpooler/providers/gce.rb @@ -134,7 +134,7 @@ module Vmpooler # [String] hostname : Specifies the hostname of the instance. The specified hostname must be RFC1035 compliant. If hostname is not specified, # the default hostname is [ INSTANCE_NAME].c.[PROJECT_ID].internal when using the global DNS, and # [ INSTANCE_NAME].[ZONE].c.[PROJECT_ID].internal when using zonal DNS - # [String] template : This is the name of template exposed by the API. It must _match_ the poolname ??? TODO + # [String] template : This is the name of template # [String] poolname : Name of the pool the VM as per labels # [Time] boottime : Time when the VM was created/booted # [String] status : One of the following values: PROVISIONING, STAGING, RUNNING, STOPPING, SUSPENDING, SUSPENDED, REPAIRING, and TERMINATED @@ -198,9 +198,6 @@ module Vmpooler network_interfaces: [network_interfaces], labels: { 'vm' => new_vmname, 'pool' => pool_name, project => nil } ) - # TODO: Maybe this will be needed to set the hostname (usually internal DNS name but in our case for some reason its nil) - # given_hostname = "#{new_vmname}.#{dns_zone}" - # client.hostname = given_hostname if given_hostname debug_logger('trigger insert_instance') result = connection.insert_instance(project, zone(pool_name), client) @@ -559,14 +556,17 @@ module Vmpooler def dns_setup(created_instance) zone = dns.zone dns_zone_resource_name if dns_zone_resource_name - return unless zone && created_instance + return unless zone && created_instance && created_instance['name'] && created_instance['ip'] name = created_instance['name'] - change = zone.add name, 'A', 60, [created_instance['ip']] - debug_logger("#{change.id} - #{change.started_at} - #{change.status}") if change - # TODO: should we catch Google::Cloud::AlreadyExistsError that is thrown when it already exist? - # and then delete and recreate? - # eg the error is Google::Cloud::AlreadyExistsError: alreadyExists: The resource 'entity.change.additions[0]' named 'instance-8.test.vmpooler.puppet.net. (A)' already exists + begin + change = zone.add name, 'A', 60, [created_instance['ip']] + debug_logger("#{change.id} - #{change.started_at} - #{change.status}") if change + rescue AlreadyExistsError => _e + # DNS setup is done only for new instances, so in the rare case where a DNS record already exists (it is stale) and we replace it. + # the error is Google::Cloud::AlreadyExistsError: alreadyExists: The resource 'entity.change.additions[0]' named 'instance-8.test.vmpooler.net. (A)' already exists + zone.replace(name, 'A', 60, [created_instance['ip']]) + end end def dns_teardown(created_instance) @@ -640,7 +640,7 @@ module Vmpooler end # Return a hash of VM data - # Provides vmname, hostname, template, poolname, boottime, status, zone, machine_type information + # Provides vmname, hostname, template, poolname, boottime, status, zone, machine_type, labels, label_fingerprint, ip information def generate_vm_hash(vm_object, pool_name) pool_configuration = pool_config(pool_name) return nil if pool_configuration.nil? @@ -648,7 +648,7 @@ module Vmpooler { 'name' => vm_object.name, 'hostname' => vm_object.hostname, - 'template' => pool_configuration&.key?('template') ? pool_configuration['template'] : nil, # TODO: get it from the API, not from config, but this is what vSphere does too! + 'template' => pool_configuration&.key?('template') ? pool_configuration['template'] : nil, # was expecting to get it from API, not from config, but this is what vSphere does too! 'poolname' => vm_object.labels&.key?('pool') ? vm_object.labels['pool'] : nil, 'boottime' => vm_object.creation_timestamp, 'status' => vm_object.status, # One of the following values: PROVISIONING, STAGING, RUNNING, STOPPING, SUSPENDING, SUSPENDED, REPAIRING, and TERMINATED @@ -657,7 +657,6 @@ module Vmpooler 'labels' => vm_object.labels, 'label_fingerprint' => vm_object.label_fingerprint, 'ip' => vm_object.network_interfaces ? vm_object.network_interfaces.first.network_ip : nil - # 'powerstate' => powerstate } end