457 lines
16 KiB
Python
457 lines
16 KiB
Python
# Copyright 2016 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 copy import deepcopy
|
|
import datetime
|
|
|
|
import alembic
|
|
from oslo_serialization import jsonutils
|
|
import sqlalchemy as sa
|
|
|
|
from nailgun.db import db
|
|
from nailgun.db import dropdb
|
|
from nailgun.db.migration import ALEMBIC_CONFIG
|
|
from nailgun.test import base
|
|
|
|
|
|
_prepare_revision = '3763c404ca48'
|
|
_test_revision = 'f2314e5d63c9'
|
|
|
|
ATTRIBUTES_METADATA = {
|
|
'editable': {
|
|
'common': {}
|
|
}
|
|
}
|
|
SECURITY_GROUPS = {
|
|
'value': 'iptables_hybrid',
|
|
'values': [
|
|
{
|
|
'data': 'openvswitch',
|
|
'label': 'Open vSwitch Firewall Driver',
|
|
'description': 'Choose this driver for OVS based security groups '
|
|
'implementation. NOTE: Open vSwitch Firewall '
|
|
'Driver requires kernel version >= 4.3 '
|
|
'for non-dpdk case.'
|
|
},
|
|
{
|
|
'data': 'iptables_hybrid',
|
|
'label': 'Iptables-based Firewall Driver'
|
|
' (No firewall for DPDK case)',
|
|
'description': 'Choose this driver for iptables/linux bridge '
|
|
'based security groups implementation.'
|
|
}
|
|
],
|
|
'group': 'security',
|
|
'weight': 20,
|
|
'type': 'radio',
|
|
}
|
|
|
|
ROLES_META = {
|
|
'controller': {
|
|
'tags': [
|
|
'controller',
|
|
'rabbitmq',
|
|
'database',
|
|
'keystone',
|
|
'neutron'
|
|
]
|
|
}
|
|
}
|
|
|
|
PLUGIN_ROLE_META = {
|
|
'test_plugin_role': {
|
|
'tags': ['test_plugin_tag']
|
|
}
|
|
}
|
|
|
|
PLUGIN_TAGS_META = {
|
|
'test_plugin_tag':
|
|
{'has_primary': False}
|
|
}
|
|
|
|
TAGS_META = {
|
|
'controller': {
|
|
'has_primary': True,
|
|
},
|
|
'rabbitmq': {
|
|
'has_primary': True
|
|
},
|
|
'database': {
|
|
'has_primary': True
|
|
},
|
|
'keystone': {
|
|
'has_primary': True
|
|
},
|
|
'neutron': {
|
|
'has_primary': True
|
|
}
|
|
}
|
|
|
|
|
|
def setup_module():
|
|
dropdb()
|
|
alembic.command.upgrade(ALEMBIC_CONFIG, _prepare_revision)
|
|
prepare()
|
|
alembic.command.downgrade(ALEMBIC_CONFIG, _test_revision)
|
|
|
|
|
|
def prepare():
|
|
meta = base.reflect_db_metadata()
|
|
attrs_with_sec_group = deepcopy(ATTRIBUTES_METADATA)
|
|
attrs_with_sec_group.setdefault('editable', {}).setdefault(
|
|
'common', {}).setdefault('security_groups', SECURITY_GROUPS)
|
|
plugin = {
|
|
'name': 'Test_P',
|
|
'version': '3.0.0',
|
|
'title': 'Test Plugin',
|
|
'package_version': '5.0.0',
|
|
'roles_metadata': jsonutils.dumps(PLUGIN_ROLE_META),
|
|
'tags_metadata': jsonutils.dumps(PLUGIN_TAGS_META)
|
|
}
|
|
result = db.execute(meta.tables['plugins'].insert(), [plugin])
|
|
|
|
for release_name, env_version, cluster_name, attrs in zip(
|
|
('release_1', 'release_2', 'release_3'),
|
|
('mitaka-9.0', 'liberty-8.0', 'mitaka-9.0'),
|
|
('cluster_1', 'cluster_2', 'cluster_3'),
|
|
(ATTRIBUTES_METADATA, ATTRIBUTES_METADATA, attrs_with_sec_group)
|
|
):
|
|
release = {
|
|
'name': release_name,
|
|
'version': env_version,
|
|
'operating_system': 'ubuntu',
|
|
'state': 'available',
|
|
'deployment_tasks': '[]',
|
|
'roles_metadata': jsonutils.dumps(ROLES_META),
|
|
'tags_matadata': jsonutils.dumps(TAGS_META),
|
|
'is_deployable': True,
|
|
'networks_metadata': '{}',
|
|
'attributes_metadata': jsonutils.dumps(attrs)
|
|
}
|
|
result = db.execute(meta.tables['releases'].insert(), [release])
|
|
release_id = result.inserted_primary_key[0]
|
|
|
|
result = db.execute(
|
|
meta.tables['clusters'].insert(),
|
|
[{
|
|
'name': cluster_name,
|
|
'release_id': release_id,
|
|
'mode': 'ha_compact',
|
|
'status': 'new',
|
|
'net_provider': 'neutron',
|
|
'grouping': 'roles',
|
|
'fuel_version': '9.0',
|
|
'deployment_tasks': '[]',
|
|
'roles_metadata': jsonutils.dumps(ROLES_META),
|
|
'tags_metadata': '{}',
|
|
}])
|
|
|
|
cluster_id = result.inserted_primary_key[0]
|
|
editable = attrs.get('editable', {})
|
|
db.execute(
|
|
meta.tables['attributes'].insert(),
|
|
[{
|
|
'cluster_id': cluster_id,
|
|
'editable': jsonutils.dumps(editable)
|
|
}]
|
|
)
|
|
|
|
db.execute(
|
|
meta.tables['nodes'].insert(),
|
|
[{
|
|
'uuid': 'fcd49872-3917-4a18-98f9-3f5acfe3fdec',
|
|
'cluster_id': cluster_id,
|
|
'group_id': None,
|
|
'status': 'ready',
|
|
'roles': ['role_x', 'role_y'],
|
|
'primary_tags': ['role_y', 'test'],
|
|
'meta': '{}',
|
|
'mac': 'bb:aa:aa:aa:aa:aa',
|
|
'timestamp': datetime.datetime.utcnow(),
|
|
}]
|
|
)
|
|
|
|
new_node = db.execute(
|
|
meta.tables['nodes'].insert(),
|
|
[{
|
|
'uuid': '26b508d0-0d76-4159-bce9-f67ec2765481',
|
|
'cluster_id': None,
|
|
'group_id': None,
|
|
'status': 'discover',
|
|
'mac': 'aa:aa:aa:aa:aa:aa',
|
|
'timestamp': datetime.datetime.utcnow()
|
|
}]
|
|
)
|
|
node_id = new_node.inserted_primary_key[0]
|
|
|
|
bond_interface = db.execute(
|
|
meta.tables['node_bond_interfaces'].insert(),
|
|
[{
|
|
'node_id': node_id,
|
|
'name': 'test_bond_interface',
|
|
'mode': 'balance-tlb',
|
|
'attributes': jsonutils.dumps({
|
|
'lacp_rate': {'value': {'value': ''}},
|
|
'xmit_hash_policy': {'value': {'value': 'layer2'}},
|
|
'offloading': {
|
|
'disable': {'value': True},
|
|
'modes': {'value': {'tx-checksumming': None,
|
|
'tx-checksum-sctp': None}}
|
|
},
|
|
'mtu': {'value': {'value': 50}},
|
|
'lacp': {'value': {'value': ''}},
|
|
'mode': {'value': {'value': 'balance-tlb'}},
|
|
'type__': {'value': 'linux'},
|
|
'dpdk': {'enabled': {'value': False}}
|
|
})
|
|
}]
|
|
)
|
|
bond_id = bond_interface.inserted_primary_key[0]
|
|
|
|
db.execute(
|
|
meta.tables['node_nic_interfaces'].insert(),
|
|
[{
|
|
'node_id': node_id,
|
|
'name': 'test_nic_empty_attributes',
|
|
'mac': '00:00:00:00:00:01',
|
|
'attributes': jsonutils.dumps({}),
|
|
'meta': jsonutils.dumps({})
|
|
}]
|
|
)
|
|
db.execute(
|
|
meta.tables['node_nic_interfaces'].insert(),
|
|
[{
|
|
'node_id': node_id,
|
|
'name': 'test_nic_attributes',
|
|
'parent_id': bond_id,
|
|
'mac': '00:00:00:00:00:01',
|
|
'attributes': jsonutils.dumps({
|
|
'offloading': {
|
|
'disable': {'value': 'test_disable_offloading'},
|
|
'modes': {
|
|
'value': {
|
|
'tx-checksum-ipv4': 'IPV4_STATE',
|
|
'tx-checksumming': 'TX_STATE',
|
|
'rx-checksumming': 'RX_STATE',
|
|
'tx-checksum-ipv6': 'IPV6_STATE'
|
|
}
|
|
}
|
|
},
|
|
'mtu': {
|
|
'value': {'value': 'test_mtu'}
|
|
},
|
|
'sriov': {
|
|
'numvfs': {'value': 'test_sriov_numfs'},
|
|
'enabled': {'value': 'test_sriov_enabled'},
|
|
'physnet': {'value': 'test_sriov_physnet'}
|
|
},
|
|
'dpdk': {
|
|
'enabled': {'value': 'test_dpdk_enabled'}
|
|
}
|
|
}),
|
|
'meta': jsonutils.dumps({
|
|
'offloading_modes': [{
|
|
'state': None,
|
|
'name': 'tx-checksumming',
|
|
'sub': [
|
|
{'state': False, 'name': 'tx-checksum-sctp',
|
|
'sub': []},
|
|
{'state': None, 'name': 'tx-checksum-ipv6',
|
|
'sub': []},
|
|
{'state': None, 'name': 'tx-checksum-ipv4',
|
|
'sub': []}
|
|
]
|
|
}, {
|
|
'state': None, 'name': 'rx-checksumming', 'sub': []
|
|
}],
|
|
'numa_node': 12345,
|
|
'pci_id': 'test_pci_id',
|
|
'sriov': {
|
|
'available': 'test_sriov_available',
|
|
'totalvfs': 6789,
|
|
'pci_id': 'test_sriov_pci_id'
|
|
},
|
|
'dpdk': {'available': True}
|
|
})
|
|
}]
|
|
)
|
|
|
|
db.commit()
|
|
|
|
|
|
class TestAttributesDowngrade(base.BaseAlembicMigrationTest):
|
|
|
|
def test_cluster_attributes_downgrade(self):
|
|
clusters_attributes = self.meta.tables['attributes']
|
|
results = db.execute(
|
|
sa.select([clusters_attributes.c.editable]))
|
|
for editable in results:
|
|
editable = jsonutils.loads(editable[0])
|
|
common = editable.setdefault('common', {})
|
|
self.assertEqual(common.get('security_groups'), None)
|
|
|
|
def test_release_attributes_downgrade(self):
|
|
releases = self.meta.tables['releases']
|
|
results = db.execute(
|
|
sa.select([releases.c.attributes_metadata]))
|
|
for attrs in results:
|
|
attrs = jsonutils.loads(attrs[0])
|
|
common = attrs.setdefault('editable', {}).setdefault('common', {})
|
|
self.assertEqual(common.get('security_groups'), None)
|
|
|
|
|
|
class TestTags(base.BaseAlembicMigrationTest):
|
|
def test_primary_tags_downgrade(self):
|
|
nodes = self.meta.tables['nodes']
|
|
query = sa.select([nodes.c.primary_roles]).where(
|
|
nodes.c.uuid == 'fcd49872-3917-4a18-98f9-3f5acfe3fdec')
|
|
primary_roles = db.execute(query).fetchone()[0]
|
|
self.assertItemsEqual(primary_roles, ['role_y'])
|
|
|
|
def test_downgrade_tags_metadata(self):
|
|
releases = self.meta.tables['releases']
|
|
self.assertNotIn('tags_metadata', releases.c._all_columns)
|
|
|
|
clusters = self.meta.tables['clusters']
|
|
self.assertNotIn('tags_metadata', clusters.c._all_columns)
|
|
self.assertNotIn('roles_metadata', clusters.c._all_columns)
|
|
|
|
plugins = self.meta.tables['plugins']
|
|
self.assertNotIn('tags_metadata', plugins.c._all_columns)
|
|
|
|
def test_downgrade_field_tags_from_roles(self):
|
|
releases = self.meta.tables['releases']
|
|
query = sa.select([releases.c.roles_metadata])
|
|
for role_meta in db.execute(query).fetchall():
|
|
self.assertNotIn('tags', role_meta)
|
|
|
|
plugins = self.meta.tables['plugins']
|
|
query = sa.select([plugins.c.roles_metadata])
|
|
for role_meta in db.execute(query):
|
|
self.assertNotIn('tags', role_meta)
|
|
|
|
|
|
class TestNodeNICAndBondAttributesMigration(base.BaseAlembicMigrationTest):
|
|
|
|
def test_downgrade_release_with_nic_attributes(self):
|
|
releases_table = self.meta.tables['releases']
|
|
result = db.execute(
|
|
sa.select([releases_table.c.nic_attributes,
|
|
releases_table.c.bond_attributes])
|
|
).fetchall()[0]
|
|
self.assertEqual(result['nic_attributes'], '{}')
|
|
self.assertEqual(result['bond_attributes'], '{}')
|
|
|
|
def test_downgrade_node_nic_attributes_with_empty_attributes(self):
|
|
interfaces_table = self.meta.tables['node_nic_interfaces']
|
|
result = db.execute(
|
|
sa.select([interfaces_table.c.interface_properties,
|
|
interfaces_table.c.offloading_modes]).
|
|
where(interfaces_table.c.name == 'test_nic_empty_attributes')
|
|
).fetchone()
|
|
self.assertEqual(
|
|
jsonutils.loads(result['interface_properties']),
|
|
{
|
|
'mtu': None,
|
|
'pci_id': '',
|
|
'disable_offloading': False,
|
|
'sriov': {
|
|
'enabled': False,
|
|
'available': False,
|
|
'sriov_numvfs': None,
|
|
'physnet': 'physnet2',
|
|
'pci_id': '',
|
|
'sriov_totalvfs': 0
|
|
},
|
|
'dpdk': {
|
|
'enabled': False,
|
|
'available': False
|
|
}
|
|
}
|
|
)
|
|
self.assertEqual(jsonutils.loads(result['offloading_modes']), [])
|
|
|
|
def test_downgrade_node_nic_attributes(self):
|
|
interfaces_table = self.meta.tables['node_nic_interfaces']
|
|
result = db.execute(
|
|
sa.select([interfaces_table.c.interface_properties,
|
|
interfaces_table.c.offloading_modes,
|
|
interfaces_table.c.attributes,
|
|
interfaces_table.c.meta]).
|
|
where(interfaces_table.c.name == 'test_nic_attributes')
|
|
).fetchone()
|
|
|
|
self.assertEqual(
|
|
jsonutils.loads(result['interface_properties']),
|
|
{
|
|
'mtu': 'test_mtu',
|
|
'pci_id': 'test_pci_id',
|
|
'disable_offloading': 'test_disable_offloading',
|
|
'sriov': {
|
|
'enabled': 'test_sriov_enabled',
|
|
'available': 'test_sriov_available',
|
|
'sriov_numvfs': 'test_sriov_numfs',
|
|
'physnet': 'test_sriov_physnet',
|
|
'pci_id': 'test_sriov_pci_id',
|
|
'sriov_totalvfs': 6789
|
|
},
|
|
'dpdk': {
|
|
'enabled': 'test_dpdk_enabled',
|
|
'available': True
|
|
}
|
|
}
|
|
)
|
|
self.assertEqual(
|
|
jsonutils.loads(result['offloading_modes']),
|
|
[{
|
|
'state': 'TX_STATE',
|
|
'name': 'tx-checksumming',
|
|
'sub': [
|
|
{'state': False, 'name': 'tx-checksum-sctp', 'sub': []},
|
|
{'state': 'IPV6_STATE', 'name': 'tx-checksum-ipv6',
|
|
'sub': []},
|
|
{'state': 'IPV4_STATE', 'name': 'tx-checksum-ipv4',
|
|
'sub': []}
|
|
]
|
|
}, {
|
|
'state': 'RX_STATE', 'name': 'rx-checksumming', 'sub': []
|
|
}]
|
|
)
|
|
|
|
self.assertEqual(result['meta'], '{}')
|
|
self.assertEqual(result['attributes'], '{}')
|
|
|
|
def test_downgrade_node_bond_attributes(self):
|
|
node_bonds_table = self.meta.tables['node_bond_interfaces']
|
|
result = db.execute(
|
|
sa.select([node_bonds_table.c.interface_properties,
|
|
node_bonds_table.c.bond_properties,
|
|
node_bonds_table.c.offloading_modes,
|
|
node_bonds_table.c.attributes]).
|
|
where(node_bonds_table.c.name == 'test_bond_interface')
|
|
).fetchone()
|
|
|
|
self.assertEqual(
|
|
jsonutils.loads(result['bond_properties']),
|
|
{'type__': 'linux', 'mode': 'balance-tlb',
|
|
'xmit_hash_policy': 'layer2'}
|
|
)
|
|
self.assertEqual(
|
|
jsonutils.loads(result['interface_properties']),
|
|
{'mtu': 50, 'disable_offloading': True,
|
|
'dpdk': {'available': True, 'enabled': False}}
|
|
)
|
|
self.assertEqual(result['offloading_modes'], "[]")
|
|
self.assertEqual(result['attributes'], "{}")
|