diff --git a/dev/gstfsd b/dev/gstfsd new file mode 100755 index 0000000..008223c --- /dev/null +++ b/dev/gstfsd @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +import SocketServer +import json +import guestfs +import re + + +PORT = 16510 +ADDRESS = "0.0.0.0" + + +class MyTCPServer(SocketServer.ThreadingTCPServer): + allow_reuse_address = True + + +class MyTCPServerHandler(SocketServer.BaseRequestHandler): + def handle(self): + try: + # recive data + data = json.loads(self.request.recv(1024).strip()) + dom_name = data['vname'] + passwd_hash = data['passwd'] + + # GuestFS + gfs = guestfs.GuestFS (python_return_dict=True) + try: + gfs.add_domain(dom_name) + gfs.launch() + parts = gfs.list_partitions() + for part in parts: + try: + gfs.mount(part, '/') + if gfs.is_file('/etc/shadow'): + file_shadow = gfs.cat('/etc/shadow') + new_root_hash = "root:" + passwd_hash + ":" + file_shadow_new = re.sub('^root:.*?:', new_root_hash, file_shadow) + gfs.write("/etc/shadow", file_shadow_new) + gfs.chmod('640', '/etc/shadow') + gfs.umount(part) + self.request.sendall(json.dumps({'return':'success'})) + except RuntimeError: + pass + gfs.shutdown() + gfs.close() + except RuntimeError, err: + self.request.sendall(json.dumps({'return': 'error', 'message': err.message})) + + except Exception, e: + print "Exception wile receiving message: ", e + +server = MyTCPServer((ADDRESS, PORT), MyTCPServerHandler) +server.serve_forever() diff --git a/instances/templates/instance.html b/instances/templates/instance.html index c9811b1..6c82eb5 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -39,6 +39,8 @@ <!-- /.row --> {% include 'errors_block.html' %} + {% include 'messages_block.html' %} + <div class="row" id="max-width-page"> <div class="col-lg-12"> @@ -215,6 +217,11 @@ {% trans "Console" %} </a> </li> + <li role="presentation"> + <a href="#rootpasswd" aria-controls="rootpasswd" role="tab" data-toggle="tab"> + {% trans "Root Password" %} + </a> + </li> </ul> <!-- Tab panes --> <div class="tab-content"> @@ -227,6 +234,22 @@ {% endifequal %} <div class="clearfix"></div> </div> + <div role="tabpanel" class="tab-pane tab-pane-bordered" id="rootpasswd"> + <p>{% trans "You need shut down your instance and enter a new root password." %}</p> + <form class="form-inline" method="post" role="form">{% csrf_token %} + <div class="form-group"> + <div class="col-sm-12"> + <input type="text" class="form-control input-lg" name="passwd" placeholder="{% trans "Enter Password" %}" maxlength="24"> + </div> + </div> + {% ifequal status 5 %} + <input type="submit" class="btn btn-lg btn-success pull-right" name="rootpasswd" value="{% trans "Reset Root Password" %}"> + {% else %} + <button class="btn btn-lg btn-success pull-right disabled">{% trans "Reset Root Password" %}</button> + {% endifequal %} + </form> + <div class="clearfix"></div> + </div> </div> </div> </div> diff --git a/instances/views.py b/instances/views.py index df48504..f7fccef 100644 --- a/instances/views.py +++ b/instances/views.py @@ -1,5 +1,7 @@ import time import json +import socket +import crypt from string import letters, digits from random import choice from bisect import insort @@ -261,6 +263,26 @@ def instance(request, compute_id, vname): conn.delete() return HttpResponseRedirect(reverse('instances')) + if 'rootpasswd' in request.POST: + passwd = request.POST.get('passwd', '') + + passwd_hash = crypt.crypt(passwd, '$6$kgPoiREy') + data = {'passwd': passwd_hash, 'vname': vname} + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((compute.hostname, 16510)) + s.send(json.dumps(data)) + result = json.loads(s.recv(1024)) + s.close() + + msg = _("Reset root password") + addlogmsg(request.user.username, instance.name, msg) + + if result['return'] == 'success': + messages.append(msg) + else: + error_messages(msg) + if 'resize' in request.POST: vcpu = request.POST.get('vcpu', '') cur_vcpu = request.POST.get('cur_vcpu', '') @@ -298,7 +320,7 @@ def instance(request, compute_id, vname): conn.create_snapshot(name) msg = _("New snapshot") addlogmsg(request.user.username, instance.name, msg) - return HttpResponseRedirect(request.get_full_path() + '#takesnapshot') + return HttpResponseRedirect(request.get_full_path() + '#restoresnapshot') if 'delete_snapshot' in request.POST: snap_name = request.POST.get('name', '') diff --git a/templates/messages_block.html b/templates/messages_block.html new file mode 100644 index 0000000..cb2aef6 --- /dev/null +++ b/templates/messages_block.html @@ -0,0 +1,14 @@ +{% if messages %} + {% for message in messages %} + <!-- Success Messages --> + <div class="row"> + <div class="col-lg-12"> + <div class="alert alert-success alert-dismissible" role="susses"> + <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button> + <strong>Success:</strong> {{ message }} + </div> + </div> + </div> + <!-- /.row --> + {% endfor %} +{% endif %} \ No newline at end of file