Merge "Move network database models to extension"

This commit is contained in:
Jenkins 2016-04-12 16:25:44 +00:00 committed by Gerrit Code Review
commit 153a6a110d
7 changed files with 324 additions and 312 deletions

View File

@ -37,20 +37,29 @@ from nailgun.db.sqlalchemy.models.cluster import VmwareAttributes
from nailgun.db.sqlalchemy.models.release import Release
from nailgun.extensions.network_manager.models.network import NetworkGroup
from nailgun.extensions.network_manager.models.network import IPAddr
from nailgun.extensions.network_manager.models.network import IPAddrRange
from nailgun.extensions.network_manager.models.network import \
NetworkNICAssignment
from nailgun.extensions.network_manager.models.network import \
NetworkBondAssignment
from nailgun.extensions.network_manager.models.network import \
NodeBondInterface
from nailgun.extensions.network_manager.models.network import \
NodeNICInterface
from nailgun.extensions.network_manager.models import network
from nailgun.db.sqlalchemy.models.node import Node
from nailgun.db.sqlalchemy.models.node import NodeBondInterface
from nailgun.db.sqlalchemy.models.node import NodeNICInterface
from nailgun.db.sqlalchemy.models.node import NodeGroup
from nailgun.db.sqlalchemy.models.network import NetworkGroup
from nailgun.db.sqlalchemy.models.network import IPAddr
from nailgun.db.sqlalchemy.models.network import IPAddrRange
from nailgun.db.sqlalchemy.models.network import NetworkNICAssignment
from nailgun.db.sqlalchemy.models.network import NetworkBondAssignment
from nailgun.db.sqlalchemy.models.network_config import NetworkingConfig
from nailgun.db.sqlalchemy.models.network_config import NeutronConfig
from nailgun.db.sqlalchemy.models.network_config import NovaNetworkConfig
from nailgun.extensions.network_manager.models.network_config import \
NetworkingConfig
from nailgun.extensions.network_manager.models.network_config import \
NeutronConfig
from nailgun.extensions.network_manager.models.network_config import \
NovaNetworkConfig
from nailgun.db.sqlalchemy.models.notification import Notification
from nailgun.db.sqlalchemy.models.cluster_plugin_link import ClusterPluginLink

View File

@ -1,118 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2013 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy.dialects import postgresql as psql
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy.orm import relationship
from sqlalchemy import String
from nailgun.db.sqlalchemy.models.base import Base
from nailgun.db.sqlalchemy.models.fields import JSON
from nailgun.db.sqlalchemy.models.mutable import MutableDict
class IPAddr(Base):
__tablename__ = 'ip_addrs'
id = Column(Integer, primary_key=True)
network = Column(Integer, ForeignKey('network_groups.id',
ondelete="CASCADE"))
node = Column(Integer, ForeignKey('nodes.id', ondelete="CASCADE"))
ip_addr = Column(psql.INET, nullable=False)
vip_name = Column(String(50), nullable=True)
vip_namespace = Column(
String(50),
nullable=True,
server_default=None
)
is_user_defined = Column(
Boolean,
nullable=False,
default=False,
server_default="false"
)
network_data = relationship("NetworkGroup")
node_data = relationship("Node")
class IPAddrRange(Base):
__tablename__ = 'ip_addr_ranges'
id = Column(Integer, primary_key=True)
network_group_id = Column(Integer, ForeignKey('network_groups.id',
ondelete="CASCADE"))
first = Column(psql.INET, nullable=False)
last = Column(psql.INET, nullable=False)
class NetworkGroup(Base):
__tablename__ = 'network_groups'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
# can be nullable only for fuelweb admin net
release = Column(Integer, ForeignKey('releases.id', ondelete='CASCADE'))
# can be nullable only for fuelweb admin net
group_id = Column(
Integer,
ForeignKey('nodegroups.id', ondelete='CASCADE'),
nullable=True
)
vlan_start = Column(Integer)
cidr = Column(psql.CIDR)
gateway = Column(psql.INET)
ip_ranges = relationship(
"IPAddrRange",
backref="network_group",
cascade="all, delete, delete-orphan"
)
nodes = relationship(
"Node",
secondary=IPAddr.__table__,
backref="networks",
passive_deletes=True
)
meta = Column(MutableDict.as_mutable(JSON), default={})
class NetworkNICAssignment(Base):
__tablename__ = 'net_nic_assignments'
id = Column(Integer, primary_key=True)
network_id = Column(
Integer,
ForeignKey('network_groups.id', ondelete="CASCADE"),
nullable=False
)
interface_id = Column(
Integer,
ForeignKey('node_nic_interfaces.id', ondelete="CASCADE"),
nullable=False
)
class NetworkBondAssignment(Base):
__tablename__ = 'net_bond_assignments'
id = Column(Integer, primary_key=True)
network_id = Column(
Integer,
ForeignKey('network_groups.id', ondelete="CASCADE"),
nullable=False
)
bond_id = Column(
Integer,
ForeignKey('node_bond_interfaces.id', ondelete="CASCADE"),
nullable=False
)

