forked from aristanetworks/sonic
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The logic of the scripts is in a module called arista This brings more modularity and better platform support. A script named arista is added under /usr/bin that makes use of this lib It currently allows to read the prefdl, setup/clean the drivers, and reset devices Change-Id: I7c3c994b7fe9eadf6525ceddeb869e241c716eab
- Loading branch information
Showing
17 changed files
with
605 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,3 +13,9 @@ modules.order | |
DEBIAN | ||
.tmp_versions | ||
.finished.build | ||
|
||
# python | ||
*.pyc | ||
/build | ||
/*.egg-info | ||
/venv |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
|
||
import logging | ||
import os | ||
|
||
from ..core.component import Component | ||
from ..core.driver import KernelDriver | ||
from ..core.utils import simulation | ||
from ..core.types import PciAddr, I2cAddr | ||
|
||
class PciComponent(Component): | ||
def __init__(self, addr, **kwargs): | ||
assert isinstance(addr, PciAddr) | ||
super(PciComponent, self).__init__(addr=addr, **kwargs) | ||
|
||
class I2cComponent(Component): | ||
def __init__(self, addr, **kwargs): | ||
assert isinstance(addr, I2cAddr) | ||
super(I2cComponent, self).__init__(addr=addr, **kwargs) | ||
|
||
class I2cKernelComponent(I2cComponent): | ||
def __init__(self, addr, name): | ||
super(I2cKernelComponent, self).__init__(addr) | ||
self.addDriver(I2cKernelDriver, name) | ||
|
||
class PciKernelDriver(KernelDriver): | ||
def __init__(self, component, name, args=None): | ||
assert isinstance(component, PciComponent) | ||
super(PciKernelDriver, self).__init__(component, name, args) | ||
|
||
def getSysfsPath(self): | ||
return os.path.join('/sys/bus/pci/devices', str(self.component.addr)) | ||
|
||
class I2cKernelDriver(KernelDriver): | ||
def __init__(self, component, name): | ||
assert isinstance(component, I2cComponent) | ||
super(I2cKernelDriver, self).__init__(component, None) | ||
self.name = name | ||
|
||
def getSysfsPath(self): | ||
return os.path.join('/sys/bus/i2c/devices', str(self.component.addr)) | ||
|
||
def getSysfsBusPath(self): | ||
return '/sys/bus/i2c/devices/i2c-%d' % self.component.addr.bus | ||
|
||
def setup(self): | ||
addr = self.component.addr | ||
devicePath = self.getSysfsPath() | ||
path = os.path.join(self.getSysfsBusPath(), 'new_device') | ||
logging.debug('creating i2c device %s on bus %d at 0x%02x' % | ||
(self.name, addr.bus, addr.address)) | ||
if simulation: | ||
return | ||
if os.path.exists(devicePath): | ||
logging.debug('i2c device %s already exists' % devicePath) | ||
else: | ||
with open(path, 'w') as f: | ||
f.write('%s 0x%02x' % (self.name, self.component.addr.address)) | ||
|
||
def clean(self): | ||
# i2c kernel devices are automatically cleaned when the module is removed | ||
if simulation: | ||
return | ||
path = os.path.join(self.getSysfsBusPath(), 'delete_device') | ||
addr = self.component.addr | ||
if os.path.exists(self.getSysfsPath()): | ||
logging.debug('removing i2c device %s from bus %d' % (self.name, addr.bus)) | ||
with open(path, 'w') as f: | ||
f.write('0x%02x' % addr.address) | ||
|
||
def __str__(self): | ||
return '%s(%s)' % (self.__class__.__name__, self.name) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from __future__ import print_function | ||
|
||
from driver import Driver | ||
|
||
class Component(object): | ||
def __init__(self, **kwargs): | ||
self.components = [] | ||
self.drivers = [] | ||
for key, value in kwargs.items(): | ||
setattr(self, key, value) | ||
self.params = kwargs.keys() | ||
|
||
def __str__(self): | ||
kwargs = ['%s=%s' % (k, getattr(self, k)) for k in self.params] | ||
return '%s(%s)' % (self.__class__.__name__, ', '.join(kwargs)) | ||
|
||
def addComponents(self, components): | ||
assert all(isinstance(c, Component) for c in components) | ||
self.components += components | ||
return self | ||
|
||
def addComponent(self, component): | ||
assert isinstance(component, Component) | ||
self.components += [component] | ||
return self | ||
|
||
def addDriver(self, driverCls, *args, **kwargs): | ||
assert issubclass(driverCls, Driver) | ||
self.drivers += [driverCls(self, *args, **kwargs)] | ||
return self | ||
|
||
def setup(self): | ||
for driver in self.drivers: | ||
driver.setup() | ||
for driver in self.drivers: | ||
driver.finish() | ||
|
||
def finish(self): | ||
# underlying component are initialized recursively but require the parent to | ||
# be fully initialized | ||
for component in self.components: | ||
component.setup() | ||
for component in self.components: | ||
component.finish() | ||
|
||
def clean(self): | ||
for component in reversed(self.components): | ||
component.clean() | ||
for driver in reversed(self.drivers): | ||
driver.clean() | ||
|
||
def resetIn(self): | ||
for component in reversed(self.components): | ||
component.resetIn() | ||
for driver in reversed(self.drivers): | ||
driver.resetIn() | ||
|
||
def resetOut(self): | ||
for driver in self.drivers: | ||
driver.resetOut() | ||
for component in self.components: | ||
component.resetOut() | ||
|
||
def _dumpDrivers(self, depth, prefix): | ||
if len(self.drivers) == 1: | ||
self.drivers[0].dump(prefix=' => ') | ||
elif self.drivers: | ||
spacer = ' ' * (depth * 3) | ||
print('%s%sdrivers:' % (spacer, prefix)) | ||
for driver in self.drivers: | ||
driver.dump(depth + 1) | ||
|
||
def _dumpNode(self, depth, prefix): | ||
depth += 1 | ||
spacer = ' ' * (depth * 3) | ||
if self.drivers: | ||
self._dumpDrivers(depth, prefix) | ||
print('%s%scomponents:' % (spacer, prefix)) | ||
for component in self.components: | ||
component.dump(depth + 1) | ||
|
||
def dump(self, depth=0, prefix=' - '): | ||
spacer = ' ' * (depth * 3) | ||
end = '' if len(self.drivers) == 1 else '\n' | ||
print('%s%s%s' % (spacer, prefix,self), end=end) | ||
if self.components: | ||
self._dumpNode(depth, prefix) | ||
else: | ||
self._dumpDrivers(depth, prefix) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
from __future__ import print_function | ||
|
||
import logging | ||
import subprocess | ||
|
||
from utils import simulation | ||
|
||
def modprobe(name, args=None): | ||
logging.debug('loading module %s' % name) | ||
if args is None: | ||
args = [] | ||
args = ['modprobe', name.replace('-', '_')] + args | ||
if simulation: | ||
logging.debug('exec: %s' % ' '.join(args)) | ||
else: | ||
subprocess.check_call(args) | ||
|
||
def rmmod(name): | ||
logging.debug('unloading module %s' % name) | ||
args = ['modprobe', '-r', name.replace('-', '_')] | ||
if simulation: | ||
logging.debug('exec: %s' % ' '.join(args)) | ||
else: | ||
subprocess.check_call(args) | ||
|
||
def isModuleLoaded(name): | ||
with open('/proc/modules') as f: | ||
start = '%s ' % name.replace('-', '_') | ||
for line in f.readlines(): | ||
if line.startswith(start): | ||
return True | ||
return False | ||
|
||
class Driver(object): | ||
def __init__(self, component): | ||
self.component = component | ||
|
||
def setup(self): | ||
pass | ||
|
||
def finish(self): | ||
pass | ||
|
||
def clean(self): | ||
pass | ||
|
||
def resetIn(self): | ||
pass | ||
|
||
def resetOut(self): | ||
pass | ||
|
||
def dump(self, depth=0, prefix=' - '): | ||
spacer = ' ' * (depth * 3) | ||
print('%s%s%s' % (spacer, prefix, self)) | ||
|
||
class KernelDriver(Driver): | ||
# TODO: handle multiple kernel modules | ||
def __init__(self, component, module, args=None): | ||
super(KernelDriver, self).__init__(component) | ||
self.component = component | ||
self.module = module | ||
self.args = args if args is not None else [] | ||
|
||
def setup(self): | ||
modprobe(self.module, self.args) | ||
|
||
def clean(self): | ||
if self.loaded(): | ||
try: | ||
rmmod(self.module) | ||
except Exception as e: | ||
logging.error('Failed to unload %s: %s' % (self.module, e)) | ||
else: | ||
logging.debug('Module %s is not loaded' % self.module) | ||
|
||
def loaded(self): | ||
return isModuleLoaded(self.module) | ||
|
||
def getSysfsPath(self): | ||
raise NotImplementedError | ||
|
||
def __str__(self): | ||
return '%s(%s)' % (self.__class__.__name__, self.module) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
from __future__ import print_function | ||
|
||
import logging | ||
import subprocess | ||
import os | ||
import sys | ||
|
||
from collections import OrderedDict | ||
|
||
from component import Component | ||
from utils import simulation | ||
from driver import modprobe, rmmod, KernelDriver | ||
|
||
platforms = {} | ||
syseeprom = None | ||
|
||
def readPrefdl(): | ||
if simulation: | ||
logging.debug('bypass prefdl reading by returning default values') | ||
return {'SKU': 'simulation'} | ||
|
||
# FIXME: currently a hack that import an out of module script | ||
# the prefdl should be added as part of the module | ||
prefdl = {} | ||
execfile('/usr/share/arista/prefdl', prefdl) | ||
|
||
modprobe('eeprom') | ||
for addr in ['1-0052']: | ||
eeprompath = os.path.join('/sys/bus/i2c/drivers/eeprom', addr, 'eeprom') | ||
if not os.path.exists(eeprompath): | ||
continue | ||
try: | ||
with open(eeprompath) as f: | ||
logging.debug('reading system eeprom from %s' % eeprompath) | ||
return prefdl['decode'](f).data() | ||
except Exception as e: | ||
logging.warn('could not obtain prefdl from %s' % eeprompath) | ||
logging.warn('error seen: %s' % e) | ||
|
||
raise RuntimeError("Could not find valid system eeprom") | ||
|
||
def getSysEeprom(): | ||
global syseeprom | ||
if not syseeprom: | ||
syseeprom = readPrefdl() | ||
assert 'SKU' in syseeprom | ||
return syseeprom | ||
|
||
def detectPlatform(): | ||
return getSysEeprom()['SKU'] | ||
|
||
def getPlatform(name=None): | ||
if name == None: | ||
name = detectPlatform() | ||
return platforms[name]() | ||
|
||
def getPlatforms(): | ||
return platforms | ||
|
||
def registerPlatform(sku): | ||
global platforms | ||
def wrapper(cls): | ||
platforms[sku] = cls | ||
return cls | ||
return wrapper | ||
|
||
class Platform(Component): | ||
def __init__(self): | ||
super(Platform, self).__init__() | ||
self.addDriver(KernelDriver, 'eeprom') | ||
self.addDriver(KernelDriver, 'i2c-dev') | ||
|
||
def setup(self): | ||
super(Platform, self).setup() | ||
super(Platform, self).finish() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from collections import namedtuple | ||
|
||
Register = namedtuple("Register", ["addr", "ro"]) | ||
NamedRegister = namedtuple("NamedRegister", Register._fields + ("name", )) | ||
|
||
Gpio = namedtuple("Gpio", ["bit", "ro", "activeLow"]) | ||
NamedGpio = namedtuple("NamedGpio", ("addr",) + Gpio._fields + ("name",)) | ||
|
||
ResetGpio = namedtuple("ResetGpio", ["addr", "bit", "activeLow", "name"]) | ||
|
||
class I2cAddr(object): | ||
def __init__(self, bus, address): | ||
self.bus = bus | ||
self.address = address | ||
|
||
def __str__(self): | ||
return '%d-00%02x' % (self.bus, self.address) | ||
|
||
class PciAddr(object): | ||
def __init__(self, domain=0, bus=0, device=0, func=0): | ||
self.domain = domain | ||
self.bus = bus | ||
self.device = device | ||
self.func = func | ||
|
||
def __str__(self): | ||
return '%04x:%02x:%02x.%d' % (self.domain, self.bus, self.device, self.func) | ||
|
||
|
Oops, something went wrong.