Merge "Refactor component model"
This commit is contained in:
commit
7d7366c2ec
@ -15,7 +15,7 @@
|
||||
# under the License.
|
||||
|
||||
from nailgun.api.v1.handlers import base
|
||||
from nailgun.objects import ComponentCollection
|
||||
from nailgun.objects import Release
|
||||
|
||||
|
||||
class ComponentCollectionHandler(base.CollectionHandler):
|
||||
@ -26,9 +26,10 @@ class ComponentCollectionHandler(base.CollectionHandler):
|
||||
""":returns: JSONized component data for release and releated plugins.
|
||||
|
||||
:http: * 200 (OK)
|
||||
* 404 (release not found in db)
|
||||
"""
|
||||
components = ComponentCollection.get_all_by_release(release_id)
|
||||
return ComponentCollection.to_json(components)
|
||||
release = self.get_object_or_404(Release, release_id)
|
||||
return Release.get_all_components(release)
|
||||
|
||||
def POST(self, release_id):
|
||||
"""Creating of components is disallowed
|
||||
|
@ -423,13 +423,6 @@ CLOUD_INIT_TEMPLATES = Enum(
|
||||
'meta_data',
|
||||
)
|
||||
|
||||
COMPONENT_TYPES = Enum(
|
||||
'hypervisor',
|
||||
'network',
|
||||
'storage',
|
||||
'additional_service',
|
||||
)
|
||||
|
||||
# NOTE(kozhukalov): This constant is used to collect
|
||||
# the information about installed fuel packages (rpm -q).
|
||||
# This information is necessary for fuel-stats.
|
||||
|
@ -28,10 +28,7 @@ from alembic import op
|
||||
from nailgun.db.sqlalchemy.models import fields
|
||||
from oslo_serialization import jsonutils
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql as psql
|
||||
|
||||
from nailgun.db.sqlalchemy.models.fields import JSON
|
||||
from nailgun.utils.migration import drop_enum
|
||||
from nailgun.utils.migration import upgrade_enum
|
||||
|
||||
|
||||
@ -100,8 +97,6 @@ node_errors_new = (
|
||||
|
||||
|
||||
def upgrade():
|
||||
create_components_table()
|
||||
create_release_components_table()
|
||||
upgrade_nodegroups_name_cluster_constraint()
|
||||
upgrade_release_state()
|
||||
task_statuses_upgrade()
|
||||
@ -110,9 +105,11 @@ def upgrade():
|
||||
upgrade_neutron_parameters()
|
||||
upgrade_cluster_plugins()
|
||||
upgrade_add_baremetal_net()
|
||||
upgrade_with_components()
|
||||
|
||||
|
||||
def downgrade():
|
||||
downgrade_with_components()
|
||||
downgrade_add_baremetal_net()
|
||||
downgrade_cluster_plugins()
|
||||
downgrade_neutron_parameters()
|
||||
@ -120,11 +117,7 @@ def downgrade():
|
||||
task_names_downgrade()
|
||||
task_statuses_downgrade()
|
||||
downgrade_release_state()
|
||||
|
||||
op.drop_constraint('_name_cluster_uc', 'nodegroups',)
|
||||
op.drop_table('release_components')
|
||||
op.drop_table('components')
|
||||
drop_enum('component_types')
|
||||
downgrade_nodegroups_name_cluster_constraint()
|
||||
|
||||
|
||||
def upgrade_release_state():
|
||||
@ -167,42 +160,27 @@ def upgrade_nodegroups_name_cluster_constraint():
|
||||
)
|
||||
|
||||
|
||||
def create_components_table():
|
||||
op.create_table('components',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('name', sa.String(), nullable=False),
|
||||
sa.Column('type', sa.Enum('hypervisor', 'network',
|
||||
'storage', 'additional_service',
|
||||
name='component_types'),
|
||||
nullable=False),
|
||||
sa.Column('hypervisors', psql.ARRAY(sa.String()),
|
||||
server_default='{}', nullable=False),
|
||||
sa.Column('networks', psql.ARRAY(sa.String()),
|
||||
server_default='{}', nullable=False),
|
||||
sa.Column('storages', psql.ARRAY(sa.String()),
|
||||
server_default='{}', nullable=False),
|
||||
sa.Column('additional_services', psql.ARRAY(sa.String()),
|
||||
server_default='{}', nullable=False),
|
||||
sa.Column('plugin_id', sa.Integer(), nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
['plugin_id'], ['plugins.id'], ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('name', 'type',
|
||||
name='_component_name_type_uc')
|
||||
)
|
||||
def downgrade_nodegroups_name_cluster_constraint():
|
||||
op.drop_constraint('_name_cluster_uc', 'nodegroups',)
|
||||
|
||||
|
||||
def create_release_components_table():
|
||||
op.create_table('release_components',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('release_id', sa.Integer(), nullable=False),
|
||||
sa.Column('component_id', sa.Integer(), nullable=False),
|
||||
sa.ForeignKeyConstraint(
|
||||
['component_id'], ['components.id'], ),
|
||||
sa.ForeignKeyConstraint(
|
||||
['release_id'], ['releases.id'], ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
def upgrade_with_components():
|
||||
op.add_column(
|
||||
'plugins',
|
||||
sa.Column(
|
||||
'components_metadata',
|
||||
fields.JSON(),
|
||||
server_default='[]'
|
||||
)
|
||||
)
|
||||
op.add_column(
|
||||
'releases',
|
||||
sa.Column(
|
||||
'components_metadata',
|
||||
fields.JSON(),
|
||||
server_default='[]'
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def downgrade_release_state():
|
||||
@ -484,10 +462,15 @@ def upgrade_add_baremetal_net():
|
||||
sa.Column('baremetal_gateway', sa.String(length=25),
|
||||
nullable=True))
|
||||
op.add_column('neutron_config',
|
||||
sa.Column('baremetal_range', JSON(), nullable=True,
|
||||
sa.Column('baremetal_range', fields.JSON(), nullable=True,
|
||||
server_default='[]'))
|
||||
|
||||
|
||||
def downgrade_add_baremetal_net():
|
||||
op.drop_column('neutron_config', 'baremetal_gateway')
|
||||
op.drop_column('neutron_config', 'baremetal_range')
|
||||
|
||||
|
||||
def downgrade_with_components():
|
||||
op.drop_column('plugins', 'components_metadata')
|
||||
op.drop_column('releases', 'components_metadata')
|
||||
|
@ -51,6 +51,3 @@ from nailgun.db.sqlalchemy.models.master_node_settings \
|
||||
|
||||
from nailgun.db.sqlalchemy.models.plugins import ClusterPlugins
|
||||
from nailgun.db.sqlalchemy.models.plugins import Plugin
|
||||
|
||||
from nailgun.db.sqlalchemy.models.component import Component
|
||||
from nailgun.db.sqlalchemy.models.component import ReleaseComponent
|
||||
|
@ -1,63 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 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 Column
|
||||
from sqlalchemy import Enum
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy import UniqueConstraint
|
||||
|
||||
from sqlalchemy.dialects import postgresql as psql
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from nailgun import consts
|
||||
from nailgun.db.sqlalchemy.models.base import Base
|
||||
|
||||
|
||||
class Component(Base):
|
||||
__tablename__ = 'components'
|
||||
__table_args__ = (
|
||||
UniqueConstraint('name', 'type', name='_component_name_type_uc'),
|
||||
)
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String, nullable=False)
|
||||
type = Column(
|
||||
Enum(*consts.COMPONENT_TYPES, name='component_types'),
|
||||
nullable=False
|
||||
)
|
||||
hypervisors = Column(psql.ARRAY(String), nullable=False, default=[],
|
||||
server_default='{}')
|
||||
networks = Column(psql.ARRAY(String), nullable=False, default=[],
|
||||
server_default='{}')
|
||||
storages = Column(psql.ARRAY(String), nullable=False, default=[],
|
||||
server_default='{}')
|
||||
additional_services = Column(psql.ARRAY(String), nullable=False,
|
||||
default=[], server_default='{}')
|
||||
plugin_id = Column(Integer, ForeignKey('plugins.id', ondelete='CASCADE'))
|
||||
plugin = relationship("Plugin", backref="components")
|
||||
releases = relationship('Release',
|
||||
secondary='release_components',
|
||||
backref='components')
|
||||
|
||||
|
||||
class ReleaseComponent(Base):
|
||||
|
||||
__tablename__ = 'release_components'
|
||||
id = Column(Integer, primary_key=True)
|
||||
release_id = Column(Integer, ForeignKey('releases.id', ondelete='CASCADE'),
|
||||
nullable=False)
|
||||
component_id = Column(Integer, ForeignKey('components.id'), nullable=False)
|
@ -25,6 +25,7 @@ from sqlalchemy.orm import relationship
|
||||
|
||||
from nailgun.db.sqlalchemy.models.base import Base
|
||||
from nailgun.db.sqlalchemy.models.fields import JSON
|
||||
from nailgun.db.sqlalchemy.models.mutable import MutableList
|
||||
|
||||
|
||||
class ClusterPlugins(Base):
|
||||
@ -74,6 +75,8 @@ class Plugin(Base):
|
||||
volumes_metadata = Column(JSON, server_default='{}', nullable=False)
|
||||
roles_metadata = Column(JSON, server_default='{}', nullable=False)
|
||||
network_roles_metadata = Column(JSON, server_default='[]', nullable=False)
|
||||
components_metadata = Column(
|
||||
MutableList.as_mutable(JSON), server_default='[]')
|
||||
deployment_tasks = Column(JSON, server_default='[]', nullable=False)
|
||||
# TODO(apopovych): To support old plugins versions we need separate
|
||||
# tasks which runs directly during deployment(stored in `deployment_tasks`
|
||||
|
@ -27,6 +27,7 @@ from sqlalchemy.orm import relationship
|
||||
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 MutableList
|
||||
|
||||
|
||||
class Release(Base):
|
||||
@ -58,6 +59,8 @@ class Release(Base):
|
||||
wizard_metadata = Column(JSON, default={})
|
||||
deployment_tasks = Column(JSON, default=[])
|
||||
vmware_attributes_metadata = Column(JSON, default=[])
|
||||
components_metadata = Column(
|
||||
MutableList.as_mutable(JSON), default=[], server_default='[]')
|
||||
modes = Column(JSON, default=[])
|
||||
clusters = relationship(
|
||||
"Cluster",
|
||||
|
@ -54,6 +54,3 @@ from nailgun.objects.plugin import ClusterPlugins
|
||||
|
||||
from nailgun.objects.network_group import NetworkGroup
|
||||
from nailgun.objects.network_group import NetworkGroupCollection
|
||||
|
||||
from nailgun.objects.component import Component
|
||||
from nailgun.objects.component import ComponentCollection
|
||||
|
@ -1,71 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 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.orm import joinedload
|
||||
|
||||
from nailgun.db import db
|
||||
from nailgun.db.sqlalchemy import models
|
||||
from nailgun.objects import NailgunCollection
|
||||
from nailgun.objects import NailgunObject
|
||||
from nailgun.objects import Release
|
||||
from nailgun.objects.serializers import component
|
||||
|
||||
|
||||
class Component(NailgunObject):
|
||||
|
||||
model = models.Component
|
||||
serializer = component.ComponentSerializer
|
||||
|
||||
@classmethod
|
||||
def get_by_name_and_type(cls, component_name, component_type):
|
||||
return db().query(cls.model).filter_by(
|
||||
name=component_name, type=component_type).first()
|
||||
|
||||
|
||||
class ComponentCollection(NailgunCollection):
|
||||
|
||||
single = Component
|
||||
|
||||
@classmethod
|
||||
def get_all_by_release(cls, release_id):
|
||||
"""Get all components for specific release.
|
||||
|
||||
:param release_id: release ID
|
||||
:type release_id: int
|
||||
|
||||
:returns: list -- list of components
|
||||
"""
|
||||
components = []
|
||||
release = Release.get_by_uid(release_id)
|
||||
release_os = release.operating_system.lower()
|
||||
release_version = release.version
|
||||
|
||||
db_components = db().query(cls.single.model).options(
|
||||
joinedload(cls.single.model.releases),
|
||||
joinedload(cls.single.model.plugin)).all()
|
||||
|
||||
for db_component in db_components:
|
||||
if db_component.releases:
|
||||
for db_release in db_component.releases:
|
||||
if db_release.id == release.id:
|
||||
components.append(db_component)
|
||||
elif db_component.plugin:
|
||||
for plugin_release in db_component.plugin.releases:
|
||||
if (release_os == plugin_release.get('os') and
|
||||
release_version == plugin_release.get('version')):
|
||||
components.append(db_component)
|
||||
|
||||
return components
|
@ -97,6 +97,26 @@ class PluginCollection(NailgunCollection):
|
||||
"""
|
||||
return cls.filter_by_id_list(cls.all(), plugin_ids)
|
||||
|
||||
@classmethod
|
||||
def get_by_release(cls, release):
|
||||
"""Returns plugins by given release
|
||||
|
||||
:param release: Release instance
|
||||
:type release: Release DB model
|
||||
:returns: list -- list of sorted plugins
|
||||
"""
|
||||
release_plugins = set()
|
||||
release_os = release.operating_system.lower()
|
||||
release_version = release.version
|
||||
|
||||
for plugin in PluginCollection.all():
|
||||
for plugin_release in plugin.releases:
|
||||
if (release_os == plugin_release.get('os') and
|
||||
release_version == plugin_release.get('version')):
|
||||
release_plugins.add(plugin)
|
||||
|
||||
return sorted(release_plugins, key=lambda plugin: plugin.name)
|
||||
|
||||
|
||||
class ClusterPlugins(NailgunObject):
|
||||
|
||||
|
@ -29,6 +29,7 @@ from nailgun.objects import NailgunCollection
|
||||
from nailgun.objects import NailgunObject
|
||||
from nailgun.objects.serializers import release as release_serializer
|
||||
from nailgun.orchestrator import graph_configuration
|
||||
from nailgun.plugins.manager import PluginManager
|
||||
from nailgun.settings import settings
|
||||
|
||||
|
||||
@ -162,6 +163,17 @@ class Release(NailgunObject):
|
||||
def get_min_controller_count(cls, instance):
|
||||
return instance.roles_metadata['controller']['limits']['min']
|
||||
|
||||
@classmethod
|
||||
def get_all_components(cls, instance):
|
||||
"""Get all components related to release
|
||||
|
||||
:param instance: Release instance
|
||||
:type instance: Release DB instance
|
||||
:returns: list -- list of all components
|
||||
"""
|
||||
plugin_components = PluginManager.get_components_metadata(instance)
|
||||
return instance.components_metadata + plugin_components
|
||||
|
||||
|
||||
class ReleaseCollection(NailgunCollection):
|
||||
"""Release collection"""
|
||||
|
@ -1,41 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 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 nailgun.objects.serializers.base import BasicSerializer
|
||||
|
||||
|
||||
class ComponentSerializer(BasicSerializer):
|
||||
|
||||
fields = (
|
||||
"name",
|
||||
"type",
|
||||
"plugin_id"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def serialize(cls, instance, fields=None):
|
||||
data_dict = BasicSerializer.serialize(
|
||||
instance, fields=fields if fields else cls.fields)
|
||||
prepare = lambda array: '*' if array == ['*'] else array
|
||||
data_dict['compatible'] = {
|
||||
'hypervisors': prepare(instance.hypervisors),
|
||||
'networks': prepare(instance.networks),
|
||||
'storages': prepare(instance.storages),
|
||||
'additional_services': prepare(instance.additional_services)
|
||||
}
|
||||
data_dict['releases_ids'] = [r.id for r in instance.releases]
|
||||
|
||||
return data_dict
|
@ -25,7 +25,6 @@ import yaml
|
||||
|
||||
from nailgun.errors import errors
|
||||
from nailgun.logger import logger
|
||||
from nailgun.objects.component import Component
|
||||
from nailgun.objects.plugin import ClusterPlugins
|
||||
from nailgun.objects.plugin import Plugin
|
||||
from nailgun.settings import settings
|
||||
@ -135,6 +134,14 @@ class PluginAdapterBase(object):
|
||||
def volumes_metadata(self):
|
||||
return self.plugin.volumes_metadata
|
||||
|
||||
@property
|
||||
def components_metadata(self):
|
||||
return self.plugin.components_metadata
|
||||
|
||||
@property
|
||||
def releases(self):
|
||||
return self.plugin.releases
|
||||
|
||||
@property
|
||||
def normalized_roles_metadata(self):
|
||||
"""Block plugin disabling if nodes with plugin-provided roles exist"""
|
||||
@ -247,7 +254,6 @@ class PluginAdapterV3(PluginAdapterV2):
|
||||
"""Sync metadata from all config yaml files to DB"""
|
||||
super(PluginAdapterV3, self).sync_metadata_to_db()
|
||||
|
||||
data_to_update = {}
|
||||
db_config_metadata_mapping = {
|
||||
'attributes_metadata': self.environment_config_name,
|
||||
'roles_metadata': self.node_roles_config_name,
|
||||
@ -257,7 +263,12 @@ class PluginAdapterV3(PluginAdapterV2):
|
||||
'tasks': self.task_config_name
|
||||
}
|
||||
|
||||
for attribute, config in six.iteritems(db_config_metadata_mapping):
|
||||
self._update_plugin(db_config_metadata_mapping)
|
||||
|
||||
def _update_plugin(self, mapping):
|
||||
data_to_update = {}
|
||||
|
||||
for attribute, config in six.iteritems(mapping):
|
||||
config_file_path = os.path.join(self.plugin_path, config)
|
||||
attribute_data = self._load_config(config_file_path)
|
||||
# Plugin columns have constraints for nullable data, so
|
||||
@ -277,23 +288,12 @@ class PluginAdapterV4(PluginAdapterV3):
|
||||
|
||||
def sync_metadata_to_db(self):
|
||||
super(PluginAdapterV4, self).sync_metadata_to_db()
|
||||
components_file_path = os.path.join(
|
||||
self.plugin_path, self.components)
|
||||
|
||||
components = self._load_config(components_file_path) or []
|
||||
for component in components:
|
||||
component_name = component.get('name')
|
||||
component_type = component.get('type')
|
||||
db_component = Component.get_by_name_and_type(
|
||||
component_name, component_type)
|
||||
if not db_component:
|
||||
components_data = component.get('compatible', {})
|
||||
components_data.update({
|
||||
'name': component_name,
|
||||
'type': component_type,
|
||||
'plugin_id': self.plugin.id
|
||||
})
|
||||
Component.create(components_data)
|
||||
db_config_metadata_mapping = {
|
||||
'components_metadata': self.components
|
||||
}
|
||||
|
||||
self._update_plugin(db_config_metadata_mapping)
|
||||
|
||||
|
||||
__version_mapping = {
|
||||
|
@ -261,9 +261,8 @@ class PluginManager(object):
|
||||
"""Get volumes metadata for cluster from all plugins which enabled it.
|
||||
|
||||
:param cluster: A cluster instance
|
||||
:type cluster: nailgun.db.sqlalchemy.models.cluster.Cluster
|
||||
:return: Object with merged volumes data from plugins
|
||||
:rtype: dict
|
||||
:type cluster: Cluster model
|
||||
:return: dict -- Object with merged volumes data from plugins
|
||||
"""
|
||||
volumes_metadata = {
|
||||
'volumes': [],
|
||||
@ -301,6 +300,35 @@ class PluginManager(object):
|
||||
|
||||
return volumes_metadata
|
||||
|
||||
@classmethod
|
||||
def get_components_metadata(cls, release):
|
||||
"""Get components metadata for all plugins which related to release.
|
||||
|
||||
:param release: A release instance
|
||||
:type release: Release model
|
||||
:return: list -- List of plugins components
|
||||
"""
|
||||
components = []
|
||||
seen_components = \
|
||||
dict((c['name'], 'release') for c in release.components_metadata)
|
||||
|
||||
for plugin_adapter in map(
|
||||
wrap_plugin, PluginCollection.get_by_release(release)):
|
||||
for component in plugin_adapter.components_metadata:
|
||||
name = component['name']
|
||||
if name in seen_components:
|
||||
raise errors.AlreadyExists(
|
||||
'Plugin {0} is overlapping with {1} by introducing '
|
||||
'the same component with name "{2}"'
|
||||
.format(plugin_adapter.full_name,
|
||||
seen_components[name],
|
||||
name))
|
||||
|
||||
seen_components[name] = plugin_adapter.full_name
|
||||
components.append(component)
|
||||
|
||||
return components
|
||||
|
||||
@classmethod
|
||||
def sync_plugins_metadata(cls, plugin_ids=None):
|
||||
"""Sync metadata for plugins by given IDs.
|
||||
|
@ -61,7 +61,6 @@ from nailgun.db.sqlalchemy.models import Task
|
||||
# here come objects
|
||||
from nailgun.objects import Cluster
|
||||
from nailgun.objects import ClusterPlugins
|
||||
from nailgun.objects import Component
|
||||
from nailgun.objects import MasterNodeSettings
|
||||
from nailgun.objects import Node
|
||||
from nailgun.objects import NodeGroup
|
||||
@ -446,23 +445,6 @@ class EnvironmentManager(object):
|
||||
ClusterPlugins.set_attributes(cluster.id, plugin.id, enabled=True)
|
||||
return plugin
|
||||
|
||||
def create_component(self, release=None, plugin=None, **kwargs):
|
||||
component = self.get_default_components(**kwargs)[0]
|
||||
component_data = component.get('compatible', {})
|
||||
component_data.update({
|
||||
'name': component.get('name'),
|
||||
'type': component.get('type')
|
||||
})
|
||||
component = Component.create(component_data)
|
||||
if release:
|
||||
component.releases.append(release)
|
||||
|
||||
if plugin:
|
||||
component.plugin = plugin
|
||||
self.db.flush()
|
||||
|
||||
return component
|
||||
|
||||
def default_metadata(self):
|
||||
item = self.find_item_by_pk_model(
|
||||
self.read_fixtures(("sample_environment",)),
|
||||
@ -719,14 +701,15 @@ class EnvironmentManager(object):
|
||||
def get_default_components(self, **kwargs):
|
||||
default_components = [
|
||||
{
|
||||
'name': 'test_hypervisor',
|
||||
'type': 'hypervisor',
|
||||
'compatible': {
|
||||
'hypervisors': ['*'],
|
||||
'networks': [],
|
||||
'storages': ['object:block:swift'],
|
||||
'additional_services': []
|
||||
}
|
||||
'name': 'hypervisor:test_hypervisor',
|
||||
'compatible': [
|
||||
{'name': 'hypervisors:*'},
|
||||
{'name': 'storages:object:block:swift'}
|
||||
],
|
||||
'incompatible': [
|
||||
{'name': 'networks:*'},
|
||||
{'name': 'additional_services:*'}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -26,7 +26,9 @@ class TestComponentHandler(base.BaseIntegrationTest):
|
||||
self.release = self.env.create_release(
|
||||
version='2015.1-8.0',
|
||||
operating_system='Ubuntu',
|
||||
modes=[consts.CLUSTER_MODES.ha_compact])
|
||||
modes=[consts.CLUSTER_MODES.ha_compact],
|
||||
components_metadata=self.env.get_default_components(
|
||||
name='hypervisor:test_component_1'))
|
||||
self.plugin = self.env.create_plugin(
|
||||
name='compatible_plugin',
|
||||
fuel_version=['8.0'],
|
||||
@ -35,47 +37,35 @@ class TestComponentHandler(base.BaseIntegrationTest):
|
||||
'version': '2015.1-8.0',
|
||||
'os': 'ubuntu',
|
||||
'mode': ['ha'],
|
||||
'deployment_scripts_path': 'deployment_scripts/'}])
|
||||
self.core_component = self.env.create_component(
|
||||
release=self.release,
|
||||
name='test_component_1')
|
||||
self.plugin_component = self.env.create_component(
|
||||
plugin=self.plugin,
|
||||
name='test_component_2',
|
||||
type='additional_service')
|
||||
'deployment_scripts_path': 'deployment_scripts/'}],
|
||||
components_metadata=self.env.get_default_components(
|
||||
name='storage:test_component_2'))
|
||||
|
||||
def test_get_components(self):
|
||||
release_id = self.release.id
|
||||
plugin_id = self.plugin.id
|
||||
|
||||
resp = self.app.get(
|
||||
reverse(
|
||||
'ComponentCollectionHandler',
|
||||
kwargs={'release_id': release_id}),
|
||||
kwargs={'release_id': self.release.id}),
|
||||
headers=self.default_headers
|
||||
)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(resp.json_body, [
|
||||
{
|
||||
'name': 'test_component_1',
|
||||
'type': 'hypervisor',
|
||||
'releases_ids': [release_id],
|
||||
'plugin_id': None,
|
||||
'compatible': {
|
||||
'hypervisors': '*',
|
||||
'networks': [],
|
||||
'storages': ['object:block:swift'],
|
||||
'additional_services': []}},
|
||||
'name': 'hypervisor:test_component_1',
|
||||
'compatible': [
|
||||
{'name': 'hypervisors:*'},
|
||||
{'name': 'storages:object:block:swift'}],
|
||||
'incompatible': [
|
||||
{'name': 'networks:*'},
|
||||
{'name': 'additional_services:*'}]},
|
||||
{
|
||||
'name': 'test_component_2',
|
||||
'type': 'additional_service',
|
||||
'releases_ids': [],
|
||||
'plugin_id': plugin_id,
|
||||
'compatible': {
|
||||
'hypervisors': '*',
|
||||
'networks': [],
|
||||
'storages': ['object:block:swift'],
|
||||
'additional_services': []}}])
|
||||
'name': 'storage:test_component_2',
|
||||
'compatible': [
|
||||
{'name': 'hypervisors:*'},
|
||||
{'name': 'storages:object:block:swift'}],
|
||||
'incompatible': [
|
||||
{'name': 'networks:*'},
|
||||
{'name': 'additional_services:*'}]}])
|
||||
|
||||
def test_404_for_get_components_with_none_release_id(self):
|
||||
resp = self.app.get(
|
||||
@ -89,12 +79,10 @@ class TestComponentHandler(base.BaseIntegrationTest):
|
||||
self.assertEqual(404, resp.status_code)
|
||||
|
||||
def test_post_components_not_allowed(self):
|
||||
release_id = self.release.id
|
||||
|
||||
resp = self.app.post(
|
||||
reverse(
|
||||
'ComponentCollectionHandler',
|
||||
kwargs={'release_id': release_id}),
|
||||
kwargs={'release_id': self.release.id}),
|
||||
headers=self.default_headers,
|
||||
expect_errors=True
|
||||
)
|
||||
|
@ -29,7 +29,12 @@ class TestPluginManager(base.BaseIntegrationTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestPluginManager, self).setUp()
|
||||
self.env.create()
|
||||
self.env.create(
|
||||
release_kwargs={
|
||||
'version': '2015.1-8.0',
|
||||
'operating_system': 'Ubuntu'})
|
||||
|
||||
self.release = self.env.releases[0]
|
||||
self.cluster = self.env.clusters[0]
|
||||
|
||||
# Create two plugins with package verion 3.0.0
|
||||
@ -161,6 +166,67 @@ class TestPluginManager(base.BaseIntegrationTest):
|
||||
PluginManager.sync_plugins_metadata([self.env.plugins[0].id])
|
||||
self.assertEqual(sync_mock.call_count, 1)
|
||||
|
||||
def test_get_components_metadata(self):
|
||||
self.env.create_plugin(
|
||||
name='plugin_with_components',
|
||||
package_version='4.0.0',
|
||||
fuel_version=['8.0'],
|
||||
components_metadata=self.env.get_default_components())
|
||||
|
||||
components_metadata = PluginManager.get_components_metadata(
|
||||
self.release)
|
||||
self.assertEqual(
|
||||
components_metadata, self.env.get_default_components())
|
||||
|
||||
def test_raise_exception_when_plugin_overlap_release_component(self):
|
||||
release = self.env.create_release(
|
||||
version='2015.1-8.1',
|
||||
operating_system='Ubuntu',
|
||||
modes=[consts.CLUSTER_MODES.ha_compact],
|
||||
components_metadata=self.env.get_default_components())
|
||||
|
||||
self.env.create_plugin(
|
||||
name='plugin_with_components',
|
||||
package_version='4.0.0',
|
||||
fuel_version=['8.0'],
|
||||
releases=[{
|
||||
'repository_path': 'repositories/ubuntu',
|
||||
'version': '2015.1-8.1', 'os': 'ubuntu',
|
||||
'mode': ['ha'],
|
||||
'deployment_scripts_path': 'deployment_scripts/'}],
|
||||
components_metadata=self.env.get_default_components())
|
||||
|
||||
expected_message = (
|
||||
'Plugin plugin_with_components-0.1.0 is overlapping with release '
|
||||
'by introducing the same component with name '
|
||||
'"hypervisor:test_hypervisor"')
|
||||
|
||||
with self.assertRaisesRegexp(errors.AlreadyExists,
|
||||
expected_message):
|
||||
PluginManager.get_components_metadata(release)
|
||||
|
||||
def test_raise_exception_when_plugin_overlap_another_component(self):
|
||||
self.env.create_plugin(
|
||||
name='plugin_with_components_1',
|
||||
package_version='4.0.0',
|
||||
fuel_version=['8.0'],
|
||||
components_metadata=self.env.get_default_components())
|
||||
|
||||
self.env.create_plugin(
|
||||
name='plugin_with_components_2',
|
||||
package_version='4.0.0',
|
||||
fuel_version=['8.0'],
|
||||
components_metadata=self.env.get_default_components())
|
||||
|
||||
expected_message = (
|
||||
'Plugin plugin_with_components_2-0.1.0 is overlapping with '
|
||||
'plugin_with_components_1-0.1.0 by introducing the same component '
|
||||
'with name "hypervisor:test_hypervisor"')
|
||||
|
||||
with self.assertRaisesRegexp(errors.AlreadyExists,
|
||||
expected_message):
|
||||
PluginManager.get_components_metadata(self.release)
|
||||
|
||||
|
||||
class TestClusterPluginIntegration(base.BaseTestCase):
|
||||
|
||||
|
@ -1,112 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2015 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 nailgun import consts
|
||||
from nailgun.objects import ComponentCollection
|
||||
from nailgun.objects.serializers.component import ComponentSerializer
|
||||
from nailgun.test import base
|
||||
|
||||
|
||||
class BaseComponentTestCase(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BaseComponentTestCase, self).setUp()
|
||||
self.release = self.env.create_release(
|
||||
version='2015.1-8.0',
|
||||
operating_system='Ubuntu',
|
||||
modes=[consts.CLUSTER_MODES.ha_compact])
|
||||
self.plugin = self.env.create_plugin(
|
||||
name='compatible_plugin',
|
||||
fuel_version=['8.0'],
|
||||
releases=[{
|
||||
'repository_path': 'repositories/ubuntu',
|
||||
'version': '2015.1-8.0',
|
||||
'os': 'ubuntu',
|
||||
'mode': ['ha'],
|
||||
'deployment_scripts_path': 'deployment_scripts/'}])
|
||||
self.core_component = self.env.create_component(
|
||||
release=self.release,
|
||||
name='test_component_1')
|
||||
self.plugin_component = self.env.create_component(
|
||||
plugin=self.plugin,
|
||||
name='test_component_2',
|
||||
type='additional_service')
|
||||
|
||||
|
||||
class TestComponentCollection(BaseComponentTestCase):
|
||||
|
||||
def test_get_all_by_release(self):
|
||||
self.incompatible_plugin = self.env.create_plugin(
|
||||
fuel_version=['6.0'],
|
||||
releases=[{
|
||||
'repository_path': 'repositories/centos',
|
||||
'version': '2014.2-6.0',
|
||||
'os': 'centos',
|
||||
'mode': ['ha'],
|
||||
'deployment_scripts_path': 'deployment_scripts/'}]
|
||||
)
|
||||
self.incompatible_release = self.env.create_release(
|
||||
operating_system='Ubuntu',
|
||||
modes=[consts.CLUSTER_MODES.ha_compact])
|
||||
self.env.create_component(
|
||||
plugin=self.incompatible_plugin,
|
||||
name='incompatible_plugin_component')
|
||||
self.env.create_component(
|
||||
release=self.incompatible_release,
|
||||
name='incompatible_core_component')
|
||||
components = ComponentCollection.get_all_by_release(self.release.id)
|
||||
for component in components:
|
||||
self.assertIn(
|
||||
component.name, ['test_component_1', 'test_component_2'])
|
||||
self.assertNotIn(component.name, [
|
||||
'incompatible_plugin_component',
|
||||
'incompatible_core_component'])
|
||||
self.assertEqual(len(components), 2)
|
||||
|
||||
|
||||
class TestComponentSerializer(BaseComponentTestCase):
|
||||
|
||||
def test_core_component_serialization(self):
|
||||
release_id = self.release.id
|
||||
component_data = ComponentSerializer.serialize(
|
||||
self.core_component)
|
||||
self.assertDictEqual(component_data, {
|
||||
'name': 'test_component_1',
|
||||
'type': 'hypervisor',
|
||||
'compatible': {
|
||||
'additional_services': [],
|
||||
'networks': [],
|
||||
'storages': ['object:block:swift'],
|
||||
'hypervisors': '*'
|
||||
},
|
||||
'plugin_id': None,
|
||||
'releases_ids': [release_id]})
|
||||
|
||||
def test_plugin_component_serialization(self):
|
||||
plugin_id = self.plugin.id
|
||||
component_data = ComponentSerializer.serialize(
|
||||
self.plugin_component)
|
||||
self.assertDictEqual(component_data, {
|
||||
'name': 'test_component_2',
|
||||
'type': 'additional_service',
|
||||
'compatible': {
|
||||
'additional_services': [],
|
||||
'networks': [],
|
||||
'storages': ['object:block:swift'],
|
||||
'hypervisors': '*'
|
||||
},
|
||||
'plugin_id': plugin_id,
|
||||
'releases_ids': []})
|
@ -68,7 +68,7 @@ def prepare():
|
||||
'status': 'new',
|
||||
'net_provider': 'neutron',
|
||||
'grouping': 'roles',
|
||||
'fuel_version': '6.1',
|
||||
'fuel_version': '7.0',
|
||||
}
|
||||
)
|
||||
|
||||
@ -200,159 +200,6 @@ def insert_table_row(table, row_data):
|
||||
return result.inserted_primary_key[0]
|
||||
|
||||
|
||||
class TestComponentTableMigration(base.BaseAlembicMigrationTest):
|
||||
def test_table_fields_and_default_values(self):
|
||||
component_table = self.meta.tables['components']
|
||||
insert_table_row(component_table,
|
||||
{'name': 'test_component', 'type': 'network'})
|
||||
columns = [t.name for t in component_table.columns]
|
||||
self.assertItemsEqual(columns, ['id', 'name', 'type', 'hypervisors',
|
||||
'networks', 'storages',
|
||||
'plugin_id', 'additional_services'])
|
||||
|
||||
column_with_default_values = [
|
||||
(component_table.c.hypervisors, []),
|
||||
(component_table.c.networks, []),
|
||||
(component_table.c.storages, []),
|
||||
(component_table.c.additional_services, [])
|
||||
]
|
||||
result = db.execute(
|
||||
sa.select([item[0] for item in column_with_default_values]))
|
||||
db_values = result.fetchone()
|
||||
|
||||
for idx, db_value in enumerate(db_values):
|
||||
self.assertEqual(db_value, column_with_default_values[idx][1])
|
||||
|
||||
def test_unique_name_type_constraint(self):
|
||||
test_name = six.text_type(uuid.uuid4())
|
||||
test_type = 'storage'
|
||||
component_table = self.meta.tables['components']
|
||||
insert_table_row(component_table,
|
||||
{'name': test_name, 'type': test_type})
|
||||
|
||||
insert_table_row(component_table,
|
||||
{'name': six.text_type(uuid.uuid4()),
|
||||
'type': test_type})
|
||||
same_type_components_count = db.execute(
|
||||
sa.select([sa.func.count(component_table.c.name)]).
|
||||
where(component_table.c.type == test_type)
|
||||
).fetchone()[0]
|
||||
self.assertEqual(same_type_components_count, 2)
|
||||
|
||||
with self.assertRaisesRegexp(IntegrityError,
|
||||
'duplicate key value violates unique '
|
||||
'constraint "_component_name_type_uc"'):
|
||||
insert_table_row(component_table,
|
||||
{'name': test_name, 'type': test_type})
|
||||
|
||||
def test_component_types_enum(self):
|
||||
allow_type_name = ('hypervisor', 'network', 'storage',
|
||||
'additional_service')
|
||||
component_table = self.meta.tables['components']
|
||||
for type in allow_type_name:
|
||||
name = six.text_type(uuid.uuid4())
|
||||
insert_table_row(component_table, {'name': name, 'type': type})
|
||||
inserted_count = db.execute(
|
||||
sa.select([sa.func.count(component_table.c.name)]).
|
||||
where(sa.and_(component_table.c.type == type,
|
||||
component_table.c.name == name))
|
||||
).fetchone()[0]
|
||||
self.assertEqual(inserted_count, 1)
|
||||
|
||||
with self.assertRaisesRegexp(DataError, 'invalid input value for '
|
||||
'enum component_types'):
|
||||
insert_table_row(component_table,
|
||||
{'name': 'test', 'type': 'wrong_type_name'})
|
||||
|
||||
def test_cascade_plugin_deletion(self):
|
||||
plugin_table = self.meta.tables['plugins']
|
||||
plugin_id = insert_table_row(
|
||||
plugin_table,
|
||||
{
|
||||
'name': 'test_plugin',
|
||||
'title': 'Test plugin',
|
||||
'version': '1.0.0',
|
||||
'description': 'Test plugin for Fuel',
|
||||
'homepage': 'http://fuel_plugins.test_plugin.com',
|
||||
'package_version': '3.0.0'
|
||||
}
|
||||
)
|
||||
component_table = self.meta.tables['components']
|
||||
insert_table_row(
|
||||
component_table,
|
||||
{'name': 'test_name', 'plugin_id': plugin_id, 'type': 'storage'})
|
||||
db.execute(
|
||||
sa.delete(plugin_table).where(plugin_table.c.id == plugin_id))
|
||||
deleted_plugin_components = db.execute(
|
||||
sa.select([sa.func.count(component_table.c.name)]).
|
||||
where(component_table.c.plugin_id == plugin_id)
|
||||
).fetchone()[0]
|
||||
self.assertEqual(deleted_plugin_components, 0)
|
||||
|
||||
|
||||
class TestReleaseComponentTableMigration(base.BaseAlembicMigrationTest):
|
||||
def test_component_foreign_key_constraints(self):
|
||||
release_component_table = self.meta.tables['release_components']
|
||||
component_id = insert_table_row(
|
||||
self.meta.tables['components'],
|
||||
{'name': 'test_name', 'type': 'network'}
|
||||
)
|
||||
with self.assertRaisesRegexp(IntegrityError,
|
||||
'violates foreign key constraint '
|
||||
'"release_components_release_id_fkey"'):
|
||||
insert_table_row(
|
||||
release_component_table,
|
||||
{'release_id': -1, 'component_id': component_id}
|
||||
)
|
||||
|
||||
def test_release_foreign_key_constraints(self):
|
||||
release_component_table = self.meta.tables['release_components']
|
||||
release_table = self.meta.tables['releases']
|
||||
release_id = db.execute(sa.select([release_table.c.id])).fetchone()[0]
|
||||
|
||||
with self.assertRaisesRegexp(IntegrityError,
|
||||
'violates foreign key constraint '
|
||||
'"release_components_component_id_fkey"'):
|
||||
insert_table_row(
|
||||
release_component_table,
|
||||
{'release_id': release_id, 'component_id': -1}
|
||||
)
|
||||
|
||||
def test_non_null_fields(self):
|
||||
release_component_table = self.meta.tables['release_components']
|
||||
with self.assertRaisesRegexp(IntegrityError,
|
||||
'violates not-null constraint'):
|
||||
insert_table_row(release_component_table, {})
|
||||
|
||||
def test_cascade_release_deletion(self):
|
||||
release_component_table = self.meta.tables['release_components']
|
||||
release_table = self.meta.tables['releases']
|
||||
release_id = insert_table_row(
|
||||
release_table,
|
||||
{
|
||||
'name': 'release_with_components',
|
||||
'version': '2014.2.2-6.1',
|
||||
'operating_system': 'ubuntu',
|
||||
'state': 'available'
|
||||
}
|
||||
)
|
||||
component_id = insert_table_row(
|
||||
self.meta.tables['components'],
|
||||
{'name': six.text_type(uuid.uuid4()), 'type': 'hypervisor'}
|
||||
)
|
||||
insert_table_row(
|
||||
release_component_table,
|
||||
{'release_id': release_id, 'component_id': component_id}
|
||||
)
|
||||
db.execute(
|
||||
sa.delete(release_table).where(release_table.c.id == release_id))
|
||||
deleted_plugin_components = db.execute(
|
||||
sa.select([sa.func.count(release_component_table.c.id)]).
|
||||
where(release_component_table.c.release_id == release_id)
|
||||
).fetchone()[0]
|
||||
self.assertEqual(deleted_plugin_components, 0)
|
||||
|
||||
|
||||
class TestNodeGroupsMigration(base.BaseAlembicMigrationTest):
|
||||
|
||||
def test_name_cluster_unique_constraint_migration(self):
|
||||
@ -396,6 +243,12 @@ class TestReleaseMigrations(base.BaseAlembicMigrationTest):
|
||||
for state in states:
|
||||
self.assertEqual(state, 'manageonly')
|
||||
|
||||
def test_new_component_metadata_field_exists_and_empty(self):
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['releases'].c.components_metadata]))
|
||||
self.assertEqual(
|
||||
jsonutils.loads(result.fetchone()[0]), [])
|
||||
|
||||
|
||||
class TestTaskStatus(base.BaseAlembicMigrationTest):
|
||||
|
||||
@ -592,3 +445,12 @@ class TestBaremetalFields(base.BaseAlembicMigrationTest):
|
||||
self.meta.tables['neutron_config'].c.baremetal_range])).\
|
||||
fetchall()
|
||||
self.assertIn((baremetal_gateway, baremetal_range), result)
|
||||
|
||||
|
||||
class TestPluginMigration(base.BaseAlembicMigrationTest):
|
||||
|
||||
def test_new_component_metadata_field_exists_and_empty(self):
|
||||
result = db.execute(
|
||||
sa.select([self.meta.tables['plugins'].c.components_metadata]))
|
||||
self.assertEqual(
|
||||
jsonutils.loads(result.fetchone()[0]), [])
|
||||
|
@ -89,6 +89,14 @@ class TestPluginCollection(ExtraFunctions):
|
||||
self.assertListEqual(
|
||||
[plugin.id for plugin in plugins], ids)
|
||||
|
||||
def test_get_by_release(self):
|
||||
release = self.env.create_release(
|
||||
version='2015.1-8.0',
|
||||
operating_system='Ubuntu',
|
||||
modes=[consts.CLUSTER_MODES.ha_compact])
|
||||
for plugin in PluginCollection.get_by_release(release):
|
||||
self.assertNotEqual(plugin.name, 'incompatible_plugin')
|
||||
|
||||
|
||||
class TestClusterPlugins(ExtraFunctions):
|
||||
|
||||
|
@ -1426,3 +1426,48 @@ class TestNetworkGroup(BaseTestCase):
|
||||
def test_get_default_networkgroup(self):
|
||||
ng = objects.NetworkGroup.get_default_admin_network()
|
||||
self.assertIsNotNone(ng)
|
||||
|
||||
|
||||
class TestRelease(BaseTestCase):
|
||||
|
||||
def test_get_all_components(self):
|
||||
release = self.env.create_release(
|
||||
version='2015.1-8.0',
|
||||
operating_system='Ubuntu',
|
||||
modes=[consts.CLUSTER_MODES.ha_compact],
|
||||
components_metadata=self.env.get_default_components(
|
||||
name='hypervisor:test_component_1'))
|
||||
|
||||
self.env.create_plugin(
|
||||
name='plugin_with_components',
|
||||
package_version='4.0.0',
|
||||
fuel_version=['8.0'],
|
||||
releases=[{
|
||||
'repository_path': 'repositories/ubuntu',
|
||||
'version': '2015.1-8.0',
|
||||
'os': 'ubuntu',
|
||||
'mode': ['ha'],
|
||||
'deployment_scripts_path': 'deployment_scripts/'}],
|
||||
components_metadata=self.env.get_default_components(
|
||||
name='storage:test_component_2')
|
||||
)
|
||||
|
||||
components = objects.Release.get_all_components(release)
|
||||
|
||||
self.assertListEqual(components, [
|
||||
{
|
||||
'name': 'hypervisor:test_component_1',
|
||||
'compatible': [
|
||||
{'name': 'hypervisors:*'},
|
||||
{'name': 'storages:object:block:swift'}],
|
||||
'incompatible': [
|
||||
{'name': 'networks:*'},
|
||||
{'name': 'additional_services:*'}]},
|
||||
{
|
||||
'name': 'storage:test_component_2',
|
||||
'compatible': [
|
||||
{'name': 'hypervisors:*'},
|
||||
{'name': 'storages:object:block:swift'}],
|
||||
'incompatible': [
|
||||
{'name': 'networks:*'},
|
||||
{'name': 'additional_services:*'}]}])
|
||||
|
@ -24,7 +24,6 @@ from nailgun.db import db
|
||||
from nailgun.errors import errors
|
||||
from nailgun.expression import Expression
|
||||
from nailgun.objects import ClusterPlugins
|
||||
from nailgun.objects import Component
|
||||
from nailgun.objects import Plugin
|
||||
from nailgun.plugins import adapters
|
||||
from nailgun.settings import settings
|
||||
@ -312,26 +311,8 @@ class TestPluginV4(TestPluginBase):
|
||||
self.plugin.deployment_tasks, deployment_tasks)
|
||||
self.assertEqual(
|
||||
self.plugin.tasks, tasks)
|
||||
|
||||
component = Component.get_by_name_and_type(
|
||||
components_metadata[0].get('name'),
|
||||
components_metadata[0].get('type'))
|
||||
compatible = components_metadata[0].get('compatible')
|
||||
|
||||
self.assertEqual(
|
||||
component.name, components_metadata[0].get('name'))
|
||||
self.assertEqual(
|
||||
component.type, components_metadata[0].get('type'))
|
||||
self.assertEqual(
|
||||
component.hypervisors, compatible.get('hypervisors'))
|
||||
self.assertEqual(
|
||||
component.networks, compatible.get('networks'))
|
||||
self.assertEqual(
|
||||
component.storages, compatible.get('storages'))
|
||||
self.assertEqual(
|
||||
component.additional_services,
|
||||
compatible.get('additional_services'))
|
||||
self.assertEqual(component.plugin_id, self.plugin.id)
|
||||
self.plugin.components_metadata, components_metadata)
|
||||
|
||||
|
||||
class TestClusterCompatibilityValidation(base.BaseTestCase):
|
||||
|
Loading…
Reference in New Issue
Block a user