Repository: ambari Updated Branches: refs/heads/trunk a6ab3881c -> c4bbeeb29
AMBARI-19415. Network interface check returns no value if there is no `ifconfig` command. (Masahiro Tanaka via yusaku) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c4bbeeb2 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c4bbeeb2 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c4bbeeb2 Branch: refs/heads/trunk Commit: c4bbeeb29d8f9e3b04d20e38570769f3cc3fdec6 Parents: a6ab388 Author: Yusaku Sako <yus...@hortonworks.com> Authored: Sat Jan 21 09:49:40 2017 -0800 Committer: Yusaku Sako <yus...@hortonworks.com> Committed: Sat Jan 21 09:49:40 2017 -0800 ---------------------------------------------------------------------- .../src/main/python/ambari_agent/Facter.py | 44 ++++++++++++++---- .../test/python/ambari_agent/TestHardware.py | 47 ++++++++++++++++++++ 2 files changed, 82 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/c4bbeeb2/ambari-agent/src/main/python/ambari_agent/Facter.py ---------------------------------------------------------------------- diff --git a/ambari-agent/src/main/python/ambari_agent/Facter.py b/ambari-agent/src/main/python/ambari_agent/Facter.py index 3643ff7..7e92c1b 100644 --- a/ambari-agent/src/main/python/ambari_agent/Facter.py +++ b/ambari-agent/src/main/python/ambari_agent/Facter.py @@ -375,15 +375,18 @@ class FacterLinux(Facter): # selinux command GET_SE_LINUX_ST_CMD = "/usr/sbin/sestatus" GET_IFCONFIG_SHORT_CMD = "ifconfig -s" + GET_IP_LINK_CMD = "ip link" GET_UPTIME_CMD = "cat /proc/uptime" GET_MEMINFO_CMD = "cat /proc/meminfo" def __init__(self, config): super(FacterLinux,self).__init__(config) self.DATA_IFCONFIG_SHORT_OUTPUT = FacterLinux.setDataIfConfigShortOutput() + self.DATA_IP_LINK_OUTPUT = FacterLinux.setDataIpLinkOutput() self.DATA_UPTIME_OUTPUT = FacterLinux.setDataUpTimeOutput() self.DATA_MEMINFO_OUTPUT = FacterLinux.setMemInfoOutput() + # Returns the output of `ifconfig -s` command @staticmethod def setDataIfConfigShortOutput(): @@ -394,6 +397,17 @@ class FacterLinux(Facter): log.warn("Can't execute {0}".format(FacterLinux.GET_IFCONFIG_SHORT_CMD)) return "" + # Returns the output of `ip link` command + @staticmethod + def setDataIpLinkOutput(): + + try: + result = os.popen(FacterLinux.GET_IP_LINK_CMD).read() + return result + except OSError: + log.warn("Can't execute {0}".format(FacterLinux.GET_IP_LINK_CMD)) + return "" + @staticmethod def setDataUpTimeOutput(): @@ -438,6 +452,14 @@ class FacterLinux(Facter): result = re.sub(r',$', "", result) return result + def return_ifnames_from_ip_link(self, ip_link_output): + list = [] + prog = re.compile("^\d") + for line in ip_link_output.splitlines(): + if prog.match(line): + list.append(line.split()[1].rstrip(":")) + return ",".join(list) + def data_return_first(self, patern, data): full_list = re.findall(patern, data) result = "" @@ -452,13 +474,12 @@ class FacterLinux(Facter): import struct primary_ip = self.getIpAddress().strip() - for line in self.DATA_IFCONFIG_SHORT_OUTPUT.splitlines()[1:]: - if line.strip(): - i = line.split()[0] - ip_address_by_ifname = self.get_ip_address_by_ifname(i.strip()) + for ifname in self.getInterfaces().split(","): + if ifname.strip(): + ip_address_by_ifname = self.get_ip_address_by_ifname(ifname) if ip_address_by_ifname is not None: if primary_ip == ip_address_by_ifname.strip(): - return socket.inet_ntoa(fcntl.ioctl(socket.socket(socket.AF_INET, socket.SOCK_DGRAM), 35099, struct.pack('256s', i))[20:24]) + return socket.inet_ntoa(fcntl.ioctl(socket.socket(socket.AF_INET, socket.SOCK_DGRAM), 35099, struct.pack('256s', ifname))[20:24]) return None @@ -483,11 +504,16 @@ class FacterLinux(Facter): # Return interfaces def getInterfaces(self): result = self.return_first_words_from_list(self.DATA_IFCONFIG_SHORT_OUTPUT.splitlines()[1:]) - if result == '': - log.warn("Can't get a network interfaces list from {0}".format(self.DATA_IFCONFIG_SHORT_OUTPUT)) - return 'OS NOT SUPPORTED' - else: + # If the host has `ifconfig` command, then return that result. + if result != '': return result + # If the host has `ip` command, then return that result. + result = self.return_ifnames_from_ip_link(self.DATA_IP_LINK_OUTPUT) + if result != '': + return result + # If the host has neither `ifocnfig` command nor `ip` command, then return "OS NOT SUPPORTED" + log.warn("Can't get a network interfaces list from {0}".format(self.DATA_IFCONFIG_SHORT_OUTPUT)) + return 'OS NOT SUPPORTED' # Return uptime seconds def getUptimeSeconds(self): http://git-wip-us.apache.org/repos/asf/ambari/blob/c4bbeeb2/ambari-agent/src/test/python/ambari_agent/TestHardware.py ---------------------------------------------------------------------- diff --git a/ambari-agent/src/test/python/ambari_agent/TestHardware.py b/ambari-agent/src/test/python/ambari_agent/TestHardware.py index ff3b40b..79205cf 100644 --- a/ambari-agent/src/test/python/ambari_agent/TestHardware.py +++ b/ambari-agent/src/test/python/ambari_agent/TestHardware.py @@ -43,6 +43,12 @@ eth0 1500 0 9986 0 0 0 5490 0 0 0 BMRU eth1 1500 0 0 0 0 0 6 0 0 0 BMRU eth2 1500 0 0 0 0 0 6 0 0 0 BMRU lo 16436 0 2 0 0 0 2 0 0 0 LRU''')) +@patch.object(FacterLinux, "setDataIpLinkOutput", new=MagicMock(return_value='''1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1 + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 +2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 + link/ether 08:00:27:d3:e8:0f brd ff:ff:ff:ff:ff:ff +3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 + link/ether 08:00:27:09:92:3a brd ff:ff:ff:ff:ff:ff''')) class TestHardware(TestCase): @patch.object(Hardware, "osdisks", new=MagicMock(return_value=[])) @@ -443,6 +449,47 @@ SwapFree: 1598676 kB self.assertEquals(expected_mounts_left, mounts_left) +@not_for_platform(PLATFORM_WINDOWS) +@patch.object(platform, "linux_distribution", new=MagicMock(return_value=('Suse', '11', 'Final'))) +@patch.object(socket, "getfqdn", new=MagicMock(return_value="ambari.apache.org")) +@patch.object(socket, "gethostbyname", new=MagicMock(return_value="192.168.1.1")) +@patch.object(FacterLinux, "setDataIfConfigShortOutput", new=MagicMock(return_value='')) +@patch.object(FacterLinux, "setDataIpLinkOutput", new=MagicMock(return_value='''1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1 + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 +2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 + link/ether 08:00:27:d3:e8:0f brd ff:ff:ff:ff:ff:ff +3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000 + link/ether 08:00:27:09:92:3a brd ff:ff:ff:ff:ff:ff''')) +class TestHardwareWithoutIfConfig(TestCase): + @patch("fcntl.ioctl") + @patch("socket.socket") + @patch("struct.pack") + @patch("socket.inet_ntoa") + @patch.object(FacterLinux, "get_ip_address_by_ifname") + @patch.object(Facter, "getIpAddress") + @patch.object(OSCheck, "get_os_type") + @patch.object(OSCheck, "get_os_version") + def test_facterDataIpLinkOutput(self, get_os_version_mock, + get_os_type_mock, getIpAddress_mock, get_ip_address_by_ifname_mock, + inet_ntoa_mock, struct_pack_mock, + socket_socket_mock, fcntl_ioctl_mock): + + getIpAddress_mock.return_value = "10.0.2.15" + get_ip_address_by_ifname_mock.return_value = "10.0.2.15" + inet_ntoa_mock.return_value = "255.255.255.0" + + get_os_type_mock.return_value = "suse" + get_os_version_mock.return_value = "11" + config = None + result = Facter(config).facterInfo() + + self.assertTrue(inet_ntoa_mock.called) + self.assertTrue(get_ip_address_by_ifname_mock.called) + self.assertTrue(getIpAddress_mock.called) + self.assertEquals(result['ipaddress'], '10.0.2.15') + self.assertEquals(result['netmask'], '255.255.255.0') + self.assertEquals(result['interfaces'], 'lo,enp0s3,enp0s8') + if __name__ == "__main__": unittest.main()