View File

@ -13,7 +13,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
import uuid
from sqlalchemy import Boolean
@ -35,8 +34,6 @@ from nailgun.db.sqlalchemy.models.base import Base
from nailgun.db.sqlalchemy.models.fields import JSON
from nailgun.db.sqlalchemy.models.mutable import MutableDict
from nailgun.db.sqlalchemy.models.mutable import MutableList
from nailgun.db.sqlalchemy.models.network import NetworkBondAssignment
from nailgun.db.sqlalchemy.models.network import NetworkNICAssignment
from nailgun.extensions.volume_manager.manager import VolumeManager
from nailgun.logger import logger
@ -231,178 +228,3 @@ class Node(Base):
data["interfaces"] = result
self.meta = data
class NodeNICInterface(Base):
__tablename__ = 'node_nic_interfaces'
id = Column(Integer, primary_key=True)
node_id = Column(
Integer,
ForeignKey('nodes.id', ondelete="CASCADE"),
nullable=False)
name = Column(String(128), nullable=False)
mac = Column(psql.MACADDR, nullable=False)
max_speed = Column(Integer)
current_speed = Column(Integer)
assigned_networks_list = relationship(
"NetworkGroup",
secondary=NetworkNICAssignment.__table__,
order_by="NetworkGroup.id")
ip_addr = Column(psql.INET)
netmask = Column(psql.INET)
state = Column(String(25))
interface_properties = Column(
MutableDict.as_mutable(JSON), default={}, nullable=False,
server_default='{}')
parent_id = Column(
Integer,
ForeignKey('node_bond_interfaces.id', ondelete='SET NULL')
)
driver = Column(Text)
bus_info = Column(Text)
pxe = Column(Boolean, default=False, nullable=False)
offloading_modes = Column(MutableList.as_mutable(JSON),
default=[], nullable=False,
server_default='[]')
@property
def type(self):
return consts.NETWORK_INTERFACE_TYPES.ether
@property
def assigned_networks(self):
return [
{"id": n.id, "name": n.name}
for n in self.assigned_networks_list
]
@assigned_networks.setter
def assigned_networks(self, value):
self.assigned_networks_list = value
# TODO(fzhadaev): move to object
@classmethod
def offloading_modes_as_flat_dict(cls, modes):
"""Represents multilevel structure of offloading modes as flat dict
This is done to ease merging
:param modes: list of offloading modes
:return: flat dictionary {mode['name']: mode['state']}
"""
result = dict()
if modes is None:
return result
for mode in modes:
result[mode["name"]] = mode["state"]
if mode["sub"]:
result.update(cls.offloading_modes_as_flat_dict(mode["sub"]))
return result
class NodeBondInterface(Base):
__tablename__ = 'node_bond_interfaces'
id = Column(Integer, primary_key=True)
node_id = Column(
Integer,
ForeignKey('nodes.id', ondelete="CASCADE"),
nullable=False)
name = Column(String(32), nullable=False)
mac = Column(psql.MACADDR)
assigned_networks_list = relationship(
"NetworkGroup",
secondary=NetworkBondAssignment.__table__,
order_by="NetworkGroup.id")
state = Column(String(25))
interface_properties = Column(
MutableDict.as_mutable(JSON), default={}, nullable=False,
server_default='{}')
mode = Column(
Enum(
*consts.BOND_MODES,
name='bond_mode'
),
nullable=False,
default=consts.BOND_MODES.active_backup
)
bond_properties = Column(
MutableDict.as_mutable(JSON), default={}, nullable=False,
server_default='{}')
slaves = relationship("NodeNICInterface", backref="bond")
@property
def max_speed(self):
return None
@property
def current_speed(self):
return None
@property
def type(self):
return consts.NETWORK_INTERFACE_TYPES.bond
@property
def assigned_networks(self):
return [
{"id": n.id, "name": n.name}
for n in self.assigned_networks_list
]
@assigned_networks.setter
def assigned_networks(self, value):
self.assigned_networks_list = value
@property
def offloading_modes(self):
tmp = None
intersection_dict = {}
for interface in self.slaves:
modes = interface.offloading_modes
if tmp is None:
tmp = modes
intersection_dict = \
interface.offloading_modes_as_flat_dict(tmp)
continue
intersection_dict = self._intersect_offloading_dicts(
intersection_dict,
interface.offloading_modes_as_flat_dict(modes)
)
return self._apply_intersection(tmp, intersection_dict)
@offloading_modes.setter
def offloading_modes(self, new_modes):
new_modes_dict = \
NodeNICInterface.offloading_modes_as_flat_dict(new_modes)
for interface in self.slaves:
self._update_modes(interface.offloading_modes, new_modes_dict)
interface.offloading_modes.changed()
def _update_modes(self, modes, update_dict):
for mode in modes:
if mode['name'] in update_dict:
mode['state'] = update_dict[mode['name']]
if mode['sub']:
self._update_modes(mode['sub'], update_dict)
def _intersect_offloading_dicts(self, dict1, dict2):
result = dict()
for mode in dict1:
if mode in dict2:
result[mode] = dict1[mode] and dict2[mode]
return result
def _apply_intersection(self, modes, intersection_dict):
result = list()
if modes is None:
return result
for mode in copy.deepcopy(modes):
if mode["name"] not in intersection_dict:
continue
mode["state"] = intersection_dict[mode["name"]]
if mode["sub"]:
mode["sub"] = \
self._apply_intersection(mode["sub"], intersection_dict)
result.append(mode)
return result

