Initial Murano support
First stab at Murano support. Supports plugin autodetection, importing Packages and Bundles, installation detection and launch support. Change-Id: I70a268879e48a9d7e6c7cc6b5011a5d1e4710765
This commit is contained in:
parent
0d4bc3a00a
commit
60b8f3ada0
|
@ -20,8 +20,6 @@ How to try this package
|
|||
git clone http://github.com/openstack/horizon.git
|
||||
git clone http://github.com/stackforge/apps-catalog-ui.git
|
||||
cd horizon
|
||||
git fetch https://review.openstack.org/openstack/horizon refs/changes/73/206773/23 && git checkout FETCH_HEAD
|
||||
git fetch https://review.openstack.org/openstack/horizon refs/changes/43/216443/1 && git cherry-pick FETCH_HEAD
|
||||
./run_tests.sh -f --docs
|
||||
cp ./openstack_dashboard/local/local_settings.py.example ./openstack_dashboard/local/local_settings.py
|
||||
pushd ../apps-catalog-ui
|
||||
|
@ -30,3 +28,5 @@ How to try this package
|
|||
popd
|
||||
./run_tests.sh --runserver 127.0.0.1:18000
|
||||
|
||||
* For Murano support, you need to patch the murano-dashboard plugin with:
|
||||
https://review.openstack.org/#/c/217747/
|
||||
|
|
|
@ -8,10 +8,27 @@
|
|||
<div ng-switch-when="glance" ng-switch="asset.attributes.indirect_url || '_undefined_'">
|
||||
<a ng-switch-default ng-class="extraclasses" class="btn btn-primary btn-default" target="_blank" href="{$ asset.attributes.indirect_url $}">Install Instructions</a>
|
||||
<div ng-switch-when="_undefined_" ng-switch="asset.installed">
|
||||
<a ng-switch-default ng-class="extraclasses" class="btn btn-default disabled ajax-modal" href="/}">Checking</a>
|
||||
<a ng-switch-default ng-class="extraclasses" class="btn btn-default disabled ajax-modal" href="/">Checking</a>
|
||||
<a ng-switch-when="false" ng-class="extraclasses" class="btn btn-primary btn-default ajax-modal" href="/project/images/create/?name={$ asset.name | encodeURIComponent $}&source_type=url&image_url={$ asset.attributes.url | encodeURIComponent $}&disk_format={$ asset.service.disk_format $}&architecture={$ asset.service.architecture $}&minimum_disk={$ asset.service.min_disk $}&minimum_ram={$ asset.service.min_ram $}&description={$ asset.description $}">Install</a>
|
||||
<a ng-switch-when="true" ng-class="extraclasses" class="btn btn-success btn-default ajax-modal" href="/project/instances/launch?source_type=image_id&source_id={$ asset.installed_id $}">Launch</a>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-switch-when="murano" ng-switch="asset.has_murano">
|
||||
<a ng-switch-when="false" ng-class="extraclasses" class="btn btn-default disabled ajax-modal" href="/">Unsupported</a>
|
||||
<div ng-switch-when="true" ng-switch="asset.installed">
|
||||
<a ng-switch-default ng-class="extraclasses" class="btn btn-default disabled ajax-modal" href="/">Checking</a>
|
||||
<a ng-switch-when="false" ng-class="extraclasses" class="btn btn-primary btn-default ajax-modal" href="/murano/packages/upload?repo_name={$ asset.service.package_name | encodeURIComponent $}&import_type=by_name">Install</a>
|
||||
<a ng-switch-when="true" ng-class="extraclasses" class="btn btn-success btn-default ajax-modal" href="/murano/catalog/quick-add/{$ asset.service.murano_id $}">Launch</a>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-switch-when="bundle" ng-switch="asset.service.murano_package_name || '_undefined_'">
|
||||
<div ng-switch-when="_undefined_"></div>
|
||||
<div ng-switch-default ng-switch="asset.has_murano">
|
||||
<a ng-switch-when="false" ng-class="extraclasses" class="btn btn-default disabled ajax-modal" href="/">Unsupported</a>
|
||||
<div ng-switch-when="true" ng-switch="asset.installed || '_undefined_'">
|
||||
<a ng-switch-default ng-class="extraclasses" class="btn btn-primary btn-default ajax-modal" href="/murano/packages/import_bundle?name={$ asset.service.murano_package_name | encodeURIComponent $}&import_type=by_repo">Install</a>
|
||||
<a ng-switch-when="true" ng-class="extraclasses" class="btn btn-default disabled ajax-modal" href="/">Installed</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -40,18 +40,20 @@
|
|||
'$scope',
|
||||
'$http',
|
||||
'$timeout',
|
||||
'$modal',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'appCatalogModel',
|
||||
appComponentCatalogTableCtrl
|
||||
]).service('appCatalogModel', [
|
||||
'$http',
|
||||
'$injector',
|
||||
'horizon.app.core.openstack-service-api.heat',
|
||||
'horizon.app.core.openstack-service-api.glance',
|
||||
'horizon.app.core.openstack-service-api.serviceCatalog',
|
||||
appCatalogModel
|
||||
]).directive('stars', stars);
|
||||
|
||||
function appCatalogModel($http, heatAPI, glanceAPI, serviceCatalog) {
|
||||
function appCatalogModel($http, $injector, heatAPI, glanceAPI, serviceCatalog) {
|
||||
var $scope = this;
|
||||
var callbacks = {
|
||||
update: [],
|
||||
|
@ -97,6 +99,12 @@
|
|||
callback();
|
||||
});
|
||||
};
|
||||
var muranoAPI;
|
||||
$scope.has_murano = false;
|
||||
if ($injector.has('horizon.app.core.openstack-service-api.murano')) {
|
||||
muranoAPI = $injector.get('horizon.app.core.openstack-service-api.murano');
|
||||
$scope.has_murano = true;
|
||||
}
|
||||
//FIXME [{'name':'heat', 'type':'orchestration'}, {'name':'glance', 'type':'image'}]
|
||||
serviceCatalog.get().then(function(catalog){
|
||||
angular.forEach(catalog, function(entry){
|
||||
|
@ -156,11 +164,12 @@
|
|||
this.register_callback = function(type, callback) {
|
||||
callbacks[type].push(callback);
|
||||
};
|
||||
this.init = function(app_catalog_url) {
|
||||
this.init = function(app_catalog_settings) {
|
||||
var app_catalog_url = app_catalog_settings.APP_CATALOG_URL;
|
||||
var req = {
|
||||
url: app_catalog_url + '/api/v1/assets',
|
||||
headers: {'X-Requested-With': undefined}
|
||||
}
|
||||
};
|
||||
$http(req).success(function(data) {
|
||||
if('deprecated' in data) {
|
||||
notify_deprecated(data['deprecated']);
|
||||
|
@ -187,7 +196,10 @@
|
|||
}
|
||||
if (asset.service.type == 'heat') {
|
||||
process(asset);
|
||||
} else if (asset.service.type == 'murano') {
|
||||
asset.validated = true;
|
||||
}
|
||||
asset.has_murano = $scope.has_murano;
|
||||
}
|
||||
$scope.glance_loaded = true;
|
||||
$scope.murano_loaded = true;
|
||||
|
@ -195,6 +207,21 @@
|
|||
}).error(function() {
|
||||
notify_error('There was an error while retrieving entries from the Application Catalog.');
|
||||
});
|
||||
if($scope.has_murano) {
|
||||
muranoAPI.getPackages().success(function(data) {
|
||||
$scope.murano_packages = data;
|
||||
var murano_package_definitions = {};
|
||||
for (var p in data.packages){
|
||||
var definitions = data.packages[p]['class_definitions'];
|
||||
for (var d in definitions) {
|
||||
var definition = definitions[d];
|
||||
murano_package_definitions[definition] = {'id': data.packages[p]['id']};
|
||||
}
|
||||
}
|
||||
$scope.murano_package_definitions = murano_package_definitions;
|
||||
update_found_assets($scope);
|
||||
});
|
||||
}
|
||||
glanceAPI.getImages().success(function(data) {
|
||||
$scope.glance_images = data;
|
||||
var glance_names = {}
|
||||
|
@ -300,7 +327,7 @@
|
|||
};
|
||||
}
|
||||
|
||||
function appComponentCatalogTableCtrl($scope, $http, $timeout, toast, appCatalogModel) {
|
||||
function appComponentCatalogTableCtrl($scope, $http, $timeout, $modal, toast, appCatalogModel) {
|
||||
$scope.assets = appCatalogModel.assets_filtered
|
||||
var update = function(){
|
||||
$timeout(function() {
|
||||
|
@ -308,7 +335,7 @@
|
|||
}, 0, false);
|
||||
};
|
||||
appCatalogModel.register_callback('update', update);
|
||||
common_init($scope, toast, appCatalogModel);
|
||||
common_init($scope, $modal, toast, appCatalogModel);
|
||||
$scope.switcher = {pannel: 'component', active: 'list'};
|
||||
}
|
||||
|
||||
|
@ -326,6 +353,19 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
if('murano_loaded' in $scope && 'murano_package_definitions' in $scope){
|
||||
for (var i in $scope.assets){
|
||||
if($scope.assets[i].service.type != 'murano'){
|
||||
continue;
|
||||
}
|
||||
var definition = $scope.assets[i].service.package_name;
|
||||
var is_installed = definition in ($scope.murano_package_definitions);
|
||||
$scope.assets[i].installed = is_installed;
|
||||
if(is_installed) {
|
||||
$scope.assets[i].service.murano_id = $scope.murano_package_definitions[definition]['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
var asset_name_to_asset = {};
|
||||
angular.forEach($scope.assets, function(asset){
|
||||
asset_name_to_asset[asset.name] = asset;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
{% block main %}
|
||||
|
||||
<div ng-cloak
|
||||
ng-controller="appCatalogTableCtrl" ng-init="init('{{ APP_CATALOG_URL }}')">
|
||||
ng-controller="appCatalogTableCtrl" ng-init='init({{ APP_CATALOG_SETTINGS }})'>
|
||||
<ng-include src="'{{ STATIC_URL }}dashboard/project/app_catalog/main_panel.html'"></ng-include>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,11 +1,23 @@
|
|||
from horizon import Horizon
|
||||
from horizon import views
|
||||
from django.conf import settings
|
||||
|
||||
import json
|
||||
|
||||
class IndexView(views.APIView):
|
||||
# A very simple class-based view...
|
||||
template_name = 'app_catalog/index.html'
|
||||
|
||||
def get_data(self, request, context, *args, **kwargs):
|
||||
context['APP_CATALOG_URL'] = getattr(settings, 'APP_CATALOG_URL', 'http://apps.openstack.org')
|
||||
has_murano = False
|
||||
try:
|
||||
Horizon.get_dashboard('murano')
|
||||
has_murano = True
|
||||
except:
|
||||
pass
|
||||
app_catalog_settings = {
|
||||
'HAS_MURANO': has_murano,
|
||||
'APP_CATALOG_URL': getattr(settings, 'APP_CATALOG_URL', 'http://apps.openstack.org')
|
||||
}
|
||||
context['APP_CATALOG_SETTINGS'] = json.dumps(app_catalog_settings)
|
||||
return context
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
{% block main %}
|
||||
|
||||
<div ng-cloak
|
||||
ng-controller="appComponentCatalogTableCtrl" ng-init="init('{{ APP_CATALOG_URL }}')">
|
||||
ng-controller="appComponentCatalogTableCtrl" ng-init="init({{ APP_CATALOG_SETTINGS }})">
|
||||
<ng-include src="'{{ STATIC_URL }}dashboard/project/app_catalog/main_panel.html'"></ng-include>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,12 +1,24 @@
|
|||
from horizon import Horizon
|
||||
from horizon import views
|
||||
from django.conf import settings
|
||||
|
||||
import json
|
||||
|
||||
class IndexView(views.APIView):
|
||||
# A very simple class-based view...
|
||||
template_name = 'component_catalog/index.html'
|
||||
|
||||
def get_data(self, request, context, *args, **kwargs):
|
||||
context['APP_CATALOG_URL'] = getattr(settings, 'APP_CATALOG_URL', 'http://apps.openstack.org')
|
||||
has_murano = False
|
||||
try:
|
||||
Horizon.get_dashboard('murano')
|
||||
has_murano = True
|
||||
except:
|
||||
pass
|
||||
app_catalog_settings = {
|
||||
'HAS_MURANO': has_murano,
|
||||
'APP_CATALOG_URL': getattr(settings, 'APP_CATALOG_URL', 'http://apps.openstack.org')
|
||||
}
|
||||
context['APP_CATALOG_SETTINGS'] = json.dumps(app_catalog_settings)
|
||||
return context
|
||||
|
||||
|
|
Loading…
Reference in New Issue