trove/trove/common/neutron.py

150 lines
4.3 KiB
Python

# Copyright 2019 Catalyst Cloud Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import netaddr
from oslo_log import log as logging
from trove.common import cfg
from trove.common import exception
from trove.common import remote
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
MGMT_NETWORKS = None
def get_management_networks(context):
"""Cache the management network names.
When CONF.management_networks is changed, the Trove service needs to
restart so the global cache will be refreshed.
"""
global MGMT_NETWORKS
if MGMT_NETWORKS is not None:
return MGMT_NETWORKS
MGMT_NETWORKS = []
if len(CONF.management_networks) > 0:
neutron_client = remote.create_neutron_client(context)
for net_id in CONF.management_networks:
MGMT_NETWORKS.append(
neutron_client.show_network(net_id)['network']['name']
)
return MGMT_NETWORKS
def reset_management_networks():
"""This method is only for testing purpose."""
global MGMT_NETWORKS
MGMT_NETWORKS = None
def create_port(client, name, description, network_id, security_groups,
is_public=False):
port_body = {
"port": {
"name": name,
"description": description,
"network_id": network_id,
"security_groups": security_groups
}
}
port = client.create_port(body=port_body)
port_id = port['port']['id']
if is_public:
public_network_id = get_public_network(client)
if not public_network_id:
raise exception.PublicNetworkNotFound()
fip_body = {
"floatingip": {
'floating_network_id': public_network_id,
'port_id': port_id,
}
}
client.create_floatingip(fip_body)
return port_id
def delete_port(client, id):
ret = client.list_floatingips(port_id=id)
if len(ret['floatingips']) > 0:
for fip in ret['floatingips']:
try:
client.delete_floatingip(fip['id'])
except Exception as e:
LOG.error(
'Failed to delete floating IP for port %s, error: %s',
id, str(e)
)
client.delete_port(id)
def get_public_network(client):
"""Get public network ID.
If not given in the config file, try to query all the public networks and
use the first one in the list.
"""
if CONF.network.public_network_id:
return CONF.network.public_network_id
kwargs = {'router:external': True}
ret = client.list_networks(**kwargs)
if len(ret.get('networks', [])) == 0:
return None
return ret['networks'][0].get('id')
def create_security_group(client, name, instance_id):
body = {
'security_group': {
'name': name,
'description': 'Security group for trove instance %s' % instance_id
}
}
ret = client.create_security_group(body=body)
return ret['security_group']['id']
def create_security_group_rule(client, sg_id, protocol, ports, remote_ips):
for remote_ip in remote_ips:
ip = netaddr.IPNetwork(remote_ip)
ethertype = 'IPv4' if ip.version == 4 else 'IPv6'
for port_or_range in set(ports):
from_, to_ = port_or_range[0], port_or_range[-1]
body = {
"security_group_rule": {
"direction": "ingress",
"ethertype": ethertype,
"protocol": protocol,
"security_group_id": sg_id,
"port_range_min": int(from_),
"port_range_max": int(to_),
"remote_ip_prefix": remote_ip
}
}
client.create_security_group_rule(body)