Skip to content

Commit

Permalink
Merge pull request #40 from rackerlabs/list_mac_addrs
Browse files Browse the repository at this point in the history
RFR: Allow listing of Network Interfaces
  • Loading branch information
russellhaering committed Jan 28, 2014
2 parents f0a2a78 + 3347102 commit 727feb2
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 12 deletions.
37 changes: 34 additions & 3 deletions teeth_agent/hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"""

import abc
import os

import plumbum
import stevedore
Expand Down Expand Up @@ -43,13 +44,22 @@ def __init__(self, name, size, start_sector):
self.start_sector = start_sector


class NetworkInterface(object):
def __init__(self, name, mac_addr):
self.name = name
self.mac_address = mac_addr
# TODO(russellhaering): Pull these from LLDP
self.switch_port_descr = None
self.switch_chassis_descr = None


class HardwareManager(object):
@abc.abstractmethod
def evaluate_hardware_support(cls):
pass

@abc.abstractmethod
def get_primary_mac_address(self):
def list_network_interfaces(self):
pass

@abc.abstractmethod
Expand All @@ -58,11 +68,32 @@ def get_os_install_device(self):


class GenericHardwareManager(HardwareManager):
def __init__(self):
self.sys_path = '/sys'

if os.path.isdir('/mnt/sys'):
self.sys_path = '/mnt/sys'

def evaluate_hardware_support(cls):
return HardwareSupport.GENERIC

def get_primary_mac_address(self):
return open('/sys/class/net/eth0/address', 'r').read().strip('\n')
def _get_interface_info(self, interface_name):
addr_path = '{}/class/net/{}/address'.format(self.sys_path,
interface_name)
addr_file = open(addr_path, 'r')
mac_addr = addr_file.read().strip()
return NetworkInterface(interface_name, mac_addr)

def _is_device(self, interface_name):
device_path = '{}/class/net/{}/device'.format(self.sys_path,
interface_name)
return os.path.exists(device_path)

def list_network_interfaces(self):
iface_names = os.listdir('{}/class/net'.format(self.sys_path))
return [self._get_interface_info(name)
for name in iface_names
if self._is_device(name)]

def _cmd(self, command_name):
"""Mocking plumbum is frustratingly difficult. Instead, mock this."""
Expand Down
22 changes: 13 additions & 9 deletions teeth_agent/tests/hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,20 @@ class TestGenericHardwareManager(unittest.TestCase):
def setUp(self):
self.hardware = hardware.GenericHardwareManager()

@mock.patch('os.listdir')
@mock.patch('os.path.exists')
@mock.patch('__builtin__.open')
def test_get_primary_mac_address(self, mocked_open):
f = mocked_open.return_value
f.read.return_value = '00:0c:29:8c:11:b1\n'

mac_addr = self.hardware.get_primary_mac_address()
self.assertEqual(mac_addr, '00:0c:29:8c:11:b1')

mocked_open.assert_called_once_with('/sys/class/net/eth0/address', 'r')
f.read.assert_called_once_with()
def test_list_network_interfaces(self,
mocked_open,
mocked_exists,
mocked_listdir):
mocked_listdir.return_value = ['lo', 'eth0']
mocked_exists.side_effect = [False, True]
mocked_open.return_value.read.return_value = '00:0c:29:8c:11:b1\n'
interfaces = self.hardware.list_network_interfaces()
self.assertEqual(len(interfaces), 1)
self.assertEqual(interfaces[0].name, 'eth0')
self.assertEqual(interfaces[0].mac_address, '00:0c:29:8c:11:b1')

def test_get_os_install_device(self):
self.hardware._cmd = mock.Mock()
Expand Down

0 comments on commit 727feb2

Please sign in to comment.