LUInstanceRename: Fail if renamed hostname mismatch
authorRené Nussbaumer <rn@google.com>
Thu, 3 Mar 2011 09:18:08 +0000 (10:18 +0100)
committerRené Nussbaumer <rn@google.com>
Thu, 3 Mar 2011 15:45:59 +0000 (16:45 +0100)
There's a problem if you run gnt-instance rename with a non FQDN and the
renamed LU tries to resolve the hostname to make it FQDN. It could be
that this resolved hostname was just a CNAME to another name which leads
to wrongly renamed instances name.

Given a name of "foobar" is a CNAME to "moohost" now if you gonna rewrite an
instance named "foobar1" to "foobar" it will pickup the host "moohost".
This is not obvious behaviour. If we detect this case we abort with a
prereq error. The user then however can continue with a FQDN and
--no-name-check if he intends to force the operation.

Signed-off-by: René Nussbaumer <rn@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>

lib/cmdlib.py
qa/qa_instance.py
qa/qa_utils.py

index 34a7f59..60cf6ee 100644 (file)
@@ -5528,6 +5528,11 @@ class LUInstanceRename(LogicalUnit):
       hostname = netutils.GetHostname(name=new_name)
       self.LogInfo("Resolved given name '%s' to '%s'", new_name,
                    hostname.name)
+      if not utils.MatchNameComponent(self.op.new_name, [hostname.name]):
+        raise errors.OpPrereqError(("Resolved hostname '%s' does not look the"
+                                    " same as given hostname '%s'") %
+                                    (hostname.name, self.op.new_name),
+                                    errors.ECODE_INVAL)
       new_name = self.op.new_name = hostname.name
       if (self.op.ip_check and
           netutils.TcpPing(hostname.ip, constants.DEFAULT_NODED_PORT)):
index 4f039e5..2728529 100644 (file)
@@ -148,6 +148,17 @@ def TestInstanceRename(rename_source, rename_target):
   _CheckSsconfInstanceList(rename_source)
   AssertCommand(["gnt-instance", "rename", rename_source, rename_target])
   _CheckSsconfInstanceList(rename_target)
+  AssertCommand(["gnt-instance", "rename", rename_target, rename_source])
+  _CheckSsconfInstanceList(rename_source)
+  qa_utils.AddToEtcHosts(["meeeeh-not-exists", rename_target])
+  try:
+    AssertCommand(["gnt-instance", "rename", rename_source, rename_target],
+                  fail=True)
+    _CheckSsconfInstanceList(rename_source)
+  finally:
+    qa_utils.RemoveFromEtcHosts(["meeeeh-not-exists", rename_target])
+  AssertCommand(["gnt-instance", "rename", rename_source, rename_target])
+  _CheckSsconfInstanceList(rename_target)
 
 
 def TestInstanceFailover(instance):
index be37818..ce33e62 100644 (file)
@@ -470,3 +470,44 @@ def _FormatWithColor(text, seq):
 FormatWarning = lambda text: _FormatWithColor(text, _WARNING_SEQ)
 FormatError = lambda text: _FormatWithColor(text, _ERROR_SEQ)
 FormatInfo = lambda text: _FormatWithColor(text, _INFO_SEQ)
+
+
+def AddToEtcHosts(hostnames):
+  """Adds hostnames to /etc/hosts.
+
+  @param hostnames: List of hostnames first used A records, all other CNAMEs
+
+  """
+  master = qa_config.GetMasterNode()
+  tmp_hosts = UploadData(master["primary"], "", mode=0644)
+
+  quoted_tmp_hosts = utils.ShellQuote(tmp_hosts)
+  data = []
+  for localhost in ("::1", "127.0.0.1"):
+    data.append("%s %s" % (localhost, " ".join(hostnames)))
+
+  try:
+    AssertCommand(("cat /etc/hosts > %s && echo -e '%s' >> %s && mv %s"
+                   " /etc/hosts") % (quoted_tmp_hosts, "\\n".join(data),
+                                     quoted_tmp_hosts, quoted_tmp_hosts))
+  except qa_error.Error:
+    AssertCommand(["rm", tmp_hosts])
+
+
+def RemoveFromEtcHosts(hostnames):
+  """Remove hostnames from /etc/hosts.
+
+  @param hostnames: List of hostnames first used A records, all other CNAMEs
+
+  """
+  master = qa_config.GetMasterNode()
+  tmp_hosts = UploadData(master["primary"], "", mode=0644)
+  quoted_tmp_hosts = utils.ShellQuote(tmp_hosts)
+
+  sed_data = " ".join(hostnames)
+  try:
+    AssertCommand(("sed -e '/^\(::1\|127\.0\.0\.1\)\s\+%s/d' /etc/hosts > %s"
+                   " && mv %s /etc/hosts") % (sed_data, quoted_tmp_hosts,
+                                              quoted_tmp_hosts))
+  except qa_error.Error:
+    AssertCommand(["rm", tmp_hosts])