forked from 3wordchant/capsul-flask
		
	implement deleting capsuls
This commit is contained in:
		| @ -161,6 +161,7 @@ def cron_task(): | ||||
|         index_to_send = i | ||||
|      | ||||
|     if index_to_send > -1: | ||||
|       print(f"cron_task: sending {warnings[index_to_send]['id']} warning email to {account['email']}.") | ||||
|       current_app.config["FLASK_MAIL_INSTANCE"].send( | ||||
|           Message( | ||||
|             warnings[index_to_send]['subject'], | ||||
| @ -170,7 +171,10 @@ def cron_task(): | ||||
|       ) | ||||
|       get_model().set_account_balance_warning(account['email'], warnings[index_to_send]['id']) | ||||
|       if index_to_send == len(warnings)-1: | ||||
|         print('TODO: delete capsuls') | ||||
|         for vm in vms: | ||||
|           print(f"cron_task: deleting {vm['id']} ( {account['email']} ) due to negative account balance.") | ||||
|           current_app.config["VIRTUALIZATION_MODEL"].destroy(email=account["email"], id=vm['id']) | ||||
|           get_model().delete_vm(email=account["email"], id=vm['id']) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -27,7 +27,7 @@ def double_check_capsul_address(id, ipv4): | ||||
|     result = current_app.config["VIRTUALIZATION_MODEL"].get(id) | ||||
|     if result.ipv4 != ipv4: | ||||
|       ipv4 = result.ipv4 | ||||
|       get_model().updateVm(email=session["account"], id=id, ipv4=result.ipv4) | ||||
|       get_model().update_vm_ip(email=session["account"], id=id, ipv4=result.ipv4) | ||||
|   except: | ||||
|     print(f""" | ||||
|       the virtualization model threw an error in double_check_capsul_address of {id}: | ||||
| @ -55,12 +55,12 @@ def index(): | ||||
|       os=x['os'],  | ||||
|       created=x['created'].strftime("%b %d %Y") | ||||
|     ), | ||||
|     vms | ||||
|     list(filter(lambda x: not x['deleted'], vms)) | ||||
|   )) | ||||
|  | ||||
|   return render_template("capsuls.html", vms=vms, has_vms=len(vms) > 0) | ||||
|  | ||||
| @bp.route("/<string:id>") | ||||
| @bp.route("/<string:id>", methods=("GET", "POST")) | ||||
| @account_required | ||||
| def detail(id): | ||||
|  | ||||
| @ -73,16 +73,31 @@ def detail(id): | ||||
|   if vm is None: | ||||
|     return abort(404, f"{id} doesn't exist.") | ||||
|  | ||||
|   vm["ipv4"] = double_check_capsul_address(vm["id"], vm["ipv4"]) | ||||
|   vm["created"] = vm['created'].strftime("%b %d %Y %H:%M") | ||||
|   vm["ssh_public_keys"] = ", ".join(vm["ssh_public_keys"]) if len(vm["ssh_public_keys"]) > 0 else "<missing>" | ||||
|   if vm['deleted']: | ||||
|     return render_template("capsul-detail.html", vm=vm, delete=True, are_you_sure=True) | ||||
|  | ||||
|   return render_template( | ||||
|     "capsul-detail.html",  | ||||
|     vm=vm,  | ||||
|     durations=list(map(lambda x: x.strip("_"), metric_durations.keys())), | ||||
|     duration=duration | ||||
|   ) | ||||
|   if request.method == "POST": | ||||
|     if 'are_you_sure' not in request.form or not request.form['are_you_sure']: | ||||
|  | ||||
|       return render_template("capsul-detail.html", vm=vm, delete=True, are_you_sure=False) | ||||
|     else: | ||||
|       print(f"deleting {vm['id']} per user request ({session['account']})") | ||||
|       current_app.config["VIRTUALIZATION_MODEL"].destroy(email=session['account'], id=id) | ||||
|       get_model().delete_vm(email=session['account'], id=id) | ||||
|  | ||||
|       return render_template("capsul-detail.html", vm=vm, delete=True, are_you_sure=True) | ||||
|  | ||||
|   else: | ||||
|     vm["ipv4"] = double_check_capsul_address(vm["id"], vm["ipv4"]) | ||||
|     vm["created"] = vm['created'].strftime("%b %d %Y %H:%M") | ||||
|     vm["ssh_public_keys"] = ", ".join(vm["ssh_public_keys"]) if len(vm["ssh_public_keys"]) > 0 else "<missing>" | ||||
|  | ||||
|     return render_template( | ||||
|       "capsul-detail.html",  | ||||
|       vm=vm, delete=False, | ||||
|       durations=list(map(lambda x: x.strip("_"), metric_durations.keys())), | ||||
|       duration=duration | ||||
|     ) | ||||
|  | ||||
|  | ||||
| @bp.route("/create", methods=("GET", "POST")) | ||||
|  | ||||
| @ -90,7 +90,7 @@ class DBModel: | ||||
|       self.cursor.fetchall() | ||||
|     )) | ||||
|  | ||||
|   def updateVm(self, email, id, ipv4): | ||||
|   def update_vm_ip(self, email, id, ipv4): | ||||
|     self.cursor.execute("UPDATE vms SET last_seen_ipv4 = %s WHERE email = %s AND id = %s", (ipv4, email, id)) | ||||
|     self.connection.commit() | ||||
|  | ||||
| @ -111,9 +111,9 @@ class DBModel: | ||||
|       ) | ||||
|     self.connection.commit() | ||||
|  | ||||
|   # def vm_exists(self, email, id): | ||||
|   #   self.cursor.execute("SELECT id FROM vms WHERE email = %s AND id = %s ", (email, id)) | ||||
|   #   return len(self.cursor.fetchall()) > 0 | ||||
|   def delete_vm(self, email, id): | ||||
|     self.cursor.execute("UPDATE vms SET deleted = now() WHERE email = %s AND id = %s", ( email, id)) | ||||
|     self.connection.commit() | ||||
|  | ||||
|   def get_vm_detail(self, email, id): | ||||
|     self.cursor.execute("""  | ||||
|  | ||||
| @ -23,21 +23,15 @@ a { | ||||
|   text-shadow: 1px 1px 0px #000c; | ||||
| } | ||||
|  | ||||
| a.no-shadow { | ||||
|   text-shadow: initial; | ||||
| } | ||||
|  | ||||
| a:hover, a:active, a:visited { | ||||
|   color: #b5bd68; | ||||
| }  | ||||
|  | ||||
| .nav-row { | ||||
|   display: flex; | ||||
|   justify-content: space-between; | ||||
| } | ||||
| .nav-row a { | ||||
|   white-space: nowrap; | ||||
| } | ||||
| .nav-row:last-child { | ||||
|   justify-content: center; | ||||
| } | ||||
| .nav-row:last-child a { | ||||
| .nav-links  a { | ||||
|   margin: 0 1em; | ||||
| } | ||||
|  | ||||
| @ -88,6 +82,9 @@ main { | ||||
|   justify-content: space-around; | ||||
|   width: 100%; | ||||
| } | ||||
| .center { | ||||
|   align-items: center; | ||||
| } | ||||
| .wrap { | ||||
|   flex-wrap: wrap; | ||||
| } | ||||
| @ -104,10 +101,19 @@ main { | ||||
|   justify-content: flex-end; | ||||
| } | ||||
|  | ||||
| .justify-space-between { | ||||
|   justify-content: space-between; | ||||
| } | ||||
| .justify-center { | ||||
|   justify-content: center; | ||||
| } | ||||
|  | ||||
|  | ||||
| form { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   align-items: flex-start; | ||||
|   margin: 0; | ||||
| } | ||||
|  | ||||
| label.align { | ||||
| @ -170,6 +176,14 @@ input[type=submit], select { | ||||
|   cursor: pointer; | ||||
| } | ||||
|  | ||||
| input[type=submit].form-submit-link { | ||||
|   border: none; | ||||
|   background-color: initial; | ||||
|   color: #6CF; | ||||
|   padding: 0; | ||||
|   margin: 0; | ||||
| } | ||||
|  | ||||
| input::-webkit-outer-spin-button, | ||||
| input::-webkit-inner-spin-button { | ||||
|   -webkit-appearance: none; | ||||
|  | ||||
| @ -10,11 +10,12 @@ | ||||
| </head> | ||||
| <body> | ||||
| <nav> | ||||
|   <div class="nav-row half-margin"> | ||||
|   <div class="row justify-space-between half-margin"> | ||||
|     <div> | ||||
|       <a href="/"><b>Capsul</b></a>💊 | ||||
|     </div> | ||||
|     <div> | ||||
|         | ||||
|       {% if session["account"] %}  | ||||
|         { {{ session["account"] }} <a href="{{ url_for('auth.logout') }}">Log Out</a> }  | ||||
|       {% else %}  | ||||
| @ -22,7 +23,7 @@ | ||||
|       {% endif %} | ||||
|     </div> | ||||
|   </div> | ||||
|   <div class="nav-row  half-margin wrap"> | ||||
|   <div class="row justify-center half-margin wrap nav-links"> | ||||
|     <a href="/faq">FAQ</a> | ||||
|     <a href="/changelog">Changelog</a> | ||||
|  | ||||
|  | ||||
| @ -3,103 +3,138 @@ | ||||
| {% block title %}{{ vm['id'] }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
| <div class="row third-margin"> | ||||
|   <h1>{{ vm['id'] }}</h1> | ||||
| </div> | ||||
| <div class="row wrap grid-large third-margin"> | ||||
|  | ||||
| {% if delete %} | ||||
|   {% if are_you_sure %} | ||||
|     <div class="row third-margin"> | ||||
|       <h1>DELETED</h1> | ||||
|     </div> | ||||
|     <div class="row third-margin"> | ||||
|       <p>{{ vm['id'] }} has been deleted.</p> | ||||
|     </div> | ||||
|   {% else %} | ||||
|     <div class="row third-margin"> | ||||
|       <h1>Are you sure?</h1> | ||||
|     </div> | ||||
|     <div class="row third-margin"> | ||||
|       <p>Are you sure you want to delete {{ vm['id'] }}?</p> | ||||
|     </div> | ||||
|     <div class="row third-margin"> | ||||
|       <a href="/console/{{ vm['id'] }}">No, Cancel!</a> | ||||
|       <form id="delete_action" method="post"> | ||||
|         <input type="hidden" name="delete" value="True"/> | ||||
|         <input type="hidden" name="are_you_sure" value="True"/> | ||||
|         <input type="submit" class="form-submit-link" value="Yes, Delete"> | ||||
|       </form> | ||||
|     </div> | ||||
|      | ||||
|   <div class="row justify-start"> | ||||
|     <label class="align" for="created">Created</label> | ||||
|     <span id=created>{{ vm['created'] }}</span> | ||||
|   {% endif %} | ||||
| {% else %} | ||||
|   <div class="row third-margin"> | ||||
|     <h1>{{ vm['id'] }}</h1> | ||||
|   </div> | ||||
|   <div class="row justify-start"> | ||||
|     <label class="align" for="size">Capsul Size</label> | ||||
|     <span id=size>{{ vm['size'] }}</span> | ||||
|   <div class="row wrap grid-large third-margin"> | ||||
|        | ||||
|     <div class="row justify-start"> | ||||
|       <label class="align" for="created">Created</label> | ||||
|       <span id="created">{{ vm['created'] }}</span> | ||||
|     </div> | ||||
|     <div class="row justify-start"> | ||||
|       <label class="align" for="size">Capsul Size</label> | ||||
|       <span id="size">{{ vm['size'] }}</span> | ||||
|     </div> | ||||
|     <div class="row justify-start"> | ||||
|       <label class="align" for="dollars_per_month">Monthly Cost</label> | ||||
|       <span id="dollars_per_month">${{ vm['dollars_per_month'] }}</span> | ||||
|     </div> | ||||
|     <div class="row justify-start"> | ||||
|       <label class="align" for="ipv4">IPv4 Address</label> | ||||
|       <span id="ipv4">{{ vm['ipv4'] }}</span> | ||||
|     </div> | ||||
|     <div class="row justify-start"> | ||||
|       <label class="align" for="os_description">Operating System</label> | ||||
|       <span id="os_description">{{ vm['os_description'] }}</span> | ||||
|     </div> | ||||
|     <div class="row justify-start"> | ||||
|       <label class="align" for="vcpus">VCPUs</label> | ||||
|       <span id="vcpus">{{ vm['vcpus'] }}</span> | ||||
|     </div> | ||||
|     <div class="row justify-start"> | ||||
|       <label class="align" for="memory_mb">Memory</label> | ||||
|       <span id="memory_mb">{{ vm['memory_mb'] }}MB</span> | ||||
|     </div> | ||||
|     <div class="row justify-start"> | ||||
|       <label class="align" for="bandwidth_gb_per_month">Bandwidth</label> | ||||
|       <span id="bandwidth_gb_per_month">{{ vm['bandwidth_gb_per_month'] }}GB/month</span> | ||||
|     </div> | ||||
|     <div class="row justify-start"> | ||||
|       <label class="align" for="ssh_username">SSH Username</label> | ||||
|       <span id="ssh_username">cyberian</span> | ||||
|     </div> | ||||
|     <div class="row justify-start"> | ||||
|       <label class="align" for="ssh_public_keys">SSH Public Keys</label> | ||||
|       <a id="ssh_public_keys" href="/console/ssh">{{ vm['ssh_public_keys'] }}</a> | ||||
|     </div> | ||||
|     <div class="row center justify-start"> | ||||
|       <label class="align" for="delete_action">Actions</label> | ||||
|       <form id="delete_action" method="post"> | ||||
|         <input type="hidden" name="delete" value="True"/> | ||||
|         <input type="submit" class="form-submit-link" value="Delete..."> | ||||
|       </form> | ||||
|     </div> | ||||
|   </div> | ||||
|   <div class="row justify-start"> | ||||
|     <label class="align" for="dollars_per_month">Monthly Cost</label> | ||||
|     <span id=dollars_per_month>${{ vm['dollars_per_month'] }}</span> | ||||
|   <div class="row "> | ||||
|     <hr/> | ||||
|   </div> | ||||
|   <div class="row justify-start"> | ||||
|     <label class="align" for="ipv4">IPv4 Address</label> | ||||
|     <span id=ipv4>{{ vm['ipv4'] }}</span> | ||||
|   </div> | ||||
|   <div class="row justify-start"> | ||||
|     <label class="align" for="os_description">Operating System</label> | ||||
|     <span id=os_description>{{ vm['os_description'] }}</span> | ||||
|   </div> | ||||
|   <div class="row justify-start"> | ||||
|     <label class="align" for="vcpus">VCPUs</label> | ||||
|     <span id=vcpus>{{ vm['vcpus'] }}</span> | ||||
|   </div> | ||||
|   <div class="row justify-start"> | ||||
|     <label class="align" for="memory_mb">Memory</label> | ||||
|     <span id=memory_mb>{{ vm['memory_mb'] }}MB</span> | ||||
|   </div> | ||||
|   <div class="row justify-start"> | ||||
|     <label class="align" for="bandwidth_gb_per_month">Bandwidth</label> | ||||
|     <span id=bandwidth_gb_per_month>{{ vm['bandwidth_gb_per_month'] }}GB/month</span> | ||||
|   </div> | ||||
|   <div class="row justify-start"> | ||||
|     <label class="align" for="ssh_username">SSH Username</label> | ||||
|     <span id=ssh_username>cyberian</span> | ||||
|   </div> | ||||
|   <div class="row justify-start"> | ||||
|     <label class="align" for="ssh_public_keys">SSH Public Keys</label> | ||||
|     <a id=ssh_public_keys href="/console/ssh">{{ vm['ssh_public_keys'] }}</a> | ||||
|   </div> | ||||
| </div> | ||||
| <div class="row "> | ||||
|   <hr/> | ||||
| </div> | ||||
| <div class="row third-margin"> | ||||
|   {% for d in durations %} | ||||
|     <a href="/console/{{  vm['id']  }}?duration={{ d }}"> | ||||
|       {% if d == duration %} | ||||
|       <span class="code">{{ d }}</span> | ||||
|       {% else %} | ||||
|       {{ d }} | ||||
|       {% endif %} | ||||
|   <div class="row third-margin"> | ||||
|     {% for d in durations %} | ||||
|       <a href="/console/{{  vm['id']  }}?duration={{ d }}"> | ||||
|         {% if d == duration %} | ||||
|         <span class="code">{{ d }}</span> | ||||
|         {% else %} | ||||
|         {{ d }} | ||||
|         {% endif %} | ||||
|  | ||||
|     </a> | ||||
|   {% endfor %} | ||||
| </div> | ||||
| <div class="row wrap grid-small  justify-end"> | ||||
|   <div class="metric"> | ||||
|     <h1>cpu</h1> | ||||
|     <a href="/metrics/html/cpu/{{ vm['id'] }}/{{ duration }}"> | ||||
|       <img src="/metrics/cpu/{{ vm['id'] }}/{{ duration }}/m"/> | ||||
|     </a> | ||||
|       </a> | ||||
|     {% endfor %} | ||||
|   </div> | ||||
|   <div class="row wrap grid-small  justify-end"> | ||||
|     <div class="metric"> | ||||
|       <h1>cpu</h1> | ||||
|       <a href="/metrics/html/cpu/{{ vm['id'] }}/{{ duration }}"> | ||||
|         <img src="/metrics/cpu/{{ vm['id'] }}/{{ duration }}/m"/> | ||||
|       </a> | ||||
|     </div> | ||||
|  | ||||
|   <div  class="metric"> | ||||
|     <h1>memory</h1> | ||||
|     <a href="/metrics/html/memory/{{ vm['id'] }}/{{ duration }}"> | ||||
|       <img src="/metrics/memory/{{ vm['id'] }}/{{ duration }}/m"/> | ||||
|     </a> | ||||
|   </div> | ||||
|    | ||||
|   <div  class="metric"> | ||||
|     <h1>network_in</h1> | ||||
|     <a href="/metrics/html/network_in/{{ vm['id'] }}/{{ duration }}"> | ||||
|       <img src="/metrics/network_in/{{ vm['id'] }}/{{ duration }}/m"/> | ||||
|     </a> | ||||
|   </div> | ||||
|     <div  class="metric"> | ||||
|       <h1>memory</h1> | ||||
|       <a href="/metrics/html/memory/{{ vm['id'] }}/{{ duration }}"> | ||||
|         <img src="/metrics/memory/{{ vm['id'] }}/{{ duration }}/m"/> | ||||
|       </a> | ||||
|     </div> | ||||
|      | ||||
|     <div  class="metric"> | ||||
|       <h1>network_in</h1> | ||||
|       <a href="/metrics/html/network_in/{{ vm['id'] }}/{{ duration }}"> | ||||
|         <img src="/metrics/network_in/{{ vm['id'] }}/{{ duration }}/m"/> | ||||
|       </a> | ||||
|     </div> | ||||
|  | ||||
|   <div  class="metric"> | ||||
|     <h1>network_out</h1> | ||||
|     <a href="/metrics/html/network_out/{{ vm['id'] }}/{{ duration }}"> | ||||
|       <img src="/metrics/network_out/{{ vm['id'] }}/{{ duration }}/m"/> | ||||
|     </a> | ||||
|   </div> | ||||
|     <div  class="metric"> | ||||
|       <h1>network_out</h1> | ||||
|       <a href="/metrics/html/network_out/{{ vm['id'] }}/{{ duration }}"> | ||||
|         <img src="/metrics/network_out/{{ vm['id'] }}/{{ duration }}/m"/> | ||||
|       </a> | ||||
|     </div> | ||||
|  | ||||
|   <div  class="metric"> | ||||
|     <h1>disk</h1> | ||||
|     <a href="/metrics/html/disk/{{ vm['id'] }}/{{ duration }}"> | ||||
|       <img src="/metrics/disk/{{ vm['id'] }}/{{ duration }}/m"/> | ||||
|     </a> | ||||
|     <div  class="metric"> | ||||
|       <h1>disk</h1> | ||||
|       <a href="/metrics/html/disk/{{ vm['id'] }}/{{ duration }}"> | ||||
|         <img src="/metrics/disk/{{ vm['id'] }}/{{ duration }}/m"/> | ||||
|       </a> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
| {% endif %} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block pagesource %}/templates/create-capsul.html{% endblock %} | ||||
|  | ||||
| @ -27,7 +27,7 @@ | ||||
|       <tbody> | ||||
|         {% for vm in vms %} | ||||
|           <tr> | ||||
|             <td><a href="/console/{{ vm['id'] }}">{{ vm["id"] }}</a></td> | ||||
|             <td><a class="no-shadow" href="/console/{{ vm['id'] }}">{{ vm["id"] }}</a></td> | ||||
|             <td>{{ vm["size"] }}</td> | ||||
|             <td class="metrics"><img src="/metrics/cpu/{{ vm['id'] }}/5m/s"/></td> | ||||
|             <td class="metrics"><img src="/metrics/memory/{{ vm['id'] }}/5m/s"/></td> | ||||
| @ -41,7 +41,9 @@ | ||||
|   </div> | ||||
|    | ||||
|   {% else %}  | ||||
|   <div class="row">You don't have any Capsuls running. <a href="/console/create">Create one</a> today!</div> | ||||
|   <div class="row"> | ||||
|     <p>You don't have any Capsuls running. <a href="/console/create">Create one</a> today!</p> | ||||
|   </div> | ||||
|   {% endif %} | ||||
| </div> | ||||
| {% endblock %} | ||||
|  | ||||
		Reference in New Issue
	
	Block a user