diff --git a/circle/common/models.py b/circle/common/models.py index 0a2153f..64f3fd5 100644 --- a/circle/common/models.py +++ b/circle/common/models.py @@ -27,6 +27,7 @@ from warnings import warn from django.contrib import messages from django.contrib.auth.models import User from django.core.cache import cache +from django.core.exceptions import PermissionDenied from django.core.serializers.json import DjangoJSONEncoder from django.db.models import ( CharField, DateTimeField, ForeignKey, NullBooleanField @@ -413,6 +414,10 @@ class HumanReadableObject(object): self._set_values(user_text_template, admin_text_template, params) def _set_values(self, user_text_template, admin_text_template, params): + if isinstance(user_text_template, Promise): + user_text_template = user_text_template._proxy____args[0] + if isinstance(admin_text_template, Promise): + admin_text_template = admin_text_template._proxy____args[0] self.user_text_template = user_text_template self.admin_text_template = admin_text_template self.params = params @@ -451,6 +456,12 @@ class HumanReadableObject(object): self.user_text_template, unicode(self.params)) return self.user_text_template + def get_text(self, user): + if user and user.is_superuser: + return self.get_admin_text() + else: + return self.get_user_text() + def to_dict(self): return {"user_text_template": self.user_text_template, "admin_text_template": self.admin_text_template, @@ -481,13 +492,34 @@ class HumanReadableException(HumanReadableObject, Exception): self.level = "error" def send_message(self, request, level=None): - if request.user and request.user.is_superuser: - msg = self.get_admin_text() - else: - msg = self.get_user_text() + msg = self.get_text(request.user) getattr(messages, level or self.level)(request, msg) +def fetch_human_exception(exception, user=None): + """Fetch user readable message from exception. + + >>> r = humanize_exception("foo", Exception()) + >>> fetch_human_exception(r, User()) + u'foo' + >>> fetch_human_exception(r).get_text(User()) + u'foo' + >>> fetch_human_exception(Exception(), User()) + u'Unknown error' + >>> fetch_human_exception(PermissionDenied(), User()) + u'Permission Denied' + """ + + if not isinstance(exception, HumanReadableException): + if isinstance(exception, PermissionDenied): + exception = create_readable(ugettext_noop("Permission Denied")) + else: + exception = create_readable(ugettext_noop("Unknown error"), + ugettext_noop("Unknown error: %(ex)s"), + ex=unicode(exception)) + return exception.get_text(user) if user else exception + + def humanize_exception(message, exception=None, level=None, **params): """Return new dynamic-class exception which is based on HumanReadableException and the original class with the dict of exception. diff --git a/circle/common/operations.py b/circle/common/operations.py index da985ac..4c5413d 100644 --- a/circle/common/operations.py +++ b/circle/common/operations.py @@ -18,10 +18,10 @@ from inspect import getargspec from logging import getLogger -from .models import activity_context, has_suffix - from django.core.exceptions import PermissionDenied, ImproperlyConfigured +from django.utils.translation import ugettext_noop +from .models import activity_context, has_suffix, humanize_exception logger = getLogger(__name__) @@ -31,6 +31,7 @@ class Operation(object): """ async_queue = 'localhost.man' required_perms = None + superuser_required = False do_not_call_in_templates = True abortable = False has_percentage = False @@ -143,13 +144,26 @@ class Operation(object): def check_precond(self): pass - def check_auth(self, user): - if self.required_perms is None: + @classmethod + def check_perms(cls, user): + """Check if user is permitted to run this operation on any instance + """ + + if cls.required_perms is None: raise ImproperlyConfigured( "Set required_perms to () if none needed.") - if not user.has_perms(self.required_perms): + if not user.has_perms(cls.required_perms): raise PermissionDenied("%s doesn't have the required permissions." % user) + if cls.superuser_required and not user.is_superuser: + raise humanize_exception(ugettext_noop( + "Superuser privileges are required."), PermissionDenied()) + + def check_auth(self, user): + """Check if user is permitted to run this operation on this instance + """ + + self.check_perms(user) def create_activity(self, parent, user, kwargs): raise NotImplementedError @@ -185,14 +199,17 @@ class OperatedMixin(object): def __getattr__(self, name): # NOTE: __getattr__ is only called if the attribute doesn't already # exist in your __dict__ - cls = self.__class__ + return self.get_operation_class(name)(self) + + @classmethod + def get_operation_class(cls, name): ops = getattr(cls, operation_registry_name, {}) op = ops.get(name) if op: - return op(self) + return op else: raise AttributeError("%r object has no attribute %r" % - (self.__class__.__name__, name)) + (cls.__name__, name)) def get_available_operations(self, user): """Yield Operations that match permissions of user and preconditions. diff --git a/circle/dashboard/static/dashboard/dashboard.css b/circle/dashboard/static/dashboard/dashboard.css index 197b77c..f5eb508 100644 --- a/circle/dashboard/static/dashboard/dashboard.css +++ b/circle/dashboard/static/dashboard/dashboard.css @@ -867,3 +867,76 @@ textarea[name="list-new-namelist"] { border-bottom: 1px dotted #aaa; padding: 5px 0px; } + + +#vm-list-table .migrating-icon { + -webkit-animation: passing 2s linear infinite; + animation: passing 2s linear infinite; +} + +@-webkit-keyframes passing { + 0% { + -webkit-transform: translateX(50%); + transform: translateX(50%); + opacity: 0; + } + + 50% { + -webkit-transform: translateX(0%); + transform: translateX(0%); + opacity: 1; + } + + 100% { + -webkit-transform: translateX(-50%); + transform: translateX(-50%); + opacity: 0; + } +} + +@keyframes passing { + 0% { + -webkit-transform: translateX(50%); + -ms-transform: translateX(50%); + transform: translateX(50%); + opacity: 0; + } + + 50% { + -webkit-transform: translateX(0%); + -ms-transform: translateX(0%); + transform: translateX(0%); + opacity: 1; + } + + 100% { + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); + opacity: 0; + } +} + +.mass-migrate-node { + cursor: pointer; +} + +.mass-op-panel { + padding: 6px 10px; +} + +.mass-op-panel .check { + color: #449d44; +} + +.mass-op-panel .minus { + color: #d9534f; +} + +.mass-op-panel .status-icon { + font-size: .8em; +} + +#vm-list-search, #vm-mass-ops { + margin-top: 8px; +} diff --git a/circle/dashboard/static/dashboard/dashboard.js b/circle/dashboard/static/dashboard/dashboard.js index 9f66211..f7e5448 100644 --- a/circle/dashboard/static/dashboard/dashboard.js +++ b/circle/dashboard/static/dashboard/dashboard.js @@ -488,14 +488,19 @@ function addSliderMiscs() { ram_fire = true; $(".ram-slider").simpleSlider("setValue", parseInt(val)); }); - $(".cpu-priority-input").trigger("change"); - $(".cpu-count-input, .ram-input").trigger("input"); + + setDefaultSliderValues(); $(".cpu-priority-slider").simpleSlider("setDisabled", $(".cpu-priority-input").prop("disabled")); $(".cpu-count-slider").simpleSlider("setDisabled", $(".cpu-count-input").prop("disabled")); $(".ram-slider").simpleSlider("setDisabled", $(".ram-input").prop("disabled")); } +function setDefaultSliderValues() { + $(".cpu-priority-input").trigger("change"); + $(".ram-input, .cpu-count-input").trigger("input"); +} + /* deletes the VM with the pk * if dir is true, then redirect to the dashboard landing page diff --git a/circle/dashboard/static/dashboard/vm-create.js b/circle/dashboard/static/dashboard/vm-create.js index 8806993..bf082e4 100644 --- a/circle/dashboard/static/dashboard/vm-create.js +++ b/circle/dashboard/static/dashboard/vm-create.js @@ -28,6 +28,9 @@ function vmCreateLoaded() { $('#create-modal').on('hidden.bs.modal', function() { $('#create-modal').remove(); }); + $("#create-modal").on("shown.bs.modal", function() { + setDefaultSliderValues(); + }); }); return false; }); @@ -217,6 +220,8 @@ function vmCustomizeLoaded() { }); if(error) return true; + $(this).find("i").prop("class", "fa fa-spinner fa-spin"); + $.ajax({ url: '/dashboard/vm/create/', headers: {"X-CSRFToken": getCookie('csrftoken')}, diff --git a/circle/dashboard/static/dashboard/vm-list.js b/circle/dashboard/static/dashboard/vm-list.js index cd19fcd..1967817 100644 --- a/circle/dashboard/static/dashboard/vm-list.js +++ b/circle/dashboard/static/dashboard/vm-list.js @@ -14,6 +14,7 @@ $(function() { $('.vm-list-table tbody').find('tr').mousedown(function() { var retval = true; + if(!$(this).data("vm-pk")) return; if (ctrlDown) { setRowColor($(this)); if(!$(this).hasClass('vm-list-selected')) { @@ -46,86 +47,20 @@ $(function() { selected = [{'index': $(this).index(), 'vm': $(this).data("vm-pk")}]; } - // reset btn disables - $('.vm-list-table tbody tr .btn').attr('disabled', false); // show/hide group controls if(selected.length > 0) { - $('.vm-list-group-control a').attr('disabled', false); - for(var i = 0; i < selected.length; i++) { - $('.vm-list-table tbody tr').eq(selected[i]).find('.btn').attr('disabled', true); - } + $('#vm-mass-ops .mass-operation').attr('disabled', false); } else { - $('.vm-list-group-control a').attr('disabled', true); + $('#vm-mass-ops .mass-operation').attr('disabled', true); } return retval; }); - - $('#vm-list-group-migrate').click(function() { - // pass? - }); - - $('.vm-list-details').popover({ - 'placement': 'auto', - 'html': true, - 'trigger': 'hover' - }); - - $('.vm-list-connect').popover({ - 'placement': 'left', - 'html': true, - 'trigger': 'click' - }); - $('tbody a').mousedown(function(e) { // parent tr doesn't get selected when clicked e.stopPropagation(); }); - $('tbody a').click(function(e) { - // browser doesn't jump to top when clicked the buttons - if(!$(this).hasClass('real-link')) { - return false; - } - }); - - /* rename */ - $("#vm-list-rename-button, .vm-details-rename-button").click(function() { - $("#vm-list-column-name", $(this).closest("tr")).hide(); - $("#vm-list-rename", $(this).closest("tr")).css('display', 'inline'); - $("#vm-list-rename-name", $(this).closest("tr")).focus(); - }); - - /* rename ajax */ - $('.vm-list-rename-submit').click(function() { - var row = $(this).closest("tr") - var name = $('#vm-list-rename-name', row).val(); - var url = '/dashboard/vm/' + row.children("td:first-child").text().replace(" ", "") + '/'; - $.ajax({ - method: 'POST', - url: url, - data: {'new_name': name}, - headers: {"X-CSRFToken": getCookie('csrftoken')}, - success: function(data, textStatus, xhr) { - - $("#vm-list-column-name", row).html( - $("<a/>", { - 'class': "real-link", - href: "/dashboard/vm/" + data['vm_pk'] + "/", - text: data['new_name'] - }) - ).show(); - $('#vm-list-rename', row).hide(); - // addMessage(data['message'], "success"); - }, - error: function(xhr, textStatus, error) { - addMessage("Error during renaming!", "danger"); - } - }); - return false; - }); - - /* group actions */ /* select all */ @@ -133,27 +68,69 @@ $(function() { $('.vm-list-table tbody tr').each(function() { var index = $(this).index(); var vm = $(this).data("vm-pk"); - if(!isAlreadySelected(vm)) { + if(vm && !isAlreadySelected(vm)) { selected.push({'index': index, 'vm': vm}); $(this).addClass('vm-list-selected'); } }); if(selected.length > 0) - $('.vm-list-group-control a').attr('disabled', false); + $('#vm-mass-ops .mass-operation').attr('disabled', false); return false; }); - /* mass vm delete */ - $('#vm-list-group-delete').click(function() { - addModalConfirmation(massDeleteVm, - { - 'url': '/dashboard/vm/mass-delete/', - 'data': { - 'selected': selected, - 'v': collectIds(selected) + + /* mass operations */ + $("#vm-mass-ops").on('click', '.mass-operation', function(e) { + var icon = $(this).children("i").addClass('fa-spinner fa-spin'); + params = "?" + selected.map(function(a){return "vm=" + a.vm}).join("&"); + + $.ajax({ + type: 'GET', + url: $(this).attr('href') + params, + success: function(data) { + icon.removeClass("fa-spinner fa-spin"); + $('body').append(data); + $('#confirmation-modal').modal('show'); + $('#confirmation-modal').on('hidden.bs.modal', function() { + $('#confirmation-modal').remove(); + }); + $("[title]").tooltip({'placement': "left"}); + } + }); + return false; + }); + + + $("body").on("click", "#op-form-send", function() { + var url = $(this).closest("form").prop("action"); + $(this).find("i").prop("class", "fa fa-fw fa-spinner fa-spin"); + + $.ajax({ + url: url, + headers: {"X-CSRFToken": getCookie('csrftoken')}, + type: 'POST', + data: $(this).closest('form').serialize(), + success: function(data, textStatus, xhr) { + /* hide the modal we just submitted */ + $('#confirmation-modal').modal("hide"); + + updateStatuses(1); + + /* if there are messages display them */ + if(data.messages && data.messages.length > 0) { + addMessage(data.messages.join("<br />"), "danger"); + } + }, + error: function(xhr, textStatus, error) { + $('#confirmation-modal').modal("hide"); + + if (xhr.status == 500) { + addMessage("500 Internal Server Error", "danger"); + } else { + addMessage(xhr.status + " " + xhr.statusText, "danger"); } } - ); + }); return false; }); @@ -181,8 +158,65 @@ $(function() { $(".vm-list-table th a").on("click", function(event) { event.preventDefault(); }); + + $(document).on("click", ".mass-migrate-node", function() { + $(this).find('input[type="radio"]').prop("checked", true); + }); + + if(checkStatusUpdate()) { + updateStatuses(1); + } }); + +function checkStatusUpdate() { + icons = $("#vm-list-table tbody td.state i"); + if(icons.hasClass("fa-spin") || icons.hasClass("migrating-icon")) { + return true; + } +} + + +function updateStatuses(runs) { + $.get("/dashboard/vm/list/?compact", function(result) { + $("#vm-list-table tbody tr").each(function() { + vm = $(this).data("vm-pk"); + status_td = $(this).find("td.state"); + status_icon = status_td.find("i"); + status_text = status_td.find("span"); + + if(vm in result) { + if(result[vm].in_status_change) { + if(!status_icon.hasClass("fa-spin")) { + status_icon.prop("class", "fa fa-fw fa-spinner fa-spin"); + } + } + else if(result[vm].status == "MIGRATING") { + if(!status_icon.hasClass("migrating-icon")) { + status_icon.prop("class", "fa fa-fw " + result[vm].icon + " migrating-icon"); + } + } else { + status_icon.prop("class", "fa fa-fw " + result[vm].icon); + } + status_text.text(result[vm].status); + if("node" in result[vm]) { + $(this).find(".node").text(result[vm].node); + } + } else { + $(this).remove(); + } + }); + + if(checkStatusUpdate()) { + setTimeout( + function() {updateStatuses(runs + 1)}, + 1000 + Math.exp(runs * 0.05) + ); + } + }); +} + + function isAlreadySelected(vm) { for(var i=0; i<selected.length; i++) if(selected[i].vm == vm) diff --git a/circle/dashboard/templates/dashboard/_notifications-timeline.html b/circle/dashboard/templates/dashboard/_notifications-timeline.html index 3192f75..31cd4b2 100644 --- a/circle/dashboard/templates/dashboard/_notifications-timeline.html +++ b/circle/dashboard/templates/dashboard/_notifications-timeline.html @@ -1,16 +1,17 @@ {% load i18n %} +{% load hro %} {% for n in notifications %} <li class="notification-message" id="msg-{{n.id}}"> <span class="notification-message-subject"> {% if n.status == "new" %}<i class="fa fa-envelope-o"></i> {% endif %} - {{ n.subject.get_user_text }} + {{ n.subject|get_text:user }} </span> <span class="notification-message-date pull-right" title="{{n.created}}"> {{ n.created|timesince }} </span> <div style="clear: both;"></div> <div class="notification-message-text"> - {{ n.message.get_user_text|safe }} + {{ n.message|get_text:user|safe }} </div> </li> {% empty %} diff --git a/circle/dashboard/templates/dashboard/_vm-mass-migrate.html b/circle/dashboard/templates/dashboard/_vm-mass-migrate.html new file mode 100644 index 0000000..6038785 --- /dev/null +++ b/circle/dashboard/templates/dashboard/_vm-mass-migrate.html @@ -0,0 +1,36 @@ +{% extends "dashboard/mass-operate.html" %} +{% load i18n %} +{% load sizefieldtags %} + + +{% block formfields %} + <hr /> + <ul id="vm-migrate-node-list" class="list-unstyled"> + <li class="panel panel-default panel-primary mass-migrate-node"> + <div class="panel-body"> + <label for="migrate-to-none"> + <strong>{% trans "Reschedule" %}</strong> + </label> + <input id="migrate-to-none" type="radio" name="node" value="" style="float: right;" checked="checked"> + <span class="vm-migrate-node-property"> + {% trans "This option will reschedule each virtual machine to the optimal node." %} + </span> + <div style="clear: both;"></div> + </div> + </li> + {% for n in nodes %} + <li class="panel panel-default mass-migrate-node"> + <div class="panel-body"> + <label for="migrate-to-{{n.pk}}"> + <strong>{{ n }}</strong> + </label> + <input id="migrate-to-{{n.pk}}" type="radio" name="node" value="{{ n.pk }}" style="float: right;"/> + <span class="vm-migrate-node-property">{% trans "CPU load" %}: {{ n.cpu_usage }}</span> + <span class="vm-migrate-node-property">{% trans "RAM usage" %}: {{ n.byte_ram_usage|filesize }}/{{ n.ram_size|filesize }}</span> + <div style="clear: both;"></div> + </div> + </li> + {% endfor %} + </ul> + <hr /> +{% endblock %} diff --git a/circle/dashboard/templates/dashboard/instanceactivity_detail.html b/circle/dashboard/templates/dashboard/instanceactivity_detail.html index a8acbbb..c16cfae 100644 --- a/circle/dashboard/templates/dashboard/instanceactivity_detail.html +++ b/circle/dashboard/templates/dashboard/instanceactivity_detail.html @@ -1,16 +1,12 @@ {% extends "dashboard/base.html" %} {% load i18n %} +{% load hro %} {% block content %} <div class="body-content"> <div class="page-header"> <h1><i class="fa fa-{{icon}}"></i> - {{ object.instance.name }}: - {% if user.is_superuser %} - {{object.readable_name.get_admin_text}} - {% else %} - {{object.readable_name.get_user_text}} - {% endif %} + {{ object.instance.name }}: {{object.readable_name|get_text:user}} </h1> </div> <div class="row"> @@ -58,7 +54,7 @@ <dt>{% trans "result" %}</dt> - <dd><textarea class="form-control">{% if user.is_superuser %}{{object.result.get_admin_text}}{% else %}{{object.result.get_user_text}}{% endif %}</textarea></dd> + <dd><textarea class="form-control">{{object.result|get_text:user}}</textarea></dd> <dt>{% trans "resultant state" %}</dt> <dd>{{object.resultant_state|default:'n/a'}}</dd> diff --git a/circle/dashboard/templates/dashboard/mass-operate.html b/circle/dashboard/templates/dashboard/mass-operate.html new file mode 100644 index 0000000..33d6e83 --- /dev/null +++ b/circle/dashboard/templates/dashboard/mass-operate.html @@ -0,0 +1,38 @@ +{% load i18n %} +{% load crispy_forms_tags %} + +{% block question %} +<p> +{% blocktrans with op=op.name count count=vm_count %} +Do you want to perform the <strong>{{op}}</strong> operation on the following instance? +{% plural %} +Do you want to perform the <strong>{{op}}</strong> operation on the following {{ count }} instances? +{% endblocktrans %} +</p> +<p class="text-info">{{op.description}}</p> +{% endblock %} +<form method="POST" action="{{url}}">{% csrf_token %} + {% block formfields %}{% endblock %} + {% for i in instances %} + <div class="panel panel-default mass-op-panel"> + <i class="fa {{ i.get_status_icon }} fa-fw"></i> + {{ i.name }} ({{ i.pk }}) + <div style="float: right;" title="{{ i.disabled }}" class="status-icon"> + <span class="fa-stack"> + <i class="fa fa-stack-2x fa-square {{ i.disabled|yesno:"minus,check" }}"></i> + <i class="fa fa-stack-1x fa-inverse fa-{% if i.disabled %}{{i.disabled_icon|default:"minus"}}{% else %}check{% endif %}"></i> + </span> + </div> + </div> + <input type="checkbox" name="vm" value="{{ i.pk }}" {% if not i.disabled %}checked{% endif %} + style="display: none;"/> + {% endfor %} + + <div class="pull-right"> + <a class="btn btn-default" href="{% url "dashboard.views.vm-list" %}" + data-dismiss="modal">{% trans "Cancel" %}</a> + <button class="btn btn-{{ opview.effect }}" type="submit" id="op-form-send"> + {% if opview.icon %}<i class="fa fa-fw fa-{{opview.icon}}"></i> {% endif %}{{ opview.name|capfirst }} + </button> + </div> +</form> diff --git a/circle/dashboard/templates/dashboard/node-detail/_activity-timeline.html b/circle/dashboard/templates/dashboard/node-detail/_activity-timeline.html index 1aead0a..58a5c1b 100644 --- a/circle/dashboard/templates/dashboard/node-detail/_activity-timeline.html +++ b/circle/dashboard/templates/dashboard/node-detail/_activity-timeline.html @@ -1,4 +1,5 @@ {% load i18n %} +{% load hro %} <div id="activity-timeline" class="timeline"> {% for a in activities %} <div class="activity" data-activity-id="{{ a.pk }}"> @@ -16,10 +17,7 @@ <div data-activity-id="{{ s.pk }}" class="sub-activity{% if s.has_failed %} sub-activity-failed{% endif %}" > - {% if user.is_superuser %} - {{ s.readable_name.get_admin_text }} - {% else %} - {{ s.readable_name.get_user_text }}{% endif %} + {{ s.readable_name|get_text:user }} – {% if s.finished %} {{ s.finished|time:"H:i:s" }} diff --git a/circle/dashboard/templates/dashboard/vm-detail/_activity-timeline.html b/circle/dashboard/templates/dashboard/vm-detail/_activity-timeline.html index 609b8a6..0d0c96e 100644 --- a/circle/dashboard/templates/dashboard/vm-detail/_activity-timeline.html +++ b/circle/dashboard/templates/dashboard/vm-detail/_activity-timeline.html @@ -1,5 +1,5 @@ {% load i18n %} - +{% load hro %} <div id="activity-timeline" class="timeline"> {% for a in activities %} @@ -7,10 +7,10 @@ <span class="timeline-icon{% if a.has_failed %} timeline-icon-failed{% endif %}"> <i class="fa {% if not a.finished %}fa-refresh fa-spin {% else %}fa-{{a.icon}}{% endif %}"></i> </span> -<strong{% if a.result %} title="{{ a.result.get_user_text }}"{% endif %}> +<strong{% if a.result %} title="{{ a.result|get_text:user }}"{% endif %}> <a href="{{ a.get_absolute_url }}"> {% if a.times > 1 %}({{ a.times }}x){% endif %} - {{ a.readable_name.get_user_text|capfirst }}</a> + {{ a.readable_name|get_text:user|capfirst }}</a> {% if a.has_percent %} - {{ a.percentage }}% @@ -33,9 +33,9 @@ <div class="sub-timeline"> {% for s in a.children.all %} <div data-activity-id="{{ s.pk }}" class="sub-activity{% if s.has_failed %} sub-activity-failed{% endif %}{% if s.pk == active.pk %} sub-activity-active{% endif %}"> - <span{% if s.result %} title="{{ s.result.get_user_text }}"{% endif %}> + <span{% if s.result %} title="{{ s.result|get_text:user }}"{% endif %}> <a href="{{ s.get_absolute_url }}"> - {{ s.readable_name.get_user_text|capfirst }}</a></span> – + {{ s.readable_name|get_text:user|capfirst }}</a></span> – {% if s.finished %} {{ s.finished|time:"H:i:s" }} {% else %} diff --git a/circle/dashboard/templates/dashboard/vm-list.html b/circle/dashboard/templates/dashboard/vm-list.html index 0f4e6e7..8fe5400 100644 --- a/circle/dashboard/templates/dashboard/vm-list.html +++ b/circle/dashboard/templates/dashboard/vm-list.html @@ -15,41 +15,36 @@ </div> <h3 class="no-margin"><i class="fa fa-desktop"></i> {% trans "Virtual machines" %}</h3> </div> - <div class="pull-right" style="max-width: 300px; margin-top: 15px; margin-right: 15px;"> - <form action="" method="GET"> - <div class="input-group"> - {{ search_form.s }} - <div class="input-group-btn"> - {{ search_form.stype }} - <button type="submit" class="btn btn-primary input-tags"> - <i class="fa fa-search"></i> - </button> - </div> - </div> - </form> - </div> - <div class="panel-body vm-list-group-control"> - <p> - <strong>{% trans "Group actions" %}</strong> - <!-- - <button id="vm-list-group-select-all" class="btn btn-info btn-xs">{% trans "Select all" %}</button> - <a href="#" class="btn btn-default btn-xs" title="{% trans "Migrate" %}" disabled> - <i class="fa fa-truck"></i> - </a> - <a href="#" class="btn btn-default btn-xs" title="{% trans "Reboot" %}" disabled> - <i class="fa fa-refresh"></i> - </a> - <a href="#" class="btn btn-default btn-xs" title="{% trans "Shutdown" %}" disabled> - <i class="fa fa-power-off"></i> - </a> - --> - <a title="{% trans "Destroy" %}" id="vm-list-group-delete" disabled href="#" class="btn btn-danger btn-xs" disabled> - <i class="fa fa-times"></i> - </a> - </p> - </div> <div class="panel-body"> - <table class="table table-bordered table-striped table-hover vm-list-table"> + <div class="row"> + <div class="col-md-8 vm-list-group-control" id="vm-mass-ops"> + <strong>{% trans "Group actions" %}</strong> + <button id="vm-list-group-select-all" class="btn btn-info btn-xs">{% trans "Select all" %}</button> + {% for o in ops %} + <a href="{{ o.get_url }}" class="btn btn-xs btn-{{ o.effect }} mass-operation" + title="{{ o.name|capfirst }}" disabled> + <i class="fa fa-{{ o.icon }}"></i> + </a> + {% endfor %} + </div><!-- .vm-list-group-control --> + <div class="col-md-4" id="vm-list-search"> + <form action="" method="GET"> + <div class="input-group"> + {{ search_form.s }} + <div class="input-group-btn"> + {{ search_form.stype }} + <button type="submit" class="btn btn-primary input-tags"> + <i class="fa fa-search"></i> + </button> + </div> + </div><!-- .input-group --> + </form> + </div><!-- .col-md-4 #vm-list-search --> + </div><!-- .row --> + </div><!-- .panel-body --> + <div class="panel-body"> + <table class="table table-bordered table-striped table-hover vm-list-table" + id="vm-list-table"> <thead><tr> <th data-sort="int" class="orderable pk sortable vm-list-table-thin" style="min-width: 50px;"> {% trans "ID" as t %} @@ -76,12 +71,21 @@ <tr class="{% cycle 'odd' 'even' %}" data-vm-pk="{{ i.pk }}"> <td class="pk"><div id="vm-{{i.pk}}">{{i.pk}}</div> </td> <td class="name"><a class="real-link" href="{% url "dashboard.views.detail" i.pk %}">{{ i.name }}</a> </td> - <td class="state">{{ i.get_status_display }}</td> + <td class="state"> + <i class="fa fa-fw + {% if i.is_in_status_change %} + fa-spin fa-spinner + {% else %} + {{ i.get_status_icon }}{% endif %}"></i> + <span>{{ i.get_status_display }}</span> + </td> <td> {% include "dashboard/_display-name.html" with user=i.owner show_org=True %} </td> {% if user.is_superuser %} - <td data-sort-value="{{ i.node.normalized_name }}">{{ i.node.name|default:"-" }}</td> + <td class="node "data-sort-value="{{ i.node.normalized_name }}"> + {{ i.node.name|default:"-" }} + </td> {% endif %} </tr> {% empty %} @@ -115,6 +119,5 @@ {% block extra_js %} <script src="{{ STATIC_URL}}dashboard/vm-list.js"></script> - <script src="{{ STATIC_URL}}dashboard/vm-common.js"></script> <script src="{{ STATIC_URL}}dashboard/js/stupidtable.min.js"></script> {% endblock %} diff --git a/circle/dashboard/templatetags/hro.py b/circle/dashboard/templatetags/hro.py new file mode 100644 index 0000000..7226639 --- /dev/null +++ b/circle/dashboard/templatetags/hro.py @@ -0,0 +1,12 @@ +from django.template import Library + + +register = Library() + + +@register.filter +def get_text(human_readable, user): + if human_readable is None: + return u"" + else: + return human_readable.get_text(user) diff --git a/circle/dashboard/tests/test_mockedviews.py b/circle/dashboard/tests/test_mockedviews.py index 497054f..ef7bae2 100644 --- a/circle/dashboard/tests/test_mockedviews.py +++ b/circle/dashboard/tests/test_mockedviews.py @@ -29,7 +29,7 @@ from django.utils import baseconv from ..models import Profile from ..views import InstanceActivityDetail, InstanceActivity -from ..views import vm_ops, Instance, UnsubscribeFormView +from ..views import vm_ops, vm_mass_ops, Instance, UnsubscribeFormView from ..views import AclUpdateView from .. import views @@ -259,6 +259,114 @@ class VmOperationViewTestCase(unittest.TestCase): self.assertEquals(rend.status_code, 200) +class VmMassOperationViewTestCase(unittest.TestCase): + + def test_available(self): + request = FakeRequestFactory(superuser=True) + view = vm_mass_ops['destroy'] + + with patch.object(view, 'get_object') as go: + inst = MagicMock(spec=Instance) + inst._meta.object_name = "Instance" + inst.destroy = Instance._ops['destroy'](inst) + go.return_value = [inst] + self.assertEquals( + view.as_view()(request, pk=1234).render().status_code, 200) + + def test_unpermitted_choice(self): + "User has user level, but not the needed ownership." + request = FakeRequestFactory() + view = vm_mass_ops['destroy'] + + with patch.object(view, 'get_object') as go: + inst = MagicMock(spec=Instance) + inst._meta.object_name = "Instance" + inst.has_level = lambda self, l: {"user": True, "owner": False}[l] + inst.destroy = Instance._ops['destroy'](inst) + inst.destroy._operate = MagicMock() + go.return_value = [inst] + view.as_view()(request, pk=1234).render() + assert not inst.destroy._operate.called + + def test_unpermitted(self): + request = FakeRequestFactory() + view = vm_mass_ops['destroy'] + + with patch.object(view, 'get_object') as go: + inst = MagicMock(spec=Instance) + inst._meta.object_name = "Instance" + inst.destroy = Instance._ops['destroy'](inst) + inst.has_level.return_value = False + go.return_value = [inst] + with self.assertRaises(PermissionDenied): + view.as_view()(request, pk=1234).render() + + def test_migrate(self): + request = FakeRequestFactory(POST={'node': 1}, superuser=True) + view = vm_mass_ops['migrate'] + + with patch.object(view, 'get_object') as go, \ + patch('dashboard.views.messages') as msg, \ + patch('dashboard.views.get_object_or_404') as go4: + inst = MagicMock(spec=Instance) + inst._meta.object_name = "Instance" + inst.migrate = Instance._ops['migrate'](inst) + inst.migrate.async = MagicMock() + inst.has_level.return_value = True + go.return_value = [inst] + go4.return_value = MagicMock() + assert view.as_view()(request, pk=1234)['location'] + assert not msg.error.called + + def test_migrate_failed(self): + request = FakeRequestFactory(POST={'node': 1}, superuser=True) + view = vm_mass_ops['migrate'] + + with patch.object(view, 'get_object') as go, \ + patch('dashboard.views.messages') as msg, \ + patch('dashboard.views.get_object_or_404') as go4: + inst = MagicMock(spec=Instance) + inst._meta.object_name = "Instance" + inst.migrate = Instance._ops['migrate'](inst) + inst.migrate.async = MagicMock() + inst.migrate.async.side_effect = Exception + inst.has_level.return_value = True + go.return_value = [inst] + go4.return_value = MagicMock() + assert view.as_view()(request, pk=1234)['location'] + assert msg.error.called + + def test_migrate_wo_permission(self): + request = FakeRequestFactory(POST={'node': 1}, superuser=False) + view = vm_mass_ops['migrate'] + + with patch.object(view, 'get_object') as go, \ + patch('dashboard.views.get_object_or_404') as go4: + inst = MagicMock(spec=Instance) + inst._meta.object_name = "Instance" + inst.migrate = Instance._ops['migrate'](inst) + inst.migrate.async = MagicMock() + inst.has_level.return_value = True + go.return_value = [inst] + go4.return_value = MagicMock() + with self.assertRaises(PermissionDenied): + assert view.as_view()(request, pk=1234)['location'] + + def test_migrate_template(self): + """check if GET dialog's template can be rendered""" + request = FakeRequestFactory(superuser=True) + view = vm_mass_ops['migrate'] + + with patch.object(view, 'get_object') as go: + inst = MagicMock(spec=Instance) + inst._meta.object_name = "Instance" + inst.migrate = Instance._ops['migrate'](inst) + inst.has_level.return_value = True + go.return_value = [inst] + self.assertEquals( + view.as_view()(request, pk=1234).render().status_code, 200) + + class RenewViewTest(unittest.TestCase): def test_renew_template(self): diff --git a/circle/dashboard/tests/test_views.py b/circle/dashboard/tests/test_views.py index 8e416a7..895853d 100644 --- a/circle/dashboard/tests/test_views.py +++ b/circle/dashboard/tests/test_views.py @@ -107,20 +107,6 @@ class VmDetailTest(LoginMixin, TestCase): response = c.get('/dashboard/vm/1/') self.assertEqual(response.status_code, 200) - def test_unpermitted_vm_mass_delete(self): - c = Client() - self.login(c, 'user1') - response = c.post('/dashboard/vm/mass-delete/', {'vms': [1]}) - self.assertEqual(response.status_code, 403) - - def test_permitted_vm_mass_delete(self): - c = Client() - self.login(c, 'user2') - inst = Instance.objects.get(pk=1) - inst.set_level(self.u2, 'owner') - response = c.post('/dashboard/vm/mass-delete/', {'vms': [1]}) - self.assertEqual(response.status_code, 302) - def test_unpermitted_password_change(self): c = Client() self.login(c, "user2") diff --git a/circle/dashboard/urls.py b/circle/dashboard/urls.py index dc147b7..6c7113b 100644 --- a/circle/dashboard/urls.py +++ b/circle/dashboard/urls.py @@ -29,7 +29,7 @@ from .views import ( NotificationView, PortDelete, TemplateAclUpdateView, TemplateCreate, TemplateDelete, TemplateDetail, TemplateList, TransferOwnershipConfirmView, TransferOwnershipView, vm_activity, VmCreate, VmDetailView, - VmDetailVncTokenView, VmGraphView, VmList, VmMassDelete, + VmDetailVncTokenView, VmGraphView, VmList, DiskRemoveView, get_disk_download_status, InterfaceDeleteView, GroupRemoveUserView, GroupRemoveFutureUserView, @@ -49,7 +49,6 @@ from .views import ( autocomplete_light.autodiscover() urlpatterns = patterns( - '', url(r'^$', IndexView.as_view(), name="dashboard.index"), url(r'^lease/(?P<pk>\d+)/$', LeaseDetail.as_view(), @@ -74,7 +73,7 @@ urlpatterns = patterns( url(r"^template/delete/(?P<pk>\d+)/$", TemplateDelete.as_view(), name="dashboard.views.template-delete"), - url(r'^vm/(?P<pk>\d+)/op/', include('dashboard.vm.urls')), + url(r'^vm/', include('dashboard.vm.urls')), url(r'^vm/(?P<pk>\d+)/remove_port/(?P<rule>\d+)/$', PortDelete.as_view(), name='dashboard.views.remove-port'), url(r'^vm/(?P<pk>\d+)/$', VmDetailView.as_view(), @@ -88,8 +87,6 @@ urlpatterns = patterns( url(r'^vm/list/$', VmList.as_view(), name='dashboard.views.vm-list'), url(r'^vm/create/$', VmCreate.as_view(), name='dashboard.views.vm-create'), - url(r'^vm/mass-delete/', VmMassDelete.as_view(), - name='dashboard.view.mass-delete-vm'), url(r'^vm/(?P<pk>\d+)/activity/$', vm_activity), url(r'^vm/activity/(?P<pk>\d+)/$', InstanceActivityDetail.as_view(), name='dashboard.views.vm-activity'), diff --git a/circle/dashboard/views.py b/circle/dashboard/views.py index a0f6c58..c08484c 100644 --- a/circle/dashboard/views.py +++ b/circle/dashboard/views.py @@ -77,7 +77,10 @@ from .tables import ( NodeListTable, TemplateListTable, LeaseListTable, GroupListTable, UserKeyListTable ) -from common.models import HumanReadableObject, HumanReadableException +from common.models import ( + HumanReadableObject, HumanReadableException, fetch_human_exception, + create_readable, +) from vm.models import ( Instance, instance_activity, InstanceActivity, InstanceTemplate, Interface, InterfaceTemplate, Lease, Node, NodeActivity, Trait, @@ -561,6 +564,10 @@ class OperationView(RedirectToLoginMixin, DetailView): setattr(self, '_opobj', getattr(self.get_object(), self.op)) return self._opobj + @classmethod + def get_operation_class(cls): + return cls.model.get_operation_class(cls.op) + def get_context_data(self, **kwargs): ctx = super(OperationView, self).get_context_data(**kwargs) ctx['op'] = self.get_op() @@ -576,6 +583,10 @@ class OperationView(RedirectToLoginMixin, DetailView): logger.debug("OperationView.check_auth(%s)", unicode(self)) self.get_op().check_auth(self.request.user) + @classmethod + def check_perms(cls, user): + cls.get_operation_class().check_perms(user) + def get(self, request, *args, **kwargs): self.check_auth() return super(OperationView, self).get(request, *args, **kwargs) @@ -1010,6 +1021,112 @@ def get_operations(instance, user): return ops +class MassOperationView(OperationView): + template_name = 'dashboard/mass-operate.html' + + def check_auth(self): + self.get_op().check_perms(self.request.user) + for i in self.get_object(): + if not i.has_level(self.request.user, "user"): + raise PermissionDenied( + "You have no user access to instance %d" % i.pk) + + @classmethod + def get_urlname(cls): + return 'dashboard.vm.mass-op.%s' % cls.op + + @classmethod + def get_url(cls): + return reverse("dashboard.vm.mass-op.%s" % cls.op) + + def get_op(self, instance=None): + if instance: + return getattr(instance, self.op) + else: + return Instance._ops[self.op] + + def get_context_data(self, **kwargs): + ctx = super(MassOperationView, self).get_context_data(**kwargs) + instances = self.get_object() + ctx['instances'] = self._get_operable_instances( + instances, self.request.user) + ctx['vm_count'] = sum(1 for i in ctx['instances'] if not i.disabled) + return ctx + + def _call_operations(self, extra): + request = self.request + user = request.user + instances = self.get_object() + for i in instances: + try: + self.get_op(i).async(user=user, **extra) + except HumanReadableException as e: + e.send_message(request) + except Exception as e: + # pre-existing errors should have been catched when the + # confirmation dialog was constructed + messages.error(request, _( + "Failed to execute %(op)s operation on " + "instance %(instance)s.") % {"op": self.name, + "instance": i}) + + def get_object(self): + vms = getattr(self.request, self.request.method).getlist("vm") + return Instance.objects.filter(pk__in=vms) + + def _get_operable_instances(self, instances, user): + for i in instances: + try: + op = self.get_op(i) + op.check_auth(user) + op.check_precond() + except PermissionDenied as e: + i.disabled = create_readable( + _("You are not permitted to execute %(op)s on instance " + "%(instance)s."), instance=i.pk, op=self.name) + i.disabled_icon = "lock" + except Exception as e: + i.disabled = fetch_human_exception(e) + else: + i.disabled = None + return instances + + def post(self, request, extra=None, *args, **kwargs): + self.check_auth() + if extra is None: + extra = {} + self._call_operations(extra) + if request.is_ajax(): + store = messages.get_messages(request) + store.used = True + return HttpResponse( + json.dumps({'messages': [unicode(m) for m in store]}), + content_type="application/json" + ) + else: + return redirect(reverse("dashboard.views.vm-list")) + + @classmethod + def factory(cls, vm_op, extra_bases=(), **kwargs): + return type(str(cls.__name__ + vm_op.op), + tuple(list(extra_bases) + [cls, vm_op]), kwargs) + + +class MassMigrationView(MassOperationView, VmMigrateView): + template_name = 'dashboard/_vm-mass-migrate.html' + +vm_mass_ops = OrderedDict([ + ('deploy', MassOperationView.factory(vm_ops['deploy'])), + ('wake_up', MassOperationView.factory(vm_ops['wake_up'])), + ('sleep', MassOperationView.factory(vm_ops['sleep'])), + ('reboot', MassOperationView.factory(vm_ops['reboot'])), + ('reset', MassOperationView.factory(vm_ops['reset'])), + ('shut_off', MassOperationView.factory(vm_ops['shut_off'])), + ('migrate', MassMigrationView), + ('destroy', MassOperationView.factory(vm_ops['destroy'])), +]) + + class NodeDetailView(LoginRequiredMixin, SuperuserRequiredMixin, DetailView): template_name = "dashboard/node-detail.html" model = Node @@ -1582,11 +1699,41 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView): def get_context_data(self, *args, **kwargs): context = super(VmList, self).get_context_data(*args, **kwargs) + context['ops'] = [] + for k, v in vm_mass_ops.iteritems(): + try: + v.check_perms(user=self.request.user) + except PermissionDenied: + pass + else: + context['ops'].append(v) context['search_form'] = self.search_form return context def get(self, *args, **kwargs): if self.request.is_ajax(): + return self._create_ajax_request() + else: + self.search_form = VmListSearchForm(self.request.GET) + self.search_form.full_clean() + return super(VmList, self).get(*args, **kwargs) + + def _create_ajax_request(self): + if self.request.GET.get("compact") is not None: + instances = Instance.get_objects_with_level( + "user", self.request.user).filter(destroyed_at=None) + statuses = {} + for i in instances: + statuses[i.pk] = { + 'status': i.get_status_display(), + 'icon': i.get_status_icon(), + 'in_status_change': i.is_in_status_change(), + } + if self.request.user.is_superuser: + statuses[i.pk]['node'] = i.node.name if i.node else "-" + return HttpResponse(json.dumps(statuses), + content_type="application/json") + else: favs = Instance.objects.filter( favourite__user=self.request.user).values_list('pk', flat=True) instances = Instance.get_objects_with_level( @@ -1598,15 +1745,12 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView): 'icon': i.get_status_icon(), 'host': "" if not i.primary_host else i.primary_host.hostname, 'status': i.get_status_display(), - 'fav': i.pk in favs} for i in instances] + 'fav': i.pk in favs, + } for i in instances] return HttpResponse( json.dumps(list(instances)), # instances is ValuesQuerySet content_type="application/json", ) - else: - self.search_form = VmListSearchForm(self.request.GET) - self.search_form.full_clean() - return super(VmList, self).get(*args, **kwargs) def get_queryset(self): logger.debug('VmList.get_queryset() called. User: %s', @@ -1969,7 +2113,7 @@ class VmCreate(LoginRequiredMixin, TemplateView): "Successfully created %(count)d VM.", # this should not happen "Successfully created %(count)d VMs.", len(instances)) % { 'count': len(instances)}) - path = reverse("dashboard.index") + path = "%s?stype=owned" % reverse("dashboard.views.vm-list") else: messages.success(request, _("VM successfully created.")) path = instances[0].get_absolute_url() @@ -2371,48 +2515,6 @@ class PortDelete(LoginRequiredMixin, DeleteView): kwargs={'pk': self.kwargs.get("pk")}) -class VmMassDelete(LoginRequiredMixin, View): - def get(self, request, *args, **kwargs): - vms = request.GET.getlist('v[]') - objects = Instance.objects.filter(pk__in=vms) - return render(request, "dashboard/confirm/mass-delete.html", - {'objects': objects}) - - def post(self, request, *args, **kwargs): - vms = request.POST.getlist('vms') - names = [] - if vms is not None: - for i in Instance.objects.filter(pk__in=vms): - if not i.has_level(request.user, 'owner'): - logger.info('Tried to delete instance #%d without owner ' - 'permission by %s.', i.pk, - unicode(request.user)) - # no need for rollback or proper error message, this can't - # normally happen: - raise PermissionDenied() - try: - i.destroy.async(user=request.user) - names.append(i.name) - except Exception as e: - logger.error(e) - - success_message = ungettext_lazy( - "Mass delete complete, the following VM was deleted: %s.", - "Mass delete complete, the following VMs were deleted: %s.", - len(names)) % u', '.join(names) - - # we can get this only via AJAX ... - if request.is_ajax(): - return HttpResponse( - json.dumps({'message': success_message}), - content_type="application/json" - ) - else: - messages.success(request, success_message) - next = request.GET.get('next') - return redirect(next if next else reverse_lazy('dashboard.index')) - - class LeaseCreate(LoginRequiredMixin, PermissionRequiredMixin, SuccessMessageMixin, CreateView): model = Lease @@ -2744,7 +2846,7 @@ class NodeGraphView(SuperuserRequiredMixin, GraphViewBase): model = Node def get_prefix(self, instance): - return 'circle.%s' % instance.name + return 'circle.%s' % instance.host.hostname def get_title(self, instance, metric): return '%s - %s' % (instance.name, metric) diff --git a/circle/dashboard/vm/urls.py b/circle/dashboard/vm/urls.py index 5d7c7f6..f78acde 100644 --- a/circle/dashboard/vm/urls.py +++ b/circle/dashboard/vm/urls.py @@ -17,9 +17,17 @@ from django.conf.urls import patterns, url -from ..views import vm_ops +from ..views import vm_ops, vm_mass_ops -urlpatterns = patterns('', - *(url(r'^%s/$' % op, v.as_view(), name=v.get_urlname()) - for op, v in vm_ops.iteritems())) +urlpatterns = patterns( + '', + *(url(r'^(?P<pk>\d+)/op/%s/$' % op, v.as_view(), name=v.get_urlname()) + for op, v in vm_ops.iteritems()) +) + +urlpatterns += patterns( + '', + *(url(r'^mass_op/%s/$' % op, v.as_view(), name=v.get_urlname()) + for op, v in vm_mass_ops.iteritems()) +) diff --git a/circle/locale/hu/LC_MESSAGES/django.po b/circle/locale/hu/LC_MESSAGES/django.po index c349465..e2e2e7a 100644 --- a/circle/locale/hu/LC_MESSAGES/django.po +++ b/circle/locale/hu/LC_MESSAGES/django.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-08-01 19:36+0200\n" -"PO-Revision-Date: 2014-08-01 23:05+0200\n" +"POT-Creation-Date: 2014-08-29 09:21+0200\n" +"PO-Revision-Date: 2014-08-29 09:46+0200\n" "Last-Translator: Mate Ory <ory.mate@ik.bme.hu>\n" "Language-Team: Hungarian <cloud@ik.bme.hu>\n" "Language: hu\n" @@ -25,76 +25,93 @@ msgstr "Angol" msgid "Hungarian" msgstr "Magyar" -#: common/models.py:59 +#: common/models.py:62 msgid "Failure." msgstr "Hiba." -#: common/models.py:60 +#: common/models.py:63 #, python-format msgid "Unhandled exception: %(error)s" msgstr "Kezeletlen kivétel: %(error)s" -#: common/models.py:135 -#: dashboard/templates/dashboard/instanceactivity_detail.html:32 +#: common/models.py:138 +#: dashboard/templates/dashboard/instanceactivity_detail.html:28 msgid "activity code" msgstr "tevékenységkód" -#: common/models.py:138 +#: common/models.py:141 msgid "human readable name" msgstr "olvasható név" -#: common/models.py:139 +#: common/models.py:142 msgid "Human readable name of activity." msgstr "A tevékenység neve olvasható formában." -#: common/models.py:143 +#: common/models.py:146 msgid "Celery task unique identifier." msgstr "Celery feladat egyedi azonosítója." -#: common/models.py:144 +#: common/models.py:147 msgid "task_uuid" msgstr "feladat uuid" -#: common/models.py:145 -#: dashboard/templates/dashboard/instanceactivity_detail.html:41 -#: firewall/models.py:282 vm/models/common.py:84 vm/models/instance.py:135 -#: vm/models/instance.py:213 +#: common/models.py:148 +#: dashboard/templates/dashboard/instanceactivity_detail.html:37 +#: firewall/models.py:273 vm/models/common.py:84 vm/models/instance.py:136 +#: vm/models/instance.py:217 msgid "user" msgstr "felhasználó" -#: common/models.py:146 +#: common/models.py:149 msgid "The person who started this activity." msgstr "A tevékenységet indító felhasználó." -#: common/models.py:147 +#: common/models.py:150 msgid "started at" msgstr "indítás ideje" -#: common/models.py:149 +#: common/models.py:152 msgid "Time of activity initiation." msgstr "A tevékenység megkezdésének időpontja." -#: common/models.py:150 +#: common/models.py:153 msgid "finished at" msgstr "befejezés ideje" -#: common/models.py:152 +#: common/models.py:155 msgid "Time of activity finalization." msgstr "A tevékenység befejeztének ideje." -#: common/models.py:154 +#: common/models.py:157 msgid "True, if the activity has finished successfully." msgstr "Igaz, ha a tevékenység sikeresen befejeződött." -#: common/models.py:156 -#: dashboard/templates/dashboard/instanceactivity_detail.html:60 +#: common/models.py:159 +#: dashboard/templates/dashboard/instanceactivity_detail.html:56 msgid "result" msgstr "eredmény" -#: common/models.py:158 +#: common/models.py:161 msgid "Human readable result of activity." msgstr "A tevékenység eredménye olvasható formában." +#: common/models.py:515 +msgid "Permission Denied" +msgstr "Hozzáférés megtagadva" + +#: common/models.py:517 +msgid "Unknown error" +msgstr "Ismeretlen hiba" + +#: common/models.py:518 +#, python-format +msgid "Unknown error: %(ex)s" +msgstr "Ismeretlen hiba: %(ex)s" + +#: common/operations.py:160 +msgid "Superuser privileges are required." +msgstr "Rendszergazdai jogosultság szükséges." + #: dashboard/autocomplete_light_registry.py:12 #: dashboard/templates/dashboard/lease-edit.html:86 msgid "Name of group or user" @@ -120,17 +137,17 @@ msgstr "szerver" msgid "realtime" msgstr "valós idejű" -#: dashboard/forms.py:71 dashboard/forms.py:723 dashboard/forms.py:744 -#: dashboard/forms.py:1013 dashboard/tables.py:264 -#: dashboard/templates/dashboard/_vm-create-2.html:20 -#: dashboard/templates/dashboard/vm-list.html:44 -#: dashboard/templates/dashboard/vm-detail/home.html:8 firewall/models.py:294 +#: dashboard/forms.py:71 dashboard/forms.py:746 dashboard/forms.py:767 +#: dashboard/forms.py:1034 dashboard/tables.py:229 +#: dashboard/templates/dashboard/_vm-create-2.html:19 +#: dashboard/templates/dashboard/vm-list.html:54 +#: dashboard/templates/dashboard/vm-detail/home.html:8 firewall/models.py:285 #: network/templates/network/index.html:22 #: network/templates/network/switch-port-edit.html:43 msgid "Name" msgstr "Név" -#: dashboard/forms.py:72 vm/models/instance.py:140 +#: dashboard/forms.py:72 vm/models/instance.py:141 msgid "Human readable name of template." msgstr "A sablon olvasható neve." @@ -156,9 +173,9 @@ msgstr "Címtári azonosító" msgid "Create" msgstr "Létrehozás" -#: dashboard/forms.py:227 dashboard/forms.py:953 dashboard/forms.py:970 -#: dashboard/forms.py:996 dashboard/forms.py:1026 dashboard/forms.py:1051 -#: dashboard/forms.py:1071 dashboard/forms.py:1100 +#: dashboard/forms.py:227 dashboard/forms.py:974 dashboard/forms.py:991 +#: dashboard/forms.py:1017 dashboard/forms.py:1047 dashboard/forms.py:1072 +#: dashboard/forms.py:1092 dashboard/forms.py:1121 #: dashboard/templates/dashboard/_manage_access.html:73 #: dashboard/templates/dashboard/group-detail.html:101 #: dashboard/templates/dashboard/lease-edit.html:96 @@ -170,7 +187,7 @@ msgid "Host" msgstr "Gép" #: dashboard/forms.py:329 dashboard/templates/dashboard/node-detail.html:4 -#: dashboard/templates/dashboard/vm-list.html:56 +#: dashboard/templates/dashboard/vm-list.html:66 msgid "Node" msgstr "Csomópont" @@ -178,107 +195,150 @@ msgstr "Csomópont" msgid "Networks" msgstr "Hálózatok" -#: dashboard/forms.py:636 dashboard/tables.py:169 +#: dashboard/forms.py:637 msgid "Suspend in" msgstr "Felfüggesztés ideje" -#: dashboard/forms.py:642 dashboard/forms.py:670 +#: dashboard/forms.py:641 dashboard/forms.py:665 msgid "hours" msgstr "óra" -#: dashboard/forms.py:647 dashboard/forms.py:675 +#: dashboard/forms.py:646 dashboard/forms.py:670 msgid "days" msgstr "nap" -#: dashboard/forms.py:652 dashboard/forms.py:680 +#: dashboard/forms.py:651 dashboard/forms.py:675 msgid "weeks" msgstr "hét" -#: dashboard/forms.py:657 dashboard/forms.py:685 +#: dashboard/forms.py:656 dashboard/forms.py:680 msgid "months" msgstr "hónap" -#: dashboard/forms.py:664 dashboard/tables.py:172 +#: dashboard/forms.py:661 msgid "Delete in" msgstr "Törlés ideje" -#: dashboard/forms.py:701 +#: dashboard/forms.py:686 dashboard/templates/dashboard/template-edit.html:63 +msgid "Save changes" +msgstr "Változások mentése" + +#: dashboard/forms.py:696 msgid "Set expiration times even if they are shorter than the current value." msgstr "" "Akkor is állítsa át a lejárati időket, ha rövidebbek lesznek a jelenleginél." -#: dashboard/forms.py:711 +#: dashboard/forms.py:699 +msgid "Save selected lease." +msgstr "Kiválasztott bérlet mentése." + +#: dashboard/forms.py:708 msgid "Length" msgstr "Hossz" -#: dashboard/forms.py:725 +#: dashboard/forms.py:723 +msgid "Forcibly interrupt all running activities." +msgstr "Futó tevékenységek erőltetett befejezése." + +#: dashboard/forms.py:724 +msgid "Set all activities to finished state, but don't interrupt any tasks." +msgstr "" +"Minden tevékenység befejezettre állítása (a feladatok megszakítása nélkül)." + +#: dashboard/forms.py:727 +msgid "New status" +msgstr "Új állapot" + +#: dashboard/forms.py:748 #: dashboard/templates/dashboard/store/_list-box.html:117 msgid "Size" msgstr "Méret" -#: dashboard/forms.py:726 +#: dashboard/forms.py:749 msgid "Size of disk to create in bytes or with units like MB or GB." msgstr "Létrehozandó lemez mérete byte-okban vagy mértékegységgel (MB, GB)." -#: dashboard/forms.py:732 +#: dashboard/forms.py:755 msgid "Invalid format, you can use GB or MB!" msgstr "Érvénytelen formátum. „GB” és „MB” is használható." -#: dashboard/forms.py:745 +#: dashboard/forms.py:768 msgid "URL" msgstr "URL" -#: dashboard/forms.py:760 -#: dashboard/templates/dashboard/node-detail/resources.html:14 +#: dashboard/forms.py:783 +#: dashboard/templates/dashboard/node-detail/resources.html:17 msgid "Vlan" msgstr "Vlan" -#: dashboard/forms.py:763 +#: dashboard/forms.py:786 msgid "No more networks." msgstr "Nincs több hálózat." -#: dashboard/forms.py:791 dashboard/templates/dashboard/profile.html:25 +#: dashboard/forms.py:814 dashboard/templates/dashboard/profile.html:25 #: dashboard/templates/dashboard/vm-detail.html:94 msgid "Username" msgstr "Felhasználónév" -#: dashboard/forms.py:805 dashboard/templates/dashboard/vm-detail.html:96 +#: dashboard/forms.py:828 dashboard/templates/dashboard/vm-detail.html:96 msgid "Password" msgstr "Jelszó" -#: dashboard/forms.py:810 +#: dashboard/forms.py:833 msgid "Sign in" msgstr "Bejelentkezés" -#: dashboard/forms.py:833 dashboard/templates/dashboard/profile.html:31 +#: dashboard/forms.py:856 dashboard/templates/dashboard/profile.html:31 msgid "Email address" msgstr "E-mail cím" -#: dashboard/forms.py:838 +#: dashboard/forms.py:861 msgid "Reset password" msgstr "Új jelszó" -#: dashboard/forms.py:854 dashboard/forms.py:979 +#: dashboard/forms.py:877 dashboard/forms.py:1000 msgid "Change password" msgstr "Jelszóváltoztatás" -#: dashboard/forms.py:1015 +#: dashboard/forms.py:949 +msgid "Add trait" +msgstr "Jellemző hozzáadása" + +#: dashboard/forms.py:1036 msgid "Key" msgstr "Kulcs" -#: dashboard/forms.py:1016 +#: dashboard/forms.py:1037 msgid "For example: ssh-rsa AAAAB3NzaC1yc2ED..." msgstr "Például: ssh-rsa AAAAB3NzaC1yc2ED…" -#: dashboard/forms.py:1086 +#: dashboard/forms.py:1107 msgid "permissions" msgstr "jogosultságok" +#: dashboard/forms.py:1164 +msgid "owned" +msgstr "saját" + +#: dashboard/forms.py:1165 +msgid "shared" +msgstr "osztott" + +#: dashboard/forms.py:1166 +msgid "all" +msgstr "összes" + +#: dashboard/forms.py:1173 dashboard/templates/dashboard/index-groups.html:21 +#: dashboard/templates/dashboard/index-nodes.html:34 +#: dashboard/templates/dashboard/index-vm.html:54 +msgid "Search..." +msgstr "Keresés..." + #: dashboard/models.py:63 dashboard/templates/dashboard/index-groups.html:39 -#: dashboard/templates/dashboard/index-nodes.html:46 -#: dashboard/templates/dashboard/index-nodes.html:71 +#: dashboard/templates/dashboard/index-nodes.html:48 +#: dashboard/templates/dashboard/index-nodes.html:73 #: dashboard/templates/dashboard/index-templates.html:38 -#: dashboard/templates/dashboard/index-vm.html:68 +#: dashboard/templates/dashboard/index-vm.html:73 #: dashboard/templates/dashboard/store/_list-box.html:101 msgid "new" msgstr "új" @@ -335,15 +395,15 @@ msgstr "Lemezkvóta mebibyte-okban." msgid "Can use autocomplete." msgstr "Használhat automatikus kiegészítést." -#: dashboard/models.py:184 firewall/models.py:283 vm/models/common.py:85 -#: vm/models/instance.py:136 vm/models/instance.py:214 +#: dashboard/models.py:184 firewall/models.py:274 vm/models/common.py:85 +#: vm/models/instance.py:137 vm/models/instance.py:218 msgid "operator" msgstr "operátor" -#: dashboard/models.py:185 firewall/models.py:100 firewall/models.py:378 -#: firewall/models.py:431 firewall/models.py:454 firewall/models.py:519 -#: firewall/models.py:825 firewall/models.py:854 vm/models/common.py:86 -#: vm/models/instance.py:137 vm/models/instance.py:215 +#: dashboard/models.py:185 firewall/models.py:100 firewall/models.py:369 +#: firewall/models.py:422 firewall/models.py:445 firewall/models.py:510 +#: firewall/models.py:822 firewall/models.py:851 vm/models/common.py:86 +#: vm/models/instance.py:138 vm/models/instance.py:219 msgid "owner" msgstr "tulajdonos" @@ -351,232 +411,252 @@ msgstr "tulajdonos" msgid "Unique identifier of the group at the organization." msgstr "A csoport egyedi szervezeti azonosítója." -#: dashboard/tables.py:57 -#: dashboard/templates/dashboard/node-detail/resources.html:12 -msgid "Priority" -msgstr "Prioritás" +#: dashboard/tables.py:38 +msgid "Overcommit" +msgstr "Túlfoglalás" + +#: dashboard/tables.py:56 +msgid "Number of VMs" +msgstr "VM-ek száma" + +#: dashboard/tables.py:62 +msgid "Monitor" +msgstr "Állapot" -#: dashboard/tables.py:193 +#: dashboard/tables.py:69 dashboard/tables.py:180 dashboard/tables.py:211 +#: dashboard/tables.py:244 +msgid "Actions" +msgstr "Műveletek" + +#: dashboard/tables.py:150 msgid "Cores" msgstr "Magok száma" -#: dashboard/tables.py:202 vm/models/instance.py:112 +#: dashboard/tables.py:159 vm/models/instance.py:113 msgid "Lease" msgstr "Bérlet" -#: dashboard/tables.py:215 dashboard/tables.py:246 dashboard/tables.py:279 -msgid "Actions" -msgstr "Műveletek" +#: dashboard/tables.py:170 dashboard/templates/dashboard/vm-list.html:62 +#: dashboard/templates/dashboard/vm-detail/access.html:2 +msgid "Owner" +msgstr "Tulajdonos" + +#: dashboard/tables.py:175 +msgid "Running" +msgstr "Fut" -#: dashboard/tables.py:269 +#: dashboard/tables.py:234 msgid "Fingerprint" msgstr "Ujjlenyomat" -#: dashboard/tables.py:274 +#: dashboard/tables.py:239 msgid "Created at" msgstr "Létrehozva" -#: dashboard/views.py:281 +#: dashboard/views.py:284 msgid "console access" msgstr "konzolhozzáférés" -#: dashboard/views.py:368 +#: dashboard/views.py:376 msgid "VM successfully renamed." msgstr "A virtuális gép átnevezésre került." -#: dashboard/views.py:392 +#: dashboard/views.py:400 msgid "VM description successfully updated." msgstr "A VM leírása megváltoztatásra került." -#: dashboard/views.py:469 +#: dashboard/views.py:477 msgid "There is a problem with your input." msgstr "A megadott érték nem megfelelő." -#: dashboard/views.py:471 +#: dashboard/views.py:479 msgid "Unknown error." msgstr "Ismeretlen hiba." -#: dashboard/views.py:603 +#: dashboard/views.py:620 msgid "Could not start operation." msgstr "A művelet megkezdése meghiúsult." -#: dashboard/views.py:620 +#: dashboard/views.py:637 msgid "Operation failed." msgstr "A művelet meghiúsult." -#: dashboard/views.py:625 +#: dashboard/views.py:642 msgid "Operation succeeded." msgstr "A művelet sikeresen végrehajtásra került." -#: dashboard/views.py:627 +#: dashboard/views.py:644 msgid "Operation is started." msgstr "A művelet megkezdődött." -#: dashboard/views.py:862 +#: dashboard/views.py:881 msgid "The token has expired." msgstr "A token lejárt." -#: dashboard/views.py:1019 +#: dashboard/views.py:1069 +#, python-format +msgid "Failed to execute %(op)s operation on instance %(instance)s." +msgstr "%(op)s végrehajtása meghiúsult a következőn: %(instance)s." + +#: dashboard/views.py:1085 +#, python-format +msgid "You are not permitted to execute %(op)s on instance %(instance)s." +msgstr "Nem engedélyezett a(z) %(op)s végrehajtása a(z) %(instance)s gépen." + +#: dashboard/views.py:1163 msgid "Node successfully renamed." msgstr "A csomópont átnevezésre került." -#: dashboard/views.py:1113 +#: dashboard/views.py:1257 #, python-format msgid "User \"%s\" not found." msgstr "Nem található „%s” felhasználó." -#: dashboard/views.py:1129 +#: dashboard/views.py:1273 msgid "Group successfully renamed." msgstr "A csoport átnevezésre került." -#: dashboard/views.py:1160 +#: dashboard/views.py:1304 #, python-format msgid "Acl user/group %(w)s successfully modified." msgstr "A(z) %(w)s ACL felhasználó/csoport módosításra került." -#: dashboard/views.py:1162 +#: dashboard/views.py:1306 #, python-format msgid "Acl user/group %(w)s successfully added." msgstr "A(z) %(w)s ACL felhasználó/csoport hozzáadásra került." -#: dashboard/views.py:1164 +#: dashboard/views.py:1308 #, python-format msgid "Acl user/group %(w)s successfully removed." msgstr "A(z) %(w)s ACL felhasználó/csoport törlésre került." -#: dashboard/views.py:1248 +#: dashboard/views.py:1392 msgid "" "The original owner cannot be removed, however you can transfer ownership." msgstr "Az eredeti tulajdonos nem törölhető, azonban a tulajdon átruházható." -#: dashboard/views.py:1284 +#: dashboard/views.py:1428 #, python-format msgid "User \"%s\" has already access to this object." msgstr "„%s” felhasználó már hozzáfér az objektumhoz." -#: dashboard/views.py:1293 +#: dashboard/views.py:1437 #, python-format msgid "Group \"%s\" has already access to this object." msgstr "„%s” csoport már hozzáfér az objektumhoz." -#: dashboard/views.py:1298 +#: dashboard/views.py:1442 #, python-format msgid "User or group \"%s\" not found." msgstr "Nem található „%s” felhasználó vagy csoport." -#: dashboard/views.py:1336 +#: dashboard/views.py:1480 msgid "Choose template" msgstr "Válasszon sablont" -#: dashboard/views.py:1351 +#: dashboard/views.py:1495 msgid "Select an option to proceed." msgstr "Válasszon a folytatáshoz." -#: dashboard/views.py:1382 +#: dashboard/views.py:1526 msgid "Create a new base VM" msgstr "Alap VM létrehozása" -#: dashboard/views.py:1438 +#: dashboard/views.py:1582 msgid "Successfully modified template." msgstr "A sablon módosításra került." -#: dashboard/views.py:1532 +#: dashboard/views.py:1676 msgid "Template successfully deleted." msgstr "A sablon törlésre került." -#: dashboard/views.py:1729 +#: dashboard/views.py:1919 msgid "Member successfully removed from group." msgstr "A csoporttag eltávolításra került." -#: dashboard/views.py:1770 +#: dashboard/views.py:1960 msgid "Future user successfully removed from group." msgstr "A leendő csoporttag eltávolításra került." -#: dashboard/views.py:1797 +#: dashboard/views.py:1987 msgid "Group successfully deleted." msgstr "A csoport törlésre került." -#: dashboard/views.py:1846 +#: dashboard/views.py:2036 msgid "Customize VM" msgstr "VM testreszabása" -#: dashboard/views.py:1854 +#: dashboard/views.py:2044 msgid "Create a VM" msgstr "VM létrehozása" -#: dashboard/views.py:1920 +#: dashboard/views.py:2113 #, python-format msgid "Successfully created %(count)d VM." msgid_plural "Successfully created %(count)d VMs." msgstr[0] "%(count)d VM létrehozásra került." msgstr[1] "%(count)d VM létrehozásra került." -#: dashboard/views.py:1925 +#: dashboard/views.py:2118 msgid "VM successfully created." msgstr "VM létrehozásra került." -#: dashboard/views.py:1954 +#: dashboard/views.py:2147 #, python-format msgid "Instance limit (%d) exceeded." msgstr "A példányok létrehozási korlátját (%d) túllépte." -#: dashboard/views.py:2014 +#: dashboard/views.py:2207 msgid "Node successfully created." msgstr "A csomópont létrehozásra került." -#: dashboard/views.py:2058 +#: dashboard/views.py:2251 msgid "Group successfully created." msgstr "A csoport létrehozásra került." -#: dashboard/views.py:2072 +#: dashboard/views.py:2265 msgid "Group is successfully updated." msgstr "A csoport frissítésre került." -#: dashboard/views.py:2135 +#: dashboard/views.py:2328 msgid "Node successfully deleted." msgstr "A csomópont törlésre került." -#: dashboard/views.py:2182 +#: dashboard/views.py:2375 msgid "Trait successfully added to node." msgstr "A csomópontjellemző hozzáadásra került." -#: dashboard/views.py:2227 +#: dashboard/views.py:2420 msgid "Node successfully changed status." msgstr "A csomópont állapota megváltoztatásra került." -#: dashboard/views.py:2274 +#: dashboard/views.py:2467 msgid "Node successfully flushed." msgstr "A csomópont ürítésre kerül." -#: dashboard/views.py:2293 +#: dashboard/views.py:2486 msgid "Port delete confirmation" msgstr "Porteltávolítás megerősítése" -#: dashboard/views.py:2294 +#: dashboard/views.py:2487 #, python-format msgid "Are you sure you want to close %(port)d/%(proto)s on %(vm)s?" msgstr "Biztosan bezárja a(z) %(port)d/%(proto)s portot a következőn: %(vm)s?" -#: dashboard/views.py:2309 +#: dashboard/views.py:2502 msgid "Port successfully removed." msgstr "A port eltávolításra került." -#: dashboard/views.py:2351 -#, python-format -msgid "Mass delete complete, the following VM was deleted: %s." -msgid_plural "Mass delete complete, the following VMs were deleted: %s." -msgstr[0] "Sikeres tömeges törlés. A következő VM törlésre került: %s." -msgstr[1] "Sikeres tömeges törlés. A következő VM-ek törlésre kerültek: %s." - -#: dashboard/views.py:2373 +#: dashboard/views.py:2524 msgid "Successfully created a new lease." msgstr "Új bérlési mód létrehozásra került." -#: dashboard/views.py:2388 +#: dashboard/views.py:2539 msgid "Successfully modified lease." msgstr "A bérlési mód megváltoztatásra került." -#: dashboard/views.py:2418 +#: dashboard/views.py:2569 msgid "" "You can't delete this lease because some templates are still using it, " "modify these to proceed: " @@ -584,19 +664,19 @@ msgstr "" "Nem törölhető a bérleti mód, mivel az alábbi sablonok még használják. A " "folytatáshoz módosítsa őket: " -#: dashboard/views.py:2435 +#: dashboard/views.py:2586 msgid "Lease successfully deleted." msgstr "A bérlési mód törlésre került." -#: dashboard/views.py:2516 +#: dashboard/views.py:2668 msgid "Can not find specified user." msgstr "Nem található a megadott felhasználó." -#: dashboard/views.py:2532 +#: dashboard/views.py:2684 msgid "Ownership offer" msgstr "Átruházási ajánlat" -#: dashboard/views.py:2533 +#: dashboard/views.py:2685 #, python-format msgid "" "%(user)s offered you to take the ownership of his/her virtual machine called " @@ -606,49 +686,49 @@ msgstr "" "%(user)s át kívánja ruházni %(instance)s nevű virtuális gépét Önre. <a href=" "\"%(token)s\" class=\"btn btn-success btn-small\">Elfogadás</a>" -#: dashboard/views.py:2539 +#: dashboard/views.py:2691 msgid "Can not notify selected user." msgstr "A kiválaszott felhasználó értesítése sikertelen." -#: dashboard/views.py:2542 +#: dashboard/views.py:2694 #, python-format msgid "User %s is notified about the offer." msgstr "%s felhasználó értesítésre került az ajánlatról." -#: dashboard/views.py:2553 +#: dashboard/views.py:2705 msgid "Ownership successfully transferred to you." msgstr "A tulajdon átruházásra került." -#: dashboard/views.py:2566 +#: dashboard/views.py:2718 msgid "This token is for an other user." msgstr "A token más felhasználó nevére szól." -#: dashboard/views.py:2569 +#: dashboard/views.py:2721 msgid "This token is invalid or has expired." msgstr "A token érvénytelen vagy lejárt." -#: dashboard/views.py:2591 +#: dashboard/views.py:2743 msgid "Ownership accepted" msgstr "Átruházás elfogadva" -#: dashboard/views.py:2592 +#: dashboard/views.py:2744 #, python-format msgid "Your ownership offer of %(instance)s has been accepted by %(user)s." msgstr "%(instance)s gépre vonatkozó átruházási ajánlatát elfogadta %(user)s." -#: dashboard/views.py:2766 +#: dashboard/views.py:2918 msgid "You don't have a profile." msgstr "Nincs profilja." -#: dashboard/views.py:2804 +#: dashboard/views.py:2956 msgid "Successfully modified subscription." msgstr "A feliratkozás módosításra került." -#: dashboard/views.py:2865 +#: dashboard/views.py:3017 msgid "Disk remove confirmation" msgstr "Lemez törlésének megerősítése" -#: dashboard/views.py:2866 +#: dashboard/views.py:3018 #, python-format msgid "" "Are you sure you want to remove <strong>%(disk)s</strong> from <strong>" @@ -657,59 +737,63 @@ msgstr "" "Biztosan eltávolítja a(z) <strong>%(disk)s</strong> lemezt a következőből: " "%(app)s?" -#: dashboard/views.py:2885 +#: dashboard/views.py:3037 msgid "Disk successfully removed." msgstr "A lemez eltávolításra került." -#: dashboard/views.py:2967 +#: dashboard/views.py:3134 #, python-format msgid "" "Are you sure you want to remove this interface from <strong>%(vm)s</strong>?" msgstr "" "Biztosan eltávolítja az interfészt a(z) <strong>%(vm)s</strong> gépből?" -#: dashboard/views.py:2981 +#: dashboard/views.py:3148 msgid "Interface successfully deleted." msgstr "Az interfész törlésre került." -#: dashboard/views.py:3082 +#: dashboard/views.py:3249 msgid "Successfully modified SSH key." msgstr "Az SSH kulcs módosításra került." -#: dashboard/views.py:3120 +#: dashboard/views.py:3287 msgid "SSH key successfully deleted." msgstr "Az SSH kulcs törlésre került." -#: dashboard/views.py:3136 +#: dashboard/views.py:3303 msgid "Successfully created a new SSH key." msgstr "Az új SSH kulcs hozzáadásra került." -#: dashboard/views.py:3185 +#: dashboard/views.py:3352 msgid "No store." msgstr "Nincs tárhely." -#: dashboard/views.py:3188 +#: dashboard/views.py:3354 msgid "Store has some problems now. Try again later." msgstr "A tárhely nem működik. Próbálja később." -#: dashboard/views.py:3206 +#: dashboard/views.py:3358 +msgid "Unknown store error." +msgstr "Ismeretlen tárhelyhiba." + +#: dashboard/views.py:3375 msgid "Something went wrong during download." msgstr "Hiba a letöltésben." -#: dashboard/views.py:3221 dashboard/views.py:3241 +#: dashboard/views.py:3390 dashboard/views.py:3410 msgid "Unable to upload file." msgstr "Fájl feltöltése sikertelen." -#: dashboard/views.py:3278 +#: dashboard/views.py:3447 #, python-format msgid "Unable to remove %s." msgstr "%s törlése sikertelen." -#: dashboard/views.py:3297 +#: dashboard/views.py:3466 msgid "Unable to create folder." msgstr "Mappa létrehozása sikertelen." -#: dashboard/tasks/local_periodic_tasks.py:59 +#: dashboard/tasks/local_periodic_tasks.py:60 #, python-format msgid "%d new notification" msgid_plural "%d new notifications" @@ -778,7 +862,7 @@ msgstr "Ki" msgid "What" msgstr "Mi" -#: dashboard/templates/dashboard/_notifications-timeline.html:18 +#: dashboard/templates/dashboard/_notifications-timeline.html:19 msgid "You have no notifications." msgstr "Nincs értesítése." @@ -829,17 +913,17 @@ msgid "Next" msgstr "Tovább" #: dashboard/templates/dashboard/_template-create.html:15 -#: dashboard/templates/dashboard/template-edit.html:28 +#: dashboard/templates/dashboard/template-edit.html:40 msgid "Resource configuration" msgstr "Erőforrásbeállítások" #: dashboard/templates/dashboard/_template-create.html:21 -#: dashboard/templates/dashboard/template-edit.html:34 +#: dashboard/templates/dashboard/template-edit.html:46 msgid "Virtual machine settings" msgstr "Virtuális gépek beállításai" #: dashboard/templates/dashboard/_template-create.html:31 -#: dashboard/templates/dashboard/template-edit.html:44 +#: dashboard/templates/dashboard/template-edit.html:56 msgid "External resources" msgstr "Külső erőforrások" @@ -868,13 +952,13 @@ msgid "Memory" msgstr "Memória" #: dashboard/templates/dashboard/_vm-create-1.html:33 -#: dashboard/templates/dashboard/_vm-create-2.html:48 +#: dashboard/templates/dashboard/_vm-create-2.html:49 #: dashboard/templates/dashboard/vm-detail/resources.html:28 msgid "Disks" msgstr "Lemezek" #: dashboard/templates/dashboard/_vm-create-1.html:40 -#: dashboard/templates/dashboard/_vm-create-2.html:64 +#: dashboard/templates/dashboard/_vm-create-2.html:65 #: dashboard/templates/dashboard/base.html:46 #: dashboard/templates/dashboard/vm-detail.html:150 msgid "Network" @@ -890,28 +974,53 @@ msgid "Customize" msgstr "Testreszabás" #: dashboard/templates/dashboard/_vm-create-1.html:68 -#: dashboard/templates/dashboard/_vm-create-2.html:18 +#: dashboard/templates/dashboard/_vm-create-2.html:17 msgid "Start" msgstr "Indítás" -#: dashboard/templates/dashboard/_vm-create-2.html:29 +#: dashboard/templates/dashboard/_vm-create-1.html:76 +msgid "" +"You can't start new virtual machines because no templates are shared with " +"you." +msgstr "" +"Még nem tud virtuális gépet indítani, mivel egy sablonhoz sincs hozzáférése." + +#: dashboard/templates/dashboard/_vm-create-2.html:30 msgid "Amount" msgstr "Mennyiség" -#: dashboard/templates/dashboard/_vm-create-2.html:37 -#: dashboard/templates/dashboard/node-detail.html:74 +#: dashboard/templates/dashboard/_vm-create-2.html:38 +#: dashboard/templates/dashboard/node-detail.html:78 #: dashboard/templates/dashboard/vm-detail.html:136 msgid "Resources" msgstr "Erőforrások" -#: dashboard/templates/dashboard/_vm-create-2.html:55 +#: dashboard/templates/dashboard/_vm-create-2.html:56 msgid "No disks are added." msgstr "Egy lemez sincs hozzáadva." -#: dashboard/templates/dashboard/_vm-create-2.html:72 +#: dashboard/templates/dashboard/_vm-create-2.html:73 msgid "Not added to any network." msgstr "Egy hálózathoz sincs hozzáadva." +#: dashboard/templates/dashboard/_vm-mass-migrate.html:12 +msgid "Reschedule" +msgstr "Újraütemezés" + +#: dashboard/templates/dashboard/_vm-mass-migrate.html:16 +msgid "This option will reschedule each virtual machine to the optimal node." +msgstr "Ez a lehetőség minden virtuális gépet az optimális csomópontra migrál." + +#: dashboard/templates/dashboard/_vm-mass-migrate.html:28 +#: dashboard/templates/dashboard/_vm-migrate.html:27 +msgid "CPU load" +msgstr "CPU-terhelés" + +#: dashboard/templates/dashboard/_vm-mass-migrate.html:29 +#: dashboard/templates/dashboard/_vm-migrate.html:28 +msgid "RAM usage" +msgstr "RAM-használat" + #: dashboard/templates/dashboard/_vm-migrate.html:7 #, python-format msgid "" @@ -929,14 +1038,6 @@ msgstr "jelenlegi" msgid "recommended" msgstr "javasolt" -#: dashboard/templates/dashboard/_vm-migrate.html:27 -msgid "CPU load" -msgstr "CPU-terhelés" - -#: dashboard/templates/dashboard/_vm-migrate.html:28 -msgid "RAM usage" -msgstr "RAM-használat" - #: dashboard/templates/dashboard/_vm-save.html:7 msgid "" "\n" @@ -982,8 +1083,7 @@ msgstr "Bejelentkezés" #: dashboard/templates/dashboard/node-detail.html:32 #: dashboard/templates/dashboard/vm-detail.html:50 #: dashboard/templates/dashboard/group-list/column-name.html:7 -#: dashboard/templates/dashboard/node-list/column-actions.html:5 -#: dashboard/templates/dashboard/node-list/column-admin.html:5 +#: dashboard/templates/dashboard/node-list/column-actions.html:9 #: dashboard/templates/dashboard/node-list/column-name.html:7 #: dashboard/templates/dashboard/vm-detail/home.html:22 #: dashboard/templates/dashboard/vm-list/column-name.html:7 @@ -996,7 +1096,7 @@ msgstr "Átnevezés" #: dashboard/templates/dashboard/node-detail.html:48 #: dashboard/templates/dashboard/confirm/ajax-delete.html:18 #: dashboard/templates/dashboard/confirm/mass-delete.html:12 -#: dashboard/templates/dashboard/node-list/column-actions.html:9 +#: dashboard/templates/dashboard/node-list/column-actions.html:29 #: dashboard/templates/dashboard/template-list/column-lease-actions.html:5 #: dashboard/templates/dashboard/template-list/column-template-actions.html:5 #: dashboard/templates/dashboard/userkey-list/column-userkey-actions.html:5 @@ -1060,13 +1160,6 @@ msgstr "Azon csoportok, amelyekhez hozzáférése van." msgid "Groups" msgstr "Csoportok" -#: dashboard/templates/dashboard/index-groups.html:21 -#: dashboard/templates/dashboard/index-nodes.html:32 -#: dashboard/templates/dashboard/index-vm.html:50 -#: dashboard/templates/dashboard/vm-list.html:20 -msgid "Search..." -msgstr "Keresés..." - #: dashboard/templates/dashboard/index-groups.html:30 #, python-format msgid "" @@ -1087,12 +1180,12 @@ msgstr[1] "" " " #: dashboard/templates/dashboard/index-groups.html:36 -#: dashboard/templates/dashboard/index-nodes.html:43 -#: dashboard/templates/dashboard/index-vm.html:65 +#: dashboard/templates/dashboard/index-nodes.html:45 +#: dashboard/templates/dashboard/index-vm.html:70 msgid "list" msgstr "felsorolás" -#: dashboard/templates/dashboard/index-nodes.html:10 +#: dashboard/templates/dashboard/index-nodes.html:12 msgid "" "List of compute nodes, also called worker nodes or hypervisors, which run " "the virtual machines." @@ -1100,13 +1193,13 @@ msgstr "" "A virtuális gépeket futtató számítási csomópontok (más néven worker node-ok, " "hypervisorok) listája." -#: dashboard/templates/dashboard/index-nodes.html:13 +#: dashboard/templates/dashboard/index-nodes.html:15 #: dashboard/templates/dashboard/node-list.html:5 msgid "Nodes" msgstr "Csomópontok" -#: dashboard/templates/dashboard/index-nodes.html:41 -#: dashboard/templates/dashboard/index-nodes.html:68 +#: dashboard/templates/dashboard/index-nodes.html:43 +#: dashboard/templates/dashboard/index-nodes.html:70 #, python-format msgid "<strong>%(count)s</strong> more" msgstr "még <strong>%(count)s</strong>" @@ -1142,39 +1235,39 @@ msgstr "" msgid "show all" msgstr "összes" -#: dashboard/templates/dashboard/index-vm.html:7 +#: dashboard/templates/dashboard/index-vm.html:8 msgid "summary view" msgstr "összefoglaló nézet" -#: dashboard/templates/dashboard/index-vm.html:9 +#: dashboard/templates/dashboard/index-vm.html:11 msgid "list view" msgstr "listanézet" -#: dashboard/templates/dashboard/index-vm.html:11 +#: dashboard/templates/dashboard/index-vm.html:13 msgid "" "List of your current virtual machines. Favourited ones are ahead of others." msgstr "A meglévő virtuális gépei. A megjelöltek megelőzik a többit." -#: dashboard/templates/dashboard/index-vm.html:14 +#: dashboard/templates/dashboard/index-vm.html:16 #: dashboard/templates/dashboard/vm-list.html:4 #: dashboard/templates/dashboard/vm-list.html:16 templates/info/help.html:46 msgid "Virtual machines" msgstr "Virtuális gépek" -#: dashboard/templates/dashboard/index-vm.html:29 +#: dashboard/templates/dashboard/index-vm.html:31 msgid "Unfavourite" msgstr "Kedvencnek jelölés törlése" -#: dashboard/templates/dashboard/index-vm.html:31 +#: dashboard/templates/dashboard/index-vm.html:33 msgid "Mark as favorite" msgstr "Kedvencnek jelölés" -#: dashboard/templates/dashboard/index-vm.html:38 -#: dashboard/templates/dashboard/vm-list.html:78 +#: dashboard/templates/dashboard/index-vm.html:40 +#: dashboard/templates/dashboard/vm-list.html:97 msgid "You have no virtual machines." msgstr "Még nincs virtuális gépe." -#: dashboard/templates/dashboard/index-vm.html:59 +#: dashboard/templates/dashboard/index-vm.html:64 #, python-format msgid "" "\n" @@ -1193,12 +1286,12 @@ msgstr[1] "" " még <strong>%(counter)s</strong>\n" " " -#: dashboard/templates/dashboard/index-vm.html:77 +#: dashboard/templates/dashboard/index-vm.html:82 #, python-format msgid "<big>%(count)s</big> running" msgstr "<big>%(count)s</big> fut" -#: dashboard/templates/dashboard/index-vm.html:93 +#: dashboard/templates/dashboard/index-vm.html:98 #, python-format msgid "" "\n" @@ -1217,7 +1310,7 @@ msgstr[1] "" " összesen <strong>%(counter)s</strong> gép\n" " " -#: dashboard/templates/dashboard/index-vm.html:99 +#: dashboard/templates/dashboard/index-vm.html:104 #, python-format msgid "<big>%(count)s</big> stopped" msgstr "<big>%(count)s</big> leállítva" @@ -1230,29 +1323,29 @@ msgstr "Kezdőoldal" msgid "You have no permission to start or manage virtual machines." msgstr "Nincs jogosultsága virtuális gépek indítására vagy kezelésére." -#: dashboard/templates/dashboard/instanceactivity_detail.html:29 -#: dashboard/templates/dashboard/node-detail.html:82 +#: dashboard/templates/dashboard/instanceactivity_detail.html:25 +#: dashboard/templates/dashboard/node-detail.html:91 #: dashboard/templates/dashboard/vm-detail.html:155 #: dashboard/templates/dashboard/node-detail/activity.html:3 #: dashboard/templates/dashboard/vm-detail/activity.html:3 msgid "Activity" msgstr "Tevékenységek" -#: dashboard/templates/dashboard/instanceactivity_detail.html:35 -#: vm/models/activity.py:71 vm/models/instance.py:278 vm/models/network.py:68 +#: dashboard/templates/dashboard/instanceactivity_detail.html:31 +#: vm/models/activity.py:71 vm/models/instance.py:282 vm/models/network.py:68 msgid "instance" msgstr "példány" -#: dashboard/templates/dashboard/instanceactivity_detail.html:38 +#: dashboard/templates/dashboard/instanceactivity_detail.html:34 msgid "time" msgstr "idő" -#: dashboard/templates/dashboard/instanceactivity_detail.html:44 -#: firewall/models.py:850 firewall/models.py:976 +#: dashboard/templates/dashboard/instanceactivity_detail.html:40 +#: firewall/models.py:847 firewall/models.py:973 msgid "type" msgstr "típus" -#: dashboard/templates/dashboard/instanceactivity_detail.html:47 +#: dashboard/templates/dashboard/instanceactivity_detail.html:43 #, python-format msgid "" "\n" @@ -1263,19 +1356,19 @@ msgstr "" " <a href=\"%(url)s\">%(name)s</a> résztevékenysége\n" " " -#: dashboard/templates/dashboard/instanceactivity_detail.html:50 +#: dashboard/templates/dashboard/instanceactivity_detail.html:46 msgid "top level activity" msgstr "felső szintű tevékenység" -#: dashboard/templates/dashboard/instanceactivity_detail.html:53 +#: dashboard/templates/dashboard/instanceactivity_detail.html:49 msgid "task uuid" msgstr "feladat uuid" -#: dashboard/templates/dashboard/instanceactivity_detail.html:56 +#: dashboard/templates/dashboard/instanceactivity_detail.html:52 msgid "status" msgstr "állapot" -#: dashboard/templates/dashboard/instanceactivity_detail.html:63 +#: dashboard/templates/dashboard/instanceactivity_detail.html:59 msgid "resultant state" msgstr "új állapot" @@ -1301,31 +1394,61 @@ msgid "Edit lease" msgstr "Bérlési mód szerkesztése" #: dashboard/templates/dashboard/lease-edit.html:27 -#: dashboard/templates/dashboard/template-edit.html:60 +#: dashboard/templates/dashboard/template-edit.html:72 #: network/templates/network/vlan-edit.html:24 msgid "Manage access" msgstr "Jogosultságok kezelése" +#: dashboard/templates/dashboard/mass-operate.html:6 +#, python-format +msgid "" +"\n" +"Do you want to perform the <strong>%(op)s</strong> operation on the " +"following instance?\n" +msgid_plural "" +"\n" +"Do you want to perform the <strong>%(op)s</strong> operation on the " +"following %(count)s instances?\n" +msgstr[0] "" +"\n" +"Biztosan végrehajtja a(z) <strong>%(op)s</strong> műveletet a következő " +"példányon?\n" +msgstr[1] "" +"\n" +"Biztosan végrehajtja a(z) <strong>%(op)s</strong> műveletet a következő %" +"(count)s példányon?\n" + +#: dashboard/templates/dashboard/mass-operate.html:33 +#: dashboard/templates/dashboard/operate.html:21 +#: dashboard/templates/dashboard/confirm/ajax-delete.html:15 +#: dashboard/templates/dashboard/confirm/ajax-node-flush.html:17 +#: dashboard/templates/dashboard/confirm/ajax-node-status.html:17 +#: dashboard/templates/dashboard/confirm/base-delete.html:27 +#: dashboard/templates/dashboard/confirm/mass-delete.html:11 +#: dashboard/templates/dashboard/confirm/node-status.html:27 +#: dashboard/templates/dashboard/store/remove.html:34 +msgid "Cancel" +msgstr "Mégsem" + #: dashboard/templates/dashboard/node-add-trait.html:19 msgid "Add Trait" msgstr "Jellemző hozzáadása" #: dashboard/templates/dashboard/node-detail.html:11 #: dashboard/templates/dashboard/node-detail.html:36 -#: dashboard/templates/dashboard/node-list/column-actions.html:6 -#: dashboard/templates/dashboard/node-list/column-admin.html:2 +#: dashboard/templates/dashboard/node-list/column-actions.html:14 msgid "Flush" msgstr "Ürítés" #: dashboard/templates/dashboard/node-detail.html:12 #: dashboard/templates/dashboard/node-detail.html:40 -#: dashboard/templates/dashboard/node-list/column-actions.html:7 +#: dashboard/templates/dashboard/node-list/column-actions.html:19 msgid "Enable" msgstr "Engedélyezés" #: dashboard/templates/dashboard/node-detail.html:13 #: dashboard/templates/dashboard/node-detail.html:44 -#: dashboard/templates/dashboard/node-list/column-actions.html:8 +#: dashboard/templates/dashboard/node-list/column-actions.html:24 msgid "Disable" msgstr "Tiltás" @@ -1349,12 +1472,12 @@ msgstr "Csomópont tiltása." msgid "Remove node and it's host." msgstr "Csomópont és hoszt törlése." -#: dashboard/templates/dashboard/node-detail.html:70 +#: dashboard/templates/dashboard/node-detail.html:72 #: dashboard/templates/dashboard/vm-detail.html:131 msgid "Home" msgstr "Kezdőoldal" -#: dashboard/templates/dashboard/node-detail.html:78 +#: dashboard/templates/dashboard/node-detail.html:85 msgid "Virtual Machines" msgstr "Virtuális gépek" @@ -1374,17 +1497,6 @@ msgstr "" "Biztosan végrehajtja a(z) <strong>%(op)s</strong> műveletet\n" "a következőn: <a data-dismiss=\"modal\" href=\"%(url)s\">%(obj)s</a>?\n" -#: dashboard/templates/dashboard/operate.html:21 -#: dashboard/templates/dashboard/confirm/ajax-delete.html:15 -#: dashboard/templates/dashboard/confirm/ajax-node-flush.html:17 -#: dashboard/templates/dashboard/confirm/ajax-node-status.html:17 -#: dashboard/templates/dashboard/confirm/base-delete.html:27 -#: dashboard/templates/dashboard/confirm/mass-delete.html:11 -#: dashboard/templates/dashboard/confirm/node-status.html:27 -#: dashboard/templates/dashboard/store/remove.html:34 -msgid "Cancel" -msgstr "Mégsem" - #: dashboard/templates/dashboard/profile.html:5 #: dashboard/templates/dashboard/profile_form.html:6 msgid "Profile" @@ -1468,15 +1580,15 @@ msgstr "SSH publikus kulcsok" msgid "Edit template" msgstr "Sablon szerkesztése" -#: dashboard/templates/dashboard/template-edit.html:51 -msgid "Save changes" -msgstr "Változások mentése" +#: dashboard/templates/dashboard/template-edit.html:32 +msgid "Visit" +msgstr "Megtekintés" -#: dashboard/templates/dashboard/template-edit.html:70 +#: dashboard/templates/dashboard/template-edit.html:82 msgid "Disk list" msgstr "Lemezek" -#: dashboard/templates/dashboard/template-edit.html:75 +#: dashboard/templates/dashboard/template-edit.html:87 #: dashboard/templates/dashboard/vm-detail/resources.html:39 msgid "No disks are added!" msgstr "Egy lemez sincs hozzáadva!" @@ -1597,7 +1709,7 @@ msgid "Connection is not possible." msgstr "A csatlakozás nem lehetséges." #: dashboard/templates/dashboard/vm-detail.html:121 -#: dashboard/templates/dashboard/vm-list.html:29 +#: dashboard/templates/dashboard/vm-list.html:22 msgid "Select all" msgstr "Összes kiválasztása" @@ -1613,44 +1725,23 @@ msgstr "Hozzáférés" msgid "Sorting ... " msgstr "Rendezés…" -#: dashboard/templates/dashboard/vm-list.html:28 +#: dashboard/templates/dashboard/vm-list.html:21 msgid "Group actions" msgstr "Csoportos műveletek" -#: dashboard/templates/dashboard/vm-list.html:30 -msgid "Migrate" -msgstr "Migrálás" - -#: dashboard/templates/dashboard/vm-list.html:31 -msgid "Reboot" -msgstr "Újraindítás" - -#: dashboard/templates/dashboard/vm-list.html:32 -msgid "Shutdown" -msgstr "Leállítás" - -#: dashboard/templates/dashboard/vm-list.html:33 -msgid "Destroy" -msgstr "Megsemmisítés" - -#: dashboard/templates/dashboard/vm-list.html:40 +#: dashboard/templates/dashboard/vm-list.html:50 msgid "ID" msgstr "ID" -#: dashboard/templates/dashboard/vm-list.html:48 +#: dashboard/templates/dashboard/vm-list.html:58 msgid "State" msgstr "Állapot" -#: dashboard/templates/dashboard/vm-list.html:52 -#: dashboard/templates/dashboard/vm-detail/access.html:2 -msgid "Owner" -msgstr "Tulajdonos" - -#: dashboard/templates/dashboard/vm-list.html:76 +#: dashboard/templates/dashboard/vm-list.html:95 msgid "No result." msgstr "Nincs eredmény." -#: dashboard/templates/dashboard/vm-list.html:92 +#: dashboard/templates/dashboard/vm-list.html:114 msgid "" "You can select multiple vm instances while holding down the <strong>CTRL</" "strong> key." @@ -1658,7 +1749,7 @@ msgstr "" "Több virtuális gépet is kiválaszthat a <strong>CTRL</strong> billentyű " "lenyomásával." -#: dashboard/templates/dashboard/vm-list.html:93 +#: dashboard/templates/dashboard/vm-list.html:115 msgid "" "If you want to select multiple instances by one click select an instance " "then hold down <strong>SHIFT</strong> key and select another one!" @@ -1864,14 +1955,22 @@ msgstr "Engedélyezve" msgid "Host online" msgstr "Gép elérhető" +#: dashboard/templates/dashboard/node-detail/resources.html:12 +msgid "Priority" +msgstr "Prioritás" + #: dashboard/templates/dashboard/node-detail/resources.html:13 msgid "Host owner" msgstr "Gép tulajdonosa" -#: dashboard/templates/dashboard/node-detail/resources.html:15 +#: dashboard/templates/dashboard/node-detail/resources.html:18 msgid "Host name" msgstr "Gépnév" +#: dashboard/templates/dashboard/node-detail/resources.html:23 +msgid "Edit host" +msgstr "Gép szerkesztése" + #: dashboard/templates/dashboard/notifications/email.txt:2 #, python-format msgid "Dear %(u)s," @@ -1923,7 +2022,7 @@ msgid "Name " msgstr "Név " #: dashboard/templates/dashboard/store/_list-box.html:73 -#: dashboard/templates/dashboard/store/index-files.html:51 +#: dashboard/templates/dashboard/store/index-files.html:57 msgid "Refresh" msgstr "Frissítés" @@ -1936,7 +2035,7 @@ msgid "Latest modification" msgstr "Legutóbbi változtatás" #: dashboard/templates/dashboard/store/_list-box.html:128 -#: dashboard/templates/dashboard/store/index-files.html:29 +#: dashboard/templates/dashboard/store/index-files.html:30 msgid "Download" msgstr "Letöltés" @@ -1966,15 +2065,19 @@ msgstr "" msgid "Files" msgstr "Fájlok" -#: dashboard/templates/dashboard/store/index-files.html:33 +#: dashboard/templates/dashboard/store/index-files.html:34 msgid "Show in directory" -msgstr "Megjelenítés könyvtában" +msgstr "Megjelenítés könyvtárban" + +#: dashboard/templates/dashboard/store/index-files.html:50 +msgid "Your toplist is empty, upload something." +msgstr "Nincs friss fájlja. Töltsön föl valamit most." -#: dashboard/templates/dashboard/store/index-files.html:56 +#: dashboard/templates/dashboard/store/index-files.html:62 msgid "show my files" msgstr "fájlok megjelenítése" -#: dashboard/templates/dashboard/store/index-files.html:59 +#: dashboard/templates/dashboard/store/index-files.html:65 msgid "upload" msgstr "feltöltés" @@ -1992,6 +2095,7 @@ msgstr "Felsorolás" #: dashboard/templates/dashboard/store/list.html:4 #: dashboard/templates/dashboard/store/upload.html:4 +#: dashboard/templates/dashboard/vm-detail/home.html:105 msgid "Store" msgstr "Tárhely" @@ -2157,7 +2261,11 @@ msgstr "Nincs címke." msgid "Add tag" msgstr "Címke hozzáadása" -#: dashboard/templates/dashboard/vm-detail/network.html:8 vm/operations.py:114 +#: dashboard/templates/dashboard/vm-detail/home.html:94 +msgid "Template" +msgstr "Sablon" + +#: dashboard/templates/dashboard/vm-detail/network.html:8 vm/operations.py:121 msgid "add interface" msgstr "új interfész" @@ -2174,12 +2282,12 @@ msgid "edit" msgstr "szerkesztés" #: dashboard/templates/dashboard/vm-detail/network.html:34 -#: firewall/models.py:491 +#: firewall/models.py:482 msgid "IPv4 address" msgstr "IPv4 cím" #: dashboard/templates/dashboard/vm-detail/network.html:35 -#: firewall/models.py:501 +#: firewall/models.py:492 msgid "IPv6 address" msgstr "IPv6 cím" @@ -2307,10 +2415,10 @@ msgstr "irány" msgid "If the rule matches egress or ingress packets." msgstr "A szabály kimenő vagy bejövő csomagokra illeszkedik." -#: firewall/models.py:68 firewall/models.py:343 firewall/models.py:428 -#: firewall/models.py:451 firewall/models.py:508 firewall/models.py:831 -#: firewall/models.py:855 firewall/models.py:925 vm/models/instance.py:141 -#: vm/models/instance.py:228 +#: firewall/models.py:68 firewall/models.py:334 firewall/models.py:419 +#: firewall/models.py:442 firewall/models.py:499 firewall/models.py:828 +#: firewall/models.py:852 firewall/models.py:922 vm/models/instance.py:142 +#: vm/models/instance.py:232 msgid "description" msgstr "leírás" @@ -2397,17 +2505,17 @@ msgstr "Célport számának átírása a megadottra NAT esetén." msgid "external IPv4 address" msgstr "külső IPv4 cím" -#: firewall/models.py:118 firewall/models.py:376 firewall/models.py:433 -#: firewall/models.py:456 firewall/models.py:527 +#: firewall/models.py:118 firewall/models.py:367 firewall/models.py:424 +#: firewall/models.py:447 firewall/models.py:518 msgid "created at" msgstr "létrehozva" -#: firewall/models.py:121 firewall/models.py:380 firewall/models.py:435 -#: firewall/models.py:458 firewall/models.py:529 +#: firewall/models.py:121 firewall/models.py:371 firewall/models.py:426 +#: firewall/models.py:449 firewall/models.py:520 msgid "modified at" msgstr "módosítva" -#: firewall/models.py:124 firewall/models.py:516 vm/models/network.py:40 +#: firewall/models.py:124 firewall/models.py:507 vm/models/network.py:40 #: vm/models/network.py:65 msgid "vlan" msgstr "vlan" @@ -2424,8 +2532,8 @@ msgstr "vlan-csoport" msgid "Group of vlans the rule applies to (if type is vlan)." msgstr "Erre a vlan-csoportra vonatkozik a szabály (ha a típus vlan)." -#: firewall/models.py:133 firewall/models.py:848 firewall/models.py:968 -#: vm/models/network.py:67 vm/models/node.py:67 +#: firewall/models.py:133 firewall/models.py:845 firewall/models.py:965 +#: vm/models/network.py:67 vm/models/node.py:70 msgid "host" msgstr "gép" @@ -2453,39 +2561,39 @@ msgstr "Erre a tűzfalra vonatkozik a szabály (ha a típus tűzfal)." msgid "Only one field can be selected." msgstr "Csak egy mező választható ki." -#: firewall/models.py:256 +#: firewall/models.py:247 msgid "rule" msgstr "szabály" -#: firewall/models.py:257 +#: firewall/models.py:248 msgid "rules" msgstr "szabályok" -#: firewall/models.py:285 +#: firewall/models.py:276 msgid "public" msgstr "nyilvános" -#: firewall/models.py:286 +#: firewall/models.py:277 msgid "portforward" msgstr "porttovábbítás" -#: firewall/models.py:288 +#: firewall/models.py:279 msgid "VID" msgstr "VID" -#: firewall/models.py:289 +#: firewall/models.py:280 msgid "The vlan ID of the subnet." msgstr "Az alhálózat vlan-azonosítója." -#: firewall/models.py:295 +#: firewall/models.py:286 msgid "The short name of the subnet." msgstr "Az alhálózat rövid neve." -#: firewall/models.py:299 +#: firewall/models.py:290 msgid "IPv4 address/prefix" msgstr "IPv4 cím/prefixhossz" -#: firewall/models.py:301 +#: firewall/models.py:292 msgid "" "The IPv4 address and the prefix length of the gateway. Recommended value is " "the last valid address of the subnet, for example 10.4.255.254/16 for " @@ -2494,11 +2602,11 @@ msgstr "" "Az útválasztó IPv4 címe és prefixhossza. Az ajánlott érték az alhálózat " "utolsó érvényes címe, például 10.4.255.254/16 a 10.4.0.0/16 hálózat esetén." -#: firewall/models.py:308 +#: firewall/models.py:299 msgid "IPv6 prefixlen/host" msgstr "IPv6 prefixhossz/gép" -#: firewall/models.py:309 +#: firewall/models.py:300 msgid "" "The prefix length of the subnet assigned to a host. For example /112 = 65536 " "addresses/host." @@ -2506,19 +2614,19 @@ msgstr "" "A géphez rendelt alhálózat prefixhossza. Például a /112 beállítás 65536 " "címet jelent gépenként." -#: firewall/models.py:317 +#: firewall/models.py:308 msgid "IPv6 address/prefix" msgstr "IPv6 cím/prefixhossz" -#: firewall/models.py:319 +#: firewall/models.py:310 msgid "The IPv6 address and the prefix length of the gateway." msgstr "Az útválasztó IPv6 címe és prefixhossza." -#: firewall/models.py:323 +#: firewall/models.py:314 msgid "NAT IP address" msgstr "NAT IP cím" -#: firewall/models.py:325 +#: firewall/models.py:316 msgid "" "Common IPv4 address used for address translation of connections to the " "networks selected below (typically to the internet)." @@ -2526,11 +2634,11 @@ msgstr "" "Közös címfordításra használt IPv4 cím a kiválasztott hálózatok felé irányuló " "kapcsolatokhoz (tipikusan az internet felé)." -#: firewall/models.py:331 +#: firewall/models.py:322 msgid "NAT to" msgstr "NAT ide" -#: firewall/models.py:333 +#: firewall/models.py:324 msgid "" "Connections to these networks should be network address translated, i.e. " "their source address is rewritten to the value of NAT IP address." @@ -2538,39 +2646,39 @@ msgstr "" "A megadott hálózatok felé induló kapcsolatok címfordításra kerülnek: a " "forráscímük a megadott NAT IP címre lesz átírva." -#: firewall/models.py:339 +#: firewall/models.py:330 msgid "network type" msgstr "hálózat típusa" -#: firewall/models.py:342 vm/models/network.py:42 +#: firewall/models.py:333 vm/models/network.py:42 msgid "managed" msgstr "menedzselt" -#: firewall/models.py:345 +#: firewall/models.py:336 msgid "Description of the goals and elements of the vlan network." msgstr "A vlan hálózat céljainak és elemeinek leírása." -#: firewall/models.py:347 +#: firewall/models.py:338 msgid "comment" msgstr "megjegyzés" -#: firewall/models.py:349 +#: firewall/models.py:340 msgid "Notes, comments about the network" msgstr "Jegyzetek, megjegyzések a hálózatról" -#: firewall/models.py:350 +#: firewall/models.py:341 msgid "domain name" msgstr "tartománynév" -#: firewall/models.py:351 +#: firewall/models.py:342 msgid "Domain name of the members of this network." msgstr "A hálózat tagjainak tartományneve." -#: firewall/models.py:355 +#: firewall/models.py:346 msgid "reverse domain" msgstr "reverz tartomány" -#: firewall/models.py:356 +#: firewall/models.py:347 #, python-format msgid "" "Template of the IPv4 reverse domain name that should be generated for each " @@ -2585,15 +2693,15 @@ msgstr "" "Például a szabványos reverz név sablonja: \"%(d)d.%(c)d.%(b)d.%(a)d.in-addr." "arpa\"." -#: firewall/models.py:366 +#: firewall/models.py:357 msgid "ipv6 template" msgstr "ipv6 sablon" -#: firewall/models.py:368 +#: firewall/models.py:359 msgid "DHCP pool" msgstr "DHCP készlet" -#: firewall/models.py:370 +#: firewall/models.py:361 msgid "" "The address range of the DHCP pool: empty for no DHCP service, \"manual\" " "for no DHCP pool, or the first and last address of the range separated by a " @@ -2603,47 +2711,47 @@ msgstr "" "tiltásához adja meg a „manual” értéket, engedélyezéséhez az első és utolsó " "érvényes címet szóközzel elválasztva." -#: firewall/models.py:414 +#: firewall/models.py:405 msgid "All IP addresses are already in use." msgstr "Minden IP cím használatban van." -#: firewall/models.py:422 firewall/models.py:449 firewall/models.py:802 -#: firewall/models.py:824 firewall/models.py:845 storage/models.py:47 +#: firewall/models.py:413 firewall/models.py:440 firewall/models.py:799 +#: firewall/models.py:821 firewall/models.py:842 storage/models.py:47 #: storage/models.py:86 vm/models/common.py:65 vm/models/common.py:89 -#: vm/models/common.py:165 vm/models/instance.py:139 vm/models/instance.py:226 -#: vm/models/node.py:62 +#: vm/models/common.py:165 vm/models/instance.py:140 vm/models/instance.py:230 +#: vm/models/node.py:65 msgid "name" msgstr "név" -#: firewall/models.py:423 firewall/models.py:450 +#: firewall/models.py:414 firewall/models.py:441 msgid "The name of the group." msgstr "A csoport neve." -#: firewall/models.py:425 +#: firewall/models.py:416 msgid "vlans" msgstr "vlanok" -#: firewall/models.py:426 +#: firewall/models.py:417 msgid "The vlans which are members of the group." msgstr "A csoport tagjait képező vlanok." -#: firewall/models.py:429 firewall/models.py:452 +#: firewall/models.py:420 firewall/models.py:443 msgid "Description of the group." msgstr "A csoport leírása." -#: firewall/models.py:474 storage/models.py:50 +#: firewall/models.py:465 storage/models.py:50 msgid "hostname" msgstr "gépnév" -#: firewall/models.py:475 +#: firewall/models.py:466 msgid "The alphanumeric hostname of the host, the first part of the FQDN." msgstr "A gép alfanumerikus gépneve, az FQDN első része." -#: firewall/models.py:481 +#: firewall/models.py:472 msgid "reverse" msgstr "reverz" -#: firewall/models.py:482 +#: firewall/models.py:473 msgid "" "The fully qualified reverse hostname of the host, if different than hostname." "domain." @@ -2651,139 +2759,139 @@ msgstr "" "A gép teljes reverz tartományneve, amennyiben különbözik ettől: gépnév." "tartomány." -#: firewall/models.py:486 +#: firewall/models.py:477 msgid "MAC address" msgstr "MAC cím" -#: firewall/models.py:487 +#: firewall/models.py:478 msgid "" "The MAC (Ethernet) address of the network interface. For example: 99:AA:BB:" "CC:DD:EE." msgstr "A hálózati interfész MAC (Ethernet) címe. Például 99:AA:BB:CC:DD:EE." -#: firewall/models.py:492 +#: firewall/models.py:483 msgid "The real IPv4 address of the host, for example 10.5.1.34." msgstr "A gép valódi IPv4 címe, például 10.5.1.34." -#: firewall/models.py:496 +#: firewall/models.py:487 msgid "WAN IPv4 address" msgstr "WAN IPv4 cím" -#: firewall/models.py:497 +#: firewall/models.py:488 msgid "" "The public IPv4 address of the host on the wide area network, if different." msgstr "A gép nyilvános IPv4 címe a nagy kiterjedésű hálózaton, ha eltér." -#: firewall/models.py:502 +#: firewall/models.py:493 msgid "The global IPv6 address of the host, for example 2001:db:88:200::10." msgstr "A gép globális IPv6 címe, például 2001:db:88:200::10." -#: firewall/models.py:504 +#: firewall/models.py:495 msgid "shared IP" msgstr "osztott IP" -#: firewall/models.py:506 +#: firewall/models.py:497 msgid "If the given WAN IPv4 address is used by multiple hosts." msgstr "A WAN IPv4 címet több gép használja-e." -#: firewall/models.py:509 +#: firewall/models.py:500 msgid "What is this host for, what kind of machine is it." msgstr "Mi a gép célja, milyen gép ez." -#: firewall/models.py:512 +#: firewall/models.py:503 msgid "Notes" msgstr "Jegyzetek" -#: firewall/models.py:513 +#: firewall/models.py:504 msgid "location" msgstr "elhelyezés" -#: firewall/models.py:515 +#: firewall/models.py:506 msgid "The physical location of the machine." msgstr "A gép fizikai helye." -#: firewall/models.py:518 +#: firewall/models.py:509 msgid "Vlan network that the host is part of." msgstr "Az a vlan hálózat, amelynek a gép része." -#: firewall/models.py:521 +#: firewall/models.py:512 msgid "The person responsible for this host." msgstr "A gépért felelős személy." -#: firewall/models.py:523 +#: firewall/models.py:514 msgid "groups" msgstr "csoportok" -#: firewall/models.py:525 +#: firewall/models.py:516 msgid "Host groups the machine is part of." msgstr "Gépcsoportok, amelyeknek tagja a gép." -#: firewall/models.py:562 +#: firewall/models.py:553 msgid "If shared_ip has been checked, external_ipv4 has to be unique." msgstr "" "Amennyiben az osztott IP mező igaz, a külső IPv4 cím mező egyedi kell legyen." -#: firewall/models.py:565 +#: firewall/models.py:556 msgid "You can't use another host's NAT'd address as your own IPv4." msgstr "Nem használható másik gép NAT-olt címe saját IPv4 címként." -#: firewall/models.py:654 +#: firewall/models.py:649 #, python-format msgid "All %s ports are already in use." msgstr "Minden %s port használatban van." -#: firewall/models.py:672 +#: firewall/models.py:667 #, python-format msgid "Port %(proto)s %(public)s is already in use." msgstr "A(z) %(public)s %(proto)s port használatban van." -#: firewall/models.py:690 +#: firewall/models.py:685 msgid "Only ports above 1024 can be used." msgstr "Csak az 1024 feletti portok használhatóak." -#: firewall/models.py:827 firewall/models.py:857 firewall/models.py:927 -#: firewall/models.py:955 firewall/models.py:979 +#: firewall/models.py:824 firewall/models.py:854 firewall/models.py:924 +#: firewall/models.py:952 firewall/models.py:976 msgid "created_at" msgstr "létrehozva" -#: firewall/models.py:829 firewall/models.py:859 firewall/models.py:929 -#: firewall/models.py:957 firewall/models.py:981 +#: firewall/models.py:826 firewall/models.py:856 firewall/models.py:926 +#: firewall/models.py:954 firewall/models.py:978 msgid "modified_at" msgstr "módosítva" -#: firewall/models.py:830 firewall/models.py:853 +#: firewall/models.py:827 firewall/models.py:850 msgid "ttl" msgstr "ttl" -#: firewall/models.py:846 +#: firewall/models.py:843 msgid "domain" msgstr "tartomány" -#: firewall/models.py:852 +#: firewall/models.py:849 msgid "address" msgstr "cím" -#: firewall/models.py:874 +#: firewall/models.py:871 msgid "Address must be specified!" msgstr "A cím megadása kötelező." -#: firewall/models.py:887 +#: firewall/models.py:884 msgid "Unknown record type." msgstr "Ismeretlen rekordtípus." -#: firewall/models.py:921 +#: firewall/models.py:918 msgid "untagged vlan" msgstr "untagged vlan" -#: firewall/models.py:924 +#: firewall/models.py:921 msgid "tagged vlans" msgstr "tagged vlanok" -#: firewall/models.py:947 +#: firewall/models.py:944 msgid "interface" msgstr "interfész" -#: firewall/models.py:948 +#: firewall/models.py:945 msgid "" "The name of network interface the gateway should serve this network on. For " "example eth2." @@ -2791,23 +2899,23 @@ msgstr "" "Azon hálózati interfész nevve, amelyen az útválasztó ezt a hálózatot " "kiszolgálja. Például eth2." -#: firewall/models.py:953 +#: firewall/models.py:950 msgid "switch port" msgstr "switch port" -#: firewall/models.py:969 +#: firewall/models.py:966 msgid "reason" msgstr "indok" -#: firewall/models.py:971 +#: firewall/models.py:968 msgid "short message" msgstr "rövid üzenet" -#: firewall/models.py:991 +#: firewall/models.py:988 msgid "blacklist item" msgstr "tiltólista eleme" -#: firewall/models.py:992 +#: firewall/models.py:989 msgid "blacklist" msgstr "tiltólista" @@ -3297,7 +3405,7 @@ msgstr "eszközazonosító" msgid "disk" msgstr "lemez" -#: storage/models.py:104 vm/models/instance.py:146 vm/models/instance.py:253 +#: storage/models.py:104 vm/models/instance.py:147 vm/models/instance.py:257 msgid "disks" msgstr "lemezek" @@ -3379,7 +3487,7 @@ msgstr "" "lemezen, mivel az alapja, „%(b_name)s” (%(b_pk)s) [%(b_filename)s] nem " "volt még csatolva." -#: storage/models.py:413 storage/models.py:488 vm/models/instance.py:886 +#: storage/models.py:413 storage/models.py:488 vm/models/instance.py:895 msgid "Operation aborted by user." msgstr "A műveletet a felhasználó megszakította." @@ -3395,7 +3503,7 @@ msgstr "Az oldal nem létezik." msgid ":(" msgstr ":(" -#: templates/500.html:13 +#: templates/500.html:18 msgid "Internal Server Error... Please leave the server alone..." msgstr "Kiszolgálóoldali hiba. Ne bántsa a szervert." @@ -3428,7 +3536,8 @@ msgid "" " instances based on templates.\n" " These templates are also easy to create.\n" " " -msgstr "\n" +msgstr "" +"\n" "Legfontosabb funkciója a virtuális gépek indítása és kezelése könnyen " "létrehozható sablonok alapján." @@ -3440,7 +3549,8 @@ msgid "" " intuitive, and the web interface shows detailed instructions on\n" " advanced options.\n" " " -msgstr "\n" +msgstr "" +"\n" "Ezen az útmutatón kívül javasoljuk, hogy próbálja ki a rendszert, amelynek " "használata magától értetődő. A webes felületen részletes útmutatást talál a " "haladó lehetőségekről." @@ -3453,7 +3563,8 @@ msgid "" "can log in\n" " to the dashboard.\n" " " -msgstr "\n" +msgstr "" +"\n" "A szolgáltatást a <tt>https://%(host)s/</tt> címen érheti el. Itt " "bejelentkezhet az irányítópultra." @@ -3464,7 +3575,8 @@ msgid "" " resources, and the main starting point to access the functions of\n" " the system.\n" " " -msgstr "\n" +msgstr "" +"\n" "Az irányítópult összefoglalja a virtuális gépeket és más erőforrásokat. Ez a " "kiindulópont a rendszer lehetőségeinek eléréséhez." @@ -3482,12 +3594,12 @@ msgid "" " Click on the name of a virtual machine to see its connection\n" " details, preferences, or to change its state.\n" " " -msgstr "\n" -"A <em>virtuális gépek</em> dobozban találja legutóbbi virtuális gépeit. " -"Egy összefoglaló nézet is elérhető az műszer gombra (<i class=\"fa " -"fa-dashboard\"></i>) kattintva. " -"Kattintson a virtuális gép nevére a kapcsolódási adatok, beállítások " -"megtekintéséhez, vagy az állapotának megváltoztatásához." +msgstr "" +"\n" +"A <em>virtuális gépek</em> dobozban találja legutóbbi virtuális gépeit. Egy " +"összefoglaló nézet is elérhető az műszer gombra (<i class=\"fa fa-dashboard" +"\"></i>) kattintva. Kattintson a virtuális gép nevére a kapcsolódási adatok, " +"beállítások megtekintéséhez, vagy az állapotának megváltoztatásához." #: templates/info/help.html:61 msgid "" @@ -3501,14 +3613,14 @@ msgid "" " <i class=\"fa fa-plus-circle\"></i> new</span> button, and\n" " choosing a template.\n" " " -msgstr "\n" -"A fontos vagy gyakran használt gépeket megjelölheti kedvencként (<i " -"class=\"fa fa-star-o\"></i>). " -"A keresés mező inkrementálisan mutatja az eredményeket, beküldésével (⏎) " -"közvetlenül a megtalált gépre ugrik, ha pontosan egy találat van. " -"Új virtuális gépeket az <span class=\"btn btn-success disabled btn-xs\"><i " -"class=\"fa fa-plus-circle\"></i> új</span> gombra kattintva, majd a sablont " -"kiválasztva indíthat. " +msgstr "" +"\n" +"A fontos vagy gyakran használt gépeket megjelölheti kedvencként (<i class=" +"\"fa fa-star-o\"></i>). A keresés mező inkrementálisan mutatja az " +"eredményeket, beküldésével (⏎) közvetlenül a megtalált gépre ugrik, ha " +"pontosan egy találat van. Új virtuális gépeket az <span class=\"btn btn-" +"success disabled btn-xs\"><i class=\"fa fa-plus-circle\"></i> új</span> " +"gombra kattintva, majd a sablont kiválasztva indíthat. " #: templates/info/help.html:72 msgid "" @@ -3523,11 +3635,12 @@ msgid "" "about\n" " the machine in categories.\n" " " -msgstr "\n" -"Ha kiválaszt egy virtuális gépet, a gép adatait és műveleteit elérhetővé tévő " -"oldalra jut. Baloldalt a gép állapotát és a <strong>csatlakozáshoz</strong> " -"szükséges adatokat találja. Középen egy több lapból álló panel van, amely a " -"gép összes részletét kategorizálva mutatja be." +msgstr "" +"\n" +"Ha kiválaszt egy virtuális gépet, a gép adatait és műveleteit elérhetővé " +"tévő oldalra jut. Baloldalt a gép állapotát és a <strong>csatlakozáshoz</" +"strong> szükséges adatokat találja. Középen egy több lapból álló panel van, " +"amely a gép összes részletét kategorizálva mutatja be." #: templates/info/help.html:81 msgid "" @@ -3536,9 +3649,10 @@ msgid "" " important actions that control the <strong>lifecycle</strong> of\n" " the machine.\n" " " -msgstr "\n" -"A jobb felső sarokban a műveleteket tartalmazó eszköztár található a gép <" -"strong>életciklusát</strong> befolyásoló, legfontosabb műveletekkel." +msgstr "" +"\n" +"A jobb felső sarokban a műveleteket tartalmazó eszköztár található a gép " +"<strong>életciklusát</strong> befolyásoló, legfontosabb műveletekkel." #: templates/info/help.html:87 msgid "" @@ -3551,7 +3665,8 @@ msgid "" " You can click on them as the confirmation dialog explains in\n" " detail what they do.\n" " " -msgstr "\n" +msgstr "" +"\n" "Az eszköztár gombjai színkódoltak a hatásuk szerint, valamint a gép " "állapotától függően kerülnek engedélyezésre/tiltásra. Az ajánlott művelet " "gombja a legnagyobb, amelyen szerepel az adott művelet megnevezése is. " @@ -3572,7 +3687,8 @@ msgid "" " can reset the counters. Of course you will get a notification if\n" " the machine is going to expire.\n" " " -msgstr "\n" +msgstr "" +"\n" "A <strong><i class=\"fa fa-compass\"></i> Kezdőoldal</strong> lap " "statisztikát mutat be a gép működéséről, valamint itt változtathatja meg a " "gép nevét, leírását és címkéit. Kifejezetten ajánljuk a leírás kitöltését, " @@ -3591,19 +3707,19 @@ msgid "" " details about how much memory and CPU the VM has, and how is it\n" " scheduled.\n" " " -msgstr "\n" -"Az" -" <strong><i class=\"fa fa-tasks\"></i> Erőforrások</strong> lap " +msgstr "" +"\n" +"Az <strong><i class=\"fa fa-tasks\"></i> Erőforrások</strong> lap " "bemutatja, hogy a virtuális gép mennyi CPU-val és memóriával rendelkezik, " -"valamint milyen az ütemezése." -" " +"valamint milyen az ütemezése. " #: templates/info/help.html:115 msgid "" "\n" " Users with specific permission can change these settings if\n" " the machine is stopped." -msgstr "\n" +msgstr "" +"\n" "A megfelelő jogosultsággal rendelkező felhasználók megváltoztathatják ezeket " "a beállításokat, ha a gépet leállították." @@ -3614,7 +3730,8 @@ msgid "" "allows\n" " to see the console of the virutal machine for troubleshooting and\n" " operating system installation." -msgstr "\n" +msgstr "" +"\n" "A\n" " <strong><i class=\"fa fa-desktop\"></i> Konzol</strong> lap " "lehetővé teszi a virtuális gépek hibaelhárítását és az operációs rendszer " @@ -3649,7 +3766,8 @@ msgid "" " Users can see the details of the machine, operators can use most\n" " functions, and owners can also destroy the machine.\n" " " -msgstr "\n" +msgstr "" +"\n" "A <strong><i class=\"fa fa-group\"></i> Hozzáférés</strong> lap a gép " "megosztását és a tulajdon átruházását teszi lehetővé. A gép felhasználói " "láthatják a gép részleteit, az operátorok használhatják a legtöbb műveletet, " @@ -3663,7 +3781,8 @@ msgid "" " You can add or remove interfaces, and allow remote access of\n" " different TCP/UDP ports.\n" " " -msgstr "\n" +msgstr "" +"\n" "A\n" " <strong><i class=\"fa fa-globe\"></i> Hálózat</strong> lap a " "virtuális gép hálózati kapcsolatait mutatja be. Lehetőség van interfészek " @@ -3680,7 +3799,8 @@ msgid "" "name of\n" " the action).\n" " " -msgstr "\n" +msgstr "" +"\n" "A \n" " <strong><i class=\"fa fa-clock-o\"></i> Tevékenységek</strong> " "lapon látszik a virtuális gép teljes élettörténete. Itt lehet a műveletek " @@ -3712,7 +3832,8 @@ msgid "" "can\n" " share them with your groups or other users.\n" " " -msgstr "\n" +msgstr "" +"\n" "Az irányítópulti dobozban a saját sablonait, valamint azokat látja, " "amelyekhez legalább <em>operátor</em> jogosultsága van. Ez azt jelenti, hogy " "megoszthatja őket csoportjaival vagy egyes felhasználókkal." @@ -3728,9 +3849,8 @@ msgid "" " " msgstr "" "\n" -" Bármely virtuális gépből létrehozhat sablont a" -" <span class=\"btn btn-info disabled btn-xs\"><i class=\"fa fa-" -"save\"></i>\n" +" Bármely virtuális gépből létrehozhat sablont a <span " +"class=\"btn btn-info disabled btn-xs\"><i class=\"fa fa-save\"></i>\n" " mentés sablonként</span>\n" " gomb segítségével.\n" " " @@ -3743,7 +3863,8 @@ msgid "" " <i class=\"fa fa-plus-circle\"></i> new</span> button of the\n" " template box, and follow the template creation wizard.\n" " " -msgstr "\n" +msgstr "" +"\n" "Ezen felül a sablonok dobozban lévő <span class=\"btn btn-success disabled " "btn-xs\"><i class=\"fa fa-plus-circle\"></i> új</span> gombbal is elindíthat " "egy sablonkészítő varázslót." @@ -3758,7 +3879,8 @@ msgid "" " Groups are the main building blocks of permission management.\n" " On the dashboard you see a list of groups you have access to.\n" " " -msgstr "\n" +msgstr "" +"\n" "A csoportok a jogosultságkezelés epítőelemei. Az irányítópulton azon " "csoportokat látja, amelykhez hozzáférése van." @@ -3770,7 +3892,8 @@ msgid "" " <i class=\"fa fa-plus-circle\"></i> new</span> button of the\n" " groups box.\n" " " -msgstr "\n" +msgstr "" +"\n" "Saját csoportokat is létrehozhat a csoportok dobozban lévő <span class=\"btn " "btn-success disabled btn-xs\"><i class=\"fa fa-plus-circle\"></i> új</span> " "gombbal." @@ -3786,7 +3909,8 @@ msgid "" " specific organizational identifier set, so members will\n" " automatically added if they log in.\n" " " -msgstr "\n" +msgstr "" +"\n" "SSO azonosítással belépett felhasználók automatikusan tagjai lehetnek " "csoportoknak a szervezeti azonosítójuk alapján. Aki adminisztrátorai egy " "csoportnak (vagy oktatói egy tantárgynak az akadémiai szférában) olyan " @@ -3799,7 +3923,8 @@ msgid "" " You can also add users based on their identifier, also if they\n" " have not logged in at the time.\n" " " -msgstr "\n" +msgstr "" +"\n" "Azonosítójuk alapján is hozzáadhat felhasználókat, akkor is, ha még nem " "léptek be a rendszerbe." @@ -3814,7 +3939,8 @@ msgid "" "easiest\n" " way to keep and retrieve your work done on virtual machines.\n" " " -msgstr "\n" +msgstr "" +"\n" "Minden felhasználónak van egy személyes tárhelye, ami a egyszerű módot ad a " "virtuális gépeken elkészített munka tárolására és letöltésére." @@ -3831,13 +3957,14 @@ msgid "" " <i class=\"fa fa-briefcase\"></i> mount store</span> button\n" " of the virtual machine.\n" " " -msgstr "\n" -"Fájljait a webes felületről és a virtuális gépekről is eléri. A webes felület " -"olyan, mint bármelyik fájlböngésző. A virtuális gépek alapesetben nem kapják " -"meg a tárhely eléréséhez szükséges azonosítókat elkerülendő megosztásukat a " -"gép esetleges többi használójával. A tárhely használatához nyomja meg a <span " -"class=\"btn btn-info disabled btn-xs\"><i class=\"fa fa-briefcase\"></i> " -"tárhely csatolása</span> gombot a virtuális gépen." +msgstr "" +"\n" +"Fájljait a webes felületről és a virtuális gépekről is eléri. A webes " +"felület olyan, mint bármelyik fájlböngésző. A virtuális gépek alapesetben " +"nem kapják meg a tárhely eléréséhez szükséges azonosítókat elkerülendő " +"megosztásukat a gép esetleges többi használójával. A tárhely használatához " +"nyomja meg a <span class=\"btn btn-info disabled btn-xs\"><i class=\"fa fa-" +"briefcase\"></i> tárhely csatolása</span> gombot a virtuális gépen." #: templates/info/help.html:251 msgid "" @@ -3854,7 +3981,8 @@ msgid "" " that can be deployed with minimal effort on a single computer as " "well as on a larger cluster.\n" " " -msgstr "\n" +msgstr "" +"\n" "A CIRCLE Cloud egy teljeskörű nyílt forrású felhőmegoldás, amely könnyen " "telepíthető egy gépre, vagy akár egy nagyobb fürtre." @@ -3866,8 +3994,7 @@ msgid "" " " msgstr "" "\n" -" A szolgáltatás üzemeltetője:" -" %(maintainer)s \n" +" A szolgáltatás üzemeltetője: %(maintainer)s \n" " " #: templates/info/policy.html:9 @@ -3879,7 +4006,9 @@ msgid "" "\n" " The system cannot be used for illegal activites.\n" " " -msgstr "\nA rendszer nem használható jogszerűtlen célokra." +msgstr "" +"\n" +"A rendszer nem használható jogszerűtlen célokra." #: templates/info/policy.html:22 msgid "" @@ -3901,7 +4030,8 @@ msgid "" " updating the operating system is the responsibility of the " "user.\n" " " -msgstr "\n" +msgstr "" +"\n" "A virtuális gépek biztonságos üzemeltetése, a rajtuk futó szoftverek " "frissítése a felhasználó felelőssége." @@ -3914,7 +4044,8 @@ msgid "" "either via SSH\n" " or NoMachine NX (GUI).\n" " " -msgstr "\n" +msgstr "" +"\n" "A gépekhez az adott operációs rendszeren szokásos módon csatlakozhat: Window " "alatt RDP-vel (távoli asztali kapcsolat), Linuxot futtató gépekhez SSH-val " "vagy grafikusan a NoMachine NX rendszerrel." @@ -3927,7 +4058,8 @@ msgid "" " you have an idea for a feature please contact the maintainer of the " "site.\n" " " -msgstr "\n" +msgstr "" +"\n" "A CIRCLE Cloud egy nyílt forrású felhőmegoldás. Amennyiben hibát tapasztal, " "vagy fejlesztési javaslata van, keresse meg a szolgáltatás üzemeltetőjét." @@ -3998,59 +4130,59 @@ msgstr "Jelszó visszaállítása" msgid "Enter your email address to reset your password!" msgstr "Adja meg e-mail címét a jelszó visszaállításához." -#: vm/operations.py:80 +#: vm/operations.py:85 #, python-format msgid "%(acl_level)s level is required for this operation." msgstr "%(acl_level)s jogosultság szükséges a művelethez." -#: vm/operations.py:115 +#: vm/operations.py:122 msgid "Add a new network interface for the specified VLAN to the VM." msgstr "Új hálózati interfész hozzáadása a megadott VLAN-ba." -#: vm/operations.py:123 +#: vm/operations.py:130 msgid "destroy network (rollback)" msgstr "hálózat megsemmisítése (visszagörgetés)" -#: vm/operations.py:130 +#: vm/operations.py:137 #, python-format msgid "User acces to vlan %(vlan)s is required." msgstr "Használói jogosultság szükséges a(z) %(vlan)s vlan-hoz." -#: vm/operations.py:142 +#: vm/operations.py:149 msgid "attach network" msgstr "hálózat csatolása" -#: vm/operations.py:151 +#: vm/operations.py:158 #, python-format msgid "add %(vlan)s interface" msgstr "új %(vlan)s interfész" -#: vm/operations.py:162 +#: vm/operations.py:169 msgid "create disk" msgstr "lemez létrehozása" -#: vm/operations.py:163 +#: vm/operations.py:170 msgid "Create and attach empty disk to the virtual machine." msgstr "Üres lemez létehozása és virtuális géphez csatolása." -#: vm/operations.py:184 +#: vm/operations.py:191 msgid "deploying disk" msgstr "lemez létrehozása" -#: vm/operations.py:189 vm/operations.py:234 +#: vm/operations.py:196 vm/operations.py:241 msgid "attach disk" msgstr "lemez csatolása" -#: vm/operations.py:195 +#: vm/operations.py:202 #, python-format msgid "create disk %(name)s (%(size)s)" msgstr "%(name)s lemez létrehozása (%(size)s)" -#: vm/operations.py:205 +#: vm/operations.py:212 msgid "download disk" msgstr "lemez letöltése" -#: vm/operations.py:206 +#: vm/operations.py:213 msgid "" "Download and attach disk image (ISO file) for the virtual machine. Most " "operating systems do not detect a new optical drive, so you may have to " @@ -4060,16 +4192,16 @@ msgstr "" "operációs rendszer nem érzékeli az új optikai meghajtót, így valószínűleg " "újra kell indítania a virtuális gépet." -#: vm/operations.py:228 +#: vm/operations.py:235 #, python-format msgid "download %(name)s" msgstr "%(name)s letöltése" -#: vm/operations.py:244 +#: vm/operations.py:251 msgid "deploy" msgstr "indítás" -#: vm/operations.py:245 +#: vm/operations.py:252 msgid "" "Deploy and start the virtual machine (including storage and network " "configuration)." @@ -4077,48 +4209,58 @@ msgstr "" "Virtuális gép elhelyezése és indítása (valamint a lemezek és a hálózat " "beállítása)." -#: vm/operations.py:266 +#: vm/operations.py:269 +#, python-format +msgid "virtual machine successfully deployed to node: %(node)s" +msgstr "a virtuális gép sikeresen elindítva a következő csomóponton: %(node)s" + +#: vm/operations.py:281 msgid "deploy disks" msgstr "lemez létrehozása" -#: vm/operations.py:273 +#: vm/operations.py:286 msgid "deploy virtual machine" msgstr "virtuális gép létrehozása" -#: vm/operations.py:279 vm/operations.py:398 vm/operations.py:729 +#: vm/operations.py:287 +#, python-format +msgid "deploy vm to %(node)s" +msgstr "vm létrehozása: %(node)s" + +#: vm/operations.py:296 vm/operations.py:408 vm/operations.py:731 msgid "deploy network" msgstr "hálózati kapcsolat létrehozása" -#: vm/operations.py:285 +#: vm/operations.py:302 msgid "boot virtual machine" msgstr "virtuális gép indítása" -#: vm/operations.py:300 +#: vm/operations.py:317 msgid "destroy" msgstr "megsemmisítés" -#: vm/operations.py:301 +#: vm/operations.py:318 msgid "Permanently destroy virtual machine, its network settings and disks." msgstr "" "Virtuális gép és lemezeinek, hálózati beállításainak végleges eltávolítása." -#: vm/operations.py:312 +#: vm/operations.py:327 msgid "destroy network" msgstr "hálózat megsemmisítése" -#: vm/operations.py:321 +#: vm/operations.py:336 msgid "destroy virtual machine" msgstr "virtuális gép megsemmisítése" -#: vm/operations.py:327 +#: vm/operations.py:342 msgid "destroy disks" msgstr "lemez megsemmisítése" -#: vm/operations.py:350 +#: vm/operations.py:365 msgid "migrate" msgstr "migrálás" -#: vm/operations.py:351 +#: vm/operations.py:366 msgid "" "Move virtual machine to an other worker node with a few seconds of " "interruption (live migration)." @@ -4126,38 +4268,38 @@ msgstr "" "A virtuális gép áthelyezése egy másik számítási csomópontra néhány másodperc " "kimaradással (live migration)." -#: vm/operations.py:359 +#: vm/operations.py:375 msgid "redeploy network (rollback)" msgstr "hálózati kapcsolat újraépítése (visszagörgetés)" -#: vm/operations.py:372 +#: vm/operations.py:382 msgid "schedule" msgstr "ütemezés" -#: vm/operations.py:379 +#: vm/operations.py:389 #, python-format msgid "migrate to %(node)s" msgstr "migrálás %(node)s csomópontra" -#: vm/operations.py:389 vm/operations.py:680 +#: vm/operations.py:399 vm/operations.py:684 msgid "shutdown network" msgstr "hálózati kapcsolat leállítása" -#: vm/operations.py:408 +#: vm/operations.py:418 msgid "reboot" msgstr "újraindítás" -#: vm/operations.py:409 +#: vm/operations.py:419 msgid "" "Warm reboot virtual machine by sending Ctrl+Alt+Del signal to its console." msgstr "" "Virtuális gép újraindítása a konzoljára a Ctrl+Alt+Del kombináció küldésével." -#: vm/operations.py:424 +#: vm/operations.py:434 msgid "remove interface" msgstr "interfész törlése" -#: vm/operations.py:425 +#: vm/operations.py:435 msgid "" "Remove the specified network interface and erase IP address allocations, " "related firewall rules and hostnames." @@ -4165,50 +4307,50 @@ msgstr "" "A kiválasztott hálózati interfész eltávolítása, a foglalt IP címek, " "tűzfalszabályok és gépnevek törlése." -#: vm/operations.py:435 +#: vm/operations.py:445 msgid "detach network" msgstr "hálózat lecsatolása" -#: vm/operations.py:444 +#: vm/operations.py:454 #, python-format msgid "remove %(vlan)s interface" msgstr "%(vlan)s interfész törlése" -#: vm/operations.py:454 +#: vm/operations.py:464 msgid "remove disk" msgstr "lemez eltávolítása" -#: vm/operations.py:455 +#: vm/operations.py:465 msgid "" "Remove the specified disk from the virtual machine, and destroy the data." msgstr "A megadott lemez eltávolítása a virtuális gépből és az adat törlése." -#: vm/operations.py:464 +#: vm/operations.py:474 msgid "detach disk" msgstr "lemez leválasztása" -#: vm/operations.py:469 +#: vm/operations.py:479 msgid "destroy disk" msgstr "lemez megsemmisítése" -#: vm/operations.py:474 +#: vm/operations.py:484 #, python-format msgid "remove disk %(name)s" msgstr "%(name)s lemez eltávolítása" -#: vm/operations.py:483 +#: vm/operations.py:493 msgid "reset" -msgstr "újraindítás" +msgstr "reset" -#: vm/operations.py:484 +#: vm/operations.py:494 msgid "Cold reboot virtual machine (power cycle)." msgstr "Virtuális gép hideg újraindítása (hálózati tápellátás megszakítása)." -#: vm/operations.py:497 +#: vm/operations.py:507 msgid "save as template" msgstr "mentés sablonként" -#: vm/operations.py:498 +#: vm/operations.py:508 msgid "" "Save virtual machine as a template so they can be shared with users and " "groups. Anyone who has access to a template (and to the networks it uses) " @@ -4218,30 +4360,30 @@ msgstr "" "felhasználókkal és csoportokkal. Mindenki, aki hozzáférést kap egy sablonhoz " "(és az általa használt hálózatokhoz), képes lesz egy példányát elindítani." -#: vm/operations.py:567 +#: vm/operations.py:577 #, python-format msgid "saving disk %(name)s" msgstr "%(name)s lemez mentése" -#: vm/operations.py:594 +#: vm/operations.py:604 msgid "shutdown" msgstr "leállítás" -#: vm/operations.py:595 +#: vm/operations.py:605 msgid "" "Try to halt virtual machine by a standard ACPI signal, allowing the " "operating system to keep a consistent state. The operation will fail if the " "machine does not turn itself off in a period." msgstr "" "Virtuális gép megállítása szabványos ACPI jelzéssel, lehetővé téve az " -"operációs rendszer számár a szabályos leállást. A művelet meghiúsul, ha a gép " -"nem áll le." +"operációs rendszer számár a szabályos leállást. A művelet meghiúsul, ha a " +"gép nem áll le." -#: vm/operations.py:618 +#: vm/operations.py:626 msgid "shut off" msgstr "kikapcsolás" -#: vm/operations.py:619 +#: vm/operations.py:627 msgid "" "Forcibly halt a virtual machine without notifying the operating system. This " "operation will even work in cases when shutdown does not, but the operating " @@ -4254,11 +4396,11 @@ msgstr "" "rendszer és a fájlrendszer sérülhet, adatvesztés történhet. A művelet hatása " "hasonló, mint egy fizikai gép tápellátásának megszüntetése." -#: vm/operations.py:652 +#: vm/operations.py:658 msgid "sleep" msgstr "altatás" -#: vm/operations.py:653 +#: vm/operations.py:659 msgid "" "Suspend virtual machine. This means the machine is stopped and its memory is " "saved to disk, so if the machine is waked up, all the applications will keep " @@ -4267,22 +4409,22 @@ msgid "" "when resumed. In the meantime, the machine will only use storage resources, " "and keep network resources allocated." msgstr "" -"Virtuális gép felfüggesztése. A virtuális gép megállításra, memóriája lemezre " -"mentésre kerül. Így a gép ébresztése után minden futó alkalmazás folytatódik. " -"A legtöbb alkalmazás elviseli akár a hosszabb idejű felfüggesztést, azonban a " -"folyamatos hálózati kapcsolatot igénylő programok megállhatnak visszaállítás " -"után. A felfüggesztés ideje alatt a virtuális gép csak tárterületet és " -"hálózati erőforrásokat foglal." - -#: vm/operations.py:686 +"Virtuális gép felfüggesztése. A virtuális gép megállításra, memóriája " +"lemezre mentésre kerül. Így a gép ébresztése után minden futó alkalmazás " +"folytatódik. A legtöbb alkalmazás elviseli akár a hosszabb idejű " +"felfüggesztést, azonban a folyamatos hálózati kapcsolatot igénylő programok " +"megállhatnak visszaállítás után. A felfüggesztés ideje alatt a virtuális gép " +"csak tárterületet és hálózati erőforrásokat foglal." + +#: vm/operations.py:690 msgid "suspend virtual machine" msgstr "virtuális gép felfüggesztése" -#: vm/operations.py:699 +#: vm/operations.py:703 msgid "wake up" msgstr "virtuális gép ébresztése" -#: vm/operations.py:700 +#: vm/operations.py:704 msgid "" "Wake up sleeping (suspended) virtual machine. This will load the saved " "memory of the system and start the virtual machine from this state." @@ -4290,15 +4432,15 @@ msgstr "" "Alvó (felfüggesztett) gép ébresztése: az elmentett memóriatartalom " "visszatöltése és a virtuális gép indítása ebből a mentett állapotból." -#: vm/operations.py:723 +#: vm/operations.py:725 msgid "resume virtual machine" msgstr "virtuális gép ébresztése" -#: vm/operations.py:744 +#: vm/operations.py:746 msgid "renew" msgstr "megújítás" -#: vm/operations.py:745 +#: vm/operations.py:747 msgid "" "Virtual machines are suspended and destroyed after they expire. This " "operation renews expiration times according to the lease type. If the " @@ -4308,7 +4450,7 @@ msgstr "" "a művelet megújítja a bérletet a kiválasztott típusnak megfelelően. Ha egy " "gép közeledik a lejárathoz, a tulajdonost értesítjük." -#: vm/operations.py:758 +#: vm/operations.py:760 msgid "" "Renewing the machine with the selected lease would result in its suspension " "time get earlier than before." @@ -4316,7 +4458,7 @@ msgstr "" "A gép megújítása a kiválasztott bérleti mód mellett a felfüggesztési időt " "korábbra állította volna, mint a jelenlegi érték." -#: vm/operations.py:763 +#: vm/operations.py:765 msgid "" "Renewing the machine with the selected lease would result in its delete time " "get earlier than before." @@ -4324,17 +4466,17 @@ msgstr "" "A gép megújítása a kiválasztott bérleti mód mellett a törlési időt korábbra " "állította volna, mint a jelenlegi érték." -#: vm/operations.py:769 +#: vm/operations.py:773 #, python-format msgid "Renewed to suspend at %(suspend)s and destroy at %(delete)s." msgstr "" "Megújítás után felfüggesztés ideje: %(suspend)s, a törlésé: %(delete)s." -#: vm/operations.py:779 +#: vm/operations.py:783 msgid "emergency state change" msgstr "vész-állapotváltás" -#: vm/operations.py:780 +#: vm/operations.py:784 msgid "" "Change the virtual machine state to NOSTATE. This should only be used if " "manual intervention was needed in the virtualization layer, and the machine " @@ -4345,28 +4487,28 @@ msgstr "" "rétegben, és úgy szeretné a gépet újból elindítani, hogy ne vesszenek el " "lemezei vagy hálózati erőforrásai." -#: vm/operations.py:826 +#: vm/operations.py:796 +msgid "Activity is forcibly interrupted." +msgstr "A tevékenység erőszakos megszakításra került." + +#: vm/operations.py:838 msgid "flush" msgstr "ürítés" -#: vm/operations.py:827 +#: vm/operations.py:839 msgid "Disable node and move all instances to other ones." msgstr "A csomópont tiltása és az összes példány másikakra mozgatása." -#: vm/operations.py:839 -msgid "Superuser privileges are required." -msgstr "Rendszergazdai jogosultság szükséges." - -#: vm/operations.py:848 +#: vm/operations.py:854 #, python-format msgid "migrate %(instance)s (%(pk)s)" msgstr "%(instance)s (%(pk)s) migrálása" -#: vm/operations.py:860 +#: vm/operations.py:866 msgid "screenshot" msgstr "képernyőkép" -#: vm/operations.py:861 +#: vm/operations.py:867 msgid "" "Get a screenshot about the virtual machine's console. A key will be pressed " "on the keyboard to stop screensaver." @@ -4374,11 +4516,11 @@ msgstr "" "Képernyőkép készítése a virtuális gép konzoljáról. Egy billentyűnyomást " "követően készül a kép a képernyővédő miatt." -#: vm/operations.py:878 +#: vm/operations.py:884 msgid "recover" msgstr "visszaállítás" -#: vm/operations.py:879 +#: vm/operations.py:885 msgid "" "Try to recover virtual machine disks from destroyed state. Network resources " "(allocations) are already lost, so you will have to manually add interfaces " @@ -4388,27 +4530,27 @@ msgstr "" "hálózati erőforrások foglalásai már végleg elvesztek, így az interfészeket " "kézzel kell a visszaállítás után pótolni." -#: vm/operations.py:910 +#: vm/operations.py:914 msgid "resources change" msgstr "erőforrások módosítása" -#: vm/operations.py:911 +#: vm/operations.py:915 msgid "Change resources of a stopped virtual machine." msgstr "Leállított virtuális gép erőforrásainak változtatása." -#: vm/operations.py:928 +#: vm/operations.py:932 #, python-format msgid "" "Priority: %(priority)s, Num cores: %(num_cores)s, Ram size: %(ram_size)s" msgstr "" -"Prioritás: %(priority)s, magok száma: %(num_cores)s, memória mérete: %" -"(ram_size)s" +"Prioritás: %(priority)s, magok száma: %(num_cores)s, memória mérete: " +"%(ram_size)s" -#: vm/operations.py:940 +#: vm/operations.py:963 msgid "password reset" msgstr "jelszó visszaállítása" -#: vm/operations.py:941 +#: vm/operations.py:964 msgid "" "Generate and set a new login password on the virtual machine. This operation " "requires the agent running. Resetting the password is not warranted to allow " @@ -4418,6 +4560,18 @@ msgstr "" "művelet megköveteli az ügynök futását. A jelszó átállítása nem garantálja a " "sikeres belépést, mivel más beállítások is megakadályozhatják ezt." +#: vm/operations.py:986 +msgid "mount store" +msgstr "tárhely csatolása" + +#: vm/operations.py:988 +msgid "" +"This operation attaches your personal file store. Other users who have " +"access to this machine can see these files as well." +msgstr "" +"Ez a művelet csatolja az ön személyes tárhelyét. A gép más felhasználói is " +"elérhetik fájljait." + #: vm/models/activity.py:47 #, python-format msgid "%(activity)s activity is currently in progress." @@ -4432,15 +4586,15 @@ msgstr "%(activity)s (%(pk)s) folyamatban van." msgid "Instance this activity works on." msgstr "A tevékenység tárgyát képező példány." -#: vm/models/activity.py:211 +#: vm/models/activity.py:218 msgid "Node this activity works on." msgstr "A tevékenység tárgyát képező csomópont." -#: vm/models/activity.py:212 +#: vm/models/activity.py:219 msgid "node" msgstr "csomópont" -#: vm/models/activity.py:270 +#: vm/models/activity.py:277 msgid "Manager is restarted, activity is cleaned up. You can try again now." msgstr "" "A menedzser újraindítása miatt a tevékenység lezárásra került. Próbálja újra." @@ -4469,7 +4623,7 @@ msgstr "Felső memóriaméret-korlát ballooning esetén." msgid "architecture" msgstr "architektúra" -#: vm/models/common.py:52 vm/models/node.py:65 +#: vm/models/common.py:52 vm/models/node.py:68 msgid "priority" msgstr "prioritás" @@ -4510,221 +4664,226 @@ msgstr "soha" msgid "%(name)s (suspend: %(s)s, remove: %(r)s)" msgstr "%(name)s (felfüggesztés: %(s)s, törlés: %(r)s)" -#: vm/models/instance.py:106 +#: vm/models/instance.py:107 msgid "access method" msgstr "elérés módja" -#: vm/models/instance.py:107 +#: vm/models/instance.py:108 msgid "Primary remote access method." msgstr "Elsődleges távoli elérési mód." -#: vm/models/instance.py:108 +#: vm/models/instance.py:109 msgid "boot menu" msgstr "rendszerbetöltő menüje" -#: vm/models/instance.py:110 +#: vm/models/instance.py:111 msgid "Show boot device selection menu on boot." msgstr "" "A rendszerbetöltés eszközének kiválasztását lehetővé tevő menü megjelenítése " "indításkor." -#: vm/models/instance.py:111 +#: vm/models/instance.py:112 msgid "Preferred expiration periods." msgstr "Javasolt bérlési mód." -#: vm/models/instance.py:113 +#: vm/models/instance.py:114 msgid "raw_data" msgstr "nyers adat" -#: vm/models/instance.py:114 +#: vm/models/instance.py:115 msgid "Additional libvirt domain parameters in XML format." msgstr "További libvirt domain-paraméterek XML formátumban." -#: vm/models/instance.py:116 +#: vm/models/instance.py:117 msgid "" "A set of traits required for a node to declare to be suitable for hosting " "the VM." msgstr "A VM indításához szükséges csomópontjellemzők halmaza." -#: vm/models/instance.py:119 +#: vm/models/instance.py:120 msgid "required traits" msgstr "elvárt jellemzők" -#: vm/models/instance.py:120 +#: vm/models/instance.py:121 msgid "operating system" msgstr "operációs rendszer" -#: vm/models/instance.py:121 +#: vm/models/instance.py:122 #, python-format msgid "Name of operating system in format like \"%s\"." msgstr "Az operációs rendszer neve. Például „%s”." -#: vm/models/instance.py:124 vm/models/node.py:75 +#: vm/models/instance.py:125 vm/models/node.py:78 msgid "tags" msgstr "címkék" -#: vm/models/instance.py:143 +#: vm/models/instance.py:144 msgid "parent template" msgstr "szülősablon" -#: vm/models/instance.py:145 +#: vm/models/instance.py:146 msgid "Template which this one is derived of." msgstr "Az a sablon, amelyből az aktuális származik." -#: vm/models/instance.py:148 +#: vm/models/instance.py:149 msgid "Disks which are to be mounted." msgstr "A csatolandó lemezek." -#: vm/models/instance.py:156 +#: vm/models/instance.py:157 msgid "Can create an instance template." msgstr "Létrehozhat példánysablont." -#: vm/models/instance.py:158 +#: vm/models/instance.py:159 msgid "Can create an instance template (base)." msgstr "Létrehozhat példánysablont (alapokból)." -#: vm/models/instance.py:160 +#: vm/models/instance.py:161 msgid "Can change resources of a template." msgstr "Változtathatja egy sablon erőforrásait." -#: vm/models/instance.py:162 vm/models/instance.py:232 vm/models/network.py:45 +#: vm/models/instance.py:163 vm/models/instance.py:236 vm/models/network.py:45 msgid "template" msgstr "sablon" -#: vm/models/instance.py:163 +#: vm/models/instance.py:164 msgid "templates" msgstr "sablonok" -#: vm/models/instance.py:218 +#: vm/models/instance.py:222 msgid "no state" msgstr "nincs állapot" -#: vm/models/instance.py:219 +#: vm/models/instance.py:223 msgid "running" msgstr "fut" -#: vm/models/instance.py:220 +#: vm/models/instance.py:224 msgid "stopped" msgstr "leállítva" -#: vm/models/instance.py:221 +#: vm/models/instance.py:225 msgid "suspended" msgstr "felfüggesztve" -#: vm/models/instance.py:222 +#: vm/models/instance.py:226 msgid "error" msgstr "hiba" -#: vm/models/instance.py:223 +#: vm/models/instance.py:227 msgid "pending" msgstr "függő" -#: vm/models/instance.py:224 +#: vm/models/instance.py:228 msgid "destroyed" msgstr "megsemmisítve" -#: vm/models/instance.py:227 +#: vm/models/instance.py:231 msgid "Human readable name of instance." msgstr "A példány olvasható neve." -#: vm/models/instance.py:231 +#: vm/models/instance.py:235 msgid "Template the instance derives from." msgstr "Az a sablon, amelyből a példány származik." -#: vm/models/instance.py:233 +#: vm/models/instance.py:237 msgid "Original password of the instance." msgstr "A példány eredeti jelszava." -#: vm/models/instance.py:234 +#: vm/models/instance.py:238 msgid "password" msgstr "jelszó" -#: vm/models/instance.py:236 +#: vm/models/instance.py:240 msgid "time of suspend" msgstr "felfüggesztés ideje" -#: vm/models/instance.py:237 +#: vm/models/instance.py:241 msgid "Proposed time of automatic suspension." msgstr "A felfüggesztés kijelölt ideje." -#: vm/models/instance.py:240 +#: vm/models/instance.py:244 msgid "time of delete" msgstr "törlés ideje" -#: vm/models/instance.py:241 +#: vm/models/instance.py:245 msgid "Proposed time of automatic deletion." msgstr "Automatikus törlés kijelölt ideje." -#: vm/models/instance.py:244 +#: vm/models/instance.py:248 msgid "Time stamp of successful boot report." msgstr "A gép sikeres indításjelzésének ideje." -#: vm/models/instance.py:246 +#: vm/models/instance.py:250 msgid "active since" msgstr "aktív ezóta" -#: vm/models/instance.py:249 +#: vm/models/instance.py:253 msgid "Current hypervisor of this instance." msgstr "A példány jelenlegi hypervisorja." -#: vm/models/instance.py:250 +#: vm/models/instance.py:254 msgid "host node" msgstr "csomópont" -#: vm/models/instance.py:252 +#: vm/models/instance.py:256 msgid "Set of mounted disks." msgstr "1Csatolt lemezek halmaza." -#: vm/models/instance.py:255 +#: vm/models/instance.py:259 msgid "TCP port where VNC console listens." msgstr "Az a TCP port, amelyen a VNC konzol hallgat." -#: vm/models/instance.py:256 +#: vm/models/instance.py:260 msgid "vnc_port" msgstr "VNC port" -#: vm/models/instance.py:260 +#: vm/models/instance.py:264 msgid "The virtual machine's time of destruction." msgstr "A virtuális gép megsemmisítésének ideje." -#: vm/models/instance.py:270 +#: vm/models/instance.py:274 msgid "Can access the graphical console of a VM." msgstr "Elérheti a VM grafikus konzolját." -#: vm/models/instance.py:271 +#: vm/models/instance.py:275 msgid "Can change resources of a running VM." msgstr "Megváltoztathatja a VM erőforrásait." -#: vm/models/instance.py:272 +#: vm/models/instance.py:276 msgid "Can change resources of a new VM." msgstr "Megválaszthatja egy új VM erőforrásait." -#: vm/models/instance.py:273 +#: vm/models/instance.py:277 msgid "Can create a new VM." msgstr "Létrehozhat új VM-et." -#: vm/models/instance.py:274 +#: vm/models/instance.py:278 msgid "Can configure port forwards." msgstr "Beállíthat porttovábbításokat." -#: vm/models/instance.py:275 +#: vm/models/instance.py:279 msgid "Can recover a destroyed VM." msgstr "Visszaállíthat egy megsemmisített VM-et." -#: vm/models/instance.py:276 +#: vm/models/instance.py:280 msgid "Can change VM state to NOSTATE." msgstr "Átállíthatja a VM állapotát NOSTATE-re." -#: vm/models/instance.py:279 +#: vm/models/instance.py:283 msgid "instances" msgstr "példányok" -#: vm/models/instance.py:291 +#: vm/models/instance.py:295 #, python-format msgid "Instance %(instance)s has already been destroyed." msgstr "%(instance)s példány már meg van semmisítve." -#: vm/models/instance.py:295 +#: vm/models/instance.py:299 +#, python-format +msgid "No agent software is running on instance %(instance)s." +msgstr "Nem fut ügynökszoftver a következőn: %(instance)s." + +#: vm/models/instance.py:303 #, python-format msgid "" "Current state (%(state)s) of instance %(instance)s is inappropriate for the " @@ -4733,16 +4892,16 @@ msgstr "" "A(z) %(instance)s példány aktuális állapota (%(state)s) nem megfelelő a " "választott művelethez." -#: vm/models/instance.py:369 +#: vm/models/instance.py:377 msgid "create instance" msgstr "példány létrehozása" -#: vm/models/instance.py:447 +#: vm/models/instance.py:455 #, python-format msgid "vm state changed to %(state)s" msgstr "VM állapota erre változott: %(state)s" -#: vm/models/instance.py:650 +#: vm/models/instance.py:659 #, python-format msgid "" "Your instance <a href=\"%(url)s\">%(instance)s</a> is going to expire. It " @@ -4754,7 +4913,7 @@ msgstr "" "kerül. Kérjük, <a href=\"%(token)s\">újítsa meg</a> vagy <a href=\"%(url)s" "\">törölje</a> most." -#: vm/models/instance.py:662 +#: vm/models/instance.py:671 #, python-format msgid "" "%(failed)s notifications failed and %(success) succeeded. Failed ones are: " @@ -4763,7 +4922,7 @@ msgstr "" "%(failed)s értesítés sikertelen és %(success) sikeres. A sikertelenek: " "%(faileds)s." -#: vm/models/instance.py:664 +#: vm/models/instance.py:673 #, python-format msgid "" "%(failed)s notifications failed and %(success) succeeded. Failed ones are: " @@ -4772,16 +4931,16 @@ msgstr "" "%(failed)s értesítés sikertelen és %(success) sikeres. A sikertelenek: " "%(faileds_ex)s." -#: vm/models/instance.py:672 +#: vm/models/instance.py:681 #, python-format msgid "%(success)s notifications succeeded." msgstr "%(success)s sikeres értesítés." -#: vm/models/instance.py:677 +#: vm/models/instance.py:686 msgid "notify owner about expiration" msgstr "tulaj értesítése a lejáratról" -#: vm/models/instance.py:685 +#: vm/models/instance.py:694 #, python-format msgid "%(instance)s expiring soon" msgstr "%(instance)s hamarosan lejár" @@ -4823,59 +4982,59 @@ msgstr "" "Az interfész létrehozásra került.Az új címek: %(ip4)s (ipv4), %(ip6)s " "(ipv6). Vlan: %(vlan)s." -#: vm/models/node.py:63 +#: vm/models/node.py:66 msgid "Human readable name of node." msgstr "A csomópont olvasható neve." -#: vm/models/node.py:66 +#: vm/models/node.py:69 msgid "Node usage priority." msgstr "Csomóponthasználat prioritása." -#: vm/models/node.py:68 +#: vm/models/node.py:71 msgid "Host in firewall." msgstr "Tűzfalbeli gép." -#: vm/models/node.py:69 +#: vm/models/node.py:72 msgid "enabled" msgstr "engedélyezve" -#: vm/models/node.py:70 +#: vm/models/node.py:73 msgid "Indicates whether the node can be used for hosting." msgstr "A csomópont használható-e gépek fogadására." -#: vm/models/node.py:73 +#: vm/models/node.py:76 msgid "Declared traits." msgstr "Biztosított jellemzők." -#: vm/models/node.py:74 +#: vm/models/node.py:77 msgid "traits" msgstr "jellemzők" -#: vm/models/node.py:76 +#: vm/models/node.py:79 msgid "overcommit ratio" msgstr "túlfoglalási arány" -#: vm/models/node.py:77 +#: vm/models/node.py:80 msgid "The ratio of total memory with to without overcommit." msgstr "Az összes memória és a túlfoglalható memória aránya." -#: vm/models/node.py:125 +#: vm/models/node.py:128 msgid "offline" msgstr "nem elérhető" -#: vm/models/node.py:126 +#: vm/models/node.py:129 msgid "disabled" msgstr "tiltva" -#: vm/models/node.py:127 +#: vm/models/node.py:130 msgid "missing" msgstr "eltűnt" -#: vm/models/node.py:128 +#: vm/models/node.py:131 msgid "online" msgstr "elérhető" -#: vm/models/node.py:145 vm/models/node.py:149 +#: vm/models/node.py:148 vm/models/node.py:152 msgid "disable node" msgstr "csomópont tiltása" @@ -4907,19 +5066,24 @@ msgstr "ügynök" msgid "starting" msgstr "indítás" -#: vm/tasks/local_agent_tasks.py:92 -#, python-format -msgid "update to %(version)s" -msgstr "frissítés erre: %(version)s" - -#: vm/tasks/local_agent_tasks.py:108 +#: vm/tasks/local_agent_tasks.py:101 msgid "start access server" msgstr "távoli elérés indítása" -#: vm/tasks/local_agent_tasks.py:140 +#: vm/tasks/local_agent_tasks.py:133 msgid "stopping" msgstr "leállítás" +#: vm/tasks/local_agent_tasks.py:142 +#, python-format +msgid "update to %(version)s" +msgstr "frissítés erre: %(version)s" + +#: vm/tasks/local_agent_tasks.py:149 +#, python-format +msgid "update agent to %(version)s" +msgstr "ügynökfrissítés erre: %(version)s" + #: vm/tasks/local_periodic_tasks.py:51 #, python-format msgid "%(instance)s destroyed" @@ -4952,6 +5116,23 @@ msgstr "" msgid "x" msgstr "x" +#~ msgid "Mass delete complete, the following VM was deleted: %s." +#~ msgid_plural "Mass delete complete, the following VMs were deleted: %s." +#~ msgstr[0] "Sikeres tömeges törlés. A következő VM törlésre került: %s." +#~ msgstr[1] "Sikeres tömeges törlés. A következő VM-ek törlésre kerültek: %s." + +#~ msgid "Migrate" +#~ msgstr "Migrálás" + +#~ msgid "Reboot" +#~ msgstr "Újraindítás" + +#~ msgid "Shutdown" +#~ msgstr "Leállítás" + +#~ msgid "Destroy" +#~ msgstr "Megsemmisítés" + #~ msgid "Create empty disk for the VM." #~ msgstr "Üres lemez létrehozása a VM-hez." @@ -5056,9 +5237,6 @@ msgstr "x" #~ msgid "This token is invalid." #~ msgstr "A token érvénytelen." -#~ msgid "Virtual machine is successfully renewed." -#~ msgstr "A virtuális gép megújításra került." - #~ msgid "Disk successfully added!" #~ msgstr "A lemez hozzáadásra került." diff --git a/circle/locale/hu/LC_MESSAGES/djangojs.po b/circle/locale/hu/LC_MESSAGES/djangojs.po index 07a41ee..faf735b 100644 --- a/circle/locale/hu/LC_MESSAGES/djangojs.po +++ b/circle/locale/hu/LC_MESSAGES/djangojs.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-08-01 19:36+0200\n" +"POT-Creation-Date: 2014-08-29 09:21+0200\n" "PO-Revision-Date: 2014-08-01 21:03+0200\n" "Last-Translator: Mate Ory <ory.mate@ik.bme.hu>\n" "Language-Team: Hungarian <cloud@ik.bme.hu>\n" @@ -23,11 +23,11 @@ msgid "Select an option to proceed!" msgstr "Válasszon a folytatáshoz." #: dashboard/static/dashboard/dashboard.js:258 -#: dashboard/static/dashboard/dashboard.js:305 -#: dashboard/static/dashboard/dashboard.js:315 -#: static_collected/dashboard/dashboard.js:257 -#: static_collected/dashboard/dashboard.js:304 -#: static_collected/dashboard/dashboard.js:314 +#: dashboard/static/dashboard/dashboard.js:306 +#: dashboard/static/dashboard/dashboard.js:316 +#: static_collected/dashboard/dashboard.js:258 +#: static_collected/dashboard/dashboard.js:306 +#: static_collected/dashboard/dashboard.js:316 msgid "No result" msgstr "Nincs eredmény" @@ -41,12 +41,15 @@ msgstr "Nincs jogosultsága a profil módosításához." msgid "Unknown error." msgstr "Ismeretlen hiba." -#: dashboard/static/dashboard/vm-create.js:108 -#: dashboard/static/dashboard/vm-create.js:171 +#: dashboard/static/dashboard/vm-create.js:111 +#: dashboard/static/dashboard/vm-create.js:174 +#: static_collected/dashboard/vm-create.js:111 +#: static_collected/dashboard/vm-create.js:174 msgid "No more networks." msgstr "Nincs több hálózat." -#: dashboard/static/dashboard/vm-create.js:140 +#: dashboard/static/dashboard/vm-create.js:143 +#: static_collected/dashboard/vm-create.js:143 msgid "Not added to any network" msgstr "Nincs hálózathoz adva" @@ -428,5 +431,3 @@ msgstr "Tegnap" #: static_collected/admin/js/admin/DateTimeShortcuts.js:203 msgid "Tomorrow" msgstr "Holnap" - -# end diff --git a/circle/vm/models/activity.py b/circle/vm/models/activity.py index a19c233..e10a001 100644 --- a/circle/vm/models/activity.py +++ b/circle/vm/models/activity.py @@ -90,7 +90,8 @@ class InstanceActivity(ActivityModel): @classmethod def create(cls, code_suffix, instance, task_uuid=None, user=None, - concurrency_check=True, readable_name=None): + concurrency_check=True, readable_name=None, + resultant_state=None): readable_name = _normalize_readable_name(readable_name, code_suffix) # Check for concurrent activities @@ -100,14 +101,14 @@ class InstanceActivity(ActivityModel): activity_code = join_activity_code(cls.ACTIVITY_CODE_BASE, code_suffix) act = cls(activity_code=activity_code, instance=instance, parent=None, - resultant_state=None, started=timezone.now(), + resultant_state=resultant_state, started=timezone.now(), readable_name_data=readable_name.to_dict(), task_uuid=task_uuid, user=user) act.save() return act def create_sub(self, code_suffix, task_uuid=None, concurrency_check=True, - readable_name=None): + readable_name=None, resultant_state=None): readable_name = _normalize_readable_name(readable_name, code_suffix) # Check for concurrent activities @@ -117,7 +118,8 @@ class InstanceActivity(ActivityModel): act = InstanceActivity( activity_code=join_activity_code(self.activity_code, code_suffix), - instance=self.instance, parent=self, resultant_state=None, + instance=self.instance, parent=self, + resultant_state=resultant_state, readable_name_data=readable_name.to_dict(), started=timezone.now(), task_uuid=task_uuid, user=self.user) act.save() @@ -198,14 +200,15 @@ class InstanceActivity(ActivityModel): @contextmanager def instance_activity(code_suffix, instance, on_abort=None, on_commit=None, task_uuid=None, user=None, concurrency_check=True, - readable_name=None): + readable_name=None, resultant_state=None): """Create a transactional context for an instance activity. """ if not readable_name: warn("Set readable_name", stacklevel=3) act = InstanceActivity.create(code_suffix, instance, task_uuid, user, concurrency_check, - readable_name=readable_name) + readable_name=readable_name, + resultant_state=resultant_state) return activitycontextimpl(act, on_abort=on_abort, on_commit=on_commit) diff --git a/circle/vm/models/instance.py b/circle/vm/models/instance.py index 14d65f2..9c52033 100644 --- a/circle/vm/models/instance.py +++ b/circle/vm/models/instance.py @@ -952,7 +952,8 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin, 'ERROR': 'fa-warning', 'PENDING': 'fa-rocket', 'DESTROYED': 'fa-trash-o', - 'MIGRATING': 'fa-truck'}.get(self.status, 'fa-question') + 'MIGRATING': 'fa-truck migrating-icon' + }.get(self.status, 'fa-question') def get_activities(self, user=None): acts = (self.activity_log.filter(parent=None). @@ -1002,3 +1003,8 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin, instance=self, succeeded=None, parent=None).latest("started") except InstanceActivity.DoesNotExist: return None + + def is_in_status_change(self): + latest = self.get_latest_activity_in_progress() + return (latest and latest.resultant_state is not None + and self.status != latest.resultant_state) diff --git a/circle/vm/models/node.py b/circle/vm/models/node.py index 1aa6edb..ca28fc2 100644 --- a/circle/vm/models/node.py +++ b/circle/vm/models/node.py @@ -260,7 +260,7 @@ class Node(OperatedMixin, TimeStampedModel): @method_cache(10) def monitor_info(self): metrics = ('cpu.usage', 'memory.usage') - prefix = 'circle.%s.' % self.name + prefix = 'circle.%s.' % self.host.hostname params = [('target', '%s%s' % (prefix, metric)) for metric in metrics] params.append(('from', '-5min')) diff --git a/circle/vm/operations.py b/circle/vm/operations.py index beddc28..8155707 100644 --- a/circle/vm/operations.py +++ b/circle/vm/operations.py @@ -55,6 +55,7 @@ class InstanceOperation(Operation): concurrency_check = True accept_states = None deny_states = None + resultant_state = None def __init__(self, instance): super(InstanceOperation, self).__init__(subject=instance) @@ -99,12 +100,14 @@ class InstanceOperation(Operation): "provided as parameter.") return parent.create_sub(code_suffix=self.activity_code_suffix, - readable_name=name) + readable_name=name, + resultant_state=self.resultant_state) else: return InstanceActivity.create( code_suffix=self.activity_code_suffix, instance=self.instance, readable_name=name, user=user, - concurrency_check=self.concurrency_check) + concurrency_check=self.concurrency_check, + resultant_state=self.resultant_state) def is_preferred(self): """If this is the recommended op in the current state of the instance. @@ -250,6 +253,7 @@ class DeployOperation(InstanceOperation): "and network configuration).") required_perms = () deny_states = ('SUSPENDED', 'RUNNING') + resultant_state = 'RUNNING' def is_preferred(self): return self.instance.status in (self.instance.STATUS.STOPPED, @@ -314,9 +318,7 @@ class DestroyOperation(InstanceOperation): description = _("Permanently destroy virtual machine, its network " "settings and disks.") required_perms = () - - def on_commit(self, activity): - activity.resultant_state = 'DESTROYED' + resultant_state = 'DESTROYED' def _operation(self, activity): # Destroy networks @@ -364,6 +366,7 @@ class MigrateOperation(InstanceOperation): description = _("Move virtual machine to an other worker node with a few " "seconds of interruption (live migration).") required_perms = () + superuser_required = True accept_states = ('RUNNING', ) def rollback(self, activity): @@ -372,12 +375,6 @@ class MigrateOperation(InstanceOperation): "redeploy network (rollback)")): self.instance.deploy_net() - def check_auth(self, user): - if not user.is_superuser: - raise PermissionDenied() - - super(MigrateOperation, self).check_auth(user=user) - def _operation(self, activity, to_node=None, timeout=120): if not to_node: with activity.sub_activity('scheduling', @@ -612,9 +609,7 @@ class ShutdownOperation(InstanceOperation): abortable = True required_perms = () accept_states = ('RUNNING', ) - - def on_commit(self, activity): - activity.resultant_state = 'STOPPED' + resultant_state = 'STOPPED' def _operation(self, task=None): self.instance.shutdown_vm(task=task) @@ -638,9 +633,7 @@ class ShutOffOperation(InstanceOperation): "of a physical machine.") required_perms = () accept_states = ('RUNNING', ) - - def on_commit(self, activity): - activity.resultant_state = 'STOPPED' + resultant_state = 'STOPPED' def _operation(self, activity): # Shutdown networks @@ -673,6 +666,7 @@ class SleepOperation(InstanceOperation): "storage resources, and keep network resources allocated.") required_perms = () accept_states = ('RUNNING', ) + resultant_state = 'SUSPENDED' def is_preferred(self): return (not self.instance.is_base and @@ -684,9 +678,6 @@ class SleepOperation(InstanceOperation): else: activity.resultant_state = 'ERROR' - def on_commit(self, activity): - activity.resultant_state = 'SUSPENDED' - def _operation(self, activity, timeout=240): # Destroy networks with activity.sub_activity('shutdown_net', readable_name=ugettext_noop( @@ -715,6 +706,7 @@ class WakeUpOperation(InstanceOperation): "virtual machine from this state.") required_perms = () accept_states = ('SUSPENDED', ) + resultant_state = 'RUNNING' def is_preferred(self): return self.instance.status == self.instance.STATUS.SUSPENDED @@ -722,9 +714,6 @@ class WakeUpOperation(InstanceOperation): def on_abort(self, activity, error): activity.resultant_state = 'ERROR' - def on_commit(self, activity): - activity.resultant_state = 'RUNNING' - def _operation(self, activity, timeout=60): # Schedule vm self.instance.allocate_vnc_port() @@ -849,6 +838,7 @@ class FlushOperation(NodeOperation): name = _("flush") description = _("Disable node and move all instances to other ones.") required_perms = () + superuser_required = True def on_abort(self, activity, error): from manager.scheduler import TraitsUnsatisfiableException @@ -856,13 +846,6 @@ class FlushOperation(NodeOperation): if self.node_enabled: self.node.enable(activity.user, activity) - def check_auth(self, user): - if not user.is_superuser: - raise humanize_exception(ugettext_noop( - "Superuser privileges are required."), PermissionDenied()) - - super(FlushOperation, self).check_auth(user=user) - def _operation(self, activity, user): self.node_enabled = self.node.enabled self.node.disable(user, activity) @@ -905,6 +888,7 @@ class RecoverOperation(InstanceOperation): acl_level = "owner" required_perms = ('vm.recover', ) accept_states = ('DESTROYED', ) + resultant_state = 'PENDING' def check_precond(self): try: @@ -912,9 +896,6 @@ class RecoverOperation(InstanceOperation): except Instance.InstanceDestroyedError: pass - def on_commit(self, activity): - activity.resultant_state = 'PENDING' - def _operation(self): for disk in self.instance.disks.all(): disk.destroyed = None