mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-14 17:01:02 +02:00
Integrating YANG live compilation into YANG runtime.
- Bumped ONOS dependency on ONOS YANG tools 2.2.0-b4. - Added CLI to compile YANG models. - Added GUI capability to compile YANG models via drag-n-drop or file upload. - Fixed defect in propagating self-contained JAR apps through the cluster. Change-Id: Icbd2a588bf1ffe0282e12d3d10a117e0957c3084
This commit is contained in:
parent
46654c3307
commit
ad37e3733e
@ -161,7 +161,7 @@ public class YangModelMessageHandler extends UiMessageHandler {
|
|||||||
// FIXME: Hack to properly resolve the YANG source resource
|
// FIXME: Hack to properly resolve the YANG source resource
|
||||||
private InputStream getSource(String modelId, YangModule module) {
|
private InputStream getSource(String modelId, YangModule module) {
|
||||||
try {
|
try {
|
||||||
module.getYangSource(); // trigger exception
|
return module.getYangSource(); // trigger exception
|
||||||
} catch (ModelException e) {
|
} catch (ModelException e) {
|
||||||
// Strip the YANG source file base-name and then use it to access
|
// Strip the YANG source file base-name and then use it to access
|
||||||
// the corresponding resource in the correct run-time context.
|
// the corresponding resource in the correct run-time context.
|
||||||
@ -172,7 +172,6 @@ public class YangModelMessageHandler extends UiMessageHandler {
|
|||||||
return loader == null ? null :
|
return loader == null ? null :
|
||||||
loader.getResourceAsStream("/yang/resources" + baseName);
|
loader.getResourceAsStream("/yang/resources" + baseName);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSource(ArrayNode source, InputStream yangSource) {
|
private void addSource(ArrayNode source, InputStream yangSource) {
|
||||||
|
@ -14,6 +14,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* -- Drag-n-Drop YANG/ZIP files -- */
|
||||||
|
div.dropping {
|
||||||
|
border: solid 3px #0095d6;
|
||||||
|
}
|
||||||
|
|
||||||
.light #yang-model-details-panel .src-frame {
|
.light #yang-model-details-panel .src-frame {
|
||||||
background-color: #f4f4f4;
|
background-color: #f4f4f4;
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,23 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ov-yang-model h2 {
|
#ov-yang-model h2 {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ov-yang-model div.ctrl-btns {
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- Drag-n-Drop file upload -- */
|
||||||
|
#ov-yang-model form#inputYangFileForm,
|
||||||
|
#ov-yang-model input#uploadYangFile {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropping {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#yang-model-details-panel.floatpanel {
|
#yang-model-details-panel.floatpanel {
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!-- YANG Model partial HTML -->
|
<!-- YANG Model partial HTML -->
|
||||||
<div id="ov-yang-model">
|
<div id="ov-yang-model" yangfiledrop on-file-drop="yangDropped()">
|
||||||
|
|
||||||
<div class="tabular-header">
|
<div class="tabular-header">
|
||||||
<h2>YANG Models ({{tableData.length}} total)</h2>
|
<h2>YANG Models ({{tableData.length}} total)</h2>
|
||||||
@ -8,6 +8,19 @@
|
|||||||
icon icon-id="refresh" icon-size="42"
|
icon icon-id="refresh" icon-size="42"
|
||||||
tooltip tt-msg="autoRefreshTip"
|
tooltip tt-msg="autoRefreshTip"
|
||||||
ng-click="toggleRefresh()"></div>
|
ng-click="toggleRefresh()"></div>
|
||||||
|
|
||||||
|
<div class="separator"></div>
|
||||||
|
|
||||||
|
<form id="inputYangFileForm">
|
||||||
|
<input id="uploadYangFile"
|
||||||
|
type="file" size="50" accept=".zip, *.jar, *.yang"
|
||||||
|
yang-file-model="yangFile">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div icon icon-size="42" icon-id="nav_yang"
|
||||||
|
class="active" trigger-yang-form
|
||||||
|
tooltip tt-msg="uploadTip">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -44,7 +44,8 @@
|
|||||||
// constants
|
// constants
|
||||||
var pName = 'yang-model-details-panel',
|
var pName = 'yang-model-details-panel',
|
||||||
detailsReq = 'yangModelDetailsRequest',
|
detailsReq = 'yangModelDetailsRequest',
|
||||||
detailsResp = 'yangModelDetailsResponse';
|
detailsResp = 'yangModelDetailsResponse',
|
||||||
|
fileUploadUrl = '/onos/yang/models?modelId=';
|
||||||
|
|
||||||
|
|
||||||
function createDetailsPanel() {
|
function createDetailsPanel() {
|
||||||
@ -135,11 +136,12 @@
|
|||||||
// defines view controller
|
// defines view controller
|
||||||
angular.module('ovYangModel', [])
|
angular.module('ovYangModel', [])
|
||||||
.controller('OvYangModelCtrl', [
|
.controller('OvYangModelCtrl', [
|
||||||
'$log', '$scope', 'TableBuilderService', 'TableDetailService',
|
'$log', '$scope', '$http', '$timeout',
|
||||||
|
'TableBuilderService', 'TableDetailService',
|
||||||
'FnService', 'MastService', 'PanelService', 'WebSocketService',
|
'FnService', 'MastService', 'PanelService', 'WebSocketService',
|
||||||
'IconService',
|
'IconService', 'UrlFnService', 'FlashService',
|
||||||
|
|
||||||
function (_$log_, _$scope_, tbs, tds, _fs_, _mast_, _ps_, _wss_, _is_) {
|
function (_$log_, _$scope_, $http, $timeout, tbs, tds, _fs_, _mast_, _ps_, _wss_, _is_, ufs, _flash_) {
|
||||||
var handlers = {};
|
var handlers = {};
|
||||||
|
|
||||||
$log = _$log_;
|
$log = _$log_;
|
||||||
@ -176,6 +178,45 @@
|
|||||||
selCb: selCb
|
selCb: selCb
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$scope.$on('YangFileChanged', function () {
|
||||||
|
var formData = new FormData(),
|
||||||
|
url, modelId, finished = false;
|
||||||
|
|
||||||
|
if ($scope.yangFile) {
|
||||||
|
modelId = $scope.yangFile.name;
|
||||||
|
modelId = modelId.substr(0, modelId.lastIndexOf("."));
|
||||||
|
url = fileUploadUrl + modelId;
|
||||||
|
formData.append('file', $scope.yangFile);
|
||||||
|
$log.info('Compiling', $scope.yangFile);
|
||||||
|
d3.select('#frame').classed('dropping', false);
|
||||||
|
|
||||||
|
// FIXME: Replace this with dialog that shows progress...
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
$timeout(function () {
|
||||||
|
if (!finished) _flash_.flash('Compiling ' + modelId);
|
||||||
|
}, i * 1100);
|
||||||
|
}
|
||||||
|
|
||||||
|
$http.post(url, formData, {
|
||||||
|
transformRequest: angular.identity,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(function () {
|
||||||
|
finished = true;
|
||||||
|
_flash_.flash('Compile completed for ' + modelId);
|
||||||
|
$scope.sortCallback($scope.sortParams);
|
||||||
|
document.getElementById('inputYangFileForm').reset();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.yangDropped = function() {
|
||||||
|
$scope.$emit('YangFileChanged');
|
||||||
|
$scope.yangFile = null;
|
||||||
|
};
|
||||||
|
|
||||||
$scope.$on('$destroy', function () {
|
$scope.$on('$destroy', function () {
|
||||||
wss.unbindHandlers(handlers);
|
wss.unbindHandlers(handlers);
|
||||||
});
|
});
|
||||||
@ -184,6 +225,78 @@
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// triggers the input form to appear when button is clicked
|
||||||
|
.directive('triggerYangForm', function () {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: function (scope, elem) {
|
||||||
|
elem.bind('click', function () {
|
||||||
|
document.getElementById('uploadYangFile')
|
||||||
|
.dispatchEvent(new MouseEvent('click'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
|
// binds the model file to the scope in scope.yangFile
|
||||||
|
// sends upload request to the server
|
||||||
|
.directive('yangFileModel', ['$parse',
|
||||||
|
function ($parse) {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: function (scope, elem, attrs) {
|
||||||
|
var model = $parse(attrs.yangFileModel),
|
||||||
|
modelSetter = model.assign;
|
||||||
|
|
||||||
|
elem.bind('change', function () {
|
||||||
|
scope.$apply(function () {
|
||||||
|
modelSetter(scope, elem[0].files[0]);
|
||||||
|
});
|
||||||
|
scope.$emit('YangFileChanged');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
.directive("yangfiledrop", ['$parse', '$document', function ($parse, $document) {
|
||||||
|
return {
|
||||||
|
restrict: "A",
|
||||||
|
link: function (scope, element, attrs) {
|
||||||
|
var onYangDrop = $parse(attrs.onFileDrop);
|
||||||
|
|
||||||
|
// When an item is dragged over the document
|
||||||
|
var onDragOver = function (e) {
|
||||||
|
d3.select('#frame').classed('dropping', true);
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
|
// When the user leaves the window, cancels the drag or drops the item
|
||||||
|
var onDragEnd = function (e) {
|
||||||
|
d3.select('#frame').classed('dropping', false);
|
||||||
|
e.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
|
// When a file is dropped
|
||||||
|
var loadFile = function (file) {
|
||||||
|
scope.yangFile = file;
|
||||||
|
scope.$apply(onYangDrop(scope));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Dragging begins on the document
|
||||||
|
$document.bind("dragover", onDragOver);
|
||||||
|
|
||||||
|
// Dragging ends on the overlay, which takes the whole window
|
||||||
|
element.bind("dragleave", onDragEnd)
|
||||||
|
.bind("drop", function (e) {
|
||||||
|
$log.info('Drag leave', e);
|
||||||
|
loadFile(e.dataTransfer.files[0]);
|
||||||
|
onDragEnd(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}])
|
||||||
|
|
||||||
.directive('yangModelDetailsPanel', [
|
.directive('yangModelDetailsPanel', [
|
||||||
'$rootScope', '$window', '$timeout', 'KeyService',
|
'$rootScope', '$window', '$timeout', 'KeyService',
|
||||||
|
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2017-present Open Networking Foundation
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.onosproject.yang;
|
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
|
||||||
import org.apache.felix.scr.annotations.Activate;
|
|
||||||
import org.apache.felix.scr.annotations.Component;
|
|
||||||
import org.apache.felix.scr.annotations.Deactivate;
|
|
||||||
import org.apache.felix.scr.annotations.Reference;
|
|
||||||
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
|
||||||
import org.apache.felix.scr.annotations.Service;
|
|
||||||
import org.onosproject.core.CoreService;
|
|
||||||
import org.onosproject.yang.compiler.api.YangCompilationParam;
|
|
||||||
import org.onosproject.yang.compiler.api.YangCompiledOutput;
|
|
||||||
import org.onosproject.yang.compiler.api.YangCompilerException;
|
|
||||||
import org.onosproject.yang.compiler.api.YangCompilerService;
|
|
||||||
import org.onosproject.yang.compiler.tool.YangCompilerManager;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents implementation of YANG live compiler manager.
|
|
||||||
*/
|
|
||||||
@Beta
|
|
||||||
@Service
|
|
||||||
@Component(immediate = true)
|
|
||||||
public class YangLiveCompilerManager implements YangCompilerService {
|
|
||||||
|
|
||||||
private static final String APP_ID = "org.onosproject.yang";
|
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
|
||||||
protected CoreService coreService;
|
|
||||||
|
|
||||||
@Activate
|
|
||||||
public void activate() {
|
|
||||||
coreService.registerApplication(APP_ID);
|
|
||||||
log.info("Started");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deactivate
|
|
||||||
public void deactivate() {
|
|
||||||
log.info("Stopped");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public YangCompiledOutput compileYangFiles(YangCompilationParam param)
|
|
||||||
throws IOException, YangCompilerException {
|
|
||||||
return new YangCompilerManager().compileYangFiles(param);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017-present Open Networking Foundation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.onosproject.yang;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime service for compiling YANG source files and packaging the compiled
|
||||||
|
* artifacts into a ready-to-load application.
|
||||||
|
*/
|
||||||
|
@Beta
|
||||||
|
public interface YangLiveCompilerService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the YANG source file(s) contained in the specified input
|
||||||
|
* stream either as individual YANG source file, or as a JAR/ZIP collection
|
||||||
|
* of YANG source files.
|
||||||
|
*
|
||||||
|
* @param modelId model identifier
|
||||||
|
* @param yangSources input stream containing a single YANG source file
|
||||||
|
* or a JAR/ZIP archive containing collection of YANG
|
||||||
|
* source files
|
||||||
|
* @return input stream containing a packaged ONOS application JAR file
|
||||||
|
* @throws IOException if issues arise when reading the yang sources stream
|
||||||
|
*/
|
||||||
|
InputStream compileYangFiles(String modelId, InputStream yangSources) throws IOException;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017-present Open Networking Foundation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package org.onosproject.yang.impl;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
import org.apache.karaf.shell.commands.Argument;
|
||||||
|
import org.apache.karaf.shell.commands.Command;
|
||||||
|
import org.apache.karaf.shell.commands.Option;
|
||||||
|
import org.onosproject.app.ApplicationAdminService;
|
||||||
|
import org.onosproject.cli.AbstractShellCommand;
|
||||||
|
import org.onosproject.core.ApplicationId;
|
||||||
|
import org.onosproject.yang.YangLiveCompilerService;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the provided YANG source files and installs the resulting model extension.
|
||||||
|
*/
|
||||||
|
@Command(scope = "onos", name = "compile-model",
|
||||||
|
description = "Compiles the provided YANG source files and installs the resulting model extension")
|
||||||
|
public class YangCompileCommand extends AbstractShellCommand {
|
||||||
|
|
||||||
|
@Option(name = "-c", aliases = "--compile-only",
|
||||||
|
description = "Only compile, but do not install the model")
|
||||||
|
private boolean compileOnly = false;
|
||||||
|
|
||||||
|
@Option(name = "-f", aliases = "--force",
|
||||||
|
description = "Force reinstall if already installed")
|
||||||
|
private boolean forceReinstall = false;
|
||||||
|
|
||||||
|
@Argument(index = 0, name = "modelId",
|
||||||
|
description = "Model ID", required = true)
|
||||||
|
String modelId = null;
|
||||||
|
|
||||||
|
@Argument(index = 1, name = "url",
|
||||||
|
description = "URL to the YANG source file(s); .yang, .zip or .jar file",
|
||||||
|
required = true)
|
||||||
|
String url = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void execute() {
|
||||||
|
try {
|
||||||
|
InputStream yangJar = new URL(url).openStream();
|
||||||
|
YangLiveCompilerService compiler = get(YangLiveCompilerService.class);
|
||||||
|
if (compileOnly) {
|
||||||
|
ByteStreams.copy(compiler.compileYangFiles(modelId, yangJar), System.out);
|
||||||
|
} else {
|
||||||
|
ApplicationAdminService appService = get(ApplicationAdminService.class);
|
||||||
|
|
||||||
|
if (forceReinstall) {
|
||||||
|
ApplicationId appId = appService.getId(modelId);
|
||||||
|
if (appId != null && appService.getApplication(appId) != null) {
|
||||||
|
appService.uninstall(appId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appService.install(compiler.compileYangFiles(modelId, yangJar));
|
||||||
|
appService.activate(appService.getId(modelId));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,232 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017-present Open Networking Foundation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.onosproject.yang.impl;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import org.apache.felix.scr.annotations.Activate;
|
||||||
|
import org.apache.felix.scr.annotations.Component;
|
||||||
|
import org.apache.felix.scr.annotations.Deactivate;
|
||||||
|
import org.apache.felix.scr.annotations.Service;
|
||||||
|
import org.onosproject.yang.YangLiveCompilerService;
|
||||||
|
import org.onosproject.yang.compiler.tool.DefaultYangCompilationParam;
|
||||||
|
import org.onosproject.yang.compiler.tool.YangCompilerManager;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.FileVisitResult;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.SimpleFileVisitor;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
import static com.google.common.io.ByteStreams.toByteArray;
|
||||||
|
import static com.google.common.io.Files.createParentDirs;
|
||||||
|
import static com.google.common.io.Files.write;
|
||||||
|
import static java.nio.file.Files.walkFileTree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents implementation of YANG live compiler manager.
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Component(immediate = true)
|
||||||
|
public class YangLiveCompilerManager implements YangLiveCompilerService {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
private static final String ZIP_MAGIC = "PK";
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public void activate() {
|
||||||
|
log.info("Started");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deactivate
|
||||||
|
public void deactivate() {
|
||||||
|
log.info("Stopped");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream compileYangFiles(String modelId,
|
||||||
|
InputStream yangSources) throws IOException {
|
||||||
|
// Generate temporary directory where the work will happen.
|
||||||
|
File root = Files.createTempDir();
|
||||||
|
log.info("Compiling YANG model to {}", root);
|
||||||
|
|
||||||
|
// Unpack the input stream
|
||||||
|
File yangRoot = unpackYangSources(root, yangSources);
|
||||||
|
|
||||||
|
// Run the YANG compilation phase
|
||||||
|
File javaRoot = runYangCompiler(root, yangRoot, modelId);
|
||||||
|
|
||||||
|
// Run the Java compilation phase
|
||||||
|
File classRoot = runJavaCompiler(root, javaRoot, modelId);
|
||||||
|
|
||||||
|
// Run the JAR assembly phase
|
||||||
|
File jarFile = runJarAssembly(root, classRoot, modelId);
|
||||||
|
|
||||||
|
// Return the final JAR file as input stream
|
||||||
|
return new FileInputStream(jarFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unpacks the given input stream into the YANG root subdirectory of the specified root directory.
|
||||||
|
private File unpackYangSources(File root, InputStream yangSources) throws IOException {
|
||||||
|
File yangRoot = new File(root, "yang/");
|
||||||
|
if (yangRoot.mkdirs()) {
|
||||||
|
// Unpack the yang sources into the newly created directory
|
||||||
|
byte[] cache = toByteArray(yangSources);
|
||||||
|
InputStream bis = new ByteArrayInputStream(cache);
|
||||||
|
if (isZipArchive(cache)) {
|
||||||
|
extractZipArchive(yangRoot, bis);
|
||||||
|
} else {
|
||||||
|
extractYangFile(yangRoot, bis);
|
||||||
|
}
|
||||||
|
return yangRoot;
|
||||||
|
}
|
||||||
|
throw new IOException("Unable to create yang source root");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extracts the YANG source stream into the specified directory.
|
||||||
|
private void extractYangFile(File dir, InputStream stream) throws IOException {
|
||||||
|
ByteStreams.copy(stream, new FileOutputStream(new File(dir, "model.yang")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extracts the ZIP stream into the specified directory.
|
||||||
|
private void extractZipArchive(File dir, InputStream stream) throws IOException {
|
||||||
|
ZipInputStream zis = new ZipInputStream(stream);
|
||||||
|
ZipEntry entry;
|
||||||
|
while ((entry = zis.getNextEntry()) != null) {
|
||||||
|
if (!entry.isDirectory()) {
|
||||||
|
byte[] data = toByteArray(zis);
|
||||||
|
zis.closeEntry();
|
||||||
|
File file = new File(dir, entry.getName());
|
||||||
|
createParentDirs(file);
|
||||||
|
write(data, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zis.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runs the YANG compiler on the YANG sources in the specified directory.
|
||||||
|
private File runYangCompiler(File root, File yangRoot, String modelId) throws IOException {
|
||||||
|
File javaRoot = new File(root, "java/");
|
||||||
|
if (javaRoot.mkdirs()) {
|
||||||
|
// Prepare the compilation parameter
|
||||||
|
DefaultYangCompilationParam.Builder param = DefaultYangCompilationParam.builder()
|
||||||
|
.setCodeGenDir(new File(javaRoot, "src").toPath())
|
||||||
|
.setMetadataGenDir(new File(javaRoot, "schema").toPath())
|
||||||
|
.setModelId(modelId);
|
||||||
|
|
||||||
|
// TODO: How to convey YANG dependencies? "/dependencies" directory?
|
||||||
|
|
||||||
|
// Iterate over all files and add all YANG sources.
|
||||||
|
walkFileTree(Paths.get(yangRoot.getAbsolutePath()),
|
||||||
|
new SimpleFileVisitor<Path>() {
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attributes)
|
||||||
|
throws IOException {
|
||||||
|
if (attributes.isRegularFile() && file.toString().endsWith(".yang")) {
|
||||||
|
param.addYangFile(file);
|
||||||
|
}
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Run the YANG compiler and collect the results
|
||||||
|
new YangCompilerManager().compileYangFiles(param.build());
|
||||||
|
return javaRoot;
|
||||||
|
}
|
||||||
|
throw new IOException("Unable to create Java results root");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runs the Java compilation on the Java sources generated by YANG compiler.
|
||||||
|
private File runJavaCompiler(File root, File javaRoot, String modelId) throws IOException {
|
||||||
|
File classRoot = new File(root, "classes/");
|
||||||
|
if (classRoot.mkdirs()) {
|
||||||
|
File compilerScript = writeResource("onos-yang-javac", root);
|
||||||
|
writeResource("YangModelRegistrator.java", root);
|
||||||
|
execute(new String[]{
|
||||||
|
"bash",
|
||||||
|
compilerScript.getAbsolutePath(),
|
||||||
|
javaRoot.getAbsolutePath(),
|
||||||
|
classRoot.getAbsolutePath(),
|
||||||
|
modelId
|
||||||
|
});
|
||||||
|
return classRoot;
|
||||||
|
}
|
||||||
|
throw new IOException("Unable to create class results root");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the JAR assembly on the classes root and include any YANG sources as well.
|
||||||
|
private File runJarAssembly(File root, File classRoot, String modelId) throws IOException {
|
||||||
|
File jarFile = new File(root, "model.jar");
|
||||||
|
File jarScript = writeResource("onos-yang-jar", root);
|
||||||
|
writeResource("app.xml", root);
|
||||||
|
writeResource("features.xml", root);
|
||||||
|
writeResource("YangModelRegistrator.xml", root);
|
||||||
|
execute(new String[]{
|
||||||
|
"bash",
|
||||||
|
jarScript.getAbsolutePath(),
|
||||||
|
classRoot.getAbsolutePath(),
|
||||||
|
jarFile.getAbsolutePath(),
|
||||||
|
modelId
|
||||||
|
});
|
||||||
|
return jarFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes the specified resource as a file in the given directory.
|
||||||
|
private File writeResource(String resourceName, File dir) throws IOException {
|
||||||
|
File script = new File(dir, resourceName);
|
||||||
|
write(toByteArray(getClass().getResourceAsStream("/" + resourceName)), script);
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicates whether the stream encoded in the given bytes is a ZIP archive.
|
||||||
|
private boolean isZipArchive(byte[] bytes) {
|
||||||
|
return substring(bytes, ZIP_MAGIC.length()).equals(ZIP_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the substring of maximum possible length from the specified bytes.
|
||||||
|
private String substring(byte[] bytes, int length) {
|
||||||
|
return new String(bytes, 0, Math.min(bytes.length, length), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes the given command arguments as a system command.
|
||||||
|
private void execute(String[] command) throws IOException {
|
||||||
|
try {
|
||||||
|
Process process = Runtime.getRuntime().exec(command);
|
||||||
|
byte[] output = toByteArray(process.getInputStream());
|
||||||
|
byte[] error = toByteArray(process.getErrorStream());
|
||||||
|
int code = process.waitFor();
|
||||||
|
if (code != 0) {
|
||||||
|
log.info("Command failed: status={}, output={}, error={}",
|
||||||
|
code, new String(output), new String(error));
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("Interrupted executing command {}", command, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.onosproject.yang;
|
package org.onosproject.yang.impl;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
@ -29,11 +29,11 @@ import org.onosproject.yang.runtime.YangModelRegistry;
|
|||||||
* Lists registered YANG models.
|
* Lists registered YANG models.
|
||||||
*/
|
*/
|
||||||
@Command(scope = "onos", name = "models",
|
@Command(scope = "onos", name = "models",
|
||||||
description = "Lists registered YANG models")
|
description = "Lists registered YANG models")
|
||||||
public class YangModelsListCommand extends AbstractShellCommand {
|
public class YangModelsListCommand extends AbstractShellCommand {
|
||||||
|
|
||||||
|
|
||||||
private static final String FORMAT = "moduleName=%s moduleRevision=%s modelId=%s";
|
private static final String FORMAT = "modelId=%s moduleName=%s moduleRevision=%s";
|
||||||
private static final String MODULE_NAME = "moduleName";
|
private static final String MODULE_NAME = "moduleName";
|
||||||
private static final String MODULE_REVISION = "moduleRevision";
|
private static final String MODULE_REVISION = "moduleRevision";
|
||||||
|
|
||||||
@ -44,11 +44,11 @@ public class YangModelsListCommand extends AbstractShellCommand {
|
|||||||
if (outputJson()) {
|
if (outputJson()) {
|
||||||
print("%s", json(service));
|
print("%s", json(service));
|
||||||
} else {
|
} else {
|
||||||
for (YangModel model: service.getModels()) {
|
for (YangModel model : service.getModels()) {
|
||||||
for (YangModule module : model.getYangModules()) {
|
for (YangModule module : model.getYangModules()) {
|
||||||
print(FORMAT, module.getYangModuleId().moduleName(),
|
print(FORMAT, model.getYangModelId(),
|
||||||
module.getYangModuleId().revision(),
|
module.getYangModuleId().moduleName(),
|
||||||
modelId(model));
|
module.getYangModuleId().revision());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,9 +58,9 @@ public class YangModelsListCommand extends AbstractShellCommand {
|
|||||||
private JsonNode json(YangModelRegistry service) {
|
private JsonNode json(YangModelRegistry service) {
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
ObjectNode result = mapper.createObjectNode();
|
ObjectNode result = mapper.createObjectNode();
|
||||||
for (YangModel model: service.getModels()) {
|
for (YangModel model : service.getModels()) {
|
||||||
ArrayNode modelNode = mapper.createArrayNode();
|
ArrayNode modelNode = mapper.createArrayNode();
|
||||||
result.set(modelId(model), modelNode);
|
result.set(model.getYangModelId(), modelNode);
|
||||||
for (YangModule module : model.getYangModules()) {
|
for (YangModule module : model.getYangModules()) {
|
||||||
ObjectNode moduleNode = mapper.createObjectNode();
|
ObjectNode moduleNode = mapper.createObjectNode();
|
||||||
modelNode.add(moduleNode);
|
modelNode.add(moduleNode);
|
||||||
@ -71,7 +71,4 @@ public class YangModelsListCommand extends AbstractShellCommand {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String modelId(YangModel m) {
|
|
||||||
return "YM" + Math.abs(m.hashCode());
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -14,9 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.onosproject.yang;
|
package org.onosproject.yang.impl;
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
|
||||||
import org.apache.felix.scr.annotations.Activate;
|
import org.apache.felix.scr.annotations.Activate;
|
||||||
import org.apache.felix.scr.annotations.Component;
|
import org.apache.felix.scr.annotations.Component;
|
||||||
import org.apache.felix.scr.annotations.Deactivate;
|
import org.apache.felix.scr.annotations.Deactivate;
|
||||||
@ -24,6 +23,7 @@ import org.apache.felix.scr.annotations.Reference;
|
|||||||
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
import org.apache.felix.scr.annotations.ReferenceCardinality;
|
||||||
import org.apache.felix.scr.annotations.Service;
|
import org.apache.felix.scr.annotations.Service;
|
||||||
import org.onosproject.core.CoreService;
|
import org.onosproject.core.CoreService;
|
||||||
|
import org.onosproject.yang.YangClassLoaderRegistry;
|
||||||
import org.onosproject.yang.model.ModelConverter;
|
import org.onosproject.yang.model.ModelConverter;
|
||||||
import org.onosproject.yang.model.ModelObjectData;
|
import org.onosproject.yang.model.ModelObjectData;
|
||||||
import org.onosproject.yang.model.NodeKey;
|
import org.onosproject.yang.model.NodeKey;
|
||||||
@ -62,7 +62,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
/**
|
/**
|
||||||
* Represents implementation of YANG runtime manager.
|
* Represents implementation of YANG runtime manager.
|
||||||
*/
|
*/
|
||||||
@Beta
|
|
||||||
@Service
|
@Service
|
||||||
@Component(immediate = true)
|
@Component(immediate = true)
|
||||||
public class YangRuntimeManager implements YangModelRegistry,
|
public class YangRuntimeManager implements YangModelRegistry,
|
20
apps/yang/src/main/java/org/onosproject/yang/impl/package-info.java
Executable file
20
apps/yang/src/main/java/org/onosproject/yang/impl/package-info.java
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017-present Open Networking Foundation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementations of various YANG runtime services.
|
||||||
|
*/
|
||||||
|
package org.onosproject.yang.impl;
|
@ -16,7 +16,10 @@
|
|||||||
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
|
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
|
||||||
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
|
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
|
||||||
<command>
|
<command>
|
||||||
<action class="org.onosproject.yang.YangModelsListCommand"/>
|
<action class="org.onosproject.yang.impl.YangModelsListCommand"/>
|
||||||
|
</command>
|
||||||
|
<command>
|
||||||
|
<action class="org.onosproject.yang.impl.YangCompileCommand"/>
|
||||||
</command>
|
</command>
|
||||||
</command-bundle>
|
</command-bundle>
|
||||||
</blueprint>
|
</blueprint>
|
||||||
|
10
apps/yang/src/main/resources/YangModelRegistrator.java
Normal file
10
apps/yang/src/main/resources/YangModelRegistrator.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Auto-generated code
|
||||||
|
package PACKAGE;
|
||||||
|
|
||||||
|
import org.onosproject.yang.AbstractYangModelRegistrator;
|
||||||
|
|
||||||
|
public class YangModelRegistrator extends AbstractYangModelRegistrator {
|
||||||
|
public YangModelRegistrator() {
|
||||||
|
super(YangModelRegistrator.class);
|
||||||
|
}
|
||||||
|
}
|
7
apps/yang/src/main/resources/YangModelRegistrator.xml
Normal file
7
apps/yang/src/main/resources/YangModelRegistrator.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="PACKAGE.YangModelRegistrator" activate="activate" deactivate="deactivate">
|
||||||
|
<implementation class="PACKAGE.YangModelRegistrator"/>
|
||||||
|
<property name="service.pid" value="PACKAGE.YangModelRegistrator"/>
|
||||||
|
<reference name="modelRegistry" interface="org.onosproject.yang.runtime.YangModelRegistry" cardinality="1..1" policy="static" bind="bindModelRegistry" unbind="unbindModelRegistry"/>
|
||||||
|
<reference name="sourceResolver" interface="org.onosproject.yang.YangClassLoaderRegistry" cardinality="1..1" policy="static" bind="bindSourceResolver" unbind="unbindSourceResolver"/>
|
||||||
|
</scr:component>
|
8
apps/yang/src/main/resources/app.xml
Normal file
8
apps/yang/src/main/resources/app.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<app name="MODEL_ID" origin="ONOS Community" version="1.0"
|
||||||
|
title="YANG Model: MODEL_ID" category="Model" url="http://onosproject.org"
|
||||||
|
featuresRepo="mvn:org.onosproject/MODEL_ID/1.0/xml/features"
|
||||||
|
features="MODEL_ID" apps="org.onosproject.yang">
|
||||||
|
<description>YANG Model: MODEL_ID</description>
|
||||||
|
<artifact>mvn:org.onosproject/MODEL_ID/1.0</artifact>
|
||||||
|
</app>
|
9
apps/yang/src/main/resources/features.xml
Normal file
9
apps/yang/src/main/resources/features.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
|
||||||
|
name="MODEL_ID-1.0">
|
||||||
|
<feature name="MODEL_ID" version="1.0"
|
||||||
|
description="YANG Model: MODEL_ID">
|
||||||
|
<feature>onos-api</feature>
|
||||||
|
<bundle>wrap:mvn:org.onosproject/MODEL_ID/1.0$Bundle-SymbolicName=MODEL_ID&Bundle-Version=1.0&Service-Component=OSGI-INF/MODEL_ID.YangModelRegistrator.xml</bundle>
|
||||||
|
</feature>
|
||||||
|
</features>
|
24
apps/yang/src/main/resources/onos-yang-jar
Normal file
24
apps/yang/src/main/resources/onos-yang-jar
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Assembles ONOS application jar from the compiled YANG model artifacts.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
classes=${1:-classes}
|
||||||
|
jar=${2:-model.jar}
|
||||||
|
modelId=${3-org.onosproject.model.unknown}
|
||||||
|
|
||||||
|
# Generate the app.xml descriptor file and stage it at the top of the jar
|
||||||
|
sed "s/MODEL_ID/$modelId/g" $(dirname $0)/app.xml > $classes/app.xml
|
||||||
|
|
||||||
|
# Generate features.xml file and stage it at the top of the jar
|
||||||
|
sed "s/MODEL_ID/$modelId/g" $(dirname $0)/features.xml > $classes/features.xml
|
||||||
|
mkdir -p $classes/m2/org/onosproject/$modelId/1.0/
|
||||||
|
cp $classes/features.xml $classes/m2/org/onosproject/$modelId/1.0/$modelId-1.0-features.xml
|
||||||
|
|
||||||
|
# Generate model self-registrator SCR descriptor
|
||||||
|
mkdir -p $classes/OSGI-INF
|
||||||
|
sed "s/PACKAGE/$modelId/g" $(dirname $0)/YangModelRegistrator.xml \
|
||||||
|
> $classes/OSGI-INF/$modelId.YangModelRegistrator.xml
|
||||||
|
|
||||||
|
cd $classes
|
||||||
|
jar cf $jar *
|
35
apps/yang/src/main/resources/onos-yang-javac
Executable file
35
apps/yang/src/main/resources/onos-yang-javac
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Compiles Java code generated by the YANG compiler.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
sources=${1:-src}
|
||||||
|
classes=${2:-classes}
|
||||||
|
modelId=${3:-org.onosproject.model.unknown}
|
||||||
|
|
||||||
|
# Stage the YANG sources and the YANG schema meta-data
|
||||||
|
mkdir -p $classes/yang/resources
|
||||||
|
cp $sources/schema/* $classes/yang/resources
|
||||||
|
|
||||||
|
root=${root:-system}
|
||||||
|
op="$root/org/onosproject"
|
||||||
|
|
||||||
|
function findLib() {
|
||||||
|
find $1/$2 -name "$2-*.jar"
|
||||||
|
}
|
||||||
|
|
||||||
|
classPath="$(findLib $op onos-yang-model)"
|
||||||
|
classPath="$classPath:$(findLib $op onos-yang-runtime)"
|
||||||
|
classPath="$classPath:$(findLib $op onos-yang-compiler-api)"
|
||||||
|
classPath="$classPath:$(findLib $op onos-apps-yang)"
|
||||||
|
|
||||||
|
package=${modelId//./\/}
|
||||||
|
mkdir -p $sources/src/$package
|
||||||
|
sed "s/PACKAGE/$modelId/g" $(dirname $0)/YangModelRegistrator.java \
|
||||||
|
> $sources/src/$package/YangModelRegistrator.java
|
||||||
|
|
||||||
|
# Compile the generated java code
|
||||||
|
find $sources/src -name '*.java' > $sources/javaFiles
|
||||||
|
javac -source 1.8 -target 1.8 \
|
||||||
|
-sourcepath "$sources/src" -classpath "$classPath" -d "$classes" \
|
||||||
|
@$sources/javaFiles
|
@ -6,6 +6,7 @@ COMPILE_DEPS = [
|
|||||||
'//lib:onos-yang-model',
|
'//lib:onos-yang-model',
|
||||||
'//lib:onos-yang-compiler-api',
|
'//lib:onos-yang-compiler-api',
|
||||||
'//lib:onos-yang-runtime',
|
'//lib:onos-yang-runtime',
|
||||||
|
'//apps/yang:onos-apps-yang'
|
||||||
]
|
]
|
||||||
|
|
||||||
TEST_DEPS = [
|
TEST_DEPS = [
|
||||||
|
@ -20,7 +20,10 @@ import org.apache.commons.io.IOUtils;
|
|||||||
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
|
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
|
||||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||||
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
|
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
|
||||||
|
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||||
|
import org.onosproject.app.ApplicationAdminService;
|
||||||
import org.onosproject.rest.AbstractWebResource;
|
import org.onosproject.rest.AbstractWebResource;
|
||||||
|
import org.onosproject.yang.YangLiveCompilerService;
|
||||||
import org.onosproject.yang.compiler.api.YangCompilationParam;
|
import org.onosproject.yang.compiler.api.YangCompilationParam;
|
||||||
import org.onosproject.yang.compiler.api.YangCompilerService;
|
import org.onosproject.yang.compiler.api.YangCompilerService;
|
||||||
import org.onosproject.yang.compiler.datamodel.YangNode;
|
import org.onosproject.yang.compiler.datamodel.YangNode;
|
||||||
@ -32,8 +35,10 @@ import org.onosproject.yang.runtime.ModelRegistrationParam;
|
|||||||
import org.onosproject.yang.runtime.YangModelRegistry;
|
import org.onosproject.yang.runtime.YangModelRegistry;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DefaultValue;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -71,6 +76,25 @@ public class YangWebResource extends AbstractWebResource {
|
|||||||
"or unregister.";
|
"or unregister.";
|
||||||
private static final String SLASH = "/";
|
private static final String SLASH = "/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles and registers the given yang files.
|
||||||
|
*
|
||||||
|
* @param modelId model identifier
|
||||||
|
* @param stream YANG, ZIP or JAR file
|
||||||
|
* @return 200 OK
|
||||||
|
* @throws IOException when fails to generate a file
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
public Response upload(@QueryParam("modelId") @DefaultValue("org.onosproject.model.unknown") String modelId,
|
||||||
|
@FormDataParam("file") InputStream stream) throws IOException {
|
||||||
|
YangLiveCompilerService compiler = get(YangLiveCompilerService.class);
|
||||||
|
ApplicationAdminService appService = get(ApplicationAdminService.class);
|
||||||
|
appService.install(compiler.compileYangFiles(modelId, stream));
|
||||||
|
appService.activate(appService.getId(modelId));
|
||||||
|
return Response.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles and registers the given yang files.
|
* Compiles and registers the given yang files.
|
||||||
*
|
*
|
||||||
@ -79,6 +103,7 @@ public class YangWebResource extends AbstractWebResource {
|
|||||||
* @throws IOException when fails to generate a file
|
* @throws IOException when fails to generate a file
|
||||||
*/
|
*/
|
||||||
@POST
|
@POST
|
||||||
|
@Path("deprecated")
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
public Response upload(FormDataMultiPart formData) throws IOException {
|
public Response upload(FormDataMultiPart formData) throws IOException {
|
||||||
Map<String, List<File>> input = parseInputData(formData);
|
Map<String, List<File>> input = parseInputData(formData);
|
||||||
@ -161,7 +186,7 @@ public class YangWebResource extends AbstractWebResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addToParam(DefaultYangCompilationParam.Builder builder,
|
private void addToParam(DefaultYangCompilationParam.Builder builder,
|
||||||
File file) {
|
File file) {
|
||||||
if (file.getName().endsWith(YANG_FILE_EXTENSION)) {
|
if (file.getName().endsWith(YANG_FILE_EXTENSION)) {
|
||||||
builder.addYangFile(Paths.get(file.getAbsolutePath()));
|
builder.addYangFile(Paths.get(file.getAbsolutePath()));
|
||||||
} else if (file.getName().endsWith(SER_FILE_EXTENSION)) {
|
} else if (file.getName().endsWith(SER_FILE_EXTENSION)) {
|
||||||
@ -198,8 +223,7 @@ public class YangWebResource extends AbstractWebResource {
|
|||||||
|
|
||||||
// first get all directories,
|
// first get all directories,
|
||||||
// then make those directory on the destination Path
|
// then make those directory on the destination Path
|
||||||
for (Enumeration<? extends ZipEntry> enums = zip.entries();
|
for (Enumeration<? extends ZipEntry> enums = zip.entries(); enums.hasMoreElements();) {
|
||||||
enums.hasMoreElements();) {
|
|
||||||
ZipEntry entry = enums.nextElement();
|
ZipEntry entry = enums.nextElement();
|
||||||
|
|
||||||
String fileName = YANG_RESOURCES + entry.getName();
|
String fileName = YANG_RESOURCES + entry.getName();
|
||||||
@ -211,8 +235,7 @@ public class YangWebResource extends AbstractWebResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//now create all files
|
//now create all files
|
||||||
for (Enumeration<? extends ZipEntry> enums = zip.entries();
|
for (Enumeration<? extends ZipEntry> enums = zip.entries(); enums.hasMoreElements();) {
|
||||||
enums.hasMoreElements();) {
|
|
||||||
ZipEntry entry = enums.nextElement();
|
ZipEntry entry = enums.nextElement();
|
||||||
String fileName = YANG_RESOURCES + entry.getName();
|
String fileName = YANG_RESOURCES + entry.getName();
|
||||||
File f = new File(fileName);
|
File f = new File(fileName);
|
||||||
|
@ -262,6 +262,9 @@ public class ApplicationArchive
|
|||||||
public synchronized InputStream getApplicationInputStream(String appName) {
|
public synchronized InputStream getApplicationInputStream(String appName) {
|
||||||
try {
|
try {
|
||||||
File appFile = appFile(appName, appName + OAR);
|
File appFile = appFile(appName, appName + OAR);
|
||||||
|
if (!appFile.exists()) {
|
||||||
|
appFile = appFile(appName, appName + JAR);
|
||||||
|
}
|
||||||
return new FileInputStream(appFile.exists() ? appFile : appFile(appName, APP_XML));
|
return new FileInputStream(appFile.exists() ? appFile : appFile(appName, APP_XML));
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
throw new ApplicationException("Application " + appName + " not found");
|
throw new ApplicationException("Application " + appName + " not found");
|
||||||
@ -383,7 +386,7 @@ public class ApplicationArchive
|
|||||||
|
|
||||||
// Create the file directory structure and copy the file there.
|
// Create the file directory structure and copy the file there.
|
||||||
File jar = appFile(desc.name(), jarName);
|
File jar = appFile(desc.name(), jarName);
|
||||||
boolean ok = jar.getParentFile().mkdirs();
|
boolean ok = jar.getParentFile().exists() || jar.getParentFile().mkdirs();
|
||||||
if (ok) {
|
if (ok) {
|
||||||
Files.write(toByteArray(stream), jar);
|
Files.write(toByteArray(stream), jar);
|
||||||
Files.copy(appFile(desc.name(), FEATURES_XML), appFile(desc.name(), featuresName));
|
Files.copy(appFile(desc.name(), FEATURES_XML), appFile(desc.name(), featuresName));
|
||||||
@ -402,7 +405,9 @@ public class ApplicationArchive
|
|||||||
cfg.setAttributeSplittingDisabled(true);
|
cfg.setAttributeSplittingDisabled(true);
|
||||||
cfg.setDelimiterParsingDisabled(true);
|
cfg.setDelimiterParsingDisabled(true);
|
||||||
cfg.load(appFile(desc.name(), FEATURES_XML));
|
cfg.load(appFile(desc.name(), FEATURES_XML));
|
||||||
return cfg.getString("feature.bundle");
|
return cfg.getString("feature.bundle")
|
||||||
|
.replaceFirst("wrap:", "")
|
||||||
|
.replaceFirst("\\$Bundle-.*$", "");
|
||||||
} catch (ConfigurationException e) {
|
} catch (ConfigurationException e) {
|
||||||
log.warn("Self-contained application {} has no features.xml", desc.name());
|
log.warn("Self-contained application {} has no features.xml", desc.name());
|
||||||
return null;
|
return null;
|
||||||
|
50
lib/BUCK
50
lib/BUCK
@ -1,4 +1,4 @@
|
|||||||
# ***** This file was auto-generated at Mon, 31 Jul 2017 23:06:54 GMT. Do not edit this file manually. *****
|
# ***** This file was auto-generated at Tue, 8 Aug 2017 17:39:19 GMT. Do not edit this file manually. *****
|
||||||
# ***** Use onos-lib-gen *****
|
# ***** Use onos-lib-gen *****
|
||||||
|
|
||||||
pass_thru_pom(
|
pass_thru_pom(
|
||||||
@ -1211,55 +1211,55 @@ remote_jar (
|
|||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'onos-yang-model',
|
name = 'onos-yang-model',
|
||||||
out = 'onos-yang-model-2.2.0-b3.jar',
|
out = 'onos-yang-model-2.2.0-b4.jar',
|
||||||
url = 'mvn:org.onosproject:onos-yang-model:jar:2.2.0-b3',
|
url = 'mvn:org.onosproject:onos-yang-model:jar:2.2.0-b4',
|
||||||
sha1 = '27e93661796c37268a09aa5c4cdc2e2f6e0ec975',
|
sha1 = 'a1ebb2e81770b2c55cfc2fd9f6e935403bf329b7',
|
||||||
maven_coords = 'org.onosproject:onos-yang-model:2.2.0-b3',
|
maven_coords = 'org.onosproject:onos-yang-model:2.2.0-b4',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'onos-yang-compiler-api',
|
name = 'onos-yang-compiler-api',
|
||||||
out = 'onos-yang-compiler-api-2.2.0-b3.jar',
|
out = 'onos-yang-compiler-api-2.2.0-b4.jar',
|
||||||
url = 'mvn:org.onosproject:onos-yang-compiler-api:jar:2.2.0-b3',
|
url = 'mvn:org.onosproject:onos-yang-compiler-api:jar:2.2.0-b4',
|
||||||
sha1 = 'eeb41cec4779b3a03c684af4fd176711ba3d999f',
|
sha1 = 'b0d7f8569dc14c2444c20b32aebc133be4b31719',
|
||||||
maven_coords = 'org.onosproject:onos-yang-compiler-api:2.2.0-b3',
|
maven_coords = 'org.onosproject:onos-yang-compiler-api:2.2.0-b4',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'onos-yang-runtime',
|
name = 'onos-yang-runtime',
|
||||||
out = 'onos-yang-runtime-2.2.0-b3.jar',
|
out = 'onos-yang-runtime-2.2.0-b4.jar',
|
||||||
url = 'mvn:org.onosproject:onos-yang-runtime:jar:2.2.0-b3',
|
url = 'mvn:org.onosproject:onos-yang-runtime:jar:2.2.0-b4',
|
||||||
sha1 = '40dc7df958b5b7779425522c0ac5dccd7c90f325',
|
sha1 = '82eeb6c0ecd3e9181f08e6309364e008efd90c73',
|
||||||
maven_coords = 'org.onosproject:onos-yang-runtime:2.2.0-b3',
|
maven_coords = 'org.onosproject:onos-yang-runtime:2.2.0-b4',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'onos-yang-serializers-json',
|
name = 'onos-yang-serializers-json',
|
||||||
out = 'onos-yang-serializers-json-2.2.0-b3.jar',
|
out = 'onos-yang-serializers-json-2.2.0-b4.jar',
|
||||||
url = 'mvn:org.onosproject:onos-yang-serializers-json:jar:2.2.0-b3',
|
url = 'mvn:org.onosproject:onos-yang-serializers-json:jar:2.2.0-b4',
|
||||||
sha1 = 'c922e6caf738debf3c82a5e950150dcee3691a68',
|
sha1 = 'ca24ff1719a3a546220b5a5346d8602fd955026c',
|
||||||
maven_coords = 'org.onosproject:onos-yang-serializers-json:2.2.0-b3',
|
maven_coords = 'org.onosproject:onos-yang-serializers-json:2.2.0-b4',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'onos-yang-serializers-xml',
|
name = 'onos-yang-serializers-xml',
|
||||||
out = 'onos-yang-serializers-xml-2.2.0-b3.jar',
|
out = 'onos-yang-serializers-xml-2.2.0-b4.jar',
|
||||||
url = 'mvn:org.onosproject:onos-yang-serializers-xml:jar:2.2.0-b3',
|
url = 'mvn:org.onosproject:onos-yang-serializers-xml:jar:2.2.0-b4',
|
||||||
sha1 = '941c0f451f77f4eeb87f34bb4f8c7c95fab558b2',
|
sha1 = '0ecfff253688a2d11574e34f3edf14a8bef25790',
|
||||||
maven_coords = 'org.onosproject:onos-yang-serializers-xml:2.2.0-b3',
|
maven_coords = 'org.onosproject:onos-yang-serializers-xml:2.2.0-b4',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
remote_jar (
|
remote_jar (
|
||||||
name = 'onos-yang-serializers-utils',
|
name = 'onos-yang-serializers-utils',
|
||||||
out = 'onos-yang-serializers-utils-2.2.0-b3.jar',
|
out = 'onos-yang-serializers-utils-2.2.0-b4.jar',
|
||||||
url = 'mvn:org.onosproject:onos-yang-serializers-utils:jar:2.2.0-b3',
|
url = 'mvn:org.onosproject:onos-yang-serializers-utils:jar:2.2.0-b4',
|
||||||
sha1 = 'a46292313584ff174b3a7feb998d54253bbb7383',
|
sha1 = 'e48c4b374fce66defa1fbe23e9d60e3e78cb48de',
|
||||||
maven_coords = 'org.onosproject:onos-yang-serializers-utils:2.2.0-b3',
|
maven_coords = 'org.onosproject:onos-yang-serializers-utils:2.2.0-b4',
|
||||||
visibility = [ 'PUBLIC' ],
|
visibility = [ 'PUBLIC' ],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
"slf4j-api",
|
"slf4j-api",
|
||||||
"osgi-core",
|
"osgi-core",
|
||||||
"org.osgi.compendium",
|
"org.osgi.compendium",
|
||||||
{ "name": "org.apache.felix.scr.annotations", "compile_only": true },
|
"org.apache.felix.scr.annotations",
|
||||||
"org.apache.felix.scr",
|
"org.apache.felix.scr",
|
||||||
"jackson-annotations",
|
"jackson-annotations",
|
||||||
"jackson-core",
|
"jackson-core",
|
||||||
@ -231,12 +231,12 @@
|
|||||||
"onos-yang-datamodel": "mvn:org.onosproject:onos-yang-datamodel:1.11",
|
"onos-yang-datamodel": "mvn:org.onosproject:onos-yang-datamodel:1.11",
|
||||||
"onos-yang-maven-plugin": "mvn:org.onosproject:onos-yang-maven-plugin:1.11",
|
"onos-yang-maven-plugin": "mvn:org.onosproject:onos-yang-maven-plugin:1.11",
|
||||||
"onos-yang-utils-generator": "mvn:org.onosproject:onos-yang-utils-generator:1.11",
|
"onos-yang-utils-generator": "mvn:org.onosproject:onos-yang-utils-generator:1.11",
|
||||||
"onos-yang-model":"mvn:org.onosproject:onos-yang-model:2.2.0-b3",
|
"onos-yang-model":"mvn:org.onosproject:onos-yang-model:2.2.0-b4",
|
||||||
"onos-yang-compiler-api":"mvn:org.onosproject:onos-yang-compiler-api:2.2.0-b3",
|
"onos-yang-compiler-api":"mvn:org.onosproject:onos-yang-compiler-api:2.2.0-b4",
|
||||||
"onos-yang-runtime":"mvn:org.onosproject:onos-yang-runtime:2.2.0-b3",
|
"onos-yang-runtime":"mvn:org.onosproject:onos-yang-runtime:2.2.0-b4",
|
||||||
"onos-yang-serializers-json":"mvn:org.onosproject:onos-yang-serializers-json:2.2.0-b3",
|
"onos-yang-serializers-json":"mvn:org.onosproject:onos-yang-serializers-json:2.2.0-b4",
|
||||||
"onos-yang-serializers-xml":"mvn:org.onosproject:onos-yang-serializers-xml:2.2.0-b3",
|
"onos-yang-serializers-xml":"mvn:org.onosproject:onos-yang-serializers-xml:2.2.0-b4",
|
||||||
"onos-yang-serializers-utils":"mvn:org.onosproject:onos-yang-serializers-utils:2.2.0-b3",
|
"onos-yang-serializers-utils":"mvn:org.onosproject:onos-yang-serializers-utils:2.2.0-b4",
|
||||||
"org.apache.servicemix.bundles.dom4j":"mvn:org.apache.servicemix.bundles:org.apache.servicemix.bundles.dom4j:1.6.1_5",
|
"org.apache.servicemix.bundles.dom4j":"mvn:org.apache.servicemix.bundles:org.apache.servicemix.bundles.dom4j:1.6.1_5",
|
||||||
"plexus-utils": "mvn:org.codehaus.plexus:plexus-utils:3.0.24",
|
"plexus-utils": "mvn:org.codehaus.plexus:plexus-utils:3.0.24",
|
||||||
"sshd-core": "mvn:org.apache.sshd:sshd-core:1.4.0",
|
"sshd-core": "mvn:org.apache.sshd:sshd-core:1.4.0",
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
# Patches lib/BUCK file to use locally built YANG tools.
|
# Patches lib/BUCK file to use locally built YANG tools.
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
BVER=2.1
|
BVER=2.2.0-b3
|
||||||
SVER=2.2-SNAPSHOT
|
SVER=2.2-SNAPSHOT
|
||||||
|
|
||||||
YANG_TOOLS_ROOT=~/onos-yang-tools
|
YANG_TOOLS_ROOT=~/onos-yang-tools
|
||||||
|
54
tools/package/runtime/bin/onos-compile-yang
Executable file
54
tools/package/runtime/bin/onos-compile-yang
Executable file
@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015-present Open Networking Foundation
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Tool to compile the specified YANG file(s) using the ONOS live compilation.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# If ONOS_HOME is set, respect its value.
|
||||||
|
# If ONOS_HOME is not set (e.g. in the init or service environment),
|
||||||
|
# set it based on this script's path.
|
||||||
|
ONOS_HOME=${ONOS_HOME:-$(cd $(dirname $0)/.. >/dev/null 2>&1 && pwd)}
|
||||||
|
ONOS_WEB_USER=${ONOS_WEB_USER:-onos} # ONOS WEB User defaults to 'onos'
|
||||||
|
ONOS_WEB_PASS=${ONOS_WEB_PASS:-rocks} # ONOS WEB Password defaults to 'rocks'
|
||||||
|
|
||||||
|
. ${ONOS_HOME}/bin/_find-node
|
||||||
|
|
||||||
|
node=$(find_node $1)
|
||||||
|
yang=$2
|
||||||
|
|
||||||
|
export URL=http://$node:8181/onos/yang/models
|
||||||
|
export curl="curl -sS --user $ONOS_WEB_USER:$ONOS_WEB_PASS --noproxy localhost "
|
||||||
|
|
||||||
|
# Prints usage help
|
||||||
|
function usage {
|
||||||
|
echo "usage: onos-compile-yang <yang-file|zip-file|jar-file|directory>" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[ -z $node -o "$node" = "-h" -o "$node" = "--help" -o "$node" = "-?" ] && usage
|
||||||
|
|
||||||
|
if [ -d $yang ]; then
|
||||||
|
newYang=/tmp/$(basename $yang).jar
|
||||||
|
jar cf $newYang $yang
|
||||||
|
yang=$newYang
|
||||||
|
fi
|
||||||
|
|
||||||
|
file=$(basename $yang)
|
||||||
|
modelId="$(echo $file | sed -E 's/(.zip|.jar|.yang)$//g')"
|
||||||
|
curl $URL?modelId=$modelId -F"file=@$yang"
|
@ -82,11 +82,11 @@
|
|||||||
if (haveItems) {
|
if (haveItems) {
|
||||||
setTdWidths(tableElems.thead, width);
|
setTdWidths(tableElems.thead, width);
|
||||||
setTdWidths(tableElems.tbody, width);
|
setTdWidths(tableElems.tbody, width);
|
||||||
setHeight(tableElems.thead, tableElems.table.select('.table-body'), height);
|
|
||||||
} else {
|
} else {
|
||||||
setTdWidths(tableElems.thead, width);
|
setTdWidths(tableElems.thead, width);
|
||||||
_width(tableElems.tbody, width + 'px');
|
_width(tableElems.tbody, width + 'px');
|
||||||
}
|
}
|
||||||
|
setHeight(tableElems.thead, tableElems.table.select('.table-body'), height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort columns state model and functions
|
// sort columns state model and functions
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<form id="inputFileForm">
|
<form id="inputFileForm">
|
||||||
<input id="uploadFile"
|
<input id="uploadFile"
|
||||||
type="file" size="50" accept=".oar"
|
type="file" size="50" accept=".oar,.jar"
|
||||||
file-model="appFile">
|
file-model="appFile">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user