Remove cloudpipe APIs
This commit removes the cloudpipe API from nova. This has been deprecated since change I415760ff634dd85974f0c3f79e788e633852efb5 and no longer works without nova-cert and the pending removal of the deprecated nova-network. Implements bp remove-nova-cert Change-Id: Ifd1fb13a5953cc66f9cc2561d30a9efcd3f4c92e
This commit is contained in:
parent
700ab86f8d
commit
acdc2da0e3
@ -114,10 +114,6 @@ In this section we focus on this related to networking.
|
||||
|
||||
TODO
|
||||
|
||||
- **Cloudpipe**
|
||||
|
||||
TODO
|
||||
|
||||
- **Extended Networks**
|
||||
|
||||
TODO
|
||||
|
@ -52,7 +52,6 @@ the `API guide <http://developer.openstack.org/api-guide/compute/index.html>`_.
|
||||
.. include:: os-services.inc
|
||||
.. include:: os-simple-tenant-usage.inc
|
||||
.. include:: os-server-external-events.inc
|
||||
.. include:: os-cloudpipe.inc
|
||||
.. include:: extensions.inc
|
||||
.. include:: os-networks.inc
|
||||
.. include:: os-volumes.inc
|
||||
@ -79,3 +78,4 @@ This section contains the reference for APIs that were part of the OpenStack
|
||||
Compute API in the past, but no longer exist.
|
||||
|
||||
.. include:: os-certificates.inc
|
||||
.. include:: os-cloudpipe.inc
|
||||
|
@ -8,7 +8,8 @@
|
||||
|
||||
This API only works with ``nova-network`` which is
|
||||
deprecated in favor of Neutron. It should be avoided
|
||||
in any new applications.
|
||||
in any new applications. It was removed in the 16.0.0
|
||||
Pike release.
|
||||
|
||||
Manages virtual VPNs for projects.
|
||||
|
||||
@ -106,4 +107,4 @@ Request
|
||||
Response
|
||||
--------
|
||||
|
||||
There is no body content for the response of a successful PUT request
|
||||
There is no body content for the response of a successful PUT request
|
||||
|
@ -14,26 +14,10 @@
|
||||
|
||||
"""Connect your vlan to the world."""
|
||||
|
||||
from oslo_utils import fileutils
|
||||
from webob import exc
|
||||
|
||||
from nova.api.openstack.compute.schemas import cloudpipe
|
||||
from nova.api.openstack import extensions
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api import validation
|
||||
from nova.cloudpipe import pipelib
|
||||
from nova import compute
|
||||
from nova.compute import utils as compute_utils
|
||||
from nova.compute import vm_states
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import network
|
||||
from nova import objects
|
||||
from nova.policies import cloudpipe as cp_policies
|
||||
from nova import utils
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
|
||||
ALIAS = 'os-cloudpipe'
|
||||
|
||||
@ -41,130 +25,23 @@ ALIAS = 'os-cloudpipe'
|
||||
class CloudpipeController(wsgi.Controller):
|
||||
"""Handle creating and listing cloudpipe instances."""
|
||||
|
||||
def __init__(self):
|
||||
self.compute_api = compute.API()
|
||||
self.network_api = network.API()
|
||||
self.cloudpipe = pipelib.CloudPipe()
|
||||
self.setup()
|
||||
|
||||
def setup(self):
|
||||
"""Ensure the keychains and folders exist."""
|
||||
# NOTE(vish): One of the drawbacks of doing this in the api is
|
||||
# the keys will only be on the api node that launched
|
||||
# the cloudpipe.
|
||||
fileutils.ensure_tree(CONF.crypto.keys_path)
|
||||
|
||||
def _get_all_cloudpipes(self, context):
|
||||
"""Get all cloudpipes."""
|
||||
instances = self.compute_api.get_all(context,
|
||||
search_opts={'deleted': False})
|
||||
return [instance for instance in instances
|
||||
if pipelib.is_vpn_image(instance.image_ref)
|
||||
and instance.vm_state != vm_states.DELETED]
|
||||
|
||||
def _get_cloudpipe_for_project(self, context):
|
||||
"""Get the cloudpipe instance for a project from context."""
|
||||
cloudpipes = self._get_all_cloudpipes(context) or [None]
|
||||
return cloudpipes[0]
|
||||
|
||||
def _vpn_dict(self, context, project_id, instance):
|
||||
elevated = context.elevated()
|
||||
rv = {'project_id': project_id}
|
||||
if not instance:
|
||||
rv['state'] = 'pending'
|
||||
return rv
|
||||
rv['instance_id'] = instance.uuid
|
||||
rv['created_at'] = utils.isotime(instance.created_at)
|
||||
nw_info = compute_utils.get_nw_info_for_instance(instance)
|
||||
if not nw_info:
|
||||
return rv
|
||||
vif = nw_info[0]
|
||||
ips = [ip for ip in vif.fixed_ips() if ip['version'] == 4]
|
||||
if ips:
|
||||
rv['internal_ip'] = ips[0]['address']
|
||||
# NOTE(vish): Currently network_api.get does an owner check on
|
||||
# project_id. This is probably no longer necessary
|
||||
# but rather than risk changes in the db layer,
|
||||
# we are working around it here by changing the
|
||||
# project_id in the context. This can be removed
|
||||
# if we remove the project_id check in the db.
|
||||
elevated.project_id = project_id
|
||||
network = self.network_api.get(elevated, vif['network']['id'])
|
||||
if network:
|
||||
vpn_ip = network['vpn_public_address']
|
||||
vpn_port = network['vpn_public_port']
|
||||
rv['public_ip'] = vpn_ip
|
||||
rv['public_port'] = vpn_port
|
||||
if vpn_ip and vpn_port:
|
||||
if utils.vpn_ping(vpn_ip, vpn_port):
|
||||
rv['state'] = 'running'
|
||||
else:
|
||||
rv['state'] = 'down'
|
||||
else:
|
||||
rv['state'] = 'invalid'
|
||||
return rv
|
||||
|
||||
@extensions.expected_errors((400, 403))
|
||||
@validation.schema(cloudpipe.create)
|
||||
@extensions.expected_errors((410))
|
||||
def create(self, req, body):
|
||||
"""Create a new cloudpipe instance, if none exists.
|
||||
|
||||
Parameters: {cloudpipe: {'project_id': ''}}
|
||||
"""
|
||||
raise exc.HTTPGone()
|
||||
|
||||
context = req.environ['nova.context']
|
||||
context.can(cp_policies.BASE_POLICY_NAME)
|
||||
params = body.get('cloudpipe', {})
|
||||
project_id = params.get('project_id', context.project_id)
|
||||
# NOTE(vish): downgrade to project context. Note that we keep
|
||||
# the same token so we can still talk to glance
|
||||
context.project_id = project_id
|
||||
context.user_id = 'project-vpn'
|
||||
context.is_admin = False
|
||||
context.roles = []
|
||||
instance = self._get_cloudpipe_for_project(context)
|
||||
if not instance:
|
||||
try:
|
||||
result = self.cloudpipe.launch_vpn_instance(context)
|
||||
instance = result[0][0]
|
||||
except exception.NoMoreNetworks:
|
||||
msg = _("Unable to claim IP for VPN instances, ensure it "
|
||||
"isn't running, and try again in a few minutes")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
return {'instance_id': instance.uuid}
|
||||
|
||||
@extensions.expected_errors((400, 403, 404))
|
||||
@extensions.expected_errors((410))
|
||||
def index(self, req):
|
||||
"""List running cloudpipe instances."""
|
||||
context = req.environ['nova.context']
|
||||
context.can(cp_policies.BASE_POLICY_NAME)
|
||||
vpns = [self._vpn_dict(context, x['project_id'], x)
|
||||
for x in self._get_all_cloudpipes(context)]
|
||||
return {'cloudpipes': vpns}
|
||||
raise exc.HTTPGone()
|
||||
|
||||
@wsgi.response(202)
|
||||
@extensions.expected_errors(400)
|
||||
@validation.schema(cloudpipe.update)
|
||||
@extensions.expected_errors(410)
|
||||
def update(self, req, id, body):
|
||||
"""Configure cloudpipe parameters for the project."""
|
||||
|
||||
context = req.environ['nova.context']
|
||||
context.can(cp_policies.BASE_POLICY_NAME)
|
||||
|
||||
if id != "configure-project":
|
||||
msg = _("Unknown action %s") % id
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
project_id = context.project_id
|
||||
networks = objects.NetworkList.get_by_project(context, project_id)
|
||||
|
||||
params = body['configure_project']
|
||||
vpn_ip = params['vpn_ip']
|
||||
vpn_port = params['vpn_port']
|
||||
for nw in networks:
|
||||
nw.vpn_public_address = vpn_ip
|
||||
nw.vpn_public_port = vpn_port
|
||||
nw.save()
|
||||
raise exc.HTTPGone()
|
||||
|
||||
|
||||
class Cloudpipe(extensions.V21APIExtensionBase):
|
||||
|
@ -1,48 +0,0 @@
|
||||
# Copyright 2014 IBM Corporation. All rights reserved.
|
||||
#
|
||||
# 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 nova.api.validation import parameter_types
|
||||
|
||||
|
||||
create = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'cloudpipe': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'project_id': parameter_types.project_id,
|
||||
},
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['cloudpipe'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
update = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'configure_project': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'vpn_ip': parameter_types.ip_address,
|
||||
'vpn_port': parameter_types.tcp_udp_port,
|
||||
},
|
||||
'required': ['vpn_ip', 'vpn_port'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['configure_project'],
|
||||
'additionalProperties': False,
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
# Copyright 2010 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
:mod:`nova.cloudpipe` -- VPN Server Management
|
||||
=====================================================
|
||||
|
||||
.. automodule:: nova.cloudpipe
|
||||
:platform: Unix
|
||||
:synopsis: An OpenVPN server for every nova user.
|
||||
"""
|
@ -1,54 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2010 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# This gets zipped and run on the cloudpipe-managed OpenVPN server
|
||||
|
||||
export LC_ALL=C
|
||||
export VPN_IP=`ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{print $$1}'`
|
||||
export BROADCAST=`ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f3 | awk '{print $$1}'`
|
||||
export DHCP_MASK=`ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f4 | awk '{print $$1}'`
|
||||
export GATEWAY=`netstat -r | grep default | cut -d' ' -f10`
|
||||
# Need a higher valued MAC address than eth0, to prevent the TAP MAC address
|
||||
# from becoming the bridge MAC address. Since Essex eth0 MAC starts with
|
||||
# FA:16:3E, we'll thus generate a MAC starting with FA:17:3E to be higher than eth0.
|
||||
export RANDOM_TAP_MAC=`openssl rand -hex 8 | sed 's/\(..\)/\1:/g' | cut -b-8 | awk '{print "FA:17:3E:"$$1}'`
|
||||
|
||||
DHCP_LOWER=`echo $$BROADCAST | awk -F. '{print $$1"."$$2"."$$3"." $$4 - ${num_vpn} }'`
|
||||
DHCP_UPPER=`echo $$BROADCAST | awk -F. '{print $$1"."$$2"."$$3"." $$4 - 1 }'`
|
||||
|
||||
# generate a server DH
|
||||
openssl dhparam -out /etc/openvpn/dh1024.pem 1024
|
||||
|
||||
cp crl.pem /etc/openvpn/
|
||||
cp server.key /etc/openvpn/
|
||||
cp ca.crt /etc/openvpn/
|
||||
cp server.crt /etc/openvpn/
|
||||
# Customize the server.conf.template
|
||||
cd /etc/openvpn
|
||||
|
||||
sed -e s/VPN_IP/$$VPN_IP/g server.conf.template > server.conf
|
||||
sed -i -e s/DHCP_SUBNET/$$DHCP_MASK/g server.conf
|
||||
sed -i -e s/DHCP_LOWER/$$DHCP_LOWER/g server.conf
|
||||
sed -i -e s/DHCP_UPPER/$$DHCP_UPPER/g server.conf
|
||||
sed -i -e s/max-clients\ 1/max-clients\ 10/g server.conf
|
||||
|
||||
echo "push \"route ${dmz_net} ${dmz_mask} $$GATEWAY\"" >> server.conf
|
||||
echo "duplicate-cn" >> server.conf
|
||||
echo "crl-verify /etc/openvpn/crl.pem" >> server.conf
|
||||
echo "lladdr $$RANDOM_TAP_MAC" >> server.conf
|
||||
|
||||
/etc/init.d/openvpn start
|
@ -1,43 +0,0 @@
|
||||
# Copyright 2010 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# NOVA user connection
|
||||
# Edit the following lines to point to your cert files:
|
||||
cert {{ certfile }}
|
||||
key {{ keyfile }}
|
||||
|
||||
ca cacert.pem
|
||||
|
||||
client
|
||||
dev tap
|
||||
proto udp
|
||||
|
||||
remote {{ ip }} {{ port }}
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
|
||||
# Downgrade privileges after initialization (non-Windows only)
|
||||
user nobody
|
||||
group nogroup
|
||||
comp-lzo
|
||||
|
||||
# Set log file verbosity.
|
||||
verb 2
|
||||
|
||||
keepalive 10 120
|
||||
ping-timer-rem
|
||||
persist-tun
|
||||
persist-key
|
@ -1,150 +0,0 @@
|
||||
# Copyright 2010 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""
|
||||
CloudPipe - Build a user-data payload zip file, and launch
|
||||
an instance with it.
|
||||
|
||||
"""
|
||||
|
||||
import base64
|
||||
import os
|
||||
import string
|
||||
import zipfile
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import fileutils
|
||||
|
||||
from nova import compute
|
||||
from nova.compute import flavors
|
||||
import nova.conf
|
||||
from nova import crypto
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova import utils
|
||||
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def is_vpn_image(image_id):
|
||||
return image_id == CONF.cloudpipe.vpn_image_id
|
||||
|
||||
|
||||
def _load_boot_script():
|
||||
with open(CONF.cloudpipe.boot_script_template, "r") as shellfile:
|
||||
s = string.Template(shellfile.read())
|
||||
return s.substitute(dmz_net=CONF.cloudpipe.dmz_net,
|
||||
dmz_mask=CONF.cloudpipe.dmz_mask,
|
||||
num_vpn=CONF.cnt_vpn_clients)
|
||||
|
||||
|
||||
class CloudPipe(object):
|
||||
def __init__(self):
|
||||
self.compute_api = compute.API()
|
||||
|
||||
def get_encoded_zip(self, project_id):
|
||||
# Make a payload.zip
|
||||
with utils.tempdir() as tmpdir:
|
||||
filename = "payload.zip"
|
||||
zippath = os.path.join(tmpdir, filename)
|
||||
z = zipfile.ZipFile(zippath, "w", zipfile.ZIP_DEFLATED)
|
||||
boot_script = _load_boot_script()
|
||||
# genvpn, sign csr
|
||||
crypto.generate_vpn_files(project_id)
|
||||
z.writestr('autorun.sh', boot_script)
|
||||
crl = os.path.join(crypto.ca_folder(project_id), 'crl.pem')
|
||||
z.write(crl, 'crl.pem')
|
||||
server_key = os.path.join(crypto.ca_folder(project_id),
|
||||
'server.key')
|
||||
z.write(server_key, 'server.key')
|
||||
ca_crt = os.path.join(crypto.ca_path(project_id))
|
||||
z.write(ca_crt, 'ca.crt')
|
||||
server_crt = os.path.join(crypto.ca_folder(project_id),
|
||||
'server.crt')
|
||||
z.write(server_crt, 'server.crt')
|
||||
z.close()
|
||||
with open(zippath, "rb") as zippy:
|
||||
# NOTE(vish): run instances expects encoded userdata,
|
||||
# it is decoded in the get_metadata_call.
|
||||
# autorun.sh also decodes the zip file,
|
||||
# hence the double encoding.
|
||||
encoded = base64.b64encode(zippy.read())
|
||||
encoded = base64.b64encode(encoded)
|
||||
|
||||
return encoded
|
||||
|
||||
def launch_vpn_instance(self, context):
|
||||
LOG.debug("Launching VPN for %s", context.project_id)
|
||||
key_name = self.setup_key_pair(context)
|
||||
group_name = self.setup_security_group(context)
|
||||
flavor = flavors.get_flavor_by_name(CONF.cloudpipe.vpn_flavor)
|
||||
instance_name = '%s%s' % (context.project_id,
|
||||
CONF.cloudpipe.vpn_key_suffix)
|
||||
user_data = self.get_encoded_zip(context.project_id)
|
||||
return self.compute_api.create(context,
|
||||
flavor,
|
||||
CONF.cloudpipe.vpn_image_id,
|
||||
display_name=instance_name,
|
||||
user_data=user_data,
|
||||
key_name=key_name,
|
||||
security_groups=[group_name])
|
||||
|
||||
def setup_security_group(self, context):
|
||||
group_name = '%s%s' % (context.project_id,
|
||||
CONF.cloudpipe.vpn_key_suffix)
|
||||
group = {'user_id': context.user_id,
|
||||
'project_id': context.project_id,
|
||||
'name': group_name,
|
||||
'description': 'Group for vpn'}
|
||||
try:
|
||||
group_ref = db.security_group_create(context, group)
|
||||
except exception.SecurityGroupExists:
|
||||
return group_name
|
||||
rule = {'parent_group_id': group_ref['id'],
|
||||
'cidr': '0.0.0.0/0',
|
||||
'protocol': 'udp',
|
||||
'from_port': 1194,
|
||||
'to_port': 1194}
|
||||
db.security_group_rule_create(context, rule)
|
||||
rule = {'parent_group_id': group_ref['id'],
|
||||
'cidr': '0.0.0.0/0',
|
||||
'protocol': 'icmp',
|
||||
'from_port': -1,
|
||||
'to_port': -1}
|
||||
db.security_group_rule_create(context, rule)
|
||||
# NOTE(vish): No need to trigger the group since the instance
|
||||
# has not been run yet.
|
||||
return group_name
|
||||
|
||||
def setup_key_pair(self, context):
|
||||
key_name = '%s%s' % (context.project_id,
|
||||
CONF.cloudpipe.vpn_key_suffix)
|
||||
try:
|
||||
keypair_api = compute.api.KeypairAPI()
|
||||
result, private_key = keypair_api.create_key_pair(context,
|
||||
context.user_id,
|
||||
key_name)
|
||||
key_dir = os.path.join(CONF.crypto.keys_path, context.user_id)
|
||||
fileutils.ensure_tree(key_dir)
|
||||
key_path = os.path.join(key_dir, '%s.pem' % key_name)
|
||||
with open(key_path, 'w') as f:
|
||||
f.write(private_key)
|
||||
except (exception.KeyPairExists, os.error, IOError):
|
||||
pass
|
||||
return key_name
|
@ -55,7 +55,6 @@ from six.moves import range
|
||||
|
||||
from nova import block_device
|
||||
from nova.cells import rpcapi as cells_rpcapi
|
||||
from nova.cloudpipe import pipelib
|
||||
from nova import compute
|
||||
from nova.compute import build_results
|
||||
from nova.compute import claims
|
||||
@ -1460,7 +1459,7 @@ class ComputeManager(manager.Manager):
|
||||
instance.save(expected_task_state=[None])
|
||||
self._update_resource_tracker(context, instance)
|
||||
|
||||
is_vpn = pipelib.is_vpn_image(instance.image_ref)
|
||||
is_vpn = False
|
||||
return network_model.NetworkInfoAsyncWrapper(
|
||||
self._allocate_network_async, context, instance,
|
||||
requested_networks, macs, security_groups, is_vpn,
|
||||
|
@ -25,7 +25,6 @@ from nova.conf import base
|
||||
from nova.conf import cache
|
||||
from nova.conf import cells
|
||||
from nova.conf import cinder
|
||||
from nova.conf import cloudpipe
|
||||
from nova.conf import compute
|
||||
from nova.conf import conductor
|
||||
from nova.conf import configdrive
|
||||
@ -80,7 +79,6 @@ base.register_opts(CONF)
|
||||
cache.register_opts(CONF)
|
||||
cells.register_opts(CONF)
|
||||
cinder.register_opts(CONF)
|
||||
cloudpipe.register_opts(CONF)
|
||||
compute.register_opts(CONF)
|
||||
conductor.register_opts(CONF)
|
||||
configdrive.register_opts(CONF)
|
||||
|
@ -1,121 +0,0 @@
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 oslo_config import cfg
|
||||
|
||||
from nova.conf import paths
|
||||
|
||||
cloudpipe_group = cfg.OptGroup(
|
||||
name='cloudpipe',
|
||||
title='Cloudpipe options')
|
||||
|
||||
cloudpipe_opts = [
|
||||
cfg.StrOpt('vpn_image_id',
|
||||
default='0',
|
||||
deprecated_group='DEFAULT',
|
||||
help="""
|
||||
Image ID used when starting up a cloudpipe VPN client.
|
||||
|
||||
An empty instance is created and configured with OpenVPN using
|
||||
boot_script_template. This instance would be snapshotted and stored
|
||||
in glance. ID of the stored image is used in 'vpn_image_id' to
|
||||
create cloudpipe VPN client.
|
||||
|
||||
Possible values:
|
||||
|
||||
* Any valid ID of a VPN image
|
||||
"""),
|
||||
cfg.StrOpt('vpn_flavor',
|
||||
default='m1.tiny',
|
||||
deprecated_group='DEFAULT',
|
||||
help="""
|
||||
Flavor for VPN instances.
|
||||
|
||||
Possible values:
|
||||
|
||||
* Any valid flavor name
|
||||
"""),
|
||||
cfg.StrOpt('boot_script_template',
|
||||
default=paths.basedir_def('nova/cloudpipe/bootscript.template'),
|
||||
deprecated_group='DEFAULT',
|
||||
help="""
|
||||
Template for cloudpipe instance boot script.
|
||||
|
||||
Possible values:
|
||||
|
||||
* Any valid path to a cloudpipe instance boot script template
|
||||
|
||||
Related options:
|
||||
|
||||
The following options are required to configure cloudpipe-managed
|
||||
OpenVPN server.
|
||||
|
||||
* dmz_net
|
||||
* dmz_mask
|
||||
* cnt_vpn_clients
|
||||
"""),
|
||||
cfg.IPOpt('dmz_net',
|
||||
default='10.0.0.0',
|
||||
deprecated_group='DEFAULT',
|
||||
help="""
|
||||
Network to push into OpenVPN config.
|
||||
|
||||
Note: Above mentioned OpenVPN config can be found at
|
||||
/etc/openvpn/server.conf.
|
||||
|
||||
Possible values:
|
||||
|
||||
* Any valid IPv4/IPV6 address
|
||||
|
||||
Related options:
|
||||
|
||||
* boot_script_template - dmz_net is pushed into bootscript.template
|
||||
to configure cloudpipe-managed OpenVPN server
|
||||
"""),
|
||||
cfg.IPOpt('dmz_mask',
|
||||
default='255.255.255.0',
|
||||
deprecated_group='DEFAULT',
|
||||
help="""
|
||||
Netmask to push into OpenVPN config.
|
||||
|
||||
Possible values:
|
||||
|
||||
* Any valid IPv4/IPV6 netmask
|
||||
|
||||
Related options:
|
||||
|
||||
* dmz_net - dmz_net and dmz_mask is pushed into bootscript.template
|
||||
to configure cloudpipe-managed OpenVPN server
|
||||
* boot_script_template
|
||||
"""),
|
||||
cfg.StrOpt('vpn_key_suffix',
|
||||
default='-vpn',
|
||||
deprecated_group='DEFAULT',
|
||||
help="""
|
||||
Suffix to add to project name for VPN key and secgroups
|
||||
|
||||
Possible values:
|
||||
|
||||
* Any string value representing the VPN key suffix
|
||||
""")
|
||||
]
|
||||
|
||||
|
||||
def register_opts(conf):
|
||||
conf.register_group(cloudpipe_group)
|
||||
conf.register_opts(cloudpipe_opts, group=cloudpipe_group)
|
||||
|
||||
|
||||
def list_opts():
|
||||
return {cloudpipe_group: cloudpipe_opts}
|
@ -195,8 +195,9 @@ Related options:
|
||||
nova-network is deprecated, as are any related configuration options.
|
||||
""",
|
||||
help="""
|
||||
This is the public IP address for the cloudpipe VPN servers. It defaults to the
|
||||
IP address of the host.
|
||||
This option is no longer used since the /os-cloudpipe API was removed in the
|
||||
16.0.0 Pike release. This is the public IP address for the cloudpipe VPN
|
||||
servers. It defaults to the IP address of the host.
|
||||
|
||||
Please note that this option is only used when using nova-network instead of
|
||||
Neutron in your deployment. It also will be ignored if the configuration option
|
||||
|
@ -24,7 +24,6 @@ from nova.policies import baremetal_nodes
|
||||
from nova.policies import base
|
||||
from nova.policies import cells
|
||||
from nova.policies import cells_scheduler
|
||||
from nova.policies import cloudpipe
|
||||
from nova.policies import config_drive
|
||||
from nova.policies import console_auth_tokens
|
||||
from nova.policies import console_output
|
||||
@ -103,7 +102,6 @@ def list_rules():
|
||||
base.list_rules(),
|
||||
cells.list_rules(),
|
||||
cells_scheduler.list_rules(),
|
||||
cloudpipe.list_rules(),
|
||||
config_drive.list_rules(),
|
||||
console_auth_tokens.list_rules(),
|
||||
console_output.list_rules(),
|
||||
|
@ -1,49 +0,0 @@
|
||||
# Copyright 2016 Cloudbase Solutions Srl
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 nova.policies import base
|
||||
|
||||
|
||||
BASE_POLICY_NAME = 'os_compute_api:os-cloudpipe'
|
||||
|
||||
|
||||
cloudpipe_policies = [
|
||||
base.create_rule_default(
|
||||
BASE_POLICY_NAME,
|
||||
base.RULE_ADMIN_API,
|
||||
"""List, create and update cloud pipes.
|
||||
|
||||
os-cloudpipe API is deprecated as this works only with nova-network which \
|
||||
itself is deprecated.
|
||||
""",
|
||||
[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/os-cloudpipe'
|
||||
},
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/os-cloudpipe'
|
||||
},
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/os-cloudpipe/configure-project'
|
||||
}
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return cloudpipe_policies
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"cloudpipe": {
|
||||
"project_id": "%(project_id)s"
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"instance_id": "%(id)s"
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"cloudpipes": [
|
||||
{
|
||||
"created_at": "%(isotime)s",
|
||||
"instance_id": "%(uuid)s",
|
||||
"internal_ip": "%(ip)s",
|
||||
"project_id": "%(project_id)s",
|
||||
"public_ip": "%(ip)s",
|
||||
"public_port": 22,
|
||||
"state": "down"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"configure_project": {
|
||||
"vpn_ip": "%(vpn_ip)s",
|
||||
"vpn_port": "%(vpn_port)s"
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
# Copyright 2014 IBM Corp.
|
||||
#
|
||||
# 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 uuid as uuid_lib
|
||||
|
||||
import nova.conf
|
||||
from nova.tests.functional.api_sample_tests import api_sample_base
|
||||
from nova.tests.unit.image import fake
|
||||
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
|
||||
|
||||
class CloudPipeSampleTest(api_sample_base.ApiSampleTestBaseV21):
|
||||
ADMIN_API = True
|
||||
sample_dir = "os-cloudpipe"
|
||||
|
||||
def setUp(self):
|
||||
super(CloudPipeSampleTest, self).setUp()
|
||||
|
||||
def get_user_data(self, project_id):
|
||||
"""Stub method to generate user data for cloudpipe tests."""
|
||||
return "VVNFUiBEQVRB\n"
|
||||
|
||||
def network_api_get(self, context, network_uuid):
|
||||
"""Stub to get a valid network and its information."""
|
||||
return {'vpn_public_address': '127.0.0.1',
|
||||
'vpn_public_port': 22}
|
||||
|
||||
self.stub_out('nova.cloudpipe.pipelib.CloudPipe.get_encoded_zip',
|
||||
get_user_data)
|
||||
self.stub_out('nova.network.api.API.get',
|
||||
network_api_get)
|
||||
|
||||
def generalize_subs(self, subs, vanilla_regexes):
|
||||
subs['project_id'] = '[0-9a-f-]+'
|
||||
return subs
|
||||
|
||||
def test_cloud_pipe_create(self):
|
||||
# Get api samples of cloud pipe extension creation.
|
||||
self.flags(vpn_image_id=fake.get_valid_image_id(), group='cloudpipe')
|
||||
subs = {'project_id': str(uuid_lib.uuid4().hex)}
|
||||
response = self._do_post('os-cloudpipe', 'cloud-pipe-create-req',
|
||||
subs)
|
||||
subs['image_id'] = CONF.cloudpipe.vpn_image_id
|
||||
self._verify_response('cloud-pipe-create-resp', subs, response, 200)
|
||||
return subs
|
||||
|
||||
def test_cloud_pipe_list(self):
|
||||
# Get api samples of cloud pipe extension get request.
|
||||
subs = self.test_cloud_pipe_create()
|
||||
response = self._do_get('os-cloudpipe')
|
||||
subs['image_id'] = CONF.cloudpipe.vpn_image_id
|
||||
self._verify_response('cloud-pipe-get-resp', subs, response, 200)
|
||||
|
||||
def test_cloud_pipe_update(self):
|
||||
subs = {'vpn_ip': '192.168.1.1',
|
||||
'vpn_port': '2000'}
|
||||
response = self._do_put('os-cloudpipe/configure-project',
|
||||
'cloud-pipe-update-req',
|
||||
subs)
|
||||
self.assertEqual(202, response.status_code)
|
||||
self.assertEqual("", response.text)
|
@ -15,38 +15,14 @@
|
||||
|
||||
import uuid as uuid_lib
|
||||
|
||||
import mock
|
||||
from oslo_utils import timeutils
|
||||
from webob import exc
|
||||
|
||||
from nova.api.openstack.compute import cloudpipe as cloudpipe_v21
|
||||
from nova.compute import utils as compute_utils
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
from nova import test
|
||||
from nova.tests.unit.api.openstack import fakes
|
||||
from nova.tests.unit import fake_network
|
||||
from nova.tests.unit import matchers
|
||||
from nova.tests import uuidsentinel as uuids
|
||||
from nova import utils
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
|
||||
|
||||
project_id = str(uuid_lib.uuid4().hex)
|
||||
uuid = uuids.fake
|
||||
|
||||
|
||||
def fake_vpn_instance():
|
||||
return objects.Instance(
|
||||
id=7, image_ref=CONF.cloudpipe.vpn_image_id, vm_state='active',
|
||||
created_at=timeutils.parse_strtime('1981-10-20T00:00:00.000000'),
|
||||
uuid=uuid, project_id=project_id)
|
||||
|
||||
|
||||
def compute_api_get_all(context, search_opts=None):
|
||||
return [fake_vpn_instance()]
|
||||
|
||||
|
||||
class CloudpipeTestV21(test.NoDBTestCase):
|
||||
@ -58,141 +34,15 @@ class CloudpipeTestV21(test.NoDBTestCase):
|
||||
self.controller = self.cloudpipe.CloudpipeController()
|
||||
self.req = fakes.HTTPRequest.blank('')
|
||||
|
||||
def test_cloudpipe_list_no_network(self):
|
||||
with test.nested(
|
||||
mock.patch.object(compute_utils, 'get_nw_info_for_instance',
|
||||
return_value={}),
|
||||
mock.patch.object(self.controller.compute_api, "get_all",
|
||||
side_effect=compute_api_get_all)
|
||||
) as (mock_utils_get_nw, mock_cpu_get_all):
|
||||
res_dict = self.controller.index(self.req)
|
||||
response = {'cloudpipes': [{'project_id': project_id,
|
||||
'instance_id': uuid,
|
||||
'created_at': '1981-10-20T00:00:00Z'}]}
|
||||
|
||||
self.assertEqual(response, res_dict)
|
||||
self.assertTrue(mock_cpu_get_all.called)
|
||||
self.assertTrue(mock_utils_get_nw.called)
|
||||
|
||||
def test_cloudpipe_list(self):
|
||||
|
||||
def network_api_get(context, network_id):
|
||||
self.assertEqual(context.project_id, project_id)
|
||||
return {'vpn_public_address': '127.0.0.1',
|
||||
'vpn_public_port': 22}
|
||||
|
||||
def fake_get_nw_info_for_instance(instance):
|
||||
return fake_network.fake_get_instance_nw_info(self)
|
||||
|
||||
with test.nested(
|
||||
mock.patch.object(utils, 'vpn_ping', return_value=True),
|
||||
mock.patch.object(compute_utils, 'get_nw_info_for_instance',
|
||||
side_effect=fake_get_nw_info_for_instance),
|
||||
mock.patch.object(self.controller.network_api, "get",
|
||||
side_effect=network_api_get),
|
||||
mock.patch.object(self.controller.compute_api, "get_all",
|
||||
side_effect=compute_api_get_all)
|
||||
) as (mock_vpn_ping, mock_utils_get, mock_nw_get, mock_cpu_get_all):
|
||||
res_dict = self.controller.index(self.req)
|
||||
response = {'cloudpipes': [{'project_id': project_id,
|
||||
'internal_ip': '192.168.1.100',
|
||||
'public_ip': '127.0.0.1',
|
||||
'public_port': 22,
|
||||
'state': 'running',
|
||||
'instance_id': uuid,
|
||||
'created_at': '1981-10-20T00:00:00Z'}]}
|
||||
|
||||
self.assertThat(response, matchers.DictMatches(res_dict))
|
||||
self.assertTrue(mock_cpu_get_all.called)
|
||||
self.assertTrue(mock_nw_get.called)
|
||||
self.assertTrue(mock_utils_get.called)
|
||||
self.assertTrue(mock_vpn_ping.called)
|
||||
self.assertRaises(exc.HTTPGone, self.controller.index, self.req)
|
||||
|
||||
def test_cloudpipe_create(self):
|
||||
def _launch_vpn_instance(context):
|
||||
return ([fake_vpn_instance()], 'fake-reservation')
|
||||
body = {'cloudpipe': {'project_id': project_id}}
|
||||
self.assertRaises(exc.HTTPGone, self.controller.create,
|
||||
self.req, body=body)
|
||||
|
||||
with test.nested(
|
||||
mock.patch.object(self.controller.compute_api, "get_all",
|
||||
return_value=[]),
|
||||
mock.patch.object(self.controller.cloudpipe,
|
||||
'launch_vpn_instance',
|
||||
side_effect=_launch_vpn_instance),
|
||||
) as (mock_cpu_get_all, mock_vpn_launch):
|
||||
body = {'cloudpipe': {'project_id': project_id}}
|
||||
res_dict = self.controller.create(self.req, body=body)
|
||||
response = {'instance_id': uuid}
|
||||
|
||||
self.assertEqual(response, res_dict)
|
||||
self.assertTrue(mock_cpu_get_all.called)
|
||||
self.assertTrue(mock_vpn_launch.called)
|
||||
|
||||
def test_cloudpipe_create_no_networks(self):
|
||||
with test.nested(
|
||||
mock.patch.object(self.controller.compute_api, "get_all",
|
||||
return_value=[]),
|
||||
mock.patch.object(self.controller.cloudpipe,
|
||||
'launch_vpn_instance',
|
||||
side_effect=exception.NoMoreNetworks),
|
||||
) as (mock_cpu_get_all, mock_vpn_launch):
|
||||
body = {'cloudpipe': {'project_id': project_id}}
|
||||
req = fakes.HTTPRequest.blank(self.url)
|
||||
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.create, req, body=body)
|
||||
self.assertTrue(mock_cpu_get_all.called)
|
||||
self.assertTrue(mock_vpn_launch.called)
|
||||
|
||||
def test_cloudpipe_create_already_running(self):
|
||||
with test.nested(
|
||||
mock.patch.object(self.controller.cloudpipe,
|
||||
'launch_vpn_instance'),
|
||||
mock.patch.object(self.controller.compute_api, "get_all",
|
||||
side_effect=compute_api_get_all),
|
||||
) as (mock_vpn_launch, mock_cpu_get_all):
|
||||
body = {'cloudpipe': {'project_id': project_id}}
|
||||
req = fakes.HTTPRequest.blank(self.url)
|
||||
res_dict = self.controller.create(req, body=body)
|
||||
response = {'instance_id': uuid}
|
||||
|
||||
self.assertEqual(response, res_dict)
|
||||
# cloudpipe.launch_vpn_instance() should not be called
|
||||
self.assertFalse(mock_vpn_launch.called)
|
||||
self.assertTrue(mock_cpu_get_all.called)
|
||||
|
||||
def test_cloudpipe_create_with_bad_project_id_failed(self):
|
||||
body = {'cloudpipe': {'project_id': 'bad.project.id'}}
|
||||
req = fakes.HTTPRequest.blank(self.url)
|
||||
self.assertRaises(exception.ValidationError,
|
||||
self.controller.create, req, body=body)
|
||||
|
||||
|
||||
class CloudpipePolicyEnforcementV21(test.NoDBTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(CloudpipePolicyEnforcementV21, self).setUp()
|
||||
self.controller = cloudpipe_v21.CloudpipeController()
|
||||
self.req = fakes.HTTPRequest.blank('')
|
||||
|
||||
def _common_policy_check(self, func, *arg, **kwarg):
|
||||
rule_name = "os_compute_api:os-cloudpipe"
|
||||
rule = {rule_name: "project:non_fake"}
|
||||
self.policy.set_rules(rule)
|
||||
exc = self.assertRaises(
|
||||
exception.PolicyNotAuthorized, func, *arg, **kwarg)
|
||||
self.assertEqual(
|
||||
"Policy doesn't allow %s to be performed." % rule_name,
|
||||
exc.format_message())
|
||||
|
||||
def test_list_policy_failed(self):
|
||||
self._common_policy_check(self.controller.index, self.req)
|
||||
|
||||
def test_create_policy_failed(self):
|
||||
body = {'cloudpipe': {'project_id': uuid}}
|
||||
self._common_policy_check(self.controller.create, self.req, body=body)
|
||||
|
||||
def test_update_policy_failed(self):
|
||||
body = {"configure_project": {'vpn_ip': '192.168.1.1',
|
||||
'vpn_port': 2000}}
|
||||
self._common_policy_check(
|
||||
self.controller.update, self.req, uuid, body=body)
|
||||
def test_cloudpipe_configure_project(self):
|
||||
body = {"configure_project": {"vpn_ip": "1.2.3.4", "vpn_port": 222}}
|
||||
self.assertRaises(exc.HTTPGone, self.controller.update,
|
||||
self.req, 'configure-project', body=body)
|
||||
|
@ -15,74 +15,21 @@
|
||||
import webob
|
||||
|
||||
from nova.api.openstack.compute import cloudpipe as clup_v21
|
||||
from nova import exception
|
||||
from nova import test
|
||||
from nova.tests.unit.api.openstack import fakes
|
||||
from nova.tests.unit import fake_network
|
||||
|
||||
|
||||
fake_networks = [fake_network.fake_network(1),
|
||||
fake_network.fake_network(2)]
|
||||
|
||||
|
||||
def fake_project_get_networks(context, project_id, associate=True):
|
||||
return fake_networks
|
||||
|
||||
|
||||
def fake_network_update(context, network_id, values):
|
||||
for network in fake_networks:
|
||||
if network['id'] == network_id:
|
||||
for key in values:
|
||||
network[key] = values[key]
|
||||
|
||||
|
||||
class CloudpipeUpdateTestV21(test.NoDBTestCase):
|
||||
bad_request = exception.ValidationError
|
||||
|
||||
def setUp(self):
|
||||
super(CloudpipeUpdateTestV21, self).setUp()
|
||||
self.stub_out("nova.db.project_get_networks",
|
||||
fake_project_get_networks)
|
||||
self.stub_out("nova.db.network_update", fake_network_update)
|
||||
self._setup()
|
||||
self.req = fakes.HTTPRequest.blank('')
|
||||
|
||||
def _setup(self):
|
||||
self.controller = clup_v21.CloudpipeController()
|
||||
self.req = fakes.HTTPRequest.blank('')
|
||||
|
||||
def _check_status(self, expected_status, res, controller_method):
|
||||
self.assertEqual(expected_status, controller_method.wsgi_code)
|
||||
|
||||
def test_cloudpipe_configure_project(self):
|
||||
body = {"configure_project": {"vpn_ip": "1.2.3.4", "vpn_port": 222}}
|
||||
result = self.controller.update(self.req, 'configure-project',
|
||||
body=body)
|
||||
self._check_status(202, result, self.controller.update)
|
||||
self.assertEqual(fake_networks[0]['vpn_public_address'], "1.2.3.4")
|
||||
self.assertEqual(fake_networks[0]['vpn_public_port'], 222)
|
||||
|
||||
def test_cloudpipe_configure_project_bad_url(self):
|
||||
body = {"configure_project": {"vpn_ip": "1.2.3.4", "vpn_port": 222}}
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.controller.update, self.req,
|
||||
'configure-projectx', body=body)
|
||||
|
||||
def test_cloudpipe_configure_project_bad_data(self):
|
||||
body = {"configure_project": {"vpn_ipxx": "1.2.3.4", "vpn_port": 222}}
|
||||
self.assertRaises(self.bad_request,
|
||||
self.controller.update, self.req,
|
||||
'configure-project', body=body)
|
||||
|
||||
def test_cloudpipe_configure_project_bad_vpn_port(self):
|
||||
body = {"configure_project": {"vpn_ipxx": "1.2.3.4",
|
||||
"vpn_port": "foo"}}
|
||||
self.assertRaises(self.bad_request,
|
||||
self.controller.update, self.req,
|
||||
'configure-project', body=body)
|
||||
|
||||
def test_cloudpipe_configure_project_vpn_port_with_empty_string(self):
|
||||
body = {"configure_project": {"vpn_ipxx": "1.2.3.4",
|
||||
"vpn_port": ""}}
|
||||
self.assertRaises(self.bad_request,
|
||||
self.controller.update, self.req,
|
||||
'configure-project', body=body)
|
||||
self.assertRaises(webob.exc.HTTPGone, self.controller.update,
|
||||
self.req, 'configure-project', body=body)
|
||||
|
@ -27,7 +27,6 @@ policy_data = """
|
||||
"os_compute_api:os-attach-interfaces": "",
|
||||
"os_compute_api:os-baremetal-nodes": "",
|
||||
"os_compute_api:os-cells": "",
|
||||
"os_compute_api:os-cloudpipe": "",
|
||||
"os_compute_api:os-config-drive": "",
|
||||
"os_compute_api:os-console-output": "",
|
||||
"os_compute_api:os-remote-consoles": "",
|
||||
|
@ -1,77 +0,0 @@
|
||||
# Copyright 2011 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 mock
|
||||
from oslo_config import cfg
|
||||
|
||||
from nova.cloudpipe import pipelib
|
||||
from nova import context
|
||||
from nova import crypto
|
||||
from nova import test
|
||||
from nova import utils
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class PipelibTest(test.TestCase):
|
||||
def setUp(self):
|
||||
super(PipelibTest, self).setUp()
|
||||
self.cloudpipe = pipelib.CloudPipe()
|
||||
self.project = "222"
|
||||
self.user = "111"
|
||||
self.context = context.RequestContext(self.user, self.project)
|
||||
|
||||
def test_get_encoded_zip(self):
|
||||
with utils.tempdir() as tmpdir:
|
||||
self.flags(ca_path=tmpdir, group='crypto')
|
||||
crypto.ensure_ca_filesystem()
|
||||
|
||||
ret = self.cloudpipe.get_encoded_zip(self.project)
|
||||
self.assertTrue(ret)
|
||||
|
||||
def test_launch_vpn_instance(self):
|
||||
@mock.patch.object(self.cloudpipe.compute_api, 'create',
|
||||
return_value=lambda *a, **kw: (None, "r-fakeres"))
|
||||
def _do_test(mock_create):
|
||||
with utils.tempdir() as tmpdir:
|
||||
self.flags(ca_path=tmpdir, keys_path=tmpdir, group='crypto')
|
||||
crypto.ensure_ca_filesystem()
|
||||
self.cloudpipe.launch_vpn_instance(self.context)
|
||||
|
||||
_do_test()
|
||||
|
||||
def test_setup_security_group(self):
|
||||
group_name = "%s%s" % (self.project, CONF.cloudpipe.vpn_key_suffix)
|
||||
|
||||
# First attempt, does not exist (thus its created)
|
||||
res1_group = self.cloudpipe.setup_security_group(self.context)
|
||||
self.assertEqual(res1_group, group_name)
|
||||
|
||||
# Second attempt, it exists in the DB
|
||||
res2_group = self.cloudpipe.setup_security_group(self.context)
|
||||
self.assertEqual(res1_group, res2_group)
|
||||
|
||||
def test_setup_key_pair(self):
|
||||
key_name = "%s%s" % (self.project, CONF.cloudpipe.vpn_key_suffix)
|
||||
with utils.tempdir() as tmpdir:
|
||||
self.flags(keys_path=tmpdir, group='crypto')
|
||||
|
||||
# First attempt, key does not exist (thus it is generated)
|
||||
res1_key = self.cloudpipe.setup_key_pair(self.context)
|
||||
self.assertEqual(res1_key, key_name)
|
||||
|
||||
# Second attempt, it exists in the DB
|
||||
res2_key = self.cloudpipe.setup_key_pair(self.context)
|
||||
self.assertEqual(res2_key, res1_key)
|
@ -291,7 +291,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
|
||||
"os_compute_api:os-cells:delete",
|
||||
"os_compute_api:os-cells:update",
|
||||
"os_compute_api:os-cells:sync_instances",
|
||||
"os_compute_api:os-cloudpipe",
|
||||
"os_compute_api:os-evacuate",
|
||||
"os_compute_api:os-extended-server-attributes",
|
||||
"os_compute_api:os-fixed-ips",
|
||||
|
@ -23,7 +23,6 @@ from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
from oslo_utils import importutils
|
||||
|
||||
from nova.cloudpipe import pipelib
|
||||
import nova.conf
|
||||
from nova.i18n import _LI
|
||||
from nova.i18n import _LW
|
||||
@ -190,9 +189,7 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
|
||||
filters added to the list must also be correctly defined
|
||||
within the subclass.
|
||||
"""
|
||||
if pipelib.is_vpn_image(instance.image_ref):
|
||||
base_filter = 'nova-vpn'
|
||||
elif allow_dhcp:
|
||||
if allow_dhcp:
|
||||
base_filter = 'nova-base'
|
||||
else:
|
||||
base_filter = 'nova-nodhcp'
|
||||
@ -218,8 +215,6 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
|
||||
self._define_filter(self._filter_container('nova-nodhcp', filter_set))
|
||||
filter_set.append('allow-dhcp-server')
|
||||
self._define_filter(self._filter_container('nova-base', filter_set))
|
||||
self._define_filter(self._filter_container('nova-vpn',
|
||||
['allow-dhcp-server']))
|
||||
self._define_filter(self.nova_dhcp_filter())
|
||||
|
||||
self.static_filters_configured = True
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
upgrade:
|
||||
- The deprecated /os-cloudpipe API endpoint has been removed. Whenever calls
|
||||
are made to that endpoint it now returns a 410 response.
|
Loading…
Reference in New Issue
Block a user