Improved VPS backend
This commit is contained in:
parent
760d6956de
commit
d6925abd72
6
TODO.md
6
TODO.md
|
@ -124,16 +124,12 @@ require_once(‘/etc/moodles/’.$moodle_host.‘config.php’);``` moodle/drupl
|
|||
|
||||
* make account available on all admin forms
|
||||
|
||||
# WPMU blog traffic
|
||||
|
||||
* more robust backend error handling, continue executing but exit code > 0 if failure: failing_cmd || exit_code=1 and don't forget to call super.commit()!!
|
||||
|
||||
* website directives uniquenes validation on serializers
|
||||
|
||||
+ is_Active custom filter with support for instance.account.is_Active annotate with F() needed (django 1.8)
|
||||
|
||||
# delete apache logs and php logs
|
||||
|
||||
* document service help things: discount/refound/compensation effect and metric table
|
||||
* Document metric interpretation help_text
|
||||
* document plugin serialization, data_serializer?
|
||||
|
@ -385,8 +381,6 @@ Case
|
|||
# Mailer: mark as sent
|
||||
|
||||
|
||||
# Implement wordpressmu change password or remove password from the form
|
||||
|
||||
# Deprecate orchestra start/stop/restart services management commands?
|
||||
|
||||
# Enable/disable ignore period orders list filter
|
||||
|
|
|
@ -236,45 +236,50 @@ class ChangePasswordAdminMixin(object):
|
|||
name='%s_%s_change_password' % info)
|
||||
] + super(ChangePasswordAdminMixin, self).get_urls()
|
||||
|
||||
def get_change_password_username(self, obj):
|
||||
return str(obj)
|
||||
|
||||
@sensitive_post_parameters_m
|
||||
def change_password(self, request, id, form_url=''):
|
||||
if not self.has_change_permission(request):
|
||||
raise PermissionDenied
|
||||
# TODO use this insetad of self.get_object(), in other places
|
||||
user = get_object_or_404(self.get_queryset(request), pk=id)
|
||||
obj = get_object_or_404(self.get_queryset(request), pk=id)
|
||||
|
||||
related = []
|
||||
try:
|
||||
# don't know why getattr(user, 'username', user.name) doesn't work
|
||||
username = user.username
|
||||
except AttributeError:
|
||||
username = user.name
|
||||
if hasattr(user, 'account'):
|
||||
account = user.account
|
||||
if user.account.username == username:
|
||||
related.append(user.account)
|
||||
for obj_name_attr in ('username', 'name', 'hostname'):
|
||||
try:
|
||||
obj_name = getattr(obj, obj_name_attr)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
break
|
||||
if hasattr(obj, 'account'):
|
||||
account = obj.account
|
||||
if obj.account.username == obj_name:
|
||||
related.append(obj.account)
|
||||
else:
|
||||
account = user
|
||||
if account.username == username:
|
||||
account = obj
|
||||
if account.username == obj_name:
|
||||
for rel in account.get_related_passwords():
|
||||
if not isinstance(user, type(rel)):
|
||||
if not isinstance(obj, type(rel)):
|
||||
related.append(rel)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = self.change_password_form(user, request.POST, related=related)
|
||||
form = self.change_password_form(obj, request.POST, related=related)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
change_message = self.construct_change_message(request, form, None)
|
||||
self.log_change(request, user, change_message)
|
||||
self.log_change(request, obj, change_message)
|
||||
msg = _('Password changed successfully.')
|
||||
messages.success(request, msg)
|
||||
update_session_auth_hash(request, form.user) # This is safe
|
||||
return HttpResponseRedirect('..')
|
||||
else:
|
||||
form = self.change_password_form(user, related=related)
|
||||
form = self.change_password_form(obj, related=related)
|
||||
|
||||
fieldsets = [
|
||||
(user._meta.verbose_name.capitalize(), {
|
||||
(obj._meta.verbose_name.capitalize(), {
|
||||
'classes': ('wide',),
|
||||
'fields': ('password1', 'password2')
|
||||
}),
|
||||
|
@ -285,9 +290,10 @@ class ChangePasswordAdminMixin(object):
|
|||
'fields': ('password1_%i' % ix, 'password2_%i' % ix)
|
||||
}))
|
||||
|
||||
obj_username = self.get_change_password_username(obj)
|
||||
adminForm = admin.helpers.AdminForm(form, fieldsets, {})
|
||||
context = {
|
||||
'title': _('Change password: %s') % escape(username),
|
||||
'title': _('Change password: %s') % obj_username,
|
||||
'adminform': adminForm,
|
||||
'errors': admin.helpers.AdminErrorList(form, []),
|
||||
'form_url': form_url,
|
||||
|
@ -299,7 +305,8 @@ class ChangePasswordAdminMixin(object):
|
|||
'has_change_permission': True,
|
||||
'has_absolute_url': False,
|
||||
'opts': self.model._meta,
|
||||
'original': user,
|
||||
'original': obj,
|
||||
'obj_username': obj_username,
|
||||
'save_as': False,
|
||||
'show_save': True,
|
||||
'password': random_ascii(10),
|
||||
|
|
|
@ -19,6 +19,7 @@ class WordPressForm(SaaSBaseForm):
|
|||
help_text = 'Admin URL: <a href="{0}">{0}</a>'.format(admin_url)
|
||||
self.fields['site_url'].help_text = mark_safe(help_text)
|
||||
|
||||
|
||||
class WordPressDataSerializer(serializers.Serializer):
|
||||
email = serializers.EmailField(label=_("Email"))
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.contrib import admin
|
|||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.contrib.accounts.actions import list_accounts
|
||||
from orchestra.contrib.accounts.admin import AccountAdminMixin
|
||||
from orchestra.forms import UserCreationForm, NonStoredUserChangeForm
|
||||
|
@ -11,7 +11,7 @@ from orchestra.forms import UserCreationForm, NonStoredUserChangeForm
|
|||
from .models import VPS
|
||||
|
||||
|
||||
class VPSAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
||||
class VPSAdmin(ChangePasswordAdminMixin, AccountAdminMixin, ExtendedModelAdmin):
|
||||
list_display = ('hostname', 'type', 'template', 'account_link')
|
||||
list_filter = ('type', 'template')
|
||||
form = NonStoredUserChangeForm
|
||||
|
@ -40,12 +40,8 @@ class VPSAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
|||
)
|
||||
actions = (list_accounts,)
|
||||
|
||||
def get_urls(self):
|
||||
useradmin = UserAdmin(VPS, self.admin_site)
|
||||
return [
|
||||
url(r'^(\d+)/password/$',
|
||||
self.admin_site.admin_view(useradmin.user_change_password))
|
||||
] + super(VPSAdmin, self).get_urls()
|
||||
def get_change_password_username(self, obj):
|
||||
return 'root@%s' % obj.hostname
|
||||
|
||||
|
||||
admin.site.register(VPS, VPSAdmin)
|
||||
|
|
|
@ -4,6 +4,8 @@ import textwrap
|
|||
from orchestra.contrib.orchestration import ServiceController
|
||||
from orchestra.contrib.resources import ServiceMonitor
|
||||
|
||||
from . import settings
|
||||
|
||||
|
||||
class ProxmoxOVZ(ServiceController):
|
||||
model = 'vps.VPS'
|
||||
|
@ -34,39 +36,58 @@ class ProxmoxOVZ(ServiceController):
|
|||
super(ProxmoxOVZ, self).prepare()
|
||||
self.append(self.GET_PROXMOX_INFO)
|
||||
|
||||
def get_vzset_args(self, vps):
|
||||
args = []
|
||||
def get_vzset_args(self, context):
|
||||
args = list(settings.VPS_DEFAULT_VZSET_ARGS)
|
||||
for resource, arg_name in self.RESOURCES:
|
||||
try:
|
||||
allocation = getattr(vps.resources, resource).allocated
|
||||
except AttributeError:
|
||||
allocation = context[resource]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
args.append('--%s %i' % (arg_name, allocation))
|
||||
return ' '.join(args)
|
||||
|
||||
def run_ssh_commands(self, ssh_commands):
|
||||
commands = '\n '.join(ssh_commands)
|
||||
self.append(textwrap.dedent("""\
|
||||
cat << EOF | ssh root@${info[1]}
|
||||
%s
|
||||
EOF""") % commands
|
||||
)
|
||||
|
||||
def save(self, vps):
|
||||
# TODO create the container
|
||||
context = self.get_context(vps)
|
||||
self.append('info=( $(get_vz_info %(hostname)s) )' % context)
|
||||
vzset_args = self.get_vzset_args(vps)
|
||||
self.append(textwrap.dedent("""
|
||||
info=( $(get_vz_info %(hostname)s) )
|
||||
echo "Managing ${info[@]}"\
|
||||
""") % context
|
||||
)
|
||||
ssh_commands = []
|
||||
vzset_args = self.get_vzset_args(context)
|
||||
if vzset_args:
|
||||
context['vzset_args'] = vzset_args
|
||||
self.append(textwrap.dedent("""\
|
||||
cat << EOF | ssh root@${info[1]}
|
||||
pvectl vzset ${info[0]} %(vzset_args)s
|
||||
EOF""") % context
|
||||
)
|
||||
ssh_commands.append("pvectl vzset ${info[0]} %(vzset_args)s" % context)
|
||||
if hasattr(vps, 'password'):
|
||||
context['password'] = vps.password.replace('$', '\\$')
|
||||
self.append(textwrap.dedent("""\
|
||||
cat << EOF | ssh root@${info[1]}
|
||||
echo 'root:%(password)s' | vzctl exec ${info[0]} chpasswd -e
|
||||
EOF""") % context
|
||||
ssh_commands.append(textwrap.dedent("""\
|
||||
echo 'root:%(password)s' \\
|
||||
| chroot /var/lib/vz/private/${info[0]} chpasswd -e""") % context
|
||||
)
|
||||
self.run_ssh_commands(ssh_commands)
|
||||
|
||||
def get_context(self, vps):
|
||||
return {
|
||||
context = {
|
||||
'hostname': vps.hostname,
|
||||
}
|
||||
for resource, __ in self.RESOURCES:
|
||||
try:
|
||||
allocation = getattr(vps.resources, resource).allocated
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
context[resource] = allocation
|
||||
return context
|
||||
|
||||
|
||||
# TODO rename to proxmox
|
||||
|
|
|
@ -27,3 +27,8 @@ VPS_DEFAULT_TEMPLATE = Setting('VPS_DEFAULT_TEMPLATE',
|
|||
'debian7',
|
||||
choices=VPS_TEMPLATES
|
||||
)
|
||||
|
||||
|
||||
VPS_DEFAULT_VZSET_ARGS = Setting('VPS_DEFAULT_VZSET_ARGS',
|
||||
('--onboot yes',),
|
||||
)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div>
|
||||
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1" />{% endif %}
|
||||
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}
|
||||
<p>{% blocktrans with username=original %}Enter a new password for the user <strong>{{ username }}</strong>, suggestion '{{ password }}'.{% endblocktrans %}</p>
|
||||
<p>{% blocktrans with username=obj_username %}Enter a new password for the user <strong>{{ username }}</strong>, suggestion '{{ password }}'.{% endblocktrans %}</p>
|
||||
|
||||
{% if errors %}
|
||||
<p class="errornote">
|
||||
|
|
Loading…
Reference in a new issue