View File

@ -0,0 +1,299 @@
# -*- coding: utf-8 -*-
# Copyright 2013 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy.dialects import postgresql as psql
from sqlalchemy import Enum
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy.orm import relationship
from sqlalchemy import String
from sqlalchemy import Text
from nailgun import consts
from nailgun.db.sqlalchemy.models.base import Base
from nailgun.db.sqlalchemy.models.fields import JSON
from nailgun.db.sqlalchemy.models.mutable import MutableDict
from nailgun.db.sqlalchemy.models.mutable import MutableList
class IPAddr(Base):
__tablename__ = 'ip_addrs'
id = Column(Integer, primary_key=True)
network = Column(Integer, ForeignKey('network_groups.id',
ondelete="CASCADE"))
node = Column(Integer, ForeignKey('nodes.id', ondelete="CASCADE"))
ip_addr = Column(psql.INET, nullable=False)
vip_name = Column(String(50), nullable=True)
vip_namespace = Column(
String(50),
nullable=True,
server_default=None
)
is_user_defined = Column(
Boolean,
nullable=False,
default=False,
server_default="false"
)
network_data = relationship("NetworkGroup")
node_data = relationship("Node")
class IPAddrRange(Base):
__tablename__ = 'ip_addr_ranges'
id = Column(Integer, primary_key=True)
network_group_id = Column(Integer, ForeignKey('network_groups.id',
ondelete="CASCADE"))
first = Column(psql.INET, nullable=False)
last = Column(psql.INET, nullable=False)
class NetworkGroup(Base):
__tablename__ = 'network_groups'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
# can be nullable only for fuelweb admin net
release = Column(Integer, ForeignKey('releases.id', ondelete='CASCADE'))
# can be nullable only for fuelweb admin net
group_id = Column(
Integer,
ForeignKey('nodegroups.id', ondelete='CASCADE'),
nullable=True
)
vlan_start = Column(Integer)
cidr = Column(psql.CIDR)
gateway = Column(psql.INET)
ip_ranges = relationship(
"IPAddrRange",
backref="network_group",
cascade="all, delete, delete-orphan"
)
nodes = relationship(
"Node",
secondary=IPAddr.__table__,
backref="networks",
passive_deletes=True
)
meta = Column(MutableDict.as_mutable(JSON), default={})
class NetworkNICAssignment(Base):
__tablename__ = 'net_nic_assignments'
id = Column(Integer, primary_key=True)
network_id = Column(
Integer,
ForeignKey('network_groups.id', ondelete="CASCADE"),
nullable=False
)
interface_id = Column(
Integer,
ForeignKey('node_nic_interfaces.id', ondelete="CASCADE"),
nullable=False
)
class NetworkBondAssignment(Base):
__tablename__ = 'net_bond_assignments'
id = Column(Integer, primary_key=True)
network_id = Column(
Integer,
ForeignKey('network_groups.id', ondelete="CASCADE"),
nullable=False
)
bond_id = Column(
Integer,
ForeignKey('node_bond_interfaces.id', ondelete="CASCADE"),
nullable=False
)
class NodeNICInterface(Base):
__tablename__ = 'node_nic_interfaces'
id = Column(Integer, primary_key=True)
node_id = Column(
Integer,
ForeignKey('nodes.id', ondelete="CASCADE"),
nullable=False)
name = Column(String(128), nullable=False)
mac = Column(psql.MACADDR, nullable=False)
max_speed = Column(Integer)
current_speed = Column(Integer)
assigned_networks_list = relationship(
"NetworkGroup",
secondary=NetworkNICAssignment.__table__,
order_by="NetworkGroup.id")
ip_addr = Column(psql.INET)
netmask = Column(psql.INET)
state = Column(String(25))
interface_properties = Column(
MutableDict.as_mutable(JSON), default={}, nullable=False,
server_default='{}')
parent_id = Column(
Integer,
ForeignKey('node_bond_interfaces.id', ondelete='SET NULL')
)
driver = Column(Text)
bus_info = Column(Text)
pxe = Column(Boolean, default=False, nullable=False)
offloading_modes = Column(MutableList.as_mutable(JSON),
default=[], nullable=False,
server_default='[]')
@property
def type(self):
return consts.NETWORK_INTERFACE_TYPES.ether
@property
def assigned_networks(self):
return [
{"id": n.id, "name": n.name}
for n in self.assigned_networks_list
]
@assigned_networks.setter
def assigned_networks(self, value):
self.assigned_networks_list = value
# TODO(fzhadaev): move to object
@classmethod
def offloading_modes_as_flat_dict(cls, modes):
"""Represents multilevel structure of offloading modes as flat dict
This is done to ease merging
:param modes: list of offloading modes
:return: flat dictionary {mode['name']: mode['state']}
"""
result = dict()
if modes is None:
return result
for mode in modes:
result[mode["name"]] = mode["state"]
if mode["sub"]:
result.update(cls.offloading_modes_as_flat_dict(mode["sub"]))
return result
class NodeBondInterface(Base):
__tablename__ = 'node_bond_interfaces'
id = Column(Integer, primary_key=True)
node_id = Column(
Integer,
ForeignKey('nodes.id', ondelete="CASCADE"),
nullable=False)
name = Column(String(32), nullable=False)
mac = Column(psql.MACADDR)
assigned_networks_list = relationship(
"NetworkGroup",
secondary=NetworkBondAssignment.__table__,
order_by="NetworkGroup.id")
state = Column(String(25))
interface_properties = Column(
MutableDict.as_mutable(JSON), default={}, nullable=False,
server_default='{}')
mode = Column(
Enum(
*consts.BOND_MODES,
name='bond_mode'
),
nullable=False,
default=consts.BOND_MODES.active_backup
)
bond_properties = Column(
MutableDict.as_mutable(JSON), default={}, nullable=False,
server_default='{}')
slaves = relationship("NodeNICInterface", backref="bond")
@property
def max_speed(self):
return None
@property
def current_speed(self):
return None
@property
def type(self):
return consts.NETWORK_INTERFACE_TYPES.bond
@property
def assigned_networks(self):
return [
{"id": n.id, "name": n.name}
for n in self.assigned_networks_list
]
@assigned_networks.setter
def assigned_networks(self, value):
self.assigned_networks_list = value
@property
def offloading_modes(self):
tmp = None
intersection_dict = {}
for interface in self.slaves:
modes = interface.offloading_modes
if tmp is None:
tmp = modes
intersection_dict = \
interface.offloading_modes_as_flat_dict(tmp)
continue
intersection_dict = self._intersect_offloading_dicts(
intersection_dict,
interface.offloading_modes_as_flat_dict(modes)
)
return self._apply_intersection(tmp, intersection_dict)
@offloading_modes.setter
def offloading_modes(self, new_modes):
new_modes_dict = \
NodeNICInterface.offloading_modes_as_flat_dict(new_modes)
for interface in self.slaves:
self._update_modes(interface.offloading_modes, new_modes_dict)
interface.offloading_modes.changed()
def _update_modes(self, modes, update_dict):
for mode in modes:
if mode['name'] in update_dict:
mode['state'] = update_dict[mode['name']]
if mode['sub']:
self._update_modes(mode['sub'], update_dict)
def _intersect_offloading_dicts(self, dict1, dict2):
result = dict()
for mode in dict1:
if mode in dict2:
result[mode] = dict1[mode] and dict2[mode]
return result
def _apply_intersection(self, modes, intersection_dict):
result = list()
if modes is None:
return result
for mode in copy.deepcopy(modes):
if mode["name"] not in intersection_dict:
continue
mode["state"] = intersection_dict[mode["name"]]
if mode["sub"]:
mode["sub"] = \
self._apply_intersection(mode["sub"], intersection_dict)
result.append(mode)
return result

View File

@ -18,8 +18,8 @@ from mock import patch
from nailgun import consts
from nailgun.db.sqlalchemy.models import Cluster
from nailgun.db.sqlalchemy.models import network as network_db
from nailgun.db.sqlalchemy.models import NetworkGroup
from nailgun.db.sqlalchemy.models import node
from nailgun.db.sqlalchemy.models import Task
from nailgun.errors import errors
from nailgun.network.checker import NetworkCheck
@ -502,12 +502,12 @@ class TestNetworkCheck(BaseIntegrationTest):
checker.check_bond_slaves_speeds()
self.assertEqual(checker.err_msgs, [])
bond_if1 = node.NodeBondInterface()
bond_if2 = node.NodeBondInterface()
bond_if1 = network_db.NodeBondInterface()
bond_if2 = network_db.NodeBondInterface()
nic1 = node.NodeNICInterface()
nic2 = node.NodeNICInterface()
nic3 = node.NodeNICInterface()
nic1 = network_db.NodeNICInterface()
nic2 = network_db.NodeNICInterface()
nic3 = network_db.NodeNICInterface()
nic1.current_speed = 100
nic2.current_speed = 10
nic3.current_speed = None