Skip to content

Commit

Permalink
bridge, bond, vlan and ethernet support
Browse files Browse the repository at this point in the history
This patch is just a proof of concept based on command line scripts
and loads of copy paste code, it should be reverted and done properly.
  • Loading branch information
phoracek committed Dec 29, 2016
1 parent 3d7e759 commit c469c3c
Show file tree
Hide file tree
Showing 53 changed files with 2,805 additions and 1 deletion.
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ netsu NetworkManager plugin

.. image:: https://coveralls.io/repos/github/netsu-project/netsu-plugin-networkmanager/badge.svg?branch=master
:target: https://coveralls.io/github/netsu-project/netsu-plugin-networkmanager?branch=master

Just a proof of concept based on command line scripts and loads of copy paste
code, the last patch should be reverted and done properly.
14 changes: 14 additions & 0 deletions netsu_plugin_networkmanager/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (C) 2016 Petr Horacek <phoracek@redhat.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
16 changes: 16 additions & 0 deletions netsu_plugin_networkmanager/bond/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright (C) 2016 Petr Horacek <phoracek@redhat.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.

BOND_CONNECTION_PREFIX = 'netsu_bond'
66 changes: 66 additions & 0 deletions netsu_plugin_networkmanager/bond/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Copyright (C) 2016 Petr Horacek <phoracek@redhat.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.

from ..utils import label
from ..utils import nmcli
from ..utils_ip import parser as ip_parser

from . import BOND_CONNECTION_PREFIX


def update(config):
config['nm_bond'] = get_bonds(only_active=True)


def get_bonds(only_active=False):
bonds = {}

connections = nmcli.list_connections()
for connection in connections:
if only_active and not _is_active(connection):
continue
if _is_bond(connection):
connection_info = nmcli.get_connection_info(connection['uuid'])
name, attrs = _read_bond_config(connection_info)
bonds[name] = attrs

return bonds


def _is_active(connection):
return connection['device'] is not None


def _is_bond(connection):
return connection['name'].startswith(BOND_CONNECTION_PREFIX)


def _read_master(connection_info):
master = connection_info['connection.master']
slave_type = connection_info['connection.slave-type']
return {'name': master, 'type': slave_type} if master != '--' else None


def _read_bond_config(connection_info):
bond_options = dict(
key_value.split('=', 1)
for key_value in connection_info['bond.options'].split(','))
return connection_info['connection.interface-name'], {
'mode': bond_options.get('mode', 'balance-rr'),
'primary': bond_options.get('primary'),
'miimon': int(bond_options.get('miimon', 100)),
'ipv4': ip_parser.read_ipv4_config(connection_info),
'master': _read_master(connection_info),
'label': label.get_label(connection_info['connection.id'])}
93 changes: 93 additions & 0 deletions netsu_plugin_networkmanager/bond/config_definitions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Copyright (C) 2016 Petr Horacek <phoracek@redhat.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.

from ..utils import label_definitions
from ..utils_ip import definitions as ip_definitions


BOND = {
'NMBondConfig': {
'type': 'object',
'default': {},
'properties': {
'mode': {
'type': 'string',
'default': 'balance-rr',
'choice': ['active-backup', 'balance-xor', 'broadcast',
'802.3ad', 'balance-tlb', 'balance-alb']
},
'primary': {
'default': None,
'anyOf': [
{'type': 'string'},
{'type': 'null'}
]
},
'miimon': {
'type': 'integer',
'default': 100
},
'ipv4': {
'$ref': '#/definitions/NMIPv4Config'
},
'master': {
'default': None,
'anyOf': [
{
'type': 'object',
'required': ['name', 'type'],
'properties': {
'name': {
'type': 'string'
},
'type': {
'type': 'string'
}
}
},
{
'type': 'null'
}
]
},
'label': {
'$ref': '#/definitions/NMLabel'
}
}
}
}

BONDS = {
'NMBondsConfig': {
'type': 'object',
'default': {},
'patternProperties': {
'^[a-zA-Z0-9-]{1,16}$': {
'$ref': '#/definitions/NMBondConfig'
}
},
'additionalProperties': False
}
}


def update(api_definitions):
api_definitions.update(ip_definitions.IPv4_CONFIG)
api_definitions.update(label_definitions.LABEL)
api_definitions.update(BOND)
api_definitions.update(BONDS)
api_definitions['Config']['properties']['nm_bond'] = {
'$ref': '#/definitions/NMBondsConfig'
}
123 changes: 123 additions & 0 deletions netsu_plugin_networkmanager/bond/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Copyright (C) 2016 Petr Horacek <phoracek@redhat.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.

