summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLingxian Kong <anlin.kong@gmail.com>2020-01-16 23:57:18 +1300
committerLingxian Kong <anlin.kong@gmail.com>2020-01-17 17:21:26 +1300
commit095a5b0514f800258a3e3cccc94c94135cab8ac5 (patch)
treee11d8b79f8f634fa23daacfcd476bd8bea852ef2
parentbaf8fee0a165de39c63d0ae0f72de7222a6f420c (diff)
downloadtrove-095a5b0514f800258a3e3cccc94c94135cab8ac5.tar.gz
Check network conflict
The user's network to create instance should not conflict with the management network. This patch also fixes the bug in trove-guestagent: AttributeError: 'TroveContext' object has no attribute 'notification' which has been merged in master branch in https://review.opendev.org/#/c/697225/ Change-Id: I922a1c5469309704cc6dd60a1ef57e43a98a3c00 (cherry picked from commit 263339b4db0fb8e1d10c9933b71a0d5b7140cc68)
-rw-r--r--.zuul.yaml2
-rwxr-xr-xintegration/scripts/trovestack5
-rw-r--r--trove/common/exception.py4
-rw-r--r--trove/common/neutron.py25
-rw-r--r--trove/instance/models.py5
-rw-r--r--trove/instance/service.py33
6 files changed, 61 insertions, 13 deletions
diff --git a/.zuul.yaml b/.zuul.yaml
index 56850e01..eb63e2ab 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -15,7 +15,6 @@
- openstack-tox-pylint
- trove-tox-bandit-baseline:
voting: false
- - trove-tox-fakemodetests
- trove-functional-mysql
- trove-scenario-mysql-single
- trove-scenario-mysql-multi
@@ -26,7 +25,6 @@
queue: trove
jobs:
- openstack-tox-pylint
- - trove-tox-fakemodetests
- trove-functional-mysql
- trove-scenario-mysql-single
- trove-scenario-mysql-multi
diff --git a/integration/scripts/trovestack b/integration/scripts/trovestack
index c24647fe..654ef6f8 100755
--- a/integration/scripts/trovestack
+++ b/integration/scripts/trovestack
@@ -552,9 +552,7 @@ function cmd_set_datastore() {
PACKAGES=${PACKAGES:-""}
if [ "$DATASTORE_TYPE" == "mysql" ]; then
- set_mysql_pkg
- PACKAGES=${PACKAGES:-$MYSQL_PKG}
- VERSION=$MYSQL_VER
+ VERSION="5.7"
elif [ "$DATASTORE_TYPE" == "percona" ]; then
PACKAGES=${PACKAGES:-"percona-server-server-5.6"}
VERSION="5.6"
@@ -562,7 +560,6 @@ function cmd_set_datastore() {
PACKAGES=${PACKAGES:-"percona-xtradb-cluster-server-5.6"}
VERSION="5.6"
elif [ "$DATASTORE_TYPE" == "mariadb" ]; then
- PACKAGES=${PACKAGES:-"mariadb-server"}
VERSION="10.4"
elif [ "$DATASTORE_TYPE" == "mongodb" ]; then
PACKAGES=${PACKAGES:-"mongodb-org"}
diff --git a/trove/common/exception.py b/trove/common/exception.py
index e6cc91e2..a03f2bee 100644
--- a/trove/common/exception.py
+++ b/trove/common/exception.py
@@ -596,6 +596,10 @@ class PublicNetworkNotFound(TroveError):
message = _("Public network cannot be found.")
+class NetworkConflict(BadRequest):
+ message = _("User network conflicts with the management network.")
+
+
class ClusterVolumeSizeRequired(TroveError):
message = _("A volume size is required for each instance in the cluster.")
diff --git a/trove/common/neutron.py b/trove/common/neutron.py
index 5f3330b1..d11ecf22 100644
--- a/trove/common/neutron.py
+++ b/trove/common/neutron.py
@@ -21,6 +21,7 @@ from trove.common import exception
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
MGMT_NETWORKS = None
+MGMT_CIDRS = None
def get_management_networks(context):
@@ -147,3 +148,27 @@ def create_security_group_rule(client, sg_id, protocol, ports, remote_ips):
}
client.create_security_group_rule(body)
+
+
+def get_subnet_cidrs(client, network_id):
+ cidrs = []
+
+ subnets = client.list_subnets(network_id=network_id)['subnets']
+ for subnet in subnets:
+ cidrs.append(subnet.get('cidr'))
+
+ return cidrs
+
+
+def get_mamangement_subnet_cidrs(client):
+ """Cache the management subnet CIDRS."""
+ global MGMT_CIDRS
+
+ if MGMT_CIDRS is not None:
+ return MGMT_CIDRS
+
+ MGMT_CIDRS = []
+ if len(CONF.management_networks) > 0:
+ MGMT_CIDRS = get_subnet_cidrs(client, CONF.management_networks[0])
+
+ return MGMT_CIDRS
diff --git a/trove/instance/models.py b/trove/instance/models.py
index 356fcc7d..7a13af2e 100644
--- a/trove/instance/models.py
+++ b/trove/instance/models.py
@@ -24,6 +24,7 @@ import six
from novaclient import exceptions as nova_exceptions
from oslo_config.cfg import NoSuchOptError
from oslo_log import log as logging
+from oslo_utils import encodeutils
from sqlalchemy import func
from trove.backup.models import Backup
@@ -1811,6 +1812,10 @@ class instance_encryption_key_cache(object):
if val is None:
return val
+ # We need string anyway
+ if isinstance(val, six.binary_type):
+ val = encodeutils.safe_decode(val)
+
if len(self._lru) == self._lru_cache_size:
tail = self._lru.pop()
del self._table[tail]
diff --git a/trove/instance/service.py b/trove/instance/service.py
index ce339704..05e433ea 100644
--- a/trove/instance/service.py
+++ b/trove/instance/service.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import ipaddress
+
from oslo_log import log as logging
from oslo_utils import strutils
@@ -20,9 +22,10 @@ from trove.backup.models import Backup as backup_model
from trove.backup import views as backup_views
import trove.common.apischema as apischema
from trove.common import cfg
-from trove.common.clients import create_guest_client
+from trove.common import clients
from trove.common import exception
from trove.common.i18n import _
+from trove.common import neutron
from trove.common import notification
from trove.common.notification import StartNotification
from trove.common import pagination
@@ -278,6 +281,19 @@ class InstanceController(wsgi.Controller):
instance.delete()
return wsgi.Result(None, 202)
+ def _check_network_overlap(self, context, user_network):
+ neutron_client = clients.create_neutron_client(context)
+ user_cidrs = neutron.get_subnet_cidrs(neutron_client, user_network)
+ mgmt_cidrs = neutron.get_mamangement_subnet_cidrs(neutron_client)
+ LOG.debug("Cidrs of the user network: %s, cidrs of the management "
+ "network: %s", user_cidrs, mgmt_cidrs)
+ for user_cidr in user_cidrs:
+ user_net = ipaddress.ip_network(user_cidr)
+ for mgmt_cidr in mgmt_cidrs:
+ mgmt_net = ipaddress.ip_network(mgmt_cidr)
+ if user_net.overlaps(mgmt_net):
+ raise exception.NetworkConflict()
+
def create(self, req, body, tenant_id):
# TODO(hub-cap): turn this into middleware
LOG.info("Creating a database instance for tenant '%s'",
@@ -341,7 +357,10 @@ class InstanceController(wsgi.Controller):
backup_id = None
availability_zone = body['instance'].get('availability_zone')
+
nics = body['instance'].get('nics', [])
+ if len(nics) > 0:
+ self._check_network_overlap(context, nics[0].get('net-id'))
slave_of_id = body['instance'].get('replica_of',
# also check for older name
@@ -498,7 +517,7 @@ class InstanceController(wsgi.Controller):
if not instance:
raise exception.NotFound(uuid=id)
self.authorize_instance_action(context, 'guest_log_list', instance)
- client = create_guest_client(context, id)
+ client = clients.create_guest_client(context, id)
guest_log_list = client.guest_log_list()
return wsgi.Result({'logs': guest_log_list}, 200)
@@ -522,7 +541,7 @@ class InstanceController(wsgi.Controller):
discard = body.get('discard', None)
if enable and disable:
raise exception.BadRequest(_("Cannot enable and disable log."))
- client = create_guest_client(context, id)
+ client = clients.create_guest_client(context, id)
guest_log = client.guest_log_action(log_name, enable, disable,
publish, discard)
return wsgi.Result({'log': guest_log}, 200)
@@ -545,13 +564,13 @@ class InstanceController(wsgi.Controller):
def _module_list_guest(self, context, id, include_contents):
"""Return information about modules on an instance."""
- client = create_guest_client(context, id)
+ client = clients.create_guest_client(context, id)
result_list = client.module_list(include_contents)
return wsgi.Result({'modules': result_list}, 200)
def _module_list(self, context, id, include_contents):
"""Return information about instance modules."""
- client = create_guest_client(context, id)
+ client = clients.create_guest_client(context, id)
result_list = client.module_list(include_contents)
return wsgi.Result({'modules': result_list}, 200)
@@ -567,7 +586,7 @@ class InstanceController(wsgi.Controller):
module_models.Modules.validate(
modules, instance.datastore.id, instance.datastore_version.id)
module_list = module_views.convert_modules_to_list(modules)
- client = create_guest_client(context, id)
+ client = clients.create_guest_client(context, id)
result_list = client.module_apply(module_list)
models.Instance.add_instance_modules(context, id, modules)
return wsgi.Result({'modules': result_list}, 200)
@@ -581,7 +600,7 @@ class InstanceController(wsgi.Controller):
self.authorize_instance_action(context, 'module_remove', instance)
module = module_models.Module.load(context, module_id)
module_info = module_views.DetailedModuleView(module).data()
- client = create_guest_client(context, id)
+ client = clients.create_guest_client(context, id)
client.module_remove(module_info)
instance_modules = module_models.InstanceModules.load_all(
context, instance_id=id, module_id=module_id)