mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-21 13:08:42 +00:00
acrn-config: web UI app for acrn-config tool
The web UI application for ACRN VM configuration tool based on Flask web framework: 1. import board info xml which is generated by acrn-config/target on target boards; or select one board from the imported list of UI. 2. load scenario settings or import scenario settings from local. 3. edit scenario settings from web UI. 4. export and save the edited scenario setting, the application will prompt error messages from UI if there are illegal configured items. 5. generate board source code, generate scenario source code. 6. load launch settings or import launch settings from local. 7. edit launch settings from web UI. 8. export and save the edited launch setting; the application will prompt error messages from UI if there are illegal configurable items 9. generate launch scripts based on current launch setting. Tracked-On: #3602 Signed-off-by: Shuang Zheng <shuang.zheng@intel.com> Reviewed-by: Victor Sun <victor.sun@intel.com> Acked-by: Terry Zou <terry.zou@intel.com>
This commit is contained in:
parent
476e9a2efe
commit
00da5a994e
43
misc/acrn-config/config_app/app.py
Normal file
43
misc/acrn-config/config_app/app.py
Normal file
@ -0,0 +1,43 @@
|
||||
# Copyright (C) 2019 Intel Corporation.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
"""Entry for config app.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
import webbrowser
|
||||
|
||||
# flask: Copyright 2010 Pallets
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Refer to https://github.com/pallets/flask/blob/master/LICENSE.rst for the permission notice.
|
||||
from flask import Flask
|
||||
|
||||
# flask: Copyright (c) 2013, Marc Brinkmann
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Refer to https://pypi.org/project/Flask-Bootstrap/ for the permission notice.
|
||||
from flask_bootstrap import Bootstrap
|
||||
|
||||
import configs
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library'))
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..',
|
||||
'board_config'))
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..',
|
||||
'scenario_config'))
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..',
|
||||
'launch_config'))
|
||||
from views import CONFIG_APP
|
||||
|
||||
APP = Flask(__name__)
|
||||
APP.config.from_object(configs)
|
||||
APP.register_blueprint(CONFIG_APP)
|
||||
APP.jinja_env.add_extension('jinja2.ext.do')
|
||||
Bootstrap(app=APP)
|
||||
|
||||
if __name__ == '__main__':
|
||||
URL = "http://127.0.0.1:5001/scenario"
|
||||
threading.Timer(1, lambda: webbrowser.open(URL)).start()
|
||||
APP.run(port=5001, debug=False)
|
13
misc/acrn-config/config_app/configs.py
Normal file
13
misc/acrn-config/config_app/configs.py
Normal file
@ -0,0 +1,13 @@
|
||||
# Copyright (C) 2019 Intel Corporation.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
"""Configurations for config app.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
BOARD_INFO = None
|
||||
BOARD_TYPE = None
|
||||
SCENARIO = None
|
||||
CONFIG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'xmls', 'config-xmls')
|
288
misc/acrn-config/config_app/controller.py
Normal file
288
misc/acrn-config/config_app/controller.py
Normal file
@ -0,0 +1,288 @@
|
||||
# Copyright (C) 2019 Intel Corporation.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
"""Controller for config app.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import xml.etree.ElementTree as ElementTree
|
||||
|
||||
|
||||
class XmlConfig:
|
||||
"""The core class to analyze and modify acrn config xml files"""
|
||||
def __init__(self, path=None, default=True):
|
||||
self._xml_path = path
|
||||
self._default = default
|
||||
self._curr_xml = None
|
||||
self._curr_xml_tree = None
|
||||
|
||||
@staticmethod
|
||||
def _get_xml_type(xml_file):
|
||||
"""
|
||||
get the config type by file.
|
||||
:param xml_file: the file path of xml file.
|
||||
:return: the xml type.
|
||||
:raises: ValueError, OSError, SyntaxError.
|
||||
"""
|
||||
xml_type = ''
|
||||
if os.path.splitext(xml_file)[1] != '.xml':
|
||||
return xml_type
|
||||
try:
|
||||
tree = ElementTree.parse(xml_file)
|
||||
root = tree.getroot()
|
||||
if 'uos_launcher' in root.attrib:
|
||||
xml_type = 'uos_launcher'
|
||||
elif 'scenario' in root.attrib:
|
||||
xml_type = 'scenario'
|
||||
elif 'board' in root.attrib:
|
||||
xml_type = 'board'
|
||||
elif 'board_setting' in root.attrib:
|
||||
xml_type = 'board_setting'
|
||||
except ValueError:
|
||||
print('xml parse error: {}'.format(xml_file))
|
||||
xml_type = ''
|
||||
except OSError:
|
||||
print('xml open error: {}'.format(xml_file))
|
||||
xml_type = ''
|
||||
except SyntaxError:
|
||||
print('xml syntax error: {}'.format(xml_file))
|
||||
xml_type = ''
|
||||
|
||||
return xml_type
|
||||
|
||||
def list_all(self, xml_type=None):
|
||||
"""
|
||||
list all xml config files by type.
|
||||
:param xml_type: the xml type.
|
||||
:return: he list of xml config files.
|
||||
"""
|
||||
xmls = []
|
||||
user_xmls = []
|
||||
|
||||
if self._xml_path is None or not os.path.exists(self._xml_path):
|
||||
return xmls, user_xmls
|
||||
for test_file in os.listdir(self._xml_path):
|
||||
test_file_path = os.path.join(self._xml_path, test_file)
|
||||
if os.path.isfile(test_file_path):
|
||||
if XmlConfig._get_xml_type(test_file_path) == xml_type:
|
||||
xmls.append(os.path.splitext(test_file)[0])
|
||||
user_path = os.path.join(self._xml_path, 'user_defined')
|
||||
if os.path.isdir(user_path):
|
||||
for test_file in os.listdir(user_path):
|
||||
test_file_path = os.path.join(user_path, test_file)
|
||||
if os.path.isfile(test_file_path):
|
||||
if XmlConfig._get_xml_type(test_file_path) == xml_type:
|
||||
user_xmls.append(os.path.splitext(test_file)[0])
|
||||
|
||||
return xmls, user_xmls
|
||||
|
||||
def set_curr(self, xml):
|
||||
"""
|
||||
set current xml file to analyze.
|
||||
:param xml: the xml file.
|
||||
:return: None.
|
||||
:raises: ValueError, OSError, SyntaxError.
|
||||
"""
|
||||
if self._xml_path is None:
|
||||
return
|
||||
try:
|
||||
self._curr_xml = xml
|
||||
|
||||
xml_path = os.path.join(self._xml_path, self._curr_xml + '.xml') \
|
||||
if self._default \
|
||||
else os.path.join(self._xml_path, 'user_defined', self._curr_xml + '.xml')
|
||||
|
||||
tree = ElementTree.parse(xml_path)
|
||||
self._curr_xml_tree = tree
|
||||
except ValueError:
|
||||
print('xml parse error: {}'.format(xml))
|
||||
self._curr_xml = None
|
||||
self._curr_xml_tree = None
|
||||
except OSError:
|
||||
print('xml open error: {}'.format(xml))
|
||||
self._curr_xml = None
|
||||
self._curr_xml_tree = None
|
||||
except SyntaxError:
|
||||
print('xml syntax error: {}'.format(xml))
|
||||
self._curr_xml = None
|
||||
self._curr_xml_tree = None
|
||||
|
||||
def get_curr(self):
|
||||
"""
|
||||
get current xml config file.
|
||||
:return: current xml config file name.
|
||||
"""
|
||||
return self._curr_xml
|
||||
|
||||
def get_curr_root(self):
|
||||
"""
|
||||
get the xml root of current xml config file.
|
||||
:return: the xml root of current xml config file.
|
||||
"""
|
||||
if self._curr_xml_tree is None:
|
||||
return None
|
||||
return self._curr_xml_tree.getroot()
|
||||
|
||||
def get_curr_value(self, *args):
|
||||
"""
|
||||
get the value of the element by its path.
|
||||
:param args: the path of the element.
|
||||
:return: the value of the element.
|
||||
"""
|
||||
if self._curr_xml_tree is None:
|
||||
return None
|
||||
dest_node = self._get_dest_node(*args)
|
||||
if dest_node is None:
|
||||
return None
|
||||
if dest_node.text is None or dest_node.text.strip() == '':
|
||||
return ''
|
||||
return dest_node.text
|
||||
|
||||
def set_curr_value(self, value, *args):
|
||||
"""
|
||||
set the value of the element by its path.
|
||||
:param value: the value of the element.
|
||||
:param args: the path of the element.
|
||||
:return: None.
|
||||
"""
|
||||
if self._curr_xml_tree is None:
|
||||
return
|
||||
dest_node = self._get_dest_node(*args)
|
||||
dest_node.text = value
|
||||
|
||||
def set_curr_list(self, values, *args):
|
||||
"""
|
||||
set a list of sub element for the element by its path.
|
||||
:param values: the list of values of the element.
|
||||
:param args: the path of the element.
|
||||
:return: None.
|
||||
"""
|
||||
if self._curr_xml_tree is None:
|
||||
return
|
||||
tag = args[-1]
|
||||
args = args[:-1]
|
||||
dest_node = self._get_dest_node(*args)
|
||||
for node in dest_node.getchildren():
|
||||
dest_node.remove(node)
|
||||
for value in values:
|
||||
new_node = ElementTree.SubElement(dest_node, tag)
|
||||
new_node.text = value
|
||||
|
||||
def set_curr_attr(self, attr_name, attr_value, *args):
|
||||
"""
|
||||
set the attribute of the element by its path.
|
||||
:param attr_name: the attribute name of the element.
|
||||
:param attr_value: the attribute value of the element.
|
||||
:param args: the path of the element.
|
||||
:return: None.
|
||||
"""
|
||||
if self._curr_xml_tree is None:
|
||||
return
|
||||
dest_node = self._get_dest_node(*args)
|
||||
dest_node.attrib[attr_name] = attr_value
|
||||
|
||||
def add_curr_value(self, key, desc, value, *args):
|
||||
"""
|
||||
add a sub element for the element by its path.
|
||||
:param key: the tag of the sub element.
|
||||
:param desc: the attribute desc of the sub element.
|
||||
:param value: the value of the sub element.
|
||||
:param args: the path of the element.
|
||||
:return: None.
|
||||
"""
|
||||
if self._curr_xml_tree is None:
|
||||
return
|
||||
|
||||
dest_node = self._get_dest_node(*args)
|
||||
|
||||
if key in ['vm']:
|
||||
ElementTree.SubElement(dest_node, key, attrib={'id': value, 'desc': desc})
|
||||
else:
|
||||
new_node = ElementTree.SubElement(dest_node, key, attrib={'desc': desc})
|
||||
new_node.text = value
|
||||
|
||||
def delete_curr_key(self, *args):
|
||||
"""
|
||||
delete the element by its path.
|
||||
:param args: the path of the element.
|
||||
:return: None.
|
||||
"""
|
||||
if self._curr_xml_tree is None:
|
||||
return
|
||||
dest_node = self._get_dest_node(*args)
|
||||
self._curr_xml_tree.getroot().remove(dest_node)
|
||||
|
||||
def _get_dest_node(self, *args):
|
||||
"""
|
||||
get the destination element by its path.
|
||||
:param args: the path of the element.
|
||||
:return: the destination element.
|
||||
"""
|
||||
if self._curr_xml_tree is None:
|
||||
return None
|
||||
dest_node = self._curr_xml_tree.getroot()
|
||||
path = '.'
|
||||
for arg in args:
|
||||
# tag:attr=xxx
|
||||
# tag:attr
|
||||
# tag
|
||||
tag = None
|
||||
attr_name = None
|
||||
attr_value = None
|
||||
if ':' not in arg:
|
||||
tag = arg
|
||||
elif '=' not in arg:
|
||||
# tag = arg.split(':')[0]
|
||||
# attr_name = arg.split(':')[1]
|
||||
raise Exception('unsupported xml path: tag:attr')
|
||||
else:
|
||||
tag = arg.split(':')[0]
|
||||
attr = arg.split(':')[1]
|
||||
attr_name = attr.split('=')[0]
|
||||
attr_value = attr.split('=')[1]
|
||||
|
||||
if attr_value is None:
|
||||
path += ("/" + tag)
|
||||
else:
|
||||
path += ("/" + tag + "[@" + attr_name + "='" + attr_value + "']")
|
||||
|
||||
dest_node = dest_node.findall(path)
|
||||
if dest_node is not None and dest_node != []:
|
||||
return dest_node[0]
|
||||
|
||||
raise Exception('can not find node by {} from xml'.format(args))
|
||||
|
||||
def save(self, xml=None):
|
||||
"""
|
||||
save current xml to file.
|
||||
:param xml: the file name to save; if not specified, save current xml to default names.
|
||||
:return: None.
|
||||
"""
|
||||
if self._curr_xml_tree is None:
|
||||
return
|
||||
if xml is None:
|
||||
xml = self._curr_xml
|
||||
|
||||
xml_path = os.path.join(self._xml_path, 'user_defined')
|
||||
if not os.path.isdir(xml_path):
|
||||
os.makedirs(xml_path)
|
||||
|
||||
self._format_xml(self._curr_xml_tree.getroot())
|
||||
self._curr_xml_tree.write(os.path.join(xml_path, xml+'.xml'), encoding='utf-8',
|
||||
xml_declaration=True, method='xml')
|
||||
|
||||
def _format_xml(self, element, depth=0):
|
||||
i = "\n" + depth * " "
|
||||
if element:
|
||||
if not element.text or not element.text.strip():
|
||||
element.text = i + " "
|
||||
if not element.tail or not element.tail.strip():
|
||||
element.tail = i
|
||||
for element in element:
|
||||
self._format_xml(element, depth + 1)
|
||||
if not element.tail or not element.tail.strip():
|
||||
element.tail = i
|
||||
else:
|
||||
if depth and (not element.tail or not element.tail.strip()):
|
||||
element.tail = i
|
3
misc/acrn-config/config_app/requirements
Normal file
3
misc/acrn-config/config_app/requirements
Normal file
@ -0,0 +1,3 @@
|
||||
Flask==1.1.1
|
||||
flask_bootstrap==3.3.7.1
|
||||
|
560
misc/acrn-config/config_app/static/main.js
Normal file
560
misc/acrn-config/config_app/static/main.js
Normal file
@ -0,0 +1,560 @@
|
||||
$().ready(function(){
|
||||
$("#board_info_file").change(function () {
|
||||
var fileObj = $(this)[0].files[0];
|
||||
if (typeof (fileObj) == "undefined" || fileObj.size <= 0) {
|
||||
alert("Upload error.");
|
||||
return;
|
||||
}
|
||||
var file_name = $(this).val();
|
||||
var formFile = new FormData();
|
||||
formFile.append("name", file_name);
|
||||
formFile.append("file", fileObj);
|
||||
|
||||
|
||||
$.ajax({
|
||||
url: "../upload_board_info",
|
||||
data: formFile,
|
||||
type: "Post",
|
||||
dataType: "json",
|
||||
cache: false,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function (result) {
|
||||
console.log(result);
|
||||
if (result.status == 'success') {
|
||||
if (result.info != 'updated') {
|
||||
alert('Upload successfully.\nA new board type: '+result.info+' created.');
|
||||
} else {
|
||||
alert('Upload successfully.');
|
||||
}
|
||||
} else {
|
||||
alert(result.status);
|
||||
}
|
||||
|
||||
window.location.reload();
|
||||
},
|
||||
error: function(e){
|
||||
console.log(e.status);
|
||||
console.log(e.responseText);
|
||||
alert(e.status+'\n'+e.responseText);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
$("#scenario_file").change(function () {
|
||||
var fileObj = $(this)[0].files[0];
|
||||
if (typeof (fileObj) == "undefined" || fileObj.size <= 0) {
|
||||
alert("Upload error.");
|
||||
return;
|
||||
}
|
||||
var file_name = $(this).val();
|
||||
|
||||
var formFile = new FormData();
|
||||
formFile.append("name", file_name);
|
||||
formFile.append("file", fileObj);
|
||||
|
||||
$.ajax({
|
||||
url: "../upload_scenario",
|
||||
data: formFile,
|
||||
type: "Post",
|
||||
dataType: "json",
|
||||
cache: false,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function (result) {
|
||||
console.log(result);
|
||||
status = result.status;
|
||||
if (status!='success') {
|
||||
alert(status);
|
||||
return;
|
||||
}
|
||||
error_list = result.error_list;
|
||||
file_name = result.file_name;
|
||||
rename = result.rename
|
||||
if(result.rename==true) {
|
||||
alert('Scenario setting existed, import successfully with a new name: '+file_name);
|
||||
} else {
|
||||
alert('Scenario setting import successfully with name: '+file_name);
|
||||
}
|
||||
window.location = 'http://'
|
||||
+ window.location.host+"/scenario/user_defined_" + file_name;
|
||||
},
|
||||
error: function(e){
|
||||
console.log(e.status);
|
||||
console.log(e.responseText);
|
||||
alert(e.status+'\n'+e.responseText);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
$("#launch_file").change(function () {
|
||||
var fileObj = $(this)[0].files[0];
|
||||
if (typeof (fileObj) == "undefined" || fileObj.size <= 0) {
|
||||
alert("Upload error.");
|
||||
return;
|
||||
}
|
||||
var file_name = $(this).val();
|
||||
|
||||
var formFile = new FormData();
|
||||
formFile.append("name", file_name);
|
||||
formFile.append("file", fileObj);
|
||||
|
||||
$.ajax({
|
||||
url: "../upload_launch",
|
||||
data: formFile,
|
||||
type: "Post",
|
||||
dataType: "json",
|
||||
cache: false,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function (result) {
|
||||
console.log(result);
|
||||
status = result.status;
|
||||
if (status!='success') {
|
||||
alert(status);
|
||||
return;
|
||||
}
|
||||
error_list = result.error_list;
|
||||
file_name = result.file_name;
|
||||
rename = result.rename
|
||||
if(result.rename==true) {
|
||||
alert('Launch setting existed, import successfully with a new name: '+file_name);
|
||||
} else {
|
||||
alert('Launch setting import successfully with name: '+file_name);
|
||||
}
|
||||
window.location = 'http://'
|
||||
+ window.location.host+"/launch/user_defined_" + file_name;
|
||||
},
|
||||
error: function(e){
|
||||
console.log(e.status);
|
||||
console.log(e.responseText);
|
||||
alert(e.status+'\n'+e.responseText);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
$("select#board_info").change(function(){
|
||||
data = {board_info: $(this).val()};
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
url : "../select_board",
|
||||
data : JSON.stringify(data),
|
||||
success : function(result) {
|
||||
console.log(result);
|
||||
window.location.reload(true);
|
||||
},
|
||||
error : function(e){
|
||||
console.log(e.status);
|
||||
console.log(e.responseText);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("input").on('blur',function(){
|
||||
$(this).parents(".form-group").removeClass("has-error");
|
||||
$(this).parents(".form-group").children("p").text("");
|
||||
});
|
||||
|
||||
$("select").on('changed.bs.select',function(){
|
||||
$(this).parents(".form-group").removeClass("has-error");
|
||||
$(this).parents(".form-group").children("p").text("");
|
||||
})
|
||||
|
||||
$('#save_board').on('click', function() {
|
||||
save_board();
|
||||
});
|
||||
|
||||
$('#save_scenario').on('click', function() {
|
||||
var name = $(this).data('id');
|
||||
if(name=="generate_board_src" || name=="generate_scenario_src") {
|
||||
save_scenario(name);
|
||||
}
|
||||
else {
|
||||
save_scenario();
|
||||
}
|
||||
});
|
||||
|
||||
$('#remove_scenario').on('click', function() {
|
||||
old_scenario_name = $("#old_scenario_name").text();
|
||||
if(old_scenario_name.indexOf('user_defined')<0) {
|
||||
alert("Default scenario setting could not be deleted.");
|
||||
return;
|
||||
}
|
||||
|
||||
var board_info = $("select#board_info").val();
|
||||
if (board_info==null || board_info=='') {
|
||||
alert("Please select one board info before this operation.");
|
||||
return;
|
||||
}
|
||||
|
||||
scenario_config = {
|
||||
old_setting_name: $("#old_scenario_name").text(),
|
||||
new_setting_name: $("#new_scenario_name").val()
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
url : "../remove_setting",
|
||||
data : JSON.stringify(scenario_config),
|
||||
success : function(result) {
|
||||
console.log(result);
|
||||
status = result.status
|
||||
info = result.info
|
||||
if (status == 'success') {
|
||||
alert('Remove current scenario setting from acrn-config app successfully.');
|
||||
window.location = window.location = 'http://'
|
||||
+ window.location.host+"/scenario";
|
||||
} else {
|
||||
alert('Remove current scenario setting from acrn-config app failed:\n'+info);
|
||||
}
|
||||
},
|
||||
error : function(e){
|
||||
console.log(e.status);
|
||||
console.log(e.responseText);
|
||||
alert(e.status+'\n'+e.responseText);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#save_launch').on('click', function() {
|
||||
var name = $(this).data('id');
|
||||
if(name=="generate_launch_script") {
|
||||
save_launch(name);
|
||||
}
|
||||
else {
|
||||
save_launch();
|
||||
}
|
||||
});
|
||||
|
||||
$('#remove_launch').on('click', function() {
|
||||
old_launch_name = $("#old_launch_name").text();
|
||||
if(old_launch_name.indexOf('user_defined')<0) {
|
||||
alert("Default launch setting could not be deleted.");
|
||||
return;
|
||||
}
|
||||
|
||||
var board_info = $("select#board_info").val();
|
||||
if (board_info==null || board_info=='') {
|
||||
alert("Please select one board before this operation.");
|
||||
return;
|
||||
}
|
||||
|
||||
launch_config = {
|
||||
old_setting_name: $("#old_launch_name").text(),
|
||||
new_setting_name: $("#new_launch_name").val(),
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
url : "../remove_setting",
|
||||
data : JSON.stringify(launch_config),
|
||||
success : function(result) {
|
||||
console.log(result);
|
||||
status = result.status
|
||||
info = result.info
|
||||
if (status == 'success') {
|
||||
alert('Remove current launch setting from acrn-config app successfully.');
|
||||
window.location = window.location = 'http://'
|
||||
+ window.location.host+"/launch";
|
||||
} else {
|
||||
alert('Remove current launch setting from acrn-config app failed:\n'+info);
|
||||
}
|
||||
},
|
||||
error : function(e){
|
||||
console.log(e.status);
|
||||
console.log(e.responseText);
|
||||
alert(e.status+'\n'+e.responseText);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#generate_board_src').on('click', function() {
|
||||
var dataId = $(this).data('id');
|
||||
$("#save_scenario").data('id', dataId);
|
||||
});
|
||||
|
||||
$('#generate_scenario_src').on('click', function() {
|
||||
var dataId = $(this).data('id');
|
||||
$("#save_scenario").data('id', dataId);
|
||||
});
|
||||
|
||||
$('#generate_launch_script').on('click', function() {
|
||||
var dataId = $(this).data('id');
|
||||
$("#save_launch").data('id', dataId);
|
||||
});
|
||||
|
||||
$("select[ID$='vuart:id=1,base']").change(function(){
|
||||
|
||||
var id = $(this).attr('id');
|
||||
var value = $(this).val();
|
||||
show_com_target(id, value);
|
||||
});
|
||||
|
||||
$("select[ID$='vuart:id=1,base']").each(function(index, item) {
|
||||
var id = $(item).attr('id');
|
||||
var value = $(item).val();
|
||||
show_com_target(id, value);
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
||||
function show_com_target(id, value) {
|
||||
|
||||
if(id==null || id=='undefined') {
|
||||
return
|
||||
}
|
||||
var id2 = id.replace('base', 'target_vm_id');
|
||||
var jquerySpecialChars = ["~", "`", "@", "#", "%", "&", "=", "'", "\"",
|
||||
":", ";", "<", ">", ",", "/"];
|
||||
for (var i = 0; i < jquerySpecialChars.length; i++) {
|
||||
id2 = id2.replace(new RegExp(jquerySpecialChars[i],
|
||||
"g"), "\\" + jquerySpecialChars[i]);
|
||||
}
|
||||
if (value == 'INVALID_COM_BASE') {
|
||||
$('#'+id2+'_label1').hide();
|
||||
$('#'+id2+'_label2').hide();
|
||||
$('#'+id2+'_config').hide();
|
||||
$('#'+id2+'_err').hide();
|
||||
}
|
||||
else {
|
||||
$('#'+id2+'_label1').show();
|
||||
$('#'+id2+'_label2').show();
|
||||
$('#'+id2+'_config').show();
|
||||
$('#'+id2+'_err').show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function save_scenario(generator=null){
|
||||
var board_info = $("select#board_info").val();
|
||||
if (board_info==null || board_info=='') {
|
||||
alert("Please select one board info before this operation.");
|
||||
return;
|
||||
}
|
||||
|
||||
scenario_config = {
|
||||
old_scenario_name: $("#old_scenario_name").text(),
|
||||
new_scenario_name: $("#new_scenario_name").val()
|
||||
}
|
||||
|
||||
$("input").each(function(){
|
||||
var id = $(this).attr('id');
|
||||
var value = $(this).val();
|
||||
if(id!='new_scenario_name' && id!='board_info_file'
|
||||
&& id!='board_info_upload' && id!="scenario_file") {
|
||||
scenario_config[id] = $(this).val();
|
||||
}
|
||||
})
|
||||
|
||||
$("textarea").each(function(){
|
||||
var id = $(this).attr('id');
|
||||
var value = $(this).val();
|
||||
if(id!='new_scenario_name' && id!='board_info_file'
|
||||
&& id!='board_info_upload' && id!="scenario_file") {
|
||||
scenario_config[id] = $(this).val();
|
||||
}
|
||||
})
|
||||
|
||||
$("select").each(function(){
|
||||
var id = $(this).attr('id');
|
||||
var value = $(this).val();
|
||||
if(id!='board_info') {
|
||||
scenario_config[$(this).attr('id')] = $(this).val();
|
||||
}
|
||||
})
|
||||
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
url : "../save_scenario",
|
||||
data : JSON.stringify(scenario_config),
|
||||
success : function(result) {
|
||||
error_list = result.error_list;
|
||||
status = result.status;
|
||||
var no_err = true;
|
||||
$.each(error_list, function(index,item){
|
||||
no_err = false;
|
||||
var jquerySpecialChars = ["~", "`", "@", "#", "%", "&", "=", "'", "\"",
|
||||
":", ";", "<", ">", ",", "/"];
|
||||
for (var i = 0; i < jquerySpecialChars.length; i++) {
|
||||
index = index.replace(new RegExp(jquerySpecialChars[i],
|
||||
"g"), "\\" + jquerySpecialChars[i]);
|
||||
}
|
||||
$("#"+index).parents(".form-group").addClass("has-error");
|
||||
$("#"+index+"_err").text(item);
|
||||
})
|
||||
if(no_err == true && status == 'success') {
|
||||
file_name = result.file_name;
|
||||
if(result.rename==true) {
|
||||
alert('Scenario setting existed, saved successfully with a new name: '
|
||||
+file_name+'\nto acrn-hypervisor/misc/acrn-config/xmls/config-xmls/'+board_info+'/user_defined/');
|
||||
} else {
|
||||
alert('Scenario setting saved successfully with name: '
|
||||
+file_name+'\nto acrn-hypervisor/misc/acrn-config/xmls/config-xmls/'+board_info+'/user_defined/');
|
||||
}
|
||||
if(generator != null) {
|
||||
generator_config = {
|
||||
type: generator,
|
||||
board_info: $("select#board_info").val(),
|
||||
board_setting: "board_setting",
|
||||
scenario_setting: file_name
|
||||
}
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
url : "../generate_src",
|
||||
data : JSON.stringify(generator_config),
|
||||
success : function(result) {
|
||||
console.log(result);
|
||||
status = result.status
|
||||
error_list = result.error_list
|
||||
if (status == 'success' && JSON.stringify(error_list)=='{}') {
|
||||
alert(generator+' successfully.');
|
||||
} else {
|
||||
alert(generator+' failed. \nError list:\n'+JSON.stringify(error_list));
|
||||
}
|
||||
window.location = "./user_defined_" + file_name;
|
||||
},
|
||||
error : function(e){
|
||||
console.log(e.status);
|
||||
console.log(e.responseText);
|
||||
alert(e.status+'\n'+e.responseText);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
window.location = "./user_defined_" + file_name;
|
||||
}
|
||||
}
|
||||
else if(status != 'success') {
|
||||
alert(JSON.stringify(error_list));
|
||||
}
|
||||
},
|
||||
error : function(e){
|
||||
console.log(e.status);
|
||||
console.log(e.responseText);
|
||||
alert(e.status+'\n'+e.responseText);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function save_launch(generator=null) {
|
||||
var board_info = $("select#board_info").val();
|
||||
var scenario_name = $("select#scenario_name").val();
|
||||
if (board_info==null || board_info=='' || scenario_name==null || scenario_name=='') {
|
||||
alert("Please select one board and scenario before this operation.");
|
||||
return;
|
||||
}
|
||||
|
||||
launch_config = {
|
||||
old_launch_name: $("#old_launch_name").text(),
|
||||
new_launch_name: $("#new_launch_name").val(),
|
||||
scenario_name: scenario_name
|
||||
}
|
||||
|
||||
$("input").each(function(){
|
||||
var id = $(this).attr('id');
|
||||
var value = $(this).val();
|
||||
if(id!='new_launch_name' && id!='board_info_file'
|
||||
&& id!='board_info_upload' && id!='scenario_name'
|
||||
&& id!="launch_file") {
|
||||
launch_config[id] = $(this).val();
|
||||
}
|
||||
})
|
||||
|
||||
$("select").each(function(){
|
||||
var id = $(this).attr('id');
|
||||
var value = $(this).val();
|
||||
if(id!='board_info') {
|
||||
launch_config[$(this).attr('id')] = $(this).val();
|
||||
}
|
||||
})
|
||||
|
||||
$("textarea").each(function(){
|
||||
var id = $(this).attr('id');
|
||||
var value = $(this).val();
|
||||
if(id!='new_scenario_name' && id!='board_info_file'
|
||||
&& id!='board_info_upload' && id!="scenario_file") {
|
||||
launch_config[id] = $(this).val();
|
||||
}
|
||||
})
|
||||
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
url : "../save_launch",
|
||||
data : JSON.stringify(launch_config),
|
||||
success : function(result) {
|
||||
console.log(result);
|
||||
error_list = result.error_list;
|
||||
status = result.status;
|
||||
|
||||
var no_err = true;
|
||||
$.each(error_list, function(index,item){
|
||||
no_err = false;
|
||||
var jquerySpecialChars = ["~", "`", "@", "#", "%", "&", "=", "'", "\"",
|
||||
":", ";", "<", ">", ",", "/"];
|
||||
for (var i = 0; i < jquerySpecialChars.length; i++) {
|
||||
index = index.replace(new RegExp(jquerySpecialChars[i],
|
||||
"g"), "\\" + jquerySpecialChars[i]);
|
||||
}
|
||||
$("#"+index).parents(".form-group").addClass("has-error");
|
||||
$("#"+index+"_err").text(item);
|
||||
})
|
||||
if(no_err == true && status == 'success') {
|
||||
file_name = result.file_name;
|
||||
if(result.rename==true) {
|
||||
alert('Launch setting existed, saved successfully with a new name: '
|
||||
+file_name+'\nto acrn-hypervisor/misc/acrn-config/xmls/config-xmls/'+board_info+'/user_defined/');
|
||||
} else {
|
||||
alert('Launch setting saved successfully with name: '
|
||||
+file_name+'\nto acrn-hypervisor/misc/acrn-config/xmls/config-xmls/'+board_info+'/user_defined/');
|
||||
}
|
||||
if(generator != null) {
|
||||
generator_config = {
|
||||
type: generator,
|
||||
board_info: $("select#board_info").val(),
|
||||
board_setting: "board_setting",
|
||||
scenario_setting: $("select#scenario_name").val(),
|
||||
launch_setting: file_name
|
||||
}
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
url : "../generate_src",
|
||||
data : JSON.stringify(generator_config),
|
||||
success : function(result) {
|
||||
console.log(result);
|
||||
status = result.status
|
||||
error_list = result.error_list
|
||||
if (status == 'success' && JSON.stringify(error_list)=='{}') {
|
||||
alert(generator+' successfully.');
|
||||
} else {
|
||||
alert(generator+' failed. \nError list:\n'+JSON.stringify(error_list));
|
||||
}
|
||||
window.location = "./user_defined_" + file_name;
|
||||
},
|
||||
error : function(e){
|
||||
console.log(e.status);
|
||||
console.log(e.responseText);
|
||||
alert(e.status+'\n'+e.responseText);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
window.location = "./user_defined_" + file_name;
|
||||
}
|
||||
}
|
||||
else if(status != 'success') {
|
||||
alert(JSON.stringify(error_list));
|
||||
}
|
||||
},
|
||||
error : function(e){
|
||||
console.log(e.status);
|
||||
console.log(e.responseText);
|
||||
alert(e.status+'\n'+e.responseText);
|
||||
}
|
||||
});
|
||||
}
|
3
misc/acrn-config/config_app/static/styles.css
Normal file
3
misc/acrn-config/config_app/static/styles.css
Normal file
@ -0,0 +1,3 @@
|
||||
ul.nav li.dropdown:hover ul.dropdown-menu {
|
||||
display: block;
|
||||
}
|
105
misc/acrn-config/config_app/templates/base.html
Normal file
105
misc/acrn-config/config_app/templates/base.html
Normal file
@ -0,0 +1,105 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
|
||||
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.10.0/css/bootstrap-select.min.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.10.0/js/bootstrap-select.min.js"></script>
|
||||
<link href="../static/styles.css" rel="stylesheet" type="text/css">
|
||||
<script src="../static/main.js" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-inverse">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="{{ url_for('CONFIG_APP.scenarios') }}">ACRN Config</a>
|
||||
</div>
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="dropdown">
|
||||
<a href="{{ url_for('CONFIG_APP.scenarios') }}">
|
||||
Scenario Setting <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{% if scenarios[0] %}
|
||||
<small class="text-muted">default</small>
|
||||
{% for sc in scenarios[0] %}
|
||||
<li><a href="{{ url_for('CONFIG_APP.scenario', scenario_name=sc) }}">{{sc}}</a></li>
|
||||
{% endfor %}
|
||||
<small class="text-muted">user-defined</small>
|
||||
{% for sc in scenarios[1] %}
|
||||
<li><a href="{{ url_for('CONFIG_APP.scenario', scenario_name='user_defined_'+sc) }}">{{sc}}</a></li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<text class="form-control" id="err_msg" data-toggle="tooltip"
|
||||
title="No board selected or not supported board">No Setting
|
||||
</text>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="{{ url_for('CONFIG_APP.launches') }}">Launch Setting <span
|
||||
class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
{% if launches[0] %}
|
||||
<small class="text-muted">default</small>
|
||||
{% for lc in launches[0] %}
|
||||
<li><a href="{{ url_for('CONFIG_APP.launch', launch_name=lc) }}">{{lc}}</a></li>
|
||||
{% endfor %}
|
||||
<small class="text-muted">user-defined</small>
|
||||
{% for lc in launches[1] %}
|
||||
<li><a href="{{ url_for('CONFIG_APP.launch', launch_name='user_defined_'+lc) }}">{{lc}}</a></li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<text class="form-control" id="err_msg" data-toggle="tooltip"
|
||||
title="No board selected or not supported board">No Setting
|
||||
</text>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<form action="" enctype="multipart/form-data" method='POST'>
|
||||
<div class="form-group">
|
||||
<label for="board_info" class="col-sm-1 control-label" style="text-align: left;">Board info:</label>
|
||||
<div class="col-sm-3">
|
||||
<div class="dropdown">
|
||||
<select class="selectpicker" id="board_info">
|
||||
<option style="display:none">
|
||||
{% for bi in board_info_list %}
|
||||
{% if bi==board_info %}
|
||||
<option value="{{bi}}" selected="selected">{{bi}}</option>
|
||||
{% else %}
|
||||
<option value="{{bi}}">{{bi}}</option>
|
||||
{% endif%}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<text class="col-sm-2" id="board_type">{{board_type if board_type != None else ''}}</text>
|
||||
<div class="col-sm-6">
|
||||
<form action="" enctype="multipart/form-data" method='POST'>
|
||||
<label for="board_info_file" class="custom-file-upload btn btn-primary" id="board_info_file2"
|
||||
style="border: 1px solid #ccc; display: inline-block; padding: 6px 12px;
|
||||
cursor: pointer; border-radius:5px; ">
|
||||
Import Board info</label>
|
||||
<input type="file" name="file" id="board_info_file" class="col-sm-6 btn btn-primary"
|
||||
style="display: none;">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr class="col-sm-12">
|
||||
|
||||
{% block body_content %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
310
misc/acrn-config/config_app/templates/launch.html
Normal file
310
misc/acrn-config/config_app/templates/launch.html
Normal file
@ -0,0 +1,310 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block body_content %}
|
||||
|
||||
<div class="modal fade" id="save_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title" id="myModalLabel">Save as</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="new_launch_name" class="col-sm-3 control-label">Launch: </label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" id="new_launch_name"
|
||||
value={{launch[13:] if launch.startswith('user_defined_') else launch}}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" id="remove_launch" class="btn btn-default" data-dismiss="modal">Remove</button>
|
||||
<button type="button" id="save_launch" data-id="" class="btn btn-primary" data-dismiss="modal">Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="form-horizontal" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label for="old_launch_name" class="col-sm-2 control-label" style="text-align: left;"> Launch
|
||||
Setting:</label>
|
||||
<div class="col-sm-3">
|
||||
<text class="form-control" id="old_launch_name" readonly>{{launch}}</text>
|
||||
</div>
|
||||
<div class="col-sm-1 col-sm-offset-1">
|
||||
{% if board_info != None %}
|
||||
<label for="launch_file" class="btn btn-primary" id="scenario_file2"
|
||||
style="border: 1px solid #ccc; display: inline-block; padding: 6px 12px;
|
||||
cursor: pointer; border-radius:5px; ">
|
||||
Import</label>
|
||||
<input type="file" name="file" id="launch_file" class="col-sm-1 btn btn-primary" style="display: none;">
|
||||
{% else %}
|
||||
<label class="btn"
|
||||
style="border: 1px solid #ccc; display: inline-block; padding: 6px 12px;
|
||||
cursor: pointer; border-radius:5px; ">
|
||||
Import</label>
|
||||
<input type="file" name="file" class="col-sm-1" style="display: none;" disabled>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if board_info != None and root != None %}
|
||||
<div class="col-sm-1">
|
||||
<button type="button" class="btn btn-primary" data-id="save" data-toggle="modal" data-target="#save_modal">
|
||||
Export
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-1">
|
||||
<button type="button" id="generate_launch_script" class="btn btn-primary" data-id="generate_launch_script"
|
||||
data-toggle="modal" data-target="#save_modal">Generate Launch Script
|
||||
</button>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-sm-1">
|
||||
<button type="button" disabled class="btn btn-primary">Export</button>
|
||||
</div>
|
||||
<div class="col-sm-1">
|
||||
<button type="button" disabled class="btn btn-primary">Generate Launch Script</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="scenario_name" class="col-sm-2 control-label" style="text-align: left;"> Select
|
||||
Scenario:</label>
|
||||
<div class="dropdown col-sm-9">
|
||||
<select class="selectpicker" data-width="auto" id="scenario_name">
|
||||
<option style="display:none">
|
||||
{% for sc in scenarios[0] %}
|
||||
{% if root != None and root.attrib['scenario'] == sc %}
|
||||
<option value="{{sc}}" selected>{{sc}}</option>
|
||||
{% else %}
|
||||
<option value="{{sc}}">{{sc}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for sc in scenarios[1] %}
|
||||
{% if root !=None and root.attrib['scenario'] == 'user_defined_'+sc%}
|
||||
<option value="{{'user_defined_'+sc}}" selected>{{'user_defined_'+sc}}</option>
|
||||
{% else %}
|
||||
<option value="{{'user_defined_'+sc}}">{{'user_defined_'+sc}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if board_info != None and root != None %}
|
||||
<table class="table table-hover" id="tab">
|
||||
{% for vm in root.getchildren() %}
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">UOS: </label>
|
||||
<label class="col-sm-1 control-label" id="vm">{{vm.attrib['id']}}</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{% for elem in vm.getchildren() %}
|
||||
{% if elem.getchildren() == [] and ('configurable' not in elem.attrib or elem.attrib['configurable'] !=
|
||||
'0') %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
title="{{elem.attrib['desc'] if 'desc' in elem.attrib else elem.tag}}">{{elem.tag}}</label>
|
||||
<label class="col-sm-2 control-label"></label>
|
||||
{% set elem_text = '' if elem.text == None else elem.text %}
|
||||
{% if ','.join(['uos', elem.tag]) not in launch_item_values %}
|
||||
<div class="col-sm-6">
|
||||
{% if 'readonly' in elem.attrib and elem.attrib['readonly'] == 'true' %}
|
||||
{% if elem.tag == 'kernel_cmdline' %}
|
||||
<textarea type="text" class="form-control"
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag}}" readonly>{{elem_text}}</textarea>
|
||||
{% else %}
|
||||
<input type="text" class="form-control"
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag}}" value="{{elem_text}}" readonly/>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if elem.tag == 'kernel_cmdline' %}
|
||||
<textarea type="text" class="form-control" style="height:120px"
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag}}">{{elem_text}}</textarea>
|
||||
{% else %}
|
||||
<input type="text" class="form-control" value="{{elem_text}}"
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag}}"/>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="dropdown col-sm-9">
|
||||
{% if 'readonly' in elem.attrib and elem.attrib['readonly'] == 'true' %}
|
||||
<select class="selectpicker" data-width="auto" title="" disabled
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag}}">
|
||||
{% else %}
|
||||
<select class="selectpicker" data-width="auto" title=""
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag}}">
|
||||
{% endif %}
|
||||
{% for item_value in launch_item_values[','.join(['uos', elem.tag])] %}
|
||||
{% if item_value == elem_text %}
|
||||
<option value="{{item_value}}" selected="selected">{{item_value}}</option>
|
||||
{% else %}
|
||||
<option value="{{item_value}}">{{item_value}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% elif elem.getchildren() != [] %}
|
||||
{% if 'multiselect' not in elem.attrib or elem.attrib['multiselect'] != 'true' %}
|
||||
{% set first_child = [] %}
|
||||
{% for sub_elem in elem.getchildren() %}
|
||||
{% set sub_elem_text = '' if sub_elem.text == None else sub_elem.text %}
|
||||
{% if 'configurable' not in sub_elem.attrib or sub_elem.attrib['configurable'] != '0' %}
|
||||
<div class="form-group">
|
||||
{% if 'id' not in elem.attrib %}
|
||||
{% if not first_child %}
|
||||
{% do first_child.append(1) %}
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
{{elem.tag}}</label>
|
||||
{% else %}
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
<label class="col-sm-2 control-label" data-toggle="tooltip"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
{{sub_elem.tag}}</label>
|
||||
|
||||
{% if ','.join(['uos', elem.tag, sub_elem.tag]) not in launch_item_values %}
|
||||
<div class="col-sm-6">
|
||||
{% if 'readonly' in sub_elem.attrib and sub_elem.attrib['readonly'] == 'true' %}
|
||||
<input type="text" class="form-control" readonly
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}"
|
||||
value="{{sub_elem_text}}">
|
||||
{% else %}
|
||||
<input type="text" class="form-control"
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}"
|
||||
value="{{sub_elem_text}}">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="dropdown col-sm-9">
|
||||
{% if 'readonly' in sub_elem.attrib and sub_elem.attrib['readonly'] == 'true' %}
|
||||
<select class="selectpicker" data-width="auto" disabled
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}">
|
||||
{% else %}
|
||||
<select class="selectpicker" data-width="auto"
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}">
|
||||
{% endif %}
|
||||
{% for item_value in launch_item_values[','.join(['uos', elem.tag, sub_elem.tag])] %}
|
||||
{% if item_value == sub_elem_text %}
|
||||
<option value="{{item_value}}" selected="selected">{{item_value}}</option>
|
||||
{% else %}
|
||||
<option value="{{item_value}}">{{item_value}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if not first_child %}
|
||||
{% do first_child.append(1) %}
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
{{elem.tag+' '+elem.attrib['id']}}</label>
|
||||
{% else %}
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
<label class="col-sm-2 control-label" data-toggle="tooltip"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
{{sub_elem.tag}}</label>
|
||||
|
||||
{% if ','.join(['uos', elem.tag, sub_elem.tag]) not in launch_item_values %}
|
||||
<div class="col-sm-6">
|
||||
{% if 'readonly' in sub_elem.attrib and sub_elem.attrib['readonly'] == 'true' %}
|
||||
<input type="text" class="form-control" readonly
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}"
|
||||
value="{{sub_elem_text}}">
|
||||
{% else %}
|
||||
<input type="text" class="form-control"
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}"
|
||||
value="{{sub_elem_text}}">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="dropdown col-sm-9">
|
||||
{% if 'readonly' in sub_elem.attrib and sub_elem.attrib['readonly'] == 'true' %}
|
||||
<select class="selectpicker" data-width="auto" disabled
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}">
|
||||
{% else %}
|
||||
<select class="selectpicker" data-width="auto"
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}">
|
||||
{% endif %}
|
||||
{% for item_value in launch_item_values[','.join(['uos', elem.tag, sub_elem.tag])] %}
|
||||
{% if item_value == sub_elem_text %}
|
||||
<option value="{{item_value}}" selected="selected">{{item_value}}</option>
|
||||
{% else %}
|
||||
<option value="{{item_value}}">{{item_value}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% elif 'configurable' not in elem.attrib or elem.attrib['configurable'] != '0' %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
title="{{elem.attrib['desc'] if 'desc' in elem.attrib else elem.tag}}">{{elem.tag}}</label>
|
||||
<label class="col-sm-2 control-label" data-toggle="tooltip"
|
||||
title="{{elem.attrib['desc'] if 'desc' in elem.attrib else elem.tag}}"></label>
|
||||
<div class="dropdown col-sm-9">
|
||||
{% if 'readonly' in elem.attrib and elem.attrib['readonly'] == 'true' %}
|
||||
<select class="selectpicker" data-width="auto" disabled
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag+','+elem.tag[:-1]}}" multiple>
|
||||
{% else %}
|
||||
<select class="selectpicker" data-width="auto" disabled
|
||||
id="{{'uos:id='+vm.attrib['id']+','+elem.tag+','+elem.tag[:-1]}}" multiple>
|
||||
{% endif %}
|
||||
{% if ','.join(['uos', elem.tag]) not in launch_item_values %}
|
||||
{% set x=1 %}
|
||||
{% for sub_elem in elem.getchildren() %}
|
||||
<option value="{{sub_elem.text}}" selected="selected">{{sub_elem.text}}</option>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% set selected_list = [] %}
|
||||
{% for sub_elem in elem.getchildren() %}
|
||||
{% do selected_list.append(sub_elem.text) %}
|
||||
{% endfor %}
|
||||
{% for item_value in launch_item_values[','.join(['uos', elem.tag])] %}
|
||||
{% if item_value in selected_list %}
|
||||
<option value="{{item_value}}" selected="selected">{{item_value}}</option>
|
||||
{% else %}
|
||||
<option value="{{item_value}}">{{item_value}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<text class="form-control" id="err_msg">No setting available. Select one board info and make sure the launch xml
|
||||
exists.
|
||||
</text>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
322
misc/acrn-config/config_app/templates/scenario.html
Normal file
322
misc/acrn-config/config_app/templates/scenario.html
Normal file
@ -0,0 +1,322 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block body_content %}
|
||||
|
||||
<div class="modal fade" id="save_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title" id="myModalLabel">Save as</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="new_scenario_name" class="col-sm-3 control-label">Scenario: </label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control" id="new_scenario_name"
|
||||
value={{ scenario[13:] if scenario.startswith('user_defined_') else scenario }}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" id="remove_scenario" class="btn btn-default" data-dismiss="modal">Remove</button>
|
||||
<button type="button" id="save_scenario" data-id="" class="btn btn-primary" data-dismiss="modal">Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="form-horizontal" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label for="old_scenario_name" class="col-sm-2 control-label" style="text-align: left;"> Scenario
|
||||
Setting:</label>
|
||||
<div class="col-sm-3">
|
||||
<text class="form-control" id="old_scenario_name" readonly>{{scenario}}</text>
|
||||
</div>
|
||||
<div class="col-sm-1 col-sm-offset-1">
|
||||
{% if board_info != None %}
|
||||
<label for="scenario_file" class="btn btn-primary" id="scenario_file2"
|
||||
style="border: 1px solid #ccc; display: inline-block; padding: 6px 12px;
|
||||
cursor: pointer; border-radius:5px; ">
|
||||
Import</label>
|
||||
<input type="file" name="file" id="scenario_file" class="col-sm-1 btn btn-primary" style="display: none;">
|
||||
{% else %}
|
||||
<label for="scenario_file" class="btn"
|
||||
style="border: 1px solid #ccc; display: inline-block; padding: 6px 12px;
|
||||
cursor: pointer; border-radius:5px; ">
|
||||
Import</label>
|
||||
<input type="file" name="file" class="col-sm-1" style="display: none;" disabled>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if board_info != None and root != None and scenario_item_values %}
|
||||
<div class="col-sm-1">
|
||||
<button type="button" data-id="save" class="btn btn-primary" data-toggle="modal" data-target="#save_modal">
|
||||
Export
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button type="button" id="generate_board_src" data-id="generate_board_src" class="btn btn-primary"
|
||||
data-toggle="modal" data-target="#save_modal">Generate Board SRC
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button type="button" id="generate_scenario_src" data-id="generate_scenario_src" class="btn btn-primary"
|
||||
data-toggle="modal" data-target="#save_modal">Generate Scenario SRC
|
||||
</button>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-sm-1">
|
||||
<button type="button" disabled class="btn btn-primary" data-toggle="modal" data-target="#save_modal">
|
||||
Export
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button type="button" disabled class="btn btn-primary" data-toggle="modal" data-target="#save_modal">
|
||||
Generate Board SRC
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button type="button" disabled class="btn btn-primary" data-toggle="modal" data-target="#save_modal">
|
||||
Generate Scenario SRC
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if board_info != None and root != None and scenario_item_values %}
|
||||
<table class="table table-hover" id="tab">
|
||||
{% for vm in root.getchildren() %}
|
||||
{% if 'configurable' not in vm.attrib or vm.attrib['configurable'] != '0'%}
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-1 control-label">VM: </label>
|
||||
<label class="col-sm-1 control-label" id="vm">{{vm.attrib['id']}}</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{% for elem in vm.getchildren() %}
|
||||
{% set elem_text = elem.text if elem.text != None else '' %}
|
||||
{% if elem.getchildren() == [] and ('configurable' not in elem.attrib or elem.attrib['configurable']
|
||||
!= '0')%}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
title="{{elem.attrib['desc'] if 'desc' in elem.attrib else elem.tag}}">{{elem.tag}}</label>
|
||||
<label class="col-sm-2 control-label"></label>
|
||||
|
||||
{% if ','.join(['vm', elem.tag]) not in scenario_item_values %}
|
||||
<div class="col-sm-6">
|
||||
{% if 'readonly' in elem.attrib and elem.attrib['readonly'] == 'true' %}
|
||||
<input type="text" class="form-control" id="{{'vm:id='+vm.attrib['id']+','+elem.tag}}"
|
||||
value="{{elem_text}}" readonly>
|
||||
{% else %}
|
||||
<input type="text" class="form-control" id="{{'vm:id='+vm.attrib['id']+','+elem.tag}}"
|
||||
value="{{elem_text}}">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="dropdown col-sm-6">
|
||||
{% if 'readonly' in elem.attrib and elem.attrib['readonly'] == 'true' %}
|
||||
<select class="selectpicker" data-width="auto"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag}}" disabled>
|
||||
{% else %}
|
||||
<select class="selectpicker" data-width="auto"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag}}">
|
||||
{% endif %}
|
||||
{% for item_value in scenario_item_values[','.join(['vm', elem.tag])] %}
|
||||
{% if item_value == elem_text %}
|
||||
<option value="{{item_value}}" selected="selected">{{item_value}}</option>
|
||||
{% else %}
|
||||
<option value="{{item_value}}">{{item_value}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
||||
<p id="{{'vm:id='+vm.attrib['id']+','+elem.tag}}_err" class="col-sm-3"></p>
|
||||
</div>
|
||||
{% elif elem.getchildren() != [] and ('configurable' not in elem.attrib or elem.attrib['configurable']
|
||||
!= '0')%}
|
||||
{% if 'multiselect' not in elem.attrib or elem.attrib['multiselect'] != 'true' %}
|
||||
{% set first_child = [] %}
|
||||
{% for sub_elem in elem.getchildren() %}
|
||||
{% set sub_elem_text = sub_elem.text if sub_elem.text != None else '' %}
|
||||
{% if 'configurable' not in sub_elem.attrib or sub_elem.attrib['configurable'] != '0' %}
|
||||
<div class="form-group">
|
||||
{% if 'id' not in elem.attrib %}
|
||||
{% if not first_child %}
|
||||
{% do first_child.append(1) %}
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
{{elem.tag}}</label>
|
||||
{% else %}
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
<label class="col-sm-2 control-label" data-toggle="tooltip"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
{{sub_elem.tag}}</label>
|
||||
{% if ','.join(['vm', elem.tag, sub_elem.tag]) not in scenario_item_values %}
|
||||
{% if sub_elem.tag in ['bootargs', 'kern_args'] %}
|
||||
<div class="col-sm-6">
|
||||
{% if 'readonly' in sub_elem.attrib and sub_elem.attrib['readonly'] == 'true' %}
|
||||
<textarea type="text" class="form-control" style="height:120px"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}"
|
||||
readonly>{{sub_elem_text}}</textarea>
|
||||
{% else %}
|
||||
<textarea type="text" class="form-control" style="height:120px"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}">
|
||||
{{sub_elem_text}}</textarea>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-sm-6">
|
||||
{% if 'readonly' in sub_elem.attrib and sub_elem.attrib['readonly'] == 'true' %}
|
||||
<input type="text" class="form-control"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}"
|
||||
value="{{sub_elem_text}}" readonly>
|
||||
{% else %}
|
||||
<input type="text" class="form-control"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}"
|
||||
value="{{sub_elem_text}}">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="dropdown col-sm-6">
|
||||
{% if 'readonly' in sub_elem.attrib and sub_elem.attrib['readonly'] == 'true' %}
|
||||
<select class="selectpicker" data-width="auto"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}" disabled>
|
||||
{% else %}
|
||||
<select class="selectpicker" data-width="auto"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}">
|
||||
{% endif %}
|
||||
{% for item_value in scenario_item_values[','.join(['vm', elem.tag, sub_elem.tag])] %}
|
||||
{% if item_value == sub_elem_text %}
|
||||
<option value="{{item_value}}" selected="selected">{{item_value}}</option>
|
||||
{% else %}
|
||||
<option value="{{item_value}}">{{item_value}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
||||
<p id="{{'vm:id='+vm.attrib['id']+','+elem.tag+','+sub_elem.tag}}_err" class="col-sm-3"></p>
|
||||
{% else %}
|
||||
{% if not first_child %}
|
||||
{% do first_child.append(1) %}
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}_label1"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
{{elem.tag+' '+elem.attrib['id']}}</label>
|
||||
{% else %}
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}_label1"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
</label>
|
||||
{% endif %}
|
||||
|
||||
<label class="col-sm-2 control-label" data-toggle="tooltip"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}_label2"
|
||||
title="{{sub_elem.attrib['desc'] if 'desc' in sub_elem.attrib else sub_elem.tag}}">
|
||||
{{sub_elem.tag}}</label>
|
||||
{% if (','.join(['vm', elem.tag, sub_elem.tag]) not in scenario_item_values) and
|
||||
(elem.tag!='vuart' or sub_elem.tag!='base') %}
|
||||
<div class="col-sm-6"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}_config">
|
||||
{% if 'readonly' in sub_elem.attrib and sub_elem.attrib['readonly'] == 'true' %}
|
||||
<input type="text" class="form-control"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}"
|
||||
value="{{sub_elem_text}}" readonly>
|
||||
{% else %}
|
||||
<input type="text" class="form-control"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}"
|
||||
value="{{sub_elem_text}}">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="dropdown col-sm-6">
|
||||
{% if 'readonly' in sub_elem.attrib and sub_elem.attrib['readonly'] == 'true' %}
|
||||
<select class="selectpicker" data-width="auto" disabled
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}">
|
||||
{% else %}
|
||||
<select class="selectpicker" data-width="auto"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}">
|
||||
{% endif %}
|
||||
{% set key = ('vm='+vm.attrib['id']+','+elem.tag+'='+elem.attrib['id']+','+sub_elem.tag)
|
||||
if (elem.tag=='vuart' and sub_elem.tag=='base')
|
||||
else ','.join(['vm', elem.tag, sub_elem.tag]) %}
|
||||
{% for item_value in scenario_item_values[key] %}
|
||||
{% if item_value == sub_elem_text %}
|
||||
<option value="{{item_value}}" selected="selected">{{item_value}}</option>
|
||||
{% else %}
|
||||
<option value="{{item_value}}">{{item_value}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
||||
<p id="{{'vm:id='+vm.attrib['id']+','+elem.tag+':id='+elem.attrib['id']+','+sub_elem.tag}}_err"
|
||||
class="col-sm-3"></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% elif 'configurable' not in elem.attrib or elem.attrib['configurable'] != '0' %}
|
||||
<div class="form-group">
|
||||
<label class="col-sm-1 control-label" data-toggle="tooltip"
|
||||
title="{{elem.attrib['desc'] if 'desc' in elem.attrib else elem.tag}}">{{elem.tag}}</label>
|
||||
<label class="col-sm-2 control-label" data-toggle="tooltip"
|
||||
title="{{elem.attrib['desc'] if 'desc' in elem.attrib else elem.tag}}"></label>
|
||||
<div class="dropdown col-sm-6">
|
||||
{% if 'readonly' in elem.attrib and elem.attrib['readonly'] == 'true' %}
|
||||
<select class="selectpicker" data-width="auto" disabled
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+','+elem.tag[:-1]}}"
|
||||
multiple>
|
||||
{% else %}
|
||||
<select class="selectpicker" data-width="auto"
|
||||
id="{{'vm:id='+vm.attrib['id']+','+elem.tag+','+elem.tag[:-1]}}"
|
||||
multiple>
|
||||
{% endif %}
|
||||
{% if ','.join(['vm', elem.tag]) not in scenario_item_values %}
|
||||
{% set x=1 %}
|
||||
{% for sub_elem in elem.getchildren() %}
|
||||
<option value="{{sub_elem.text}}" selected="selected">{{sub_elem.text}}</option>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% set selected_list = [] %}
|
||||
{% for sub_elem in elem.getchildren() %}
|
||||
{% do selected_list.append(sub_elem.text) %}
|
||||
{% endfor %}
|
||||
{% for item_value in scenario_item_values[','.join(['vm', elem.tag])] %}
|
||||
{% if item_value in selected_list %}
|
||||
<option value="{{item_value}}" selected="selected">{{item_value}}</option>
|
||||
{% else %}
|
||||
<option value="{{item_value}}">{{item_value}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</select>
|
||||
</div>
|
||||
<p id="{{'vm:id='+vm.attrib['id']+','+elem.tag+','+elem.tag[:-1]}}_err" class="col-sm-3"></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<text class="form-control" id="err_msg">No setting available. Select one board info and make sure the scenario xml
|
||||
exists.
|
||||
</text>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
672
misc/acrn-config/config_app/views.py
Normal file
672
misc/acrn-config/config_app/views.py
Normal file
@ -0,0 +1,672 @@
|
||||
# Copyright (C) 2019 Intel Corporation.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
"""View pages for config app.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
from datetime import datetime
|
||||
from shutil import copyfile
|
||||
|
||||
# flask: Copyright 2010 Pallets
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Refer to https://github.com/pallets/flask/blob/master/LICENSE.rst for the permission notice.
|
||||
from flask import request, render_template, Blueprint, redirect, url_for, current_app
|
||||
|
||||
# werkzeug: Copyright 2007 Pallets
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Refer to https://github.com/pallets/werkzeug/blob/master/LICENSE.rst for the permission notice.
|
||||
from werkzeug.utils import secure_filename
|
||||
|
||||
from controller import XmlConfig
|
||||
from scenario_config.scenario_cfg_gen import get_scenario_item_values
|
||||
from scenario_config.scenario_cfg_gen import validate_scenario_setting
|
||||
from launch_config.launch_cfg_gen import get_launch_item_values
|
||||
from launch_config.launch_cfg_gen import validate_launch_setting
|
||||
|
||||
|
||||
CONFIG_APP = Blueprint('CONFIG_APP', __name__, template_folder='templates')
|
||||
|
||||
|
||||
@CONFIG_APP.route('/')
|
||||
def index():
|
||||
"""
|
||||
render the index page
|
||||
:return: the render template of index page
|
||||
"""
|
||||
return redirect(url_for('CONFIG_APP.scenarios'))
|
||||
|
||||
|
||||
@CONFIG_APP.route('/scenario', methods=['GET'])
|
||||
def scenarios():
|
||||
"""
|
||||
render the scenario parent setting page
|
||||
:return: the render template of scenario setting parent page
|
||||
"""
|
||||
board_info, board_type, scenario_config, launch_config = get_xml_configs()
|
||||
print(board_info, scenario_config, launch_config)
|
||||
|
||||
return render_template('scenario.html', board_info_list=get_board_list(),
|
||||
board_info=board_info, board_type=board_type,
|
||||
scenarios=scenario_config.list_all(xml_type='scenario'),
|
||||
launches=launch_config.list_all(xml_type='uos_launcher'),
|
||||
scenario='', root=None)
|
||||
|
||||
|
||||
@CONFIG_APP.route('/scenario/<scenario_name>', methods=['GET'])
|
||||
def scenario(scenario_name):
|
||||
"""
|
||||
render the specified scenario setting page
|
||||
:param scenario_name: the scenario type
|
||||
:return: the render template of the specified scenario setting page
|
||||
"""
|
||||
|
||||
board_info, board_type, scenario_config, launch_config = \
|
||||
get_xml_configs(scenario_name.startswith('user_defined_'))
|
||||
print(board_info, scenario_config, launch_config)
|
||||
current_app.config.update(SCENARIO=scenario_name)
|
||||
|
||||
if scenario_name.startswith('user_defined_'):
|
||||
scenario_config.set_curr(scenario_name[13:])
|
||||
else:
|
||||
scenario_config.set_curr(scenario_name)
|
||||
|
||||
scenario_item_values = {}
|
||||
if board_info is not None and board_type is not None:
|
||||
scenario_file_path = os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
board_type, scenario_name + '.xml')
|
||||
if scenario_name.startswith('user_defined_'):
|
||||
scenario_file_path = os.path.join(current_app.config.get('CONFIG_PATH'), board_type,
|
||||
'user_defined', scenario_name[13:] + '.xml')
|
||||
if os.path.isfile(scenario_file_path):
|
||||
scenario_item_values = get_scenario_item_values(
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res', board_info+'.xml'),
|
||||
scenario_file_path)
|
||||
|
||||
print('scenario_item_values: ', scenario_item_values)
|
||||
|
||||
return render_template('scenario.html', board_info_list=get_board_list(),
|
||||
board_info=board_info, board_type=board_type,
|
||||
scenarios=scenario_config.list_all(xml_type='scenario'),
|
||||
launches=launch_config.list_all(xml_type='uos_launcher'),
|
||||
scenario=scenario_name, root=scenario_config.get_curr_root(),
|
||||
scenario_item_values=scenario_item_values)
|
||||
|
||||
|
||||
@CONFIG_APP.route('/launch', methods=['GET'])
|
||||
def launches():
|
||||
"""
|
||||
render the parent launch setting page
|
||||
:return: the render template of launch setting page
|
||||
"""
|
||||
board_info, board_type, scenario_config, launch_config = get_xml_configs()
|
||||
print(board_info, scenario_config, launch_config)
|
||||
|
||||
return render_template('launch.html', board_info_list=get_board_list(),
|
||||
board_info=board_info, board_type=board_type,
|
||||
scenarios=scenario_config.list_all(xml_type='scenario'),
|
||||
launches=launch_config.list_all(xml_type='uos_launcher'),
|
||||
launch='', root=None)
|
||||
|
||||
|
||||
@CONFIG_APP.route('/launch/<launch_name>', methods=['GET'])
|
||||
def launch(launch_name):
|
||||
"""
|
||||
render the specified launch setting page
|
||||
:param launch_name: the launch type
|
||||
:return: the render template of specified launch setting page
|
||||
"""
|
||||
print('launch: ', launch_name)
|
||||
board_info, board_type, scenario_config, launch_config = \
|
||||
get_xml_configs(launch_name.startswith('user_defined_'))
|
||||
print(board_info, scenario_config, launch_config)
|
||||
|
||||
if launch_name.startswith('user_defined_'):
|
||||
launch_config.set_curr(launch_name[13:])
|
||||
else:
|
||||
launch_config.set_curr(launch_name)
|
||||
|
||||
launch_item_values = {}
|
||||
if board_info is not None:
|
||||
launch_item_values = get_launch_item_values(
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res', board_info + '.xml'))
|
||||
|
||||
print('launch_item_values: ', launch_item_values)
|
||||
|
||||
return render_template('launch.html', board_info_list=get_board_list(),
|
||||
board_info=board_info, board_type=board_type,
|
||||
scenarios=scenario_config.list_all(xml_type='scenario'),
|
||||
launches=launch_config.list_all(xml_type='uos_launcher'),
|
||||
launch=launch_name, root=launch_config.get_curr_root(),
|
||||
scenario=current_app.config.get('SCENARIO'),
|
||||
launch_item_values=launch_item_values)
|
||||
|
||||
|
||||
@CONFIG_APP.route('/save_scenario', methods=['POST'])
|
||||
def save_scenario():
|
||||
"""
|
||||
save scenario setting.
|
||||
:return: the error list for the edited scenario setting.
|
||||
"""
|
||||
scenario_config_data = request.json if request.method == "POST" else request.args
|
||||
print("save_scenario")
|
||||
print(scenario_config_data)
|
||||
|
||||
xml_configs = \
|
||||
get_xml_configs(scenario_config_data['old_scenario_name'].startswith('user_defined_'))
|
||||
board_type = xml_configs[1]
|
||||
scenario_config = xml_configs[3]
|
||||
|
||||
if board_type is None or xml_configs[0] is None:
|
||||
return {'status': 'fail',
|
||||
'error_list': {'error': 'Please select the board info before this operation.'}}
|
||||
|
||||
scenario_path = os.path.join(current_app.config.get('CONFIG_PATH'), board_type)
|
||||
old_scenario_name = scenario_config_data['old_scenario_name']
|
||||
if scenario_config_data['old_scenario_name'].startswith('user_defined_'):
|
||||
old_scenario_name = scenario_config_data['old_scenario_name'][13:]
|
||||
scenario_config.set_curr(old_scenario_name)
|
||||
for key in scenario_config_data:
|
||||
if key not in ['old_scenario_name', 'new_scenario_name', 'board_info_file',
|
||||
'board_info_upload']:
|
||||
if isinstance(scenario_config_data[key], list):
|
||||
scenario_config.set_curr_list(scenario_config_data[key], *tuple(key.split(',')))
|
||||
else:
|
||||
scenario_config.set_curr_value(scenario_config_data[key], *tuple(key.split(',')))
|
||||
|
||||
tmp_scenario_file = os.path.join(scenario_path, 'user_defined',
|
||||
'tmp_'+scenario_config_data['new_scenario_name']+'.xml')
|
||||
# if os.path.isfile(tmp_scenario_file):
|
||||
# os.remove(tmp_scenario_file)
|
||||
scenario_config.save('tmp_'+scenario_config_data['new_scenario_name'])
|
||||
|
||||
# call validate function
|
||||
error_list = {}
|
||||
new_scenario_name = scenario_config_data['new_scenario_name']
|
||||
rename = False
|
||||
try:
|
||||
(error_list, vm_info) = validate_scenario_setting(
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res', xml_configs[0]+'.xml'),
|
||||
tmp_scenario_file)
|
||||
print('vm_info: ', vm_info)
|
||||
except Exception as error:
|
||||
return {'status': 'fail', 'file_name': new_scenario_name,
|
||||
'rename': rename, 'error_list': {'error': str(error)}}
|
||||
|
||||
print('error_list: ', error_list)
|
||||
|
||||
if not error_list:
|
||||
old_scenario_path = os.path.join(scenario_path, old_scenario_name + '.xml')
|
||||
if scenario_config_data['old_scenario_name'].startswith('user_defined_'):
|
||||
old_scenario_path = os.path.join(scenario_path, 'user_defined',
|
||||
old_scenario_name + '.xml')
|
||||
|
||||
# check name conflict
|
||||
new_scenario_path = os.path.join(scenario_path, 'user_defined',
|
||||
scenario_config_data['new_scenario_name']+'.xml')
|
||||
if old_scenario_path != new_scenario_path and os.path.isfile(new_scenario_path):
|
||||
new_scenario_name = new_scenario_name + '_' + datetime.now().strftime('%Y%m%d%H%M%S')
|
||||
rename = True
|
||||
|
||||
if os.path.isfile(old_scenario_path) \
|
||||
and scenario_config_data['old_scenario_name'].startswith('user_defined_'):
|
||||
os.remove(old_scenario_path)
|
||||
scenario_config.save(new_scenario_name)
|
||||
|
||||
if os.path.isfile(tmp_scenario_file):
|
||||
os.remove(tmp_scenario_file)
|
||||
|
||||
return {'status': 'success', 'file_name': new_scenario_name,
|
||||
'rename': rename, 'error_list': error_list}
|
||||
|
||||
|
||||
@CONFIG_APP.route('/save_launch', methods=['POST'])
|
||||
def save_launch():
|
||||
"""
|
||||
save launch setting.
|
||||
:return: the error list of the edited launch setting.
|
||||
"""
|
||||
launch_config_data = request.json if request.method == "POST" else request.args
|
||||
|
||||
xml_configs = \
|
||||
get_xml_configs(launch_config_data['old_launch_name'].startswith('user_defined_'))
|
||||
launch_config = xml_configs[3]
|
||||
|
||||
if xml_configs[1] is None or xml_configs[0] is None:
|
||||
return {'status': 'fail',
|
||||
'error_list': {'error': 'Please select the board info before this operation.'}}
|
||||
|
||||
old_launch_name = launch_config_data['old_launch_name']
|
||||
old_launch_path = os.path.join(current_app.config.get('CONFIG_PATH'), xml_configs[1],
|
||||
old_launch_name + '.xml')
|
||||
if launch_config_data['old_launch_name'].startswith('user_defined_'):
|
||||
old_launch_name = launch_config_data['old_launch_name'][13:]
|
||||
old_launch_path = os.path.join(current_app.config.get('CONFIG_PATH'), xml_configs[1],
|
||||
'user_defined', old_launch_name + '.xml')
|
||||
launch_config.set_curr(old_launch_name)
|
||||
|
||||
for key in launch_config_data:
|
||||
if key not in ['old_launch_name', 'new_launch_name', 'board_info_file',
|
||||
'board_info_upload', 'scenario_name']:
|
||||
if isinstance(launch_config_data[key], list):
|
||||
launch_config.set_curr_list(launch_config_data[key], *tuple(key.split(',')))
|
||||
else:
|
||||
launch_config.set_curr_value(launch_config_data[key], *tuple(key.split(',')))
|
||||
|
||||
scenario_name = launch_config_data['scenario_name']
|
||||
scenario_file_path = os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
current_app.config.get('BOARD_TYPE'), scenario_name + '.xml')
|
||||
if launch_config_data['scenario_name'].startswith('user_defined_'):
|
||||
scenario_name = launch_config_data['scenario_name'][13:]
|
||||
scenario_file_path = os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
current_app.config.get('BOARD_TYPE'),
|
||||
'user_defined', scenario_name + '.xml')
|
||||
launch_config.set_curr_attr('scenario', scenario_name)
|
||||
|
||||
tmp_launch_file = os.path.join(current_app.config.get('CONFIG_PATH'), xml_configs[1],
|
||||
'user_defined',
|
||||
'tmp_' + launch_config_data['new_launch_name'] + '.xml')
|
||||
# if os.path.isfile(tmp_launch_file):
|
||||
# os.remove(tmp_launch_file)
|
||||
launch_config.save('tmp_' + launch_config_data['new_launch_name'])
|
||||
|
||||
# call validate function
|
||||
rename = False
|
||||
try:
|
||||
(error_list, pthru_sel, dm_value) = validate_launch_setting(
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res', xml_configs[0]+'.xml'),
|
||||
scenario_file_path,
|
||||
tmp_launch_file)
|
||||
print(pthru_sel, dm_value)
|
||||
except Exception as error:
|
||||
return {'status': 'fail', 'file_name': launch_config_data['new_launch_name'],
|
||||
'rename': rename, 'error_list': {'launch config error': str(error)}}
|
||||
|
||||
print('error_list: ', error_list)
|
||||
|
||||
if not error_list:
|
||||
new_launch_path = os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
xml_configs[1], 'user_defined',
|
||||
launch_config_data['new_launch_name'] + '.xml')
|
||||
# check name conflict
|
||||
if old_launch_path != new_launch_path and os.path.isfile(new_launch_path):
|
||||
launch_config_data['new_launch_name'] = launch_config_data['new_launch_name'] \
|
||||
+ '_' + datetime.now().strftime('%Y%m%d%H%M%S')
|
||||
rename = True
|
||||
|
||||
if os.path.isfile(old_launch_path) \
|
||||
and launch_config_data['old_launch_name'].startswith('user_defined_'):
|
||||
os.remove(old_launch_path)
|
||||
launch_config.save(launch_config_data['new_launch_name'])
|
||||
|
||||
if os.path.isfile(tmp_launch_file):
|
||||
os.remove(tmp_launch_file)
|
||||
|
||||
return {'status': 'success', 'file_name': launch_config_data['new_launch_name'],
|
||||
'rename': rename, 'error_list': error_list}
|
||||
|
||||
|
||||
@CONFIG_APP.route('/remove_setting', methods=['POST'])
|
||||
def remove_setting():
|
||||
"""
|
||||
remove current setting from config app
|
||||
:return: the return message
|
||||
"""
|
||||
remove_config_data = request.json if request.method == "POST" else request.args
|
||||
print("*"*100+"remove_setting")
|
||||
print(remove_config_data)
|
||||
|
||||
old_setting_name = remove_config_data['old_setting_name']
|
||||
|
||||
if current_app.config.get('BOARD_TYPE') is None:
|
||||
return {'status': 'Board info not set before remove current setting'}
|
||||
|
||||
print(current_app.config.get('CONFIG_PATH'), current_app.config.get('BOARD_TYPE'))
|
||||
old_setting_path = os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
current_app.config.get('BOARD_TYPE'),
|
||||
old_setting_name+'.xml')
|
||||
if old_setting_name.startswith('user_defined_'):
|
||||
old_setting_path = os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
current_app.config.get('BOARD_TYPE'),
|
||||
'user_defined',
|
||||
old_setting_name[13:] + '.xml')
|
||||
|
||||
if os.path.isfile(old_setting_path):
|
||||
os.remove(old_setting_path)
|
||||
return {'status': 'success'}
|
||||
|
||||
|
||||
@CONFIG_APP.route('/generate_src', methods=['POST'])
|
||||
def generate_src():
|
||||
"""
|
||||
generate board src or scenario src
|
||||
:return: the error message
|
||||
"""
|
||||
generator_config_data = request.json if request.method == "POST" else request.args
|
||||
print("generate_src")
|
||||
print(generator_config_data)
|
||||
|
||||
src_type = generator_config_data['type']
|
||||
board_info = generator_config_data['board_info']
|
||||
board_type = current_app.config.get('BOARD_TYPE')
|
||||
board_info_xml = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
'res', board_info+'.xml')
|
||||
scenario_setting = generator_config_data['scenario_setting']
|
||||
scenario_setting_xml = os.path.join(current_app.config.get('CONFIG_PATH'), board_type,
|
||||
'user_defined', scenario_setting+'.xml')
|
||||
launch_setting_xml = None
|
||||
if 'launch_setting' in generator_config_data:
|
||||
launch_setting = generator_config_data['launch_setting']
|
||||
launch_setting_xml = os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
board_type, 'user_defined', launch_setting + '.xml')
|
||||
msg = {}
|
||||
error_list = {}
|
||||
status = 'success'
|
||||
if src_type == 'generate_board_src':
|
||||
try:
|
||||
from board_config.board_cfg_gen import ui_entry_api
|
||||
error_list = ui_entry_api(board_info_xml, scenario_setting_xml)
|
||||
except Exception as error:
|
||||
status = 'fail'
|
||||
error_list = {'board setting error': str(error)}
|
||||
elif src_type == 'generate_scenario_src':
|
||||
try:
|
||||
from scenario_config.scenario_cfg_gen import ui_entry_api
|
||||
error_list = ui_entry_api(board_info_xml, scenario_setting_xml)
|
||||
except Exception as error:
|
||||
status = 'fail'
|
||||
error_list = {'scenario setting error': str(error)}
|
||||
elif src_type == 'generate_launch_script':
|
||||
if scenario_setting.startswith('user_defined_'):
|
||||
scenario_setting = scenario_setting[13:]
|
||||
scenario_setting_xml = os.path.join(current_app.config.get('CONFIG_PATH'), board_type,
|
||||
'user_defined', scenario_setting + '.xml')
|
||||
else:
|
||||
scenario_setting_xml = os.path.join(current_app.config.get('CONFIG_PATH'), board_type,
|
||||
scenario_setting + '.xml')
|
||||
|
||||
try:
|
||||
from launch_config.launch_cfg_gen import ui_entry_api
|
||||
error_list = ui_entry_api(board_info_xml, scenario_setting_xml, launch_setting_xml)
|
||||
except Exception as error:
|
||||
status = 'fail'
|
||||
error_list = {'launch setting error': str(error)}
|
||||
else:
|
||||
status = 'fail'
|
||||
error_list = {'error': 'generator type not specified'}
|
||||
msg = {'status': status, 'error_list': error_list}
|
||||
print(msg)
|
||||
return msg
|
||||
|
||||
|
||||
@CONFIG_APP.route('/upload_board_info', methods=['POST'])
|
||||
def upload_board_info():
|
||||
"""
|
||||
upload board info xml file
|
||||
:return: the upload status
|
||||
"""
|
||||
if request.method == 'POST':
|
||||
if 'file' not in request.files:
|
||||
return {'status': 'Error: no file uploaded'}
|
||||
file = request.files['file']
|
||||
if file and '.' in file.filename and file.filename.rsplit('.', 1)[1] in ['xml']:
|
||||
filename = secure_filename(file.filename)
|
||||
tmp_filename = 'tmp_' + filename
|
||||
save_tmp_board_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
'res', tmp_filename)
|
||||
file.save(save_tmp_board_path)
|
||||
|
||||
board_type_list = []
|
||||
config_path = current_app.config.get('CONFIG_PATH')
|
||||
for config_name in os.listdir(config_path):
|
||||
if os.path.isdir(os.path.join(config_path, config_name)) \
|
||||
and config_name != 'generic':
|
||||
board_type_list.append(config_name)
|
||||
|
||||
res_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res')
|
||||
if not os.path.isdir(res_path):
|
||||
os.makedirs(res_path)
|
||||
|
||||
board_info_config = XmlConfig(res_path)
|
||||
board_info_config.set_curr(tmp_filename.rsplit('.', 1)[0])
|
||||
board_info_root = board_info_config.get_curr_root()
|
||||
board_type = None
|
||||
if board_info_root and 'board' in board_info_root.attrib \
|
||||
and 'scenario' not in board_info_root.attrib \
|
||||
and 'uos_launcher' not in board_info_root.attrib:
|
||||
board_type = board_info_root.attrib['board']
|
||||
if not board_type:
|
||||
os.remove(save_tmp_board_path)
|
||||
return {'status': 'Error on parsing Board info\n'
|
||||
'check the xml syntax and whether there is only the board '
|
||||
'attribute in the board info file'}
|
||||
|
||||
os.rename(save_tmp_board_path,
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
'res', filename))
|
||||
info = 'updated'
|
||||
if board_type not in board_type_list:
|
||||
info = board_type
|
||||
os.makedirs(os.path.join(config_path, board_type))
|
||||
for generic_name in os.listdir(os.path.join(config_path, 'generic')):
|
||||
generic_file = os.path.join(config_path, 'generic', generic_name)
|
||||
if os.path.isfile(generic_file):
|
||||
copyfile(generic_file, os.path.join(config_path, board_type, generic_name))
|
||||
|
||||
board_info = os.path.splitext(file.filename)[0]
|
||||
current_app.config.update(BOARD_INFO=board_info)
|
||||
current_app.config.update(BOARD_TYPE=board_type)
|
||||
|
||||
return {'status': 'success', 'info': info}
|
||||
|
||||
return {'status': 'Error: upload failed'}
|
||||
|
||||
|
||||
@CONFIG_APP.route('/select_board', methods=['POST'])
|
||||
def select_board():
|
||||
"""
|
||||
select one board info
|
||||
:return: the selected board info
|
||||
"""
|
||||
data = request.json if request.method == "POST" else request.args
|
||||
board_info = data['board_info']
|
||||
current_app.config.update(BOARD_INFO=board_info)
|
||||
|
||||
board_type = get_board_info_type(board_info)
|
||||
current_app.config.update(BOARD_TYPE=board_type)
|
||||
if board_type:
|
||||
return board_type
|
||||
|
||||
return ''
|
||||
|
||||
|
||||
@CONFIG_APP.route('/upload_scenario', methods=['POST'])
|
||||
def upload_scenario():
|
||||
"""
|
||||
upload scenario setting xml file
|
||||
:return: the upload status
|
||||
"""
|
||||
if request.method == 'POST':
|
||||
if 'file' not in request.files:
|
||||
return {'status': 'no file uploaded'}
|
||||
file = request.files['file']
|
||||
if file and '.' in file.filename and file.filename.rsplit('.', 1)[1] in ['xml']:
|
||||
filename = secure_filename(file.filename)
|
||||
print(filename)
|
||||
scenario_file_name = os.path.splitext(file.filename)[0]
|
||||
board_type = current_app.config.get('BOARD_TYPE')
|
||||
|
||||
tmp_scenario_name = 'tmp_' + scenario_file_name + '.xml'
|
||||
tmp_scenario_file = os.path.join(current_app.config.get('CONFIG_PATH'), board_type,
|
||||
'user_defined', tmp_scenario_name)
|
||||
if os.path.isfile(tmp_scenario_file):
|
||||
os.remove(tmp_scenario_file)
|
||||
|
||||
file.save(tmp_scenario_file)
|
||||
|
||||
tmp_xml_config = XmlConfig(os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
board_type, 'user_defined'))
|
||||
tmp_xml_config.set_curr(tmp_scenario_name[:-4])
|
||||
status = None
|
||||
if tmp_xml_config.get_curr_root() is None:
|
||||
status = 'Error on parsing the scenario xml file, \n' \
|
||||
'check the xml syntax and config items.'
|
||||
else:
|
||||
tmp_root = tmp_xml_config.get_curr_root()
|
||||
if 'board' not in tmp_root.attrib or 'scenario' not in tmp_root.attrib \
|
||||
or 'uos_launcher' in tmp_root.attrib:
|
||||
status = 'Invalid scenario xml file, \nonly board and scenario ' \
|
||||
'need to be configured.'
|
||||
elif tmp_root.attrib['board'] != current_app.config.get('BOARD_TYPE'):
|
||||
status = 'Current board: {} mismatched with the board in the scenario file,' \
|
||||
'\nplease reselect or upload the board info: {}'\
|
||||
.format(current_app.config.get('BOARD_TYPE'), tmp_root.attrib['board'])
|
||||
if status is not None:
|
||||
if os.path.isfile(tmp_scenario_file):
|
||||
os.remove(tmp_scenario_file)
|
||||
return {'status': status}
|
||||
|
||||
error_list = {}
|
||||
new_scenario_name = scenario_file_name
|
||||
rename = False
|
||||
if not error_list:
|
||||
new_scenario_path = os.path.join(current_app.config.get('CONFIG_PATH'), board_type,
|
||||
'user_defined', scenario_file_name + '.xml')
|
||||
if os.path.isfile(new_scenario_path):
|
||||
new_scenario_name = new_scenario_name + '_' \
|
||||
+ datetime.now().strftime('%Y%m%d%H%M%S')
|
||||
rename = True
|
||||
|
||||
os.rename(tmp_scenario_file, os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
board_type, 'user_defined',
|
||||
new_scenario_name + '.xml'))
|
||||
|
||||
return {'status': 'success', 'file_name': new_scenario_name,
|
||||
'rename': rename, 'error_list': error_list}
|
||||
|
||||
return {'status': 'unsupported method'}
|
||||
|
||||
|
||||
@CONFIG_APP.route('/upload_launch', methods=['POST'])
|
||||
def upload_launch():
|
||||
"""
|
||||
upload scenario setting xml file
|
||||
:return: the upload status
|
||||
"""
|
||||
if request.method == 'POST':
|
||||
if 'file' not in request.files:
|
||||
return {'status': 'no file uploaded'}
|
||||
file = request.files['file']
|
||||
if file and '.' in file.filename and file.filename.rsplit('.', 1)[1] in ['xml']:
|
||||
filename = secure_filename(file.filename)
|
||||
print(filename)
|
||||
launch_file_name = os.path.splitext(file.filename)[0]
|
||||
board_type = current_app.config.get('BOARD_TYPE')
|
||||
|
||||
tmp_launch_name = 'tmp_' + launch_file_name + '.xml'
|
||||
tmp_launch_file = os.path.join(current_app.config.get('CONFIG_PATH'), board_type,
|
||||
'user_defined', tmp_launch_name)
|
||||
if os.path.isfile(tmp_launch_file):
|
||||
os.remove(tmp_launch_file)
|
||||
|
||||
file.save(tmp_launch_file)
|
||||
|
||||
tmp_xml_config = XmlConfig(os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
board_type, 'user_defined'))
|
||||
tmp_xml_config.set_curr(tmp_launch_name[:-4])
|
||||
status = None
|
||||
if tmp_xml_config.get_curr_root() is None:
|
||||
status = 'Error on parsing the scenario xml file, \n' \
|
||||
'check the xml syntax and config items.'
|
||||
else:
|
||||
tmp_root = tmp_xml_config.get_curr_root()
|
||||
if 'board' not in tmp_root.attrib or 'scenario' not in tmp_root.attrib \
|
||||
or 'uos_launcher' not in tmp_root.attrib:
|
||||
status = 'Invalid launch xml file, \nboard, scenario,' \
|
||||
'and uos_launcher need to be configured.'
|
||||
elif tmp_root.attrib['board'] != current_app.config.get('BOARD_TYPE'):
|
||||
status = 'Current board: {} mismatched with the board in the launch file,' \
|
||||
'\nplease reselect or upload the board info: {}' \
|
||||
.format(current_app.config.get('BOARD_TYPE'), tmp_root.attrib['board'])
|
||||
if status is not None:
|
||||
if os.path.isfile(tmp_launch_file):
|
||||
os.remove(tmp_launch_file)
|
||||
return {'status': status}
|
||||
|
||||
error_list = {}
|
||||
new_launch_name = launch_file_name
|
||||
rename = False
|
||||
if not error_list:
|
||||
new_launch_path = os.path.join(current_app.config.get('CONFIG_PATH'), board_type,
|
||||
'user_defined', launch_file_name + '.xml')
|
||||
if os.path.isfile(new_launch_path):
|
||||
new_launch_name = new_launch_name + '_' + \
|
||||
datetime.now().strftime('%Y%m%d%H%M%S')
|
||||
rename = True
|
||||
|
||||
os.rename(tmp_launch_file, os.path.join(current_app.config.get('CONFIG_PATH'),
|
||||
board_type, 'user_defined',
|
||||
new_launch_name + '.xml'))
|
||||
|
||||
return {'status': 'success', 'file_name': new_launch_name,
|
||||
'rename': rename, 'error_list': error_list}
|
||||
|
||||
return {'status': 'unsupported method'}
|
||||
|
||||
|
||||
def get_board_list():
|
||||
"""
|
||||
get all available board info files
|
||||
:return: the file list of board info
|
||||
"""
|
||||
res_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res')
|
||||
if not os.path.isdir(res_path):
|
||||
os.makedirs(res_path)
|
||||
board_info_list = []
|
||||
for file in os.listdir(res_path):
|
||||
if os.path.isfile(os.path.join(res_path, file)) and \
|
||||
'.' in file and file.rsplit('.', 1)[1] in ['xml']:
|
||||
board_info_list.append(file.rsplit('.', 1)[0])
|
||||
return board_info_list
|
||||
|
||||
|
||||
def get_xml_configs(user_defined=False):
|
||||
"""
|
||||
get xml config related variables
|
||||
:return: board_info, board_config, scenario_config, launch_config
|
||||
"""
|
||||
|
||||
config_path = None
|
||||
board_info = current_app.config.get('BOARD_INFO')
|
||||
|
||||
board_type = get_board_info_type(board_info)
|
||||
if board_type is not None:
|
||||
config_path = os.path.join(current_app.config.get('CONFIG_PATH'), board_type)
|
||||
|
||||
if user_defined:
|
||||
scenario_config = XmlConfig(config_path, False)
|
||||
launch_config = XmlConfig(config_path, False)
|
||||
else:
|
||||
scenario_config = XmlConfig(config_path)
|
||||
launch_config = XmlConfig(config_path)
|
||||
|
||||
return board_info, board_type, scenario_config, launch_config
|
||||
|
||||
|
||||
def get_board_info_type(board_info):
|
||||
"""
|
||||
get board info type
|
||||
:param board_info: the board info file
|
||||
:return: the board type
|
||||
"""
|
||||
board_type = None
|
||||
if board_info is not None:
|
||||
board_info_config = XmlConfig(os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
'res'))
|
||||
board_info_config.set_curr(board_info)
|
||||
board_info_root = board_info_config.get_curr_root()
|
||||
if board_info_root and 'board' in board_info_root.attrib:
|
||||
board_type = board_info_root.attrib['board']
|
||||
|
||||
return board_type
|
Loading…
Reference in New Issue
Block a user