Wire initial VM management frontend
This commit is contained in:
parent
053d5a3320
commit
7e6439be67
8 changed files with 242 additions and 1 deletions
0
lib/opennebula.ex
Normal file
0
lib/opennebula.ex
Normal file
|
@ -22,12 +22,88 @@ defmodule RecycledCloud.OpenNebula.VM do
|
|||
{:cloning_failure, 11}
|
||||
]
|
||||
|
||||
@actions [
|
||||
"terminate-hard",
|
||||
"terminate",
|
||||
"undeploy-hard",
|
||||
"undeploy",
|
||||
"poweroff-hard",
|
||||
"poweroff",
|
||||
"reboot-hard",
|
||||
"reboot",
|
||||
"hold",
|
||||
"release",
|
||||
"stop",
|
||||
"suspend",
|
||||
"resume",
|
||||
"resched",
|
||||
"unresched"
|
||||
]
|
||||
|
||||
@events [
|
||||
{:NONE_ACTION , 0},
|
||||
{:MIGRATE_ACTION , 1},
|
||||
{:LIVE_MIGRATE_ACTION , 2},
|
||||
{:SHUTDOWN_ACTION , 3},
|
||||
{:SHUTDOWN_HARD_ACTION , 4},
|
||||
{:UNDEPLOY_ACTION , 5},
|
||||
{:UNDEPLOY_HARD_ACTION , 6},
|
||||
{:HOLD_ACTION , 7},
|
||||
{:RELEASE_ACTION , 8},
|
||||
{:STOP_ACTION , 9},
|
||||
{:SUSPEND_ACTION , 10},
|
||||
{:RESUME_ACTION , 11},
|
||||
{:BOOT_ACTION , 12},
|
||||
{:DELETE_ACTION , 13},
|
||||
{:DELETE_RECREATE_ACTION , 14},
|
||||
{:REBOOT_ACTION , 15},
|
||||
{:REBOOT_HARD_ACTION , 16},
|
||||
{:RESCHED_ACTION , 17},
|
||||
{:UNRESCHED_ACTION , 18},
|
||||
{:POWEROFF_ACTION , 19},
|
||||
{:POWEROFF_HARD_ACTION , 20},
|
||||
{:DISK_ATTACH_ACTION , 21},
|
||||
{:DISK_DETACH_ACTION , 22},
|
||||
{:NIC_ATTACH_ACTION , 23},
|
||||
{:NIC_DETACH_ACTION , 24},
|
||||
{:DISK_SNAPSHOT_CREATE_ACTION , 25},
|
||||
{:DISK_SNAPSHOT_DELETE_ACTION , 26},
|
||||
{:TERMINATE_ACTION , 27},
|
||||
{:TERMINATE_HARD_ACTION , 28},
|
||||
{:DISK_RESIZE_ACTION , 29},
|
||||
{:DEPLOY_ACTION , 30},
|
||||
{:CHOWN_ACTION , 31},
|
||||
{:CHMOD_ACTION , 32},
|
||||
{:UPDATECONF_ACTION , 33},
|
||||
{:RENAME_ACTION , 34},
|
||||
{:RESIZE_ACTION , 35},
|
||||
{:UPDATE_ACTION , 36},
|
||||
{:SNAPSHOT_CREATE_ACTION , 37},
|
||||
{:SNAPSHOT_DELETE_ACTION , 38},
|
||||
{:SNAPSHOT_REVERT_ACTION , 39},
|
||||
{:DISK_SAVEAS_ACTION , 40},
|
||||
{:DISK_SNAPSHOT_REVERT_ACTION , 41},
|
||||
{:RECOVER_ACTION , 42},
|
||||
{:RETRY_ACTION , 43},
|
||||
{:MONITOR_ACTION , 44},
|
||||
{:DISK_SNAPSHOT_RENAME_ACTION , 45},
|
||||
{:ALIAS_ATTACH_ACTION , 46},
|
||||
{:ALIAS_DETACH_ACTION , 47},
|
||||
]
|
||||
|
||||
def state_for(state) when is_atom(state) do
|
||||
@states |> Keyword.get(state)
|
||||
end
|
||||
|
||||
def state_for(state) when is_integer(state) do
|
||||
case Enum.find(@states, fn {atom, value} -> value == state end) do
|
||||
case Enum.find(@states, fn {_atom, value} -> value == state end) do
|
||||
{atom, _value} -> atom
|
||||
nil -> nil
|
||||
end
|
||||
end
|
||||
|
||||
def event_for(event) when is_integer(event) do
|
||||
case Enum.find(@events, fn {_atom, value} -> value == event end) do
|
||||
{atom, _value} -> atom
|
||||
nil -> nil
|
||||
end
|
||||
|
@ -43,4 +119,23 @@ defmodule RecycledCloud.OpenNebula.VM do
|
|||
{:error, err} -> {:error, err}
|
||||
end
|
||||
end
|
||||
|
||||
def get_by_username(username) do
|
||||
{:ok, %{VM: vms}} = RecycledCloud.OpenNebula.VMPool.get(%{
|
||||
filter_flag: :all,
|
||||
range_start: :infinite,
|
||||
range_end: :infinite,
|
||||
state_filter: state_for(:any_except_done),
|
||||
kv_filter: ""
|
||||
})
|
||||
|
||||
Enum.filter(vms, fn vm -> List.to_string(Map.get(vm, :UNAME)) == username end)
|
||||
end
|
||||
|
||||
def execute(vm_id, action) when action in @actions do
|
||||
case ONE.query("one.vm.action", [action, vm_id]) do
|
||||
{:ok, _raw} -> :ok
|
||||
{:error, err} -> {:error, err}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
defmodule RecycledCloudWeb.VirtualMachineHostingController do
|
||||
use RecycledCloudWeb, :controller
|
||||
|
||||
alias RecycledCloud.OpenNebula.VM
|
||||
|
||||
def index(conn, _params) do
|
||||
username = conn.assigns.current_user.username
|
||||
vms = VM.get_by_username(username)
|
||||
|
||||
render(conn, "index.html", vms: vms)
|
||||
end
|
||||
|
||||
def start(conn, %{"id" => id}) do
|
||||
case VM.execute(String.to_integer(id), "resume") do
|
||||
:ok ->
|
||||
conn
|
||||
|> put_flash(:info, "Start request sent to VMM.")
|
||||
|> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
|
||||
{:error, err} ->
|
||||
conn
|
||||
|> put_flash(:error, "Something went wrong: #{inspect(err)}")
|
||||
|> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
|
||||
end
|
||||
end
|
||||
|
||||
def stop(conn, %{"id" => id}) do
|
||||
case VM.execute(String.to_integer(id), "poweroff") do
|
||||
:ok ->
|
||||
conn
|
||||
|> put_flash(:stop, "Stop request sent to VMM.")
|
||||
|> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
|
||||
{:error, err} ->
|
||||
conn
|
||||
|> put_flash(:error, "Something went wrong: #{inspect(err)}")
|
||||
|> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
case VM.get(String.to_integer(id)) do
|
||||
{:error, err} ->
|
||||
conn
|
||||
|> put_flash(:error, "Could not fetch VM details: #{inspect(err)}")
|
||||
|> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
|
||||
{:ok, vm} ->
|
||||
owner = vm |> Map.get(:UNAME) |> List.to_string
|
||||
if owner == conn.assigns.current_user.username do
|
||||
conn
|
||||
|> assign(:vm, vm)
|
||||
|> render("show.html")
|
||||
else
|
||||
conn
|
||||
|> put_flash(:error, "You are not the owner of this machine.")
|
||||
|> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -74,6 +74,11 @@ defmodule RecycledCloudWeb.Router do
|
|||
get "/users/settings/keys/:key_id/delete", UserKeysController, :delete
|
||||
get "/billing", BillingController, :index
|
||||
post "/billing/partner/update", BillingController, :update
|
||||
|
||||
get "/hosting/vm", VirtualMachineHostingController, :index
|
||||
get "/hosting/vm/:id", VirtualMachineHostingController, :show
|
||||
get "/hosting/vm/:id/start", VirtualMachineHostingController, :start
|
||||
get "/hosting/vm/:id/stop", VirtualMachineHostingController, :stop
|
||||
end
|
||||
|
||||
scope "/", RecycledCloudWeb do
|
||||
|
|
|
@ -6,13 +6,25 @@
|
|||
<li><%= link "Settings", to: Routes.user_settings_path(@conn, :edit) %></li>
|
||||
<li><%= link "Billing", to: Routes.billing_path(@conn, :index) %></li>
|
||||
<li><%= link "Log out", to: Routes.user_session_path(@conn, :delete), method: :delete %></li>
|
||||
<hr />
|
||||
<!--
|
||||
<li><%= link "Web Hosting", to: Routes.page_path(@conn, :index) %></li>
|
||||
<li><%= link "Name Service", to: Routes.page_path(@conn, :index) %></li>
|
||||
<li><%= link "Storage Services", to: Routes.page_path(@conn, :index) %></li>
|
||||
-->
|
||||
<li><%= link "Virtual Machines", to: Routes.virtual_machine_hosting_path(@conn, :index) %></li>
|
||||
<% else %>
|
||||
<li><%= link "Log in", to: Routes.user_session_path(@conn, :new) %></li>
|
||||
<li><%= link "Register", to: Routes.user_registration_path(@conn, :new) %></li>
|
||||
<% end %>
|
||||
<hr />
|
||||
<li>
|
||||
<a href="https://status.recycled.cloud">
|
||||
Infrastructure status
|
||||
</a>
|
||||
</li>
|
||||
<a href="https://recycled.cloud">
|
||||
Back to recycled.cloud ↵
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<h1>Virtual Machines</h1>
|
||||
|
||||
<p>This page list all the Virtual Machines linked to your account. It is
|
||||
not possible to interect with them yet.</p>
|
||||
|
||||
<%= for location <- ["LNTH"] do %>
|
||||
<h2>Location: <%= location %></h2>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>State</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%= for vm <- @vms do %>
|
||||
<tr>
|
||||
<td><%= Map.get(vm, :ID) %></td>
|
||||
<td><%= Map.get(vm, :NAME) %></td>
|
||||
<td><%= VM.state_for(Map.get(vm, :STATE)) %></td>
|
||||
<td>
|
||||
<%= case VM.state_for(Map.get(vm, :STATE)) do
|
||||
:poweroff ->
|
||||
link "start", to: Routes.virtual_machine_hosting_path(@conn, :start, Map.get(vm, :ID))
|
||||
:active ->
|
||||
link "stop", to: Routes.virtual_machine_hosting_path(@conn, :stop, Map.get(vm, :ID))
|
||||
_ -> ""
|
||||
end %>
|
||||
|
||||
<%= link "show details", to: Routes.virtual_machine_hosting_path(@conn, :show, Map.get(vm, :ID)) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% end %>
|
|
@ -0,0 +1,27 @@
|
|||
<h1>VM#<%= Map.get(@vm, :ID) %> - <%= Map.get(@vm, :NAME) %></h1>
|
||||
|
||||
<ul>
|
||||
<li>State: <b><%= VM.state_for(Map.get(@vm, :STATE)) %></b></li>
|
||||
<li>LCM State: <b><%= Map.get(@vm, :LCM_STATE) %></b></li<
|
||||
</ul>
|
||||
|
||||
<h2>History</h2>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Time</th>
|
||||
<th>Action</th>
|
||||
<th>Host</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%= for entry <- @vm |> Map.get(:HISTORY_RECORDS) |> Map.get(:HISTORY) do %>
|
||||
<tr>
|
||||
<td><%= DateTime.from_unix!(Map.get(entry, :STIME)) %></td>
|
||||
<td><%= VM.event_for(Map.get(entry, :ACTION)) %></td>
|
||||
<td><%= Map.get(entry, :HOSTNAME) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
|
@ -0,0 +1,5 @@
|
|||
defmodule RecycledCloudWeb.VirtualMachineHostingView do
|
||||
use RecycledCloudWeb, :view
|
||||
|
||||
alias RecycledCloud.OpenNebula.VM
|
||||
end
|
Loading…
Reference in a new issue