From 451a6d3590ed7c049ad6ce24f8f6c01685d7d3d3 Mon Sep 17 00:00:00 2001 From: radhika Date: Tue, 16 Jun 2015 11:32:55 -0400 Subject: [PATCH] 6156: support config format for setting a node's hostname --- services/api/app/models/node.rb | 39 +++++++++---- services/api/config/application.default.yml | 18 ++++++ services/api/test/fixtures/nodes.yml | 24 ++++++++ services/api/test/unit/node_test.rb | 62 +++++++++++++++++++++ 4 files changed, 133 insertions(+), 10 deletions(-) diff --git a/services/api/app/models/node.rb b/services/api/app/models/node.rb index 1cd6387cff..0ec9136941 100644 --- a/services/api/app/models/node.rb +++ b/services/api/app/models/node.rb @@ -94,7 +94,7 @@ class Node < ArvadosModel end end - # Assign hostname + # Assign slot_number if self.slot_number.nil? try_slot = 0 begin @@ -107,6 +107,10 @@ class Node < ArvadosModel end raise "No available node slots" if try_slot == Rails.configuration.max_compute_nodes end while true + end + + # Assign hostname + if self.hostname.nil? and Rails.configuration.assign_node_hostname self.hostname = self.class.hostname_for_slot(self.slot_number) end @@ -205,21 +209,36 @@ class Node < ArvadosModel end def self.hostname_for_slot(slot_number) - "compute#{slot_number}" + config = Rails.configuration.assign_node_hostname + + return nil if !config + + begin + if config.include?('%') + sprintf(config, {:slot_number => slot_number}) + else + eval('"' + config + '"') + end + rescue => e + logger.error "Eror generating hostname: #{e.message}" + return nil + end end # At startup, make sure all DNS entries exist. Otherwise, slurmctld # will refuse to start. if Rails.configuration.dns_server_conf_dir and Rails.configuration.dns_server_conf_template (0..Rails.configuration.max_compute_nodes-1).each do |slot_number| - hostname = hostname_for_slot(slot_number) - hostfile = File.join Rails.configuration.dns_server_conf_dir, "#{hostname}.conf" - if !File.exists? hostfile - n = Node.where(:slot_number => slot_number).first - if n.nil? or n.ip_address.nil? - dns_server_update(hostname, '127.40.4.0') - else - dns_server_update(hostname, n.ip_address) + if Rails.configuration.assign_node_hostname + hostname = hostname_for_slot(slot_number) + hostfile = File.join Rails.configuration.dns_server_conf_dir, "#{hostname}.conf" + if !File.exists? hostfile + n = Node.where(:slot_number => slot_number).first + if n.nil? or n.ip_address.nil? + dns_server_update(hostname, '127.40.4.0') + else + dns_server_update(hostname, n.ip_address) + end end end end diff --git a/services/api/config/application.default.yml b/services/api/config/application.default.yml index 5488003958..8f3207a719 100644 --- a/services/api/config/application.default.yml +++ b/services/api/config/application.default.yml @@ -329,3 +329,21 @@ common: # Docker image to be used when none found in runtime_constraints of a job default_docker_image_for_jobs: false + + # Hostname to assign to a compute node when it sends a "ping" and the + # hostname in its Node record is nil. + # During bootstrapping, the "ping" script is expected to notice the + # hostname given in the ping response, and update its unix hostname + # accordingly. + # If false, leave the hostname alone (this is appropriate if your compute + # nodes' hostnames are already assigned by some other mechanism). + # + # One way or another, the hostnames of your node records should agree + # with your DNS records and your /etc/slurm-llnl/slurm.conf files. + # + # Example for compute0000, compute0001, ....: + # assign_node_hostname: compute#{slot_number.to_s.rjust(4, "0")} + # or + # assign_node_hostname: compute%04d + # (See http://ruby-doc.org/core-2.2.2/Kernel.html#method-i-format for more.) + assign_node_hostname: compute#{slot_number} diff --git a/services/api/test/fixtures/nodes.yml b/services/api/test/fixtures/nodes.yml index 15115012fa..6ca22e1526 100644 --- a/services/api/test/fixtures/nodes.yml +++ b/services/api/test/fixtures/nodes.yml @@ -54,3 +54,27 @@ was_idle_now_down: ping_secret: "1bd1yi0x4lb5q4gzqqtrnq30oyj08r8dtdimmanbqw49z1anz2" slurm_state: "idle" total_cpu_cores: 16 + +new_with_no_hostname: + uuid: zzzzz-7ekkf-newnohostname00 + owner_uuid: zzzzz-tpzed-000000000000000 + hostname: ~ + slot_number: ~ + ip_address: 172.17.2.173 + last_ping_at: ~ + first_ping_at: ~ + job_uuid: ~ + info: + ping_secret: "abcdyi0x4lb5q4gzqqtrnq30oyj08r8dtdimmanbqw49z1anz2" + +new_with_custom_hostname: + uuid: zzzzz-7ekkf-newwithhostname + owner_uuid: zzzzz-tpzed-000000000000000 + hostname: custom1 + slot_number: 23 + ip_address: 172.17.2.173 + last_ping_at: ~ + first_ping_at: ~ + job_uuid: ~ + info: + ping_secret: "abcdyi0x4lb5q4gzqqtrnq30oyj08r8dtdimmanbqw49z1anz2" diff --git a/services/api/test/unit/node_test.rb b/services/api/test/unit/node_test.rb index 98e260be9d..96d31a8c4c 100644 --- a/services/api/test/unit/node_test.rb +++ b/services/api/test/unit/node_test.rb @@ -75,4 +75,66 @@ class NodeTest < ActiveSupport::TestCase Rails.configuration.dns_server_reload_command = 'ignored!' assert Node.dns_server_update 'compute65535', '127.0.0.127' end + + test "ping new node with no hostname and default config" do + node = ping_node(:new_with_no_hostname, {}) + slot_number = node.slot_number + refute_nil slot_number + assert_equal("compute#{slot_number}", node.hostname) + end + + test "ping new node with no hostname and no config" do + Rails.configuration.assign_node_hostname = false + node = ping_node(:new_with_no_hostname, {}) + refute_nil node.slot_number + assert_nil node.hostname + end + + [ + 'compute#{slot_number.to_s.rjust(4, "0")}', + 'compute%04d', + ].each do |config| + test "ping new node with zero padding config #{config}" do + Rails.configuration.assign_node_hostname = config + node = ping_node(:new_with_no_hostname, {}) + slot_number = node.slot_number + refute_nil slot_number + assert_equal("compute000#{slot_number}", node.hostname) + end + end + + test "ping node with hostname and config and expect hostname unchanged" do + node = ping_node(:new_with_custom_hostname, {}) + assert_equal(23, node.slot_number) + assert_equal("custom1", node.hostname) + end + + test "ping node with hostname and no config and expect hostname unchanged" do + Rails.configuration.assign_node_hostname = false + node = ping_node(:new_with_custom_hostname, {}) + assert_equal(23, node.slot_number) + assert_equal("custom1", node.hostname) + end + + # Ping two nodes: one with no hostname and the other with a hostname. + # Verify that the first one gets a hostname and second one is unchanged. + test "ping two nodes one with no hostname and one with hostname and check hostnames" do + # ping node with no hostname and expect it set with config format + node = ping_node(:new_with_no_hostname, {}) + slot_number = node.slot_number + refute_nil node.slot_number + assert_equal "compute#{slot_number}", node.hostname + + # ping node with a hostname and expect it to be unchanged + node2 = ping_node(:new_with_custom_hostname, {}) + refute_nil node2.slot_number + assert_equal "custom1", node2.hostname + end + + test "ping node with no hostname and malformed config and expect nil for hostname" do + Rails.configuration.assign_node_hostname = 'compute%04' # should end with "04d" + node = ping_node(:new_with_no_hostname, {}) + refute_nil node.slot_number + assert_equal(nil, node.hostname) + end end -- 2.30.2