Commit 17b97ab3 authored by Michael Hanselmann's avatar Michael Hanselmann

utils: Move code manipulating /etc/hosts to separate file

Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parent 3ae8dd03
......@@ -219,6 +219,7 @@ utils_PYTHON = \
lib/utils/io.py \
lib/utils/log.py \
lib/utils/mlock.py \
lib/utils/nodesetup.py \
lib/utils/retry.py \
lib/utils/text.py \
lib/utils/wrapper.py \
......@@ -493,6 +494,7 @@ python_tests = \
test/ganeti.utils.hash_unittest.py \
test/ganeti.utils.io_unittest.py \
test/ganeti.utils.mlock_unittest.py \
test/ganeti.utils.nodesetup_unittest.py \
test/ganeti.utils.retry_unittest.py \
test/ganeti.utils.text_unittest.py \
test/ganeti.utils.wrapper_unittest.py \
......
......@@ -62,6 +62,7 @@ from ganeti.utils.wrapper import * # pylint: disable-msg=W0401
from ganeti.utils.filelock import * # pylint: disable-msg=W0401
from ganeti.utils.io import * # pylint: disable-msg=W0401
from ganeti.utils.x509 import * # pylint: disable-msg=W0401
from ganeti.utils.nodesetup import * # pylint: disable-msg=W0401
#: when set to True, L{RunCmd} is disabled
......@@ -1076,106 +1077,6 @@ def ParseCpuMask(cpu_mask):
return cpu_list
def SetEtcHostsEntry(file_name, ip, hostname, aliases):
"""Sets the name of an IP address and hostname in /etc/hosts.
@type file_name: str
@param file_name: path to the file to modify (usually C{/etc/hosts})
@type ip: str
@param ip: the IP address
@type hostname: str
@param hostname: the hostname to be added
@type aliases: list
@param aliases: the list of aliases to add for the hostname
"""
# Ensure aliases are unique
aliases = UniqueSequence([hostname] + aliases)[1:]
def _WriteEtcHosts(fd):
# Duplicating file descriptor because os.fdopen's result will automatically
# close the descriptor, but we would still like to have its functionality.
out = os.fdopen(os.dup(fd), "w")
try:
for line in ReadFile(file_name).splitlines(True):
fields = line.split()
if fields and not fields[0].startswith("#") and ip == fields[0]:
continue
out.write(line)
out.write("%s\t%s" % (ip, hostname))
if aliases:
out.write(" %s" % " ".join(aliases))
out.write("\n")
out.flush()
finally:
out.close()
WriteFile(file_name, fn=_WriteEtcHosts, mode=0644)
def AddHostToEtcHosts(hostname, ip):
"""Wrapper around SetEtcHostsEntry.
@type hostname: str
@param hostname: a hostname that will be resolved and added to
L{constants.ETC_HOSTS}
@type ip: str
@param ip: The ip address of the host
"""
SetEtcHostsEntry(constants.ETC_HOSTS, ip, hostname, [hostname.split(".")[0]])
def RemoveEtcHostsEntry(file_name, hostname):
"""Removes a hostname from /etc/hosts.
IP addresses without names are removed from the file.
@type file_name: str
@param file_name: path to the file to modify (usually C{/etc/hosts})
@type hostname: str
@param hostname: the hostname to be removed
"""
def _WriteEtcHosts(fd):
# Duplicating file descriptor because os.fdopen's result will automatically
# close the descriptor, but we would still like to have its functionality.
out = os.fdopen(os.dup(fd), "w")
try:
for line in ReadFile(file_name).splitlines(True):
fields = line.split()
if len(fields) > 1 and not fields[0].startswith("#"):
names = fields[1:]
if hostname in names:
while hostname in names:
names.remove(hostname)
if names:
out.write("%s %s\n" % (fields[0], " ".join(names)))
continue
out.write(line)
out.flush()
finally:
out.close()
WriteFile(file_name, fn=_WriteEtcHosts, mode=0644)
def RemoveHostFromEtcHosts(hostname):
"""Wrapper around RemoveEtcHostsEntry.
@type hostname: str
@param hostname: hostname that will be resolved and its
full and shot name will be removed from
L{constants.ETC_HOSTS}
"""
RemoveEtcHostsEntry(constants.ETC_HOSTS, hostname)
RemoveEtcHostsEntry(constants.ETC_HOSTS, hostname.split(".")[0])
def GetHomeDir(user, default=None):
"""Try to get the homedir of the given user.
......
#
#
# Copyright (C) 2006, 2007, 2010, 2011 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
"""Utility functions for manipulating /etc/hosts.
"""
import os
from ganeti import constants
from ganeti.utils import algo
from ganeti.utils import io
def SetEtcHostsEntry(file_name, ip, hostname, aliases):
"""Sets the name of an IP address and hostname in /etc/hosts.
@type file_name: str
@param file_name: path to the file to modify (usually C{/etc/hosts})
@type ip: str
@param ip: the IP address
@type hostname: str
@param hostname: the hostname to be added
@type aliases: list
@param aliases: the list of aliases to add for the hostname
"""
# Ensure aliases are unique
aliases = algo.UniqueSequence([hostname] + aliases)[1:]
def _WriteEtcHosts(fd):
# Duplicating file descriptor because os.fdopen's result will automatically
# close the descriptor, but we would still like to have its functionality.
out = os.fdopen(os.dup(fd), "w")
try:
for line in io.ReadFile(file_name).splitlines(True):
fields = line.split()
if fields and not fields[0].startswith("#") and ip == fields[0]:
continue
out.write(line)
out.write("%s\t%s" % (ip, hostname))
if aliases:
out.write(" %s" % " ".join(aliases))
out.write("\n")
out.flush()
finally:
out.close()
io.WriteFile(file_name, fn=_WriteEtcHosts, mode=0644)
def AddHostToEtcHosts(hostname, ip):
"""Wrapper around SetEtcHostsEntry.
@type hostname: str
@param hostname: a hostname that will be resolved and added to
L{constants.ETC_HOSTS}
@type ip: str
@param ip: The ip address of the host
"""
SetEtcHostsEntry(constants.ETC_HOSTS, ip, hostname, [hostname.split(".")[0]])
def RemoveEtcHostsEntry(file_name, hostname):
"""Removes a hostname from /etc/hosts.
IP addresses without names are removed from the file.
@type file_name: str
@param file_name: path to the file to modify (usually C{/etc/hosts})
@type hostname: str
@param hostname: the hostname to be removed
"""
def _WriteEtcHosts(fd):
# Duplicating file descriptor because os.fdopen's result will automatically
# close the descriptor, but we would still like to have its functionality.
out = os.fdopen(os.dup(fd), "w")
try:
for line in io.ReadFile(file_name).splitlines(True):
fields = line.split()
if len(fields) > 1 and not fields[0].startswith("#"):
names = fields[1:]
if hostname in names:
while hostname in names:
names.remove(hostname)
if names:
out.write("%s %s\n" % (fields[0], " ".join(names)))
continue
out.write(line)
out.flush()
finally:
out.close()
io.WriteFile(file_name, fn=_WriteEtcHosts, mode=0644)
def RemoveHostFromEtcHosts(hostname):
"""Wrapper around RemoveEtcHostsEntry.
@type hostname: str
@param hostname: hostname that will be resolved and its
full and shot name will be removed from
L{constants.ETC_HOSTS}
"""
RemoveEtcHostsEntry(constants.ETC_HOSTS, hostname)
RemoveEtcHostsEntry(constants.ETC_HOSTS, hostname.split(".")[0])
#!/usr/bin/python
#
# Copyright (C) 2006, 2007, 2010 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
"""Script for testing ganeti.utils.nodesetup"""
import os
import tempfile
import unittest
from ganeti import constants
from ganeti import utils
import testutils
class TestEtcHosts(testutils.GanetiTestCase):
"""Test functions modifying /etc/hosts"""
def setUp(self):
testutils.GanetiTestCase.setUp(self)
self.tmpname = self._CreateTempFile()
handle = open(self.tmpname, "w")
try:
handle.write("# This is a test file for /etc/hosts\n")
handle.write("127.0.0.1\tlocalhost\n")
handle.write("192.0.2.1 router gw\n")
finally:
handle.close()
def testSettingNewIp(self):
utils.SetEtcHostsEntry(self.tmpname, "198.51.100.4", "myhost.example.com",
["myhost"])
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1 router gw\n"
"198.51.100.4\tmyhost.example.com myhost\n")
self.assertFileMode(self.tmpname, 0644)
def testSettingExistingIp(self):
utils.SetEtcHostsEntry(self.tmpname, "192.0.2.1", "myhost.example.com",
["myhost"])
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1\tmyhost.example.com myhost\n")
self.assertFileMode(self.tmpname, 0644)
def testSettingDuplicateName(self):
utils.SetEtcHostsEntry(self.tmpname, "198.51.100.4", "myhost", ["myhost"])
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1 router gw\n"
"198.51.100.4\tmyhost\n")
self.assertFileMode(self.tmpname, 0644)
def testRemovingExistingHost(self):
utils.RemoveEtcHostsEntry(self.tmpname, "router")
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1 gw\n")
self.assertFileMode(self.tmpname, 0644)
def testRemovingSingleExistingHost(self):
utils.RemoveEtcHostsEntry(self.tmpname, "localhost")
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"192.0.2.1 router gw\n")
self.assertFileMode(self.tmpname, 0644)
def testRemovingNonExistingHost(self):
utils.RemoveEtcHostsEntry(self.tmpname, "myhost")
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1 router gw\n")
self.assertFileMode(self.tmpname, 0644)
def testRemovingAlias(self):
utils.RemoveEtcHostsEntry(self.tmpname, "gw")
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1 router\n")
self.assertFileMode(self.tmpname, 0644)
if __name__ == "__main__":
testutils.GanetiTestProgram()
......@@ -45,8 +45,7 @@ from ganeti import utils
from ganeti import errors
from ganeti.utils import RunCmd, \
FirstFree, \
RunParts, \
SetEtcHostsEntry, RemoveEtcHostsEntry
RunParts
class TestIsProcessAlive(unittest.TestCase):
......@@ -575,87 +574,6 @@ class TestParseCpuMask(unittest.TestCase):
self.assertRaises(errors.ParseError, utils.ParseCpuMask, data)
class TestEtcHosts(testutils.GanetiTestCase):
"""Test functions modifying /etc/hosts"""
def setUp(self):
testutils.GanetiTestCase.setUp(self)
self.tmpname = self._CreateTempFile()
handle = open(self.tmpname, 'w')
try:
handle.write('# This is a test file for /etc/hosts\n')
handle.write('127.0.0.1\tlocalhost\n')
handle.write('192.0.2.1 router gw\n')
finally:
handle.close()
def testSettingNewIp(self):
SetEtcHostsEntry(self.tmpname, '198.51.100.4', 'myhost.example.com',
['myhost'])
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1 router gw\n"
"198.51.100.4\tmyhost.example.com myhost\n")
self.assertFileMode(self.tmpname, 0644)
def testSettingExistingIp(self):
SetEtcHostsEntry(self.tmpname, '192.0.2.1', 'myhost.example.com',
['myhost'])
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1\tmyhost.example.com myhost\n")
self.assertFileMode(self.tmpname, 0644)
def testSettingDuplicateName(self):
SetEtcHostsEntry(self.tmpname, '198.51.100.4', 'myhost', ['myhost'])
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1 router gw\n"
"198.51.100.4\tmyhost\n")
self.assertFileMode(self.tmpname, 0644)
def testRemovingExistingHost(self):
RemoveEtcHostsEntry(self.tmpname, 'router')
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1 gw\n")
self.assertFileMode(self.tmpname, 0644)
def testRemovingSingleExistingHost(self):
RemoveEtcHostsEntry(self.tmpname, 'localhost')
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"192.0.2.1 router gw\n")
self.assertFileMode(self.tmpname, 0644)
def testRemovingNonExistingHost(self):
RemoveEtcHostsEntry(self.tmpname, 'myhost')
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1 router gw\n")
self.assertFileMode(self.tmpname, 0644)
def testRemovingAlias(self):
RemoveEtcHostsEntry(self.tmpname, 'gw')
self.assertFileContent(self.tmpname,
"# This is a test file for /etc/hosts\n"
"127.0.0.1\tlocalhost\n"
"192.0.2.1 router\n")
self.assertFileMode(self.tmpname, 0644)
class TestGetMounts(unittest.TestCase):
"""Test case for GetMounts()."""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment