~fnux/machines.sr.ht

7b893c0e4d73451e9c4612f528f3062c19d473ed — Timothée Floure a month ago 8c0f380 master
Initial VM creation + view logic
M machines/alembic/versions/598f0a752e89_initial_host_machine_volume_structure.py => machines/alembic/versions/598f0a752e89_initial_host_machine_volume_structure.py +1 -1
@@ 55,7 55,7 @@ def upgrade():
    sa.Column('cores', sa.Integer(), nullable=False),
    sa.Column('memory', sa.Integer(), nullable=False),
    sa.Column('status', sqlalchemy_utils.types.choice.ChoiceType(), nullable=False),
    sa.Column('host_id', sa.Integer(), nullable=False),
    sa.Column('host_id', sa.Integer(), nullable=True),
    sa.ForeignKeyConstraint(['host_id'], ['host.id'], ),
    sa.PrimaryKeyConstraint('id')
    )

M machines/blueprints/web.py => machines/blueprints/web.py +34 -5
@@ 2,14 2,15 @@ from flask import Blueprint, render_template, request, redirect
from srht.validation import Validation
from srht.oauth import current_user, loginrequired
from srht.database import db
from machines.types import Host, HostStatus
from machines.types import Host, HostStatus, Machine, MachineStatus

web = Blueprint("machines.web", __name__)

@web.route("/")
def index():
    if current_user:
        return render_template("dashboard.html")
        vms = Machine.query.all()
        return render_template("dashboard.html", vms=vms)
    else:
        return render_template("index.html")



@@ 45,7 46,35 @@ def create_host_POST():

    return redirect("/hosts")

@web.route("/allocate")
@web.route("/vm/<id>")
@loginrequired
def allocate():
    return render_template("allocate.html")
def vm(id):
    vm = Machine.query.filter(Machine.id == id).one_or_none()
    return render_template("vm.html", vm=vm)

@web.route("/vm/create", methods=["GET"])
@loginrequired
def vm_create_GET():
    return render_template("vm-create.html")

@web.route("/vm/create", methods=["POST"])
@loginrequired
def vm_create_POST():
    valid = Validation(request)
    name = valid.require("name", friendly_name="Name")
    description = valid.require("description", friendly_name="Description")
    cores = valid.require("cores", friendly_name="CPU Cores")
    memory = valid.require("memory", friendly_name="Memory")
    storage = valid.require("storage", friendly_name="Storage")
    status = MachineStatus.pending

    if not valid.ok:
        return render_template("vm-create.html", **valid.kwargs), 400

    vm = Machine(name=name, cores=cores, memory=memory)

    db.session.add(vm)
    db.session.flush()
    db.session.commit()

    return redirect("/vm/{}".format(vm.id))

M machines/templates/dashboard.html => machines/templates/dashboard.html +9 -9
@@ 10,7 10,7 @@
        <a href="https://man.sr.ht/machines.sr.ht">available here</a>.
      </p>
      <a
        href="/allocate"
        href="/vm/create"
        class="btn btn-primary btn-block"
      >Allocate new machine {{icon("caret-right")}}</a>
      <a


@@ 23,7 23,7 @@
      >Consult usage {{icon("caret-right")}}</a>
    </div>
    <div class="col-md-8">
      {% if not any(machines) %}
      {% if not any(vms) %}
      <p class="text-muted">
        You haven't created any machine yet.
      </p>


@@ 32,22 32,22 @@
        <input
          name="search"
          type="text"
          placeholder="Search your tasks"
          placeholder="Search your machines"
          class="form-control"
          value="{{ search if search else "" }}" />
      </form>

      <div class="event-list">
        {% for task in tasks %}
        {% for vm in vms %}
        <div class="event">
          <h4>
            <a href="{{url_for("html.edit_task", task_id=task.id)}}">
              {{ task.name }}
						<a href="/vm/{{vm.id}}">
								{{ vm.id }} {{ vm.name }}
            </a>
						<p>
						{{ vm.description }}
						</p>
          </h4>
          <p>
            {{ task.taskdef.description() }}
          </p>
        </div>
        {% endfor %}
      </div>

