acrn-config: assign VM IDs for dynamic scenario and launch setting

When dynamically creating or adding or deleting VMs, acrn config app
will assign VM IDs for the VMs with the orders of prelaunched VMs and SOS
VM and postlaunched VMs to be consistent with the VM order of vm_configs
in vm configuration. When dynamically creating launch scripts, acrn
config app will let users to specify the VM ID before launch setting.

Tracked-On: #4641

Signed-off-by: Shuang Zheng <shuang.zheng@intel.com>
Acked-by: Terry Zou <terry.zou@intel.com>
This commit is contained in:
Shuang Zheng 2020-04-21 18:43:34 +08:00 committed by wenlingz
parent 44ec68dc49
commit f7594f0a93
6 changed files with 185 additions and 46 deletions

View File

@ -84,7 +84,7 @@ class XmlConfig:
:return: None.
:raises: ValueError, OSError, SyntaxError.
"""
if self._xml_path is None:
if self._xml_path is None or xml is None:
return
try:
self._curr_xml = xml

View File

@ -348,7 +348,7 @@ $().ready(function(){
$(document).on('click', "#add_launch_submit", function() {
var curr_vm_id = $(this).data('id');
save_launch('add_vm:'+curr_vm_id)
save_launch('add_vm:'+curr_vm_id);
});
$('#add_launch_script').on('click', function() {
@ -364,6 +364,31 @@ $().ready(function(){
}
});
$(document).on('change', "select#scenario_name", function() {
data = {scenario_name: $(this).val(),
launch_name: $('text#old_launch_name').text()};
$.ajax({
type : "POST",
contentType: "application/json;charset=UTF-8",
url : "../get_post_launch_vms",
data : JSON.stringify(data),
success : function(result) {
console.log(result);
vm_list = result.vm_list
$('select#add_launch_type').empty().selectpicker('refresh');
for(i in vm_list) {
var option = vm_list[i][1]+' ( ID : '+vm_list[i][0]+' )'
$('select#add_launch_type').append(
'<option value="'+option+'">'+option+'</option>').selectpicker('refresh');
}
},
error : function(e){
console.log(e.status);
console.log(e.responseText);
}
});
});
$("select[ID$='vuart:id=1,base']").change(function(){
var id = $(this).attr('id');
var value = $(this).val();
@ -416,6 +441,11 @@ $().ready(function(){
})
$(window).load(function () {
  $("select#scenario_name").change();
});
function show_com_target(id, value) {
if(id==null || id=='undefined') {

View File

@ -43,20 +43,18 @@ the launch scripts will be generated into misc/acrn-config/xmls/config-xmls/[boa
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="addlaunchModalLabel">Add a new VM</h4>
<h4 class="modal-title" id="addlaunchModalLabel">Configure UOS for Post-launched VM</h4>
</div>
<div class="modal-body">
<div class="form-group row">
<label for="add_launch_type" class="col-sm-3 control-label">VM type: </label>
<label for="add_launch_type" class="col-sm-3 control-label">VM : </label>
<div class="dropdown col-sm-6">
<select class="selectpicker" data-width="auto" id="add_launch_type">
<option value="LAUNCH_STANDARD_VM">LAUNCH_STANDARD_VM</option>
<option value="LAUNCH_RTVM">LAUNCH_RTVM</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="new_launch_name2" class="col-sm-3 control-label">Launch Name: </label>
<label for="new_launch_name2" class="col-sm-3 control-label">Launch Name : </label>
<div class="col-sm-6">
<input type="text" class="form-control" id="new_launch_name2"
value={{ launch }}>
@ -138,15 +136,20 @@ the launch scripts will be generated into misc/acrn-config/xmls/config-xmls/[boa
<tr>
<td>
<div class="form-group">
<label class="col-sm-2 control-label">UOS: </label>
<label class="col-sm-3 control-label">UOS: </label>
<label class="col-sm-1 control-label" id="vm">{{vm.attrib['id']}}</label>
</div>
<div class="form-group">
<button type="button" class="btn" id="add_launch_vm" data-id="{{vm.attrib['id']}}" data-toggle="modal"
data-target="#add_launch_modal">Add a VM below</button>
<label class="col-sm-3 control-label">VM ID: </label>
<label class="col-sm-1 control-label" id="vm_id">
{{post_launch_vm_list[vm.attrib['id']|int-1][0] if post_launch_vm_list|length>=1 else ''}}</label>
</div>
<div class="form-group">
<button type="button" class="btn" id="remove_launch_vm" data-id="{{vm.attrib['id']}}">
<button type="button" class="col-sm-6 btn" id="add_launch_vm" data-id="{{vm.attrib['id']}}" data-toggle="modal"
data-target="#add_launch_modal">Configure an UOS below</button>
</div>
<div class="form-group">
<button type="button" class="col-sm-6 btn" id="remove_launch_vm" data-id="{{vm.attrib['id']}}">
Remove this VM</button>
</div>
</td>
@ -380,7 +383,7 @@ the launch scripts will be generated into misc/acrn-config/xmls/config-xmls/[boa
{% endfor %}
<tr><td>
<button type="button" class="btn" id="add_launch_script" data-toggle="modal" data-id="-1"
data-target="#add_launch_modal">Add a New VM</button>
data-target="#add_launch_modal">Configure an UOS</button>
</td></tr>
</table>
{% else %}

View File

@ -24,6 +24,7 @@ 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
from library.common import MAX_VM_NUM
CONFIG_APP = Blueprint('CONFIG_APP', __name__, template_folder='templates')
@ -45,7 +46,6 @@ def scenarios():
: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)
(bios_info, base_board_info) = get_board_info(board_info)
return render_template('scenario.html', board_info_list=get_board_list(),
@ -65,7 +65,6 @@ def scenario(scenario_name):
"""
board_info, board_type, scenario_config, launch_config = get_xml_configs()
print(board_info, scenario_config, launch_config)
(bios_info, base_board_info) = get_board_info(board_info)
current_app.config.update(SCENARIO=scenario_name)
@ -81,8 +80,6 @@ def scenario(scenario_name):
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,
bios_info=bios_info, base_board_info=base_board_info,
@ -99,7 +96,6 @@ def launches():
: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)
(bios_info, base_board_info) = get_board_info(board_info)
return render_template('launch.html', board_info_list=get_board_list(),
@ -118,7 +114,6 @@ def launch(launch_name):
:return: the render template of specified launch setting page
"""
board_info, board_type, scenario_config, launch_config = get_xml_configs()
print(board_info, scenario_config, launch_config)
(bios_info, base_board_info) = get_board_info(board_info)
launch_config.set_curr(launch_name)
@ -128,7 +123,11 @@ def launch(launch_name):
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)
scenario_name = None
launch_config_root = launch_config.get_curr_root()
if launch_config_root is not None and 'scenario' in launch_config_root.attrib:
scenario_name = launch_config_root.attrib['scenario']
post_launch_vm_list = get_post_launch_vm_list(scenario_name)
return render_template('launch.html', board_info_list=get_board_list(),
board_info=board_info, board_type=board_type,
@ -137,6 +136,7 @@ def launch(launch_name):
launches=launch_config.list_all(xml_type='uos_launcher'),
launch=launch_name, root=launch_config.get_curr_root(),
scenario=current_app.config.get('SCENARIO'),
post_launch_vm_list=post_launch_vm_list,
launch_item_values=launch_item_values)
@ -170,7 +170,16 @@ def save_scenario():
if generator is not None:
if generator == 'remove_vm_kata':
scenario_config.delete_curr_key('vm:desc=specific for Kata')
assign_vm_id(scenario_config)
elif generator == 'add_vm_kata':
vm_list = []
for vm in scenario_config.get_curr_root().getchildren():
if vm.tag == 'vm':
vm_list.append(vm.attrib['id'])
if len(vm_list) >= MAX_VM_NUM:
return {'status': 'fail',
'error_list': {'error': 'Can not add a new VM. Max VM number is {}.'.format(MAX_VM_NUM)}}
# clone vm kata from generic config
generic_scenario_config = get_generic_scenario_config(scenario_config)
generic_scenario_config_root = generic_scenario_config.get_curr_root()
@ -181,14 +190,15 @@ def save_scenario():
break
if elem_kata is not None:
scenario_config.clone_curr_elem(elem_kata)
assign_vm_id(scenario_config)
elif generator.startswith('add_vm:'):
vm_list = []
for vm in scenario_config.get_curr_root().getchildren():
if vm.tag == 'vm':
vm_list.append(vm.attrib['id'])
if len(vm_list) >= 8:
if len(vm_list) >= MAX_VM_NUM:
return {'status': 'fail',
'error_list': {'error': 'Can not add a new VM. Max VM number is 8.'}}
'error_list': {'error': 'Can not add a new VM. Max VM number is {}.'.format(MAX_VM_NUM)}}
curr_vm_id = generator.split(':')[1]
add_vm_type = scenario_config_data['add_vm_type']
generic_scenario_config = get_generic_scenario_config(scenario_config, add_vm_type)
@ -204,7 +214,7 @@ def save_scenario():
break
for vm in generic_scenario_config_root.getchildren():
if vm.tag == 'vm':
for i in range(0, 8):
for i in range(0, MAX_VM_NUM):
if str(i) not in vm_list:
break
vm.attrib['id'] = str(i)
@ -212,9 +222,11 @@ def save_scenario():
for vm in vm_to_add:
scenario_config.insert_curr_elem(curr_vm_index, vm)
curr_vm_index += 1
assign_vm_id(scenario_config)
elif generator.startswith('remove_vm:'):
remove_vm_id = generator.split(':')[1]
scenario_config.delete_curr_key('vm:id='+remove_vm_id.strip())
assign_vm_id(scenario_config)
scenario_config.set_curr_attr('board', board_type)
scenario_config.set_curr_attr('scenario', scenario_config_data['new_scenario_name'])
@ -234,7 +246,6 @@ def save_scenario():
(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:
if os.path.isfile(tmp_scenario_file):
os.remove(tmp_scenario_file)
@ -260,7 +271,6 @@ def save_launch():
:return: the error list of the edited launch setting.
"""
launch_config_data = request.json if request.method == "POST" else request.args
print(launch_config_data)
xml_configs = get_xml_configs()
launch_config = xml_configs[3]
@ -270,6 +280,10 @@ def save_launch():
old_launch_name = launch_config_data['old_launch_name']
launch_config.set_curr(old_launch_name)
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'),
'user_defined', scenario_name + '.xml')
for key in launch_config_data:
if key not in ['old_launch_name', 'new_launch_name', 'generator', 'add_launch_type', 'scenario_name']:
@ -285,11 +299,26 @@ def save_launch():
for vm in launch_config.get_curr_root().getchildren():
if vm.tag == 'uos':
vm_list.append(vm.attrib['id'])
if len(vm_list) >= 8:
if len(vm_list) >= MAX_VM_NUM:
return {'status': 'fail',
'error_list': {'error': 'Can not add a new VM. Max VM number is 8.'}}
'error_list': {'error': 'Can not add a new VM. Max VM number is {}.'.format(MAX_VM_NUM)}}
curr_vm_id = generator.split(':')[1].strip()
add_launch_type = launch_config_data['add_launch_type']
if add_launch_type is None or len(add_launch_type.split('ID :')) < 2:
return {'status': 'fail',
'error_list': {'error': 'No VM is selected. '
'Please select a scenario with available post launched VMs.'}}
add_vm_id = add_launch_type.split('ID :')[1].replace(')', '').strip()
add_launch_type = 'LAUNCH_' + add_launch_type.split()[0]
if add_launch_type == 'LAUNCH_KATA_VM':
add_launch_type = 'LAUNCH_POST_STD_VM'
add_launch_id = 1
post_vm_list = get_post_launch_vm_list(scenario_name)
for i in range(len(post_vm_list)):
vm_info = post_vm_list[i]
if add_vm_id == vm_info[0]:
add_launch_id = i + 1
break
generic_scenario_config = get_generic_scenario_config(launch_config, add_launch_type)
generic_scenario_config_root = generic_scenario_config.get_curr_root()
vm_to_add = []
@ -303,10 +332,10 @@ def save_launch():
break
for vm in generic_scenario_config_root.getchildren():
if vm.tag == 'uos':
for i in range(1, 8):
for i in range(1, MAX_VM_NUM):
if str(i) not in vm_list:
break
vm.attrib['id'] = str(i)
vm.attrib['id'] = str(add_launch_id)
vm_to_add.append(vm)
for vm in vm_to_add:
@ -315,10 +344,6 @@ def save_launch():
remove_vm_id = generator.split(':')[1]
launch_config.delete_curr_key('uos:id='+remove_vm_id.strip())
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'),
'user_defined', scenario_name + '.xml')
launch_config.set_curr_attr('scenario', scenario_name)
launch_config.set_curr_attr('board', current_app.config.get('BOARD_TYPE'))
@ -340,7 +365,6 @@ def save_launch():
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'res', xml_configs[0]+'.xml'),
scenario_file_path,
tmp_launch_file)
print(pthru_sel, virtio, dm_value)
except Exception as error:
if os.path.isfile(tmp_launch_file):
os.remove(tmp_launch_file)
@ -420,7 +444,7 @@ def create_setting():
os.remove(launch_file)
if mode == 'create':
template_file_name = 'LAUNCH_STANDARD_VM'
template_file_name = 'LAUNCH_POST_STD_VM'
src_file_name = os.path.join(current_app.config.get('CONFIG_PATH'), 'template', template_file_name+'.xml')
else:
src_file_name = os.path.join(current_app.config.get('CONFIG_PATH'), board_type, default_name + '.xml')
@ -494,7 +518,6 @@ def generate_src():
scenario_setting_xml = os.path.join(current_app.config.get('CONFIG_PATH'), board_type,
'user_defined', scenario_setting+'.xml')
src_path = generator_config_data['src_path']
print(src_path)
launch_setting_xml = None
if 'launch_setting' in generator_config_data:
launch_setting = generator_config_data['launch_setting']
@ -518,13 +541,8 @@ def generate_src():
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')
scenario_setting_xml = os.path.join(current_app.config.get('CONFIG_PATH'), board_type,
'user_defined', scenario_setting + '.xml')
try:
from launch_config.launch_cfg_gen import ui_entry_api
@ -639,7 +657,6 @@ def upload_scenario():
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')
@ -709,7 +726,6 @@ def upload_launch():
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')
@ -764,6 +780,56 @@ def upload_launch():
return {'status': 'unsupported method'}
@CONFIG_APP.route('/get_post_launch_vms', methods=['POST'])
def get_post_launch_vms():
"""
get vm list for the scenario setting
:return: the vm list
"""
data = request.json if request.method == "POST" else request.args
scenario_name = data['scenario_name']
vm_list = get_post_launch_vm_list(scenario_name)
uos_id_list = []
launch_name = data['launch_name']
xml_configs = get_xml_configs()
launch_config = xml_configs[3]
launch_config.set_curr(launch_name)
if launch_config is not None and launch_config.get_curr_root() is not None:
for uos in launch_config.get_curr_root().getchildren():
if 'id' in uos.attrib:
uos_id_list.append(int(uos.attrib['id'])-1)
vm_list_index = [i for i in range(len(vm_list))]
vm_list_index = set(vm_list_index)
uos_id_list = set(uos_id_list)
index = list(vm_list_index - uos_id_list)
vm_list = [vm_list[i] for i in index]
return {'vm_list': vm_list}
def get_post_launch_vm_list(scenario_name):
"""
get post launch VM list
:param scenario_name:
:return: vm_list
"""
xml_configs = get_xml_configs()
scenario_config = xml_configs[3]
scenario_config.set_curr(scenario_name)
vm_list = []
if scenario_config is not None and scenario_config.get_curr_root() is not None:
for vm in scenario_config.get_curr_root().getchildren():
if vm.tag == 'vm' and 'id' in vm.attrib:
vm_id = vm.attrib['id']
for item in vm.getchildren():
if item.tag == 'vm_type' and item.text in ['POST_STD_VM', 'POST_RT_VM']:
vm_list.append((vm_id, item.text))
break
return vm_list
def get_board_list():
"""
get all available board info files
@ -882,4 +948,44 @@ def get_board_info(board_info):
else:
base_board_info += ('\n' + line.strip())
return (bios_info, base_board_info)
return (bios_info, base_board_info)
def assign_vm_id(scenario_config):
"""
assign vm ids for the scenario setting.
:param scenario_config:
:return:
"""
root = scenario_config.get_curr_root()
pre_launched_vm_num = 0
sos_vm_num = 0
post_launched_vm_num = 0
for vm in root.getchildren():
if vm.tag == 'vm':
for item in vm.getchildren():
if item.tag == 'vm_type':
if item.text in ['PRE_STD_VM', 'SAFETY_VM']:
pre_launched_vm_num += 1
elif item.text in ['SOS_VM']:
sos_vm_num += 1
elif item.text in ['POST_STD_VM', 'POST_RT_VM', 'KATA_VM']:
post_launched_vm_num += 1
pre_launched_vm_index = 0
sos_vm_index = pre_launched_vm_num
post_launched_vm_index = pre_launched_vm_num + sos_vm_num
for vm in root.getchildren():
if vm.tag == 'vm':
for item in vm.getchildren():
if item.tag == 'vm_type':
if item.text in ['PRE_STD_VM', 'SAFETY_VM']:
vm.attrib['id'] = str(pre_launched_vm_index)
pre_launched_vm_index += 1
elif item.text in ['SOS_VM']:
vm.attrib['id'] = str(sos_vm_index)
sos_vm_index += 1
elif item.text in ['POST_STD_VM', 'POST_RT_VM', 'KATA_VM']:
vm.attrib['id'] = str(post_launched_vm_index)
post_launched_vm_index += 1

View File

@ -6,7 +6,7 @@
<gvt_args configurable="0" desc="GVT settings. Set it to gvtd for GVTd, otherwise is GVTg arguments. The recommendation arguments for GVTg is 64 448 8. Leave it blank to disable GVT."></gvt_args>
<vbootloader desc="virtual bootloader method" readonly="true">ovmf</vbootloader>
<vuart0 desc="vUART0 which emulated by device model"></vuart0>
<cpu_sharing desc="Whether the binding pCPUs are sharing with other VMs." readonly="true">Disabled</cpu_sharing>
<cpu_sharing desc="Whether the binding pCPUs are sharing with other VMs."></cpu_sharing>
<poweroff_channel desc="the method of power off uos"></poweroff_channel>
<usb_xhci desc="USB xHCI mediator configuration. input format: bus#-port#[:bus#-port#: ...]. e.g.: 1-2:2-4"></usb_xhci>