Commit ac5f3142 by Őry Máté

Merge branch 'connect-via-client' into 'master'

Connect via Client support

fixes #222
parents dd87b7e7 19408a06
......@@ -465,3 +465,6 @@ SESSION_COOKIE_NAME = "csessid%x" % (((getnode() // 139) ^
(getnode() % 983)) & 0xffff)
MAX_NODE_RAM = get_env_variable("MAX_NODE_RAM", 1024)
# Url to download the client: (e.g. http://circlecloud.org/client/download/)
CLIENT_DOWNLOAD_URL = get_env_variable('CLIENT_DOWNLOAD_URL', 'http://circlecloud.org/client/download/')
......@@ -383,6 +383,19 @@ $(function () {
$('.notification-messages').load("/dashboard/notifications/");
$('#notification-button a span[class*="badge-pulse"]').remove();
});
/* on the client confirmation button fire the clientInstalledAction */
$(document).on("click", "#client-check-button", function(event) {
var connectUri = $('#connect-uri').val();
clientInstalledAction(connectUri);
return false;
});
$("#dashboard-vm-details-connect-button").click(function(event) {
var connectUri = $(this).attr("href");
clientInstalledAction(connectUri);
return false;
});
});
function generateVmHTML(pk, name, host, icon, _status, fav, is_last) {
......@@ -589,6 +602,12 @@ function addModalConfirmation(func, data) {
});
}
function clientInstalledAction(location) {
setCookie('downloaded_client', true, 365 * 24 * 60 * 60, "/");
window.location.href = location;
$('#confirmation-modal').modal("hide");
}
// for AJAX calls
/**
* Getter for user cookies
......@@ -611,6 +630,14 @@ function getCookie(name) {
return cookieValue;
}
function setCookie(name, value, seconds, path) {
if (seconds!=null) {
var today = new Date();
var expire = new Date();
expire.setTime(today.getTime() + seconds);
}
document.cookie = name+"="+escape(value)+"; expires="+expire.toUTCString()+"; path="+path;
}
/* no js compatibility */
function noJS() {
......
......@@ -378,8 +378,14 @@ function checkNewActivity(runs) {
}
$("#vm-details-state span").html(data['human_readable_status'].toUpperCase());
if(data['status'] == "RUNNING") {
if(data['connect_uri']) {
$("#dashboard-vm-details-connect-button").removeClass('disabled');
}
$("[data-target=#_console]").attr("data-toggle", "pill").attr("href", "#console").parent("li").removeClass("disabled");
} else {
if(data['connect_uri']) {
$("#dashboard-vm-details-connect-button").addClass('disabled');
}
$("[data-target=#_console]").attr("data-toggle", "_pill").attr("href", "#").parent("li").addClass("disabled");
}
......
{% load i18n %}
<p>
{% blocktrans %}
To effortlessly connect to all kind of virtual machines you have to install the <strong>CIRCLE Client</strong>.
{% endblocktrans %}
</p>
<p class="text-info">
{% blocktrans %}
To install the <strong>CIRCLE Client</strong> click on the <strong>Download the Client</strong> button.
The button takes you to the installation detail page, where you can choose your operating system and start
the download or read more detailed information about the <strong>Client</strong>. The program can be installed on Windows XP (and above)
or Debian based Linux operating systems. To successfully install the client you have to have admin (root or elevated) rights.
After the installation complete clicking on the <strong>I have the Client installed</strong> button will launch the appropriate tool
designed for that connection with necessarily predefined configurations. This option will also save your answer and this prompt about
installation will not pop up again.
{% endblocktrans %}
</p>
<br>
<div class="pull-right">
<form method="POST" id="dashboard-client-check" action="">
{% csrf_token %}
<a class="btn btn-default" href="{% url "dashboard.views.detail" pk=instance.pk %}" data-dismiss="modal">{% trans "Cancel" %}</a>
<a class="btn btn-info" href="{{ client_download_url }}" traget="_blank">{% trans "Download the Client" %}</a>
<button data-dismiss="modal" id="client-check-button" type="submit" class="btn btn-success" title="{% trans "I downloaded and installed the client and I want to connect using it. This choice will be saved to your compuer" %}">
<i class="fa fa-external-link"></i> {% trans "I have the Client installed" %}
</button>
<input id="connect-uri" name="connect-uri" type="hidden" value="{% if instance.get_connect_uri %}{{ instance.get_connect_uri}}{% endif %}" />
<input name="vm" type="hidden" value="{% if instance.get_connect_uri %}{{ instance.pk}}{% endif %}" />
</form>
</div>
\ No newline at end of file
......@@ -133,8 +133,21 @@
<i class="fa fa-copy" title="{% trans "Select all" %}"></i>
</span>
</div>
{% endfor %}
{% if instance.get_connect_uri %}
<div id="dashboard-vm-details-connect" class="operation-wrapper">
{% if client_download %}
<a id="dashboard-vm-details-connect-button" class="btn btn-xs btn-default operation " href="{{ instance.get_connect_uri}}" title="{% trans "Connect via the CIRCLE Client" %}">
<i class="fa fa-external-link"></i> {% trans "Connect" %}
</a>
<a href="{% url "dashboard.views.client-check" %}?vm={{ instance.pk }}">{% trans "Download client" %}</a>
{% else %}
<a id="dashboard-vm-details-connect-download-button" class="btn btn-xs btn-default operation " href="{% url "dashboard.views.client-check" %}?vm={{ instance.pk }}" title="{% trans "Download the CIRCLE Client" %}">
<i class="fa fa-external-link"></i> {% trans "Connect (download client)" %}
</a>
{% endif %}
</div>
{% endif %}
</div>
<div class="col-md-8" id="vm-detail-pane">
<div class="panel panel-default" id="vm-detail-panel">
......
......@@ -45,6 +45,7 @@ from .views import (
VmTraitsUpdate, VmRawDataUpdate,
GroupPermissionsView,
LeaseAclUpdateView,
ClientCheck,
)
autocomplete_light.autodiscover()
......@@ -204,4 +205,6 @@ urlpatterns = patterns(
name="dashboard.views.store-new-directory"),
url(r"^store/refresh_toplist$", store_refresh_toplist,
name="dashboard.views.store-refresh-toplist"),
url(r"^client/check$", ClientCheck.as_view(),
name="dashboard.views.client-check"),
)
......@@ -411,6 +411,9 @@ class VmDetailView(CheckedDetailView):
context['can_change_resources'] = self.request.user.has_perm(
"vm.change_resources")
# client info
context['client_download'] = self.request.COOKIES.get(
'downloaded_client')
# can link template
context['can_link_template'] = (
instance.template and instance.template.has_level(user, "operator")
......@@ -1531,6 +1534,37 @@ class GroupAclUpdateView(AclUpdateView):
return super(GroupAclUpdateView, self).get_object().profile
class ClientCheck(LoginRequiredMixin, TemplateView):
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/_modal.html']
else:
return ['dashboard/nojs-wrapper.html']
def get_context_data(self, *args, **kwargs):
context = super(ClientCheck, self).get_context_data(*args, **kwargs)
context.update({
'box_title': _('About CIRCLE Client'),
'ajax_title': False,
'client_download_url': settings.CLIENT_DOWNLOAD_URL,
'template': "dashboard/_client-check.html",
'instance': get_object_or_404(
Instance, pk=self.request.GET.get('vm')),
})
if not context['instance'].has_level(self.request.user, 'operator'):
raise PermissionDenied()
return context
def post(self, request, *args, **kwargs):
instance = get_object_or_404(Instance, pk=request.POST.get('vm'))
if not instance.has_level(request.user, 'operator'):
raise PermissionDenied()
response = HttpResponseRedirect(instance.get_absolute_url())
response.set_cookie('downloaded_client', 'True', 365 * 24 * 60 * 60)
return response
class TemplateChoose(LoginRequiredMixin, TemplateView):
def get_template_names(self):
......@@ -2675,6 +2709,7 @@ def vm_activity(request, pk):
if not show_all:
activities = activities[:10]
response['connect_uri'] = instance.get_connect_uri()
response['human_readable_status'] = instance.get_status_display()
response['status'] = instance.status
response['icon'] = instance.get_status_icon()
......
......@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-09-03 12:57+0200\n"
"POT-Creation-Date: 2014-09-03 18:49+0200\n"
"PO-Revision-Date: 2014-09-03 12:51+0200\n"
"Last-Translator: Mate Ory <ory.mate@ik.bme.hu>\n"
"Language-Team: Hungarian <cloud@ik.bme.hu>\n"
......
......@@ -607,9 +607,7 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
port = self.get_connect_port(use_ipv6=use_ipv6)
host = self.get_connect_host(use_ipv6=use_ipv6)
proto = self.access_method
if proto == 'ssh':
proto = 'sshterm'
return ('%(proto)s:cloud:%(pw)s:%(host)s:%(port)d' %
return ('circle:%(proto)s:cloud:%(pw)s:%(host)s:%(port)d' %
{'port': port, 'proto': proto, 'pw': self.pw,
'host': host})
except:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment