Port security-group-default-rules extension into v2.1

This patch port security-group-default-rules into v2.1.

This patch just move the v2 code into v2.1 and share the unittest. The other
v2.1 related fix and improvement will be addressed by subsequent patchset.

Partially implements blueprint v2-on-v3-api

Change-Id: I4d65993d6413160d2c7c2eb2ce0c3f66768e1a36
This commit is contained in:
He Jie Xu 2014-09-26 13:58:09 +08:00
parent 94b006e210
commit c7d9924a08
14 changed files with 317 additions and 12 deletions

View File

@ -0,0 +1,8 @@
{
"security_group_default_rule": {
"ip_protocol": "TCP",
"from_port": "80",
"to_port": "80",
"cidr": "10.10.10.0/24"
}
}

View File

@ -0,0 +1,11 @@
{
"security_group_default_rule": {
"from_port": 80,
"id": 1,
"ip_protocol": "TCP",
"ip_range": {
"cidr": "10.10.10.0/24"
},
"to_port": 80
}
}

View File

@ -0,0 +1,13 @@
{
"security_group_default_rules": [
{
"from_port": 80,
"id": 1,
"ip_protocol": "TCP",
"ip_range": {
"cidr": "10.10.10.0/24"
},
"to_port": 80
}
]
}

View File

@ -0,0 +1,11 @@
{
"security_group_default_rule": {
"from_port": 80,
"id": 1,
"ip_protocol": "TCP",
"ip_range": {
"cidr": "10.10.10.0/24"
},
"to_port": 80
}
}

View File

@ -242,6 +242,8 @@
"compute_extension:v3:os-rescue:discoverable": "",
"compute_extension:v3:os-scheduler-hints:discoverable": "",
"compute_extension:security_group_default_rules": "rule:admin_api",
"compute_extension:v3:os-security-group-default-rules:discoverable": "",
"compute_extension:v3:os-security-group-default-rules": "rule:admin_api",
"compute_extension:security_groups": "",
"compute_extension:v3:os-security-groups": "",
"compute_extension:v3:os-security-groups:discoverable": "",

View File

@ -0,0 +1,158 @@
# Copyright 2013 Metacloud 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 webob import exc
from nova.api.openstack.compute.plugins.v3 import security_groups as sg
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova import exception
from nova.i18n import _
from nova.network.security_group import openstack_driver
ALIAS = "os-security-group-default-rules"
authorize = extensions.extension_authorizer('compute', 'v3:' + ALIAS)
def _authorize_context(req):
context = req.environ['nova.context']
authorize(context)
return context
class SecurityGroupDefaultRulesController(sg.SecurityGroupControllerBase):
def __init__(self):
self.security_group_api = (
openstack_driver.get_openstack_security_group_driver())
@extensions.expected_errors((400, 501))
def create(self, req, body):
context = sg._authorize_context(req)
authorize(context)
sg_rule = self._from_body(body, 'security_group_default_rule')
try:
values = self._rule_args_to_dict(to_port=sg_rule.get('to_port'),
from_port=sg_rule.get('from_port'),
ip_protocol=sg_rule.get('ip_protocol'),
cidr=sg_rule.get('cidr'))
except (exception.InvalidCidr,
exception.InvalidInput,
exception.InvalidIpProtocol,
exception.InvalidPortRange) as ex:
raise exc.HTTPBadRequest(explanation=ex.format_message())
if values is None:
msg = _('Not enough parameters to build a valid rule.')
raise exc.HTTPBadRequest(explanation=msg)
if self.security_group_api.default_rule_exists(context, values):
msg = _('This default rule already exists.')
raise exc.HTTPBadRequest(explanation=msg)
security_group_rule = self.security_group_api.add_default_rules(
context, [values])[0]
fmt_rule = self._format_security_group_default_rule(
security_group_rule)
return {'security_group_default_rule': fmt_rule}
def _rule_args_to_dict(self, to_port=None, from_port=None,
ip_protocol=None, cidr=None):
cidr = self.security_group_api.parse_cidr(cidr)
return self.security_group_api.new_cidr_ingress_rule(
cidr, ip_protocol, from_port, to_port)
@extensions.expected_errors((400, 404, 501))
def show(self, req, id):
context = sg._authorize_context(req)
authorize(context)
try:
id = self.security_group_api.validate_id(id)
except exception.Invalid as ex:
raise exc.HTTPBadRequest(explanation=ex.format_message())
try:
rule = self.security_group_api.get_default_rule(context, id)
except exception.SecurityGroupNotFound as ex:
raise exc.HTTPNotFound(explanation=ex.format_message())
fmt_rule = self._format_security_group_default_rule(rule)
return {"security_group_default_rule": fmt_rule}
@extensions.expected_errors((400, 404, 501))
@wsgi.response(204)
def delete(self, req, id):
context = sg._authorize_context(req)
authorize(context)
try:
id = self.security_group_api.validate_id(id)
except exception.Invalid as ex:
raise exc.HTTPBadRequest(explanation=ex.format_message())
try:
rule = self.security_group_api.get_default_rule(context, id)
except exception.SecurityGroupNotFound as ex:
raise exc.HTTPNotFound(explanation=ex.format_message())
try:
self.security_group_api.remove_default_rules(context, [rule['id']])
except exception.SecurityGroupDefaultRuleNotFound as ex:
raise exc.HTTPNotFound(explanation=ex.format_message())
@extensions.expected_errors((404, 501))
def index(self, req):
context = sg._authorize_context(req)
authorize(context)
ret = {'security_group_default_rules': []}
try:
for rule in self.security_group_api.get_all_default_rules(context):
rule_fmt = self._format_security_group_default_rule(rule)
ret['security_group_default_rules'].append(rule_fmt)
except exception.SecurityGroupDefaultRuleNotFound as ex:
raise exc.HTTPNotFound(explanation=ex.format_message())
return ret
def _format_security_group_default_rule(self, rule):
sg_rule = {}
sg_rule['id'] = rule['id']
sg_rule['ip_protocol'] = rule['protocol']
sg_rule['from_port'] = rule['from_port']
sg_rule['to_port'] = rule['to_port']
sg_rule['ip_range'] = {}
sg_rule['ip_range'] = {'cidr': rule['cidr']}
return sg_rule
class SecurityGroupDefaultRules(extensions.V3APIExtensionBase):
"""Default rules for security group support."""
name = "SecurityGroupDefaultRules"
alias = ALIAS
version = 1
def get_resources(self):
resources = [
extensions.ResourceExtension(ALIAS,
SecurityGroupDefaultRulesController())]
return resources
def get_controller_extensions(self):
return []

