Merge "Optimise how to retrieve pull-down options"
This commit is contained in:
commit
76ac37b3b0
@ -12,183 +12,268 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
from functools import wraps
|
||||||
|
from multiprocessing import pool
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from openstack_dashboard import api as dashboard_api
|
from openstack_dashboard import api as dashboard_api
|
||||||
from openstack_dashboard.api.neutron import neutronclient
|
|
||||||
|
|
||||||
from heat_dashboard import api
|
from heat_dashboard import api as heat_api
|
||||||
|
|
||||||
|
|
||||||
def get_resources(request):
|
try:
|
||||||
|
API_TIMEOUT = settings.API_TIMEOUT
|
||||||
|
except AttributeError:
|
||||||
|
API_TIMEOUT = 60
|
||||||
|
|
||||||
volumes = [
|
try:
|
||||||
vol.to_dict() for vol in dashboard_api.cinder.volume_list(request)]
|
API_PARALLEL = settings.API_PARALLEL
|
||||||
volume_snapshots = [
|
except AttributeError:
|
||||||
volsnap.to_dict()
|
API_PARALLEL = 2
|
||||||
for volsnap in dashboard_api.cinder.volume_snapshot_list(request)]
|
|
||||||
volume_types = [
|
|
||||||
voltype.to_dict()
|
|
||||||
for voltype in dashboard_api.cinder.volume_type_list(request)]
|
|
||||||
volume_backups = [
|
|
||||||
volbackup.to_dict()
|
|
||||||
for volbackup in dashboard_api.cinder.volume_backup_list(request)]
|
|
||||||
|
|
||||||
images = [
|
|
||||||
img.to_dict()
|
|
||||||
for img in dashboard_api.glance.image_list_detailed(request)[0]]
|
|
||||||
|
|
||||||
neutron_client = neutronclient(request)
|
|
||||||
floatingips = neutron_client.list_floatingips().get('floatingips')
|
|
||||||
networks = neutron_client.list_networks().get('networks')
|
|
||||||
ports = neutron_client.list_ports().get('ports')
|
|
||||||
security_groups = \
|
|
||||||
neutron_client.list_security_groups().get('security_groups')
|
|
||||||
subnets = neutron_client.list_subnets().get('subnets')
|
|
||||||
routers = neutron_client.list_routers().get('routers')
|
|
||||||
# qos_policies = neutron_client.list_security_groups().get('ports')
|
|
||||||
|
|
||||||
availability_zones = \
|
|
||||||
[az.to_dict()
|
|
||||||
for az in dashboard_api.nova.availability_zone_list(request)]
|
|
||||||
flavors = \
|
|
||||||
[flavor.to_dict()
|
|
||||||
for flavor in dashboard_api.nova.flavor_list(request)]
|
|
||||||
instances = \
|
|
||||||
[server.to_dict()
|
|
||||||
for server in dashboard_api.nova.server_list(request)[0]]
|
|
||||||
keypairs = \
|
|
||||||
[keypair.to_dict()
|
|
||||||
for keypair in dashboard_api.nova.keypair_list(request)]
|
|
||||||
|
|
||||||
opts = {
|
|
||||||
'user_roles': request.user.roles,
|
|
||||||
'volumes': volumes,
|
|
||||||
'volume_snapshots': volume_snapshots,
|
|
||||||
'volume_types': volume_types,
|
|
||||||
'volume_backups': volume_backups,
|
|
||||||
'images': images,
|
|
||||||
'floatingips': floatingips,
|
|
||||||
'networks': networks,
|
|
||||||
'ports': ports,
|
|
||||||
'security_groups': security_groups,
|
|
||||||
'subnets': subnets,
|
|
||||||
'routers': routers,
|
|
||||||
# 'qos_policies': qos_policies,
|
|
||||||
'availability_zones': availability_zones,
|
|
||||||
'flavors': flavors,
|
|
||||||
'instances': instances,
|
|
||||||
'keypairs': keypairs,
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.dumps(opts)
|
|
||||||
|
|
||||||
|
|
||||||
def get_resource_options(request):
|
def handle_exception(func):
|
||||||
|
@wraps(func)
|
||||||
|
def wrapped(*args, **kwargs):
|
||||||
|
ret, err = None, None
|
||||||
|
try:
|
||||||
|
ret = func(*args, **kwargs)
|
||||||
|
except Exception as error:
|
||||||
|
err = error.message
|
||||||
|
return ret if ret else [], err
|
||||||
|
return wrapped
|
||||||
|
|
||||||
volumes = [{'id': vol.id,
|
|
||||||
|
@handle_exception
|
||||||
|
def get_networks(request):
|
||||||
|
return dashboard_api.neutron.network_list(request)
|
||||||
|
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def get_subnets(request):
|
||||||
|
return dashboard_api.neutron.subnet_list(request)
|
||||||
|
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def get_volume_ids(request):
|
||||||
|
return [{'id': vol.id,
|
||||||
'name': vol.name if vol.name else '(%s)' % vol.id}
|
'name': vol.name if vol.name else '(%s)' % vol.id}
|
||||||
for vol in dashboard_api.cinder.volume_list(request)]
|
for vol in dashboard_api.cinder.volume_list(request)]
|
||||||
volume_snapshots = [
|
|
||||||
{'id': volsnap.id,
|
|
||||||
|
@handle_exception
|
||||||
|
def get_volume_snapshots(request):
|
||||||
|
return [{'id': volsnap.id,
|
||||||
'name': volsnap.name if volsnap.name else '(%s)' % volsnap.id[:6]}
|
'name': volsnap.name if volsnap.name else '(%s)' % volsnap.id[:6]}
|
||||||
for volsnap in dashboard_api.cinder.volume_snapshot_list(request)]
|
for volsnap in dashboard_api.cinder.volume_snapshot_list(request)]
|
||||||
volume_types = [{
|
|
||||||
'id': voltype.id,
|
|
||||||
|
@handle_exception
|
||||||
|
def get_volume_types(request):
|
||||||
|
return [{'id': voltype.id,
|
||||||
'name': voltype.name if voltype.name else '(%s)' % voltype.id[:6]}
|
'name': voltype.name if voltype.name else '(%s)' % voltype.id[:6]}
|
||||||
for voltype in dashboard_api.cinder.volume_type_list(request)]
|
for voltype in dashboard_api.cinder.volume_type_list(request)]
|
||||||
volume_backups = [
|
|
||||||
{'id': volbackup.id,
|
|
||||||
|
@handle_exception
|
||||||
|
def get_volume_backups(request):
|
||||||
|
return [{'id': volbackup.id,
|
||||||
'name': volbackup.name
|
'name': volbackup.name
|
||||||
if volbackup.name else '(%s)' % volbackup.id[:6]}
|
if volbackup.name else '(%s)' % volbackup.id[:6]}
|
||||||
for volbackup in dashboard_api.cinder.volume_backup_list(request)]
|
for volbackup in dashboard_api.cinder.volume_backup_list(request)]
|
||||||
|
|
||||||
images = [
|
|
||||||
{'id': img.id,
|
|
||||||
'name': img.name if img.name else '(%s)' % img.id[:6]}
|
|
||||||
for img in dashboard_api.glance.image_list_detailed(request)[0]]
|
|
||||||
|
|
||||||
floatingips = [
|
@handle_exception
|
||||||
{'id': fip.id, 'name': fip.floating_ip_address}
|
def get_images(request):
|
||||||
|
images = dashboard_api.glance.image_list_detailed(request)
|
||||||
|
if isinstance(images, tuple):
|
||||||
|
images = images[0]
|
||||||
|
return [{'id': img.id,
|
||||||
|
'name': img.name if img.name else '(%s)' % img.id[:6]}
|
||||||
|
for img in images]
|
||||||
|
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def get_floatingips(request):
|
||||||
|
return [{'id': fip.id, 'name': fip.floating_ip_address}
|
||||||
for fip in dashboard_api.neutron.tenant_floating_ip_list(
|
for fip in dashboard_api.neutron.tenant_floating_ip_list(
|
||||||
request, True)]
|
request, True)]
|
||||||
all_networks = dashboard_api.neutron.network_list(request)
|
|
||||||
networks = [{'id': nw.id,
|
|
||||||
'name': nw.name if nw.name else '(%s)' % nw.id[:6]}
|
|
||||||
for nw in all_networks if not nw['router:external']]
|
|
||||||
floating_networks = [{'id': nw.id,
|
|
||||||
'name': nw.name if nw.name else '(%s)' % nw.id[:6]}
|
|
||||||
for nw in all_networks if nw['router:external']]
|
|
||||||
floating_network_ids = [nw.get('id') for nw in floating_networks]
|
|
||||||
|
|
||||||
ports = [{'id': port.id,
|
|
||||||
|
@handle_exception
|
||||||
|
def get_ports(request):
|
||||||
|
return [{'id': port.id,
|
||||||
'name': port.name if port.name else '(%s)' % port.id[:6]}
|
'name': port.name if port.name else '(%s)' % port.id[:6]}
|
||||||
for port in dashboard_api.neutron.port_list(request)]
|
for port in dashboard_api.neutron.port_list(request)]
|
||||||
security_groups = [
|
|
||||||
{'id': secgroup.id,
|
|
||||||
|
@handle_exception
|
||||||
|
def get_security_groups(request):
|
||||||
|
return [{'id': secgroup.id,
|
||||||
'name': secgroup.name
|
'name': secgroup.name
|
||||||
if secgroup.name else '(%s)' % secgroup.id[:6]}
|
if secgroup.name else '(%s)' % secgroup.id[:6]}
|
||||||
for secgroup in dashboard_api.neutron.security_group_list(request)]
|
for secgroup in dashboard_api.neutron.security_group_list(request)]
|
||||||
all_subnets = dashboard_api.neutron.subnet_list(request)
|
|
||||||
subnets = [
|
|
||||||
{'id': subnet.id,
|
|
||||||
'name': subnet.name if subnet.name else '(%s)' % subnet.id[:6]}
|
|
||||||
for subnet in all_subnets]
|
|
||||||
|
|
||||||
floating_subnets = [{'id': subnet.id, 'name': subnet.name}
|
|
||||||
for subnet in all_subnets
|
|
||||||
if subnet.network_id in floating_network_ids]
|
|
||||||
|
|
||||||
routers = [
|
@handle_exception
|
||||||
{'id': router.id,
|
def get_routers(request):
|
||||||
|
return [{'id': router.id,
|
||||||
'name': router.name if router.name else '(%s)' % router.id[:6]}
|
'name': router.name if router.name else '(%s)' % router.id[:6]}
|
||||||
for router in dashboard_api.neutron.router_list(request)]
|
for router in dashboard_api.neutron.router_list(request)]
|
||||||
qos_policies = []
|
|
||||||
# qos_policies = [
|
|
||||||
# {'id': policy.id,
|
|
||||||
# 'name': policy.name
|
|
||||||
# if policy.name else '(%s)' % policy.id[:6]}
|
|
||||||
# for policy in dashboard_api.neutron.policy_list(request)]
|
|
||||||
|
|
||||||
availability_zones = [
|
|
||||||
{'id': az.zoneName, 'name': az.zoneName}
|
@handle_exception
|
||||||
|
def get_qos_policies(request):
|
||||||
|
return [{'id': policy.id,
|
||||||
|
'name': policy.name
|
||||||
|
if policy.name else '(%s)' % policy.id[:6]}
|
||||||
|
for policy in dashboard_api.neutron.policy_list(request)]
|
||||||
|
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def get_availability_zones(request):
|
||||||
|
return [{'id': az.zoneName, 'name': az.zoneName}
|
||||||
for az in dashboard_api.nova.availability_zone_list(request)]
|
for az in dashboard_api.nova.availability_zone_list(request)]
|
||||||
flavors = [{'id': flavor.name, 'name': flavor.name}
|
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def get_flavors(request):
|
||||||
|
return [{'id': flavor.name, 'name': flavor.name}
|
||||||
for flavor in dashboard_api.nova.flavor_list(request)]
|
for flavor in dashboard_api.nova.flavor_list(request)]
|
||||||
instances = [{'id': server.id,
|
|
||||||
'name': server.name
|
|
||||||
if server.name else '(%s)' % server.id[:6]}
|
@handle_exception
|
||||||
for server in dashboard_api.nova.server_list(request)[0]]
|
def get_instances(request):
|
||||||
keypairs = [{'name': keypair.name}
|
servers = dashboard_api.nova.server_list(request)
|
||||||
|
if isinstance(servers, tuple):
|
||||||
|
servers = servers[0]
|
||||||
|
return [{'id': server.id,
|
||||||
|
'name': server.name if server.name else '(%s)' % server.id[:6]}
|
||||||
|
for server in servers]
|
||||||
|
|
||||||
|
|
||||||
|
@handle_exception
|
||||||
|
def get_keypairs(request):
|
||||||
|
return [{'name': keypair.name}
|
||||||
for keypair in dashboard_api.nova.keypair_list(request)]
|
for keypair in dashboard_api.nova.keypair_list(request)]
|
||||||
|
|
||||||
template_versions = [
|
|
||||||
{'name': version.version, 'id': version.version}
|
@handle_exception
|
||||||
for version in api.heat.template_version_list(request)
|
def get_template_versions(request):
|
||||||
|
return [{'name': version.version, 'id': version.version}
|
||||||
|
for version in heat_api.heat.template_version_list(request)
|
||||||
if version.type == 'hot']
|
if version.type == 'hot']
|
||||||
|
|
||||||
opts = {
|
|
||||||
'auth': {
|
class APIThread(object):
|
||||||
'tenant_id': request.user.tenant_id,
|
thread_pool = pool.ThreadPool(processes=API_PARALLEL)
|
||||||
'admin': request.user.roles[0]['name'] == 'admin',
|
async_results = {}
|
||||||
},
|
|
||||||
'volumes': volumes,
|
def add_thread(self, apikey, func, args):
|
||||||
'volume_snapshots': volume_snapshots,
|
self.async_results[apikey] = self.thread_pool.apply_async(func, args)
|
||||||
'volume_types': volume_types,
|
|
||||||
'volume_backups': volume_backups,
|
def get_async_result(self, apikey):
|
||||||
'images': images,
|
if apikey not in self.async_results:
|
||||||
'floatingips': floatingips,
|
return [], None
|
||||||
'floating_networks': floating_networks,
|
try:
|
||||||
'floating_subnets': floating_subnets,
|
ret, err = self.async_results[apikey].get(
|
||||||
'networks': networks,
|
timeout=API_TIMEOUT)
|
||||||
'ports': ports,
|
except Exception as error:
|
||||||
'security_groups': security_groups,
|
ret, err = [], error.message
|
||||||
'subnets': subnets,
|
return ret, err
|
||||||
'routers': routers,
|
|
||||||
'qos_policies': qos_policies,
|
|
||||||
'availability_zones': availability_zones,
|
def _get_network_resources(options, all_networks):
|
||||||
'flavors': flavors,
|
try:
|
||||||
'instances': instances,
|
if all_networks:
|
||||||
'keypairs': keypairs,
|
options['networks'] = [
|
||||||
'template_versions': template_versions,
|
{'id': nw.id,
|
||||||
|
'name': nw.name if nw.name else '(%s)' % nw.id[: 6]}
|
||||||
|
for nw in all_networks if not getattr(nw, 'router:external')]
|
||||||
|
options['floating_networks'] = [
|
||||||
|
{'id': nw.id,
|
||||||
|
'name': nw.name if nw.name else '(%s)' % nw.id[: 6]}
|
||||||
|
for nw in all_networks if getattr(nw, 'router:external')]
|
||||||
|
else:
|
||||||
|
options['networks'] = []
|
||||||
|
options['floating_networks'] = []
|
||||||
|
except Exception:
|
||||||
|
options['networks'] = []
|
||||||
|
options['floating_networks'] = []
|
||||||
|
|
||||||
|
|
||||||
|
def _get_subnet_resources(options, all_subnets):
|
||||||
|
try:
|
||||||
|
if all_subnets and options.get('floating_networks'):
|
||||||
|
floating_network_ids = [nw.get('id')
|
||||||
|
for nw in options['floating_networks']]
|
||||||
|
options['subnets'] = [{'id': sb.id, 'name': sb.name}
|
||||||
|
for sb in all_subnets
|
||||||
|
if sb.network_id not in floating_network_ids]
|
||||||
|
|
||||||
|
options['floating_subnets'] = [
|
||||||
|
{'id': subnet.id, 'name': subnet.name}
|
||||||
|
for subnet in all_subnets
|
||||||
|
if subnet.network_id in floating_network_ids]
|
||||||
|
else:
|
||||||
|
options['subnets'] = []
|
||||||
|
options['floating_subnets'] = []
|
||||||
|
except Exception:
|
||||||
|
options['subnets'] = []
|
||||||
|
options['floating_subnets'] = []
|
||||||
|
|
||||||
|
|
||||||
|
def get_resource_options(request):
|
||||||
|
api_threads = APIThread()
|
||||||
|
api_mapping = {
|
||||||
|
'volumes': get_volume_ids,
|
||||||
|
'volume_snapshots': get_volume_snapshots,
|
||||||
|
'volume_types': get_volume_types,
|
||||||
|
'volume_backups': get_volume_backups,
|
||||||
|
'images': get_images,
|
||||||
|
'floatingips': get_floatingips,
|
||||||
|
'networks': get_networks,
|
||||||
|
'subnets': get_subnets,
|
||||||
|
'ports': get_ports,
|
||||||
|
'security_group': get_security_groups,
|
||||||
|
'routers': get_routers,
|
||||||
|
'qos_policies': get_qos_policies,
|
||||||
|
'availability_zones': get_availability_zones,
|
||||||
|
'flavors': get_flavors,
|
||||||
|
'instances': get_instances,
|
||||||
|
'keypairs': get_keypairs,
|
||||||
|
'template_versions': get_template_versions,
|
||||||
}
|
}
|
||||||
|
|
||||||
return json.dumps(opts)
|
options = {}
|
||||||
|
errors = {}
|
||||||
|
|
||||||
|
for resource, method in api_mapping.items():
|
||||||
|
api_threads.add_thread(resource, method, args=(request,))
|
||||||
|
|
||||||
|
for resource in api_mapping.keys():
|
||||||
|
ret, err = api_threads.get_async_result(resource)
|
||||||
|
options[resource] = ret
|
||||||
|
if err:
|
||||||
|
errors[resource.replace('_', ' ').capitalize()] = err
|
||||||
|
|
||||||
|
all_networks = options.pop('networks')
|
||||||
|
_get_network_resources(options, all_networks)
|
||||||
|
|
||||||
|
all_subnets = options.pop('subnets')
|
||||||
|
_get_subnet_resources(options, all_subnets)
|
||||||
|
|
||||||
|
role_names = []
|
||||||
|
for role in request.user.roles:
|
||||||
|
role_names.append(role.get('name'))
|
||||||
|
options.update({
|
||||||
|
'auth': {
|
||||||
|
'tenant_id': request.user.tenant_id,
|
||||||
|
'admin': 'admin' in role_names,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(errors.keys()) > 0:
|
||||||
|
options.update({'errors': errors})
|
||||||
|
|
||||||
|
return json.dumps(options)
|
||||||
|
@ -16,8 +16,6 @@ from heat_dashboard.content.template_generator import views
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', views.IndexView.as_view(), name='index'),
|
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||||
url(r'^get_resources$',
|
|
||||||
views.ApiView.as_view(), name="options"),
|
|
||||||
url(r'^get_resource_options$',
|
url(r'^get_resource_options$',
|
||||||
views.OptionView.as_view(), name="apis"),
|
views.OptionView.as_view(), name="apis"),
|
||||||
]
|
]
|
||||||
|
@ -17,7 +17,7 @@ from django.views import generic
|
|||||||
|
|
||||||
from horizon.browsers.views import AngularIndexView
|
from horizon.browsers.views import AngularIndexView
|
||||||
|
|
||||||
import api
|
from heat_dashboard.content.template_generator import api
|
||||||
|
|
||||||
|
|
||||||
class IndexView(AngularIndexView):
|
class IndexView(AngularIndexView):
|
||||||
@ -25,12 +25,6 @@ class IndexView(AngularIndexView):
|
|||||||
page_title = _("Template Generator")
|
page_title = _("Template Generator")
|
||||||
|
|
||||||
|
|
||||||
class ApiView(generic.View):
|
|
||||||
def get(self, request):
|
|
||||||
return HttpResponse(api.get_resources(request),
|
|
||||||
content_type="application/json")
|
|
||||||
|
|
||||||
|
|
||||||
class OptionView(generic.View):
|
class OptionView(generic.View):
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
return HttpResponse(api.get_resource_options(request),
|
return HttpResponse(api.get_resource_options(request),
|
||||||
|
@ -32,3 +32,9 @@ settings.POLICY_FILES.update({
|
|||||||
# 'propagate': False,
|
# 'propagate': False,
|
||||||
# }
|
# }
|
||||||
# })
|
# })
|
||||||
|
|
||||||
|
# Template Generator retrieve options API TIMEOUT
|
||||||
|
API_TIMEOUT = 60
|
||||||
|
|
||||||
|
# Template Generator retrieve options API PARALLEL LEVEL
|
||||||
|
API_PARALLEL = 2
|
||||||
|
@ -15,7 +15,17 @@
|
|||||||
}).then(function successCallback(response) {
|
}).then(function successCallback(response) {
|
||||||
// this callback will be called asynchronously
|
// this callback will be called asynchronously
|
||||||
// when the response is available
|
// when the response is available
|
||||||
|
if (response.data.errors){
|
||||||
|
var msg = '';
|
||||||
|
angular.forEach(response.data.errors, function(value, key){
|
||||||
|
msg += key + ': '+ value + '. '
|
||||||
|
})
|
||||||
|
|
||||||
|
hotgenNotify.show_warning('Unable to retrieve resources '+msg+'.');
|
||||||
|
}
|
||||||
|
else{
|
||||||
hotgenNotify.show_success('Retrieve openstack resources successfully.');
|
hotgenNotify.show_success('Retrieve openstack resources successfully.');
|
||||||
|
}
|
||||||
return response.data;
|
return response.data;
|
||||||
}, function errorCallback(response) {
|
}, function errorCallback(response) {
|
||||||
// called asynchronously if an error occurs
|
// called asynchronously if an error occurs
|
||||||
|
@ -60,6 +60,26 @@
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return get_resource_options with errors', function(){
|
||||||
|
spyOn($location, 'absUrl').and.callFake(function (p) {
|
||||||
|
return 'http://some-url/';
|
||||||
|
});
|
||||||
|
requestHandler.respond(200, {
|
||||||
|
'auth': {
|
||||||
|
'tenant_id': 'tenant-id',
|
||||||
|
'admin': false,
|
||||||
|
},'errors': {'a': 'b'}}
|
||||||
|
);
|
||||||
|
$httpBackend.expectGET('http://some-url/get_resource_options');
|
||||||
|
var optionsPromise = hotgenAgent.get_resource_options();
|
||||||
|
optionsPromise.then(function(options){
|
||||||
|
expect(options.auth.tenant_id).toEqual('tenant-id');
|
||||||
|
expect(options.auth.admin).toEqual(false);
|
||||||
|
});
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
it('should return error', function(){
|
it('should return error', function(){
|
||||||
spyOn($location, 'absUrl').and.callFake(function (p) {
|
spyOn($location, 'absUrl').and.callFake(function (p) {
|
||||||
return 'http://some-url';
|
return 'http://some-url';
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
$scope.nodes = hotgenStates.get_nodes();
|
$scope.nodes = hotgenStates.get_nodes();
|
||||||
$scope.selected = hotgenStates.get_selected();
|
$scope.selected = hotgenStates.get_selected();
|
||||||
$scope.toggle = function (item, list) {
|
$scope.toggle = function (item, list) {
|
||||||
|
if (typeof item == 'undefined' || !(list instanceof Array)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
var idx = list.indexOf(item);
|
var idx = list.indexOf(item);
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
list.splice(idx, 1);
|
list.splice(idx, 1);
|
||||||
@ -24,7 +27,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.exists = function (item, list) {
|
$scope.exists = function (item, list) {
|
||||||
|
if (typeof item != "undefined" && list instanceof Array){
|
||||||
return list.indexOf(item) > -1;
|
return list.indexOf(item) > -1;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
209
heat_dashboard/test/test_data/cinder_data.py
Normal file
209
heat_dashboard/test/test_data/cinder_data.py
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
# Copyright 2012 Nebula, 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 cinderclient.v2 import volume_backups as vol_backups
|
||||||
|
from cinderclient.v2 import volume_snapshots as vol_snaps
|
||||||
|
from cinderclient.v2 import volume_types
|
||||||
|
from cinderclient.v2 import volumes
|
||||||
|
|
||||||
|
from openstack_dashboard import api
|
||||||
|
|
||||||
|
from openstack_dashboard.test.test_data import utils
|
||||||
|
|
||||||
|
|
||||||
|
def data(TEST):
|
||||||
|
TEST.cinder_volumes = utils.TestDataContainer()
|
||||||
|
TEST.cinder_volume_backups = utils.TestDataContainer()
|
||||||
|
TEST.cinder_volume_types = utils.TestDataContainer()
|
||||||
|
TEST.cinder_volume_snapshots = utils.TestDataContainer()
|
||||||
|
|
||||||
|
# Volumes - Cinder v1
|
||||||
|
volume = volumes.Volume(
|
||||||
|
volumes.VolumeManager(None),
|
||||||
|
{'id': "11023e92-8008-4c8b-8059-7f2293ff3887",
|
||||||
|
'status': 'available',
|
||||||
|
'size': 40,
|
||||||
|
'display_name': 'Volume name',
|
||||||
|
'display_description': 'Volume description',
|
||||||
|
'created_at': '2014-01-27 10:30:00',
|
||||||
|
'volume_type': None,
|
||||||
|
'attachments': []})
|
||||||
|
nameless_volume = volumes.Volume(
|
||||||
|
volumes.VolumeManager(None),
|
||||||
|
{"id": "4b069dd0-6eaa-4272-8abc-5448a68f1cce",
|
||||||
|
"status": 'available',
|
||||||
|
"size": 10,
|
||||||
|
"display_name": '',
|
||||||
|
"display_description": '',
|
||||||
|
"device": "/dev/hda",
|
||||||
|
"created_at": '2010-11-21 18:34:25',
|
||||||
|
"volume_type": 'vol_type_1',
|
||||||
|
"attachments": []})
|
||||||
|
other_volume = volumes.Volume(
|
||||||
|
volumes.VolumeManager(None),
|
||||||
|
{'id': "21023e92-8008-1234-8059-7f2293ff3889",
|
||||||
|
'status': 'in-use',
|
||||||
|
'size': 10,
|
||||||
|
'display_name': u'my_volume',
|
||||||
|
'display_description': '',
|
||||||
|
'created_at': '2013-04-01 10:30:00',
|
||||||
|
'volume_type': None,
|
||||||
|
'attachments': [{"id": "1", "server_id": '1',
|
||||||
|
"device": "/dev/hda"}]})
|
||||||
|
volume_with_type = volumes.Volume(
|
||||||
|
volumes.VolumeManager(None),
|
||||||
|
{'id': "7dcb47fd-07d9-42c2-9647-be5eab799ebe",
|
||||||
|
'name': 'my_volume2',
|
||||||
|
'status': 'in-use',
|
||||||
|
'size': 10,
|
||||||
|
'display_name': u'my_volume2',
|
||||||
|
'display_description': '',
|
||||||
|
'created_at': '2013-04-01 10:30:00',
|
||||||
|
'volume_type': 'vol_type_2',
|
||||||
|
'attachments': [{"id": "2", "server_id": '2',
|
||||||
|
"device": "/dev/hdb"}]})
|
||||||
|
non_bootable_volume = volumes.Volume(
|
||||||
|
volumes.VolumeManager(None),
|
||||||
|
{'id': "21023e92-8008-1234-8059-7f2293ff3890",
|
||||||
|
'status': 'in-use',
|
||||||
|
'size': 10,
|
||||||
|
'display_name': u'my_volume',
|
||||||
|
'display_description': '',
|
||||||
|
'created_at': '2013-04-01 10:30:00',
|
||||||
|
'volume_type': None,
|
||||||
|
'bootable': False,
|
||||||
|
'attachments': [{"id": "1", "server_id": '1',
|
||||||
|
"device": "/dev/hda"}]})
|
||||||
|
|
||||||
|
volume.bootable = 'true'
|
||||||
|
nameless_volume.bootable = 'true'
|
||||||
|
other_volume.bootable = 'true'
|
||||||
|
|
||||||
|
TEST.cinder_volumes.add(api.cinder.Volume(volume))
|
||||||
|
TEST.cinder_volumes.add(api.cinder.Volume(nameless_volume))
|
||||||
|
TEST.cinder_volumes.add(api.cinder.Volume(other_volume))
|
||||||
|
TEST.cinder_volumes.add(api.cinder.Volume(volume_with_type))
|
||||||
|
TEST.cinder_volumes.add(api.cinder.Volume(non_bootable_volume))
|
||||||
|
|
||||||
|
vol_type1 = volume_types.VolumeType(volume_types.VolumeTypeManager(None),
|
||||||
|
{'id': u'1',
|
||||||
|
'name': u'vol_type_1',
|
||||||
|
'description': 'type 1 description',
|
||||||
|
'extra_specs': {'foo': 'bar',
|
||||||
|
'volume_backend_name':
|
||||||
|
'backend_1'}})
|
||||||
|
vol_type2 = volume_types.VolumeType(volume_types.VolumeTypeManager(None),
|
||||||
|
{'id': u'2',
|
||||||
|
'name': u'vol_type_2',
|
||||||
|
'description': 'type 2 description'})
|
||||||
|
vol_type3 = volume_types.VolumeType(volume_types.VolumeTypeManager(None),
|
||||||
|
{'id': u'3',
|
||||||
|
'name': u'vol_type_3',
|
||||||
|
'is_public': False,
|
||||||
|
'description': 'type 3 description'})
|
||||||
|
TEST.cinder_volume_types.add(vol_type1, vol_type2, vol_type3)
|
||||||
|
|
||||||
|
# Volumes - Cinder v2
|
||||||
|
volume_v2 = volumes.Volume(
|
||||||
|
volumes.VolumeManager(None),
|
||||||
|
{'id': "31023e92-8008-4c8b-8059-7f2293ff1234",
|
||||||
|
'name': 'v2_volume',
|
||||||
|
'description': "v2 Volume Description",
|
||||||
|
'status': 'available',
|
||||||
|
'size': 20,
|
||||||
|
'created_at': '2014-01-27 10:30:00',
|
||||||
|
'volume_type': None,
|
||||||
|
'os-vol-host-attr:host': 'host@backend-name#pool',
|
||||||
|
'bootable': 'true',
|
||||||
|
'attachments': []})
|
||||||
|
volume_v2.bootable = 'true'
|
||||||
|
|
||||||
|
TEST.cinder_volumes.add(api.cinder.Volume(volume_v2))
|
||||||
|
|
||||||
|
snapshot = vol_snaps.Snapshot(
|
||||||
|
vol_snaps.SnapshotManager(None),
|
||||||
|
{'id': '5f3d1c33-7d00-4511-99df-a2def31f3b5d',
|
||||||
|
'display_name': 'test snapshot',
|
||||||
|
'display_description': 'volume snapshot',
|
||||||
|
'size': 40,
|
||||||
|
'status': 'available',
|
||||||
|
'volume_id': '11023e92-8008-4c8b-8059-7f2293ff3887'})
|
||||||
|
snapshot2 = vol_snaps.Snapshot(
|
||||||
|
vol_snaps.SnapshotManager(None),
|
||||||
|
{'id': 'c9d0881a-4c0b-4158-a212-ad27e11c2b0f',
|
||||||
|
'name': '',
|
||||||
|
'description': 'v2 volume snapshot description',
|
||||||
|
'size': 80,
|
||||||
|
'status': 'available',
|
||||||
|
'volume_id': '31023e92-8008-4c8b-8059-7f2293ff1234'})
|
||||||
|
snapshot3 = vol_snaps.Snapshot(
|
||||||
|
vol_snaps.SnapshotManager(None),
|
||||||
|
{'id': 'c9d0881a-4c0b-4158-a212-ad27e11c2b0e',
|
||||||
|
'name': '',
|
||||||
|
'description': 'v2 volume snapshot description 2',
|
||||||
|
'size': 80,
|
||||||
|
'status': 'available',
|
||||||
|
'volume_id': '31023e92-8008-4c8b-8059-7f2293ff1234'})
|
||||||
|
snapshot4 = vol_snaps.Snapshot(
|
||||||
|
vol_snaps.SnapshotManager(None),
|
||||||
|
{'id': 'cd6be1eb-82ca-4587-8036-13c37c00c2b1',
|
||||||
|
'name': '',
|
||||||
|
'description': 'v2 volume snapshot with metadata description',
|
||||||
|
'size': 80,
|
||||||
|
'status': 'available',
|
||||||
|
'volume_id': '31023e92-8008-4c8b-8059-7f2293ff1234',
|
||||||
|
'metadata': {'snapshot_meta_key': 'snapshot_meta_value'}})
|
||||||
|
|
||||||
|
snapshot.bootable = 'true'
|
||||||
|
snapshot2.bootable = 'true'
|
||||||
|
|
||||||
|
TEST.cinder_volume_snapshots.add(api.cinder.VolumeSnapshot(snapshot))
|
||||||
|
TEST.cinder_volume_snapshots.add(api.cinder.VolumeSnapshot(snapshot2))
|
||||||
|
TEST.cinder_volume_snapshots.add(api.cinder.VolumeSnapshot(snapshot3))
|
||||||
|
TEST.cinder_volume_snapshots.add(api.cinder.VolumeSnapshot(snapshot4))
|
||||||
|
TEST.cinder_volume_snapshots.first()._volume = volume
|
||||||
|
|
||||||
|
volume_backup1 = vol_backups.VolumeBackup(
|
||||||
|
vol_backups.VolumeBackupManager(None),
|
||||||
|
{'id': 'a374cbb8-3f99-4c3f-a2ef-3edbec842e31',
|
||||||
|
'name': 'backup1',
|
||||||
|
'description': 'volume backup 1',
|
||||||
|
'size': 10,
|
||||||
|
'status': 'available',
|
||||||
|
'container_name': 'volumebackups',
|
||||||
|
'volume_id': '11023e92-8008-4c8b-8059-7f2293ff3887'})
|
||||||
|
|
||||||
|
volume_backup2 = vol_backups.VolumeBackup(
|
||||||
|
vol_backups.VolumeBackupManager(None),
|
||||||
|
{'id': 'c321cbb8-3f99-4c3f-a2ef-3edbec842e52',
|
||||||
|
'name': 'backup2',
|
||||||
|
'description': 'volume backup 2',
|
||||||
|
'size': 20,
|
||||||
|
'status': 'available',
|
||||||
|
'container_name': 'volumebackups',
|
||||||
|
'volume_id': '31023e92-8008-4c8b-8059-7f2293ff1234'})
|
||||||
|
|
||||||
|
volume_backup3 = vol_backups.VolumeBackup(
|
||||||
|
vol_backups.VolumeBackupManager(None),
|
||||||
|
{'id': 'c321cbb8-3f99-4c3f-a2ef-3edbec842e53',
|
||||||
|
'name': 'backup3',
|
||||||
|
'description': 'volume backup 3',
|
||||||
|
'size': 20,
|
||||||
|
'status': 'available',
|
||||||
|
'container_name': 'volumebackups',
|
||||||
|
'volume_id': '31023e92-8008-4c8b-8059-7f2293ff1234'})
|
||||||
|
|
||||||
|
TEST.cinder_volume_backups.add(volume_backup1)
|
||||||
|
TEST.cinder_volume_backups.add(volume_backup2)
|
||||||
|
TEST.cinder_volume_backups.add(volume_backup3)
|
426
heat_dashboard/test/test_data/glance_data.py
Normal file
426
heat_dashboard/test/test_data/glance_data.py
Normal file
@ -0,0 +1,426 @@
|
|||||||
|
# Copyright 2012 Nebula, 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 glanceclient.v1 import images
|
||||||
|
|
||||||
|
from openstack_dashboard import api
|
||||||
|
|
||||||
|
from heat_dashboard.test.test_data import utils
|
||||||
|
|
||||||
|
|
||||||
|
class Namespace(dict):
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Namespace %s>" % self._info
|
||||||
|
|
||||||
|
def __init__(self, info):
|
||||||
|
super(Namespace, self).__init__()
|
||||||
|
self.__dict__.update(info)
|
||||||
|
self.update(info)
|
||||||
|
self._info = info
|
||||||
|
|
||||||
|
def as_json(self, indent=4):
|
||||||
|
return self.__dict__
|
||||||
|
|
||||||
|
|
||||||
|
class APIResourceV2(dict):
|
||||||
|
_base_props = [
|
||||||
|
'id', 'name', 'status', 'visibility', 'protected', 'checksum', 'owner',
|
||||||
|
'size', 'virtual_size', 'container_format', 'disk_format',
|
||||||
|
'created_at', 'updated_at', 'tags', 'direct_url', 'min_ram',
|
||||||
|
'min_disk', 'self', 'file', 'schema', 'locations']
|
||||||
|
|
||||||
|
def __getattr__(self, item):
|
||||||
|
if item == 'schema':
|
||||||
|
return {'properties': {k: '' for k in self._base_props}}
|
||||||
|
else:
|
||||||
|
return self.get(item)
|
||||||
|
|
||||||
|
|
||||||
|
def data(TEST):
|
||||||
|
TEST.images = utils.TestDataContainer()
|
||||||
|
TEST.images_api = utils.TestDataContainer()
|
||||||
|
TEST.snapshots = utils.TestDataContainer()
|
||||||
|
TEST.metadata_defs = utils.TestDataContainer()
|
||||||
|
TEST.imagesV2 = utils.TestDataContainer()
|
||||||
|
|
||||||
|
# Snapshots
|
||||||
|
snapshot_dict = {'name': u'snapshot',
|
||||||
|
'container_format': u'ami',
|
||||||
|
'id': 3,
|
||||||
|
'status': "active",
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'properties': {'image_type': u'snapshot'},
|
||||||
|
'is_public': False,
|
||||||
|
'protected': False}
|
||||||
|
snapshot_dict_no_owner = {'name': u'snapshot 2',
|
||||||
|
'container_format': u'ami',
|
||||||
|
'id': 4,
|
||||||
|
'status': "active",
|
||||||
|
'owner': None,
|
||||||
|
'properties': {'image_type': u'snapshot'},
|
||||||
|
'is_public': False,
|
||||||
|
'protected': False}
|
||||||
|
snapshot_dict_queued = {'name': u'snapshot 2',
|
||||||
|
'container_format': u'ami',
|
||||||
|
'id': 5,
|
||||||
|
'status': "queued",
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'properties': {'image_type': u'snapshot'},
|
||||||
|
'is_public': False,
|
||||||
|
'protected': False}
|
||||||
|
snapshot = images.Image(images.ImageManager(None), snapshot_dict)
|
||||||
|
TEST.snapshots.add(api.glance.Image(snapshot))
|
||||||
|
snapshot = images.Image(images.ImageManager(None), snapshot_dict_no_owner)
|
||||||
|
TEST.snapshots.add(api.glance.Image(snapshot))
|
||||||
|
snapshot = images.Image(images.ImageManager(None), snapshot_dict_queued)
|
||||||
|
TEST.snapshots.add(api.glance.Image(snapshot))
|
||||||
|
|
||||||
|
# Images
|
||||||
|
image_dict = {'id': '007e7d55-fe1e-4c5c-bf08-44b4a4964822',
|
||||||
|
'name': 'public_image',
|
||||||
|
'disk_format': u'qcow2',
|
||||||
|
'status': "active",
|
||||||
|
'size': 20 * 1024 ** 3,
|
||||||
|
'virtual_size': None,
|
||||||
|
'min_disk': 0,
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'container_format': 'novaImage',
|
||||||
|
'properties': {'image_type': u'image'},
|
||||||
|
'is_public': True,
|
||||||
|
'protected': False,
|
||||||
|
'min_ram': 0,
|
||||||
|
'created_at': '2014-02-14T20:56:53'}
|
||||||
|
public_image = images.Image(images.ImageManager(None), image_dict)
|
||||||
|
|
||||||
|
image_dict = {'id': 'a001c047-22f8-47d0-80a1-8ec94a9524fe',
|
||||||
|
'name': 'private_image',
|
||||||
|
'status': "active",
|
||||||
|
'size': 10 * 1024 ** 2,
|
||||||
|
'virtual_size': 20 * 1024 ** 2,
|
||||||
|
'min_disk': 0,
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'container_format': 'aki',
|
||||||
|
'is_public': False,
|
||||||
|
'protected': False,
|
||||||
|
'min_ram': 0,
|
||||||
|
'created_at': '2014-03-14T12:56:53'}
|
||||||
|
private_image = images.Image(images.ImageManager(None), image_dict)
|
||||||
|
|
||||||
|
image_dict = {'id': 'd6936c86-7fec-474a-85c5-5e467b371c3c',
|
||||||
|
'name': 'protected_images',
|
||||||
|
'status': "active",
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'size': 2 * 1024 ** 3,
|
||||||
|
'virtual_size': None,
|
||||||
|
'min_disk': 30,
|
||||||
|
'container_format': 'novaImage',
|
||||||
|
'properties': {'image_type': u'image'},
|
||||||
|
'is_public': True,
|
||||||
|
'protected': True,
|
||||||
|
'min_ram': 0,
|
||||||
|
'created_at': '2014-03-16T06:22:14'}
|
||||||
|
protected_image = images.Image(images.ImageManager(None), image_dict)
|
||||||
|
|
||||||
|
image_dict = {'id': '278905a6-4b52-4d1e-98f9-8c57bb25ba32',
|
||||||
|
'name': None,
|
||||||
|
'status': "active",
|
||||||
|
'size': 5 * 1024 ** 3,
|
||||||
|
'virtual_size': None,
|
||||||
|
'min_disk': 0,
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'container_format': 'novaImage',
|
||||||
|
'properties': {'image_type': u'image'},
|
||||||
|
'is_public': True,
|
||||||
|
'protected': False,
|
||||||
|
'min_ram': 0}
|
||||||
|
public_image2 = images.Image(images.ImageManager(None), image_dict)
|
||||||
|
|
||||||
|
image_dict = {'id': '710a1acf-a3e3-41dd-a32d-5d6b6c86ea10',
|
||||||
|
'name': 'private_image 2',
|
||||||
|
'status': "active",
|
||||||
|
'size': 30 * 1024 ** 3,
|
||||||
|
'virtual_size': None,
|
||||||
|
'min_disk': 0,
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'container_format': 'aki',
|
||||||
|
'is_public': False,
|
||||||
|
'protected': False,
|
||||||
|
'min_ram': 0}
|
||||||
|
private_image2 = images.Image(images.ImageManager(None), image_dict)
|
||||||
|
|
||||||
|
image_dict = {'id': '7cd892fd-5652-40f3-a450-547615680132',
|
||||||
|
'name': 'private_image 3',
|
||||||
|
'status': "active",
|
||||||
|
'size': 2 * 1024 ** 3,
|
||||||
|
'virtual_size': None,
|
||||||
|
'min_disk': 0,
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'container_format': 'aki',
|
||||||
|
'is_public': False,
|
||||||
|
'protected': False,
|
||||||
|
'min_ram': 0}
|
||||||
|
private_image3 = images.Image(images.ImageManager(None), image_dict)
|
||||||
|
|
||||||
|
# A shared image. Not public and not local tenant.
|
||||||
|
image_dict = {'id': 'c8756975-7a3b-4e43-b7f7-433576112849',
|
||||||
|
'name': 'shared_image 1',
|
||||||
|
'status': "active",
|
||||||
|
'size': 8 * 1024 ** 3,
|
||||||
|
'virtual_size': None,
|
||||||
|
'min_disk': 0,
|
||||||
|
'owner': 'someothertenant',
|
||||||
|
'container_format': 'aki',
|
||||||
|
'is_public': False,
|
||||||
|
'protected': False,
|
||||||
|
'min_ram': 0}
|
||||||
|
shared_image1 = images.Image(images.ImageManager(None), image_dict)
|
||||||
|
|
||||||
|
# "Official" image. Public and tenant matches an entry
|
||||||
|
# in IMAGES_LIST_FILTER_TENANTS.
|
||||||
|
image_dict = {'id': 'f448704f-0ce5-4d34-8441-11b6581c6619',
|
||||||
|
'name': 'official_image 1',
|
||||||
|
'status': "active",
|
||||||
|
'size': 2 * 1024 ** 3,
|
||||||
|
'virtual_size': None,
|
||||||
|
'min_disk': 0,
|
||||||
|
'owner': 'officialtenant',
|
||||||
|
'container_format': 'aki',
|
||||||
|
'is_public': True,
|
||||||
|
'protected': False,
|
||||||
|
'min_ram': 0}
|
||||||
|
official_image1 = images.Image(images.ImageManager(None), image_dict)
|
||||||
|
|
||||||
|
image_dict = {'id': 'a67e7d45-fe1e-4c5c-bf08-44b4a4964822',
|
||||||
|
'name': 'multi_prop_image',
|
||||||
|
'status': "active",
|
||||||
|
'size': 20 * 1024 ** 3,
|
||||||
|
'virtual_size': None,
|
||||||
|
'min_disk': 0,
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'container_format': 'novaImage',
|
||||||
|
'properties': {'description': u'a multi prop image',
|
||||||
|
'foo': u'foo val',
|
||||||
|
'bar': u'bar val'},
|
||||||
|
'is_public': True,
|
||||||
|
'protected': False}
|
||||||
|
multi_prop_image = images.Image(images.ImageManager(None), image_dict)
|
||||||
|
|
||||||
|
# An image without name being returned based on current api
|
||||||
|
image_dict = {'id': 'c8756975-7a3b-4e43-b7f7-433576112849',
|
||||||
|
'status': "active",
|
||||||
|
'size': 8 * 1024 ** 3,
|
||||||
|
'virtual_size': None,
|
||||||
|
'min_disk': 0,
|
||||||
|
'owner': 'someothertenant',
|
||||||
|
'container_format': 'aki',
|
||||||
|
'is_public': False,
|
||||||
|
'protected': False}
|
||||||
|
no_name_image = images.Image(images.ImageManager(None), image_dict)
|
||||||
|
|
||||||
|
TEST.images_api.add(public_image, private_image, protected_image,
|
||||||
|
public_image2, private_image2, private_image3,
|
||||||
|
shared_image1, official_image1, multi_prop_image)
|
||||||
|
|
||||||
|
TEST.images.add(api.glance.Image(public_image),
|
||||||
|
api.glance.Image(private_image),
|
||||||
|
api.glance.Image(protected_image),
|
||||||
|
api.glance.Image(public_image2),
|
||||||
|
api.glance.Image(private_image2),
|
||||||
|
api.glance.Image(private_image3),
|
||||||
|
api.glance.Image(shared_image1),
|
||||||
|
api.glance.Image(official_image1),
|
||||||
|
api.glance.Image(multi_prop_image))
|
||||||
|
|
||||||
|
TEST.empty_name_image = api.glance.Image(no_name_image)
|
||||||
|
|
||||||
|
image_v2_dicts = [{
|
||||||
|
'checksum': 'eb9139e4942121f22bbc2afc0400b2a4',
|
||||||
|
'container_format': 'novaImage',
|
||||||
|
'created_at': '2014-02-14T20:56:53',
|
||||||
|
'direct_url': 'swift+config://ref1/glance/'
|
||||||
|
'da8500d5-8b80-4b9c-8410-cc57fb8fb9d5',
|
||||||
|
'disk_format': u'qcow2',
|
||||||
|
'file': '/v2/images/'
|
||||||
|
'da8500d5-8b80-4b9c-8410-cc57fb8fb9d5/file',
|
||||||
|
'id': '007e7d55-fe1e-4c5c-bf08-44b4a4964822',
|
||||||
|
'kernel_id': 'f6ebd5f0-b110-4406-8c1e-67b28d4e85e7',
|
||||||
|
'locations': [
|
||||||
|
{'metadata': {},
|
||||||
|
'url': 'swift+config://ref1/glance/'
|
||||||
|
'da8500d5-8b80-4b9c-8410-cc57fb8fb9d5'}],
|
||||||
|
'min_ram': 0,
|
||||||
|
'name': 'public_image',
|
||||||
|
'image_type': u'image',
|
||||||
|
'min_disk': 0,
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'protected': False,
|
||||||
|
'ramdisk_id': '868efefc-4f2d-4ed8-82b1-7e35576a7a47',
|
||||||
|
'size': 20 * 1024 ** 3,
|
||||||
|
'status': 'active',
|
||||||
|
'tags': ['active_image'],
|
||||||
|
'updated_at': '2015-08-31T19:37:45Z',
|
||||||
|
'virtual_size': None,
|
||||||
|
'visibility': 'public'
|
||||||
|
}, {
|
||||||
|
'checksum': None,
|
||||||
|
'container_format': 'novaImage',
|
||||||
|
'created_at': '2014-03-16T06:22:14',
|
||||||
|
'disk_format': None,
|
||||||
|
'image_type': u'image',
|
||||||
|
'file': '/v2/images/885d1cb0-9f5c-4677-9d03-175be7f9f984/file',
|
||||||
|
'id': 'd6936c86-7fec-474a-85c5-5e467b371c3c',
|
||||||
|
'locations': [],
|
||||||
|
'min_disk': 30,
|
||||||
|
'min_ram': 0,
|
||||||
|
'name': 'protected_images',
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'protected': True,
|
||||||
|
'size': 2 * 1024 ** 3,
|
||||||
|
'status': "active",
|
||||||
|
'tags': ['empty_image'],
|
||||||
|
'updated_at': '2015-09-01T22:37:32Z',
|
||||||
|
'virtual_size': None,
|
||||||
|
'visibility': 'public'
|
||||||
|
}, {
|
||||||
|
'checksum': 'e533283e6aac072533d1d091a7d2e413',
|
||||||
|
'container_format': 'novaImage',
|
||||||
|
'created_at': '2015-09-02T00:31:16Z',
|
||||||
|
'disk_format': 'qcow2',
|
||||||
|
'file': '/v2/images/10ca6b6b-48f4-43ac-8159-aa9e9353f5e4/file',
|
||||||
|
'id': 'a67e7d45-fe1e-4c5c-bf08-44b4a4964822',
|
||||||
|
'image_type': 'an image type',
|
||||||
|
'min_disk': 0,
|
||||||
|
'min_ram': 0,
|
||||||
|
'name': 'multi_prop_image',
|
||||||
|
'owner': TEST.tenant.id,
|
||||||
|
'protected': False,
|
||||||
|
'size': 20 * 1024 ** 3,
|
||||||
|
'status': 'active',
|
||||||
|
'tags': ['custom_property_image'],
|
||||||
|
'updated_at': '2015-09-02T00:31:17Z',
|
||||||
|
'virtual_size': None,
|
||||||
|
'visibility': 'public',
|
||||||
|
'description': u'a multi prop image',
|
||||||
|
'foo': u'foo val',
|
||||||
|
'bar': u'bar val'
|
||||||
|
}]
|
||||||
|
for fixture in image_v2_dicts:
|
||||||
|
apiresource = APIResourceV2(fixture)
|
||||||
|
TEST.imagesV2.add(api.glance.Image(apiresource))
|
||||||
|
|
||||||
|
metadef_dict = {
|
||||||
|
'namespace': 'namespace_1',
|
||||||
|
'display_name': 'Namespace 1',
|
||||||
|
'description': 'Mock desc 1',
|
||||||
|
'resource_type_associations': [
|
||||||
|
{
|
||||||
|
'created_at': '2014-08-21T08:39:43Z',
|
||||||
|
'prefix': 'mock',
|
||||||
|
'name': 'mock name'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'visibility': 'public',
|
||||||
|
'protected': True,
|
||||||
|
'created_at': '2014-08-21T08:39:43Z',
|
||||||
|
'properties': {
|
||||||
|
'cpu_mock:mock': {
|
||||||
|
'default': '1',
|
||||||
|
'type': 'integer',
|
||||||
|
'description': 'Number of mocks.',
|
||||||
|
'title': 'mocks'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadef = Namespace(metadef_dict)
|
||||||
|
TEST.metadata_defs.add(metadef)
|
||||||
|
|
||||||
|
metadef_dict = {
|
||||||
|
'namespace': 'namespace_2',
|
||||||
|
'display_name': 'Namespace 2',
|
||||||
|
'description': 'Mock desc 2',
|
||||||
|
'resource_type_associations': [
|
||||||
|
{
|
||||||
|
'created_at': '2014-08-21T08:39:43Z',
|
||||||
|
'prefix': 'mock',
|
||||||
|
'name': 'mock name'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'visibility': 'private',
|
||||||
|
'protected': False,
|
||||||
|
'created_at': '2014-08-21T08:39:43Z',
|
||||||
|
'properties': {
|
||||||
|
'hdd_mock:mock': {
|
||||||
|
'default': '2',
|
||||||
|
'type': 'integer',
|
||||||
|
'description': 'Number of mocks.',
|
||||||
|
'title': 'mocks'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadef = Namespace(metadef_dict)
|
||||||
|
TEST.metadata_defs.add(metadef)
|
||||||
|
|
||||||
|
metadef_dict = {
|
||||||
|
'namespace': 'namespace_3',
|
||||||
|
'display_name': 'Namespace 3',
|
||||||
|
'description': 'Mock desc 3',
|
||||||
|
'resource_type_associations': [
|
||||||
|
{
|
||||||
|
'created_at': '2014-08-21T08:39:43Z',
|
||||||
|
'prefix': 'mock',
|
||||||
|
'name': 'mock name'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'visibility': 'public',
|
||||||
|
'protected': False,
|
||||||
|
'created_at': '2014-08-21T08:39:43Z',
|
||||||
|
'properties': {
|
||||||
|
'gpu_mock:mock': {
|
||||||
|
'default': '2',
|
||||||
|
'type': 'integer',
|
||||||
|
'description': 'Number of mocks.',
|
||||||
|
'title': 'mocks'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadef = Namespace(metadef_dict)
|
||||||
|
TEST.metadata_defs.add(metadef)
|
||||||
|
|
||||||
|
metadef_dict = {
|
||||||
|
'namespace': 'namespace_4',
|
||||||
|
'display_name': 'Namespace 4',
|
||||||
|
'description': 'Mock desc 4',
|
||||||
|
'resource_type_associations': [
|
||||||
|
{
|
||||||
|
'created_at': '2014-08-21T08:39:43Z',
|
||||||
|
'prefix': 'mock',
|
||||||
|
'name': 'OS::Cinder::Volume',
|
||||||
|
'properties_target': 'user'
|
||||||
|
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'visibility': 'public',
|
||||||
|
'protected': True,
|
||||||
|
'created_at': '2014-08-21T08:39:43Z',
|
||||||
|
'properties': {
|
||||||
|
'ram_mock:mock': {
|
||||||
|
'default': '2',
|
||||||
|
'type': 'integer',
|
||||||
|
'description': 'Number of mocks.',
|
||||||
|
'title': 'mocks'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadef = Namespace(metadef_dict)
|
||||||
|
TEST.metadata_defs.add(metadef)
|
@ -22,6 +22,12 @@ from heat_dashboard.test.test_data import utils
|
|||||||
def data(TEST):
|
def data(TEST):
|
||||||
# Data returned by openstack_dashboard.api.neutron wrapper.
|
# Data returned by openstack_dashboard.api.neutron wrapper.
|
||||||
TEST.networks = utils.TestDataContainer()
|
TEST.networks = utils.TestDataContainer()
|
||||||
|
TEST.subnets = utils.TestDataContainer()
|
||||||
|
TEST.ports = utils.TestDataContainer()
|
||||||
|
TEST.routers = utils.TestDataContainer()
|
||||||
|
TEST.floating_ips = utils.TestDataContainer()
|
||||||
|
TEST.security_groups = utils.TestDataContainer()
|
||||||
|
TEST.qos_policies = utils.TestDataContainer()
|
||||||
|
|
||||||
# Data return by neutronclient.
|
# Data return by neutronclient.
|
||||||
TEST.api_networks = utils.TestDataContainer()
|
TEST.api_networks = utils.TestDataContainer()
|
||||||
@ -75,3 +81,116 @@ def data(TEST):
|
|||||||
subnetv6 = neutron.Subnet(subnetv6_dict)
|
subnetv6 = neutron.Subnet(subnetv6_dict)
|
||||||
network['subnets'] = [subnet, subnetv6]
|
network['subnets'] = [subnet, subnetv6]
|
||||||
TEST.networks.add(neutron.Network(network))
|
TEST.networks.add(neutron.Network(network))
|
||||||
|
TEST.subnets.add(subnet)
|
||||||
|
TEST.subnets.add(subnetv6)
|
||||||
|
|
||||||
|
# Ports on 1st network.
|
||||||
|
port_dict = {
|
||||||
|
'admin_state_up': True,
|
||||||
|
'device_id': 'af75c8e5-a1cc-4567-8d04-44fcd6922890',
|
||||||
|
'device_owner': 'network:dhcp',
|
||||||
|
'fixed_ips': [{'ip_address': '10.0.0.3',
|
||||||
|
'subnet_id': subnet_dict['id']}],
|
||||||
|
'id': '063cf7f3-ded1-4297-bc4c-31eae876cc91',
|
||||||
|
'mac_address': 'fa:16:3e:9c:d5:7e',
|
||||||
|
'name': '',
|
||||||
|
'network_id': network_dict['id'],
|
||||||
|
'status': 'ACTIVE',
|
||||||
|
'tenant_id': network_dict['tenant_id'],
|
||||||
|
'binding:vnic_type': 'normal',
|
||||||
|
'binding:host_id': 'host',
|
||||||
|
'allowed_address_pairs': [
|
||||||
|
{'ip_address': '174.0.0.201',
|
||||||
|
'mac_address': 'fa:16:3e:7a:7b:18'}
|
||||||
|
],
|
||||||
|
'port_security_enabled': True,
|
||||||
|
'security_groups': [],
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST.ports.add(neutron.Port(port_dict))
|
||||||
|
|
||||||
|
# External network.
|
||||||
|
network_dict = {'admin_state_up': True,
|
||||||
|
'id': '9b466b94-213a-4cda-badf-72c102a874da',
|
||||||
|
'name': 'ext_net',
|
||||||
|
'status': 'ACTIVE',
|
||||||
|
'subnets': ['d6bdc71c-7566-4d32-b3ff-36441ce746e8'],
|
||||||
|
'tenant_id': '3',
|
||||||
|
'router:external': True,
|
||||||
|
'shared': False}
|
||||||
|
subnet_dict = {'allocation_pools': [{'start': '172.24.4.226.',
|
||||||
|
'end': '172.24.4.238'}],
|
||||||
|
'dns_nameservers': [],
|
||||||
|
'host_routes': [],
|
||||||
|
'cidr': '172.24.4.0/28',
|
||||||
|
'enable_dhcp': False,
|
||||||
|
'gateway_ip': '172.24.4.225',
|
||||||
|
'id': 'd6bdc71c-7566-4d32-b3ff-36441ce746e8',
|
||||||
|
'ip_version': 4,
|
||||||
|
'name': 'ext_subnet',
|
||||||
|
'network_id': network_dict['id'],
|
||||||
|
'tenant_id': network_dict['tenant_id']}
|
||||||
|
ext_net = network_dict
|
||||||
|
network = copy.deepcopy(network_dict)
|
||||||
|
subnet = neutron.Subnet(subnet_dict)
|
||||||
|
network['subnets'] = [subnet]
|
||||||
|
TEST.networks.add(neutron.Network(network))
|
||||||
|
TEST.subnets.add(subnet)
|
||||||
|
|
||||||
|
assoc_port = port_dict
|
||||||
|
|
||||||
|
router_dict = {'id': '279989f7-54bb-41d9-ba42-0d61f12fda61',
|
||||||
|
'name': 'router1',
|
||||||
|
'status': 'ACTIVE',
|
||||||
|
'admin_state_up': True,
|
||||||
|
'distributed': True,
|
||||||
|
'external_gateway_info':
|
||||||
|
{'network_id': ext_net['id']},
|
||||||
|
'tenant_id': '1',
|
||||||
|
'availability_zone_hints': ['nova']}
|
||||||
|
TEST.routers.add(neutron.Router(router_dict))
|
||||||
|
|
||||||
|
# Associated (with compute port on 1st network).
|
||||||
|
fip_dict = {'tenant_id': '1',
|
||||||
|
'floating_ip_address': '172.16.88.228',
|
||||||
|
'floating_network_id': ext_net['id'],
|
||||||
|
'id': 'a97af8f2-3149-4b97-abbd-e49ad19510f7',
|
||||||
|
'fixed_ip_address': assoc_port['fixed_ips'][0]['ip_address'],
|
||||||
|
'port_id': assoc_port['id'],
|
||||||
|
'router_id': router_dict['id']}
|
||||||
|
fip_with_instance = copy.deepcopy(fip_dict)
|
||||||
|
fip_with_instance.update({'instance_id': '1',
|
||||||
|
'instance_type': 'compute'})
|
||||||
|
TEST.floating_ips.add(neutron.FloatingIp(fip_with_instance))
|
||||||
|
|
||||||
|
# Security group.
|
||||||
|
|
||||||
|
sec_group_1 = {'tenant_id': '1',
|
||||||
|
'description': 'default',
|
||||||
|
'id': 'faad7c80-3b62-4440-967c-13808c37131d',
|
||||||
|
'name': 'default'}
|
||||||
|
sec_group_2 = {'tenant_id': '1',
|
||||||
|
'description': 'NotDefault',
|
||||||
|
'id': '27a5c9a1-bdbb-48ac-833a-2e4b5f54b31d',
|
||||||
|
'name': 'other_group'}
|
||||||
|
sec_group_3 = {'tenant_id': '1',
|
||||||
|
'description': 'NotDefault',
|
||||||
|
'id': '443a4d7a-4bd2-4474-9a77-02b35c9f8c95',
|
||||||
|
'name': 'another_group'}
|
||||||
|
groups = [sec_group_1, sec_group_2, sec_group_3]
|
||||||
|
sg_name_dict = dict([(sg['id'], sg['name']) for sg in groups])
|
||||||
|
for sg in groups:
|
||||||
|
sg['security_group_rules'] = []
|
||||||
|
# OpenStack Dashboard internaly API.
|
||||||
|
TEST.security_groups.add(
|
||||||
|
neutron.SecurityGroup(copy.deepcopy(sg), sg_name_dict))
|
||||||
|
|
||||||
|
# qos policies
|
||||||
|
policy_dict = {'id': 'a21dcd22-7189-cccc-aa32-22adafaf16a7',
|
||||||
|
'name': 'policy 1',
|
||||||
|
'tenant_id': '1'}
|
||||||
|
TEST.qos_policies.add(neutron.QoSPolicy(policy_dict))
|
||||||
|
policy_dict1 = {'id': 'a21dcd22-7189-ssss-aa32-22adafaf16a7',
|
||||||
|
'name': 'policy 2',
|
||||||
|
'tenant_id': '1'}
|
||||||
|
TEST.qos_policies.add(neutron.QoSPolicy(policy_dict1))
|
||||||
|
201
heat_dashboard/test/test_data/nova_data.py
Normal file
201
heat_dashboard/test/test_data/nova_data.py
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
# Copyright 2012 Nebula, 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.
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from novaclient.v2 import availability_zones
|
||||||
|
from novaclient.v2 import flavors
|
||||||
|
from novaclient.v2 import keypairs
|
||||||
|
from novaclient.v2 import servers
|
||||||
|
|
||||||
|
from heat_dashboard.test.test_data import utils
|
||||||
|
|
||||||
|
|
||||||
|
class FlavorExtraSpecs(dict):
|
||||||
|
def __repr__(self):
|
||||||
|
return "<FlavorExtraSpecs %s>" % self._info
|
||||||
|
|
||||||
|
def __init__(self, info):
|
||||||
|
super(FlavorExtraSpecs, self).__init__()
|
||||||
|
self.__dict__.update(info)
|
||||||
|
self.update(info)
|
||||||
|
self._info = info
|
||||||
|
|
||||||
|
|
||||||
|
SERVER_DATA = """
|
||||||
|
{
|
||||||
|
"server": {
|
||||||
|
"OS-EXT-SRV-ATTR:instance_name": "instance-00000005",
|
||||||
|
"OS-EXT-SRV-ATTR:host": "instance-host",
|
||||||
|
"OS-EXT-STS:task_state": null,
|
||||||
|
"addresses": {
|
||||||
|
"private": [
|
||||||
|
{
|
||||||
|
"version": 4,
|
||||||
|
"addr": "10.0.0.1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "%(host)s/v1.1/%(tenant_id)s/servers/%(server_id)s",
|
||||||
|
"rel": "self"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"href": "%(host)s/%(tenant_id)s/servers/%(server_id)s",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"image": {
|
||||||
|
"id": "%(image_id)s",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "%(host)s/%(tenant_id)s/images/%(image_id)s",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"OS-EXT-STS:vm_state": "active",
|
||||||
|
"flavor": {
|
||||||
|
"id": "%(flavor_id)s",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"href": "%(host)s/%(tenant_id)s/flavors/%(flavor_id)s",
|
||||||
|
"rel": "bookmark"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"id": "%(server_id)s",
|
||||||
|
"user_id": "%(user_id)s",
|
||||||
|
"OS-DCF:diskConfig": "MANUAL",
|
||||||
|
"accessIPv4": "",
|
||||||
|
"accessIPv6": "",
|
||||||
|
"progress": null,
|
||||||
|
"OS-EXT-STS:power_state": 1,
|
||||||
|
"config_drive": "",
|
||||||
|
"status": "%(status)s",
|
||||||
|
"updated": "2012-02-28T19:51:27Z",
|
||||||
|
"hostId": "c461ea283faa0ab5d777073c93b126c68139e4e45934d4fc37e403c2",
|
||||||
|
"key_name": "%(key_name)s",
|
||||||
|
"name": "%(name)s",
|
||||||
|
"created": "2012-02-28T19:51:17Z",
|
||||||
|
"tenant_id": "%(tenant_id)s",
|
||||||
|
"metadata": {"someMetaLabel": "someMetaData",
|
||||||
|
"some<b>html</b>label": "<!--",
|
||||||
|
"empty": ""}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def data(TEST):
|
||||||
|
TEST.servers = utils.TestDataContainer()
|
||||||
|
TEST.flavors = utils.TestDataContainer()
|
||||||
|
TEST.keypairs = utils.TestDataContainer()
|
||||||
|
TEST.availability_zones = utils.TestDataContainer()
|
||||||
|
|
||||||
|
# Flavors
|
||||||
|
flavor_1 = flavors.Flavor(flavors.FlavorManager(None),
|
||||||
|
{'id': "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
|
||||||
|
'name': 'm1.tiny',
|
||||||
|
'vcpus': 1,
|
||||||
|
'disk': 0,
|
||||||
|
'ram': 512,
|
||||||
|
'swap': 0,
|
||||||
|
'rxtx_factor': 1,
|
||||||
|
'extra_specs': {},
|
||||||
|
'os-flavor-access:is_public': True,
|
||||||
|
'OS-FLV-EXT-DATA:ephemeral': 0})
|
||||||
|
flavor_2 = flavors.Flavor(flavors.FlavorManager(None),
|
||||||
|
{'id': "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
|
||||||
|
'name': 'm1.massive',
|
||||||
|
'vcpus': 1000,
|
||||||
|
'disk': 1024,
|
||||||
|
'ram': 10000,
|
||||||
|
'swap': 0,
|
||||||
|
'rxtx_factor': 1,
|
||||||
|
'extra_specs': {'Trusted': True, 'foo': 'bar'},
|
||||||
|
'os-flavor-access:is_public': True,
|
||||||
|
'OS-FLV-EXT-DATA:ephemeral': 2048})
|
||||||
|
flavor_3 = flavors.Flavor(flavors.FlavorManager(None),
|
||||||
|
{'id': "dddddddd-dddd-dddd-dddd-dddddddddddd",
|
||||||
|
'name': 'm1.secret',
|
||||||
|
'vcpus': 1000,
|
||||||
|
'disk': 1024,
|
||||||
|
'ram': 10000,
|
||||||
|
'swap': 0,
|
||||||
|
'rxtx_factor': 1,
|
||||||
|
'extra_specs': {},
|
||||||
|
'os-flavor-access:is_public': False,
|
||||||
|
'OS-FLV-EXT-DATA:ephemeral': 2048})
|
||||||
|
flavor_4 = flavors.Flavor(flavors.FlavorManager(None),
|
||||||
|
{'id': "eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee",
|
||||||
|
'name': 'm1.metadata',
|
||||||
|
'vcpus': 1000,
|
||||||
|
'disk': 1024,
|
||||||
|
'ram': 10000,
|
||||||
|
'swap': 0,
|
||||||
|
'rxtx_factor': 1,
|
||||||
|
'extra_specs': FlavorExtraSpecs(
|
||||||
|
{'key': 'key_mock',
|
||||||
|
'value': 'value_mock'}),
|
||||||
|
'os-flavor-access:is_public': False,
|
||||||
|
'OS-FLV-EXT-DATA:ephemeral': 2048})
|
||||||
|
TEST.flavors.add(flavor_1, flavor_2, flavor_3, flavor_4)
|
||||||
|
|
||||||
|
# Key pairs
|
||||||
|
keypair = keypairs.Keypair(keypairs.KeypairManager(None),
|
||||||
|
dict(name='keyName'))
|
||||||
|
TEST.keypairs.add(keypair)
|
||||||
|
|
||||||
|
# Servers
|
||||||
|
vals = {"host": "http://nova.example.com:8774",
|
||||||
|
"name": "server_1",
|
||||||
|
"status": "ACTIVE",
|
||||||
|
"tenant_id": TEST.tenants.first().id,
|
||||||
|
"user_id": TEST.user.id,
|
||||||
|
"server_id": "1",
|
||||||
|
"flavor_id": flavor_1.id,
|
||||||
|
"image_id": TEST.images.first().id,
|
||||||
|
"key_name": keypair.name}
|
||||||
|
server_1 = servers.Server(servers.ServerManager(None),
|
||||||
|
json.loads(SERVER_DATA % vals)['server'])
|
||||||
|
vals.update({"name": "server_2",
|
||||||
|
"status": "BUILD",
|
||||||
|
"server_id": "2"})
|
||||||
|
server_2 = servers.Server(servers.ServerManager(None),
|
||||||
|
json.loads(SERVER_DATA % vals)['server'])
|
||||||
|
vals.update({"name": "server_4",
|
||||||
|
"status": "PAUSED",
|
||||||
|
"server_id": "4"})
|
||||||
|
server_4 = servers.Server(servers.ServerManager(None),
|
||||||
|
json.loads(SERVER_DATA % vals)['server'])
|
||||||
|
TEST.servers.add(server_1, server_2, server_4)
|
||||||
|
|
||||||
|
# Availability Zones
|
||||||
|
TEST.availability_zones.add(availability_zones.AvailabilityZone(
|
||||||
|
availability_zones.AvailabilityZoneManager(None),
|
||||||
|
{
|
||||||
|
'zoneName': 'nova',
|
||||||
|
'zoneState': {'available': True},
|
||||||
|
'hosts': {
|
||||||
|
"host001": {
|
||||||
|
"nova-network": {
|
||||||
|
"active": True,
|
||||||
|
"available": True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
))
|
@ -14,18 +14,21 @@
|
|||||||
|
|
||||||
|
|
||||||
def load_test_data(load_onto=None):
|
def load_test_data(load_onto=None):
|
||||||
|
from heat_dashboard.test.test_data import cinder_data
|
||||||
from heat_dashboard.test.test_data import exceptions
|
from heat_dashboard.test.test_data import exceptions
|
||||||
|
from heat_dashboard.test.test_data import glance_data
|
||||||
from heat_dashboard.test.test_data import heat_data
|
from heat_dashboard.test.test_data import heat_data
|
||||||
from heat_dashboard.test.test_data import keystone_data
|
from heat_dashboard.test.test_data import keystone_data
|
||||||
from heat_dashboard.test.test_data import neutron_data
|
from heat_dashboard.test.test_data import neutron_data
|
||||||
|
from heat_dashboard.test.test_data import nova_data
|
||||||
|
|
||||||
# The order of these loaders matters, some depend on others.
|
# The order of these loaders matters, some depend on others.
|
||||||
loaders = (
|
loaders = (
|
||||||
exceptions.data,
|
exceptions.data,
|
||||||
keystone_data.data,
|
keystone_data.data,
|
||||||
# glance_data.data,
|
glance_data.data,
|
||||||
# nova_data.data,
|
nova_data.data,
|
||||||
# cinder_data.data,
|
cinder_data.data,
|
||||||
neutron_data.data,
|
neutron_data.data,
|
||||||
# swift_data.data,
|
# swift_data.data,
|
||||||
heat_data.data,
|
heat_data.data,
|
||||||
|
105
heat_dashboard/test/tests/content/test_template_generator.py
Normal file
105
heat_dashboard/test/tests/content/test_template_generator.py
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# 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 json
|
||||||
|
|
||||||
|
from mox3.mox import IsA
|
||||||
|
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from django import http
|
||||||
|
from openstack_dashboard import api as dashboard_api
|
||||||
|
|
||||||
|
from heat_dashboard import api
|
||||||
|
from heat_dashboard.test import helpers as test
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateGeneratorTests(test.TestCase):
|
||||||
|
|
||||||
|
def test_index(self):
|
||||||
|
self.client.get(reverse('horizon:project:template_generator:index'))
|
||||||
|
self.assertTemplateUsed(
|
||||||
|
template_name='project/template_generator/index.html')
|
||||||
|
|
||||||
|
@test.create_stubs({
|
||||||
|
api.heat: ('template_version_list', ),
|
||||||
|
dashboard_api.neutron: (
|
||||||
|
'network_list', 'subnet_list', 'tenant_floating_ip_list',
|
||||||
|
'port_list', 'security_group_list', 'router_list', 'policy_list'),
|
||||||
|
dashboard_api.cinder: (
|
||||||
|
'volume_list', 'volume_snapshot_list',
|
||||||
|
'volume_type_list', 'volume_backup_list'),
|
||||||
|
dashboard_api.glance: ('image_list_detailed', ),
|
||||||
|
dashboard_api.nova: ('availability_zone_list', 'flavor_list',
|
||||||
|
'server_list', 'keypair_list')})
|
||||||
|
def test_option(self):
|
||||||
|
volumes = self.cinder_volumes.list()
|
||||||
|
volume_snapshots = self.cinder_volume_snapshots.list()
|
||||||
|
volume_types = self.cinder_volume_types.list()
|
||||||
|
volume_backups = self.cinder_volume_backups.list()
|
||||||
|
images = self.imagesV2.list()
|
||||||
|
networks = self.networks.list()
|
||||||
|
subnets = self.subnets.list()
|
||||||
|
floating_ips = self.floating_ips.list()
|
||||||
|
ports = self.ports.list()
|
||||||
|
security_groups = self.security_groups.list()
|
||||||
|
routers = self.routers.list()
|
||||||
|
qos_policies = self.qos_policies.list()
|
||||||
|
availability_zones = self.availability_zones.list()
|
||||||
|
flavors = self.flavors.list()
|
||||||
|
instances = self.servers.list()
|
||||||
|
keypairs = self.keypairs.list()
|
||||||
|
template_versions = self.template_versions.list()
|
||||||
|
|
||||||
|
dashboard_api.cinder.volume_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(volumes)
|
||||||
|
dashboard_api.cinder.volume_snapshot_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(volume_snapshots)
|
||||||
|
dashboard_api.cinder.volume_type_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(volume_types)
|
||||||
|
dashboard_api.cinder.volume_backup_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(volume_backups)
|
||||||
|
dashboard_api.glance.image_list_detailed(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(images)
|
||||||
|
dashboard_api.neutron.network_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(networks)
|
||||||
|
dashboard_api.neutron.subnet_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(subnets)
|
||||||
|
dashboard_api.neutron.tenant_floating_ip_list(
|
||||||
|
IsA(http.HttpRequest), True).AndReturn(floating_ips)
|
||||||
|
dashboard_api.neutron.port_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(ports)
|
||||||
|
dashboard_api.neutron.security_group_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(security_groups)
|
||||||
|
dashboard_api.neutron.router_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(routers)
|
||||||
|
dashboard_api.neutron.policy_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(qos_policies)
|
||||||
|
dashboard_api.nova.availability_zone_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(availability_zones)
|
||||||
|
dashboard_api.nova.flavor_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(flavors)
|
||||||
|
dashboard_api.nova.server_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(instances)
|
||||||
|
dashboard_api.nova.keypair_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(keypairs)
|
||||||
|
api.heat.template_version_list(
|
||||||
|
IsA(http.HttpRequest)).AndReturn(template_versions)
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
resp = self.client.get(reverse(
|
||||||
|
'horizon:project:template_generator:apis'))
|
||||||
|
data = resp.content
|
||||||
|
if isinstance(data, bytes):
|
||||||
|
data = data.decode('utf-8')
|
||||||
|
json_data = json.loads(data)
|
||||||
|
self.assertEqual(len(json_data.keys()), 20)
|
Loading…
Reference in New Issue
Block a user