mirror of
https://github.com/retspen/webvirtcloud
synced 2024-11-01 03:54:15 +00:00
commit
d5fe941b2f
12 changed files with 470 additions and 114 deletions
|
@ -36,15 +36,17 @@
|
|||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-sm-4">
|
||||
<div class="col-xs-3">
|
||||
<p><strong>{% trans "Status" %}:</strong></p>
|
||||
</div>
|
||||
<div class="col-xs-4 col-sm-6">
|
||||
<div class="col-xs-9">
|
||||
{% ifequal compute.status 1 %}
|
||||
<p>{% trans "Connected" %}</p>
|
||||
{% else %}
|
||||
<p>{% trans "Not Connected" %}</p>
|
||||
{% endifequal %}
|
||||
</div>
|
||||
<div class="col-xs-offset-3 col-sm-8">
|
||||
{% if compute.details %}
|
||||
<p>{% trans compute.details %}</p>
|
||||
{% else %}
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
|
||||
<div class="noVNC_scroll">
|
||||
|
||||
<h1 class="noVNC_logo" translate="no"><span>no</span><br />VNC</h1>
|
||||
<h1 class="noVNC_logo" translate="no"><span>no</span><br/>VNC</h1>
|
||||
|
||||
<!-- Drag/Pan the viewport -->
|
||||
<input type="image" alt="viewport drag" src="{% static "js/novnc/app/images/drag.svg" %}"
|
||||
|
@ -225,7 +225,7 @@
|
|||
<div class="noVNC_expander">WebSocket</div>
|
||||
<div><ul>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_encrypt" type="checkbox" /> Encrypt</label>
|
||||
<label><input id="noVNC_setting_encrypt" type="checkbox"/>Encrypt</label>
|
||||
</li>
|
||||
<li>
|
||||
<label for="noVNC_setting_host">Host:</label>
|
||||
|
@ -233,17 +233,17 @@
|
|||
</li>
|
||||
<li>
|
||||
<label for="noVNC_setting_port">Port:</label>
|
||||
<input id="noVNC_setting_port" value="{{ ws_port }}" type="number" />
|
||||
<input id="noVNC_setting_port" value="{{ ws_port }}" type="number"/>
|
||||
</li>
|
||||
<li>
|
||||
<label for="noVNC_setting_path">Path:</label>
|
||||
<input id="noVNC_setting_path" type="input" value="websockify" />
|
||||
<input id="noVNC_setting_path" type="input" value="websockify"/>
|
||||
</li>
|
||||
</ul></div>
|
||||
</li>
|
||||
<li><hr></li>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_reconnect" type="checkbox" /> Automatic Reconnect</label>
|
||||
<label><input id="noVNC_setting_reconnect" type="checkbox" />Automatic Reconnect</label>
|
||||
<input id="noVNC_setting_autoconnect" type="checkbox" value="true" hidden/>
|
||||
</li>
|
||||
<li>
|
||||
|
@ -252,7 +252,7 @@
|
|||
</li>
|
||||
<li><hr></li>
|
||||
<li>
|
||||
<label><input id="noVNC_setting_show_dot" type="checkbox"> Show Dot when No Cursor</label>
|
||||
<label><input id="noVNC_setting_show_dot" type="checkbox">Show Dot when No Cursor</label>
|
||||
</li>
|
||||
<li><hr></li>
|
||||
<!-- Logging selection dropdown -->
|
||||
|
|
|
@ -16,6 +16,9 @@ from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_BUS
|
|||
from webvirtcloud.settings import INSTANCE_CPU_DEFAULT_MODE
|
||||
from webvirtcloud.settings import INSTANCE_MACHINE_DEFAULT_TYPE
|
||||
from webvirtcloud.settings import QEMU_CONSOLE_DEFAULT_TYPE
|
||||
from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_IO
|
||||
from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES
|
||||
from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_DISCARD
|
||||
from django.contrib import messages
|
||||
from logs.views import addlogmsg
|
||||
|
||||
|
@ -97,7 +100,10 @@ def create_instance(request, compute_id, arch, machine):
|
|||
instances = conn.get_instances()
|
||||
videos = conn.get_video_models(arch, machine)
|
||||
cache_modes = sorted(conn.get_cache_modes().items())
|
||||
default_cache = INSTANCE_VOLUME_DEFAULT_CACHE
|
||||
default_cache = INSTANCE_VOLUME_DEFAULT_CACHE.lower()
|
||||
default_io = INSTANCE_VOLUME_DEFAULT_IO.lower()
|
||||
default_zeroes = INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES.lower()
|
||||
default_discard = INSTANCE_VOLUME_DEFAULT_DISCARD.lower()
|
||||
listener_addr = QEMU_CONSOLE_LISTEN_ADDRESSES
|
||||
mac_auto = util.randomMAC()
|
||||
disk_devices = conn.get_disk_device_types(arch, machine)
|
||||
|
@ -238,6 +244,7 @@ def create_instance(request, compute_id, arch, machine):
|
|||
vcpu_mode=data['vcpu_mode'], uuid=uuid, arch=arch, machine=machine,
|
||||
firmware=firmware,
|
||||
images=volume_list, cache_mode=data['cache_mode'],
|
||||
io_mode=default_io, discard_mode=default_discard, detect_zeroes_mode=default_zeroes,
|
||||
networks=data['networks'], virtio=data['virtio'],
|
||||
listen_addr=data["listener_addr"], nwfilter=data["nwfilter"],
|
||||
graphics=data["graphics"], video=data["video"],
|
||||
|
|
|
@ -84,7 +84,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-lg btn-success pull-right" name="add_new_vol">{% trans "Add Volume" %}</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
|
||||
<button type="submit" class="btn btn-success" name="add_new_vol">{% trans "Add Volume" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -138,7 +139,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-lg btn-success pull-right" name="add_existing_vol">{% trans "Add Volume" %}</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
|
||||
<button type="submit" class="btn btn-success" name="add_existing_vol">{% trans "Add Volume" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
126
instances/templates/edit_instance_volume.html
Normal file
126
instances/templates/edit_instance_volume.html
Normal file
|
@ -0,0 +1,126 @@
|
|||
{% load i18n %}
|
||||
{% if request.user.is_superuser %}
|
||||
<button href="#editvol{{ id }}" type="button" class="btn btn-sm btn-default" data-toggle="modal" title="Edit Volume">
|
||||
<i class="glyphicon glyphicon-edit" aria-hidden="true"></i>
|
||||
</button>
|
||||
|
||||
<!-- Modal pool -->
|
||||
<div class="modal fade" id="editvol{{ id }}" tabindex="-1" role="dialog" aria-labelledby="editInstanceVolumeLabel{{ id }}" 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">{% trans "Edit Instance Volume" %}</h4>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
<li role="presentation" class="active"><a href="#VirtualDisk{{ id }}" data-toggle="tab">{% trans 'Virtual Disk' %}</a></li>
|
||||
<li role="presentation"><a href="#PerformanceVolume{{ id }}" data-toggle="tab">{% trans 'Performance' %}</a></li>
|
||||
<li role="presentation"><a href="#AdvancedVolume{{ id }}" data-toggle="tab">{% trans 'Advanced' %}</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane active" id="VirtualDisk{{ id }}">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">{% trans 'Volume Path' %}</label>
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control" name="vol_path" value="{{ disk.path }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">{% trans 'Readonly' %}</label>
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control-static" type="checkbox" name="vol_readonly" value="True" {% if disk.readonly %}checked{% endif %}/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">{% trans 'Shareable' %}</label>
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control-static" type="checkbox" name="vol_shareable" value="True" {% if disk.shareable %}checked{% endif %}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="AdvancedVolume{{ id }}">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">{% trans 'Bus' %}</label>
|
||||
<div class="col-sm-8">
|
||||
<select class="form-control" name="vol_bus">
|
||||
{% for bus in bus_host %}
|
||||
<option value="{{ bus }}" {% if bus == disk.bus %}selected{% endif %}>{{ bus }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">{% trans 'Serial Number' %}</label>
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control" type="text" name="vol_serial" value="{{ disk.serial }}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">{% trans 'Storage Format' %}</label>
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control" type="text" name="vol_format" value="{{ disk.format }}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="PerformanceVolume{{ id }}">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">{% trans 'Cache mode' %}</label>
|
||||
<div class="col-sm-8">
|
||||
<select class="form-control" name="vol_cache">
|
||||
{% for key, val in cache_modes %}
|
||||
<option value="{{ key }}" {% if key == disk.cache %}selected{% endif %}>{{ val }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">{% trans 'IO mode' %}</label>
|
||||
<div class="col-sm-8">
|
||||
<select class="form-control" name="vol_io_mode">
|
||||
{% for key, val in io_modes %}
|
||||
<option value="{{ key }}" {% if key == disk.io %}selected{% endif %}>{{ val }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">{% trans 'Discard mode' %}</label>
|
||||
<div class="col-sm-8">
|
||||
<select class="form-control" name="vol_discard_mode">
|
||||
{% for key, val in discard_modes %}
|
||||
<option value="{{ key }}" {% if key == disk.discard %}selected{% endif %}>{{ val }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">{% trans 'Detect zeroes' %}</label>
|
||||
<div class="col-sm-8">
|
||||
<select class="form-control" name="vol_detect_zeroes">
|
||||
{% for key, val in detect_zeroes_modes %}
|
||||
<option value="{{ key }}" {% if key == disk.detect_zeroes %}selected{% endif %}>{{ val }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.tabpane-content -->
|
||||
</div><!-- /.tab-content -->
|
||||
</div> <!-- /.modal-body -->
|
||||
<div class="clearfix"></div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
|
||||
<button type="submit" class="btn btn-success" name="edit_volume">{% trans "Save" %}</button>
|
||||
</div><!-- /.modal-footer -->
|
||||
|
||||
</div> <!-- /.modal-content -->
|
||||
</div> <!-- /.modal-dialog -->
|
||||
|
||||
</div> <!-- /.modal -->
|
||||
{% endif %}
|
|
@ -34,6 +34,11 @@
|
|||
{% for disk in disks %}
|
||||
{{ disk.size|filesizeformat }} {% trans "Disk" %} |
|
||||
{% endfor %}
|
||||
{% for net in networks %}
|
||||
{% for ipv4 in net.ipv4|default:"-" %}
|
||||
{{ ipv4 }} |
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
<button
|
||||
{% if guest_agent == True %}
|
||||
{% if guest_agent_ready == True %}
|
||||
|
@ -823,14 +828,14 @@
|
|||
<th>{% trans "Capacity" %}</th>
|
||||
<th>{% trans "Storage" %}</th>
|
||||
<th>{% trans "Source" %}</th>
|
||||
<th style="width:100px;">{% trans "Action" %}</th>
|
||||
<th>{% trans "Action" %}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for disk in disks %}
|
||||
<tr>
|
||||
<td>
|
||||
<button type="submit" class="btn btn-sm btn-default"
|
||||
name="details"
|
||||
name="details{{ forloop.counter0 }}"
|
||||
title="{% trans "Details" %}"
|
||||
tabindex="0"
|
||||
data-trigger="focus"
|
||||
|
@ -838,7 +843,13 @@
|
|||
data-html="true"
|
||||
data-content="<strong>Bus:</strong> {{ disk.bus }} <br/>
|
||||
<strong>Format:</strong> {{ disk.format }} <br/>
|
||||
<strong>Cache:</strong> {{ disk.cache }}">
|
||||
<strong>Cache:</strong> {{ disk.cache }} <br/>
|
||||
<strong>Serial:</strong> {{ disk.serial }} <br/>
|
||||
<strong>Readonly:</strong> {{ disk.readonly }} <br/>
|
||||
<strong>Shareable:</strong> {{ disk.shareable }}</br>
|
||||
<strong>IO Mode:</strong> {{ disk.io }} <br/>
|
||||
<strong>Discard:</strong> {{ disk.discard }} <br/>
|
||||
<strong>Detect Zeroes:</strong> {{ disk.detect_zeroes }}">
|
||||
<i class="fa fa-info"></i>
|
||||
</button>
|
||||
{{ disk.dev }}
|
||||
|
@ -850,11 +861,12 @@
|
|||
<td>{{ disk.storage }}</td>
|
||||
<td>{{ disk.path }}</td>
|
||||
<td>
|
||||
<form action="" method="post" style="height:10px" role="form">{% csrf_token %}
|
||||
<form action="" method="post" role="form">{% csrf_token %}
|
||||
<input type="hidden" name="path" value="{{ disk.path }}">
|
||||
<input type="hidden" name="dev" value="{{ disk.dev }}">
|
||||
<input type="hidden" name="storage" value="{{ disk.storage }}">
|
||||
<input type="hidden" name="name" value="{{ disk.image }}">
|
||||
{% include 'edit_instance_volume.html' with id=forloop.counter0 %}
|
||||
{% ifequal status 5 %}
|
||||
<button type="submit" class="btn btn-sm btn-default" name="detach_vol" value="{{ disk.dev }}" title="{% trans "Detach" %}" onclick="return confirm('{% trans "Are you sure to detach volume?" %}')">
|
||||
<i class="fa fa-eject"></i>
|
||||
|
@ -863,14 +875,15 @@
|
|||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
{% else %}
|
||||
<button class="btn btn-sm btn-default disabled" name="detach_vol" value="{{ disk.dev }}" title="{% trans "Detach" %}" onclick="return confirm('{% trans "Are you sure to detach volume after shutdown?" %}')">
|
||||
<button class="btn btn-sm btn-default disabled" name="detach_vol" value="{{ disk.dev }}" title="{% trans "Detach" %}" onclick="return confirm('{% trans "Are you sure? This may lead data corruption!" %}')">
|
||||
<i class="fa fa-eject"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-default disabled" name="delete_vol" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure to delete after shutdown?" %}')">
|
||||
<button class="btn btn-sm btn-default disabled" name="delete_vol" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure? This may lead data corruption!" %}')">
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
{% endifequal %}
|
||||
</form>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -887,44 +900,35 @@
|
|||
|
||||
<div class="col-xs-12 col-sm-12">
|
||||
<p><strong>{% trans "Network Devices" %}</strong></p>
|
||||
<table class="table table-hover">
|
||||
<table class="table table-condensed table-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans 'Name' %}</th>
|
||||
<th>{% trans 'MAC' %}</th>
|
||||
<th>{% trans 'IP Address' %}</th>
|
||||
<th>{% trans 'Source' %}</th>
|
||||
<th>{% trans 'LinkState' %}</th>
|
||||
<th>{% trans 'Filter' %}</th>
|
||||
<th>{% trans 'Qos' %}</th>
|
||||
<th>{% trans 'Actions' %}</th>
|
||||
<th class="hidden-xs hidden-sm" colspan="6">{% trans 'Info' %}</th>
|
||||
<th class="visible-xs visible-sm" colspan="2">{% trans 'Info' %}</th>
|
||||
<th colspan="2">{% trans 'Actions' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for network in networks %}
|
||||
{% for network in networks %}
|
||||
<tr>
|
||||
<td class="col-sm-1">eth{{ forloop.counter0 }}({{ network.target|default:"no target" }})</td>
|
||||
<td>{{ network.mac }}</td>
|
||||
<td>{{ network.ipv4|default:"unknown" }}</td>
|
||||
<td>{{ network.nic }}</td>
|
||||
<td>
|
||||
<form method="post">{% csrf_token %}
|
||||
<input name="mac" value="{{ network.mac }}" hidden/>
|
||||
<input name="set_link_state" value="{{ network.state }}" hidden/>
|
||||
<input type="checkbox" {% if network.state == 'up' %} checked
|
||||
{% endif %} onclick='submit();' />
|
||||
{% trans 'active' %}
|
||||
</form>
|
||||
</td>
|
||||
<td>{{ network.filterref|default:"None" }}</td>
|
||||
<td>
|
||||
<form class="form-horizontal" method="post" name="add_qos{{ forloop.counter0 }}" role="form">{% csrf_token %}
|
||||
<input type="text" name="net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}" hidden/>
|
||||
{% include 'add_network_qos.html' with id=forloop.counter0 %}
|
||||
<td rowspan="2">eth{{ forloop.counter0 }}({{ network.target|default:"no target" }})
|
||||
<form method="post">{% csrf_token %}
|
||||
<input name="mac" value="{{ network.mac }}" hidden/>
|
||||
<input name="set_link_state" value="{{ network.state }}" hidden/>
|
||||
<input type="checkbox" {% if network.state == 'up' %} checked
|
||||
{% endif %} onclick='submit();' />
|
||||
<strong>{% trans 'active' %}</strong>
|
||||
</form>
|
||||
</td>
|
||||
<td class="col-sm-2">
|
||||
<form class="form-horizontal" method="post" name="set_qos{{ forloop.counter0 }}" role="form">{% csrf_token %}
|
||||
<th class="hidden-xs hidden-sm">{% trans 'MAC' %}</th>
|
||||
<td>{{ network.mac }}</td>
|
||||
<th class="hidden-xs hidden-sm">{% trans 'Filter' %}</th>
|
||||
<td class="hidden-xs">{{ network.filterref|default:"None" }}</td>
|
||||
<th class="hidden-xs hidden-sm">{% trans 'Source' %}</th>
|
||||
<td>{{ network.nic }}</td>
|
||||
<td>
|
||||
<form class="form-horizontal" method="post" name="edit_network{{ forloop.counter0 }}" role="form">{% csrf_token %}
|
||||
<button data-target="#editInstanceNetwork{{ forloop.counter0 }}" type="button" class="btn btn-sm btn-primary"
|
||||
title="Edit NIC" data-toggle="modal">
|
||||
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
|
||||
|
@ -939,13 +943,13 @@
|
|||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group form-inline">
|
||||
<label class="col-sm-2 control-label">{% trans "MAC" %} </label>
|
||||
<label class="col-sm-3 control-label">{% trans "MAC Addr" %} </label>
|
||||
<input class="form-control" type="text" value="{{ network.mac }}" readonly/>
|
||||
<label class="control-label"><em>to</em></label>
|
||||
<input class="form-control" type="text" name="net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}"/>
|
||||
</div>
|
||||
<div class="form-group form-inline">
|
||||
<label class="col-sm-2 control-label">{% trans "NIC" %} </label>
|
||||
<label class="col-sm-3 control-label">{% trans "Net Source" %} </label>
|
||||
<input class="form-control" type="text" value="{{ network.nic }}" readonly/>
|
||||
<label class="control-label"><em>to</em></label>
|
||||
<select class="form-control" name="net-source-{{ forloop.counter0 }}">
|
||||
|
@ -958,7 +962,7 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="form-group form-inline">
|
||||
<label class="col-sm-2 control-label">{% trans "Filter" %} </label>
|
||||
<label class="col-sm-3 control-label">{% trans "NW Filter" %} </label>
|
||||
<input class="form-control" type="text" value="{{ network.filterref }}" readonly/>
|
||||
<label class="control-label"><em>to</em></label>
|
||||
<select class="form-control" name="net-nwfilter-{{ forloop.counter0 }}">
|
||||
|
@ -968,20 +972,59 @@
|
|||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary btn-block" name="change_network" title="{% trans "Apply Network Changes" %}">{% trans "Apply" %}</button>
|
||||
<div class="form-group form-inline">
|
||||
<label class="col-sm-3 control-label">{% trans "Model" %} </label>
|
||||
<input class="form-control" type="text" value="{{ network.model }}" readonly/>
|
||||
<label class="control-label"><em>to</em></label>
|
||||
<select class="form-control" name="net-model-{{ forloop.counter0 }}">
|
||||
{% for model in net_models_host %}
|
||||
<option value="{{ model }}" {% ifequal model network.model %} selected {% endifequal %}>{{ model }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-default" data-dismiss="modal">{% trans 'Close' %}</button>
|
||||
<button class="btn btn-success" name="change_network" title="{% trans "Apply Network Changes" %}">{% trans "Apply" %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-sm btn-danger" value="{{ network.mac }}" name="delete_network" title="{% trans "Delete Device" %}"
|
||||
onclick="return confirm('{% trans "Are you sure?" %}')">
|
||||
<i class="glyphicon glyphicon-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
<td align="right">
|
||||
<form method="post" name="delete_network" role="form">{% csrf_token %}
|
||||
<button class="btn btn-sm btn-danger" value="{{ network.mac }}" name="delete_network" title="{% trans "Delete Device" %}"
|
||||
onclick="return confirm('{% trans "Are you sure?" %}')">
|
||||
<i class="glyphicon glyphicon-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th class="hidden-xs hidden-sm">{% trans 'IPv4' %}</th>
|
||||
<td>
|
||||
{% for ipv4 in network.ipv4|default:"unknown" %}{{ ipv4 }}{% endfor %}
|
||||
</td>
|
||||
<th class="hidden-xs hidden-sm">{% trans 'IPv6' %}</th>
|
||||
<td class="hidden-xs">
|
||||
{% for ipv6 in network.ipv6|default:"unknown" %}{{ ipv6 }}{% endfor %}
|
||||
</td>
|
||||
<th class="hidden-xs hidden-sm">{% trans 'Model' %}</th>
|
||||
<td>{{ network.model }}</td>
|
||||
<th>{% trans 'QoS' %}</th>
|
||||
<td align="right">
|
||||
<form class="form-horizontal" method="post" name="add_qos{{ forloop.counter0 }}" role="form">{% csrf_token %}
|
||||
<input type="text" name="net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}" hidden/>
|
||||
{% include 'add_network_qos.html' with id=forloop.counter0 %}
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="bg-primary hidden-xs hidden-sm" colspan="9"></td>
|
||||
<td class="bg-primary visible-xs visible-sm" colspan="5"></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -994,7 +1037,7 @@
|
|||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Direction" %}</th>
|
||||
<th>{% trans "MAC/Direction" %}</th>
|
||||
<th>{% trans "Average" %}</th>
|
||||
<th>{% trans "Peak" %}</th>
|
||||
<th>{% trans "Burst" %}</th>
|
||||
|
|
|
@ -313,6 +313,12 @@ def instance(request, compute_id, vname):
|
|||
clone_free_names = get_clone_free_names()
|
||||
user_quota_msg = check_user_quota(0, 0, 0, 0)
|
||||
cache_modes = sorted(conn.get_cache_modes().items())
|
||||
io_modes = sorted(conn.get_io_modes().items())
|
||||
discard_modes = sorted(conn.get_discard_modes().items())
|
||||
detect_zeroes_modes = sorted(conn.get_detect_zeroes_modes().items())
|
||||
default_io = settings.INSTANCE_VOLUME_DEFAULT_IO
|
||||
default_discard = settings.INSTANCE_VOLUME_DEFAULT_DISCARD
|
||||
default_zeroes = settings.INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES
|
||||
default_cache = settings.INSTANCE_VOLUME_DEFAULT_CACHE
|
||||
default_format = settings.INSTANCE_VOLUME_DEFAULT_FORMAT
|
||||
default_owner = settings.INSTANCE_VOLUME_DEFAULT_OWNER
|
||||
|
@ -347,6 +353,7 @@ def instance(request, compute_id, vname):
|
|||
networks_host = sorted(conn.get_networks())
|
||||
nwfilters_host = conn.get_nwfilters()
|
||||
storages_host = sorted(conn.get_storages(True))
|
||||
net_models_host = conn.get_network_models()
|
||||
|
||||
try:
|
||||
interfaces_host = sorted(conn.get_ifaces())
|
||||
|
@ -506,6 +513,7 @@ def instance(request, compute_id, vname):
|
|||
conn.resize_cpu(cur_vcpu, vcpu)
|
||||
msg = _("Resize CPU")
|
||||
addlogmsg(request.user.username, instance.name, msg)
|
||||
messages.success(request, msg)
|
||||
return HttpResponseRedirect(request.get_full_path() + '#resize')
|
||||
|
||||
if 'resizevm_mem' in request.POST and (request.user.is_superuser or
|
||||
|
@ -529,6 +537,7 @@ def instance(request, compute_id, vname):
|
|||
conn.resize_mem(cur_memory, memory)
|
||||
msg = _("Resize Memory")
|
||||
addlogmsg(request.user.username, instance.name, msg)
|
||||
messages.success(request, msg)
|
||||
return HttpResponseRedirect(request.get_full_path() + '#resize')
|
||||
|
||||
if 'resizevm_disk' in request.POST and (
|
||||
|
@ -549,6 +558,7 @@ def instance(request, compute_id, vname):
|
|||
conn.resize_disk(disks_new)
|
||||
msg = _("Resize")
|
||||
addlogmsg(request.user.username, instance.name, msg)
|
||||
messages.success(request, msg)
|
||||
return HttpResponseRedirect(request.get_full_path() + '#resize')
|
||||
|
||||
if 'add_new_vol' in request.POST and allow_admin_or_not_template:
|
||||
|
@ -563,10 +573,10 @@ def instance(request, compute_id, vname):
|
|||
meta_prealloc = True if request.POST.get('meta_prealloc', False) else False
|
||||
bus = request.POST.get('bus', default_bus)
|
||||
cache = request.POST.get('cache', default_cache)
|
||||
target = get_new_disk_dev(media, disks, bus)
|
||||
target_dev = get_new_disk_dev(media, disks, bus)
|
||||
|
||||
path = conn_create.create_volume(storage, name, size, format, meta_prealloc, default_owner)
|
||||
conn.attach_disk(path, target, subdriver=format, cache=cache, targetbus=bus)
|
||||
source = conn_create.create_volume(storage, name, size, format, meta_prealloc, default_owner)
|
||||
conn.attach_disk(source, target_dev, target_bus=bus, driver_type=format, cache_mode=cache)
|
||||
msg = _('Attach new disk {} ({})'.format(name, format))
|
||||
addlogmsg(request.user.username, instance.name, msg)
|
||||
return HttpResponseRedirect(request.get_full_path() + '#disks')
|
||||
|
@ -583,16 +593,43 @@ def instance(request, compute_id, vname):
|
|||
compute.type,
|
||||
storage)
|
||||
|
||||
format = conn_create.get_volume_type(name)
|
||||
driver_type = conn_create.get_volume_type(name)
|
||||
path = conn_create.get_target_path()
|
||||
target = get_new_disk_dev(media, disks, bus)
|
||||
target_dev = get_new_disk_dev(media, disks, bus)
|
||||
source = path + "/" + name
|
||||
|
||||
conn.attach_disk(source, target, subdriver=format, cache=cache, targetbus=bus)
|
||||
msg = _('Attach Existing disk: ' + target)
|
||||
conn.attach_disk(source, target_dev, target_bus=bus, driver_type=driver_type, cache_mode=cache)
|
||||
msg = _('Attach Existing disk: ' + target_dev)
|
||||
addlogmsg(request.user.username, instance.name, msg)
|
||||
return HttpResponseRedirect(request.get_full_path() + '#disks')
|
||||
|
||||
if 'edit_volume' in request.POST and allow_admin_or_not_template:
|
||||
target_dev = request.POST.get('dev', '')
|
||||
|
||||
new_path = request.POST.get('vol_path', '')
|
||||
shareable = bool(request.POST.get('vol_shareable', False))
|
||||
readonly = bool(request.POST.get('vol_readonly', False))
|
||||
bus = request.POST.get('vol_bus', '')
|
||||
serial = request.POST.get('vol_serial', '')
|
||||
format = request.POST.get('vol_format', '')
|
||||
cache = request.POST.get('vol_cache', default_cache)
|
||||
io = request.POST.get('vol_io_mode', default_io)
|
||||
discard = request.POST.get('vol_discard_mode', default_discard)
|
||||
zeroes = request.POST.get('vol_detect_zeroes', default_zeroes)
|
||||
|
||||
conn.edit_disk(target_dev, new_path, readonly, shareable, bus, serial, format,
|
||||
cache, io, discard, zeroes)
|
||||
|
||||
if not conn.get_status() == 5:
|
||||
messages.success(request, _("Disk changes changes are applied. " +
|
||||
"But it will be activated after shutdown"))
|
||||
else:
|
||||
messages.success(request, _("Disk is changed successfully."))
|
||||
msg = _('Edit disk: ' + target_dev)
|
||||
addlogmsg(request.user.username, instance.name, msg)
|
||||
|
||||
return HttpResponseRedirect(request.get_full_path() + '#disks')
|
||||
|
||||
if 'delete_vol' in request.POST and allow_admin_or_not_template:
|
||||
storage = request.POST.get('storage', '')
|
||||
conn_delete = wvmStorage(compute.hostname,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</a>
|
||||
|
||||
<!-- Modal pool -->
|
||||
<div class="modal fade" id="AddQos{{ id }}" tabindex="-1" role="dialog" aria-labelledby="AddQosLabel"
|
||||
<div class="modal fade" id="AddQos{{ id }}" tabindex="-1" role="dialog" aria-labelledby="AddQosLabel{{ id }}"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
|
|
|
@ -494,6 +494,31 @@ class wvmConnect(object):
|
|||
'unsafe': 'Unsafe', # since libvirt 0.9.7
|
||||
}
|
||||
|
||||
def get_io_modes(self):
|
||||
"""Get io threads available modes"""
|
||||
return {
|
||||
'default': 'Default',
|
||||
'native': 'Native',
|
||||
'threads': 'Threads',
|
||||
}
|
||||
|
||||
def get_discard_modes(self):
|
||||
"""Get discard available modes"""
|
||||
return {
|
||||
'default': 'Default',
|
||||
'ignore': 'Ignore',
|
||||
'unmap': 'Unmap',
|
||||
}
|
||||
|
||||
def get_detect_zeroes_modes(self):
|
||||
"""Get detect zeroes available modes"""
|
||||
return {
|
||||
'default': 'Default',
|
||||
'on': 'On',
|
||||
'off': 'Off',
|
||||
'unmap': 'Unmap',
|
||||
}
|
||||
|
||||
def get_hypervisors_domain_types(self):
|
||||
"""Return hypervisor type"""
|
||||
def hypervisors(ctx):
|
||||
|
@ -614,6 +639,10 @@ class wvmConnect(object):
|
|||
return [v.text for v in ctx.xpath("/domainCapabilities/devices/hostdev/enum[@name='subsysType']/value")]
|
||||
return util.get_xml_path(self.get_dom_cap_xml(arch, machine), func=get_hostdev_list)
|
||||
|
||||
def get_network_models(self):
|
||||
"""Get available image filename extensions"""
|
||||
return ['default', 'e1000', 'virtio']
|
||||
|
||||
def get_image_formats(self):
|
||||
"""Get available image formats"""
|
||||
return ['raw', 'qcow', 'qcow2']
|
||||
|
|
|
@ -4,7 +4,8 @@ from vrtManager.connection import wvmConnect
|
|||
from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_OWNER as DEFAULT_OWNER
|
||||
from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_FORMAT
|
||||
from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER
|
||||
from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_DRIVER_OPTS as OPTS
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -165,7 +166,11 @@ class wvmCreate(wvmConnect):
|
|||
vol = self.get_volume_by_path(path)
|
||||
vol.delete()
|
||||
|
||||
def create_instance(self, name, memory, vcpu, vcpu_mode, uuid, arch, machine, firmware, images, cache_mode, networks, nwfilter, graphics, virtio, listen_addr, video="vga", console_pass="random", mac=None, qemu_ga=False):
|
||||
def create_instance(self, name, memory, vcpu, vcpu_mode, uuid, arch, machine, firmware, images,
|
||||
networks, nwfilter, graphics, virtio, listen_addr,
|
||||
video="vga", console_pass="random", mac=None,
|
||||
cache_mode=None, io_mode=None, discard_mode=None, detect_zeroes_mode=None,
|
||||
qemu_ga=True):
|
||||
"""
|
||||
Create VM function
|
||||
"""
|
||||
|
@ -173,7 +178,6 @@ class wvmCreate(wvmConnect):
|
|||
dom_caps = self.get_dom_capabilities(arch, machine)
|
||||
|
||||
memory = int(memory) * 1024
|
||||
#hypervisor_type = 'kvm' if self.is_kvm_supported() else 'qemu'
|
||||
|
||||
xml = """
|
||||
<domain type='%s'>
|
||||
|
@ -237,6 +241,17 @@ class wvmCreate(wvmConnect):
|
|||
hd_disk_letters = list(string.lowercase)
|
||||
sd_disk_letters = list(string.lowercase)
|
||||
add_cd = True
|
||||
|
||||
disk_opts = ''
|
||||
if cache_mode is not None and cache_mode != 'default':
|
||||
disk_opts += "cache='%s' " % cache_mode
|
||||
if io_mode is not None and io_mode != 'default':
|
||||
disk_opts += "io='%s' " % io_mode
|
||||
if discard_mode is not None and discard_mode != 'default':
|
||||
disk_opts += "discard='%s' " % discard_mode
|
||||
if detect_zeroes_mode is not None and detect_zeroes_mode != 'default':
|
||||
disk_opts += "detect_zeroes='%s' " % detect_zeroes_mode
|
||||
|
||||
for volume in images:
|
||||
stg = self.get_storage_by_vol_path(volume['path'])
|
||||
stg_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type")
|
||||
|
@ -246,7 +261,7 @@ class wvmCreate(wvmConnect):
|
|||
if stg_type == 'rbd':
|
||||
ceph_user, secret_uuid, ceph_hosts = get_rbd_storage_data(stg)
|
||||
xml += """<disk type='network' device='disk'>
|
||||
<driver name='qemu' type='%s' cache='%s' %s />""" % (volume['type'], cache_mode, OPTS.get("network", ''))
|
||||
<driver name='qemu' type='%s' %s />""" % (volume['type'], disk_opts)
|
||||
xml += """ <auth username='%s'>
|
||||
<secret type='ceph' uuid='%s'/>
|
||||
</auth>
|
||||
|
@ -262,7 +277,7 @@ class wvmCreate(wvmConnect):
|
|||
xml += """</source>"""
|
||||
else:
|
||||
xml += """<disk type='file' device='%s'>""" % volume['device']
|
||||
xml += """ <driver name='qemu' type='%s' cache='%s' %s/>""" % (volume['type'], cache_mode, OPTS.get("file", ''))
|
||||
xml += """ <driver name='qemu' type='%s' %s/>""" % (volume['type'], disk_opts)
|
||||
xml += """ <source file='%s'/>""" % volume['path']
|
||||
|
||||
if volume.get('bus') == 'virtio':
|
||||
|
@ -313,7 +328,12 @@ class wvmCreate(wvmConnect):
|
|||
|
||||
if 'usb' in dom_caps['disk_bus']:
|
||||
xml += """<input type='mouse' bus='{}'/>""".format('virtio' if virtio else 'usb')
|
||||
xml += """<input type='keyboard' bus='{}'/>""".format('virtio' if virtio else 'usb')
|
||||
xml += """<input type='tablet' bus='{}'/>""".format('virtio' if virtio else 'usb')
|
||||
else:
|
||||
xml += """<input type='mouse'/>"""
|
||||
xml += """<input type='keyboard'/>"""
|
||||
xml += """<input type='tablet'/>"""
|
||||
|
||||
xml += """
|
||||
<graphics type='%s' port='-1' autoport='yes' %s listen='%s'/>
|
||||
|
|
|
@ -287,8 +287,8 @@ class wvmInstance(wvmConnect):
|
|||
leases = []
|
||||
|
||||
def extract_dom(info):
|
||||
ipv4 = None
|
||||
ipv6 = None
|
||||
ipv4 = []
|
||||
ipv6 = []
|
||||
for addrs in info.values():
|
||||
if addrs["hwaddr"] != iface_mac:
|
||||
continue
|
||||
|
@ -296,20 +296,20 @@ class wvmInstance(wvmConnect):
|
|||
continue
|
||||
for addr in addrs["addrs"]:
|
||||
if addr["type"] == 0:
|
||||
ipv4 = addr["addr"]
|
||||
ipv4.append(addr["addr"])
|
||||
elif (addr["type"] == 1 and
|
||||
not str(addr["addr"]).startswith("fe80")):
|
||||
ipv6 = addr["addr"] + "/" + str(addr["prefix"])
|
||||
ipv6.append(addr["addr"] + "/" + str(addr["prefix"]))
|
||||
return ipv4, ipv6
|
||||
|
||||
def extract_lease(info):
|
||||
ipv4 = None
|
||||
ipv6 = None
|
||||
ipv4 = []
|
||||
ipv6 = []
|
||||
if info["mac"] == iface_mac:
|
||||
if info["type"] == 0:
|
||||
ipv4 = info["ipaddr"]
|
||||
ipv4.append(info["ipaddr"])
|
||||
elif info["type"] == 1:
|
||||
ipv6 = info["ipaddr"]
|
||||
ipv6.append(info["ipaddr"])
|
||||
return ipv4, ipv6
|
||||
|
||||
for ips in ([qemuga] + leases + [arp]):
|
||||
|
@ -354,6 +354,7 @@ class wvmInstance(wvmConnect):
|
|||
target_inst = '' if not net.xpath('target/@dev') else net.xpath('target/@dev')[0]
|
||||
link_state = 'up' if not net.xpath('link') else net.xpath('link/@state')[0]
|
||||
filterref_inst = '' if not net.xpath('filterref/@filter') else net.xpath('filterref/@filter')[0]
|
||||
model_type = net.xpath('model/@type')[0]
|
||||
if net.xpath('bandwidth/inbound'):
|
||||
in_attr = net.xpath('bandwidth/inbound')[0]
|
||||
in_av = in_attr.get('average')
|
||||
|
@ -375,6 +376,7 @@ class wvmInstance(wvmConnect):
|
|||
'nic': nic_inst,
|
||||
'target': target_inst,
|
||||
'state': link_state,
|
||||
'model': model_type,
|
||||
'ipv4': ipv4,
|
||||
'ipv6': ipv6,
|
||||
'filterref': filterref_inst,
|
||||
|
@ -388,10 +390,13 @@ class wvmInstance(wvmConnect):
|
|||
def get_disk_devices(self):
|
||||
def disks(doc):
|
||||
result = []
|
||||
dev = volume = storage = src_file = bus = None
|
||||
disk_format = used_size = disk_size = disk_cache = None
|
||||
|
||||
for disk in doc.xpath('/domain/devices/disk'):
|
||||
dev = volume = storage = src_file = bus = None
|
||||
disk_format = used_size = disk_size = None
|
||||
disk_cache = disk_io = disk_discard = disk_zeroes = 'default'
|
||||
readonly = shareable = serial = None
|
||||
|
||||
device = disk.xpath('@device')[0]
|
||||
if device == 'disk':
|
||||
try:
|
||||
|
@ -406,6 +411,23 @@ class wvmInstance(wvmConnect):
|
|||
disk_cache = disk.xpath('driver/@cache')[0]
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
disk_io = disk.xpath('driver/@io')[0]
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
disk_discard = disk.xpath('driver/@discard')[0]
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
disk_zeroes = disk.xpath('driver/@detect_zeroes')[0]
|
||||
except:
|
||||
pass
|
||||
|
||||
readonly = True if disk.xpath('readonly') else False
|
||||
shareable = True if disk.xpath('shareable') else False
|
||||
serial = disk.xpath('serial')[0].text if disk.xpath('serial') else None
|
||||
|
||||
try:
|
||||
vol = self.get_volume_by_path(src_file)
|
||||
volume = vol.name()
|
||||
|
@ -421,7 +443,9 @@ class wvmInstance(wvmConnect):
|
|||
finally:
|
||||
result.append(
|
||||
{'dev': dev, 'bus': bus, 'image': volume, 'storage': storage, 'path': src_file,
|
||||
'format': disk_format, 'size': disk_size, 'used': used_size, 'cache': disk_cache})
|
||||
'format': disk_format, 'size': disk_size, 'used': used_size,
|
||||
'cache': disk_cache, 'io': disk_io, 'discard': disk_discard, 'detect_zeroes': disk_zeroes,
|
||||
'readonly': readonly, 'shareable': shareable, 'serial': serial})
|
||||
return result
|
||||
|
||||
return util.get_xml_path(self._XMLDesc(0), func=disks)
|
||||
|
@ -620,39 +644,88 @@ class wvmInstance(wvmConnect):
|
|||
xmldom = ElementTree.tostring(tree)
|
||||
self._defineXML(xmldom)
|
||||
|
||||
def attach_disk(self, source, target, sourcetype='file', device='disk', driver='qemu', subdriver='raw', cache='none', targetbus='ide'):
|
||||
xml_disk = "<disk type='%s' device='%s'>" % (sourcetype, device)
|
||||
if device == 'cdrom':
|
||||
xml_disk += "<driver name='%s' type='%s'/>" % (driver, subdriver)
|
||||
elif device == 'disk':
|
||||
xml_disk += "<driver name='%s' type='%s' cache='%s'/>" % (driver, subdriver, cache)
|
||||
def attach_disk(self, source, target_dev, target_bus='ide', disk_type='file',
|
||||
disk_device='disk', driver_name='qemu', driver_type='raw',
|
||||
readonly=False, shareable=False, serial=None,
|
||||
cache_mode=None, io_mode=None, discard_mode=None, detect_zeroes_mode=None):
|
||||
|
||||
additionals = ''
|
||||
if cache_mode is not None and cache_mode != 'default':
|
||||
additionals += "cache='%s' " % cache_mode
|
||||
if io_mode is not None and io_mode != 'default':
|
||||
additionals += "io='%s' " % io_mode
|
||||
if discard_mode is not None and discard_mode != 'default':
|
||||
additionals += "discard='%s' " % discard_mode
|
||||
if detect_zeroes_mode is not None and detect_zeroes_mode != 'default':
|
||||
additionals += "detect_zeroes='%s' " % detect_zeroes_mode
|
||||
|
||||
xml_disk = "<disk type='%s' device='%s'>" % (disk_type, disk_device)
|
||||
if disk_device == 'cdrom':
|
||||
xml_disk += "<driver name='%s' type='%s'/>" % (driver_name, driver_type)
|
||||
elif disk_device == 'disk':
|
||||
xml_disk += "<driver name='%s' type='%s' %s/>" % (driver_name, driver_type, additionals)
|
||||
xml_disk += """<source file='%s'/>
|
||||
<target dev='%s' bus='%s'/>
|
||||
</disk>
|
||||
""" % (source, target, targetbus)
|
||||
<target dev='%s' bus='%s'/>""" % (source, target_dev, target_bus)
|
||||
if readonly:
|
||||
xml_disk += """<readonly/>"""
|
||||
if shareable:
|
||||
xml_disk += """<shareable/>"""
|
||||
if serial is not None and serial != 'None' and serial != '':
|
||||
xml_disk += """<serial>%s</serial>""" % serial
|
||||
xml_disk += """</disk>"""
|
||||
if self.get_status() == 1:
|
||||
self.instance.attachDeviceFlags(xml_disk, VIR_DOMAIN_AFFECT_LIVE)
|
||||
self.instance.attachDeviceFlags(xml_disk, VIR_DOMAIN_AFFECT_CONFIG)
|
||||
if self.get_status() == 5:
|
||||
self.instance.attachDeviceFlags(xml_disk, VIR_DOMAIN_AFFECT_CONFIG)
|
||||
|
||||
def detach_disk(self, dev):
|
||||
tree = ElementTree.fromstring(self._XMLDesc(0))
|
||||
def detach_disk(self, target_dev):
|
||||
tree = etree.fromstring(self._XMLDesc(0))
|
||||
|
||||
for disk in tree.findall("./devices/disk"):
|
||||
target = disk.find("target")
|
||||
if target.get("dev") == dev:
|
||||
devices = tree.find('devices')
|
||||
devices.remove(disk)
|
||||
disk_el = tree.xpath("./devices/disk/target[@dev='{}']".format(target_dev))[0].getparent()
|
||||
xml_disk = etree.tostring(disk_el)
|
||||
devices = tree.find('devices')
|
||||
devices.remove(disk_el)
|
||||
|
||||
if self.get_status() == 1:
|
||||
xml_disk = ElementTree.tostring(disk)
|
||||
ret = self.instance.detachDevice(xml_disk)
|
||||
xmldom = self._XMLDesc(VIR_DOMAIN_XML_SECURE)
|
||||
if self.get_status() == 5:
|
||||
xmldom = ElementTree.tostring(tree)
|
||||
break
|
||||
self._defineXML(xmldom)
|
||||
if self.get_status() == 1:
|
||||
self.instance.detachDeviceFlags(xml_disk, VIR_DOMAIN_AFFECT_LIVE)
|
||||
self.instance.detachDeviceFlags(xml_disk, VIR_DOMAIN_AFFECT_CONFIG)
|
||||
if self.get_status() == 5:
|
||||
self.instance.detachDeviceFlags(xml_disk, VIR_DOMAIN_AFFECT_CONFIG)
|
||||
|
||||
def edit_disk(self, target_dev, source, readonly, shareable, target_bus, serial, format, cache_mode, io_mode, discard_mode, detect_zeroes_mode):
|
||||
tree = etree.fromstring(self._XMLDesc(0))
|
||||
disk_el = tree.xpath("./devices/disk/target[@dev='{}']".format(target_dev))[0].getparent()
|
||||
old_disk_type = disk_el.get('type')
|
||||
old_disk_device = disk_el.get('device')
|
||||
old_driver_name = disk_el.xpath('driver/@name')[0]
|
||||
|
||||
additionals = ''
|
||||
if cache_mode is not None and cache_mode != 'default':
|
||||
additionals += "cache='%s' " % cache_mode
|
||||
if io_mode is not None and io_mode != 'default':
|
||||
additionals += "io='%s' " % io_mode
|
||||
if discard_mode is not None and discard_mode != 'default':
|
||||
additionals += "discard='%s' " % discard_mode
|
||||
if detect_zeroes_mode is not None and detect_zeroes_mode != 'default':
|
||||
additionals += "detect_zeroes='%s' " % detect_zeroes_mode
|
||||
|
||||
xml_disk = "<disk type='%s' device='%s'>" % (old_disk_type, old_disk_device)
|
||||
if old_disk_device == 'cdrom':
|
||||
xml_disk += "<driver name='%s' type='%s'/>" % (old_driver_name, format)
|
||||
elif old_disk_device == 'disk':
|
||||
xml_disk += "<driver name='%s' type='%s' %s/>" % (old_driver_name, format, additionals)
|
||||
xml_disk += """<source file='%s'/>
|
||||
<target dev='%s' bus='%s'/>""" % (source, target_dev, target_bus)
|
||||
if readonly:
|
||||
xml_disk += """<readonly/>"""
|
||||
if shareable:
|
||||
xml_disk += """<shareable/>"""
|
||||
if serial is not None and serial != 'None' and serial != '':
|
||||
xml_disk += """<serial>%s</serial>""" % serial
|
||||
xml_disk += """</disk>"""
|
||||
|
||||
self.instance.updateDeviceFlags(xml_disk, VIR_DOMAIN_AFFECT_CONFIG)
|
||||
|
||||
def cpu_usage(self):
|
||||
cpu_usage = {}
|
||||
|
@ -1241,14 +1314,21 @@ class wvmInstance(wvmConnect):
|
|||
net_source = network_data.get('net-source-' + str(num))
|
||||
net_source_type = network_data.get('net-source-' + str(num) + '-type')
|
||||
net_filter = network_data.get('net-nwfilter-' + str(num))
|
||||
net_model = network_data.get('net-model-' + str(num))
|
||||
bridge_name = self.get_bridge_name(net_source, net_source_type)
|
||||
if interface.get('type') == 'bridge':
|
||||
source = interface.find('mac')
|
||||
source.set('address', net_mac)
|
||||
source = interface.find('source')
|
||||
source.set('bridge', bridge_name)
|
||||
source = interface.find('filterref')
|
||||
|
||||
source = interface.find('model')
|
||||
if net_model != 'default':
|
||||
source.attrib['type'] = net_model
|
||||
else:
|
||||
interface.remove(source)
|
||||
|
||||
source = interface.find('filterref')
|
||||
if net_filter:
|
||||
if source is not None: source.set('filter', net_filter)
|
||||
else:
|
||||
|
@ -1262,8 +1342,14 @@ class wvmInstance(wvmConnect):
|
|||
source.set('address', net_mac)
|
||||
source = interface.find('source')
|
||||
source.set('network', net_source)
|
||||
source = interface.find('filterref')
|
||||
|
||||
source = interface.find('model')
|
||||
if net_model != 'default':
|
||||
source.attrib['type'] = net_model
|
||||
else:
|
||||
interface.remove(source)
|
||||
|
||||
source = interface.find('filterref')
|
||||
if net_filter:
|
||||
if source is not None: source.set('filter', net_filter)
|
||||
else:
|
||||
|
|
|
@ -158,17 +158,21 @@ INSTANCE_VOLUME_DEFAULT_FORMAT = 'qcow2'
|
|||
# available bus types: virtio, scsi, ide, usb, sata
|
||||
INSTANCE_VOLUME_DEFAULT_BUS = 'virtio'
|
||||
|
||||
#SCSI types: 'virtio-scsi', 'lsilogic'
|
||||
#SCSI types: virtio-scsi, lsilogic
|
||||
INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER = 'virtio-scsi'
|
||||
|
||||
# Volume optionals: two variable: disk driver type is file and network(rbd, iscsi),
|
||||
# optionals : discard='unmap|ignore', detect_zeroes='on|off|unmap', copy_on_read='on|off'
|
||||
# Example: {"file": "discard='unmap' copy_on_read='on'", "network": "detect_zeroes='unmap'"}
|
||||
INSTANCE_VOLUME_DEFAULT_DRIVER_OPTS = {"file": "", "network": ""}
|
||||
|
||||
# available cache types: none, unsafe, writeback, writethrough
|
||||
# Volume cache: default, directsync, none, unsafe, writeback, writethrough
|
||||
INSTANCE_VOLUME_DEFAULT_CACHE = 'directsync'
|
||||
|
||||
# Volume io mode: default, native, threads
|
||||
INSTANCE_VOLUME_DEFAULT_IO = 'default'
|
||||
|
||||
# Volume detect zeroes mode: default, on, off, unmap
|
||||
INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES = 'default'
|
||||
|
||||
# Volume discard mode: default, unmap, ignore
|
||||
INSTANCE_VOLUME_DEFAULT_DISCARD = 'default'
|
||||
|
||||
# up to os, 0=root, 107=qemu or libvirt-bin(for ubuntu)
|
||||
INSTANCE_VOLUME_DEFAULT_OWNER = {'uid': 0, 'guid': 0}
|
||||
|
||||
|
|
Loading…
Reference in a new issue