View File

@ -16,7 +16,10 @@ from lxml import etree
from oslo.config import cfg
import webob
from nova.api.openstack.compute.contrib import security_group_default_rules
from nova.api.openstack.compute.contrib import \
security_group_default_rules as security_group_default_rules_v2
from nova.api.openstack.compute.plugins.v3 import \
security_group_default_rules as security_group_default_rules_v21
from nova.api.openstack import wsgi
from nova import context
import nova.db
@ -48,12 +51,14 @@ def security_group_default_rule_db(security_group_default_rule, id=None):
return AttrDict(attrs)
class TestSecurityGroupDefaultRulesNeutron(test.TestCase):
class TestSecurityGroupDefaultRulesNeutronV21(test.TestCase):
controller_cls = (security_group_default_rules_v21.
SecurityGroupDefaultRulesController)
def setUp(self):
self.flags(security_group_api='neutron')
super(TestSecurityGroupDefaultRulesNeutron, self).setUp()
self.controller = \
security_group_default_rules.SecurityGroupDefaultRulesController()
super(TestSecurityGroupDefaultRulesNeutronV21, self).setUp()
self.controller = self.controller_cls()
def test_create_security_group_default_rule_not_implemented_neutron(self):
sgr = security_group_default_rule_template()
@ -81,11 +86,18 @@ class TestSecurityGroupDefaultRulesNeutron(test.TestCase):
req, '602ed77c-a076-4f9b-a617-f93b847b62c5')
class TestSecurityGroupDefaultRules(test.TestCase):
class TestSecurityGroupDefaultRulesNeutronV2(test.TestCase):
controller_cls = (security_group_default_rules_v2.
SecurityGroupDefaultRulesController)
class TestSecurityGroupDefaultRulesV21(test.TestCase):
controller_cls = (security_group_default_rules_v21.
SecurityGroupDefaultRulesController)
def setUp(self):
super(TestSecurityGroupDefaultRules, self).setUp()
self.controller = \
security_group_default_rules.SecurityGroupDefaultRulesController()
super(TestSecurityGroupDefaultRulesV21, self).setUp()
self.controller = self.controller_cls()
def test_create_security_group_default_rule(self):
sgr = security_group_default_rule_template()
@ -323,10 +335,15 @@ class TestSecurityGroupDefaultRules(test.TestCase):
self.assertEqual(sgr['cidr'], security_group_rule.cidr)
class TestSecurityGroupDefaultRulesV2(test.TestCase):
controller_cls = (security_group_default_rules_v2.
SecurityGroupDefaultRulesController)
class TestSecurityGroupDefaultRulesXMLDeserializer(test.TestCase):
def setUp(self):
super(TestSecurityGroupDefaultRulesXMLDeserializer, self).setUp()
deserializer = security_group_default_rules.\
deserializer = security_group_default_rules_v2.\
SecurityGroupDefaultRulesXMLDeserializer()
self.deserializer = deserializer
@ -423,9 +440,9 @@ class TestSecurityGroupDefaultRuleXMLSerializer(test.TestCase):
super(TestSecurityGroupDefaultRuleXMLSerializer, self).setUp()
self.namespace = wsgi.XMLNS_V11
self.rule_serializer =\
security_group_default_rules.SecurityGroupDefaultRuleTemplate()
security_group_default_rules_v2.SecurityGroupDefaultRuleTemplate()
self.index_serializer =\
security_group_default_rules.SecurityGroupDefaultRulesTemplate()
security_group_default_rules_v2.SecurityGroupDefaultRulesTemplate()
def _tag(self, elem):
tagname = elem.tag