M machines/templates/host-create.html => machines/templates/host-create.html +0 -5
@@ 1,11 1,6 @@
{% extends "layout.html" %}
{% block content %}
<div class="row">
	<div class="col-md-4">
		<p>
		Create host.
		</p>
	</div>
	<div class="col-md-8">
		<h2>Connect new host</h2>
		<form method="POST" action="/host/create">

M machines/templates/hosts.html => machines/templates/hosts.html +39 -8
@@ 3,22 3,53 @@
<div class="row">
	<div class="col-md-4">
		<p>
		This page list hosts.
		This page allows you to manage hosts.
		</p>
		<a
			href="/host/create"
			class="btn btn-secondary btn-block"
			>Connect host {{icon("caret-right")}}</a>
			>Connect new host {{icon("caret-right")}}</a>
	</div>
	<div class="col-md-8">
		<table>
		<div class="host-table">
			<div class="id th">
				#
			</div>
			<div class="name th">
				Hostname
			</div>
			<div class="status th">
				Status
			</div>
			<div class="machines th">
				Machine Count
			</div>
			<div class="cores th">
				Cores
			</div>
			<div class="memory th">
				Memory
			</div>
			{% for host in hosts %}
			<tr>
				<td>{{ host.id }}</td>
				<td>{{ host.name }}</td>
			</tr>
			<div class="id">
				{{ host.id }}
			</div>
			<div class="name">
				{{ host.name }}
			</div>
			<div class="status">
				{{ host.status }}
			</div>
			<div class="machines">
				?
			</div>
			<div class="cores">
				{{ host.cores }}
			</div>
			<div class="memory">
				{{ host.memory }} GB
			</div>
			{% endfor %}
		</table>
		</div>
	</div>
</div>

R machines/templates/allocate.html => machines/templates/vm-create.html +82 -82
@@ 1,96 1,96 @@
{% extends "layout.html" %}
{% block title %}
<title>
  Allocate nachine
  &mdash;
  {{ cfg("sr.ht", "site-name") }} machines
	Allocate nachine
	&mdash;
	{{ cfg("sr.ht", "site-name") }} machines
</title>
{% endblock %}
{% block body %}
<div class="container">
  <div class="row">
    <div class="col-md-6">
      <h2>Allocate new machine</h2>
      <form method="POST" action="/allocate">
        {{csrf_token()}}
        <div class="form-group">
          <label for="name">Name</label>
          <input
            type="text"
            name="name"
            id="name"
            class="form-control {{valid.cls("name")}}"
            value="{{ name or "" }}"
            aria-describedby="name-help" />
          {{valid.summary("name")}}
        </div>
        <div class="form-group">
          <label for="description">Description</label>
          <textarea
            name="description"
            id="description"
            class="form-control {{valid.cls("description")}}"
            value="{{ description or "" }}"
            rows="5"
            aria-describedby="description-help">{{description or ""}}</textarea>
          <p id="description-help" class="form-text text-muted">
            Markdown supported
          </p>
          {{valid.summary("description")}}
        </div>
	<div class="row">
		<div class="col-md-6">
			<h2>Allocate new machine</h2>
			<form method="POST" action="/vm/create">
				{{csrf_token()}}
				<div class="form-group">
					<label for="name">Name</label>
					<input
						type="text"
						name="name"
						id="name"
						class="form-control {{valid.cls("name")}}"
						value="{{ name or "" }}"
						aria-describedby="name-help" />
					{{valid.summary("name")}}
				</div>
				<div class="form-group">
					<label for="description">Description</label>
					<textarea
						name="description"
						id="description"
						class="form-control {{valid.cls("description")}}"
						value="{{ description or "" }}"
						rows="5"
						aria-describedby="description-help">{{description or ""}}</textarea>
					<p id="description-help" class="form-text text-muted">
					Markdown supported
					</p>
					{{valid.summary("description")}}
				</div>
				<div class="form-row">
					<div class="col">
        <div class="form-group">
          <label for="name">CPU (cores)</label>
          <input
            type="text"
            name="name"
            id="name"
            class="form-control {{valid.cls("name")}}"
            value="{{ name or "" }}"
            aria-describedby="name-help" />
          {{valid.summary("name")}}
        </div>
            </div>
    <div class="col">
        <div class="form-group">
          <label for="name">Memory (GB)</label>
          <input
            type="text"
            name="name"
            id="name"
            class="form-control {{valid.cls("name")}}"
            value="{{ name or "" }}"
            aria-describedby="name-help" />
          {{valid.summary("name")}}
        </div>
            </div>
    <div class="col">
        <div class="form-group">
          <label for="name">Storage (GB)</label>
          <input
            type="text"
            name="name"
            id="name"
            class="form-control {{valid.cls("name")}}"
            value="{{ name or "" }}"
            aria-describedby="name-help" />
          {{valid.summary("name")}}
        </div>
		</div>
						<div class="form-group">
							<label for="cores">CPU (cores)</label>
							<input
								type="text"
								name="cores"
								id="cores"
								class="form-control {{valid.cls("cores")}}"
								value="{{ name or "" }}"
								aria-describedby="cores-help" />
							{{valid.summary("cores")}}
						</div>
					</div>
					<div class="col">
						<div class="form-group">
							<label for="memory">Memory (GB)</label>
							<input
								type="text"
								name="memory"
								id="memory"
								class="form-control {{valid.cls("memory")}}"
								value="{{ name or "" }}"
								aria-describedby="memory-help" />
							{{valid.summary("memory")}}
						</div>
					</div>
					<div class="col">
						<div class="form-group">
							<label for="storage">Storage (GB)</label>
							<input
								type="text"
								name="storage"
								id="storage"
								class="form-control {{valid.cls("storage")}}"
								value="{{ name or "" }}"
								aria-describedby="storage-help" />
							{{valid.summary("storage")}}
						</div>
					</div>
				</div>

        {{valid.summary()}}
				{{valid.summary()}}

        <button
          type="submit"
          class="btn btn-primary"
          name="create"
        >
          Allocate machine {{icon("caret-right")}}
        </button>
      </form>
    </div>
  </div>
				<button
					type="submit"
					class="btn btn-primary"
					name="create"
					>
					Allocate machine {{icon("caret-right")}}
				</button>
			</form>
		</div>
	</div>
