Data model changes for Plugin NIC, BOND and Node attributes
This patch: * extends current DB model with new entities and provides related migrations. * extends plugin sync method to support storing new plugins attributes. * provides cosmetic fix for ClusterPlugin model. Lets write table names in the plural but model names in the singular. Change-Id: I3edbde1d48461ce3fab7c93f17e2db5332b1f7fb Implements: blueprint nics-and-nodes-attributes-via-plugin
This commit is contained in:
parent
c3a868dd32
commit
9d86b078cf
|
@ -17,7 +17,7 @@
|
|||
from nailgun.api.v1.validators.base import BasicValidator
|
||||
from nailgun.api.v1.validators.json_schema import plugin
|
||||
from nailgun import errors
|
||||
from nailgun.objects import ClusterPlugins
|
||||
from nailgun.objects import ClusterPlugin
|
||||
from nailgun.objects import Plugin
|
||||
|
||||
|
||||
|
@ -25,7 +25,7 @@ class PluginValidator(BasicValidator):
|
|||
|
||||
@classmethod
|
||||
def validate_delete(cls, data, instance):
|
||||
if ClusterPlugins.is_plugin_used(instance.id):
|
||||
if ClusterPlugin.is_plugin_used(instance.id):
|
||||
raise errors.CannotDelete(
|
||||
"Can't delete plugin which is enabled "
|
||||
"for some environment."
|
||||
|
|
|
@ -23,6 +23,8 @@ Create Date: 2016-04-08 15:20:43.989472
|
|||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
from nailgun.db.sqlalchemy.models import fields
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c6edea552f1e'
|
||||
|
@ -31,9 +33,11 @@ down_revision = '675105097a69'
|
|||
|
||||
def upgrade():
|
||||
upgrade_plugin_links_constraints()
|
||||
upgrade_plugin_with_nics_and_nodes_attributes()
|
||||
|
||||
|
||||
def downgrade():
|
||||
downgrade_plugin_with_nics_and_nodes_attributes()
|
||||
downgrade_plugin_links_constraints()
|
||||
|
||||
|
||||
|
@ -80,3 +84,153 @@ def downgrade_plugin_links_constraints():
|
|||
'cluster_plugin_links')
|
||||
|
||||
op.drop_constraint('plugin_links_url_uc', 'plugin_links')
|
||||
|
||||
|
||||
def upgrade_plugin_with_nics_and_nodes_attributes():
|
||||
op.add_column(
|
||||
'plugins',
|
||||
sa.Column(
|
||||
'nic_attributes_metadata',
|
||||
fields.JSON(),
|
||||
nullable=False,
|
||||
server_default='{}'
|
||||
)
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
'plugins',
|
||||
sa.Column(
|
||||
'bond_attributes_metadata',
|
||||
fields.JSON(),
|
||||
nullable=False,
|
||||
server_default='{}'
|
||||
)
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
'plugins',
|
||||
sa.Column(
|
||||
'node_attributes_metadata',
|
||||
fields.JSON(),
|
||||
nullable=False,
|
||||
server_default='{}'
|
||||
)
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
'node_nic_interfaces',
|
||||
sa.Column(
|
||||
'attributes',
|
||||
fields.JSON(),
|
||||
nullable=False,
|
||||
server_default='{}'
|
||||
)
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
'node_nic_interfaces',
|
||||
sa.Column(
|
||||
'meta',
|
||||
fields.JSON(),
|
||||
nullable=False,
|
||||
server_default='{}'
|
||||
)
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
'node_bond_interfaces',
|
||||
sa.Column(
|
||||
'attributes',
|
||||
fields.JSON(),
|
||||
nullable=False,
|
||||
server_default='{}'
|
||||
)
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
'releases',
|
||||
sa.Column(
|
||||
'nic_attributes',
|
||||
fields.JSON(),
|
||||
nullable=False,
|
||||
server_default='{}'
|
||||
)
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
'releases',
|
||||
sa.Column(
|
||||
'bond_attributes',
|
||||
fields.JSON(),
|
||||
nullable=False,
|
||||
server_default='{}'
|
||||
)
|
||||
)
|
||||
|
||||
op.create_table(
|
||||
'node_nic_interface_cluster_plugins',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column(
|
||||
'attributes', fields.JSON(), nullable=False, server_default='{}'),
|
||||
sa.Column('cluster_plugin_id', sa.Integer(), nullable=False),
|
||||
sa.Column('interface_id', sa.Integer(), nullable=False),
|
||||
sa.Column('node_id', sa.Integer(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.ForeignKeyConstraint(
|
||||
['cluster_plugin_id'],
|
||||
['cluster_plugins.id'],
|
||||
ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(
|
||||
['interface_id'], ['node_nic_interfaces.id'], ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(
|
||||
['node_id'], ['nodes.id'], ondelete='CASCADE')
|
||||
)
|
||||
|
||||
op.create_table(
|
||||
'node_bond_interface_cluster_plugins',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column(
|
||||
'attributes', fields.JSON(), nullable=False, server_default='{}'),
|
||||
sa.Column('cluster_plugin_id', sa.Integer(), nullable=False),
|
||||
sa.Column('bond_id', sa.Integer(), nullable=False),
|
||||
sa.Column('node_id', sa.Integer(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.ForeignKeyConstraint(
|
||||
['cluster_plugin_id'],
|
||||
['cluster_plugins.id'],
|
||||
ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(
|
||||
['bond_id'], ['node_bond_interfaces.id'], ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(
|
||||
['node_id'], ['nodes.id'], ondelete='CASCADE')
|
||||
)
|
||||
|
||||
op.create_table(
|
||||
'node_cluster_plugins',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column(
|
||||
'attributes', fields.JSON(), nullable=False, server_default='{}'),
|
||||
sa.Column('cluster_plugin_id', sa.Integer(), nullable=False),
|
||||
sa.Column('node_id', sa.Integer(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.ForeignKeyConstraint(
|
||||
['cluster_plugin_id'],
|
||||
['cluster_plugins.id'],
|
||||
ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(
|
||||
['node_id'], ['nodes.id'], ondelete='CASCADE')
|
||||
)
|
||||
|
||||
|
||||
def downgrade_plugin_with_nics_and_nodes_attributes():
|
||||
op.drop_table('node_cluster_plugins')
|
||||
op.drop_table('node_bond_interface_cluster_plugins')
|
||||
op.drop_table('node_nic_interface_cluster_plugins')
|
||||
op.drop_column('releases', 'bond_attributes')
|
||||
op.drop_column('releases', 'nic_attributes')
|
||||
op.drop_column('node_bond_interfaces', 'attributes')
|
||||
op.drop_column('node_nic_interfaces', 'meta')
|
||||
op.drop_column('node_nic_interfaces', 'attributes')
|
||||
op.drop_column('plugins', 'node_attributes_metadata')
|
||||
op.drop_column('plugins', 'bond_attributes_metadata')
|
||||
op.drop_column('plugins', 'nic_attributes_metadata')
|
||||
|
|
|
@ -71,7 +71,12 @@ from nailgun.db.sqlalchemy.models.deployment_history import DeploymentHistory
|
|||
from nailgun.db.sqlalchemy.models.master_node_settings \
|
||||
import MasterNodeSettings
|
||||
|
||||
from nailgun.db.sqlalchemy.models.plugins import ClusterPlugins
|
||||
from nailgun.db.sqlalchemy.models.plugins import ClusterPlugin
|
||||
from nailgun.db.sqlalchemy.models.plugins import NodeClusterPlugin
|
||||
from nailgun.db.sqlalchemy.models.plugins \
|
||||
import NodeBondInterfaceClusterPlugin
|
||||
from nailgun.db.sqlalchemy.models.plugins \
|
||||
import NodeNICInterfaceClusterPlugin
|
||||
from nailgun.db.sqlalchemy.models.plugins import Plugin
|
||||
|
||||
from nailgun.db.sqlalchemy.models.openstack_config import OpenstackConfig
|
||||
|
|
|
@ -20,7 +20,7 @@ from sqlalchemy import String
|
|||
from sqlalchemy import Text
|
||||
from sqlalchemy import UniqueConstraint
|
||||
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.orm import relationship, backref
|
||||
|
||||
from nailgun.db.sqlalchemy.models.base import Base
|
||||
from nailgun.db.sqlalchemy.models.fields import JSON
|
||||
|
@ -28,7 +28,7 @@ from nailgun.db.sqlalchemy.models.mutable import MutableDict
|
|||
from nailgun.db.sqlalchemy.models.mutable import MutableList
|
||||
|
||||
|
||||
class ClusterPlugins(Base):
|
||||
class ClusterPlugin(Base):
|
||||
|
||||
__tablename__ = 'cluster_plugins'
|
||||
|
||||
|
@ -50,6 +50,105 @@ class ClusterPlugins(Base):
|
|||
attributes = Column(MutableDict.as_mutable(JSON),
|
||||
nullable=False,
|
||||
server_default='{}')
|
||||
cluster = relationship("Cluster", backref=backref(
|
||||
"cluster_plugins", cascade="delete"))
|
||||
plugin = relationship("Plugin", backref=backref(
|
||||
"cluster_plugins", cascade="delete"))
|
||||
|
||||
|
||||
class NodeNICInterfaceClusterPlugin(Base):
|
||||
"""Operates with NIC data from plugins
|
||||
|
||||
Example (fetch plugin data for specific interaface):
|
||||
db().query(
|
||||
NodeNICInterfaceClusterPlugin
|
||||
).join(
|
||||
models.ClusterPlugin,
|
||||
).filter(
|
||||
NodeNICInterfaceClusterPlugin.interface_id == interface_id
|
||||
).filter(
|
||||
models.ClusterPlugin.enabled.is_(True)).all()
|
||||
"""
|
||||
|
||||
__tablename__ = 'node_nic_interface_cluster_plugins'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
cluster_plugin_id = Column(
|
||||
Integer,
|
||||
ForeignKey('cluster_plugins.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
interface_id = Column(
|
||||
Integer,
|
||||
ForeignKey('node_nic_interfaces.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
node_id = Column(
|
||||
Integer,
|
||||
ForeignKey('nodes.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
attributes = Column(
|
||||
MutableDict.as_mutable(JSON),
|
||||
nullable=False,
|
||||
server_default='{}')
|
||||
node = relationship("Node", backref=backref(
|
||||
"node_nic_interface_cluster_plugins", cascade="delete"))
|
||||
|
||||
|
||||
class NodeBondInterfaceClusterPlugin(Base):
|
||||
"""Operates with Bond data from plugins
|
||||
|
||||
Example (fetch plugin data for specific bond):
|
||||
db().query(
|
||||
NodeBondInterfaceClusterPlugin
|
||||
).join(
|
||||
models.ClusterPlugin,
|
||||
).filter(
|
||||
NodeBondInterfaceClusterPlugin.bond_id == bond_id
|
||||
).filter(
|
||||
models.ClusterPlugin.enabled.is_(True)).all()
|
||||
"""
|
||||
|
||||
__tablename__ = 'node_bond_interface_cluster_plugins'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
cluster_plugin_id = Column(
|
||||
Integer,
|
||||
ForeignKey('cluster_plugins.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
bond_id = Column(
|
||||
Integer,
|
||||
ForeignKey('node_bond_interfaces.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
node_id = Column(
|
||||
Integer,
|
||||
ForeignKey('nodes.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
attributes = Column(
|
||||
MutableDict.as_mutable(JSON),
|
||||
nullable=False,
|
||||
server_default='{}')
|
||||
node = relationship("Node", backref=backref(
|
||||
"node_bond_interface_cluster_plugins", cascade="delete"))
|
||||
|
||||
|
||||
class NodeClusterPlugin(Base):
|
||||
|
||||
__tablename__ = 'node_cluster_plugins'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
cluster_plugin_id = Column(
|
||||
Integer,
|
||||
ForeignKey('cluster_plugins.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
node_id = Column(
|
||||
Integer,
|
||||
ForeignKey('nodes.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
attributes = Column(
|
||||
MutableDict.as_mutable(JSON),
|
||||
nullable=False,
|
||||
server_default='{}')
|
||||
node = relationship("Node", backref=backref(
|
||||
"node_cluster_plugins", cascade="delete"))
|
||||
|
||||
|
||||
class Plugin(Base):
|
||||
|
@ -83,6 +182,12 @@ class Plugin(Base):
|
|||
MutableDict.as_mutable(JSON), server_default='{}', nullable=False)
|
||||
network_roles_metadata = Column(
|
||||
MutableList.as_mutable(JSON), server_default='[]', nullable=False)
|
||||
nic_attributes_metadata = Column(
|
||||
MutableDict.as_mutable(JSON), server_default='{}', nullable=False)
|
||||
bond_attributes_metadata = Column(
|
||||
MutableDict.as_mutable(JSON), server_default='{}', nullable=False)
|
||||
node_attributes_metadata = Column(
|
||||
MutableDict.as_mutable(JSON), server_default='{}', nullable=False)
|
||||
components_metadata = Column(
|
||||
MutableList.as_mutable(JSON), server_default='[]')
|
||||
# TODO(apopovych): To support old plugins versions we need separate
|
||||
|
@ -98,7 +203,7 @@ class Plugin(Base):
|
|||
tasks = Column(
|
||||
MutableList.as_mutable(JSON), server_default='[]', nullable=False)
|
||||
clusters = relationship("Cluster",
|
||||
secondary=ClusterPlugins.__table__,
|
||||
secondary=ClusterPlugin.__table__,
|
||||
backref="plugins")
|
||||
links = relationship(
|
||||
"PluginLink", backref="plugin", cascade="delete")
|
||||
|
|
|
@ -70,6 +70,10 @@ class Release(Base):
|
|||
default=[], nullable=False, server_default='{}')
|
||||
node_attributes = Column(MutableDict.as_mutable(JSON), default={},
|
||||
server_default='{}', nullable=False)
|
||||
nic_attributes = Column(MutableDict.as_mutable(JSON), default={},
|
||||
server_default='{}', nullable=False)
|
||||
bond_attributes = Column(MutableDict.as_mutable(JSON), default={},
|
||||
server_default='{}', nullable=False)
|
||||
|
||||
# TODO(enchantner): get rid of properties
|
||||
|
||||
|
|
|
@ -156,6 +156,12 @@ class NodeNICInterface(Base):
|
|||
offloading_modes = Column(MutableList.as_mutable(JSON),
|
||||
default=[], nullable=False,
|
||||
server_default='[]')
|
||||
attributes = Column(
|
||||
MutableDict.as_mutable(JSON),
|
||||
default={}, server_default='{}', nullable=False)
|
||||
meta = Column(
|
||||
MutableDict.as_mutable(JSON),
|
||||
default={}, server_default='{}', nullable=False)
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
|
@ -220,6 +226,9 @@ class NodeBondInterface(Base):
|
|||
MutableDict.as_mutable(JSON), default={}, nullable=False,
|
||||
server_default='{}')
|
||||
slaves = relationship("NodeNICInterface", backref="bond")
|
||||
attributes = Column(
|
||||
MutableDict.as_mutable(JSON),
|
||||
default={}, server_default='{}', nullable=False)
|
||||
|
||||
@property
|
||||
def max_speed(self):
|
||||
|
|
|
@ -75,7 +75,7 @@ from nailgun.objects.node_group import NodeGroupCollection
|
|||
|
||||
from nailgun.objects.plugin import Plugin
|
||||
from nailgun.objects.plugin import PluginCollection
|
||||
from nailgun.objects.plugin import ClusterPlugins
|
||||
from nailgun.objects.plugin import ClusterPlugin
|
||||
|
||||
from nailgun.objects.plugin_link import PluginLink
|
||||
from nailgun.objects.plugin_link import PluginLinkCollection
|
||||
|
|
|
@ -41,7 +41,7 @@ from nailgun.logger import logger
|
|||
from nailgun.objects import DeploymentGraph
|
||||
from nailgun.objects import NailgunCollection
|
||||
from nailgun.objects import NailgunObject
|
||||
from nailgun.objects.plugin import ClusterPlugins
|
||||
from nailgun.objects.plugin import ClusterPlugin
|
||||
from nailgun.objects import Release
|
||||
from nailgun.objects.serializers.cluster import ClusterSerializer
|
||||
from nailgun.plugins.manager import PluginManager
|
||||
|
@ -185,7 +185,7 @@ class Cluster(NailgunObject):
|
|||
cls.add_pending_changes(
|
||||
cluster, consts.CLUSTER_CHANGES.vmware_attributes)
|
||||
|
||||
ClusterPlugins.add_compatible_plugins(cluster)
|
||||
ClusterPlugin.add_compatible_plugins(cluster)
|
||||
PluginManager.enable_plugins_by_components(cluster)
|
||||
|
||||
fire_callback_on_cluster_create(cluster, data)
|
||||
|
|
|
@ -48,7 +48,7 @@ class Plugin(NailgunObject):
|
|||
plugin_adapter = wrap_plugin(new_plugin)
|
||||
cls.update(new_plugin, plugin_adapter.get_metadata())
|
||||
|
||||
ClusterPlugins.add_compatible_clusters(new_plugin)
|
||||
ClusterPlugin.add_compatible_clusters(new_plugin)
|
||||
|
||||
return new_plugin
|
||||
|
||||
|
@ -132,9 +132,9 @@ class PluginCollection(NailgunCollection):
|
|||
return sorted(release_plugins, key=lambda plugin: plugin.name)
|
||||
|
||||
|
||||
class ClusterPlugins(NailgunObject):
|
||||
class ClusterPlugin(NailgunObject):
|
||||
|
||||
model = models.ClusterPlugins
|
||||
model = models.ClusterPlugin
|
||||
|
||||
@classmethod
|
||||
def is_compatible(cls, cluster, plugin):
|
||||
|
|
|
@ -286,7 +286,7 @@ class DeploymentMultinodeSerializer(object):
|
|||
:param attributes: the serialized attributes
|
||||
:param cluster: the cluster object
|
||||
"""
|
||||
plugins = objects.ClusterPlugins.get_enabled(cluster.id)
|
||||
plugins = objects.ClusterPlugin.get_enabled(cluster.id)
|
||||
attributes['plugins'] = [
|
||||
self.serialize_plugin(cluster, p) for p in plugins
|
||||
]
|
||||
|
|
|
@ -164,6 +164,18 @@ class PluginAdapterBase(object):
|
|||
def components_metadata(self):
|
||||
return self.plugin.components_metadata
|
||||
|
||||
@property
|
||||
def bond_attributes_metadata(self):
|
||||
return self.plugin.bond_attributes_metadata
|
||||
|
||||
@property
|
||||
def nic_attributes_metadata(self):
|
||||
return self.plugin.bond_attributes_metadata
|
||||
|
||||
@property
|
||||
def node_attributes_metadata(self):
|
||||
return self.plugin.node_attributes_metadata
|
||||
|
||||
@property
|
||||
def releases(self):
|
||||
return self.plugin.releases
|
||||
|
@ -360,6 +372,12 @@ class PluginAdapterV4(PluginAdapterV3):
|
|||
class PluginAdapterV5(PluginAdapterV4):
|
||||
"""Plugin wrapper class for package version 5.0.0"""
|
||||
|
||||
def __init__(self, plugin):
|
||||
super(PluginAdapterV5, self).__init__(plugin)
|
||||
self.db_cfg_mapping['nic_attributes_metadata'] = 'nic_config.yaml'
|
||||
self.db_cfg_mapping['bond_attributes_metadata'] = 'bond_config.yaml'
|
||||
self.db_cfg_mapping['node_attributes_metadata'] = 'node_config.yaml'
|
||||
|
||||
|
||||
__version_mapping = {
|
||||
'1.0.': PluginAdapterV1,
|
||||
|
|
|
@ -18,7 +18,7 @@ from six.moves import map
|
|||
|
||||
from nailgun import errors
|
||||
from nailgun.logger import logger
|
||||
from nailgun.objects.plugin import ClusterPlugins
|
||||
from nailgun.objects.plugin import ClusterPlugin
|
||||
from nailgun.objects.plugin import Plugin
|
||||
from nailgun.objects.plugin import PluginCollection
|
||||
from nailgun.plugins.adapters import wrap_plugin
|
||||
|
@ -46,7 +46,6 @@ class PluginManager(object):
|
|||
for k in list(attributes):
|
||||
if cls.is_plugin_data(attributes[k]):
|
||||
plugins[k] = attributes.pop(k)['metadata']
|
||||
cluster.attributes.editable.pop(k, None)
|
||||
|
||||
for container in six.itervalues(plugins):
|
||||
default = container.get('default', False)
|
||||
|
@ -60,7 +59,7 @@ class PluginManager(object):
|
|||
continue
|
||||
enabled = container['enabled']\
|
||||
and plugin_id == container['chosen_id']
|
||||
ClusterPlugins.set_attributes(
|
||||
ClusterPlugin.set_attributes(
|
||||
cluster.id, plugin.id, enabled=enabled,
|
||||
attrs=attrs if enabled or default else None
|
||||
)
|
||||
|
@ -80,7 +79,7 @@ class PluginManager(object):
|
|||
:rtype: dict
|
||||
"""
|
||||
plugins_attributes = {}
|
||||
for plugin in ClusterPlugins.get_connected_plugins_data(cluster.id):
|
||||
for plugin in ClusterPlugin.get_connected_plugins_data(cluster.id):
|
||||
db_plugin = Plugin.get_by_uid(plugin.id)
|
||||
plugin_adapter = wrap_plugin(db_plugin)
|
||||
default_attrs = plugin_adapter.attributes_metadata
|
||||
|
@ -182,7 +181,7 @@ class PluginManager(object):
|
|||
@classmethod
|
||||
def get_enabled_plugins(cls, cluster):
|
||||
return [wrap_plugin(plugin)
|
||||
for plugin in ClusterPlugins.get_enabled(cluster.id)]
|
||||
for plugin in ClusterPlugin.get_enabled(cluster.id)]
|
||||
|
||||
@classmethod
|
||||
def get_network_roles(cls, cluster, merge_policy):
|
||||
|
@ -196,7 +195,7 @@ class PluginManager(object):
|
|||
all_roles = dict((role['id'], role) for role in instance_roles)
|
||||
conflict_roles = dict()
|
||||
|
||||
for plugin in ClusterPlugins.get_enabled(cluster.id):
|
||||
for plugin in ClusterPlugin.get_enabled(cluster.id):
|
||||
for role in plugin.network_roles_metadata:
|
||||
role_id = role['id']
|
||||
if role_id in all_roles:
|
||||
|
@ -226,7 +225,7 @@ class PluginManager(object):
|
|||
deployment_tasks = []
|
||||
processed_tasks = {}
|
||||
|
||||
enabled_plugins = ClusterPlugins.get_enabled(cluster.id)
|
||||
enabled_plugins = ClusterPlugin.get_enabled(cluster.id)
|
||||
for plugin_adapter in map(wrap_plugin, enabled_plugins):
|
||||
depl_tasks = plugin_adapter.get_deployment_tasks(graph_type)
|
||||
|
||||
|
@ -252,7 +251,7 @@ class PluginManager(object):
|
|||
result = {}
|
||||
core_roles = set(cluster.release.roles_metadata)
|
||||
|
||||
for plugin_db in ClusterPlugins.get_enabled(cluster.id):
|
||||
for plugin_db in ClusterPlugin.get_enabled(cluster.id):
|
||||
plugin_roles = wrap_plugin(plugin_db).normalized_roles_metadata
|
||||
|
||||
# we should check all possible cases of roles intersection
|
||||
|
@ -293,7 +292,7 @@ class PluginManager(object):
|
|||
release_volumes_ids = [v['id'] for v in release_volumes]
|
||||
processed_volumes = {}
|
||||
|
||||
enabled_plugins = ClusterPlugins.get_enabled(cluster.id)
|
||||
enabled_plugins = ClusterPlugin.get_enabled(cluster.id)
|
||||
for plugin_adapter in map(wrap_plugin, enabled_plugins):
|
||||
metadata = plugin_adapter.volumes_metadata
|
||||
|
||||
|
@ -383,7 +382,7 @@ class PluginManager(object):
|
|||
cluster_components = set(cluster.components)
|
||||
plugin_ids = [p.id for p in PluginCollection.all_newest()]
|
||||
|
||||
for plugin in ClusterPlugins.get_connected_plugins(
|
||||
for plugin in ClusterPlugin.get_connected_plugins(
|
||||
cluster, plugin_ids):
|
||||
plugin_adapter = wrap_plugin(plugin)
|
||||
plugin_components = set(
|
||||
|
@ -391,7 +390,7 @@ class PluginManager(object):
|
|||
for component in plugin_adapter.components_metadata)
|
||||
|
||||
if cluster_components & plugin_components:
|
||||
ClusterPlugins.set_attributes(
|
||||
ClusterPlugin.set_attributes(
|
||||
cluster.id, plugin.id, enabled=True)
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -38,7 +38,7 @@ from nailgun.db.sqlalchemy.models import Node
|
|||
from nailgun.db.sqlalchemy.models import Release
|
||||
from nailgun.extensions.network_manager import connectivity_check
|
||||
from nailgun.extensions.network_manager import utils as net_utils
|
||||
from nailgun.objects.plugin import ClusterPlugins
|
||||
from nailgun.objects.plugin import ClusterPlugin
|
||||
from nailgun.task.helpers import TaskHelper
|
||||
from nailgun.utils import logs as logs_utils
|
||||
from nailgun.utils import reverse
|
||||
|
@ -600,7 +600,7 @@ class NailgunReceiver(object):
|
|||
|
||||
if task.name != consts.TASK_NAMES.provision:
|
||||
plugins_msg = cls._make_plugins_success_message(
|
||||
ClusterPlugins.get_enabled(task.cluster.id))
|
||||
ClusterPlugin.get_enabled(task.cluster.id))
|
||||
if plugins_msg:
|
||||
message = '{0}\n\n{1}'.format(message, plugins_msg)
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ from nailgun.objects import Cluster
|
|||
from nailgun.objects import ClusterCollection
|
||||
from nailgun.objects import MasterNodeSettings
|
||||
from nailgun.objects import NodeCollection
|
||||
from nailgun.objects.plugin import ClusterPlugins
|
||||
from nailgun.objects.plugin import ClusterPlugin
|
||||
from nailgun.settings import settings
|
||||
from nailgun.statistics.utils import get_attr_value
|
||||
from nailgun.statistics.utils import WhiteListRule
|
||||
|
@ -179,6 +179,12 @@ class InstallationInfo(object):
|
|||
WhiteListRule(('network_roles_metadata',),
|
||||
'network_roles_metadata', None),
|
||||
WhiteListRule(('components_metadata',), 'components_metadata', None),
|
||||
WhiteListRule(
|
||||
('nic_attributes_metadata',), 'nic_attributes_metadata', None),
|
||||
WhiteListRule(
|
||||
('bond_attributes_metadata',), 'bond_attributes_metadata', None),
|
||||
WhiteListRule(
|
||||
('node_attributes_metadata',), 'node_attributes_metadata', None),
|
||||
WhiteListRule(('deployment_tasks',), 'deployment_tasks', None),
|
||||
WhiteListRule(('tasks',), 'tasks', None),
|
||||
)
|
||||
|
@ -286,14 +292,15 @@ class InstallationInfo(object):
|
|||
'network_configuration': self.get_network_configuration_info(
|
||||
cluster),
|
||||
'installed_plugins': self.get_cluster_plugins_info(cluster),
|
||||
'components': cluster.components
|
||||
'components': cluster.components,
|
||||
'cluster_plugins': cluster.cluster_plugins
|
||||
}
|
||||
clusters_info.append(cluster_info)
|
||||
return clusters_info
|
||||
|
||||
def get_cluster_plugins_info(self, cluster):
|
||||
plugins_info = []
|
||||
for plugin_inst in ClusterPlugins.get_enabled(cluster.id):
|
||||
for plugin_inst in ClusterPlugin.get_enabled(cluster.id):
|
||||
plugin_info = self.get_attributes(plugin_inst.__dict__,
|
||||
self.plugin_info_white_list)
|
||||
plugins_info.append(plugin_info)
|
||||
|
|
|
@ -65,7 +65,7 @@ from nailgun.db.sqlalchemy.models import Task
|
|||
|
||||
# here come objects
|
||||
from nailgun.objects import Cluster
|
||||
from nailgun.objects import ClusterPlugins
|
||||
from nailgun.objects import ClusterPlugin
|
||||
from nailgun.objects import MasterNodeSettings
|
||||
from nailgun.objects import NetworkGroup
|
||||
from nailgun.objects import Node
|
||||
|
@ -542,6 +542,9 @@ class EnvironmentManager(object):
|
|||
deployment_tasks = plugin_data.pop('deployment_tasks', None)
|
||||
tasks = plugin_data.pop('tasks', None)
|
||||
components = plugin_data.pop('components', None)
|
||||
nic_config = plugin_data.pop('nic_config', None)
|
||||
bond_config = plugin_data.pop('bond_config', None)
|
||||
node_config = plugin_data.pop('node_config', None)
|
||||
|
||||
mocked_metadata = {
|
||||
'metadata.yaml': plugin_data,
|
||||
|
@ -551,7 +554,10 @@ class EnvironmentManager(object):
|
|||
'network_roles.yaml': network_roles,
|
||||
'deployment_tasks.yaml': deployment_tasks,
|
||||
'tasks.yaml': tasks,
|
||||
'components.yaml': components
|
||||
'components.yaml': components,
|
||||
'nic_config.yaml': nic_config,
|
||||
'bond_config.yaml': bond_config,
|
||||
'node_config.yaml': node_config
|
||||
}
|
||||
|
||||
m_load_conf.side_effect = lambda key: copy.deepcopy(
|
||||
|
@ -572,7 +578,7 @@ class EnvironmentManager(object):
|
|||
# Enable plugin for specific cluster
|
||||
if cluster:
|
||||
cluster.plugins.append(plugin)
|
||||
ClusterPlugins.set_attributes(
|
||||
ClusterPlugin.set_attributes(
|
||||
cluster.id, plugin.id, enabled=enabled,
|
||||
attrs=plugin.attributes_metadata or {}
|
||||
)
|
||||
|
@ -751,6 +757,48 @@ class EnvironmentManager(object):
|
|||
'weight': kwargs.get('weight', 25),
|
||||
'label': kwargs.get('label', 'label')}}}
|
||||
|
||||
def get_default_plugin_nic_config(self, **kwargs):
|
||||
nic_attributes = {
|
||||
'plugin_name_text': {
|
||||
'value': 'value',
|
||||
'type': 'text',
|
||||
'description': 'Some description',
|
||||
'weight': 25,
|
||||
'label': 'label'
|
||||
}
|
||||
}
|
||||
|
||||
nic_attributes.update(kwargs)
|
||||
return nic_attributes
|
||||
|
||||
def get_default_plugin_bond_config(self, **kwargs):
|
||||
bond_attributes = {
|
||||
'plugin_name_text': {
|
||||
'value': 'value',
|
||||
'type': 'text',
|
||||
'description': 'Some description',
|
||||
'weight': 25,
|
||||
'label': 'label'
|
||||
}
|
||||
}
|
||||
|
||||
bond_attributes.update(kwargs)
|
||||
return bond_attributes
|
||||
|
||||
def get_default_plugin_node_config(self, **kwargs):
|
||||
node_attributes = {
|
||||
'plugin_name_text': {
|
||||
'value': 'value',
|
||||
'type': 'text',
|
||||
'description': 'Some description',
|
||||
'weight': 25,
|
||||
'label': 'label'
|
||||
}
|
||||
}
|
||||
|
||||
node_attributes.update(kwargs)
|
||||
return node_attributes
|
||||
|
||||
def get_default_plugin_node_roles_config(self, **kwargs):
|
||||
node_roles = {
|
||||
'testing_plugin': {
|
||||
|
|
|
@ -140,9 +140,9 @@ class TestClusterRolesHandler(base.BaseTestCase):
|
|||
plugin_data['roles_metadata'] = self.ROLES
|
||||
plugin = objects.Plugin.create(plugin_data)
|
||||
self.cluster.plugins.append(plugin)
|
||||
objects.ClusterPlugins.set_attributes(self.cluster.id,
|
||||
plugin.id,
|
||||
enabled=True)
|
||||
objects.ClusterPlugin.set_attributes(self.cluster.id,
|
||||
plugin.id,
|
||||
enabled=True)
|
||||
self.db.flush()
|
||||
|
||||
roles = self.app.get(
|
||||
|
@ -164,9 +164,9 @@ class TestClusterRolesHandler(base.BaseTestCase):
|
|||
plugin_data['volumes_metadata'] = self.VOLUMES
|
||||
plugin = objects.Plugin.create(plugin_data)
|
||||
self.cluster.plugins.append(plugin)
|
||||
objects.ClusterPlugins.set_attributes(self.cluster.id,
|
||||
plugin.id,
|
||||
enabled=True)
|
||||
objects.ClusterPlugin.set_attributes(self.cluster.id,
|
||||
plugin.id,
|
||||
enabled=True)
|
||||
self.db.flush()
|
||||
plugin_adapter = adapters.wrap_plugin(plugin)
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import uuid
|
|||
|
||||
from nailgun import consts
|
||||
from nailgun import errors
|
||||
from nailgun.objects import ClusterPlugins
|
||||
from nailgun.objects import ClusterPlugin
|
||||
from nailgun.plugins.adapters import PluginAdapterV3
|
||||
from nailgun.plugins.manager import PluginManager
|
||||
from nailgun.test import base
|
||||
|
@ -282,7 +282,7 @@ class TestPluginManager(base.BaseIntegrationTest):
|
|||
'hypervisor:test_hypervisor',
|
||||
'storage:test_storage']})
|
||||
|
||||
enabled_plugins = ClusterPlugins.get_enabled(cluster.id)
|
||||
enabled_plugins = ClusterPlugin.get_enabled(cluster.id)
|
||||
self.assertItemsEqual([plugin], enabled_plugins)
|
||||
|
||||
def test_get_plugins_attributes_when_cluster_is_locked(self):
|
||||
|
@ -530,7 +530,7 @@ class TestClusterPluginIntegration(base.BaseTestCase):
|
|||
plugin_a = self._create_plugin(**self._compat_meta)
|
||||
self._create_plugin(**self._uncompat_meta)
|
||||
|
||||
compat_plugins = ClusterPlugins.get_compatible_plugins(self.cluster)
|
||||
compat_plugins = ClusterPlugin.get_compatible_plugins(self.cluster)
|
||||
self.assertItemsEqual(compat_plugins, [plugin_a])
|
||||
|
||||
def test_get_compatible_plugins_for_new_cluster(self):
|
||||
|
@ -544,18 +544,18 @@ class TestClusterPluginIntegration(base.BaseTestCase):
|
|||
'mode': consts.CLUSTER_MODES.ha_compact,
|
||||
})
|
||||
|
||||
compat_plugins = ClusterPlugins.get_compatible_plugins(cluster)
|
||||
compat_plugins = ClusterPlugin.get_compatible_plugins(cluster)
|
||||
self.assertItemsEqual(compat_plugins, [plugin_a, plugin_b])
|
||||
|
||||
def test_get_enabled_plugins(self):
|
||||
plugin_a = self._create_plugin(**self._compat_meta)
|
||||
plugin_b = self._create_plugin(**self._compat_meta)
|
||||
|
||||
ClusterPlugins.set_attributes(
|
||||
ClusterPlugin.set_attributes(
|
||||
self.cluster.id, plugin_a.id, enabled=True)
|
||||
|
||||
compat_plugins = ClusterPlugins.get_compatible_plugins(self.cluster)
|
||||
compat_plugins = ClusterPlugin.get_compatible_plugins(self.cluster)
|
||||
self.assertItemsEqual(compat_plugins, [plugin_a, plugin_b])
|
||||
|
||||
enabled_plugins = ClusterPlugins.get_enabled(self.cluster.id)
|
||||
enabled_plugins = ClusterPlugin.get_enabled(self.cluster.id)
|
||||
self.assertItemsEqual(enabled_plugins, [plugin_a])
|
||||
|
|
|
@ -145,21 +145,21 @@ class TestPluginsApi(BasePluginTest):
|
|||
cluster = self.create_cluster()
|
||||
self.assertItemsEqual(
|
||||
[],
|
||||
objects.ClusterPlugins.get_enabled(cluster.id)
|
||||
objects.ClusterPlugin.get_enabled(cluster.id)
|
||||
)
|
||||
|
||||
resp = self.enable_plugin(cluster, plugin.name, plugin.id)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertItemsEqual(
|
||||
[plugin],
|
||||
objects.ClusterPlugins.get_enabled(cluster.id)
|
||||
objects.ClusterPlugin.get_enabled(cluster.id)
|
||||
)
|
||||
|
||||
resp = self.disable_plugin(cluster, plugin.name)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertItemsEqual(
|
||||
[],
|
||||
objects.ClusterPlugins.get_enabled(cluster.id)
|
||||
objects.ClusterPlugin.get_enabled(cluster.id)
|
||||
)
|
||||
|
||||
def test_delete_plugin(self):
|
||||
|
@ -236,10 +236,10 @@ class TestPluginsApi(BasePluginTest):
|
|||
return response.json_body['id']
|
||||
|
||||
def get_num_enabled(cluster_id):
|
||||
return objects.ClusterPlugins.get_enabled(cluster_id).count()
|
||||
return objects.ClusterPlugin.get_enabled(cluster_id).count()
|
||||
|
||||
def get_enabled_version(cluster_id):
|
||||
plugin = objects.ClusterPlugins.get_enabled(cluster_id).first()
|
||||
plugin = objects.ClusterPlugin.get_enabled(cluster_id).first()
|
||||
return plugin.version
|
||||
|
||||
plugin_ids = []
|
||||
|
|
|
@ -520,7 +520,9 @@ class TestInstallationInfo(BaseTestCase):
|
|||
# Related tables
|
||||
'clusters', 'cluster_changes',
|
||||
'nodegroups', 'ip_addrs', 'node_nic_interfaces',
|
||||
'node_bond_interfaces', 'network_groups'
|
||||
'node_bond_interfaces', 'network_groups',
|
||||
'node_nic_interface_cluster_plugins',
|
||||
'node_bond_interface_cluster_plugins', 'node_cluster_plugins'
|
||||
)
|
||||
for field in remove_fields:
|
||||
node_schema.pop(field)
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
|
||||
import alembic
|
||||
from oslo_serialization import jsonutils
|
||||
import sqlalchemy as sa
|
||||
|
@ -68,10 +70,61 @@ def prepare():
|
|||
meta.tables['releases'].insert(),
|
||||
[{
|
||||
'name': 'test_name',
|
||||
'version': '2015.1-8.0',
|
||||
'version': '2015.1-10.0',
|
||||
'operating_system': 'ubuntu',
|
||||
'state': 'available',
|
||||
'deployment_tasks': jsonutils.dumps(JSON_TASKS),
|
||||
'roles': jsonutils.dumps([
|
||||
'controller',
|
||||
'compute',
|
||||
'virt',
|
||||
'compute-vmware',
|
||||
'ironic',
|
||||
'cinder',
|
||||
'cinder-block-device',
|
||||
'cinder-vmware',
|
||||
'ceph-osd',
|
||||
'mongo',
|
||||
'base-os',
|
||||
]),
|
||||
'roles_metadata': jsonutils.dumps({
|
||||
'controller': {
|
||||
'name': 'Controller',
|
||||
},
|
||||
'compute': {
|
||||
'name': 'Compute',
|
||||
},
|
||||
'virt': {
|
||||
'name': 'Virtual',
|
||||
},
|
||||
'compute-vmware': {
|
||||
'name': 'Compute VMware',
|
||||
},
|
||||
'ironic': {
|
||||
'name': 'Ironic',
|
||||
},
|
||||
'cinder': {
|
||||
'name': 'Cinder',
|
||||
},
|
||||
'cinder-block-device': {
|
||||
'name': 'Cinder Block Device',
|
||||
},
|
||||
'cinder-vmware': {
|
||||
'name': 'Cinder Proxy to VMware Datastore',
|
||||
},
|
||||
'ceph-osd': {
|
||||
'name': 'Ceph OSD',
|
||||
},
|
||||
'mongo': {
|
||||
'name': 'Telemetry - MongoDB',
|
||||
},
|
||||
'base-os': {
|
||||
'name': 'Operating System',
|
||||
}
|
||||
}),
|
||||
'is_deployable': True
|
||||
}])
|
||||
|
||||
release_id = result.inserted_primary_key[0]
|
||||
|
||||
cluster_ids = []
|
||||
|
@ -85,10 +138,25 @@ def prepare():
|
|||
'status': 'new',
|
||||
'net_provider': 'neutron',
|
||||
'grouping': 'roles',
|
||||
'fuel_version': '10.0'
|
||||
'fuel_version': '10.0',
|
||||
'deployment_tasks': jsonutils.dumps(JSON_TASKS)
|
||||
}])
|
||||
cluster_ids.append(result.inserted_primary_key[0])
|
||||
|
||||
result = db.execute(
|
||||
meta.tables['nodes'].insert(),
|
||||
[{
|
||||
'uuid': '26b508d0-0d76-4159-bce9-f67ec2765480',
|
||||
'cluster_id': None,
|
||||
'group_id': None,
|
||||
'status': 'discover',
|
||||
'meta': '{}',
|
||||
'mac': 'aa:aa:aa:aa:aa:aa',
|
||||
'timestamp': datetime.datetime.utcnow(),
|
||||
}]
|
||||
)
|
||||
node_id = result.inserted_primary_key[0]
|
||||
|
||||
result = db.execute(
|
||||
meta.tables['plugins'].insert(),
|
||||
[{
|
||||
|
@ -97,7 +165,7 @@ def prepare():
|
|||
'version': '2.0.0',
|
||||
'description': 'Test plugin A for Fuel',
|
||||
'homepage': 'http://fuel_plugins.test_plugin.com',
|
||||
'package_version': '4.0.0',
|
||||
'package_version': '5.0.0',
|
||||
'groups': jsonutils.dumps(['tgroup']),
|
||||
'authors': jsonutils.dumps(['tauthor']),
|
||||
'licenses': jsonutils.dumps(['tlicense']),
|
||||
|
@ -105,7 +173,7 @@ def prepare():
|
|||
{'repository_path': 'repositories/ubuntu'}
|
||||
]),
|
||||
'deployment_tasks': jsonutils.dumps(JSON_TASKS),
|
||||
'fuel_version': jsonutils.dumps(['8.0']),
|
||||
'fuel_version': jsonutils.dumps(['10.0']),
|
||||
'network_roles_metadata': jsonutils.dumps([{
|
||||
'id': 'admin/vip',
|
||||
'default_mapping': 'fuelweb_admin',
|
||||
|
@ -136,14 +204,14 @@ def prepare():
|
|||
'version': '2.0.0',
|
||||
'description': 'Test plugin B for Fuel',
|
||||
'homepage': 'http://fuel_plugins.test_plugin.com',
|
||||
'package_version': '4.0.0',
|
||||
'package_version': '5.0.0',
|
||||
'groups': jsonutils.dumps(['tgroup']),
|
||||
'authors': jsonutils.dumps(['tauthor']),
|
||||
'licenses': jsonutils.dumps(['tlicense']),
|
||||
'releases': jsonutils.dumps([
|
||||
{'repository_path': 'repositories/ubuntu'}
|
||||
]),
|
||||
'fuel_version': jsonutils.dumps(['8.0']),
|
||||
'fuel_version': jsonutils.dumps(['10.0']),
|
||||
'network_roles_metadata': jsonutils.dumps([{
|
||||
'id': 'admin/vip',
|
||||
'default_mapping': 'fuelweb_admin',
|
||||
|
@ -196,6 +264,14 @@ def prepare():
|
|||
]
|
||||
)
|
||||
|
||||
db.execute(
|
||||
meta.tables['cluster_plugins'].insert(),
|
||||
[
|
||||
{'cluster_id': cluster_ids[0], 'plugin_id': plugin_a_id},
|
||||
{'cluster_id': cluster_ids[0], 'plugin_id': plugin_b_id}
|
||||
]
|
||||
)
|
||||
|
||||
db.execute(
|
||||
meta.tables['plugin_links'].insert(),
|
||||
[
|
||||
|
@ -217,6 +293,36 @@ def prepare():
|
|||
]
|
||||
)
|
||||
|
||||
db.execute(
|
||||
meta.tables['node_nic_interfaces'].insert(),
|
||||
[{
|
||||
'id': 1,
|
||||
'node_id': node_id,
|
||||
'name': 'test_interface',
|
||||
'mac': '00:00:00:00:00:01',
|
||||
'max_speed': 200,
|
||||
'current_speed': 100,
|
||||
'ip_addr': '10.20.0.2',
|
||||
'netmask': '255.255.255.0',
|
||||
'state': 'test_state',
|
||||
'interface_properties': jsonutils.dumps(
|
||||
{'test_property': 'test_value'}),
|
||||
'driver': 'test_driver',
|
||||
'bus_info': 'some_test_info'
|
||||
}]
|
||||
)
|
||||
|
||||
db.execute(
|
||||
meta.tables['node_bond_interfaces'].insert(),
|
||||
[{
|
||||
'node_id': node_id,
|
||||
'name': 'test_bond_interface',
|
||||
'mode': 'active-backup',
|
||||
'bond_properties': jsonutils.dumps(
|
||||
{'test_property': 'test_value'})
|
||||
}]
|
||||
)
|
||||
|
||||
db.commit()
|
||||
|
||||
|
||||
|
@ -235,3 +341,83 @@ class TestPluginLinksConstraints(base.BaseAlembicMigrationTest):
|
|||
[sa.func.count(self.meta.tables['cluster_plugin_links'].c.id)]
|
||||
)).fetchone()[0]
|
||||
self.assertEqual(links_count, 2)
|
||||
|
||||
|
||||
class TestPluginAttributesMigration(base.BaseAlembicMigrationTest):
|
||||
|
||||
def test_new_attributes_fields_exist(self):
|
||||
node_bond_interfaces_table = self.meta.tables['node_bond_interfaces']
|
||||
node_nic_interfaces_table = self.meta.tables['node_nic_interfaces']
|
||||
plugins_table = self.meta.tables['plugins']
|
||||
releases_table = self.meta.tables['releases']
|
||||
columns = [
|
||||
plugins_table.c.nic_attributes_metadata,
|
||||
plugins_table.c.bond_attributes_metadata,
|
||||
plugins_table.c.node_attributes_metadata,
|
||||
node_bond_interfaces_table.c.attributes,
|
||||
node_nic_interfaces_table.c.attributes,
|
||||
node_nic_interfaces_table.c.meta,
|
||||
releases_table.c.nic_attributes,
|
||||
releases_table.c.bond_attributes
|
||||
]
|
||||
|
||||
for column in columns:
|
||||
db_values = db.execute(sa.select([column])).fetchone()
|
||||
for db_value in db_values:
|
||||
self.assertEqual(db_value, '{}')
|
||||
|
||||
def test_node_nic_interface_cluster_plugins_creation(self):
|
||||
node_nic_interface_cluster_plugins = \
|
||||
self.meta.tables['node_nic_interface_cluster_plugins']
|
||||
cluster_plugins = self.meta.tables['cluster_plugins']
|
||||
node_nic_interfaces = self.meta.tables['node_nic_interfaces']
|
||||
nodes = self.meta.tables['nodes']
|
||||
|
||||
cluster_plugin_id = db.execute(sa.select([cluster_plugins])).scalar()
|
||||
interface_id = db.execute(sa.select([node_nic_interfaces])).scalar()
|
||||
node_id = db.execute(sa.select([nodes])).scalar()
|
||||
|
||||
db.execute(
|
||||
node_nic_interface_cluster_plugins.insert(),
|
||||
[{
|
||||
'cluster_plugin_id': cluster_plugin_id,
|
||||
'interface_id': interface_id,
|
||||
'node_id': node_id,
|
||||
'attributes': jsonutils.dumps({'test_attr': 'test'})
|
||||
}])
|
||||
|
||||
def test_node_bond_interface_cluster_plugins_creation(self):
|
||||
node_bond_interface_cluster_plugins = \
|
||||
self.meta.tables['node_bond_interface_cluster_plugins']
|
||||
cluster_plugins = self.meta.tables['cluster_plugins']
|
||||
node_bond_interfaces = self.meta.tables['node_bond_interfaces']
|
||||
nodes = self.meta.tables['nodes']
|
||||
|
||||
cluster_plugin_id = db.execute(sa.select([cluster_plugins])).scalar()
|
||||
bond_id = db.execute(sa.select([node_bond_interfaces])).scalar()
|
||||
node_id = db.execute(sa.select([nodes])).scalar()
|
||||
|
||||
db.execute(
|
||||
node_bond_interface_cluster_plugins.insert(),
|
||||
[{
|
||||
'cluster_plugin_id': cluster_plugin_id,
|
||||
'bond_id': bond_id,
|
||||
'node_id': node_id,
|
||||
'attributes': jsonutils.dumps({'test_attr': 'test'})
|
||||
}])
|
||||
|
||||
def test_node_cluster_plugins_creation(self):
|
||||
node_cluster_plugins = self.meta.tables['node_cluster_plugins']
|
||||
cluster_plugins = self.meta.tables['cluster_plugins']
|
||||
nodes = self.meta.tables['nodes']
|
||||
|
||||
cluster_plugin_id = db.execute(sa.select([cluster_plugins])).scalar()
|
||||
node_id = db.execute(sa.select([nodes])).scalar()
|
||||
|
||||
db.execute(
|
||||
node_cluster_plugins.insert(),
|
||||
[{
|
||||
'cluster_plugin_id': cluster_plugin_id,
|
||||
'node_id': node_id,
|
||||
'attributes': jsonutils.dumps({'test_attr': 'test'})
|
||||
}])
|
||||
|
|
|
@ -385,7 +385,7 @@ class TestNeutronConfigInternalFloatingNames(base.BaseAlembicMigrationTest):
|
|||
self.assertEqual('net04_ext', neutron_config['floating_name'])
|
||||
|
||||
|
||||
class TestClusterPluginsMigration(base.BaseAlembicMigrationTest):
|
||||
class TestClusterPluginMigration(base.BaseAlembicMigrationTest):
|
||||
|
||||
def _get_enabled(self, plugin_name):
|
||||
plugins = self.meta.tables['plugins']
|
||||
|
|
|
@ -267,7 +267,7 @@ def prepare():
|
|||
'editable': jsonutils.dumps(editable)
|
||||
}])
|
||||
|
||||
db.execute(
|
||||
result = db.execute(
|
||||
meta.tables['nodes'].insert(),
|
||||
[{
|
||||
'uuid': '26b508d0-0d76-4159-bce9-f67ec2765480',
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from nailgun import consts
|
||||
from nailgun.objects import ClusterPlugins
|
||||
from nailgun.objects import ClusterPlugin
|
||||
from nailgun.objects import Plugin
|
||||
from nailgun.objects import PluginCollection
|
||||
from nailgun.test import base
|
||||
|
@ -93,7 +93,7 @@ class TestPluginCollection(ExtraFunctions):
|
|||
self.assertNotEqual(plugin.name, 'incompatible_plugin')
|
||||
|
||||
|
||||
class TestClusterPlugins(ExtraFunctions):
|
||||
class TestClusterPlugin(ExtraFunctions):
|
||||
|
||||
def test_connect_to_cluster(self):
|
||||
meta = base.reflect_db_metadata()
|
||||
|
@ -109,8 +109,8 @@ class TestClusterPlugins(ExtraFunctions):
|
|||
self._create_test_plugins()
|
||||
cluster = self._create_test_cluster()
|
||||
|
||||
plugin = ClusterPlugins.get_connected_plugins(cluster).first()
|
||||
ClusterPlugins.set_attributes(cluster.id, plugin.id, enabled=True)
|
||||
plugin = ClusterPlugin.get_connected_plugins(cluster).first()
|
||||
ClusterPlugin.set_attributes(cluster.id, plugin.id, enabled=True)
|
||||
|
||||
columns = meta.tables['cluster_plugins'].c
|
||||
enabled = self.db.execute(
|
||||
|
@ -124,21 +124,21 @@ class TestClusterPlugins(ExtraFunctions):
|
|||
self._create_test_plugins()
|
||||
cluster = self._create_test_cluster()
|
||||
number_of_connected_plugins_data_items =\
|
||||
ClusterPlugins.get_connected_plugins_data(cluster.id).count()
|
||||
ClusterPlugin.get_connected_plugins_data(cluster.id).count()
|
||||
self.assertEqual(7, number_of_connected_plugins_data_items)
|
||||
|
||||
def test_get_all_connected_plugins(self):
|
||||
self._create_test_plugins()
|
||||
cluster = self._create_test_cluster()
|
||||
number_of_connected_plugins =\
|
||||
ClusterPlugins.get_connected_plugins(cluster).count()
|
||||
ClusterPlugin.get_connected_plugins(cluster).count()
|
||||
self.assertEqual(7, number_of_connected_plugins)
|
||||
|
||||
def test_get_connected_for_specific_plugins(self):
|
||||
plugin_ids = self._create_test_plugins()
|
||||
cluster = self._create_test_cluster()
|
||||
number_of_connected_plugins =\
|
||||
ClusterPlugins.get_connected_plugins(
|
||||
ClusterPlugin.get_connected_plugins(
|
||||
cluster, plugin_ids[1:]).count()
|
||||
self.assertEqual(6, number_of_connected_plugins)
|
||||
|
||||
|
@ -147,24 +147,24 @@ class TestClusterPlugins(ExtraFunctions):
|
|||
for _ in range(2):
|
||||
self._create_test_cluster()
|
||||
number_of_connected_clusters =\
|
||||
ClusterPlugins.get_connected_clusters(plugin_id).count()
|
||||
ClusterPlugin.get_connected_clusters(plugin_id).count()
|
||||
self.assertEqual(2, number_of_connected_clusters)
|
||||
|
||||
def test_get_enabled(self):
|
||||
self._create_test_plugins()
|
||||
cluster = self._create_test_cluster()
|
||||
|
||||
plugin = ClusterPlugins.get_connected_plugins(cluster).first()
|
||||
ClusterPlugins.set_attributes(cluster.id, plugin.id, enabled=True)
|
||||
plugin = ClusterPlugin.get_connected_plugins(cluster).first()
|
||||
ClusterPlugin.set_attributes(cluster.id, plugin.id, enabled=True)
|
||||
|
||||
enabled_plugin = ClusterPlugins.get_enabled(cluster.id).first()
|
||||
enabled_plugin = ClusterPlugin.get_enabled(cluster.id).first()
|
||||
self.assertEqual(plugin.id, enabled_plugin.id)
|
||||
|
||||
def test_is_plugin_used(self):
|
||||
self._create_test_plugins()
|
||||
cluster = self._create_test_cluster()
|
||||
|
||||
plugin = ClusterPlugins.get_connected_plugins(cluster).first()
|
||||
self.assertFalse(ClusterPlugins.is_plugin_used(plugin.id))
|
||||
ClusterPlugins.set_attributes(cluster.id, plugin.id, enabled=True)
|
||||
self.assertTrue(ClusterPlugins.is_plugin_used(plugin.id))
|
||||
plugin = ClusterPlugin.get_connected_plugins(cluster).first()
|
||||
self.assertFalse(ClusterPlugin.is_plugin_used(plugin.id))
|
||||
ClusterPlugin.set_attributes(cluster.id, plugin.id, enabled=True)
|
||||
self.assertTrue(ClusterPlugin.is_plugin_used(plugin.id))
|
||||
|
|
|
@ -1163,9 +1163,9 @@ class TestClusterObject(BaseTestCase):
|
|||
for kw in plugins_kw_list:
|
||||
plugin = objects.Plugin.create(kw)
|
||||
cluster.plugins.append(plugin)
|
||||
objects.ClusterPlugins.set_attributes(cluster.id,
|
||||
plugin.id,
|
||||
enabled=True)
|
||||
objects.ClusterPlugin.set_attributes(cluster.id,
|
||||
plugin.id,
|
||||
enabled=True)
|
||||
return cluster
|
||||
|
||||
def _get_network_role_metadata(self, **kwargs):
|
||||
|
@ -1811,9 +1811,9 @@ class TestClusterObjectGetRoles(BaseTestCase):
|
|||
roles_metadata=roles_metadata,
|
||||
))
|
||||
self.cluster.plugins.append(plugin)
|
||||
objects.ClusterPlugins.set_attributes(self.cluster.id,
|
||||
plugin.id,
|
||||
enabled=True)
|
||||
objects.ClusterPlugin.set_attributes(self.cluster.id,
|
||||
plugin.id,
|
||||
enabled=True)
|
||||
self.db.refresh(plugin)
|
||||
return plugin
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ from nailgun import consts
|
|||
from nailgun.db import db
|
||||
from nailgun import errors
|
||||
from nailgun.expression import Expression
|
||||
from nailgun.objects import ClusterPlugins
|
||||
from nailgun.objects import ClusterPlugin
|
||||
from nailgun.objects import DeploymentGraph
|
||||
from nailgun.objects import Plugin
|
||||
from nailgun.plugins import adapters
|
||||
|
@ -378,6 +378,81 @@ class TestPluginV4(TestPluginBase):
|
|||
ValueError, self.plugin_adapter._load_tasks)
|
||||
|
||||
|
||||
class TestPluginV5(TestPluginBase):
|
||||
|
||||
__test__ = True
|
||||
package_version = '5.0.0'
|
||||
|
||||
def test_get_metadata(self):
|
||||
plugin_metadata = self.env.get_default_plugin_metadata()
|
||||
attributes_metadata = self.env.get_default_plugin_env_config()
|
||||
nic_attributes_metadata = self.env.get_default_plugin_nic_config()
|
||||
bond_attributes_metadata = self.env.get_default_plugin_bond_config()
|
||||
node_attributes_metadata = self.env.get_default_plugin_node_config()
|
||||
roles_metadata = self.env.get_default_plugin_node_roles_config()
|
||||
volumes_metadata = self.env.get_default_plugin_volumes_config()
|
||||
network_roles_metadata = self.env.get_default_network_roles_config()
|
||||
deployment_tasks = self.env.get_default_plugin_deployment_tasks()
|
||||
tasks = self.env.get_default_plugin_tasks()
|
||||
components_metadata = self.env.get_default_components()
|
||||
|
||||
mocked_metadata = {
|
||||
self._find_path('metadata'): plugin_metadata,
|
||||
self._find_path('environment_config'): attributes_metadata,
|
||||
self._find_path('node_roles'): roles_metadata,
|
||||
self._find_path('volumes'): volumes_metadata,
|
||||
self._find_path('network_roles'): network_roles_metadata,
|
||||
self._find_path('deployment_tasks'): deployment_tasks,
|
||||
self._find_path('tasks'): tasks,
|
||||
self._find_path('components'): components_metadata,
|
||||
self._find_path('nic_config'): nic_attributes_metadata,
|
||||
self._find_path('bond_config'): bond_attributes_metadata,
|
||||
self._find_path('node_config'): node_attributes_metadata
|
||||
}
|
||||
|
||||
with mock.patch.object(
|
||||
self.plugin_adapter, '_load_config') as load_conf:
|
||||
load_conf.side_effect = lambda key: mocked_metadata[key]
|
||||
Plugin.update(self.plugin, self.plugin_adapter.get_metadata())
|
||||
|
||||
for key, val in six.iteritems(plugin_metadata):
|
||||
self.assertEqual(
|
||||
getattr(self.plugin, key), val)
|
||||
|
||||
self.assertEqual(
|
||||
self.plugin.attributes_metadata,
|
||||
attributes_metadata['attributes'])
|
||||
self.assertEqual(
|
||||
self.plugin.roles_metadata, roles_metadata)
|
||||
self.assertEqual(
|
||||
self.plugin.volumes_metadata, volumes_metadata)
|
||||
self.assertEqual(
|
||||
self.plugin.tasks, tasks)
|
||||
self.assertEqual(
|
||||
self.plugin.components_metadata, components_metadata)
|
||||
self.assertEqual(
|
||||
self.plugin.nic_attributes_metadata,
|
||||
nic_attributes_metadata)
|
||||
self.assertEqual(
|
||||
self.plugin.bond_attributes_metadata,
|
||||
bond_attributes_metadata)
|
||||
self.assertEqual(
|
||||
self.plugin.node_attributes_metadata,
|
||||
bond_attributes_metadata)
|
||||
|
||||
plugin_tasks = self.env.get_default_plugin_deployment_tasks()
|
||||
self.assertGreater(len(plugin_tasks), 0)
|
||||
for k, v in six.iteritems(plugin_tasks[0]):
|
||||
# this field is updated by plugin adapter
|
||||
if k is 'parameters':
|
||||
v.update({
|
||||
'cwd': '/etc/fuel/plugins/testing_plugin-0.1/'
|
||||
})
|
||||
self.assertEqual(
|
||||
self.plugin_adapter.get_deployment_tasks()[0][k],
|
||||
v)
|
||||
|
||||
|
||||
class TestClusterCompatibilityValidation(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -396,7 +471,7 @@ class TestClusterCompatibilityValidation(base.BaseTestCase):
|
|||
|
||||
def validate_with_cluster(self, **kwargs):
|
||||
cluster = self.cluster_mock(**kwargs)
|
||||
return ClusterPlugins.is_compatible(cluster, self.plugin)
|
||||
return ClusterPlugin.is_compatible(cluster, self.plugin)
|
||||
|
||||
def test_validation_ubuntu_ha(self):
|
||||
self.assertTrue(self.validate_with_cluster(
|
||||
|
|
|
@ -19,7 +19,7 @@ from mock import patch
|
|||
|
||||
from nailgun import consts
|
||||
from nailgun import errors
|
||||
from nailgun.objects import ClusterPlugins
|
||||
from nailgun.objects import ClusterPlugin
|
||||
from nailgun.objects import Plugin
|
||||
from nailgun.rpc.receiver import NailgunReceiver
|
||||
from nailgun.test import base
|
||||
|
@ -44,9 +44,9 @@ class TestNailgunReceiver(base.BaseTestCase):
|
|||
|
||||
self.plugin = Plugin.create(meta)
|
||||
self.cluster.plugins.append(self.plugin)
|
||||
ClusterPlugins.set_attributes(self.cluster.id,
|
||||
self.plugin.id,
|
||||
enabled=True)
|
||||
ClusterPlugin.set_attributes(self.cluster.id,
|
||||
self.plugin.id,
|
||||
enabled=True)
|
||||
|
||||
self.task = self.env.create_task(
|
||||
name=consts.TASK_NAMES.deployment,
|
||||
|
|
Loading…
Reference in New Issue