200 lines
9.6 KiB
Python
200 lines
9.6 KiB
Python
|
#!/usr/bin/env python3
|
||
|
|
||
|
# SRIOVVFInstance.py - Class implementing a PVC SR-IOV VF and run by pvcnoded
|
||
|
# Part of the Parallel Virtual Cluster (PVC) system
|
||
|
#
|
||
|
# Copyright (C) 2018-2021 Joshua M. Boniface <joshua@boniface.me>
|
||
|
#
|
||
|
# 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, version 3.
|
||
|
#
|
||
|
# 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, see <https://www.gnu.org/licenses/>.
|
||
|
#
|
||
|
###############################################################################
|
||
|
|
||
|
import daemon_lib.common as common
|
||
|
|
||
|
|
||
|
def boolToOnOff(state):
|
||
|
if state and str(state) == 'True':
|
||
|
return 'on'
|
||
|
else:
|
||
|
return 'off'
|
||
|
|
||
|
|
||
|
class SRIOVVFInstance(object):
|
||
|
# Initialization function
|
||
|
def __init__(self, vf, zkhandler, config, logger, this_node):
|
||
|
self.vf = vf
|
||
|
self.zkhandler = zkhandler
|
||
|
self.config = config
|
||
|
self.logger = logger
|
||
|
self.this_node = this_node
|
||
|
self.myhostname = self.this_node.name
|
||
|
|
||
|
self.pf = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.pf', self.vf))
|
||
|
self.mtu = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.mtu', self.vf))
|
||
|
|
||
|
self.vfid = self.vf.replace('{}v'.format(self.pf), '')
|
||
|
self.mac = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.mac', self.vf))
|
||
|
|
||
|
self.vlan_id = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.config.vlan_id', self.vf))
|
||
|
self.vlan_qos = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.config.vlan_qos', self.vf))
|
||
|
self.tx_rate_min = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.config.tx_rate_min', self.vf))
|
||
|
self.tx_rate_max = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.config.tx_rate_max', self.vf))
|
||
|
self.spoof_check = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.config.spoof_check', self.vf))
|
||
|
self.link_state = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.config.link_state', self.vf))
|
||
|
self.trust = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.config.trust', self.vf))
|
||
|
self.query_rss = self.zkhandler.read(('node.sriov.vf', self.myhostname, 'sriov_vf.config.query_rss', self.vf))
|
||
|
|
||
|
# Zookeeper handlers for changed configs
|
||
|
@self.zkhandler.zk_conn.DataWatch(self.zkhandler.schema.path('node.sriov.vf', self.myhostname) + self.zkhandler.schema.path('sriov_vf.mac', self.vf))
|
||
|
def watch_vf_mac(data, stat, event=''):
|
||
|
if event and event.type == 'DELETED':
|
||
|
# The key has been deleted after existing before; terminate this watcher
|
||
|
# because this class instance is about to be reaped in Daemon.py
|
||
|
return False
|
||
|
|
||
|
try:
|
||
|
data = data.decode('ascii')
|
||
|
except AttributeError:
|
||
|
data = '00:00:00:00:00:00'
|
||
|
|
||
|
if data != self.mac:
|
||
|
self.mac = data
|
||
|
|
||
|
@self.zkhandler.zk_conn.DataWatch(self.zkhandler.schema.path('node.sriov.vf', self.myhostname) + self.zkhandler.schema.path('sriov_vf.config.vlan_id', self.vf))
|
||
|
def watch_vf_vlan_id(data, stat, event=''):
|
||
|
if event and event.type == 'DELETED':
|
||
|
# The key has been deleted after existing before; terminate this watcher
|
||
|
# because this class instance is about to be reaped in Daemon.py
|
||
|
return False
|
||
|
|
||
|
try:
|
||
|
data = data.decode('ascii')
|
||
|
except AttributeError:
|
||
|
data = '0'
|
||
|
|
||
|
if data != self.vlan_id:
|
||
|
self.vlan_id = data
|
||
|
common.run_os_command('ip link set {} vf {} vlan {} qos {}'.format(self.pf, self.vfid, self.vlan_id, self.vlan_qos))
|
||
|
|
||
|
@self.zkhandler.zk_conn.DataWatch(self.zkhandler.schema.path('node.sriov.vf', self.myhostname) + self.zkhandler.schema.path('sriov_vf.config.vlan_qos', self.vf))
|
||
|
def watch_vf_vlan_qos(data, stat, event=''):
|
||
|
if event and event.type == 'DELETED':
|
||
|
# The key has been deleted after existing before; terminate this watcher
|
||
|
# because this class instance is about to be reaped in Daemon.py
|
||
|
return False
|
||
|
|
||
|
try:
|
||
|
data = data.decode('ascii')
|
||
|
except AttributeError:
|
||
|
data = '0'
|
||
|
|
||
|
if data != self.vlan_qos:
|
||
|
self.vlan_qos = data
|
||
|
common.run_os_command('ip link set {} vf {} vlan {} qos {}'.format(self.pf, self.vfid, self.vlan_id, self.vlan_qos))
|
||
|
|
||
|
@self.zkhandler.zk_conn.DataWatch(self.zkhandler.schema.path('node.sriov.vf', self.myhostname) + self.zkhandler.schema.path('sriov_vf.config.tx_rate_min', self.vf))
|
||
|
def watch_vf_tx_rate_min(data, stat, event=''):
|
||
|
if event and event.type == 'DELETED':
|
||
|
# The key has been deleted after existing before; terminate this watcher
|
||
|
# because this class instance is about to be reaped in Daemon.py
|
||
|
return False
|
||
|
|
||
|
try:
|
||
|
data = data.decode('ascii')
|
||
|
except AttributeError:
|
||
|
data = '0'
|
||
|
|
||
|
if data != self.tx_rate_min:
|
||
|
self.tx_rate_min = data
|
||
|
common.run_os_command('ip link set {} vf {} min_tx_rate {}'.format(self.pf, self.vfid, self.tx_rate_min))
|
||
|
|
||
|
@self.zkhandler.zk_conn.DataWatch(self.zkhandler.schema.path('node.sriov.vf', self.myhostname) + self.zkhandler.schema.path('sriov_vf.config.tx_rate_max', self.vf))
|
||
|
def watch_vf_tx_rate_max(data, stat, event=''):
|
||
|
if event and event.type == 'DELETED':
|
||
|
# The key has been deleted after existing before; termaxate this watcher
|
||
|
# because this class instance is about to be reaped in Daemon.py
|
||
|
return False
|
||
|
|
||
|
try:
|
||
|
data = data.decode('ascii')
|
||
|
except AttributeError:
|
||
|
data = '0'
|
||
|
|
||
|
if data != self.tx_rate_max:
|
||
|
self.tx_rate_max = data
|
||
|
common.run_os_command('ip link set {} vf {} max_tx_rate {}'.format(self.pf, self.vfid, self.tx_rate_max))
|
||
|
|
||
|
@self.zkhandler.zk_conn.DataWatch(self.zkhandler.schema.path('node.sriov.vf', self.myhostname) + self.zkhandler.schema.path('sriov_vf.config.spoof_check', self.vf))
|
||
|
def watch_vf_spoof_check(data, stat, event=''):
|
||
|
if event and event.type == 'DELETED':
|
||
|
# The key has been deleted after existing before; terminate this watcher
|
||
|
# because this class instance is about to be reaped in Daemon.py
|
||
|
return False
|
||
|
|
||
|
try:
|
||
|
data = data.decode('ascii')
|
||
|
except AttributeError:
|
||
|
data = '0'
|
||
|
|
||
|
if data != self.spoof_check:
|
||
|
self.spoof_check = data
|
||
|
common.run_os_command('ip link set {} vf {} spoofchk {}'.format(self.pf, self.vfid, boolToOnOff(self.spoof_check)))
|
||
|
|
||
|
@self.zkhandler.zk_conn.DataWatch(self.zkhandler.schema.path('node.sriov.vf', self.myhostname) + self.zkhandler.schema.path('sriov_vf.config.link_state', self.vf))
|
||
|
def watch_vf_link_state(data, stat, event=''):
|
||
|
if event and event.type == 'DELETED':
|
||
|
# The key has been deleted after existing before; terminate this watcher
|
||
|
# because this class instance is about to be reaped in Daemon.py
|
||
|
return False
|
||
|
|
||
|
try:
|
||
|
data = data.decode('ascii')
|
||
|
except AttributeError:
|
||
|
data = 'on'
|
||
|
|
||
|
if data != self.link_state:
|
||
|
self.link_state = data
|
||
|
common.run_os_command('ip link set {} vf {} state {}'.format(self.pf, self.vfid, self.link_state))
|
||
|
|
||
|
@self.zkhandler.zk_conn.DataWatch(self.zkhandler.schema.path('node.sriov.vf', self.myhostname) + self.zkhandler.schema.path('sriov_vf.config.trust', self.vf))
|
||
|
def watch_vf_trust(data, stat, event=''):
|
||
|
if event and event.type == 'DELETED':
|
||
|
# The key has been deleted after existing before; terminate this watcher
|
||
|
# because this class instance is about to be reaped in Daemon.py
|
||
|
return False
|
||
|
|
||
|
try:
|
||
|
data = data.decode('ascii')
|
||
|
except AttributeError:
|
||
|
data = 'off'
|
||
|
|
||
|
if data != self.trust:
|
||
|
self.trust = data
|
||
|
common.run_os_command('ip link set {} vf {} trust {}'.format(self.pf, self.vfid, boolToOnOff(self.trust)))
|
||
|
|
||
|
@self.zkhandler.zk_conn.DataWatch(self.zkhandler.schema.path('node.sriov.vf', self.myhostname) + self.zkhandler.schema.path('sriov_vf.config.query_rss', self.vf))
|
||
|
def watch_vf_query_rss(data, stat, event=''):
|
||
|
if event and event.type == 'DELETED':
|
||
|
# The key has been deleted after existing before; terminate this watcher
|
||
|
# because this class instance is about to be reaped in Daemon.py
|
||
|
return False
|
||
|
|
||
|
try:
|
||
|
data = data.decode('ascii')
|
||
|
except AttributeError:
|
||
|
data = 'off'
|
||
|
|
||
|
if data != self.query_rss:
|
||
|
self.query_rss = data
|
||
|
common.run_os_command('ip link set {} vf {} trust {}'.format(self.pf, self.vfid, boolToOnOff(self.query_rss)))
|