Network Rest API for Angular Front End

This is the API which abstracts Nova vs Neutron calls
for the angular front end.

This initial patch will only implement the APIs needed to
support the launch instance work.

Partially Implements: blueprint launch-instance-redesign

Change-Id: I6967fbae472e6aa944994d94ab327c4fb594b1d0
Co-Authored-By: Richard Jones <r1chardj0n3s@gmail.com>
This commit is contained in:
Travis Tripp 2015-02-18 22:13:17 -07:00
parent 84b3915dcc
commit c7a3e891fe
7 changed files with 182 additions and 0 deletions

View File

@ -0,0 +1,75 @@
/*
Copyright 2015, Hewlett-Packard Development Company, L.P.
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.
*/
(function () {
'use strict';
/**
* @ngdoc service
* @name hz.api.SecurityGroup
* @description Provides access to Security Groups
*/
function SecurityGroup(apiService) {
/**
* @name hz.api.SecurityGroup.list
* @description
* Get a list of security groups.
*
* The listing result is an object with property "items". Each item is
* an image.
*
* @example
* The following is an example response:
* {
* "items": [
* {
* "description": "Default security group",
* "id": "4a4c9dd4-ffa0-454a-beaa-23e8fa569062",
* "name": "default",
* "security_group_rules": [
* {
* "direction": "ingress",
* "ethertype": "IPv4",
* "id": "22961412-fba1-4d0d-8eb8-d4460c921346",
* "port_range_max": null,
* "port_range_min": null,
* "protocol": null,
* "remote_group_id": "4a4c9dd4-ffa0-454a-beaa-23e8fa569062",
* "remote_ip_prefix": null,
* "security_group_id": "4a4c9dd4-ffa0-454a-beaa-23e8fa569062",
* "tenant_id": "3f867827f7eb45d4aa1d1395237f426b"
* }
* ],
* "tenant_id": "3f867827f7eb45d4aa1d1395237f426b"
* }
* ]
* }
*/
this.query = function() {
return apiService.get('/api/network/securitygroups/')
.error(function () {
horizon.alert('error', gettext('Unable to retrieve security groups.'));
});
};
}
// Register it with the API module so that anybody using the
// API module will have access to the Security Group APIs.
angular.module('hz.api')
.service('securityGroup', ['apiService', SecurityGroup]);
}());

View File

@ -143,6 +143,9 @@ class SecurityGroup(NeutronAPIDictWrapper):
for rule in sg['security_group_rules']]
super(SecurityGroup, self).__init__(sg)
def to_dict(self):
return {k: self._apidict[k] for k in self._apidict if k != 'rules'}
class SecurityGroupRule(NeutronAPIDictWrapper):
# Required attributes:

View File

@ -214,6 +214,9 @@ class SecurityGroup(base.APIResourceWrapper):
for rule in self._apiresource.rules]
return [SecurityGroupRule(rule) for rule in rule_objs]
def to_dict(self):
return self._apiresource.to_dict()
class SecurityGroupRule(base.APIResourceWrapper):
"""Wrapper for individual rules in a SecurityGroup."""

View File

@ -25,4 +25,5 @@ in https://wiki.openstack.org/wiki/APIChangeGuidelines.
import cinder #flake8: noqa
import glance #flake8: noqa
import keystone #flake8: noqa
import network #flake8: noqa
import nova #flake8: noqa

View File

@ -0,0 +1,46 @@
# Copyright 2015, Hewlett-Packard Development Company, L.P.
#
# 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.
"""API for the network abstraction APIs.
"""
from django.views import generic
from openstack_dashboard import api
from openstack_dashboard.api.rest import urls
from openstack_dashboard.api.rest import utils as rest_utils
@urls.register
class SecurityGroups(generic.View):
"""API for Network Abstraction
Handles differences between Nova and Neutron.
"""
url_regex = r'network/securitygroups/$'
@rest_utils.ajax()
def get(self, request):
"""Get a list of security groups.
The listing result is an object with property "items". Each item is
an image.
Example GET:
http://localhost/api/network/securitygroups
"""
security_groups = api.network.security_group_list(request)
return {'items': [sg.to_dict() for sg in security_groups]}

View File

@ -0,0 +1,34 @@
# Copyright 2015, Hewlett-Packard Development Company, L.P.
#
# 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 openstack_dashboard.api.rest import network
from openstack_dashboard.test.api_tests import rest_test_utils
from openstack_dashboard.test import helpers as test
class RestNetworkApiSecurityGroupTests(test.RestAPITestCase):
@mock.patch.object(network.api, 'network')
def test_security_group_detailed(self, client):
request = rest_test_utils.construct_request()
client.security_group_list.return_value = [
mock.Mock(**{'to_dict.return_value': {'name': 'default'}}),
]
response = network.SecurityGroups().get(request)
self.assertStatusCode(response, 200)
self.assertEqual(response.content,
'{"items": [{"name": "default"}]}')
client.security_group_list.assert_called_once_with(request)

View File

@ -20,6 +20,7 @@ import collections
import copy
from functools import wraps # noqa
import os
import testtools
from ceilometerclient.v2 import client as ceilometer_client
from cinderclient import client as cinder_client
@ -424,6 +425,25 @@ class APITestCase(TestCase):
return self.saharaclient
class RestAPITestCase(testtools.TestCase):
"""Testing APIs.
For use with tests which deal with the underlying clients rather than
stubbing out the openstack_dashboard.api.* methods.
"""
def assertStatusCode(self, response, expected_code):
"""Validates an expected status code.
Matches camel case of other assert functions
"""
if response.status_code == expected_code:
return
self.fail('status code %r != %r: %s' % (response.status_code,
expected_code,
response.content))
@unittest.skipUnless(os.environ.get('WITH_SELENIUM', False),
"The WITH_SELENIUM env variable is not set.")
class SeleniumTestCase(horizon_helpers.SeleniumTestCase):