</div>
{% endblock %}

A machines/templates/vm.html => machines/templates/vm.html +20 -0
@@ 0,0 1,20 @@
{% extends "layout.html" %}
{% block content %}
<div class="row">
	<div class="col-md-8">
		<h2>{{ vm.name }}</h2>

		<h3>History</h3>
		<table class="table">
			<thead>
				<tr>
					<th>Date</th>
					<th>Action</th>
				</tr>
			</thead>
			<tbody>
			</tbody>
		</table>
	</div>
</div>
{% endblock %}

M machines/types/machine.py => machines/types/machine.py +1 -1
@@ 20,5 20,5 @@ class Machine(Base):
            nullable=False,
            default=MachineStatus.pending)

    host_id = sa.Column(sa.Integer, sa.ForeignKey("host.id"), nullable=False)
    host_id = sa.Column(sa.Integer, sa.ForeignKey("host.id"), nullable=True)
    host = sa.orm.relationship("Host", backref=sa.orm.backref("machines"))

R run.py => run-master.py +0 -0

M scss/main.scss => scss/main.scss +9 -5
@@ 1,6 1,6 @@
@import "base";

.usage-table {
.host-table {
  width: 100%;
  border-right: 1px solid #ced4da;
  border-bottom: 1px solid #ced4da;


@@ 14,6 14,10 @@
    color: $gray-900;
  }

  .th {
    font-weight: bold;
  }

  @include media-breakpoint-down(xs) {
    display: block;
    border: none;


@@ 24,7 28,7 @@
      border: none !important;
      padding: 0 !important;

      &:nth-child(5n+4) {
      &:nth-child(6n+4) {
        margin-bottom: 1rem;
      }
    }


@@ 77,13 81,13 @@
      }
    }

    @for $i from 1 through 5 {
      &:nth-child(5n+#{$i}) {
    @for $i from 1 through 6 {
      &:nth-child(6n+#{$i}) {
        grid-column-start: $i;
      }

      // Striped rows
      &:nth-child(10n+#{$i}) {
      &:nth-child(12n+#{$i}) {
        background: rgba(0,0,0,.05);
      }
    }