Add load balancer flavor support
Change-Id: If698df8e5cea1b527477b9f546afd52bd37d8989 Depends-On: https://review.openstack.org/634532
This commit is contained in:
parent
7943510362
commit
38e835ceea
@ -46,7 +46,7 @@ msgpack-python==0.4.0
|
|||||||
munch==2.1.0
|
munch==2.1.0
|
||||||
netaddr==0.7.18
|
netaddr==0.7.18
|
||||||
netifaces==0.10.4
|
netifaces==0.10.4
|
||||||
openstacksdk==0.11.2
|
openstacksdk==0.24.0
|
||||||
os-client-config==1.28.0
|
os-client-config==1.28.0
|
||||||
os-service-types==1.2.0
|
os-service-types==1.2.0
|
||||||
osc-lib==1.8.0
|
osc-lib==1.8.0
|
||||||
|
@ -126,14 +126,27 @@ def poll_loadbalancer_status(request, loadbalancer_id, callback,
|
|||||||
def create_loadbalancer(request):
|
def create_loadbalancer(request):
|
||||||
data = request.DATA
|
data = request.DATA
|
||||||
|
|
||||||
|
flavor_id = data['loadbalancer'].get('flavor_id')
|
||||||
|
|
||||||
conn = _get_sdk_connection(request)
|
conn = _get_sdk_connection(request)
|
||||||
|
if flavor_id:
|
||||||
loadbalancer = conn.load_balancer.create_load_balancer(
|
loadbalancer = conn.load_balancer.create_load_balancer(
|
||||||
project_id=request.user.project_id,
|
project_id=request.user.project_id,
|
||||||
vip_subnet_id=data['loadbalancer']['vip_subnet_id'],
|
vip_subnet_id=data['loadbalancer']['vip_subnet_id'],
|
||||||
name=data['loadbalancer'].get('name'),
|
name=data['loadbalancer'].get('name'),
|
||||||
description=data['loadbalancer'].get('description'),
|
description=data['loadbalancer'].get('description'),
|
||||||
vip_address=data['loadbalancer'].get('vip_address'),
|
vip_address=data['loadbalancer'].get('vip_address'),
|
||||||
admin_state_up=data['loadbalancer'].get('admin_state_up')
|
admin_state_up=data['loadbalancer'].get('admin_state_up'),
|
||||||
|
flavor_id=flavor_id
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
loadbalancer = conn.load_balancer.create_load_balancer(
|
||||||
|
project_id=request.user.project_id,
|
||||||
|
vip_subnet_id=data['loadbalancer']['vip_subnet_id'],
|
||||||
|
name=data['loadbalancer'].get('name'),
|
||||||
|
description=data['loadbalancer'].get('description'),
|
||||||
|
vip_address=data['loadbalancer'].get('vip_address'),
|
||||||
|
admin_state_up=data['loadbalancer'].get('admin_state_up'),
|
||||||
)
|
)
|
||||||
|
|
||||||
if data.get('listener'):
|
if data.get('listener'):
|
||||||
@ -284,6 +297,39 @@ def create_health_monitor(request, **kwargs):
|
|||||||
return _get_sdk_object_dict(health_mon)
|
return _get_sdk_object_dict(health_mon)
|
||||||
|
|
||||||
|
|
||||||
|
def create_flavor(request, **kwargs):
|
||||||
|
"""Create a new flavor.
|
||||||
|
|
||||||
|
"""
|
||||||
|
data = request.DATA
|
||||||
|
|
||||||
|
conn = _get_sdk_connection(request)
|
||||||
|
flavor = conn.load_balancer.create_flavor(
|
||||||
|
name=data['flavor']['name'],
|
||||||
|
flavor_profile_id=data['flavor']['flavor_profile_id'],
|
||||||
|
description=data['flavor'].get('description'),
|
||||||
|
enabled=data['flavor'].get('enabled'),
|
||||||
|
)
|
||||||
|
|
||||||
|
return _get_sdk_object_dict(flavor)
|
||||||
|
|
||||||
|
|
||||||
|
def create_flavor_profile(request, **kwargs):
|
||||||
|
"""Create a new flavor profile.
|
||||||
|
|
||||||
|
"""
|
||||||
|
data = request.DATA
|
||||||
|
|
||||||
|
conn = _get_sdk_connection(request)
|
||||||
|
flavor_profile = conn.load_balancer.create_flavor(
|
||||||
|
name=data['flavor_profile']['name'],
|
||||||
|
provider_name=data['flavor_profile']['provider_name'],
|
||||||
|
flavor_data=data['flavor_profile']['flavor_data'],
|
||||||
|
)
|
||||||
|
|
||||||
|
return _get_sdk_object_dict(flavor_profile)
|
||||||
|
|
||||||
|
|
||||||
def add_member(request, **kwargs):
|
def add_member(request, **kwargs):
|
||||||
"""Add a member to a pool.
|
"""Add a member to a pool.
|
||||||
|
|
||||||
@ -534,6 +580,42 @@ def update_monitor(request, **kwargs):
|
|||||||
return _get_sdk_object_dict(healthmonitor)
|
return _get_sdk_object_dict(healthmonitor)
|
||||||
|
|
||||||
|
|
||||||
|
def update_flavor(request, **kwargs):
|
||||||
|
"""Update a flavor.
|
||||||
|
|
||||||
|
"""
|
||||||
|
data = request.DATA
|
||||||
|
flavor_id = data['flavor']['id']
|
||||||
|
|
||||||
|
conn = _get_sdk_connection(request)
|
||||||
|
flavor = conn.load_balancer.update_flavor(
|
||||||
|
flavor_id,
|
||||||
|
name=data['flavor'].get('name'),
|
||||||
|
description=data['flavor'].get('description'),
|
||||||
|
enabled=data['flavor'].get('enabled'),
|
||||||
|
)
|
||||||
|
|
||||||
|
return _get_sdk_object_dict(flavor)
|
||||||
|
|
||||||
|
|
||||||
|
def update_flavor_profile(request, **kwargs):
|
||||||
|
"""Update a flavor profile.
|
||||||
|
|
||||||
|
"""
|
||||||
|
data = request.DATA
|
||||||
|
flavor_profile_id = data['flavor_profile']['id']
|
||||||
|
|
||||||
|
conn = _get_sdk_connection(request)
|
||||||
|
flavor_profile = conn.load_balancer.update_flavor_profile(
|
||||||
|
flavor_profile_id,
|
||||||
|
name=data['flavor_profile'].get('name'),
|
||||||
|
provider_name=data['flavor_profile'].get('provider_name'),
|
||||||
|
flavor_data=data['flavor_profile'].get('flavor_data'),
|
||||||
|
)
|
||||||
|
|
||||||
|
return _get_sdk_object_dict(flavor_profile)
|
||||||
|
|
||||||
|
|
||||||
def update_member_list(request, **kwargs):
|
def update_member_list(request, **kwargs):
|
||||||
"""Update the list of members by adding or removing the necessary members.
|
"""Update the list of members by adding or removing the necessary members.
|
||||||
|
|
||||||
@ -1183,3 +1265,134 @@ class HealthMonitor(generic.View):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
update_monitor(request)
|
update_monitor(request)
|
||||||
|
|
||||||
|
|
||||||
|
@urls.register
|
||||||
|
class Flavors(generic.View):
|
||||||
|
"""API for load balancer flavors.
|
||||||
|
|
||||||
|
"""
|
||||||
|
url_regex = r'lbaas/flavors/$'
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def get(self, request):
|
||||||
|
"""List of flavors for the current project.
|
||||||
|
|
||||||
|
The listing result is an object with property "items".
|
||||||
|
"""
|
||||||
|
conn = _get_sdk_connection(request)
|
||||||
|
flavor_list = _sdk_object_to_list(
|
||||||
|
conn.load_balancer.flavors()
|
||||||
|
)
|
||||||
|
|
||||||
|
return {'items': flavor_list}
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def post(self, request):
|
||||||
|
"""Create a new flavor.
|
||||||
|
|
||||||
|
"""
|
||||||
|
kwargs = {
|
||||||
|
'flavor': request.DATA.get('flavor')
|
||||||
|
}
|
||||||
|
return create_flavor(request, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@urls.register
|
||||||
|
class Flavor(generic.View):
|
||||||
|
"""API for retrieving a single flavor.
|
||||||
|
|
||||||
|
"""
|
||||||
|
url_regex = r'lbaas/flavors/(?P<flavor_id>[^/]+)/$'
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def get(self, request, flavor_id):
|
||||||
|
"""Get a specific flavor.
|
||||||
|
|
||||||
|
"""
|
||||||
|
conn = _get_sdk_connection(request)
|
||||||
|
flavor = conn.load_balancer.find_flavor(flavor_id)
|
||||||
|
return _get_sdk_object_dict(flavor)
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def delete(self, request, flavor_id):
|
||||||
|
"""Delete a specific flavor.
|
||||||
|
|
||||||
|
http://localhost/api/lbaas/flavors/3971d368-ca9b-4770-929a-3adca5bf89eb
|
||||||
|
"""
|
||||||
|
conn = _get_sdk_connection(request)
|
||||||
|
conn.load_balancer.delete_flavor(flavor_id,
|
||||||
|
ignore_missing=True)
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def put(self, request, flavor_id):
|
||||||
|
"""Edit a flavor.
|
||||||
|
|
||||||
|
"""
|
||||||
|
update_flavor(request)
|
||||||
|
|
||||||
|
|
||||||
|
@urls.register
|
||||||
|
class FlavorProfiles(generic.View):
|
||||||
|
"""API for load balancer flavor profiles.
|
||||||
|
|
||||||
|
"""
|
||||||
|
url_regex = r'lbaas/flavorprofiles/$'
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def get(self, request):
|
||||||
|
"""List of flavor profiles for the current project.
|
||||||
|
|
||||||
|
The listing result is an object with property "items".
|
||||||
|
"""
|
||||||
|
conn = _get_sdk_connection(request)
|
||||||
|
flavor_profile_list = _sdk_object_to_list(
|
||||||
|
conn.load_balancer.flavor_profiles()
|
||||||
|
)
|
||||||
|
|
||||||
|
return {'items': flavor_profile_list}
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def post(self, request):
|
||||||
|
"""Create a new flavor_profile.
|
||||||
|
|
||||||
|
"""
|
||||||
|
kwargs = {
|
||||||
|
'flavor_profile': request.DATA.get('flavor_profile')
|
||||||
|
}
|
||||||
|
return create_flavor_profile(request, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@urls.register
|
||||||
|
class FlavorProfile(generic.View):
|
||||||
|
"""API for retrieving a single flavor profile.
|
||||||
|
|
||||||
|
"""
|
||||||
|
url_regex = r'lbaas/flavorprofiles/(?P<flavor_profile_id>[^/]+)/$'
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def get(self, request, flavor_profile_id):
|
||||||
|
"""Get a specific flavor profile.
|
||||||
|
|
||||||
|
"""
|
||||||
|
conn = _get_sdk_connection(request)
|
||||||
|
flavor_profile = conn.load_balancer.find_flavor_profile(
|
||||||
|
flavor_profile_id)
|
||||||
|
return _get_sdk_object_dict(flavor_profile)
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def delete(self, request, flavor_profile_id):
|
||||||
|
"""Delete a specific flavor profile.
|
||||||
|
|
||||||
|
http://localhost/api/lbaas/flavorprofiles/e8150eab-aefa-42cc-867e-3fb336da52bd
|
||||||
|
"""
|
||||||
|
conn = _get_sdk_connection(request)
|
||||||
|
conn.load_balancer.delete_flavor_profile(flavor_profile_id,
|
||||||
|
ignore_missing=True)
|
||||||
|
|
||||||
|
@rest_utils.ajax()
|
||||||
|
def put(self, request, flavor_profile_id):
|
||||||
|
"""Edit a flavor profile.
|
||||||
|
|
||||||
|
"""
|
||||||
|
update_flavor_profile(request)
|
||||||
|
@ -70,7 +70,17 @@
|
|||||||
deleteHealthMonitor: deleteHealthMonitor,
|
deleteHealthMonitor: deleteHealthMonitor,
|
||||||
createHealthMonitor: createHealthMonitor,
|
createHealthMonitor: createHealthMonitor,
|
||||||
editHealthMonitor: editHealthMonitor,
|
editHealthMonitor: editHealthMonitor,
|
||||||
updateMemberList: updateMemberList
|
updateMemberList: updateMemberList,
|
||||||
|
getFlavors: getFlavors,
|
||||||
|
getFlavor: getFlavor,
|
||||||
|
deleteFlavor: deleteFlavor,
|
||||||
|
createFlavor: createFlavor,
|
||||||
|
editFlavor: editFlavor,
|
||||||
|
getFlavorProfiles: getFlavorProfiles,
|
||||||
|
getFlavorProfile: getFlavorProfile,
|
||||||
|
deleteFlavorProfile: deleteFlavorProfile,
|
||||||
|
createFlavorProfile: createFlavorProfile,
|
||||||
|
editFlavorProfile: editFlavorProfile
|
||||||
};
|
};
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
@ -721,5 +731,169 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flavors
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.app.core.openstack-service-api.lbaasv2.getFlavor
|
||||||
|
* @description
|
||||||
|
* Get a single load balancer flavor by ID.
|
||||||
|
* @param {string} flavorId
|
||||||
|
* Specifies the id of the flavor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.app.core.openstack-service-api.lbaasv2.getFlavors
|
||||||
|
* @description
|
||||||
|
* Get the list of flavors.
|
||||||
|
*
|
||||||
|
* The listing result is an object with property "items". Each item is
|
||||||
|
* a flavor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getFlavors() {
|
||||||
|
var params = {params: {}};
|
||||||
|
return apiService.get('/api/lbaas/flavors/', params)
|
||||||
|
.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to retrieve flavors.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlavor(flavorId) {
|
||||||
|
return apiService.get('/api/lbaas/flavors/' + flavorId + '/')
|
||||||
|
.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to retrieve flavor.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.app.core.openstack-service-api.lbaasv2.editFlavor
|
||||||
|
* @description
|
||||||
|
* Edit a flavor
|
||||||
|
* @param {string} id
|
||||||
|
* Specifies the id of the flavor to update.
|
||||||
|
* @param {object} spec
|
||||||
|
* Specifies the data used to update the flavor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function editFlavor(id, spec) {
|
||||||
|
return apiService.put('/api/lbaas/flavors/' + id + '/', spec)
|
||||||
|
.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to update flavor.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.app.core.openstack-service-api.lbaasv2.deleteFlavor
|
||||||
|
* @description
|
||||||
|
* Delete a single flavor by ID
|
||||||
|
* @param {string} id
|
||||||
|
* Specifies the id of the flavor to delete.
|
||||||
|
* @param {boolean} quiet
|
||||||
|
*/
|
||||||
|
|
||||||
|
function deleteFlavor(id, quiet) {
|
||||||
|
var promise = apiService.delete('/api/lbaas/flavors/' + id + '/');
|
||||||
|
return quiet ? promise : promise.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to delete flavor.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.app.core.openstack-service-api.lbaasv2.createFlavor
|
||||||
|
* @description
|
||||||
|
* Create a new flavor
|
||||||
|
* @param {object} spec
|
||||||
|
* Specifies the data used to create the new flavor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function createFlavor(spec) {
|
||||||
|
return apiService.post('/api/lbaas/flavors/', spec)
|
||||||
|
.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to create flavor.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flavor Profiles
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.app.core.openstack-service-api.lbaasv2.getFlavorProfile
|
||||||
|
* @description
|
||||||
|
* Get a single load balancer flavor profile by ID.
|
||||||
|
* @param {string} flavorProfileId
|
||||||
|
* Specifies the id of the flavor profile.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.app.core.openstack-service-api.lbaasv2.getFlavorProfiles
|
||||||
|
* @description
|
||||||
|
* Get the list of flavor profiles.
|
||||||
|
*
|
||||||
|
* The listing result is an object with property "items". Each item is
|
||||||
|
* a flavor profile.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getFlavorProfiles() {
|
||||||
|
var params = {params: {}};
|
||||||
|
return apiService.get('/api/lbaas/flavorprofiles/', params)
|
||||||
|
.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to retrieve flavor profiles.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFlavorProfile(flavorProfileId) {
|
||||||
|
return apiService.get('/api/lbaas/flavorprofiles/' + flavorProfileId + '/')
|
||||||
|
.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to retrieve flavor profile.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.app.core.openstack-service-api.lbaasv2.editFlavorProfile
|
||||||
|
* @description
|
||||||
|
* Edit a flavor Profile
|
||||||
|
* @param {string} id
|
||||||
|
* Specifies the id of the flavor profile to update.
|
||||||
|
* @param {object} spec
|
||||||
|
* Specifies the data used to update the flavor profile.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function editFlavorProfile(id, spec) {
|
||||||
|
return apiService.put('/api/lbaas/flavorprofiles/' + id + '/', spec)
|
||||||
|
.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to update flavor profile.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.app.core.openstack-service-api.lbaasv2.deleteFlavorProfile
|
||||||
|
* @description
|
||||||
|
* Delete a single flavor profile by ID
|
||||||
|
* @param {string} id
|
||||||
|
* Specifies the id of the flavor profile to delete.
|
||||||
|
* @param {boolean} quiet
|
||||||
|
*/
|
||||||
|
|
||||||
|
function deleteFlavorProfile(id, quiet) {
|
||||||
|
var promise = apiService.delete('/api/lbaas/flavorprofiles/' + id + '/');
|
||||||
|
return quiet ? promise : promise.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to delete flavor profile.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name horizon.app.core.openstack-service-api.lbaasv2.createFlavorProfile
|
||||||
|
* @description
|
||||||
|
* Create a new flavor profile
|
||||||
|
* @param {object} spec
|
||||||
|
* Specifies the data used to create the new flavor profile.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function createFlavorProfile(spec) {
|
||||||
|
return apiService.post('/api/lbaas/flavorprofiles/', spec)
|
||||||
|
.error(function () {
|
||||||
|
toastService.add('error', gettext('Unable to create flavor profile.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
|
@ -269,6 +269,66 @@
|
|||||||
error: 'Unable to delete health monitor.',
|
error: 'Unable to delete health monitor.',
|
||||||
testInput: [ '1234' ]
|
testInput: [ '1234' ]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
func: 'getFlavors',
|
||||||
|
method: 'get',
|
||||||
|
path: '/api/lbaas/flavors/',
|
||||||
|
error: 'Unable to retrieve flavors.',
|
||||||
|
testInput: [],
|
||||||
|
data: { params: {} }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
func: 'getFlavor',
|
||||||
|
method: 'get',
|
||||||
|
path: '/api/lbaas/flavors/1234/',
|
||||||
|
error: 'Unable to retrieve flavor.',
|
||||||
|
testInput: [ '1234' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
func: 'editFlavor',
|
||||||
|
method: 'put',
|
||||||
|
path: '/api/lbaas/flavors/1234/',
|
||||||
|
error: 'Unable to update flavor.',
|
||||||
|
data: { name: 'flavor-1' },
|
||||||
|
testInput: [ '1234', { name: 'flavor-1' } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
func: 'deleteFlavor',
|
||||||
|
method: 'delete',
|
||||||
|
path: '/api/lbaas/flavors/1234/',
|
||||||
|
error: 'Unable to delete flavor.',
|
||||||
|
testInput: [ '1234' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
func: 'getFlavorProfiles',
|
||||||
|
method: 'get',
|
||||||
|
path: '/api/lbaas/flavorprofiles/',
|
||||||
|
error: 'Unable to retrieve flavor profiles.',
|
||||||
|
testInput: [],
|
||||||
|
data: { params: {} }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
func: 'getFlavorProfile',
|
||||||
|
method: 'get',
|
||||||
|
path: '/api/lbaas/flavorprofiles/1234/',
|
||||||
|
error: 'Unable to retrieve flavor profile.',
|
||||||
|
testInput: [ '1234' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
func: 'editFlavorProfile',
|
||||||
|
method: 'put',
|
||||||
|
path: '/api/lbaas/flavorprofiles/1234/',
|
||||||
|
error: 'Unable to update flavor profile.',
|
||||||
|
data: { name: 'flavorprofile-1' },
|
||||||
|
testInput: [ '1234', { name: 'flavorprofile-1' } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
func: 'deleteFlavorProfile',
|
||||||
|
method: 'delete',
|
||||||
|
path: '/api/lbaas/flavorprofiles/1234/',
|
||||||
|
error: 'Unable to delete flavor profile.',
|
||||||
|
testInput: [ '1234' ]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
func: 'createLoadBalancer',
|
func: 'createLoadBalancer',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
@ -364,6 +424,22 @@
|
|||||||
data: { name: 'healthmonitor-1' },
|
data: { name: 'healthmonitor-1' },
|
||||||
testInput: [ { name: 'healthmonitor-1' } ]
|
testInput: [ { name: 'healthmonitor-1' } ]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
func: 'createFlavor',
|
||||||
|
method: 'post',
|
||||||
|
path: '/api/lbaas/flavors/',
|
||||||
|
error: 'Unable to create flavor.',
|
||||||
|
data: { name: 'flavor-1' },
|
||||||
|
testInput: [ { name: 'flavor-1' } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
func: 'createFlavorProfile',
|
||||||
|
method: 'post',
|
||||||
|
path: '/api/lbaas/flavorprofiles/',
|
||||||
|
error: 'Unable to create flavor profile.',
|
||||||
|
data: { name: 'flavorprofile-1' },
|
||||||
|
testInput: [ { name: 'flavorprofile-1' } ]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
func: 'updateMemberList',
|
func: 'updateMemberList',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -412,6 +488,16 @@
|
|||||||
expect(service.deleteHealthMonitor("whatever", true)).toBe("promise");
|
expect(service.deleteHealthMonitor("whatever", true)).toBe("promise");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('supresses the error if instructed for deleteFlavor', function() {
|
||||||
|
spyOn(apiService, 'delete').and.returnValue("promise");
|
||||||
|
expect(service.deleteFlavor("whatever", true)).toBe("promise");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('supresses the error if instructed for deleteFlavorProfile', function() {
|
||||||
|
spyOn(apiService, 'delete').and.returnValue("promise");
|
||||||
|
expect(service.deleteFlavorProfile("whatever", true)).toBe("promise");
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
item="ctrl.loadbalancer"
|
item="ctrl.loadbalancer"
|
||||||
property-groups="[[
|
property-groups="[[
|
||||||
'id', 'name', 'description', 'project_id', 'created_at', 'updated_at',
|
'id', 'name', 'description', 'project_id', 'created_at', 'updated_at',
|
||||||
'vip_port_id', 'vip_subnet_id', 'vip_network_id', 'provider', 'flavor',
|
'vip_port_id', 'vip_subnet_id', 'vip_network_id', 'provider', 'flavor_id',
|
||||||
'floating_ip_address']]">
|
'floating_ip_address']]">
|
||||||
</hz-resource-property-list>
|
</hz-resource-property-list>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,5 +5,5 @@
|
|||||||
['name', 'id', 'project_id'],
|
['name', 'id', 'project_id'],
|
||||||
['created_at', 'updated_at', 'description'],
|
['created_at', 'updated_at', 'description'],
|
||||||
['vip_network_id', 'vip_subnet_id', 'vip_port_id'],
|
['vip_network_id', 'vip_subnet_id', 'vip_port_id'],
|
||||||
['provider', 'floating_ip_address']]">
|
['flavor_id', 'provider', 'floating_ip_address']]">
|
||||||
</hz-resource-property-list>
|
</hz-resource-property-list>
|
||||||
|
@ -178,8 +178,8 @@
|
|||||||
listeners: gettext('Listeners'),
|
listeners: gettext('Listeners'),
|
||||||
pools: gettext('Pools'),
|
pools: gettext('Pools'),
|
||||||
provider: gettext('Provider'),
|
provider: gettext('Provider'),
|
||||||
flavor: {
|
flavor_id: {
|
||||||
label: gettext('Flavor'),
|
label: gettext('Flavor ID'),
|
||||||
filters: ['noValue']
|
filters: ['noValue']
|
||||||
},
|
},
|
||||||
floating_ip_address: {
|
floating_ip_address: {
|
||||||
|
@ -87,10 +87,52 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Defines columns for the flavor selection filtered pop-up
|
||||||
|
ctrl.flavorColumns = [{
|
||||||
|
label: gettext('Flavor'),
|
||||||
|
value: 'name'
|
||||||
|
}, {
|
||||||
|
label: gettext('Flavor ID'),
|
||||||
|
value: 'id'
|
||||||
|
}, {
|
||||||
|
label: gettext('Flavor Description'),
|
||||||
|
value: 'description'
|
||||||
|
}, {
|
||||||
|
label: gettext('Provider'),
|
||||||
|
value: function(flavor) {
|
||||||
|
var flavorProfile = $scope.model.flavorProfiles[flavor.flavor_profile_id];
|
||||||
|
return flavorProfile ? flavorProfile.provider_name : '';
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
ctrl.flavorOptions = [];
|
||||||
|
|
||||||
|
ctrl.flavorShorthand = function(flavor) {
|
||||||
|
var flavorProfile = $scope.model.flavorProfiles[flavor.flavor_profile_id];
|
||||||
|
|
||||||
|
var providerText =
|
||||||
|
flavorProfile
|
||||||
|
? flavorProfile.provider_name
|
||||||
|
: '';
|
||||||
|
var flavorText = flavor.name || flavor.id.substring(0, 10) + '...';
|
||||||
|
var flavorDescription = flavor.description || '';
|
||||||
|
|
||||||
|
return flavorText + ' (' + providerText + '): ' + flavorDescription;
|
||||||
|
};
|
||||||
|
|
||||||
|
ctrl.setFlavor = function(option) {
|
||||||
|
if (option) {
|
||||||
|
$scope.model.spec.loadbalancer.flavor_id = option;
|
||||||
|
} else {
|
||||||
|
$scope.model.spec.loadbalancer.flavor_id = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ctrl.dataLoaded = false;
|
ctrl.dataLoaded = false;
|
||||||
ctrl._checkLoaded = function() {
|
ctrl._checkLoaded = function() {
|
||||||
if ($scope.model.initialized) {
|
if ($scope.model.initialized) {
|
||||||
ctrl.buildSubnetOptions();
|
ctrl.buildSubnetOptions();
|
||||||
|
ctrl.buildFlavorOptions();
|
||||||
ctrl.dataLoaded = true;
|
ctrl.dataLoaded = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -112,6 +154,12 @@
|
|||||||
$scope.$watchCollection('model.networks', function() {
|
$scope.$watchCollection('model.networks', function() {
|
||||||
ctrl._checkLoaded();
|
ctrl._checkLoaded();
|
||||||
});
|
});
|
||||||
|
$scope.$watchCollection('model.flavors', function() {
|
||||||
|
ctrl._checkLoaded();
|
||||||
|
});
|
||||||
|
$scope.$watchCollection('model.flavorProfiles', function() {
|
||||||
|
ctrl._checkLoaded();
|
||||||
|
});
|
||||||
$scope.$watch('model.initialized', function() {
|
$scope.$watch('model.initialized', function() {
|
||||||
ctrl._checkLoaded();
|
ctrl._checkLoaded();
|
||||||
});
|
});
|
||||||
@ -121,5 +169,13 @@
|
|||||||
// Subnets are sliced to maintain data immutability
|
// Subnets are sliced to maintain data immutability
|
||||||
ctrl.subnetOptions = $scope.model.subnets.slice(0);
|
ctrl.subnetOptions = $scope.model.subnets.slice(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ctrl.buildFlavorOptions = function() {
|
||||||
|
ctrl.flavorOptions = Object.keys($scope.model.flavors).filter(function(key) {
|
||||||
|
return $scope.model.flavors[key].is_enabled;
|
||||||
|
}).map(function(key) {
|
||||||
|
return $scope.model.flavors[key];
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||||
|
|
||||||
describe('LoadBalancerDetailsController', function() {
|
describe('LoadBalancerDetailsController', function() {
|
||||||
var ctrl, scope, mockSubnets;
|
var ctrl, scope, mockSubnets, mockFlavors;
|
||||||
beforeEach(inject(function($controller, $rootScope) {
|
beforeEach(inject(function($controller, $rootScope) {
|
||||||
mockSubnets = [{
|
mockSubnets = [{
|
||||||
id: '7262744a-e1e4-40d7-8833-18193e8de191',
|
id: '7262744a-e1e4-40d7-8833-18193e8de191',
|
||||||
@ -41,6 +41,24 @@
|
|||||||
cidr: '2.2.2.2/16'
|
cidr: '2.2.2.2/16'
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
mockFlavors = [{
|
||||||
|
id: '15d990e1-3438-4073-89b8-6e4706f0b176',
|
||||||
|
flavor_profile_id: '79e16118-daba-4255-9d1d-9cc7812e18a1',
|
||||||
|
name: 'flavor_1',
|
||||||
|
description: 'Flavor 1 description',
|
||||||
|
is_enabled: true
|
||||||
|
}, {
|
||||||
|
id: 'b0703ed4-dd30-4dbe-92bb-dccc945365e9',
|
||||||
|
flavor_profile_id: 'ace487e6-9946-4bdc-882e-c889af43fc3b',
|
||||||
|
name: 'flavor_2',
|
||||||
|
is_enabled: true
|
||||||
|
}, {
|
||||||
|
id: '94306089-567a-44ed-ab16-87653adbece3',
|
||||||
|
flavor_profile_id: 'b272d5fb-0021-4002-beb5-db758e59a763',
|
||||||
|
name: '',
|
||||||
|
is_enabled: true
|
||||||
|
}];
|
||||||
|
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
scope.model = {
|
scope.model = {
|
||||||
networks: {
|
networks: {
|
||||||
@ -49,6 +67,21 @@
|
|||||||
name: 'network_1'
|
name: 'network_1'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
flavors: {
|
||||||
|
'15d990e1-3438-4073-89b8-6e4706f0b176': {
|
||||||
|
id: '15d990e1-3438-4073-89b8-6e4706f0b176',
|
||||||
|
name: 'flavor_1',
|
||||||
|
flavor_profile_id: '79e16118-daba-4255-9d1d-9cc7812e18a1',
|
||||||
|
is_enabled: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
flavorProfiles: {
|
||||||
|
'79e16118-daba-4255-9d1d-9cc7812e18a1': {
|
||||||
|
id: '79e16118-daba-4255-9d1d-9cc7812e18a1',
|
||||||
|
name: 'flavor_profile_1',
|
||||||
|
provider_name: 'amphora'
|
||||||
|
}
|
||||||
|
},
|
||||||
subnets: [{}, {}],
|
subnets: [{}, {}],
|
||||||
spec: {
|
spec: {
|
||||||
loadbalancer: {
|
loadbalancer: {
|
||||||
@ -61,6 +94,7 @@
|
|||||||
ctrl = $controller('LoadBalancerDetailsController', {$scope: scope});
|
ctrl = $controller('LoadBalancerDetailsController', {$scope: scope});
|
||||||
|
|
||||||
spyOn(ctrl, 'buildSubnetOptions').and.callThrough();
|
spyOn(ctrl, 'buildSubnetOptions').and.callThrough();
|
||||||
|
spyOn(ctrl, 'buildFlavorOptions').and.callThrough();
|
||||||
spyOn(ctrl, '_checkLoaded').and.callThrough();
|
spyOn(ctrl, '_checkLoaded').and.callThrough();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -87,6 +121,18 @@
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should create flavor shorthand text', function() {
|
||||||
|
expect(ctrl.flavorShorthand(mockFlavors[0])).toBe(
|
||||||
|
'flavor_1 (amphora): Flavor 1 description'
|
||||||
|
);
|
||||||
|
expect(ctrl.flavorShorthand(mockFlavors[1])).toBe(
|
||||||
|
'flavor_2 (): '
|
||||||
|
);
|
||||||
|
expect(ctrl.flavorShorthand(mockFlavors[2])).toBe(
|
||||||
|
'94306089-5... (): '
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should set subnet', function() {
|
it('should set subnet', function() {
|
||||||
ctrl.setSubnet(mockSubnets[0]);
|
ctrl.setSubnet(mockSubnets[0]);
|
||||||
expect(scope.model.spec.loadbalancer.vip_subnet_id).toBe(mockSubnets[0]);
|
expect(scope.model.spec.loadbalancer.vip_subnet_id).toBe(mockSubnets[0]);
|
||||||
@ -94,6 +140,13 @@
|
|||||||
expect(scope.model.spec.loadbalancer.vip_subnet_id).toBe(null);
|
expect(scope.model.spec.loadbalancer.vip_subnet_id).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should set flavor', function() {
|
||||||
|
ctrl.setFlavor(mockFlavors[0]);
|
||||||
|
expect(scope.model.spec.loadbalancer.flavor_id).toBe(mockFlavors[0]);
|
||||||
|
ctrl.setFlavor(null);
|
||||||
|
expect(scope.model.spec.loadbalancer.flavor_id).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
it('should initialize watchers', function() {
|
it('should initialize watchers', function() {
|
||||||
ctrl.$onInit();
|
ctrl.$onInit();
|
||||||
|
|
||||||
@ -105,6 +158,14 @@
|
|||||||
scope.$apply();
|
scope.$apply();
|
||||||
expect(ctrl._checkLoaded).toHaveBeenCalled();
|
expect(ctrl._checkLoaded).toHaveBeenCalled();
|
||||||
|
|
||||||
|
scope.model.flavors = {};
|
||||||
|
scope.$apply();
|
||||||
|
expect(ctrl._checkLoaded).toHaveBeenCalled();
|
||||||
|
|
||||||
|
scope.model.flavorProfiles = {};
|
||||||
|
scope.$apply();
|
||||||
|
expect(ctrl._checkLoaded).toHaveBeenCalled();
|
||||||
|
|
||||||
scope.model.initialized = true;
|
scope.model.initialized = true;
|
||||||
|
|
||||||
scope.$apply();
|
scope.$apply();
|
||||||
@ -158,6 +219,34 @@
|
|||||||
expect(ctrl.buildSubnetOptions).toHaveBeenCalled();
|
expect(ctrl.buildSubnetOptions).toHaveBeenCalled();
|
||||||
expect(ctrl.dataLoaded).toBe(true);
|
expect(ctrl.dataLoaded).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should initialize flavors watcher', function() {
|
||||||
|
ctrl.$onInit();
|
||||||
|
|
||||||
|
scope.model.flavors = {};
|
||||||
|
scope.$apply();
|
||||||
|
//expect(ctrl.buildSubnetOptions).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should produce flavor column data', function() {
|
||||||
|
expect(ctrl.flavorColumns).toBeDefined();
|
||||||
|
|
||||||
|
expect(ctrl.flavorColumns[0].label).toBe('Flavor');
|
||||||
|
expect(ctrl.flavorColumns[0].value).toBe('name');
|
||||||
|
|
||||||
|
expect(ctrl.flavorColumns[1].label).toBe('Flavor ID');
|
||||||
|
expect(ctrl.flavorColumns[1].value).toBe('id');
|
||||||
|
|
||||||
|
expect(ctrl.flavorColumns[2].label).toBe('Flavor Description');
|
||||||
|
expect(ctrl.flavorColumns[2].value).toBe('description');
|
||||||
|
|
||||||
|
expect(ctrl.flavorColumns[3].label).toBe('Provider');
|
||||||
|
var flavorLabel3 = ctrl.flavorColumns[3].value(mockFlavors[0]);
|
||||||
|
expect(flavorLabel3).toBe('amphora');
|
||||||
|
flavorLabel3 = ctrl.flavorColumns[3].value(mockFlavors[1]);
|
||||||
|
expect(flavorLabel3).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
@ -35,6 +35,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label">
|
||||||
|
<translate>Flavor</translate>
|
||||||
|
</label>
|
||||||
|
<!-- value="model.spec.loadbalancer.flavor_id" -->
|
||||||
|
<filter-select
|
||||||
|
shorthand="ctrl.flavorShorthand"
|
||||||
|
|
||||||
|
on-select="ctrl.setFlavor(option)"
|
||||||
|
disabled="model.context.id"
|
||||||
|
columns="ctrl.flavorColumns"
|
||||||
|
options="ctrl.flavorOptions"
|
||||||
|
loaded="ctrl.dataLoaded"
|
||||||
|
|
||||||
|
ng-model="model.spec.loadbalancer.flavor_id"
|
||||||
|
></filter-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 col-sm-12 col-md-12">
|
<div class="col-xs-12 col-sm-12 col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -85,6 +85,8 @@
|
|||||||
subnets: [],
|
subnets: [],
|
||||||
members: [],
|
members: [],
|
||||||
networks: {},
|
networks: {},
|
||||||
|
flavors: {},
|
||||||
|
flavorProfiles: {},
|
||||||
listenerProtocols: ['HTTP', 'TCP', 'TERMINATED_HTTPS', 'HTTPS'],
|
listenerProtocols: ['HTTP', 'TCP', 'TERMINATED_HTTPS', 'HTTPS'],
|
||||||
l7policyActions: ['REJECT', 'REDIRECT_TO_URL', 'REDIRECT_TO_POOL'],
|
l7policyActions: ['REJECT', 'REDIRECT_TO_URL', 'REDIRECT_TO_POOL'],
|
||||||
l7ruleTypes: ['HOST_NAME', 'PATH', 'FILE_TYPE', 'HEADER', 'COOKIE'],
|
l7ruleTypes: ['HOST_NAME', 'PATH', 'FILE_TYPE', 'HEADER', 'COOKIE'],
|
||||||
@ -149,6 +151,7 @@
|
|||||||
description: null,
|
description: null,
|
||||||
vip_address: null,
|
vip_address: null,
|
||||||
vip_subnet_id: null,
|
vip_subnet_id: null,
|
||||||
|
flavor_id: null,
|
||||||
admin_state_up: true
|
admin_state_up: true
|
||||||
},
|
},
|
||||||
listener: {
|
listener: {
|
||||||
@ -263,6 +266,8 @@
|
|||||||
function initCreateLoadBalancer(keymanagerPromise) {
|
function initCreateLoadBalancer(keymanagerPromise) {
|
||||||
model.context.submit = createLoadBalancer;
|
model.context.submit = createLoadBalancer;
|
||||||
return $q.all([
|
return $q.all([
|
||||||
|
lbaasv2API.getFlavors().then(onGetFlavors),
|
||||||
|
lbaasv2API.getFlavorProfiles().then(onGetFlavorProfiles),
|
||||||
neutronAPI.getSubnets().then(onGetSubnets),
|
neutronAPI.getSubnets().then(onGetSubnets),
|
||||||
neutronAPI.getPorts().then(onGetPorts),
|
neutronAPI.getPorts().then(onGetPorts),
|
||||||
neutronAPI.getNetworks().then(onGetNetworks),
|
neutronAPI.getNetworks().then(onGetNetworks),
|
||||||
@ -277,6 +282,18 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onGetFlavors(response) {
|
||||||
|
angular.forEach(response.data.items, function(value) {
|
||||||
|
model.flavors[value.id] = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onGetFlavorProfiles(response) {
|
||||||
|
angular.forEach(response.data.items, function(value) {
|
||||||
|
model.flavorProfiles[value.id] = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function initCreateListener(keymanagerPromise) {
|
function initCreateListener(keymanagerPromise) {
|
||||||
model.context.submit = createListener;
|
model.context.submit = createListener;
|
||||||
return $q.all([
|
return $q.all([
|
||||||
@ -337,10 +354,12 @@
|
|||||||
function initEditLoadBalancer() {
|
function initEditLoadBalancer() {
|
||||||
model.context.submit = editLoadBalancer;
|
model.context.submit = editLoadBalancer;
|
||||||
return $q.all([
|
return $q.all([
|
||||||
|
lbaasv2API.getFlavors().then(onGetFlavors),
|
||||||
|
lbaasv2API.getFlavorProfiles().then(onGetFlavorProfiles),
|
||||||
lbaasv2API.getLoadBalancer(model.context.id).then(onGetLoadBalancer),
|
lbaasv2API.getLoadBalancer(model.context.id).then(onGetLoadBalancer),
|
||||||
neutronAPI.getSubnets().then(onGetSubnets),
|
neutronAPI.getSubnets().then(onGetSubnets),
|
||||||
neutronAPI.getNetworks().then(onGetNetworks)
|
neutronAPI.getNetworks().then(onGetNetworks)
|
||||||
]).then(initSubnet);
|
]).then(initSubnet).then(initFlavor);
|
||||||
}
|
}
|
||||||
|
|
||||||
function initEditListener() {
|
function initEditListener() {
|
||||||
@ -457,6 +476,10 @@
|
|||||||
function cleanFinalSpecLoadBalancer(finalSpec) {
|
function cleanFinalSpecLoadBalancer(finalSpec) {
|
||||||
var context = model.context;
|
var context = model.context;
|
||||||
|
|
||||||
|
if (angular.isObject(finalSpec.loadbalancer.flavor_id)) {
|
||||||
|
finalSpec.loadbalancer.flavor_id = finalSpec.loadbalancer.flavor_id.id;
|
||||||
|
}
|
||||||
|
|
||||||
// Load balancer requires vip_subnet_id
|
// Load balancer requires vip_subnet_id
|
||||||
if (!finalSpec.loadbalancer.vip_subnet_id) {
|
if (!finalSpec.loadbalancer.vip_subnet_id) {
|
||||||
delete finalSpec.loadbalancer;
|
delete finalSpec.loadbalancer;
|
||||||
@ -466,6 +489,7 @@
|
|||||||
|
|
||||||
// Cannot edit the IP or subnet
|
// Cannot edit the IP or subnet
|
||||||
if (context.resource === 'loadbalancer' && context.id) {
|
if (context.resource === 'loadbalancer' && context.id) {
|
||||||
|
delete finalSpec.flavor_id;
|
||||||
delete finalSpec.vip_subnet_id;
|
delete finalSpec.vip_subnet_id;
|
||||||
delete finalSpec.vip_address;
|
delete finalSpec.vip_address;
|
||||||
}
|
}
|
||||||
@ -751,6 +775,7 @@
|
|||||||
spec.description = loadbalancer.description;
|
spec.description = loadbalancer.description;
|
||||||
spec.vip_address = loadbalancer.vip_address;
|
spec.vip_address = loadbalancer.vip_address;
|
||||||
spec.vip_subnet_id = loadbalancer.vip_subnet_id;
|
spec.vip_subnet_id = loadbalancer.vip_subnet_id;
|
||||||
|
spec.flavor_id = loadbalancer.flavor_id;
|
||||||
spec.admin_state_up = loadbalancer.admin_state_up;
|
spec.admin_state_up = loadbalancer.admin_state_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,6 +917,10 @@
|
|||||||
model.spec.loadbalancer.vip_subnet_id = subnet;
|
model.spec.loadbalancer.vip_subnet_id = subnet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initFlavor() {
|
||||||
|
model.spec.loadbalancer.flavor_id = model.flavors[model.spec.loadbalancer.flavor_id];
|
||||||
|
}
|
||||||
|
|
||||||
function mapSubnetObj(subnetId) {
|
function mapSubnetObj(subnetId) {
|
||||||
var subnet = model.subnets.filter(function mapSubnet(subnet) {
|
var subnet = model.subnets.filter(function mapSubnet(subnet) {
|
||||||
return subnet.id === subnetId;
|
return subnet.id === subnetId;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
describe('LBaaS v2 Workflow Model Service', function() {
|
describe('LBaaS v2 Workflow Model Service', function() {
|
||||||
var model, $q, scope, listenerResources, barbicanEnabled,
|
var model, $q, scope, listenerResources, barbicanEnabled,
|
||||||
certificatesError, mockNetworks;
|
certificatesError, mockNetworks, mockFlavors, mockFlavorProfiles;
|
||||||
var includeChildResources = true;
|
var includeChildResources = true;
|
||||||
|
|
||||||
beforeEach(module('horizon.framework.util.i18n'));
|
beforeEach(module('horizon.framework.util.i18n'));
|
||||||
@ -95,6 +95,26 @@
|
|||||||
id: 'b2'
|
id: 'b2'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
mockFlavors = {
|
||||||
|
f1: {
|
||||||
|
name: 'flavor_1',
|
||||||
|
id: 'f1'
|
||||||
|
},
|
||||||
|
f2: {
|
||||||
|
name: 'flavor_2',
|
||||||
|
id: 'f2'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mockFlavorProfiles = {
|
||||||
|
p1: {
|
||||||
|
name: 'flavor_profile_1',
|
||||||
|
id: 'p1'
|
||||||
|
},
|
||||||
|
p2: {
|
||||||
|
name: 'flavor_profile_2',
|
||||||
|
id: 'p2'
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(module(function($provide) {
|
beforeEach(module(function($provide) {
|
||||||
@ -118,6 +138,7 @@
|
|||||||
name: 'Load Balancer 1',
|
name: 'Load Balancer 1',
|
||||||
vip_address: '1.2.3.4',
|
vip_address: '1.2.3.4',
|
||||||
vip_subnet_id: 'subnet-1',
|
vip_subnet_id: 'subnet-1',
|
||||||
|
flavor_id: 'flavor-1',
|
||||||
description: ''
|
description: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -242,6 +263,32 @@
|
|||||||
|
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
},
|
},
|
||||||
|
getFlavors: function() {
|
||||||
|
var flavors = [{
|
||||||
|
name: 'flavor_1',
|
||||||
|
id: 'f1'
|
||||||
|
}, {
|
||||||
|
name: 'flavor_2',
|
||||||
|
id: 'f2'
|
||||||
|
}];
|
||||||
|
|
||||||
|
var deferred = $q.defer();
|
||||||
|
deferred.resolve({data: {items: flavors}});
|
||||||
|
return deferred.promise;
|
||||||
|
},
|
||||||
|
getFlavorProfiles: function() {
|
||||||
|
var flavorProfiles = [{
|
||||||
|
name: 'flavor_profile_1',
|
||||||
|
id: 'p1'
|
||||||
|
}, {
|
||||||
|
name: 'flavor_profile_2',
|
||||||
|
id: 'p2'
|
||||||
|
}];
|
||||||
|
|
||||||
|
var deferred = $q.defer();
|
||||||
|
deferred.resolve({data: {items: flavorProfiles}});
|
||||||
|
return deferred.promise;
|
||||||
|
},
|
||||||
createLoadBalancer: function(spec) {
|
createLoadBalancer: function(spec) {
|
||||||
return spec;
|
return spec;
|
||||||
},
|
},
|
||||||
@ -486,6 +533,8 @@
|
|||||||
expect(model.initialized).toBe(true);
|
expect(model.initialized).toBe(true);
|
||||||
expect(model.subnets.length).toBe(2);
|
expect(model.subnets.length).toBe(2);
|
||||||
expect(model.networks).toEqual(mockNetworks);
|
expect(model.networks).toEqual(mockNetworks);
|
||||||
|
expect(model.flavors).toEqual(mockFlavors);
|
||||||
|
expect(model.flavorProfiles).toEqual(mockFlavorProfiles);
|
||||||
expect(model.members.length).toBe(2);
|
expect(model.members.length).toBe(2);
|
||||||
expect(model.certificates.length).toBe(2);
|
expect(model.certificates.length).toBe(2);
|
||||||
expect(model.listenerPorts.length).toBe(0);
|
expect(model.listenerPorts.length).toBe(0);
|
||||||
@ -742,6 +791,8 @@
|
|||||||
expect(model.initialized).toBe(true);
|
expect(model.initialized).toBe(true);
|
||||||
expect(model.subnets.length).toBe(2);
|
expect(model.subnets.length).toBe(2);
|
||||||
expect(model.networks).toEqual(mockNetworks);
|
expect(model.networks).toEqual(mockNetworks);
|
||||||
|
expect(model.flavors).toEqual(mockFlavors);
|
||||||
|
expect(model.flavorProfiles).toEqual(mockFlavorProfiles);
|
||||||
expect(model.members.length).toBe(0);
|
expect(model.members.length).toBe(0);
|
||||||
expect(model.certificates.length).toBe(0);
|
expect(model.certificates.length).toBe(0);
|
||||||
expect(model.listenerPorts.length).toBe(0);
|
expect(model.listenerPorts.length).toBe(0);
|
||||||
@ -1238,7 +1289,7 @@
|
|||||||
// to implement tests for them.
|
// to implement tests for them.
|
||||||
it('has the right number of properties', function() {
|
it('has the right number of properties', function() {
|
||||||
expect(Object.keys(model.spec).length).toBe(11);
|
expect(Object.keys(model.spec).length).toBe(11);
|
||||||
expect(Object.keys(model.spec.loadbalancer).length).toBe(5);
|
expect(Object.keys(model.spec.loadbalancer).length).toBe(6);
|
||||||
expect(Object.keys(model.spec.listener).length).toBe(14);
|
expect(Object.keys(model.spec.listener).length).toBe(14);
|
||||||
expect(Object.keys(model.spec.l7policy).length).toBe(8);
|
expect(Object.keys(model.spec.l7policy).length).toBe(8);
|
||||||
expect(Object.keys(model.spec.l7rule).length).toBe(7);
|
expect(Object.keys(model.spec.l7rule).length).toBe(7);
|
||||||
@ -1486,6 +1537,7 @@
|
|||||||
it('should set final spec properties', function() {
|
it('should set final spec properties', function() {
|
||||||
model.spec.loadbalancer.vip_address = '1.2.3.4';
|
model.spec.loadbalancer.vip_address = '1.2.3.4';
|
||||||
model.spec.loadbalancer.vip_subnet_id = model.subnets[0];
|
model.spec.loadbalancer.vip_subnet_id = model.subnets[0];
|
||||||
|
model.spec.loadbalancer.flavor_id = model.flavors[Object.keys(model.flavors)[0]];
|
||||||
model.spec.listener.protocol = 'TCP';
|
model.spec.listener.protocol = 'TCP';
|
||||||
model.spec.listener.protocol_port = 80;
|
model.spec.listener.protocol_port = 80;
|
||||||
model.spec.listener.connection_limit = 999;
|
model.spec.listener.connection_limit = 999;
|
||||||
@ -1587,6 +1639,7 @@
|
|||||||
it('should set final spec certificates', function() {
|
it('should set final spec certificates', function() {
|
||||||
model.spec.loadbalancer.vip_address = '1.2.3.4';
|
model.spec.loadbalancer.vip_address = '1.2.3.4';
|
||||||
model.spec.loadbalancer.vip_subnet_id = model.subnets[0];
|
model.spec.loadbalancer.vip_subnet_id = model.subnets[0];
|
||||||
|
model.spec.loadbalancer.flavor_id = model.flavors[Object.keys(model.flavors)[0]];
|
||||||
model.spec.listener.protocol = 'TERMINATED_HTTPS';
|
model.spec.listener.protocol = 'TERMINATED_HTTPS';
|
||||||
model.spec.listener.protocol_port = 443;
|
model.spec.listener.protocol_port = 443;
|
||||||
model.spec.listener.connection_limit = 9999;
|
model.spec.listener.connection_limit = 9999;
|
||||||
|
7
releasenotes/notes/flavor-support-0195a486faa16b7f.yaml
Normal file
7
releasenotes/notes/flavor-support-0195a486faa16b7f.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add load balancer flavor support.
|
||||||
|
issues:
|
||||||
|
- |
|
||||||
|
The octavia-dashboard requires openstacksdk > 0.24.0 for flavor support.
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
horizon>=14.0.0.0b3 # Apache-2.0
|
horizon>=14.0.0.0b3 # Apache-2.0
|
||||||
Babel!=2.4.0,>=2.3.4 # BSD
|
Babel!=2.4.0,>=2.3.4 # BSD
|
||||||
openstacksdk>=0.11.2 # Apache-2.0
|
openstacksdk>=0.24.0 # Apache-2.0
|
||||||
oslo.log>=3.36.0 # Apache-2.0
|
oslo.log>=3.36.0 # Apache-2.0
|
||||||
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
||||||
python-barbicanclient>=4.5.2 # Apache-2.0
|
python-barbicanclient>=4.5.2 # Apache-2.0
|
||||||
|
Loading…
Reference in New Issue
Block a user