from ..utils import nmcli
from ..utils import label
from ..utils_ip import setup as ip_setup

from . import BOND_CONNECTION_PREFIX
from . import config


def detach_from_master(requested_config):
system_bonds = config.get_bonds()
requested_bonds = requested_config['nm_bond']

for bond, attrs in requested_bonds.items():
if bond in system_bonds:
system_attrs = system_bonds[bond]
if system_attrs['master'] != attrs['master']:
connection_name = label.build_connection_name(
BOND_CONNECTION_PREFIX, attrs['label'], bond)
nmcli.run(['connection', 'modify', connection_name,
'connection.master', '',
'connection.slave-type', ''])


def remove(requested_config):
system_bonds = config.get_bonds()
requested_bonds = requested_config['nm_bond']

bonds2remove = system_bonds.keys() - requested_bonds.keys()
for bond in bonds2remove:
attrs = system_bonds[bond]
connection_name = label.build_connection_name(
BOND_CONNECTION_PREFIX, attrs['label'], bond)
nmcli.run(['connection', 'delete', connection_name])


def add(requested_config):
system_bonds = config.get_bonds()
requested_bonds = requested_config['nm_bond']

bonds2add = requested_bonds.keys() - system_bonds.keys()
for bond in bonds2add:
attrs = requested_bonds[bond]
connection_name = label.build_connection_name(
BOND_CONNECTION_PREFIX, attrs['label'], bond)
nmcli.run(['connection', 'add', 'type', 'bond',
'ifname', bond, 'con-name', connection_name,
'save', 'no', '--', 'ipv4.method', 'disabled'])


def attach_to_master(requested_config):
system_bonds = config.get_bonds()
requested_bonds = requested_config['nm_bond']

for bond, attrs in requested_bonds.items():
system_attrs = system_bonds[bond]
if system_attrs['master'] != attrs['master']:
connection_name = label.build_connection_name(
BOND_CONNECTION_PREFIX, attrs['label'], bond)
nmcli.run(['connection', 'modify', connection_name,
'connection.master', attrs['master']['name'],
'connection.slave-type', attrs['master']['type']])


def set_options(requested_config):
system_bonds = config.get_bonds()
requested_bonds = requested_config['nm_bond']

for bond, attrs in requested_bonds.items():
system_attrs = system_bonds[bond]
command = []

bond_options = {}
bond_options['mode'] = attrs['mode']
bond_options['miimon'] = attrs['miimon']
primary = attrs.get('primary')
if primary:
bond_options['primary'] = attrs['primary']
command.extend(
['bond.options',
(','.join('{}={}'.format(key, value) for
key, value in bond_options.items()))])

if system_attrs['label'] != attrs['label']:
new_connection_name = label.build_connection_name(
BOND_CONNECTION_PREFIX, attrs['label'], bond)
command.extend(['connection.id', new_connection_name])
command.extend(
ip_setup.ipv4_changes(system_attrs['ipv4'], attrs['ipv4']))

connection_name = label.build_connection_name(
BOND_CONNECTION_PREFIX, system_attrs['label'], bond)
nmcli.run(['connection', 'modify', connection_name] + command)


def turn_up(requested_config):
requested_bonds = requested_config['nm_bond']

for bond, attrs in requested_bonds.items():
connection_name = label.build_connection_name(
BOND_CONNECTION_PREFIX, attrs['label'], bond)
nmcli.run(['connection', 'up', connection_name])


def force_cleanup():
connections = nmcli.list_connections()
for connection in connections:
if connection['name'].startswith(BOND_CONNECTION_PREFIX):
nmcli.run(['connection', 'delete', connection['uuid']])
45 changes: 45 additions & 0 deletions netsu_plugin_networkmanager/bond/state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright (C) 2016 Petr Horacek <phoracek@redhat.com>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.

from ..utils import nmcli
from ..utils_ip import parser as ip_parser

from . import BOND_CONNECTION_PREFIX


def update(state):
state['nm_bond'] = get_bonds()


def get_bonds():
bonds = {}

connections = nmcli.list_connections()
for connection in connections:
if _is_bond(connection):
connection_info = nmcli.get_connection_info(connection['uuid'])
name, attrs = _read_bond_state(connection_info)
bonds[name] = attrs

return bonds


def _is_bond(connection):
return connection['name'].startswith(BOND_CONNECTION_PREFIX)


def _read_bond_state(connection_info):
return connection_info['connection.interface-name'], {
'ipv4': ip_parser.read_ipv4_state(connection_info)}

0 comments on commit c469c3c

Please sign in to comment.