View File

@ -279,6 +279,7 @@ policy_data = """
"compute_extension:rescue": "",
"compute_extension:v3:os-rescue": "",
"compute_extension:security_group_default_rules": "",
"compute_extension:v3:os-security-group-default-rules": "",
"compute_extension:security_groups": "",
"compute_extension:v3:os-security-groups": "",
"compute_extension:server_diagnostics": "",

View File

@ -0,0 +1,8 @@
{
"security_group_default_rule": {
"ip_protocol": "TCP",
"from_port": "80",
"to_port": "80",
"cidr": "10.10.10.0/24"
}
}

View File

@ -0,0 +1,11 @@
{
"security_group_default_rule": {
"from_port": 80,
"id": 1,
"ip_protocol": "TCP",
"ip_range":{
"cidr": "10.10.10.0/24"
},
"to_port": 80
}
}

View File

@ -0,0 +1,13 @@
{
"security_group_default_rules": [
{
"from_port": 80,
"id": 1,
"ip_protocol": "TCP",
"ip_range": {
"cidr": "10.10.10.0/24"
},
"to_port": 80
}
]
}

View File

@ -0,0 +1,11 @@
{
"security_group_default_rule": {
"id": 1,
"from_port": 80,
"to_port": 80,
"ip_protocol": "TCP",
"ip_range": {
"cidr": "10.10.10.0/24"
}
}
}

View File

@ -0,0 +1,40 @@
# 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.
from nova.tests.integrated.v3 import api_sample_base
class SecurityGroupDefaultRulesSampleJsonTest(
api_sample_base.ApiSampleTestBaseV3):
extension_name = 'os-security-group-default-rules'
def test_security_group_default_rules_create(self):
response = self._do_post('os-security-group-default-rules',
'security-group-default-rules-create-req',
{})
self._verify_response('security-group-default-rules-create-resp',
{}, response, 200)
def test_security_group_default_rules_list(self):
self.test_security_group_default_rules_create()
response = self._do_get('os-security-group-default-rules')
self._verify_response('security-group-default-rules-list-resp',
{}, response, 200)
def test_security_group_default_rules_show(self):
self.test_security_group_default_rules_create()
rule_id = '1'
response = self._do_get('os-security-group-default-rules/%s' % rule_id)
self._verify_response('security-group-default-rules-show-resp',
{}, response, 200)

View File

@ -114,6 +114,7 @@ nova.api.v3.extensions =
remote_consoles = nova.api.openstack.compute.plugins.v3.remote_consoles:RemoteConsoles
rescue = nova.api.openstack.compute.plugins.v3.rescue:Rescue
scheduler_hints = nova.api.openstack.compute.plugins.v3.scheduler_hints:SchedulerHints
security_group_default_rules = nova.api.openstack.compute.plugins.v3.security_group_default_rules:SecurityGroupDefaultRules
security_groups = nova.api.openstack.compute.plugins.v3.security_groups:SecurityGroups
server_diagnostics = nova.api.openstack.compute.plugins.v3.server_diagnostics:ServerDiagnostics
server_external_events = nova.api.openstack.compute.plugins.v3.server_external_events:ServerExternalEvents