Commit 11c3e46a by Kálmán Viktor

dashboard: resize request and how-to initial

parent c85651ea
...@@ -25,7 +25,7 @@ from django.shortcuts import redirect ...@@ -25,7 +25,7 @@ from django.shortcuts import redirect
from circle.settings.base import get_env_variable from circle.settings.base import get_env_variable
from dashboard.views import circle_login, HelpView from dashboard.views import circle_login, HelpView, ResizeHelpView
from dashboard.forms import CirclePasswordResetForm, CircleSetPasswordForm from dashboard.forms import CirclePasswordResetForm, CircleSetPasswordForm
from firewall.views import add_blacklist_item from firewall.views import add_blacklist_item
...@@ -65,6 +65,7 @@ urlpatterns = patterns( ...@@ -65,6 +65,7 @@ urlpatterns = patterns(
url(r'^info/support/$', url(r'^info/support/$',
TemplateView.as_view(template_name="info/support.html"), TemplateView.as_view(template_name="info/support.html"),
name="info.support"), name="info.support"),
url(r'^info/resize-how-to/$', ResizeHelpView.as_view(), name="info.resize"),
) )
......
...@@ -4,24 +4,27 @@ ...@@ -4,24 +4,27 @@
<i class="fa fa-file"></i> <i class="fa fa-file"></i>
{{ d.name }} (#{{ d.id }}) - {{ d.size|filesize }} {{ d.name }} (#{{ d.id }}) - {{ d.size|filesize }}
{% if op.remove_disk %}
<span class="operation-wrapper"> <span class="operation-wrapper pull-right">
<a href="{{ op.remove_disk.get_url }}?disk={{d.pk}}" {% if op.resize_disk %}
class="btn btn-xs btn-{{ op.remove_disk.effect}} pull-right operation disk-remove-btn
{% if op.remove_disk.disabled %}disabled{% endif %}">
<i class="fa fa-{{ op.remove_disk.icon }} fa-fw-12"></i> {% trans "Remove" %}
</a>
</span>
{% endif %}
{% if op.resize_disk %}
<span class="operation-wrapper">
<a href="{{ op.resize_disk.get_url }}?disk={{d.pk}}" <a href="{{ op.resize_disk.get_url }}?disk={{d.pk}}"
class="btn btn-xs btn-{{ op.resize_disk.effect }} pull-right operation disk-resize-btn class="btn btn-xs btn-{{ op.resize_disk.effect }} operation disk-resize-btn
{% if op.resize_disk.disabled %}disabled{% endif %}"> {% if op.resize_disk.disabled %}disabled{% endif %}">
<i class="fa fa-{{ op.resize_disk.icon }} fa-fw-12"></i> {% trans "Resize" %} <i class="fa fa-{{ op.resize_disk.icon }} fa-fw-12"></i> {% trans "Resize" %}
</a> </a>
</span> {% else %}
{% endif %} <a href="{% url "request.views.request-resize" vm_pk=instance.pk disk_pk=d.pk %}" class="btn btn-xs btn-primary operation">
<i class="fa fa-arrows-alt fa-fw-12"></i> {% trans "Request resize" %}
</a>
{% endif %}
{% if op.remove_disk %}
<a href="{{ op.remove_disk.get_url }}?disk={{d.pk}}"
class="btn btn-xs btn-{{ op.remove_disk.effect}} operation disk-remove-btn
{% if op.remove_disk.disabled %}disabled{% endif %}">
<i class="fa fa-{{ op.remove_disk.icon }} fa-fw-12"></i> {% trans "Remove" %}
</a>
{% endif %}
</span>
<div style="clear: both;"></div> <div style="clear: both;"></div>
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
......
...@@ -136,6 +136,10 @@ class HelpView(TemplateView): ...@@ -136,6 +136,10 @@ class HelpView(TemplateView):
return ctx return ctx
class ResizeHelpView(TemplateView):
template_name = "info/resize.html"
class OpenSearchDescriptionView(TemplateView): class OpenSearchDescriptionView(TemplateView):
template_name = "dashboard/vm-opensearch.xml" template_name = "dashboard/vm-opensearch.xml"
content_type = "application/opensearchdescription+xml" content_type = "application/opensearchdescription+xml"
......
...@@ -22,6 +22,8 @@ from django.utils.translation import ugettext_lazy as _ ...@@ -22,6 +22,8 @@ from django.utils.translation import ugettext_lazy as _
from django.template import RequestContext from django.template import RequestContext
from django.template.loader import render_to_string from django.template.loader import render_to_string
from sizefield.widgets import FileSizeWidget
from sizefield.utils import filesizeformat
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit from crispy_forms.layout import Submit
...@@ -70,34 +72,32 @@ class InitialFromFileMixin(object): ...@@ -70,34 +72,32 @@ class InitialFromFileMixin(object):
RequestContext(request, {}), RequestContext(request, {}),
) )
def clean(self): def clean_message(self):
cleaned_data = super(InitialFromFileMixin, self).clean() message = self.cleaned_data['message']
if cleaned_data['message'].strip() == self.initial['message'].strip(): if message.strip() == self.initial['message'].strip():
raise ValidationError( raise ValidationError(_("Fill in the message."), code="invalid")
_("Fill in the message."), return message.strip()
code="invalid")
return cleaned_data
class TemplateRequestForm(InitialFromFileMixin, Form): class TemplateRequestForm(InitialFromFileMixin, Form):
message = CharField(widget=Textarea, label=_("Message"))
template = ModelChoiceField(TemplateAccessType.objects.all(), template = ModelChoiceField(TemplateAccessType.objects.all(),
label=_("Template share")) label=_("Template share"))
level = ChoiceField(TemplateAccessAction.LEVELS, widget=RadioSelect, level = ChoiceField(TemplateAccessAction.LEVELS, widget=RadioSelect,
initial=TemplateAccessAction.LEVELS.user) initial=TemplateAccessAction.LEVELS.user)
message = CharField(widget=Textarea, label=_("Message"))
initial_template = "request/initials/template.html" initial_template = "request/initials/template.html"
class LeaseRequestForm(InitialFromFileMixin, Form): class LeaseRequestForm(InitialFromFileMixin, Form):
lease = ModelChoiceField(LeaseType.objects.all(), label=_("Lease")) lease = ModelChoiceField(LeaseType.objects.all(), label=_("Lease"))
message = CharField(widget=Textarea) message = CharField(widget=Textarea, label=_("Message"))
initial_template = "request/initials/lease.html" initial_template = "request/initials/lease.html"
class ResourceRequestForm(InitialFromFileMixin, VmResourcesForm): class ResourceRequestForm(InitialFromFileMixin, VmResourcesForm):
message = CharField(widget=Textarea) message = CharField(widget=Textarea, label=_("Message"))
initial_template = "request/initials/resources.html" initial_template = "request/initials/resources.html"
...@@ -110,3 +110,28 @@ class ResourceRequestForm(InitialFromFileMixin, VmResourcesForm): ...@@ -110,3 +110,28 @@ class ResourceRequestForm(InitialFromFileMixin, VmResourcesForm):
raise ValidationError( raise ValidationError(
_("You haven't changed any of the resources."), _("You haven't changed any of the resources."),
code="invalid") code="invalid")
class ResizeRequestForm(InitialFromFileMixin, Form):
message = CharField(widget=Textarea, label=_("Message"))
size = CharField(widget=FileSizeWidget, label=_('Size'),
help_text=_('Size to resize the disk in bytes or with'
' units like MB or GB.'))
initial_template = "request/initials/resize.html"
def __init__(self, *args, **kwargs):
self.disk = kwargs.pop("disk")
super(ResizeRequestForm, self).__init__(*args, **kwargs)
def clean_size(self):
cleaned_data = super(ResizeRequestForm, self).clean()
disk = self.disk
size_in_bytes = cleaned_data.get("size")
if not size_in_bytes.isdigit() and len(size_in_bytes) > 0:
raise ValidationError(_("Invalid format, you can use GB or MB!"))
if int(size_in_bytes) < int(disk.size):
raise ValidationError(_("Disk size must be greater than the actual"
"size (%s).") % filesizeformat(disk.size))
return size_in_bytes
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import sizefield.models
class Migration(migrations.Migration):
dependencies = [
('vm', '0002_interface_model'),
('storage', '0002_disk_bus'),
('request', '0003_auto_20150410_1917'),
]
operations = [
migrations.CreateModel(
name='DiskResizeAction',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('size', sizefield.models.FileSizeField(default=None, null=True)),
('disk', models.ForeignKey(to='storage.Disk')),
('instance', models.ForeignKey(to='vm.Instance')),
],
options={
'abstract': False,
},
),
migrations.AlterField(
model_name='request',
name='type',
field=models.CharField(max_length=10, choices=[(b'resource', 'resource request'), (b'lease', 'lease request'), (b'template', 'template access request'), (b'resize', 'disk resize request')]),
),
]
...@@ -32,10 +32,12 @@ from django.utils.translation import ( ...@@ -32,10 +32,12 @@ from django.utils.translation import (
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
import requests import requests
from sizefield.models import FileSizeField
from model_utils.models import TimeStampedModel from model_utils.models import TimeStampedModel
from model_utils import Choices from model_utils import Choices
from vm.models import Instance, InstanceTemplate, Lease from vm.models import Instance, InstanceTemplate, Lease
from storage.models import Disk
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -77,6 +79,7 @@ class Request(TimeStampedModel): ...@@ -77,6 +79,7 @@ class Request(TimeStampedModel):
('resource', _('resource request')), ('resource', _('resource request')),
('lease', _("lease request")), ('lease', _("lease request")),
('template', _("template access request")), ('template', _("template access request")),
('resize', _("disk resize request")),
) )
type = CharField(choices=TYPES, max_length=10) type = CharField(choices=TYPES, max_length=10)
message = TextField(verbose_name=_("Message")) message = TextField(verbose_name=_("Message"))
...@@ -99,7 +102,8 @@ class Request(TimeStampedModel): ...@@ -99,7 +102,8 @@ class Request(TimeStampedModel):
return { return {
'resource': "tasks", 'resource': "tasks",
'lease': "clock-o", 'lease': "clock-o",
'template': "puzzle-piece" 'template': "puzzle-piece",
'resize': "arrows-alt",
}.get(self.type) }.get(self.type)
def get_effect(self): def get_effect(self):
...@@ -246,6 +250,26 @@ class TemplateAccessAction(RequestAction): ...@@ -246,6 +250,26 @@ class TemplateAccessAction(RequestAction):
) % ", ".join([x.name for x in self.template_type.templates.all()]) ) % ", ".join([x.name for x in self.template_type.templates.all()])
class DiskResizeAction(RequestAction):
instance = ForeignKey(Instance)
disk = ForeignKey(Disk)
size = FileSizeField(null=True, default=None)
def get_readable_level(self):
return self.LEVELS[self.level]
def accept(self, user):
pass
@property
def accept_msg(self):
return ungettext(
"You got access to the following template: %s",
"You got access to the following templates: %s",
self.template_type.templates.count()
) % ", ".join([x.name for x in self.template_type.templates.all()])
def send_notifications(sender, instance, created, **kwargs): def send_notifications(sender, instance, created, **kwargs):
if not created: if not created:
return return
......
{% load i18n %}
{% load crispy_forms_tags %}
{% load sizefieldtags %}
<dl>
<dt>{% trans "Virtual machine" %}</dt>
<dd><a href="{{ vm.get_absolute_url }}">{{ vm.name }}</a></dd>
<dt>{% trans "Disk" %}</dt>
<dd>
{% if request.user.is_superuser %}
<a href="{{ disk.get_absolute_url }}">{{ disk.name }} (#{{ disk.id }})</a>
{% else %}
{{ disk.name }} (#{{ disk.id }})
{% endif %}
- {{ disk.size|filesize }}
</dd>
</dl>
<form action="{% url "request.views.request-resize" vm_pk=vm.pk disk_pk=disk.pk %}" method="POST">
{% include "display-form-errors.html" %}
{% csrf_token %}
{{ form.size|as_crispy_field }}
{{ form.message|as_crispy_field }}
<input type="submit" class="btn btn-primary" id="op-form-send"/>
</form>
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
{% load i18n %} {% load i18n %}
{% load render_table from django_tables2 %} {% load render_table from django_tables2 %}
{% load arrowfilter %} {% load arrowfilter %}
{% load sizefieldtags %}
{% block title-page %}{% trans "Request" %}{% endblock %} {% block title-page %}{% trans "Request" %}{% endblock %}
...@@ -85,8 +86,29 @@ ...@@ -85,8 +86,29 @@
<dt>{% trans "Ram size" %}</dt> <dt>{% trans "Ram size" %}</dt>
<dd>{{ action.ram_size }} ({{ action.instance.ram_size }}) MiB</dd> <dd>{{ action.ram_size }} ({{ action.instance.ram_size }}) MiB</dd>
</dl> </dl>
{% elif object.type == "resize" %}
<dl>
<dt>{% trans "VM name" %}</dt>
<dd><a href="{{ action.instance.get_absolute_url }}">{{ action.instance.name }}</a></dd>
<dt>{% trans "VM description" %}</dt>
<dd>{{ action.instance.description|default:"-" }}</dd>
<dt>{% trans "Disk" %}</dt>
<dd>
{% if request.user.is_superuser %}
<a href="{{ action.disk.get_absolute_url }}">
{{ action.disk.name }} (#{{ action.disk.id}})
</a>
{% else %}
{{ action.disk.name }} (#{{ action.disk.id}})</dd>
{% endif %}
</dd>
<dt>{% trans "Current size" %}</dt>
<dd>{{ action.disk.size|filesize}} ({{ action.disk.size }} bytes)</dd>
<dt>{% trans "Requested size" %}</dt>
<dd>{{ action.size|filesize}} ({{ action.size }} bytes)</dd>
</dl>
{% else %} {% else %}
hacks!!! Are you adding a new action type?
{% endif %} {% endif %}
{% if object.status == "PENDING" and request.user.is_superuser %} {% if object.status == "PENDING" and request.user.is_superuser %}
......
{% spaceless %}
{% if LANGUAGE_CODE == "en" %}
Why do you need bigger disk?
{% else %} {# place your translations here #}
Why do you need bigger disk?
{% endif %}
{% endspaceless %}
...@@ -23,7 +23,7 @@ from .views import ( ...@@ -23,7 +23,7 @@ from .views import (
LeaseTypeCreate, LeaseTypeDetail, LeaseTypeCreate, LeaseTypeDetail,
TemplateAccessTypeCreate, TemplateAccessTypeDetail, TemplateAccessTypeCreate, TemplateAccessTypeDetail,
TemplateRequestView, LeaseRequestView, ResourceRequestView, TemplateRequestView, LeaseRequestView, ResourceRequestView,
LeaseTypeDelete, TemplateAccessTypeDelete, LeaseTypeDelete, TemplateAccessTypeDelete, ResizeRequestView,
) )
urlpatterns = patterns( urlpatterns = patterns(
...@@ -60,4 +60,6 @@ urlpatterns = patterns( ...@@ -60,4 +60,6 @@ urlpatterns = patterns(
name="request.views.request-lease"), name="request.views.request-lease"),
url(r'resource/(?P<vm_pk>\d+)/$', ResourceRequestView.as_view(), url(r'resource/(?P<vm_pk>\d+)/$', ResourceRequestView.as_view(),
name="request.views.request-resource"), name="request.views.request-resource"),
url(r'resize/(?P<vm_pk>\d+)/(?P<disk_pk>\d+)/$',
ResizeRequestView.as_view(), name="request.views.request-resize"),
) )
...@@ -30,8 +30,9 @@ from django_tables2 import SingleTableView ...@@ -30,8 +30,9 @@ from django_tables2 import SingleTableView
from request.models import ( from request.models import (
Request, TemplateAccessType, LeaseType, TemplateAccessAction, Request, TemplateAccessType, LeaseType, TemplateAccessAction,
ExtendLeaseAction, ResourceChangeAction, ExtendLeaseAction, ResourceChangeAction, DiskResizeAction
) )
from storage.models import Disk
from vm.models import Instance from vm.models import Instance
from vm.operations import ResourcesOperation from vm.operations import ResourcesOperation
from request.tables import ( from request.tables import (
...@@ -39,7 +40,7 @@ from request.tables import ( ...@@ -39,7 +40,7 @@ from request.tables import (
) )
from request.forms import ( from request.forms import (
LeaseTypeForm, TemplateAccessTypeForm, TemplateRequestForm, LeaseTypeForm, TemplateAccessTypeForm, TemplateRequestForm,
LeaseRequestForm, ResourceRequestForm, LeaseRequestForm, ResourceRequestForm, ResizeRequestForm,
) )
...@@ -288,3 +289,50 @@ class ResourceRequestView(VmRequestMixin, FormView): ...@@ -288,3 +289,50 @@ class ResourceRequestView(VmRequestMixin, FormView):
req.save() req.save()
return redirect(vm.get_absolute_url()) return redirect(vm.get_absolute_url())
class ResizeRequestView(VmRequestMixin, FormView):
form_class = ResizeRequestForm
template_name = "request/_request-resize-form.html"
user_level = "owner"
def get_disk(self, *args, **kwargs):
return get_object_or_404(Disk, pk=self.kwargs['disk_pk'])
def get_form_kwargs(self):
kwargs = super(ResizeRequestView, self).get_form_kwargs()
kwargs['disk'] = self.get_disk()
return kwargs
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/_modal.html']
else:
return ['dashboard/_base.html']
def get_context_data(self, **kwargs):
context = super(ResizeRequestView, self).get_context_data(**kwargs)
context['disk'] = self.get_disk()
context['template'] = self.template_name
context['box_title'] = context['title'] = _("Disk resize request")
context['ajax_title'] = True
return context
def form_valid(self, form):
vm = self.get_vm()
disk = self.get_disk()
data = form.cleaned_data
user = self.request.user
dra = DiskResizeAction(instance=vm, disk=disk, size=data['size'])
dra.save()
req = Request(
user=user,
message=data['message'],
type=Request.TYPES.resize,
action=dra
)
req.save()
return redirect(vm.get_absolute_url())
...@@ -28,6 +28,7 @@ from celery.contrib.abortable import AbortableAsyncResult ...@@ -28,6 +28,7 @@ from celery.contrib.abortable import AbortableAsyncResult
from django.db.models import (Model, BooleanField, CharField, DateTimeField, from django.db.models import (Model, BooleanField, CharField, DateTimeField,
ForeignKey) ForeignKey)
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _, ugettext_noop from django.utils.translation import ugettext_lazy as _, ugettext_noop
from model_utils.models import TimeStampedModel from model_utils.models import TimeStampedModel
...@@ -535,3 +536,6 @@ class Disk(TimeStampedModel): ...@@ -535,3 +536,6 @@ class Disk(TimeStampedModel):
disk.is_ready = True disk.is_ready = True
disk.save() disk.save()
return disk return disk
def get_absolute_url(self):
return reverse('dashboard.views.disk-detail', kwargs={'pk': self.pk})
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load i18n %}
{% block title-page %}{% trans "Resize how-to" %}{% endblock %}
{% block content %}
<div class="row" id="resize-help">
<div class="col-lg-12">
<style>
#resize-help table {
background-color: #f5f5f5;
}
#resize-help .panel {
padding: 2px 20px;
background-color: #f5f5f5;
margin: 20px 0px;
}
#resize-help ol li {
margin-top: 15px;
}
#resize-help img {
display: block;
margin: 15px 0 5px 0;
}
#resize-help pre {
margin-top: 5px;
}
</style>
<div class="page-header">
<h1 id="disk-linux">
<i class="fa fa-linux"></i>
{% trans "Expanding disk on Linux" %}
</h1>
</div>
<p>
{% blocktrans %}
If you don't have enogh space on your virtual machine you can ask for more.
After a request has been made an administrator can extend your HDD.
If the request is granted you have to manually rescan
and extend a logical volume on your machine to acquire the extra space.
To do so you need root access/administrator rights.
{% endblocktrans %}
</p>
<ol>
<li>
{% trans "Ask the administrator for more space. After it has been granted do the following steps." %}
</li>
<li>
{% blocktrans %}
You can check how much free space is left on your machine
(on Debian based distributions like Ubuntu) with the
<strong><code>df -h</code></strong> command.
As you can see below we need more space on
<strong>/</strong> so we will extend
<strong>/dev/mapper/cloud–x–vg-root</strong>.
{% endblocktrans %}
<div class="panel panel-default">
<table class="table">
<thead>
<tr>
<th>Filesystem</th>
<th>Size</th>
<th>Used</th>
<th>Avail</th>
<th>Use%</th>
<th>Mounted on</th>
</tr>
</thead>
<tbody><tr>
<td><strong>/dev/mapper/cloud–x–vg-root</strong></td>
<td>39G</td>
<td>37G</td>
<td>65M</td>
<td>100%</td>
<td><strong>/</strong></td>
</tr>
<tr>
<td>none</td>
<td>4.0K</td>
<td>0</td>
<td>4.0K</td>
<td>0%</td>
<td>/sys/fs/cgroup</td>
</tr>
<tr>
<td>udev</td>
<td>487M</td>
<td>4.0K</td>
<td>487M</td>
<td>1%</td>
<td>/dev</td>
</tr>
<tr>
<td>tmpfs</td>
<td>100M</td>
<td>368K</td>
<td>100M</td>
<td>1%</td>
<td>/run</td>
</tr>
<tr>
<td>none</td>
<td>5.0M</td>
<td>0</td>
<td>5.0M</td>
<td>0%</td>
<td>/run/lock</td>
</tr>
<tr>
<td>none</td>
<td>498M</td>
<td>0</td>
<td>498M</td>
<td>0%</td>
<td>/run/shm</td>
</tr>
<tr>
<td>none</td>
<td>100M</td>
<td>0</td>
<td>100M</td>
<td>0%</td>
<td>/run/user</td>
</tr>
<tr>
<td>/dev/vda1</td>
<td>236M</td>
<td>37M</td>
<td>187M</td>
<td>17%</td>
<td>/boot</td>
</tr>
</tbody>
</table>
</div>
</li>
<li>
{% blocktrans %}
List logical volumes and find the
<strong>VG Name</strong>
(volume group name) of
<strong>/dev/mapper/cloud–x–vg-root</strong>:
<code>lvdisplay</code></p>
{% endblocktrans %}
<pre>
— Logical volume —
<em>LV Path /dev/cloud-x-vg/root</em>
LV Name root
<strong>VG Name cloud-x-vg</strong>
LV UUID xlGizo-eVyj-aqRn-Us7d-BRzj-dsKW-U6kp0F
LV Write Access read/write
LV Creation host, time cloud-x, 2014-07-31 13:17:53 +0200
LV Status available
<code>#</code> open 1
LV Size 38.76 GiB
Current LE 9923
Segments 2
Allocation inherit
Read ahead sectors auto
<code>-</code> currently set to 256
Block device 252:0</pre>
</li>
<li>
{% blocktrans %}
List physical volumes to get the
<strong>PV Name</strong> (partition name) of the
<strong>cloud-x-vg</strong> volume group:
<code>pvdisplay</code>
{% endblocktrans %}
<pre>
— Physical volume —
<strong>PV Name /dev/vda5</strong>
<em>VG Name cloud-x-vg</em>
PV Size 39.76 GiB / not usable 2.00 MiB
Allocatable yes (but full)
PE Size 4.00 MiB
Total PE 10178
Free PE 0
Allocated PE 10178
PV UUID JDp5TP-PHjT-Cgwk-MN4h-iAnk-9dfT-lYoldd</pre>
</li>
<li>
{% blocktrans %}
List the partitions with fdisk:
<strong><code>fdisk /dev/vda</code></strong>
and press <strong>p</strong>.
This will show something similar:
{% endblocktrans %}
<div class="panel panel-default">
<table class="table">
<thead>
<tr>
<th>Device</th>
<th>Boot</th>
<th>Start</th>
<th>End</th>
<th>Blocks</th>
<th>Id</th>
<th>System</th>
</tr>
</thead>
<tbody><tr>
<td>/dev/vda1</td>
<td>*</td>
<td>2048</td>
<td>499711</td>
<td>248832</td>
<td>83</td>
<td>Linux</td>
</tr>
<tr>
<td>/dev/vda2</td>
<td></td>
<td>501758</td>
<td>83884031</td>
<td>41691137</td>
<td>5</td>
<td>Extended</td>
</tr>
<tr>
<td>/dev/vda5</td>
<td></td>
<td>501760</td>
<td>83884031</td>
<td>41691136</td>
<td>8e</td>
<td>Linux LVM</td>
</tr>
</tbody>
</table>
</div>
<p>
{% blocktrans %}
As you can see, the <strong>/dev/vda5</strong> is in the
<strong>/dev/vda2</strong> Extended partition.
To resize it we have to recreate the Extended partition.
{% endblocktrans %}
</p>
</li>
<li>
<p>{% trans "Delete the Extended partition:" %}</p>
<p>
{% blocktrans %}
Press <strong>d</strong> and the number of the partition.
In the example above the extended partition name is
<strong>vda2</strong> so press <strong>2</strong>.
{% endblocktrans %}
</p>
</li>
<li>
<p>{% trans "Create extended partition:" %}</p>
<p>
{% blocktrans %}
Press <strong>n</strong> to create new partition.
Type <strong>e</strong> to choose extended type.
Set partition number - the same as you deleted above:
<strong>2</strong>.
You can use the default starting and ending sector.
{% endblocktrans %}
</p>
</li>
<li>
<p>{% trans "Create logical partition:" %}</p>
<p>
{% blocktrans %}
Press <strong>n</strong> to create new partition.
Type <strong>l</strong> to choose logical type.
Set partition number - the same as the Linux LVM (vda5) has above: <strong>5</strong>.
You can use the default starting and ending sector.
{% endblocktrans %}
</p>
</li>
<li>
<p>{% trans "Change the logical partition’s type:" %}</p>
<p>
{% blocktrans %}
Press <strong>t</strong> to change type.
Set the logical partition’s number: <strong>5</strong> (vda5).
Type <strong>8e</strong> to choose Linux LVM type.
(to show the full list, press L).
{% endblocktrans %}
</p>
</li>
<li>
<p>{% trans "Save and exit: Press <strong>w</strong>." %}</p>
<p>{% trans "If you list the partitions again, you will see the difference:" %}</p>
<div class="panel panel-default">
<table class="table">
<thead>
<tr>
<th>Device</th>
<th>Boot</th>
<th>Start</th>
<th>End</th>
<th>Blocks</th>
<th>Id</th>
<th>System</th>
</tr>
</thead>
<tbody>
<tr>
<td>/dev/vda1</td>
<td>*</td>
<td>2048</td>
<td>499711</td>
<td>248832</td>
<td>83</td>
<td>Linux</td>
</tr>
<tr>
<td>/dev/vda2</td>
<td></td>
<td>499712</td>
<td>89338673</td>
<td><strong>44419481</strong></td>
<td>5</td>
<td>Extended</td>
</tr>
<tr>
<td>/dev/vda5</td>
<td></td>
<td>501760</td>
<td>89338673</td>
<td><strong>44418457</strong></td>
<td>8e</td>
<td>Linux LVM</td>
</tr>
</tbody>
</table>
</div>
</li>
<li>
<p>
{% trans "Reread partition table:" %}
<code>partprobe -s /dev/vda</code>
</p>
<pre>
/dev/vda: msdos partitions 1 2 <5></pre>
</li>
<li>
<p>
{% trans "Resize logical partition:" %}
<code>pvresize /dev/vda5</code>
</p>
<pre>
Physical volume “/dev/vda5” changed
1 physical volume(s) resized / 0 physical volume(s) not resized</pre>
</li>
<li>
<p>
{% trans "Check Free PE / Size:" %}
<code>vgdisplay</code>
</p>
<pre>
...
Free PE / Size 666 / <strong>2.60 GiB</strong>
...</pre>
</li>
<li>
<p>
{% trans "Extend LVM:" %}
<code>lvextend -L</code>+<strong>2.6G</strong>
<code>/dev/mapper/cloud--x--vg-root</code>
</p>
<pre>
Rounding size to boundary between physical extents: 2.60 GiB
Extending logical volume root to 41.36 GiB
Logical volume root successfully resized</pre>
</li>
<li>
<p>
{% trans "Finally, resize filesystem:" %}
<code>resize2fs /dev/mapper/cloud--x--vg-root</code>
</p>
<pre>
resize2fs 1.42.9 (4-Feb-2014)
Filesystem at /dev/mapper/cloud–x–vg-root is mounted on /; on-line resizing required
old_desc_blocks = 3, new_desc_blocks = 3
The filesystem on /dev/mapper/cloud–x–vg-root is now 10843136 blocks long.</pre>
</li>
</ol>
<p>
{% blocktrans %}
The <strong><code>df -h</code></strong> will show now some free space on your <strong>/</strong>:
{% endblocktrans %}
</p>
<div class="panel panel-default">
<table class="table">
<thead>
<tr>
<th>Filesystem</th>
<th>Size</th>
<th>Used</th>
<th>Avail</th>
<th>Use%</th>
<th>Mounted on</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>/dev/mapper/cloud–x–vg-root</strong></td>
<td><strong>41G</strong></td>
<td>37G</td>
<td><strong>2.6G</strong></td>
<td><strong>94%</strong></td>
<td><strong>/</strong></td>
</tr>
<tr>
<td>none</td>
<td>4.0K</td>
<td>0</td>
<td>4.0K</td>
<td>0%</td>
<td>/sys/fs/cgroup</td>
</tr>
<tr>
<td>udev</td>
<td>487M</td>
<td>4.0K</td>
<td>487M</td>
<td>1%</td>
<td>/dev</td>
</tr>
<tr>
<td>tmpfs</td>
<td>100M</td>
<td>368K</td>
<td>100M</td>
<td>1%</td>
<td>/run</td>
</tr>
<tr>
<td>none</td>
<td>5.0M</td>
<td>0</td>
<td>5.0M</td>
<td>0%</td>
<td>/run/lock</td>
</tr>
<tr>
<td>none</td>
<td>498M</td>
<td>0</td>
<td>498M</td>
<td>0%</td>
<td>/run/shm</td>
</tr>
<tr>
<td>none</td>
<td>100M</td>
<td>0</td>
<td>100M</td>
<td>0%</td>
<td>/run/user</td>
</tr>
<tr>
<td>/dev/vda1</td>
<td>236M</td>
<td>37M</td>
<td>187M</td>
<td>17%</td>
<td>/boot</td>
</tr>
</tbody>
</table>
</div><!-- .panel panel-default -->
<hr />
<h1 id="disk-win7">
<i class="fa fa-windows"></i>
{% trans "Expanding disk on Windows 7" %}
</h1>
<p>
{% blocktrans %}
If we don’t have enogh space on our virtual machine, we can ask more.
After the request, the administrator will extend your HDD, but you have
to rescan and extend it manually on your machine.
{% endblocktrans %}
</p>
<ol>
<li>
{% trans "Ask the administrator for more space. After they had given more, do the following steps." %}
<img src="{% static "dashboard/img/resize/1.png" %}"
alt="Sometimes we don't have enough space"/>
</li>
<li>
{% blocktrans %}
Click on the Start menu, and type: <code>disk management</code>.
Click the <code>Create and format hard disk partitions</code>
{% endblocktrans %}
<img src="{% static "dashboard/img/resize/2.png" %}" alt="alt " title="">
</li>
<li>
{% trans "Currently you can’t see the extended size." %}
<img src="{% static "dashboard/img/resize/3.png" %}" alt="alt " title="">
</li>
<li>
{% blocktrans %}
To update the disk information, click <code>Rescan Disks</code> on the <code>Action</code> menu.
{% endblocktrans %}
<img src="{% static "dashboard/img/resize/4.png" %}" alt="alt " title="">
</li>
<li>
{% trans "After scanning Unallocated space appeared." %}
<img src="{% static "dashboard/img/resize/5.png" %}" alt="alt " title="">
</li>
<li>
{% trans "To extend the C drive, right click on it, and select <code>Extend Volume</code>." %}
<img src="{% static "dashboard/img/resize/6.png" %}" alt="alt " title="">
<pre>{% trans "You can also create a new partition from the unallocated space." %}</pre>
</li>
<li>
{% blocktrans %}
In the wizard you can change, how much space will you using from the unallocated space.
The default is to use all, so press <kbd>Next</kbd>,<kbd>Next</kbd>,<kbd>Finish</kbd>.
{% endblocktrans %}
<img src="{% static "dashboard/img/resize/7_1.png" %}" alt="" title="">
<img src="{% static "dashboard/img/resize/7_2.png" %}" alt="" title="">
<img src="{% static "dashboard/img/resize/7_3.png" %}" alt="" title="">
</li>
<li>
{% trans "Your partition is now bigger." %}
<img src="{% static "dashboard/img/resize/8_1.png" %}" alt="alt " title="">
<img src="{% static "dashboard/img/resize/8_2.png" %}" alt="alt " title="">
</li>
</ol>
</div><!-- .col-lg-12 -->
</div><!-- .row -->
{% endblock %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment