diff --git a/.gitignore b/.gitignore
index 7d921d2..b3ebced 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,6 @@ venv
 .DS_*
 *.pyc
 db.sqlite3
+console/cert.pem
+tags
+dhcpd.*
diff --git a/README.md b/README.md
index 1d140ff..f1b3767 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ WebVirtCloud is a virtualization web interface for admins and users. It can dele
 ### Install WebVirtCloud panel (Ubuntu)
 
 ```bash
-sudo apt-get -y install git python-virtualenv python-dev libxml2-dev libvirt-dev zlib1g-dev nginx supervisor libsasl2-modules
+sudo apt-get -y install git python-virtualenv python-dev libxml2-dev libvirt-dev zlib1g-dev nginx supervisor libsasl2-modules gcc pkg-config
 git clone https://github.com/retspen/webvirtcloud
 cd webvirtcloud
 sudo cp conf/supervisor/webvirtcloud.conf /etc/supervisor/conf.d
@@ -185,6 +185,12 @@ webvirtcloud                     RUNNING    pid 24185, uptime 2:59:14
 
 ```
 
+#### Apache mod_wsgi configuration
+```
+WSGIDaemonProcess webvirtcloud threads=2 maximum-requests=1000 display-name=webvirtcloud
+WSGIScriptAlias / /srv/webvirtcloud/webvirtcloud/wsgi.py
+```
+
 #### Install final required packages for libvirtd and others on Host Server
 ```bash
 wget -O - https://clck.ru/9V9fH | sudo sh
diff --git a/accounts/backends.py b/accounts/backends.py
new file mode 100644
index 0000000..77aa509
--- /dev/null
+++ b/accounts/backends.py
@@ -0,0 +1,7 @@
+from django.contrib.auth.backends import RemoteUserBackend
+
+class MyRemoteUserBackend(RemoteUserBackend):
+    def configure_user(self, user):
+        user.is_superuser = True
+        return user
+
diff --git a/accounts/forms.py b/accounts/forms.py
index 55d5c29..4127ac4 100644
--- a/accounts/forms.py
+++ b/accounts/forms.py
@@ -2,13 +2,14 @@ import re
 from django import forms
 from django.utils.translation import ugettext_lazy as _
 from django.contrib.auth.models import User
+from django.conf import settings
 
 
 class UserAddForm(forms.Form):
     name = forms.CharField(label="Name",
                            error_messages={'required': _('No User name has been entered')},
                            max_length=20)
-    password = forms.CharField(required=True, error_messages={'required': _('No password has been entered')},)
+    password = forms.CharField(required=not settings.ALLOW_EMPTY_PASSWORD, error_messages={'required': _('No password has been entered')},)
 
     def clean_name(self):
         name = self.cleaned_data['name']
diff --git a/accounts/migrations/0004_userattributes.py b/accounts/migrations/0004_userattributes.py
new file mode 100644
index 0000000..fb32539
--- /dev/null
+++ b/accounts/migrations/0004_userattributes.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+from django.conf import settings
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('accounts', '0003_usersshkey'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='UserAttributes',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('max_instances', models.IntegerField(default=0)),
+                ('max_cpus', models.IntegerField(default=0)),
+                ('max_memory', models.IntegerField(default=0)),
+                ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]
diff --git a/accounts/migrations/0005_userattributes_can_clone_instances.py b/accounts/migrations/0005_userattributes_can_clone_instances.py
new file mode 100644
index 0000000..4539657
--- /dev/null
+++ b/accounts/migrations/0005_userattributes_can_clone_instances.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('accounts', '0004_userattributes'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='userattributes',
+            name='can_clone_instances',
+            field=models.BooleanField(default=False),
+        ),
+    ]
diff --git a/accounts/migrations/0006_userattributes_max_disk_size.py b/accounts/migrations/0006_userattributes_max_disk_size.py
new file mode 100644
index 0000000..3d21f5f
--- /dev/null
+++ b/accounts/migrations/0006_userattributes_max_disk_size.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('accounts', '0005_userattributes_can_clone_instances'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='userattributes',
+            name='max_disk_size',
+            field=models.IntegerField(default=0),
+        ),
+    ]
diff --git a/accounts/migrations/0007_auto_20160426_0635.py b/accounts/migrations/0007_auto_20160426_0635.py
new file mode 100644
index 0000000..2f92aba
--- /dev/null
+++ b/accounts/migrations/0007_auto_20160426_0635.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('accounts', '0006_userattributes_max_disk_size'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='userattributes',
+            name='max_cpus',
+            field=models.IntegerField(default=1),
+        ),
+        migrations.AlterField(
+            model_name='userattributes',
+            name='max_disk_size',
+            field=models.IntegerField(default=20),
+        ),
+        migrations.AlterField(
+            model_name='userattributes',
+            name='max_instances',
+            field=models.IntegerField(default=1),
+        ),
+        migrations.AlterField(
+            model_name='userattributes',
+            name='max_memory',
+            field=models.IntegerField(default=2048),
+        ),
+    ]
diff --git a/accounts/models.py b/accounts/models.py
index 20efc6f..06fefee 100644
--- a/accounts/models.py
+++ b/accounts/models.py
@@ -21,3 +21,14 @@ class UserSSHKey(models.Model):
 
     def __unicode__(self):
         return self.keyname
+
+class UserAttributes(models.Model):
+    user = models.OneToOneField(User, on_delete=models.CASCADE)
+    can_clone_instances = models.BooleanField(default=False)
+    max_instances = models.IntegerField(default=1)
+    max_cpus = models.IntegerField(default=1)
+    max_memory = models.IntegerField(default=2048)
+    max_disk_size = models.IntegerField(default=20)
+
+    def __unicode__(self):
+        return self.user.username
diff --git a/accounts/templates/accounts.html b/accounts/templates/accounts.html
index 9ebff0b..4fdfc8a 100644
--- a/accounts/templates/accounts.html
+++ b/accounts/templates/accounts.html
@@ -71,6 +71,48 @@
                                                     <input type="password" name="user_pass" class="form-control" value="">
                                                 </div>
                                             </div>
+                                            <div class="form-group">
+                                                <label class="col-sm-4 control-label">{% trans "Is staff" %}</label>
+                                                <div class="col-sm-2">
+                                                    <input type="checkbox" name="user_is_staff" {% if user.is_staff %}checked{% endif %}>
+                                                </div>
+                                            </div>
+                                            <div class="form-group">
+                                                <label class="col-sm-4 control-label">{% trans "Is superuser" %}</label>
+                                                <div class="col-sm-2">
+                                                    <input type="checkbox" name="user_is_superuser" {% if user.is_superuser %}checked{% endif %}>
+                                                </div>
+                                            </div>
+                                            <div class="form-group">
+                                                <label class="col-sm-4 control-label">{% trans "Can clone instances" %}</label>
+                                                <div class="col-sm-2">
+                                                    <input type="checkbox" name="userattributes_can_clone_instances" {% if user.userattributes.can_clone_instances %}checked{% endif %}>
+                                                </div>
+                                            </div>
+                                            <div class="form-group">
+                                                <label class="col-sm-4 control-label">{% trans "Max instances" %}</label>
+                                                <div class="col-sm-6">
+                                                    <input type="text" name="userattributes_max_instances" class="form-control" value="{{ user.userattributes.max_instances }}">
+                                                </div>
+                                            </div>
+                                            <div class="form-group">
+                                                <label class="col-sm-4 control-label">{% trans "Max cpus" %}</label>
+                                                <div class="col-sm-6">
+                                                    <input type="text" name="userattributes_max_cpus" class="form-control" value="{{ user.userattributes.max_cpus }}">
+                                                </div>
+                                            </div>
+                                            <div class="form-group">
+                                                <label class="col-sm-4 control-label">{% trans "Max memory (MB)" %}</label>
+                                                <div class="col-sm-6">
+                                                    <input type="text" name="userattributes_max_memory" class="form-control" value="{{ user.userattributes.max_memory }}">
+                                                </div>
+                                            </div>
+                                            <div class="form-group">
+                                                <label class="col-sm-4 control-label">{% trans "Max disk size (GB)" %}</label>
+                                                <div class="col-sm-6">
+                                                    <input type="text" name="userattributes_max_disk_size" class="form-control" value="{{ user.userattributes.max_disk_size }}">
+                                                </div>
+                                            </div>
                                     </div>
                                     <div class="modal-footer">
                                         <button type="submit" class="pull-left btn btn-danger" name="delete">
@@ -99,4 +141,4 @@
                     {% endfor %}
                 {% endif %}
             </div>
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/accounts/templates/create_user_block.html b/accounts/templates/create_user_block.html
index 7752f56..f4b4679 100644
--- a/accounts/templates/create_user_block.html
+++ b/accounts/templates/create_user_block.html
@@ -23,7 +23,7 @@
                         <div class="form-group">
                             <label class="col-sm-4 control-label">{% trans "Password" %}</label>
                             <div class="col-sm-6">
-                                <input type="password" class="form-control" name="password" placeholder="*******" required>
+                                <input type="password" class="form-control" name="password" placeholder="*******" {% if not allow_empty_password %}required{% endif %}>
                             </div>
                         </div>
                 </div>
@@ -35,4 +35,4 @@
             </div> <!-- /.modal-content -->
         </div> <!-- /.modal-dialog -->
     </div> <!-- /.modal -->
-{% endif %}
\ No newline at end of file
+{% endif %}
diff --git a/accounts/views.py b/accounts/views.py
index 3b6a63e..155ecc8 100644
--- a/accounts/views.py
+++ b/accounts/views.py
@@ -3,18 +3,19 @@ from django.http import HttpResponseRedirect
 from django.core.urlresolvers import reverse
 from django.utils.translation import ugettext_lazy as _
 from django.contrib.auth.models import User
-from accounts.models import UserInstance, UserSSHKey
+from django.contrib.auth.decorators import login_required
+from accounts.models import *
 from instances.models import Instance
 from accounts.forms import UserAddForm
+from django.conf import settings
 
 
+@login_required
 def profile(request):
     """
     :param request:
     :return:
     """
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
 
     error_messages = []
     user = User.objects.get(id=request.user.id)
@@ -63,21 +64,28 @@ def profile(request):
             return HttpResponseRedirect(request.get_full_path())
     return render(request, 'profile.html', locals())
 
-
+@login_required
 def accounts(request):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
+    def create_missing_userattributes(users):
+        for user in users:
+            try:
+                userattributes = user.userattributes
+            except UserAttributes.DoesNotExist:
+                userattributes = UserAttributes(user=user)
+                userattributes.save()
 
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
     error_messages = []
-    users = User.objects.filter(is_staff=False, is_superuser=False)
+    users = User.objects.all().order_by('username')
+    create_missing_userattributes(users)
+    allow_empty_password = settings.ALLOW_EMPTY_PASSWORD
 
     if request.method == 'POST':
         if 'create' in request.POST:
@@ -96,7 +104,17 @@ def accounts(request):
             user_pass = request.POST.get('user_pass', '')
             user_edit = User.objects.get(id=user_id)
             user_edit.set_password(user_pass)
+            user_edit.is_staff = request.POST.get('user_is_staff', False)
+            user_edit.is_superuser = request.POST.get('user_is_superuser', False)
             user_edit.save()
+
+            userattributes = user_edit.userattributes
+            userattributes.can_clone_instances = request.POST.get('userattributes_can_clone_instances', False)
+            userattributes.max_instances = request.POST.get('userattributes_max_instances', 0)
+            userattributes.max_cpus = request.POST.get('userattributes_max_cpus', 0)
+            userattributes.max_memory = request.POST.get('userattributes_max_memory', 0)
+            userattributes.max_disk_size = request.POST.get('userattributes_max_disk_size', 0)
+            userattributes.save()
             return HttpResponseRedirect(request.get_full_path())
         if 'block' in request.POST:
             user_id = request.POST.get('user_id', '')
@@ -123,22 +141,20 @@ def accounts(request):
     return render(request, 'accounts.html', locals())
 
 
+@login_required
 def account(request, user_id):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
     error_messages = []
     user = User.objects.get(id=user_id)
     user_insts = UserInstance.objects.filter(user_id=user_id)
-    instances = Instance.objects.all()
+    instances = Instance.objects.all().order_by('name')
 
     if user.username == request.user.username:
         return HttpResponseRedirect(reverse('profile'))
@@ -162,12 +178,17 @@ def account(request, user_id):
             return HttpResponseRedirect(request.get_full_path())
         if 'add' in request.POST:
             inst_id = request.POST.get('inst_id', '')
-            try:
-                check_inst = UserInstance.objects.get(instance_id=int(inst_id))
+            
+            if settings.ALLOW_INSTANCE_MULTIPLE_OWNER:
+                check_inst = UserInstance.objects.filter(instance_id=int(inst_id), user_id=int(user_id))
+            else:
+                check_inst = UserInstance.objects.filter(instance_id=int(inst_id))
+            
+            if check_inst:
                 msg = _("Instance already added")
                 error_messages.append(msg)
-            except UserInstance.DoesNotExist:
-                add_user_inst = UserInstance(instance_id=int(inst_id), user_id=user_id)
+            else:
+                add_user_inst = UserInstance(instance_id=int(inst_id), user_id=int(user_id))
                 add_user_inst.save()
                 return HttpResponseRedirect(request.get_full_path())
 
diff --git a/computes/forms.py b/computes/forms.py
index a626106..7dfcbe6 100644
--- a/computes/forms.py
+++ b/computes/forms.py
@@ -149,6 +149,8 @@ class ComputeEditHostForm(forms.Form):
 class ComputeAddSocketForm(forms.Form):
     name = forms.CharField(error_messages={'required': _('No hostname has been entered')},
                            max_length=20)
+    details = forms.CharField(error_messages={'required': _('No details has been entred')},
+                           max_length=50)
 
     def clean_name(self):
         name = self.cleaned_data['name']
diff --git a/computes/migrations/0002_compute_details.py b/computes/migrations/0002_compute_details.py
new file mode 100644
index 0000000..1e0fdf5
--- /dev/null
+++ b/computes/migrations/0002_compute_details.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('computes', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='Compute',
+            name='details',
+            field=models.CharField(max_length=50, null=True, blank=True),
+        ),
+    ]
diff --git a/computes/models.py b/computes/models.py
index 6ee7de8..df9bf02 100644
--- a/computes/models.py
+++ b/computes/models.py
@@ -6,6 +6,7 @@ class Compute(models.Model):
     hostname = models.CharField(max_length=20)
     login = models.CharField(max_length=20)
     password = models.CharField(max_length=14, blank=True, null=True)
+    details = models.CharField(max_length=50, null=True, blank=True) 
     type = models.IntegerField()
 
     def __unicode__(self):
diff --git a/computes/templates/computes.html b/computes/templates/computes.html
index 7c1c28f..2ffc6f4 100644
--- a/computes/templates/computes.html
+++ b/computes/templates/computes.html
@@ -45,6 +45,11 @@
                                             {% else %}
                                                 <p>{% trans "Not Connected" %}</p>
                                             {% endif %}
+											{% if compute.details %}
+												<p>{% trans compute.details %}</p>
+											{% else %}
+												<p>{% trans "No details available" %}</p>
+											{% endif %}
                                         </div>
                                     </div>
 
diff --git a/computes/templates/create_comp_block.html b/computes/templates/create_comp_block.html
index 57e327a..9e9a965 100644
--- a/computes/templates/create_comp_block.html
+++ b/computes/templates/create_comp_block.html
@@ -141,6 +141,14 @@
                                         <input type="text" name="name" class="form-control" placeholder="Label Name" maxlength="20" required pattern="[a-z0-9\.\-_]+">
                                     </div>
                                 </div>
+
+								<div class="form-group">
+                                    <label class="col-sm-4 control-label">{% trans "Details" %}</label>
+                                    <div class="col-sm-6">
+                                        <input type="text" name="details" class="form-control" placeholder="{% trans "Details" %}">
+                                    </div>
+                                </div>
+
                         </div>
                         <div class="modal-footer">
                             <button type="button" class="btn btn-default" data-dismiss="modal">
@@ -156,4 +164,4 @@
             </div> <!-- /.modal-content -->
         </div> <!-- /.modal-dialog -->
     </div><!-- /.modal -->
-{% endif %}
\ No newline at end of file
+{% endif %}
diff --git a/computes/templates/overview.html b/computes/templates/overview.html
index 09d5d83..8bfad6e 100644
--- a/computes/templates/overview.html
+++ b/computes/templates/overview.html
@@ -40,6 +40,7 @@
                     <p>{% trans "Logical CPUs" %}</p>
                     <p>{% trans "Processor" %}</p>
                     <p>{% trans "Connection" %}</p>
+					<p>{% trans "Details" %}</p>
                 </div>
                 <div class="col-xs-8 col-sm-7">
                     <p>{{ hostname }}</p>
@@ -49,6 +50,7 @@
                     <p>{{ logical_cpu }}</p>
                     <p>{{ model_cpu }}</p>
                     <p>{{ uri_conn }}</p>
+					<p>{{ compute.details }}</p>
                 </div>
             </div>
             <div class="row">
diff --git a/computes/views.py b/computes/views.py
index 39af4d0..13fb70d 100644
--- a/computes/views.py
+++ b/computes/views.py
@@ -3,6 +3,7 @@ import json
 from django.http import HttpResponse, HttpResponseRedirect
 from django.core.urlresolvers import reverse
 from django.shortcuts import render, get_object_or_404
+from django.contrib.auth.decorators import login_required
 from computes.models import Compute
 from instances.models import Instance
 from accounts.models import UserInstance
@@ -12,15 +13,13 @@ from vrtManager.connection import CONN_SSH, CONN_TCP, CONN_TLS, CONN_SOCKET, con
 from libvirt import libvirtError
 
 
+@login_required
 def computes(request):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
@@ -36,14 +35,15 @@ def computes(request):
                                  'status': connection_manager.host_is_up(compute.type, compute.hostname),
                                  'type': compute.type,
                                  'login': compute.login,
-                                 'password': compute.password
+                                 'password': compute.password,
+                                 'details': compute.details
                                  })
         return compute_data
 
     error_messages = []
-    computes = Compute.objects.filter()
+    computes = Compute.objects.filter().order_by('name')
     computes_info = get_hosts_status(computes)
-
+    
     if request.method == 'POST':
         if 'host_del' in request.POST:
             compute_id = request.POST.get('host_id', '')
@@ -104,6 +104,7 @@ def computes(request):
             if form.is_valid():
                 data = form.cleaned_data
                 new_socket_host = Compute(name=data['name'],
+                                          details=data['details'],
                                           hostname='localhost',
                                           type=CONN_SOCKET,
                                           login='',
@@ -122,6 +123,7 @@ def computes(request):
                 compute_edit.hostname = data['hostname']
                 compute_edit.login = data['login']
                 compute_edit.password = data['password']
+                compute.edit_details = data['details']
                 compute_edit.save()
                 return HttpResponseRedirect(request.get_full_path())
             else:
@@ -130,15 +132,13 @@ def computes(request):
     return render(request, 'computes.html', locals())
 
 
+@login_required
 def overview(request, compute_id):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
@@ -160,15 +160,13 @@ def overview(request, compute_id):
     return render(request, 'overview.html', locals())
 
 
+@login_required
 def compute_graph(request, compute_id):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('login'))
-
     points = 5
     datasets = {}
     cookies = {}
diff --git a/console/views.py b/console/views.py
index a123064..4651c87 100644
--- a/console/views.py
+++ b/console/views.py
@@ -2,6 +2,7 @@ import re
 from django.shortcuts import render
 from django.http import HttpResponseRedirect
 from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
 from instances.models import Instance
 from vrtManager.instance import wvmInstance
 from webvirtcloud.settings import WS_PORT
@@ -9,15 +10,13 @@ from webvirtcloud.settings import WS_PUBLIC_HOST
 from libvirt import libvirtError
 
 
+@login_required
 def console(request):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('login'))
-
     if request.method == 'GET':
         token = request.GET.get('token', '')
 
diff --git a/create/templates/create_instance.html b/create/templates/create_instance.html
index 9df7326..d2be478 100644
--- a/create/templates/create_instance.html
+++ b/create/templates/create_instance.html
@@ -239,7 +239,7 @@
                     </div>
                 {% else %}
                     <div class="col-lg-12">
-                        <h3 class="page-header">{% trans "Create from flover" %}</h3>
+                        <h3 class="page-header">{% trans "Create from flavor" %}</h3>
                         <div class="table-responsive">
                             <table class="table table-bordered table-hover">
                             <thead>
diff --git a/create/views.py b/create/views.py
index c3e1139..6c223da 100644
--- a/create/views.py
+++ b/create/views.py
@@ -2,6 +2,7 @@ from django.shortcuts import render, get_object_or_404
 from django.http import HttpResponseRedirect
 from django.utils.translation import ugettext_lazy as _
 from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
 from computes.models import Compute
 from create.models import Flavor
 from create.forms import FlavorAddForm, NewVMForm
@@ -11,15 +12,13 @@ from vrtManager import util
 from libvirt import libvirtError
 
 
+@login_required
 def create_instance(request, compute_id):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
diff --git a/instances/migrations/0002_instance_is_template.py b/instances/migrations/0002_instance_is_template.py
new file mode 100644
index 0000000..cbf2cdd
--- /dev/null
+++ b/instances/migrations/0002_instance_is_template.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('instances', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='instance',
+            name='is_template',
+            field=models.BooleanField(default=False),
+        ),
+    ]
diff --git a/instances/models.py b/instances/models.py
index 4345cc1..bf2a1c4 100644
--- a/instances/models.py
+++ b/instances/models.py
@@ -6,6 +6,7 @@ class Instance(models.Model):
     compute = models.ForeignKey(Compute)
     name = models.CharField(max_length=20)
     uuid = models.CharField(max_length=36)
+    is_template = models.BooleanField(default=False)
 
     def __unicode__(self):
         return self.name
diff --git a/instances/templates/create_inst_block.html b/instances/templates/create_inst_block.html
index 36ec37d..264aa75 100644
--- a/instances/templates/create_inst_block.html
+++ b/instances/templates/create_inst_block.html
@@ -35,16 +35,16 @@
                         {% trans "Close" %}
                     </button>
                     {% if computes %}
-                        <button type="submit" class="btn btn-primary" name="chose" onclick='goto_compute()'>
-                            {% trans "Chose" %}
+                        <button type="submit" class="btn btn-primary" name="choose" onclick='goto_compute()'>
+                            {% trans "Choose" %}
                         </button>
                     {% else %}
                         <button class="btn btn-primary disabled">
-                            {% trans "Chose" %}
+                            {% trans "Choose" %}
                         </button>
                     {% endif %}
                 </div>
             </div> <!-- /.modal-content -->
         </div> <!-- /.modal-dialog -->
     </div> <!-- /.modal -->
-{% endif %}
\ No newline at end of file
+{% endif %}
diff --git a/instances/templates/instance.html b/instances/templates/instance.html
index 36e7afa..e7ca557 100644
--- a/instances/templates/instance.html
+++ b/instances/templates/instance.html
@@ -2,6 +2,7 @@
 {% load i18n %}
 {% block title %}{% trans "Instance" %} - {{ vname }}{% endblock %}
 {% block content %}
+                {% include 'pleasewaitdialog.html' %}
                 <!-- Page Heading -->
                  <div class="row">
                     <table>
@@ -18,6 +19,9 @@
                                     <span class="label label-warning">{% trans "Suspend" %}</span>
                                 {% endifequal %}
                             </td>
+                            <td>
+                                <a href="{% url 'instance' compute.id vname %}" type="button" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-refresh"></span></a>
+                            </td>
                         </tr>
                     </table>
                     <table width="65%">
@@ -39,6 +43,9 @@
                             {% endfor %}
                         </tr>
                     </table>
+                    {% if user_quota_msg %}
+                        <span class="label label-warning">{{ user_quota_msg|capfirst }} quota reached.</span>
+                    {% endif %}
                     <hr>
                 </div>
 
@@ -204,7 +211,12 @@
                                                 <div role="tabpanel" class="tab-pane tab-pane-bordered active" id="boot">
                                                     <p>{% trans "Click on Boot button to start this instance." %}</p>
                                                     <form action="" method="post" role="form">{% csrf_token %}
-                                                        <input type="submit" name="poweron" class="btn btn-lg btn-success pull-right" value="{% trans "Power On" %}">
+                                                        {% if instance.is_template %}
+                                                            <p>{% trans "Template instance cannot be started." %}</p>
+                                                            <input type="submit" name="poweron" class="btn btn-lg btn-success pull-right disabled" value="{% trans "Power On" %}">
+                                                        {% else %}
+                                                            <input type="submit" name="poweron" class="btn btn-lg btn-success pull-right" value="{% trans "Power On" %}">
+                                                        {% endif %}
                                                         <div class="clearfix"></div>
                                                     </form>
                                                 </div>
@@ -355,6 +367,15 @@
                                                                 <small><input type="checkbox" class="js-custom__checkbox" /> {% trans "Custom value" %}</small>
                                                             </div>
                                                         </div>
+                                                        <p style="font-weight:bold;">{% trans "Disk allocation (B):" %}</p>
+                                                        {% for disk in disks %}
+                                                        <div class="form-group">
+                                                            <label class="col-sm-4 control-label" style="font-weight:normal;">{% trans "Current allocation" %} ({{ disk.dev }})</label>
+                                                            <div class="col-sm-4 js-custom__container">
+                                                                <input type="text" name="disk_size_{{ disk.dev }}" class="form-control" value="{{ disk.size|filesizeformat }}" />
+                                                            </div>
+                                                        </div>
+                                                        {% endfor %}
                                                         {% ifequal status 5 %}
                                                             <button type="submit" class="btn btn-lg btn-success pull-right" name="resize">{% trans "Resize" %}</button>
                                                         {% else %}
@@ -486,11 +507,20 @@
                                                 </li>
                                             {% endif %}
                                             {% if request.user.is_superuser %}
+                                                <li role="presentation">
+                                                    <a href="#network" aria-controls="network" role="tab" data-toggle="tab">
+                                                        {% trans "Network" %}
+                                                    </a>
+                                                </li>
+                                            {% endif %}
+                                            {% if request.user.is_superuser or request.user.userattributes.can_clone_instances %}
                                                 <li role="presentation">
                                                     <a href="#clone" aria-controls="clone" role="tab" data-toggle="tab">
                                                         {% trans "Clone" %}
                                                     </a>
                                                 </li>
+                                            {% endif %}
+                                            {% if request.user.is_superuser %}
                                                 <li role="presentation">
                                                     <a href="#migrate" aria-controls="migrate" role="tab" data-toggle="tab">
                                                         {% trans "Migrate" %}
@@ -501,6 +531,16 @@
                                                         {% trans "XML" %}
                                                     </a>
                                                 </li>
+                                                <li role="presentation">
+                                                    <a href="#options" aria-controls="options" role="tab" data-toggle="tab">
+                                                        {% trans "Options" %}
+                                                    </a>
+                                                </li>
+                                                <li role="presentation">
+                                                    <a href="#users" aria-controls="users" role="tab" data-toggle="tab">
+                                                        {% trans "Users" %}
+                                                    </a>
+                                                </li>
                                             {% endif %}
                                         </ul>
                                         <!-- Tab panes -->
@@ -651,51 +691,118 @@
                                                 </div>
                                             {% endif %}
                                             {% if request.user.is_superuser %}
+                                                <div role="tabpanel" class="tab-pane tab-pane-bordered" id="network">
+                                                    <p>{% trans "Assign network device to bridge" %}</p>
+                                                    <form class="form-horizontal" action="" method="post" role="form">{% csrf_token %}
+                                                        <p style="font-weight:bold;">{% trans "Network devices" %}</p>
+                                                        {% for network in networks %}
+                                                            <div class="form-group">
+                                                                <label class="col-sm-3 control-label" style="font-weight:normal;">eth{{ forloop.counter0 }}</label>
+                                                                <div class="col-sm-4">
+                                                                    <input type="text" class="form-control" name="net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}"/>
+                                                                </div>
+                                                                <div class="col-sm-3">
+                                                                    <input type="text" class="form-control" name="net-source-{{ forloop.counter0 }}" value="{{ network.nic }}"/>
+                                                                </div>
+                                                            </div>
+                                                        {% endfor %}
+                                                        {% ifequal status 5 %}
+                                                            <button type="submit" class="btn btn-lg btn-success pull-right" name="change_network">{% trans "Change" %}</button>
+                                                        {% else %}
+                                                            <button class="btn btn-lg btn-success pull-right disabled" name="change_network">{% trans "Change" %}</button>
+                                                        {% endifequal %}
+                                                    </form>
+                                                    <div class="clearfix"></div>
+                                                </div>
+                                            {% endif %}
+                                            {% if request.user.is_superuser or request.user.userattributes.can_clone_instances %}
                                                 <div role="tabpanel" class="tab-pane tab-pane-bordered" id="clone">
                                                     <p style="font-weight:bold;">{% trans "Create a clone" %}</p>
                                                     <form class="form-horizontal" action="" method="post" role="form">{% csrf_token %}
                                                         <div class="form-group">
                                                             <label class="col-sm-3 control-label" style="font-weight:normal;">{% trans "Clone Name" %}</label>
-                                                            <div class="col-sm-3">
-                                                                <input type="text" class="form-control" name="name" value="{{ vname }}-clone"/>
+                                                            {% if request.user.is_superuser %}
+                                                            <div class="col-sm-4">
+                                                                <input id="clone_name" type="text" class="form-control" name="name" value="{{ vname }}-clone"/>
+                                                            </div>
+                                                            <div class="col-sm-4">
+                                                                <button type="button" class="btn btn-sm btn-success pull-left" name="guess-clone-name"
+                                                                        onclick="guess_clone_name()" style="margin-top: 2px;">{% trans "Guess" %}</button>
+                                                            </div>
+                                                            {% else %}
+                                                            <div class="col-sm-4">
+                                                                <select id="select_clone_name" class="form-control" name="name" size="1"/>
+                                                                {% for name in clone_free_names %}
+                                                                    <option value="{{ name }}">{{ name }}</option>
+                                                                {% endfor %}
+                                                                </select>
+                                                            </div>
+                                                            {% endif %}
+                                                        </div>
+                                                        {% if request.user.is_superuser %}
+                                                            <p style="font-weight:bold;">{% trans "Network devices" %}</p>
+                                                            {% for network in networks %}
+                                                                <div class="form-group">
+                                                                    <label class="col-sm-3 control-label" style="font-weight:normal;">eth{{ forloop.counter0 }} ({{ network.nic }})</label>
+                                                                    <div class="col-sm-4">
+                                                                        <input type="text" class="form-control" name="clone-net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}"/>
+                                                                    </div>
+                                                                    <div class="col-sm-4">
+                                                                        <button type="button" class="btn btn-sm btn-success pull-left" name="random-mac-{{ forloop.counter0 }}"
+                                                                                onclick="random_mac({{ forloop.counter0 }})" style="margin-top: 2px;">{% trans "Random" %}</button>
+                                                                        <button type="button" class="btn btn-sm btn-success pull-left" name="guess-mac-{{ forloop.counter0 }}"
+                                                                                onclick="guess_mac_address('#clone_name', {{ forloop.counter0 }})" style="margin-top: 2px;">{% trans "Guess" %}</button>
+                                                                    </div>
+                                                                </div>
+                                                            {% endfor %}
+                                                        {% else %}
+                                                            {% for network in networks %}
+                                                                <input type="hidden" class="form-control" name="clone-net-mac-{{ forloop.counter0 }}" value="{{ network.mac }}"/>
+                                                            {% endfor %}
+                                                        {% endif %}
+                                                        {% if request.user.is_superuser %}
+                                                            <p style="font-weight:bold;">{% trans "Storage devices" %}</p>
+                                                            {% for disk in clone_disks %}
+                                                                <div class="form-group">
+                                                                    <label class="col-sm-3 control-label" style="font-weight:normal;">{{ disk.dev }} ({{ disk.storage }})</label>
+                                                                    <div class="col-sm-4">
+                                                                        <input id="disk_name-{{ disk.dev }}" type="text" class="form-control" name="disk-{{ disk.dev }}" value="{{ disk.image }}"/>
+                                                                    </div>
+                                                                    {% ifequal disk.format 'qcow2' %}
+                                                                        <label class="col-sm-2 control-label" style="font-weight:normal;margin-left:-35px;">Metadata</label>
+                                                                        <div class="col-sm-1">
+                                                                            <input type="checkbox" name="meta-{{ disk.dev }}" value="true" style="margin-top: 10px;">
+                                                                        </div>
+                                                                    {% endifequal %}
+                                                                </div>
+                                                            {% endfor %}
+                                                        {% else %}
+                                                            {% for disk in clone_disks %}
+                                                                <input id="disk_name-{{ disk.dev }}" type="hidden" class="form-control" name="disk-{{ disk.dev }}" value="{{ disk.image }}"/>
+                                                            {% endfor %}
+                                                        {% endif %}
+                                                        <div class="form-group">
+                                                            <label class="col-sm-3 control-label">{% trans "Title" %}</label>
+                                                            <div class="col-sm-6">
+                                                                <input type="text" name="clone-title" class="form-control">
                                                             </div>
                                                         </div>
-                                                        <p style="font-weight:bold;">{% trans "Network devices" %}</p>
-                                                        {% for network in networks %}
-                                                            <div class="form-group">
-                                                                <label class="col-sm-3 control-label" style="font-weight:normal;">eth{{ forloop.counter0 }} ({{ network.nic }})</label>
-                                                                <div class="col-sm-3">
-                                                                    <input type="text" class="form-control" name="net-{{ forloop.counter0 }}" value="{{ network.mac }}"/>
-                                                                </div>
-                                                                <div class="col-sm-1">
-                                                                    <button type="button" class="btn btn-sm btn-success pull-left" name="random-mac-{{ forloop.counter0 }}"
-                                                                            onclick="random_mac({{ forloop.counter0 }})" style="margin-top: 2px;">{% trans "Random" %}</button>
-                                                                </div>
+                                                        <div class="form-group">
+                                                            <label class="col-sm-3 control-label">{% trans "Description" %}</label>
+                                                            <div class="col-sm-6">
+                                                                <textarea name="clone-description" class="form-control"></textarea>
                                                             </div>
-                                                        {% endfor %}
-                                                        <p style="font-weight:bold;">{% trans "Storage devices" %}</p>
-                                                        {% for disk in clone_disks %}
-                                                            <div class="form-group">
-                                                                <label class="col-sm-3 control-label" style="font-weight:normal;">{{ disk.dev }} ({{ disk.storage }})</label>
-                                                                <div class="col-sm-3">
-                                                                    <input type="text" class="form-control" name="disk-{{ disk.dev }}" value="{{ disk.image }}"/>
-                                                                </div>
-                                                                {% ifequal disk.format 'qcow2' %}
-                                                                    <label class="col-sm-2 control-label" style="font-weight:normal;margin-left:-35px;">Metadata</label>
-                                                                    <div class="col-sm-1">
-                                                                        <input type="checkbox" name="meta-{{ disk.dev }}" value="true" style="margin-top: 10px;">
-                                                                    </div>
-                                                                {% endifequal %}
-                                                            </div>
-                                                        {% endfor %}
+                                                        </div>
                                                         {% ifequal status 5 %}
-                                                            <button type="submit" class="btn btn-lg btn-success pull-right" name="clone">{% trans "Clone" %}</button>
+                                                            <button type="submit" class="btn btn-lg btn-success pull-right" name="clone" onclick="showPleaseWaitDialog();">{% trans "Clone" %}</button>
                                                         {% else %}
                                                             <button class="btn btn-lg btn-success pull-right disabled" name="clone">{% trans "Clone" %}</button>
                                                         {% endifequal %}
                                                     </form>
                                                     <div class="clearfix"></div>
                                                 </div>
+                                            {% endif %}
+                                            {% if request.user.is_superuser %}
                                                 <div role="tabpanel" class="tab-pane tab-pane-bordered" id="migrate">
                                                     <p>{% trans "For migration both host servers must have equal settings and OS type" %}</p>
                                                     <form class="form-horizontal" method="post" role="form">{% csrf_token %}
@@ -722,7 +829,7 @@
                                                         <div class="form-group">
                                                             <label class="col-sm-3 control-label">{% trans "Live migration" %}</label>
                                                             <div class="col-sm-6">
-                                                                <input type="checkbox" name="live_migrate" value="true" id="vm_live_migrate">
+                                                                <input type="checkbox" name="live_migrate" value="true" id="vm_live_migrate" checked>
                                                             </div>
                                                         </div>
                                                         <div class="form-group">
@@ -734,11 +841,11 @@
                                                         <div class="form-group">
                                                             <label class="col-sm-3 control-label">{% trans "Delete original" %}</label>
                                                             <div class="col-sm-6">
-                                                                <input type="checkbox" name="xml_delete" value="true" id="xml_delete">
+                                                                <input type="checkbox" name="xml_delete" value="true" id="xml_delete" checked>
                                                             </div>
                                                         </div>
                                                         {% if computes_count != 1 %}
-                                                            <button type="submit" class="btn btn-lg btn-success pull-right" name="migrate">{% trans "Migrate" %}</button>
+                                                            <button type="submit" class="btn btn-lg btn-success pull-right" name="migrate" onclick="showPleaseWaitDialog();">{% trans "Migrate" %}</button>
                                                         {% else %}
                                                             <button class="btn btn-lg btn-success pull-right disabled">{% trans "Migrate" %}</button>
                                                         {% endif %}
@@ -764,6 +871,41 @@
                                                     </form>
                                                     <div class="clearfix"></div>
                                                 </div>
+                                                <div role="tabpanel" class="tab-pane tab-pane-bordered" id="options">
+                                                    <form class="form-horizontal" action="" method="post" role="form">{% csrf_token %}
+                                                        <div class="form-group">
+                                                            <label class="col-sm-3 control-label">{% trans "Title" %}</label>
+                                                            <div class="col-sm-6">
+                                                                <input type="text" name="title" class="form-control" value="{{ title }}">
+                                                            </div>
+                                                        </div>
+                                                        <div class="form-group">
+                                                            <label class="col-sm-3 control-label">{% trans "Description" %}</label>
+                                                            <div class="col-sm-6">
+                                                                <textarea name="description" class="form-control">{{ description }}</textarea>
+                                                            </div>
+                                                        </div>
+                                                        <div class="form-group">
+                                                            <label class="col-sm-3 control-label">{% trans "Is template" %}</label>
+                                                            <div class="col-sm-6">
+                                                                <input type="checkbox" name="is_template" value="true" id="is_template" {% if instance.is_template %}checked{% endif %}>
+                                                            </div>
+                                                        </div>
+                                                        {% ifequal status 5 %}
+                                                            <button type="submit" class="btn btn-lg btn-success pull-right" name="change_options">{% trans "Change" %}</button>
+                                                        {% else %}
+                                                            <button class="btn btn-lg btn-success pull-right disabled" name="change_options">{% trans "Change" %}</button>
+                                                        {% endifequal %}
+                                                    </form>
+                                                    <div class="clearfix"></div>
+                                                </div>
+                                                <div role="tabpanel" class="tab-pane tab-pane-bordered" id="users">
+                                                    <p style="font-weight:bold;">{% trans "Instance owners" %}</p>
+                                                    {% for userinstance in userinstances %}
+                                                    <p><a href="{% url 'account' userinstance.user.id %}">{{ userinstance.user }}</a></p>
+                                                    {%  endfor %}
+                                                    <div class="clearfix"></div>
+                                                </div>
                                             {% endif %}
                                         </div>
                                     </div>
@@ -847,7 +989,7 @@
                                                         <form class="form-group" method="post" role="form">{% csrf_token %}
                                                             <div class="checkbox" style="margin-left: 8px;">
                                                                 <label>
-                                                                    <input type="checkbox" name="delete_disk" value="true">
+                                                                    <input type="checkbox" name="delete_disk" value="true" checked>
                                                                     <strong>{% trans "Remove Instance's data" %}</strong>
                                                                 </label>
                                                             </div>
@@ -892,7 +1034,7 @@
             macAddress+=hexDigits.charAt(Math.round(Math.random()*16));
             if (i != 2) macAddress+=":";
         }
-        $('input[name="net-'+net+'"]').val(macAddress);
+        $('input[name="clone-net-mac-'+net+'"]').val(macAddress);
     };
 </script>
 <script>
@@ -904,6 +1046,46 @@
         }
     }
 </script>
+<script>
+    function guess_mac_address(src_elem, net) {
+        new_vname = $(src_elem).val();
+        $.getJSON('/instance/guess_mac_address/' + new_vname + '/', function(data) {
+            $('input[name="clone-net-mac-'+net+'"]').val(data['mac']);
+        });
+    }
+</script>
+<script>
+    function guess_clone_name() {
+        $.getJSON('/instance/guess_clone_name/', function(data) {
+            guessed_name = data['name'].split(".")[0];
+            $('#clone_name').val(guessed_name);
+            update_clone_disk_name(guessed_name);
+            guess_mac_address('#clone_name', 0);
+        });
+    }
+</script>
+<script>
+    function update_clone_disk_name(new_vname) {
+        vname = '{{ vname }}-clone';
+        {% for disk in clone_disks %}
+        disk_name = '{{ disk.image }}';
+        disk_minus = disk_name.split('-');
+        disk_minus_suffix = disk_minus[disk_minus.length-1];
+        disk_minus.pop();
+        disk_minus_name = disk_minus.join('-');
+        disk_dot = disk_name.split('.')
+        disk_dot_suffix = disk_dot[disk_dot.length-1];
+        if (disk_name.lastIndexOf('-') > -1 && disk_minus_name == vname) {
+            image = new_vname + "-" + disk_minus_suffix;
+        } else if (disk_name.lastIndexOf('.') > -1 && disk_dot_suffix.length <= 7) {
+            image = new_vname + "." + disk_dot_suffix
+        } else {
+            image = new_vname + '-clone';
+        }
+        $('#disk_name-{{ disk.dev }}').val(image);
+        {% endfor %} 
+    }
+</script>
 <script>
     $(document).on('change', '#console_passwd_gen', function () {
         if ($(this).prop('checked')) {
@@ -928,6 +1110,9 @@
             $('#console_keymap_selection').show();
         }
     });
+    $('#clone_name').on('input', function () {
+        update_clone_disk_name($(this).val());
+    });
     $(document).ready(function () {
         // set current console keymap or fall back to default
         var keymap = "{{ console_keymap }}"
@@ -942,6 +1127,16 @@
             $("#console_select_type option[value='" + console_type + "']").prop('selected', true);
         }
     });
+{% if not request.user.is_superuser %}
+    $('#select_clone_name').on('change', function () {
+        update_clone_disk_name($(this).val());
+        guess_mac_address('#select_clone_name', 0);
+    });
+    $(document).ready(function () {
+        update_clone_disk_name($('#select_clone_name').val());
+        guess_mac_address('#select_clone_name', 0);
+    });
+{% endif %}
 </script>
 <script>
     $(function () {
@@ -1116,7 +1311,7 @@
             }
         });
     }
-    if (~$.inArray(hash, ['#media', '#clone', '#autostart', '#xmledit', '#vncsettings', '#migrate'])) {
+    if (~$.inArray(hash, ['#media', '#network', '#clone', '#autostart', '#xmledit', '#vncsettings', '#migrate', '#options', '#users'])) {
         var btnsect = $('#navbtn>li>a');
         $(btnsect).each(function () {
             if ($(this).attr('href') === '#settings') {
diff --git a/instances/templates/instances.html b/instances/templates/instances.html
index 144a5cd..8cee448 100644
--- a/instances/templates/instances.html
+++ b/instances/templates/instances.html
@@ -39,8 +39,8 @@
                                     <table class="table table-hover table-striped sortable-theme-bootstrap" data-sortable>
                                         <thead>
                                             <tr>
-                                                <th>Name</th>
-                                                <th>Host</th>
+                                                <th>Name<br>Description</th>
+                                                <th>Host<br>User</th>
                                                 <th>Status</th>
                                                 <th>VCPU</th>
                                                 <th>Memory</th>
@@ -51,8 +51,8 @@
                                             {% for host, inst  in all_host_vms.items %}
                                                 {% for vm, info in inst.items %}
                                                     <tr>
-                                                        <td><a href="{% url 'instance' host.0 vm %}">{{ vm }}</a></td>
-                                                        <td><a href="{% url 'overview' host.0 %}">{{ host.1 }}</a></td>
+                                                        <td><a href="{% url 'instance' host.0 vm %}">{{ vm }}</a><br><small><em>{{ info.title }}</em></small></td>
+                                                        <td><a href="{% url 'overview' host.0 %}">{{ host.1 }}</a><br><small><em>{% if info.userinstances.count > 0 %}{{ info.userinstances.first_user.user.username }}{% if info.userinstances.count > 1 %} (+{{ info.userinstances.count|add:"-1" }}){% endif %}{% endif %}</em></small></td>
                                                         <td>{% ifequal info.status 1 %}
                                                                 <span class="text-success">{% trans "Active" %}</span>
                                                             {% endifequal %}
@@ -69,9 +69,15 @@
                                                                 <input type="hidden" name="name" value="{{ vm }}"/>
                                                                 <input type="hidden" name="compute_id" value="{{ host.0 }}"/>
                                                                 {% ifequal info.status 5 %}
-                                                                    <button class="btn btn-sm btn-default" type="submit" name="poweron" title="{% trans "Power On" %}">
-                                                                        <span class="glyphicon glyphicon-play"></span>
-                                                                    </button>
+                                                                    {% if info.is_template %}
+                                                                        <button class="btn btn-sm btn-default" type="button" name="clone" title="{% trans "Clone" %}" onclick="goto_instance_clone({{ host.0 }}, '{{ vm }}');">
+                                                                            <span class="glyphicon glyphicon-duplicate"></span>
+                                                                        </button>
+                                                                    {% else %}
+                                                                        <button class="btn btn-sm btn-default" type="submit" name="poweron" title="{% trans "Power On" %}">
+                                                                            <span class="glyphicon glyphicon-play"></span>
+                                                                        </button>
+                                                                    {% endif %}
                                                                     <button class="btn btn-sm btn-default disabled" title="{% trans "Suspend" %}">
                                                                         <span class="glyphicon glyphicon-pause"></span>
                                                                     </button>
@@ -149,7 +155,7 @@
                                         <tbody class="searchable">
                                             {% for inst, vm in all_user_vms.items %}
                                                 <tr>
-                                                    <td><a href="{% url 'instance' vm.compute_id vm.name %}">{{ vm.name }}</a></td>
+                                                    <td><a href="{% url 'instance' vm.compute_id vm.name %}">{{ vm.name }}</a><br><small><em>{{ vm.title }}</em></small></td>
                                                     <td>{% ifequal vm.status 1 %}
                                                             <span class="text-success">{% trans "Active" %}</span>
                                                         {% endifequal %}
@@ -166,9 +172,15 @@
                                                             <input type="hidden" name="name" value="{{ vm.name }}"/>
                                                             <input type="hidden" name="compute_id" value="{{ vm.compute_id }}"/>
                                                             {% ifequal vm.status 5 %}
-                                                                <button class="btn btn-sm btn-default" type="submit" name="poweron" title="Power On">
-                                                                    <span class="glyphicon glyphicon-play"></span>
-                                                                </button>
+                                                                {% if inst.instance.is_template %}
+                                                                    <button class="btn btn-sm btn-default" type="button" name="clone" title="{% trans "Clone" %}" onclick="goto_instance_clone({{ vm.compute_id }}, '{{ vm.name }}');">
+                                                                        <span class="glyphicon glyphicon-duplicate"></span>
+                                                                    </button>
+                                                                {% else %}
+                                                                    <button class="btn btn-sm btn-default" type="submit" name="poweron" title="{% trans "Power On" %}">
+                                                                        <span class="glyphicon glyphicon-play"></span>
+                                                                    </button>
+                                                                {% endif %}
                                                                 <button class="btn btn-sm btn-default disabled" title="{% trans "Power Off" %}">
                                                                     <span class="glyphicon glyphicon-off"></span>
                                                                 </button>
@@ -227,18 +239,30 @@
     }
 </script>
 <script>
+    function filter_table() {
+        var rex = new RegExp($(this).val(), 'i');
+        $('.searchable tr').hide();
+        $('.searchable tr').filter(function () {
+            return rex.test($(this).text());
+        }).show();
+        Cookies.set("instances_filter", $(this).val(), { expires: 1 });
+    }
     $(document).ready(function () {
+        instances_filter_cookie = Cookies.get("instances_filter");
+        if (instances_filter_cookie) {
+            $('#filter').val(instances_filter_cookie);
+            $('#filter').each(filter_table);
+        }
         (function ($) {
-            $('#filter').keyup(function () {
-                var rex = new RegExp($(this).val(), 'i');
-                $('.searchable tr').hide();
-                $('.searchable tr').filter(function () {
-                    return rex.test($(this).text());
-                }).show();
-            })
+            $('#filter').keyup(filter_table)
         }(jQuery));
     });
 </script>
+<script>
+    function goto_instance_clone(compute, instance) {
+        window.location = "/instance/" + compute + "/" + instance + "/#clone";
+    }
+</script>
 {% if request.user.is_superuser %}
     <script>
         function goto_compute() {
diff --git a/instances/urls.py b/instances/urls.py
index ce53b89..e8f263b 100644
--- a/instances/urls.py
+++ b/instances/urls.py
@@ -8,4 +8,10 @@ urlpatterns = [
         views.inst_graph, name='inst_graph'),
     url(r'^status/(?P<compute_id>[0-9]+)/(?P<vname>[\w\-\.]+)/$',
         views.inst_status, name='inst_status'),
+    url(r'^guess_mac_address/(?P<vname>[\w\-\.]+)/$',
+        views.guess_mac_address, name='guess_mac_address'),
+    url(r'^guess_clone_name/$',
+        views.guess_clone_name, name='guess_clone_name'),
+    url(r'^check_instance/(?P<vname>[\w\-\.]+)/$',
+        views.check_instance, name='check_instance'),
 ]
diff --git a/instances/views.py b/instances/views.py
index 4d29df8..89f6765 100644
--- a/instances/views.py
+++ b/instances/views.py
@@ -1,3 +1,4 @@
+import os
 import time
 import json
 import socket
@@ -9,6 +10,7 @@ from django.http import HttpResponse, HttpResponseRedirect
 from django.core.urlresolvers import reverse
 from django.shortcuts import render, get_object_or_404
 from django.utils.translation import ugettext_lazy as _
+from django.contrib.auth.decorators import login_required
 from computes.models import Compute
 from instances.models import Instance
 from accounts.models import UserInstance, UserSSHKey
@@ -19,34 +21,41 @@ from vrtManager.util import randomPasswd
 from libvirt import libvirtError, VIR_DOMAIN_XML_SECURE
 from webvirtcloud.settings import QEMU_KEYMAPS, QEMU_CONSOLE_TYPES
 from logs.views import addlogmsg
+from django.conf import settings
 
 
+@login_required
 def index(request):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('login'))
-    else:
-        return HttpResponseRedirect(reverse('instances'))
+    return HttpResponseRedirect(reverse('instances'))
 
 
+@login_required
 def instances(request):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     error_messages = []
     all_host_vms = {}
     all_user_vms = {}
     computes = Compute.objects.all()
 
+    def get_userinstances_info(instance):
+        info = {}
+        uis = UserInstance.objects.filter(instance=instance)
+        info['count'] = len(uis)
+        if len(uis) > 0:
+            info['first_user'] = uis[0]
+        else:
+            info['first_user'] = None
+        return info
+
     if not request.user.is_superuser:
         user_instances = UserInstance.objects.filter(user_id=request.user.id)
         for usr_inst in user_instances:
@@ -70,6 +79,8 @@ def instances(request):
                                 check_uuid = Instance.objects.get(compute_id=comp.id, name=vm)
                                 if check_uuid.uuid != info['uuid']:
                                     check_uuid.save()
+                                all_host_vms[comp.id, comp.name][vm]['is_template'] = check_uuid.is_template
+                                all_host_vms[comp.id, comp.name][vm]['userinstances'] = get_userinstances_info(check_uuid)
                             except Instance.DoesNotExist:
                                 check_uuid = Instance(compute_id=comp.id, name=vm, uuid=info['uuid'])
                                 check_uuid.save()
@@ -145,15 +156,13 @@ def instances(request):
     return render(request, 'instances.html', locals())
 
 
+@login_required
 def instance(request, compute_id, vname):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     error_messages = []
     messages = []
     compute = get_object_or_404(Compute, pk=compute_id)
@@ -173,12 +182,15 @@ def instance(request, compute_id, vname):
         if not userinstace:
             return HttpResponseRedirect(reverse('index'))
 
-    def show_clone_disk(disks):
+    def show_clone_disk(disks, vname=''):
         clone_disk = []
         for disk in disks:
             if disk['image'] is None:
                 continue
-            if disk['image'].count(".") and len(disk['image'].rsplit(".", 1)[1]) <= 7:
+            if disk['image'].count("-") and disk['image'].rsplit("-", 1)[0] == vname:
+                name, suffix = disk['image'].rsplit("-", 1)
+                image = name + "-clone" + "-" + suffix
+            elif disk['image'].count(".") and len(disk['image'].rsplit(".", 1)[1]) <= 7:
                 name, suffix = disk['image'].rsplit(".", 1)
                 image = name + "-clone" + "." + suffix
             else:
@@ -187,6 +199,71 @@ def instance(request, compute_id, vname):
                 {'dev': disk['dev'], 'storage': disk['storage'],
                  'image': image, 'format': disk['format']})
         return clone_disk
+    
+    def filesizefstr(size_str):
+        if size_str == '':
+            return 0
+        size_str = size_str.encode('ascii', 'ignore').upper().translate(None, " B")
+        if 'K' == size_str[-1]:
+            return long(float(size_str[:-1]))<<10
+        elif 'M' == size_str[-1]:
+            return long(float(size_str[:-1]))<<20
+        elif 'G' == size_str[-1]:
+            return long(float(size_str[:-1]))<<30
+        elif 'T' == size_str[-1]:
+            return long(float(size_str[:-1]))<<40
+        elif 'P' == size_str[-1]:
+            return long(float(size_str[:-1]))<<50
+        else:
+            return long(float(size_str))
+
+    def get_clone_free_names(size=10):
+        prefix = settings.CLONE_INSTANCE_DEFAULT_PREFIX
+        free_names = []
+        existing_names = [i.name for i in Instance.objects.filter(name__startswith=prefix)]
+        index = 1
+        while len(free_names) < size:
+            new_name = prefix + str(index)
+            if new_name not in existing_names:
+                free_names.append(new_name)
+            index += 1
+        return free_names
+
+    def check_user_quota(instance, cpu, memory, disk_size):
+        user_instances = UserInstance.objects.filter(user_id=request.user.id, instance__is_template=False)
+        instance += len(user_instances)
+        for usr_inst in user_instances:
+            if connection_manager.host_is_up(usr_inst.instance.compute.type,
+                                             usr_inst.instance.compute.hostname):
+                conn = wvmInstance(usr_inst.instance.compute,
+                                      usr_inst.instance.compute.login,
+                                      usr_inst.instance.compute.password,
+                                      usr_inst.instance.compute.type,
+                                      usr_inst.instance.name)
+                cpu += int(conn.get_vcpu())
+                memory += int(conn.get_memory())
+                for disk in conn.get_disk_device():
+                    disk_size += int(disk['size'])>>30
+        
+        ua = request.user.userattributes
+        msg = ""
+        if ua.max_instances > 0 and instance > ua.max_instances:
+            msg = "instance"
+            if settings.QUOTA_DEBUG:
+                msg += " (%s > %s)" % (instance, ua.max_instances)
+        if ua.max_cpus > 0 and cpu > ua.max_cpus:
+            msg = "cpu"
+            if settings.QUOTA_DEBUG:
+                msg += " (%s > %s)" % (cpu, ua.max_cpus)
+        if ua.max_memory > 0 and memory > ua.max_memory:
+            msg = "memory"
+            if settings.QUOTA_DEBUG:
+                msg += " (%s > %s)" % (memory, ua.max_memory)
+        if ua.max_disk_size > 0 and disk_size > ua.max_disk_size:
+            msg = "disk"
+            if settings.QUOTA_DEBUG:
+                msg += " (%s > %s)" % (disk_size, ua.max_disk_size)
+        return msg
 
     try:
         conn = wvmInstance(compute.hostname,
@@ -202,6 +279,7 @@ def instance(request, compute_id, vname):
         uuid = conn.get_uuid()
         memory = conn.get_memory()
         cur_memory = conn.get_cur_memory()
+        title = conn.get_title()
         description = conn.get_description()
         disks = conn.get_disk_device()
         media = conn.get_media_device()
@@ -222,8 +300,10 @@ def instance(request, compute_id, vname):
         snapshots = sorted(conn.get_snapshot(), reverse=True)
         inst_xml = conn._XMLDesc(VIR_DOMAIN_XML_SECURE)
         has_managed_save_image = conn.get_managed_save_image()
-        clone_disks = show_clone_disk(disks)
+        clone_disks = show_clone_disk(disks, vname)
         console_passwd = conn.get_console_passwd()
+        clone_free_names = get_clone_free_names()
+        user_quota_msg = check_user_quota(0, 0, 0, 0)
 
         try:
             instance = Instance.objects.get(compute_id=compute_id, name=vname)
@@ -234,6 +314,8 @@ def instance(request, compute_id, vname):
             instance = Instance(compute_id=compute_id, name=vname, uuid=uuid)
             instance.save()
 
+        userinstances = UserInstance.objects.filter(instance=instance).order_by('user__username')
+
         if request.method == 'POST':
             if 'poweron' in request.POST:
                 conn.start()
@@ -271,15 +353,11 @@ def instance(request, compute_id, vname):
                 instance_name = instance.name
                 instance.delete()
 
-                if not request.user.is_superuser:
-                    del_userinstance = UserInstance.objects.get(id=userinstace.id)
+                try:
+                    del_userinstance = UserInstance.objects.filter(instance__compute_id=compute_id, instance__name=vname)
                     del_userinstance.delete()
-                else:
-                    try:
-                        del_userinstance = UserInstance.objects.filter(instance__compute_id=compute_id, instance__name=vname)
-                        del_userinstance.delete()
-                    except UserInstance.DoesNotExist:
-                        pass
+                except UserInstance.DoesNotExist:
+                    pass
 
                 msg = _("Destroy")
                 addlogmsg(request.user.username, instance_name, msg)
@@ -331,20 +409,37 @@ def instance(request, compute_id, vname):
                     error_messages.append(msg)
 
             if 'resize' in request.POST and (request.user.is_superuser or userinstace.is_change):
-                vcpu = request.POST.get('vcpu', '')
-                cur_vcpu = request.POST.get('cur_vcpu', '')
-                memory = request.POST.get('memory', '')
-                memory_custom = request.POST.get('memory_custom', '')
-                if memory_custom:
-                    memory = memory_custom
-                cur_memory = request.POST.get('cur_memory', '')
-                cur_memory_custom = request.POST.get('cur_memory_custom', '')
-                if cur_memory_custom:
-                    cur_memory = cur_memory_custom
-                conn.resize(cur_memory, memory, cur_vcpu, vcpu)
-                msg = _("Resize")
-                addlogmsg(request.user.username, instance.name, msg)
-                return HttpResponseRedirect(request.get_full_path() + '#resize')
+                new_vcpu = request.POST.get('vcpu', '')
+                new_cur_vcpu = request.POST.get('cur_vcpu', '')
+                new_memory = request.POST.get('memory', '')
+                new_memory_custom = request.POST.get('memory_custom', '')
+                if new_memory_custom:
+                    new_memory = new_memory_custom
+                new_cur_memory = request.POST.get('cur_memory', '')
+                new_cur_memory_custom = request.POST.get('cur_memory_custom', '')
+                if new_cur_memory_custom:
+                    new_cur_memory = new_cur_memory_custom
+                disks_new = []
+                for disk in disks:
+                    input_disk_size = filesizefstr(request.POST.get('disk_size_' + disk['dev'], ''))
+                    if input_disk_size > disk['size']+(64<<20):
+                        disk['size_new'] = input_disk_size
+                        disks_new.append(disk) 
+                disk_sum = sum([disk['size']>>30 for disk in disks_new])
+                disk_new_sum = sum([disk['size_new']>>30 for disk in disks_new])
+                quota_msg = check_user_quota(0, int(new_vcpu)-vcpu, int(new_memory)-memory, disk_new_sum-disk_sum)
+                if not request.user.is_superuser and quota_msg:    
+                    msg = _("User %s quota reached, cannot resize '%s'!" % (quota_msg, instance.name))
+                    error_messages.append(msg)
+                else:
+                    cur_memory = new_cur_memory
+                    memory = new_memory
+                    cur_vcpu = new_cur_vcpu
+                    vcpu = new_vcpu
+                    conn.resize(cur_memory, memory, cur_vcpu, vcpu, disks_new)
+                    msg = _("Resize")
+                    addlogmsg(request.user.username, instance.name, msg)
+                    return HttpResponseRedirect(request.get_full_path() + '#resize')
 
             if 'umount_iso' in request.POST:
                 image = request.POST.get('path', '')
@@ -470,23 +565,67 @@ def instance(request, compute_id, vname):
                                                 new_compute.type)
                     conn_migrate.moveto(conn, vname, live, unsafe, xml_del)
                     conn_migrate.define_move(vname)
+                    instance.compute = new_compute
+                    instance.save()
                     conn_migrate.close()
                     msg = _("Migrate")
                     addlogmsg(request.user.username, instance.name, msg)
                     return HttpResponseRedirect(reverse('instance', args=[compute_id, vname]))
 
+                if 'change_network' in request.POST:
+                    network_data = {}
+
+                    for post in request.POST:
+                        if post.startswith('net-'):
+                            network_data[post] = request.POST.get(post, '')
+
+                    conn.change_network(network_data)
+                    msg = _("Edit network")
+                    addlogmsg(request.user.username, instance.name, msg)
+                    return HttpResponseRedirect(request.get_full_path() + '#network')
+
+                if 'change_options' in request.POST:
+                    instance.is_template = request.POST.get('is_template', False)
+                    instance.save()
+                    
+                    options = {}
+                    for post in request.POST:
+                        if post in ['title', 'description']:
+                            options[post] = request.POST.get(post, '')
+                    conn.set_options(options)
+                    
+                    msg = _("Edit options")
+                    addlogmsg(request.user.username, instance.name, msg)
+                    return HttpResponseRedirect(request.get_full_path() + '#options')
+
+            if request.user.is_superuser or request.user.userattributes.can_clone_instances:
                 if 'clone' in request.POST:
                     clone_data = {}
                     clone_data['name'] = request.POST.get('name', '')
 
-                    for post in request.POST:
-                        if 'disk' or 'meta' in post:
+                    disk_sum = sum([disk['size']>>30 for disk in disks])
+                    quota_msg = check_user_quota(1, vcpu, memory, disk_sum)
+                    check_instance = Instance.objects.filter(name=clone_data['name'])
+                    
+                    if not request.user.is_superuser and quota_msg:    
+                        msg = _("User %s quota reached, cannot create '%s'!" % (quota_msg, clone_data['name']))
+                        error_messages.append(msg)
+                    elif check_instance:
+                        msg = _("Instance '%s' already exists!" % clone_data['name'])
+                        error_messages.append(msg)
+                    else:
+                        for post in request.POST:
                             clone_data[post] = request.POST.get(post, '')
 
-                    conn.clone_instance(clone_data)
-                    msg = _("Clone")
-                    addlogmsg(request.user.username, instance.name, msg)
-                    return HttpResponseRedirect(reverse('instance', args=[compute_id, clone_data['name']]))
+                        new_uuid = conn.clone_instance(clone_data)
+                        new_instance = Instance(compute_id=compute_id, name=clone_data['name'], uuid=new_uuid)
+                        new_instance.save()
+                        userinstance = UserInstance(instance_id=new_instance.id, user_id=request.user.id, is_delete=True)
+                        userinstance.save()
+
+                        msg = _("Clone of '%s'" % instance.name)
+                        addlogmsg(request.user.username, new_instance.name, msg)
+                        return HttpResponseRedirect(reverse('instance', args=[compute_id, clone_data['name']]))
 
         conn.close()
 
@@ -497,15 +636,13 @@ def instance(request, compute_id, vname):
     return render(request, 'instance.html', locals())
 
 
+@login_required
 def inst_status(request, compute_id, vname):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('login'))
-
     compute = get_object_or_404(Compute, pk=compute_id)
     response = HttpResponse()
     response['Content-Type'] = "text/javascript"
@@ -524,15 +661,13 @@ def inst_status(request, compute_id, vname):
     return response
 
 
+@login_required
 def inst_graph(request, compute_id, vname):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('login'))
-
     datasets = {}
     json_blk = []
     datasets_blk = {}
@@ -632,3 +767,42 @@ def inst_graph(request, compute_id, vname):
 
     response.write(data)
     return response
+
+@login_required
+def guess_mac_address(request, vname):
+    dhcp_file = '/srv/webvirtcloud/dhcpd.conf'
+    data = { 'vname': vname, 'mac': '52:54:00:' }
+    if os.path.isfile(dhcp_file):
+        with open(dhcp_file, 'r') as f:
+            name_found = False
+            for line in f:
+                if "host %s." % vname in line:
+                    name_found = True
+                if name_found and "hardware ethernet" in line:
+                    data['mac'] = line.split(' ')[-1].strip().strip(';')
+                    break
+    return HttpResponse(json.dumps(data));
+
+@login_required
+def guess_clone_name(request):
+    dhcp_file = '/srv/webvirtcloud/dhcpd.conf'
+    prefix = settings.CLONE_INSTANCE_DEFAULT_PREFIX
+    if os.path.isfile(dhcp_file):
+        instance_names = [i.name for i in Instance.objects.filter(name__startswith=prefix)]
+        with open(dhcp_file, 'r') as f:
+            for line in f:
+                line = line.strip()
+                if "host %s" % prefix in line:
+                    fqdn = line.split(' ')[1]
+                    hostname = fqdn.split('.')[0]
+                    if hostname.startswith(prefix) and hostname not in instance_names:
+                        return HttpResponse(json.dumps({'name': hostname}))
+    return HttpResponse(json.dumps({}));
+
+@login_required
+def check_instance(request, vname):
+    check_instance = Instance.objects.filter(name=vname)
+    data = { 'vname': vname, 'exists': False }
+    if check_instance:
+        data['exists'] = True
+    return HttpResponse(json.dumps(data));
diff --git a/interfaces/views.py b/interfaces/views.py
index a889b27..921d0b8 100644
--- a/interfaces/views.py
+++ b/interfaces/views.py
@@ -1,21 +1,20 @@
 from django.shortcuts import render, get_object_or_404
 from django.http import HttpResponseRedirect
 from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
 from computes.models import Compute
 from interfaces.forms import AddInterface
 from vrtManager.interface import wvmInterface, wvmInterfaces
 from libvirt import libvirtError
 
 
+@login_required
 def interfaces(request, compute_id):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
@@ -57,15 +56,13 @@ def interfaces(request, compute_id):
     return render(request, 'interfaces.html', locals())
 
 
+@login_required
 def interface(request, compute_id, iface):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
diff --git a/logs/templates/paging.html b/logs/templates/paging.html
new file mode 100644
index 0000000..2cf8f48
--- /dev/null
+++ b/logs/templates/paging.html
@@ -0,0 +1,12 @@
+<center>
+    {% if page > 1 %}
+        <a href="{% url 'showlogspage' page|add:"-1" %}">&larr;</a>
+    {% else %}
+        &nbsp;
+    {% endif %}
+    {% if has_next_page %}
+    <a href="{% url 'showlogspage' page|add:"1" %}">&rarr;</a>
+    {% else %}
+        &nbsp;
+    {% endif %}
+</center>
diff --git a/logs/templates/showlogs.html b/logs/templates/showlogs.html
index 1aa98da..13d0e34 100644
--- a/logs/templates/showlogs.html
+++ b/logs/templates/showlogs.html
@@ -22,31 +22,33 @@
                             </div>
                         </div>
                     {% else %}
+                        {% include "paging.html" %}
                         <div class="table-responsive">
                             <table class="table table-bordered table-hover">
                                 <thead>
                                     <tr>
                                         <th>#</th>
+                                        <th>{% trans "Date" %}</th>
                                         <th>{% trans "User" %}</th>
                                         <th>{% trans "Instance" %}</th>
                                         <th>{% trans "Message" %}</th>
-                                        <th>{% trans "Date" %}</th>
                                         </tr>
                                 </thead>
                                 <tbody>
                                     {% for log in logs %}
                                         <tr>
-                                            <td>{{ forloop.counter }}</td>
+                                            <td>{{ log.id }}</td>
+                                            <td style="width:130px;">{{ log.date|date:"M d H:i:s" }}</td>
                                             <td>{{ log.user }}</a></td>
                                             <td>{{ log.instance }}</a></td>
                                             <td>{{ log.message }}</td>
-                                            <td style="width:130px;">{{ log.date|date:"M d H:i:s" }}</td>
                                         </tr>
                                     {% endfor %}
                                 </tbody>
                             </table>
                         </div>
+                        {% include "paging.html" %}
                     {% endif %}
                 </div>
             </div>
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/logs/urls.py b/logs/urls.py
new file mode 100644
index 0000000..e579387
--- /dev/null
+++ b/logs/urls.py
@@ -0,0 +1,7 @@
+from django.conf.urls import url
+from . import views
+
+urlpatterns = [
+    url(r'^$', views.showlogs, name='showlogs'),
+    url(r'^(?P<page>[0-9]+)/$', views.showlogs, name='showlogspage'),
+]
diff --git a/logs/views.py b/logs/views.py
index cb408ca..830925e 100644
--- a/logs/views.py
+++ b/logs/views.py
@@ -2,6 +2,7 @@ from django.shortcuts import render
 from django.http import HttpResponseRedirect
 from django.core.urlresolvers import reverse
 from logs.models import Logs
+from django.conf import settings
 
 
 def addlogmsg(user, instance, message):
@@ -13,7 +14,7 @@ def addlogmsg(user, instance, message):
     add_log_msg.save()
 
 
-def showlogs(request):
+def showlogs(request, page=1):
     """
     :param request:
     :return:
@@ -25,6 +26,11 @@ def showlogs(request):
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
-    logs = Logs.objects.all()
+    page = int(page)
+    limit_from = (page-1)*settings.LOGS_PER_PAGE
+    limit_to = page*settings.LOGS_PER_PAGE
+    logs = Logs.objects.all().order_by('-date')[limit_from:limit_to+1]
+    has_next_page = logs.count() > settings.LOGS_PER_PAGE
+    # TODO: remove last element from queryset, but do not affect database
 
     return render(request, 'showlogs.html', locals())
diff --git a/networks/views.py b/networks/views.py
index 01347db..24d6bc6 100644
--- a/networks/views.py
+++ b/networks/views.py
@@ -2,6 +2,7 @@ from django.shortcuts import render, get_object_or_404
 from django.http import HttpResponseRedirect
 from django.utils.translation import ugettext_lazy as _
 from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
 from computes.models import Compute
 from networks.forms import AddNetPool
 from vrtManager.network import wvmNetwork, wvmNetworks
@@ -9,15 +10,13 @@ from vrtManager.network import network_size
 from libvirt import libvirtError
 
 
+@login_required
 def networks(request, compute_id):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
@@ -60,15 +59,13 @@ def networks(request, compute_id):
     return render(request, 'networks.html', locals())
 
 
+@login_required
 def network(request, compute_id, pool):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
diff --git a/secrets/views.py b/secrets/views.py
index 5e6bf0e..90e5e36 100644
--- a/secrets/views.py
+++ b/secrets/views.py
@@ -1,21 +1,20 @@
 from django.shortcuts import render, get_object_or_404
 from django.http import HttpResponseRedirect
 from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
 from computes.models import Compute
 from secrets.forms import AddSecret
 from vrtManager.secrets import wvmSecrets
 from libvirt import libvirtError
 
 
+@login_required
 def secrets(request, compute_id):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
diff --git a/static/css/webvirtcloud.css b/static/css/webvirtcloud.css
index d7382f1..542e8b9 100644
--- a/static/css/webvirtcloud.css
+++ b/static/css/webvirtcloud.css
@@ -12,7 +12,7 @@ body {
 }
 
 .container {
-    max-width: 768px;
+    max-width: 900px;
 }
 
 .page-header {
@@ -132,4 +132,4 @@ p {
 .keyselect {
     display: inline;
     min-width: 250px;
-}
\ No newline at end of file
+}
diff --git a/static/js/js.cookie.js b/static/js/js.cookie.js
new file mode 100644
index 0000000..d4232b9
--- /dev/null
+++ b/static/js/js.cookie.js
@@ -0,0 +1,151 @@
+/*!
+ * JavaScript Cookie v2.1.1
+ * https://github.com/js-cookie/js-cookie
+ *
+ * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
+ * Released under the MIT license
+ */
+;(function (factory) {
+	if (typeof define === 'function' && define.amd) {
+		define(factory);
+	} else if (typeof exports === 'object') {
+		module.exports = factory();
+	} else {
+		var OldCookies = window.Cookies;
+		var api = window.Cookies = factory();
+		api.noConflict = function () {
+			window.Cookies = OldCookies;
+			return api;
+		};
+	}
+}(function () {
+	function extend () {
+		var i = 0;
+		var result = {};
+		for (; i < arguments.length; i++) {
+			var attributes = arguments[ i ];
+			for (var key in attributes) {
+				result[key] = attributes[key];
+			}
+		}
+		return result;
+	}
+
+	function init (converter) {
+		function api (key, value, attributes) {
+			var result;
+			if (typeof document === 'undefined') {
+				return;
+			}
+
+			// Write
+
+			if (arguments.length > 1) {
+				attributes = extend({
+					path: '/'
+				}, api.defaults, attributes);
+
+				if (typeof attributes.expires === 'number') {
+					var expires = new Date();
+					expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
+					attributes.expires = expires;
+				}
+
+				try {
+					result = JSON.stringify(value);
+					if (/^[\{\[]/.test(result)) {
+						value = result;
+					}
+				} catch (e) {}
+
+				if (!converter.write) {
+					value = encodeURIComponent(String(value))
+						.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
+				} else {
+					value = converter.write(value, key);
+				}
+
+				key = encodeURIComponent(String(key));
+				key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
+				key = key.replace(/[\(\)]/g, escape);
+
+				return (document.cookie = [
+					key, '=', value,
+					attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE
+					attributes.path    && '; path=' + attributes.path,
+					attributes.domain  && '; domain=' + attributes.domain,
+					attributes.secure ? '; secure' : ''
+				].join(''));
+			}
+
+			// Read
+
+			if (!key) {
+				result = {};
+			}
+
+			// To prevent the for loop in the first place assign an empty array
+			// in case there are no cookies at all. Also prevents odd result when
+			// calling "get()"
+			var cookies = document.cookie ? document.cookie.split('; ') : [];
+			var rdecode = /(%[0-9A-Z]{2})+/g;
+			var i = 0;
+
+			for (; i < cookies.length; i++) {
+				var parts = cookies[i].split('=');
+				var name = parts[0].replace(rdecode, decodeURIComponent);
+				var cookie = parts.slice(1).join('=');
+
+				if (cookie.charAt(0) === '"') {
+					cookie = cookie.slice(1, -1);
+				}
+
+				try {
+					cookie = converter.read ?
+						converter.read(cookie, name) : converter(cookie, name) ||
+						cookie.replace(rdecode, decodeURIComponent);
+
+					if (this.json) {
+						try {
+							cookie = JSON.parse(cookie);
+						} catch (e) {}
+					}
+
+					if (key === name) {
+						result = cookie;
+						break;
+					}
+
+					if (!key) {
+						result[name] = cookie;
+					}
+				} catch (e) {}
+			}
+
+			return result;
+		}
+
+		api.set = api;
+		api.get = function (key) {
+			return api(key);
+		};
+		api.getJSON = function () {
+			return api.apply({
+				json: true
+			}, [].slice.call(arguments));
+		};
+		api.defaults = {};
+
+		api.remove = function (key, attributes) {
+			api(key, '', extend(attributes, {
+				expires: -1
+			}));
+		};
+
+		api.withConverter = init;
+
+		return api;
+	}
+
+	return init(function () {});
+}));
diff --git a/storages/views.py b/storages/views.py
index 499d8b3..d3f1965 100644
--- a/storages/views.py
+++ b/storages/views.py
@@ -2,21 +2,20 @@ from django.shortcuts import render, get_object_or_404
 from django.http import HttpResponseRedirect
 from django.utils.translation import ugettext_lazy as _
 from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
 from computes.models import Compute
 from storages.forms import AddStgPool, AddImage, CloneImage
 from vrtManager.storage import wvmStorage, wvmStorages
 from libvirt import libvirtError
 
 
+@login_required
 def storages(request, compute_id):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
@@ -68,15 +67,13 @@ def storages(request, compute_id):
     return render(request, 'storages.html', locals())
 
 
+@login_required
 def storage(request, compute_id, pool):
     """
     :param request:
     :return:
     """
 
-    if not request.user.is_authenticated():
-        return HttpResponseRedirect(reverse('index'))
-
     if not request.user.is_superuser:
         return HttpResponseRedirect(reverse('index'))
 
diff --git a/templates/base.html b/templates/base.html
index e9f4505..cbdd75a 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -48,6 +48,8 @@
     <script src="{% static "js/jquery.js" %}"></script>
     <!-- Bootstrap Core JavaScript -->
     <script src="{% static "js/bootstrap.min.js" %}"></script>
+    <!-- JavaScript Cookie -->
+    <script src="{% static "js/js.cookie.js" %}"></script>
     {% block script %}{% endblock %}
   </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/templates/pleasewaitdialog.html b/templates/pleasewaitdialog.html
new file mode 100644
index 0000000..49c893b
--- /dev/null
+++ b/templates/pleasewaitdialog.html
@@ -0,0 +1,25 @@
+{% load i18n %}
+    <!-- Please wait dialog -->
+    <div class="modal fade" id="pleaseWaitDialog" tabindex="-1" role="dialog" aria-labelledby="pleaseWaitDialogLabel" data-backdrop="static" data-keyboard="false">
+        <div class="modal-dialog modal-sm">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h4 class="modal-title">{% trans "Processing" %}...</h4>
+                </div>
+                <div class="modal-body">
+                    <div class="progress">
+                        <div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="10" aria-valuemin="0" aria-valuemax="10" style="width:100%">
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+<script>
+function showPleaseWaitDialog() {
+    $('#pleaseWaitDialog').modal();
+}
+function hidePleaseWaitDialog() {
+    $('#pleaseWaitDialog').modal('hide');
+}
+</script>
diff --git a/vrtManager/connection.py b/vrtManager/connection.py
index fd9fb80..c62c6e4 100644
--- a/vrtManager/connection.py
+++ b/vrtManager/connection.py
@@ -442,7 +442,16 @@ class wvmConnect(object):
                 vcpu = cur_vcpu
             else:
                 vcpu = util.get_xml_path(dom.XMLDesc(0), "/domain/vcpu")
-            vname[dom.name()] = {'status': dom.info()[0], 'uuid': dom.UUIDString(), 'vcpu': vcpu, 'memory': mem}
+            title = util.get_xml_path(dom.XMLDesc(0), "/domain/title")
+            description = util.get_xml_path(dom.XMLDesc(0), "/domain/description")
+            vname[dom.name()] = {
+                'status': dom.info()[0],
+                'uuid': dom.UUIDString(),
+                'vcpu': vcpu,
+                'memory': mem,
+                'title': title if title else '',
+                'description': description if description else '',
+            }
         return vname
 
     def get_user_instances(self, name):
@@ -454,7 +463,17 @@ class wvmConnect(object):
             vcpu = cur_vcpu
         else:
             vcpu = util.get_xml_path(dom.XMLDesc(0), "/domain/vcpu")
-        return {'name': dom.name(), 'status': dom.info()[0], 'uuid': dom.UUIDString(), 'vcpu': vcpu, 'memory': mem}
+        title = util.get_xml_path(dom.XMLDesc(0), "/domain/title")
+        description = util.get_xml_path(dom.XMLDesc(0), "/domain/description")
+        return {
+            'name': dom.name(),
+            'status': dom.info()[0],
+            'uuid': dom.UUIDString(),
+            'vcpu': vcpu,
+            'memory': mem,
+            'title': title if title else '',
+            'description': description if description else '',
+        }
 
     def close(self):
         """Close connection"""
diff --git a/vrtManager/create.py b/vrtManager/create.py
index 1d6d9e7..15f1cd8 100644
--- a/vrtManager/create.py
+++ b/vrtManager/create.py
@@ -220,7 +220,8 @@ class wvmCreate(wvmConnect):
             xml += """<interface type='network'>"""
             if mac:
                 xml += """<mac address='%s'/>""" % mac
-            xml += """<source network='%s'/>""" % net
+            xml += """<source network='%s'/>
+                      <filterref filter='clean-traffic'/>""" % net
             if virtio:
                 xml += """<model type='virtio'/>"""
             xml += """</interface>"""
diff --git a/vrtManager/instance.py b/vrtManager/instance.py
index 0f3b258..3c287e0 100644
--- a/vrtManager/instance.py
+++ b/vrtManager/instance.py
@@ -8,6 +8,7 @@ from vrtManager import util
 from xml.etree import ElementTree
 from datetime import datetime
 from vrtManager.connection import wvmConnect
+from vrtManager.storage import wvmStorage
 from webvirtcloud.settings import QEMU_CONSOLE_TYPES
 
 
@@ -184,8 +185,13 @@ class wvmInstance(wvmConnect):
         mem = util.get_xml_path(self._XMLDesc(0), "/domain/currentMemory")
         return int(mem) / 1024
 
+    def get_title(self):
+        title = util.get_xml_path(self._XMLDesc(0), "/domain/title")
+        return title if title else ''
+
     def get_description(self):
-        return util.get_xml_path(self._XMLDesc(0), "/domain/description")
+        description = util.get_xml_path(self._XMLDesc(0), "/domain/description")
+        return description if description else ''
 
     def get_max_memory(self):
         return self.wvm.getInfo()[1] * 1048576
@@ -523,7 +529,7 @@ class wvmInstance(wvmConnect):
         return util.get_xml_path(self._XMLDesc(VIR_DOMAIN_XML_SECURE),
                                  "/domain/devices/graphics/@keymap") or ''
 
-    def resize(self, cur_memory, memory, cur_vcpu, vcpu):
+    def resize(self, cur_memory, memory, cur_vcpu, vcpu, disks=[]):
         """
         Function change ram and cpu on vds.
         """
@@ -541,6 +547,11 @@ class wvmInstance(wvmConnect):
         set_vcpu.text = vcpu
         set_vcpu.set('current', cur_vcpu)
 
+        for disk in disks:
+            source_dev = disk['path']
+            vol = self.get_volume_by_path(source_dev)
+            vol.resize(disk['size_new'])
+        
         new_xml = ElementTree.tostring(tree)
         self._defineXML(new_xml)
 
@@ -598,6 +609,22 @@ class wvmInstance(wvmConnect):
     def get_managed_save_image(self):
         return self.instance.hasManagedSaveImage(0)
 
+    def get_wvmStorage(self, pool):
+        storage = wvmStorage(self.host,
+                             self.login,
+                             self.passwd,
+                             self.conn,
+                             pool)
+        return storage
+
+    def fix_mac(self, mac):
+        if ":" in mac:
+            return mac
+        # if mac does not contain ":", try to split into tuples and join with ":"
+        n = 2
+        mac_tuples = [mac[i:i+n] for i in range(0, len(mac), n)]
+        return ':'.join(mac_tuples)
+
     def clone_instance(self, clone_data):
         clone_dev_path = []
 
@@ -610,7 +637,8 @@ class wvmInstance(wvmConnect):
 
         for num, net in enumerate(tree.findall('devices/interface')):
             elm = net.find('mac')
-            elm.set('address', clone_data['net-' + str(num)])
+            mac_address = self.fix_mac(clone_data['clone-net-mac-' + str(num)])
+            elm.set('address', mac_address)
 
         for disk in tree.findall('devices/disk'):
             if disk.get('device') == 'disk':
@@ -649,5 +677,65 @@ class wvmInstance(wvmConnect):
                                     </volume>""" % (target_file, vol_format)
                     stg = vol.storagePoolLookupByVolume()
                     stg.createXMLFrom(vol_clone_xml, vol, meta_prealloc)
+                
+                source_dev = elm.get('dev')
+                if source_dev:
+                    clone_path = os.path.join(os.path.dirname(source_dev), target_file)
+                    elm.set('dev', clone_path)
+                    
+                    vol = self.get_volume_by_path(source_dev)
+                    stg = vol.storagePoolLookupByVolume()
+                    
+                    vol_name = util.get_xml_path(vol.XMLDesc(0), "/volume/name")
+                    pool_name = util.get_xml_path(stg.XMLDesc(0), "/pool/name")
+                    
+                    storage = self.get_wvmStorage(pool_name)
+                    storage.clone_volume(vol_name, target_file)
 
+        options = {
+            'title': clone_data.get('clone-title', ''),
+            'description': clone_data.get('clone-description', ''),
+        }
+        self._set_options(tree, options)
         self._defineXML(ElementTree.tostring(tree))
+
+        return self.get_instance(clone_data['name']).UUIDString()
+
+    def change_network(self, network_data):
+        xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE)
+        tree = ElementTree.fromstring(xml)
+
+        for num, interface in enumerate(tree.findall('devices/interface')):
+            if interface.get('type') == 'bridge':
+                source = interface.find('mac')
+                source.set('address', network_data['net-mac-' + str(num)])
+                source = interface.find('source')
+                source.set('bridge', network_data['net-source-' + str(num)])
+
+        new_xml = ElementTree.tostring(tree)
+        self._defineXML(new_xml)
+
+    def _set_options(self, tree, options):
+        for o in ['title', 'description']:
+            option = tree.find(o)
+            option_value = options.get(o, '').strip()
+            if not option_value:
+                if not option is None:
+                    tree.remove(option)
+            else:
+                if option is None:
+                    option = ElementTree.SubElement(tree, o)
+                option.text = option_value
+
+    def set_options(self, options):
+        """
+        Function change description, title
+        """
+        xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE)
+        tree = ElementTree.fromstring(xml)
+
+        self._set_options(tree, options)
+
+        new_xml = ElementTree.tostring(tree)
+        self._defineXML(new_xml)
+
diff --git a/webvirtcloud/settings.py b/webvirtcloud/settings.py
index a163fa3..0c31433 100644
--- a/webvirtcloud/settings.py
+++ b/webvirtcloud/settings.py
@@ -8,7 +8,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(__file__))
 
 SECRET_KEY = '4y(f4rfqc6f2!i8_vfuu)kav6tdv5#sc=n%o451dm+th0&3uci'
 
-DEBUG = False
+DEBUG = True 
 
 TEMPLATE_DEBUG = DEBUG
 
@@ -38,11 +38,19 @@ MIDDLEWARE_CLASSES = (
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.auth.middleware.RemoteUserMiddleware',
     'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 )
 
+AUTHENTICATION_BACKENDS = (
+    'django.contrib.auth.backends.RemoteUserBackend',
+    #'accounts.backends.MyRemoteUserBackend',
+)
+
+LOGIN_URL = '/accounts/login'
+
 ROOT_URLCONF = 'webvirtcloud.urls'
 
 WSGI_APPLICATION = 'webvirtcloud.wsgi.application'
@@ -103,3 +111,9 @@ QEMU_KEYMAPS = ['ar', 'da', 'de', 'de-ch', 'en-gb', 'en-us', 'es', 'et', 'fi',
 # keepalive interval and count for libvirt connections
 LIBVIRT_KEEPALIVE_INTERVAL = 5
 LIBVIRT_KEEPALIVE_COUNT = 5
+
+ALLOW_INSTANCE_MULTIPLE_OWNER = True
+CLONE_INSTANCE_DEFAULT_PREFIX = 'ourea'
+LOGS_PER_PAGE = 100
+QUOTA_DEBUG = True
+ALLOW_EMPTY_PASSWORD = True
diff --git a/webvirtcloud/urls.py b/webvirtcloud/urls.py
index 0eff1a5..8cfa9d9 100644
--- a/webvirtcloud/urls.py
+++ b/webvirtcloud/urls.py
@@ -8,6 +8,7 @@ urlpatterns = patterns('',
     url(r'^instance/', include('instances.urls')),
     url(r'^accounts/', include('accounts.urls')),
     url(r'^computes/', include('computes.urls')),
+    url(r'^logs/', include('logs.urls')),
 
     url(r'^compute/(?P<compute_id>[0-9]+)/storages/$',
         'storages.views.storages', name='storages'),
@@ -27,6 +28,5 @@ urlpatterns = patterns('',
         'create.views.create_instance', name='create_instance'),
 
     url(r'^console/$', 'console.views.console', name='console'),
-    url(r'^logs/$', 'logs.views.showlogs', name='showlogs'),
     # (r'^admin/', include(admin.site.urls)),
 )
diff --git a/webvirtcloud/wsgi.py b/webvirtcloud/wsgi.py
index 35ceb9b..a9bf44c 100644
--- a/webvirtcloud/wsgi.py
+++ b/webvirtcloud/wsgi.py
@@ -7,7 +7,10 @@ For more information on this file, see
 https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
 """
 
-import os
+execfile('/srv/webvirtcloud/venv/bin/activate_this.py', dict(__file__='/srv/webvirtcloud/venv/bin/activate_this.py'))
+
+import os, sys
+sys.path.append('/srv/webvirtcloud')
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "webvirtcloud.settings")
 
 from django.core.wsgi import get_wsgi_application