125 lines
4.6 KiB
Plaintext
125 lines
4.6 KiB
Plaintext
<% @page_title = @vm.name
|
|
|
|
viewable_fws =
|
|
dataset_authorize(Firewall.where(id: @vm.firewalls.map(&:id)), "Firewall:view")
|
|
.select_hash(:id, Sequel.as(true, :v))
|
|
.transform_keys! { UBID.from_uuidish(it).to_s } %>
|
|
|
|
<% if @vm.display_state != "running" %>
|
|
<div class="auto-refresh hidden" data-interval="10"></div>
|
|
<% end %>
|
|
|
|
<%== part(
|
|
"components/page_header",
|
|
breadcrumbs: [
|
|
%w[Projects /project],
|
|
[@project_data[:name], @project_data[:path]],
|
|
["Virtual Machines", "#{@project_data[:path]}/vm"],
|
|
[@vm.name, "#"]
|
|
],
|
|
left_items: [part("components/vm_state_label", state: @vm.display_state, extra_class: "text-md")]
|
|
) %>
|
|
|
|
<% data = [
|
|
["ID", @vm.ubid],
|
|
["Name", @vm.name],
|
|
["Location", @vm.display_location],
|
|
["Size", @vm.display_size],
|
|
["Storage", (@vm.storage_size_gib > 0) ? "#{@vm.storage_size_gib} GB" : nil]
|
|
]
|
|
if (gpu = @vm.display_gpu)
|
|
data << ["GPU", gpu]
|
|
end
|
|
subnet = @vm.nics.first.private_subnet
|
|
data += [
|
|
["IPv4", @vm.ip4_enabled ? @vm.ephemeral_net4 : "Not enabled", { copyable: @vm.ip4_enabled }],
|
|
["IPv6", @vm.ip6, { copyable: true }],
|
|
[
|
|
"SSH Command",
|
|
"<span class='bg-slate-100 text-rose-500 font-mono px-2 py-1 rounded'>#{h("ssh -i <PRIVATE_KEY_PATH> #{@vm.unix_user}@#{@vm.ephemeral_net4 || @vm.ip6}")}</span>",
|
|
{ escape: false }
|
|
],
|
|
["Private IPv4", @vm.private_ipv4, { copyable: true }],
|
|
["Private IPv6", @vm.private_ipv6, { copyable: true }],
|
|
[
|
|
"Private subnet",
|
|
"<a href='#{path(subnet)}' class='text-rose-500 hover:underline'>#{subnet.name}</a>",
|
|
{ escape: false }
|
|
]
|
|
] %>
|
|
|
|
<div class="grid gap-6">
|
|
<!-- Vm Detail Card -->
|
|
<%== part(
|
|
"components/kv_data_card",
|
|
data:
|
|
) %>
|
|
<!-- Firewall Rule List -->
|
|
<%== part(
|
|
"components/table_card",
|
|
title: "Applied Firewall Rules",
|
|
headers: ["Firewall", "CIDR", "Port Range"],
|
|
empty_state: "This VM doesn't have applied firewall",
|
|
rows:
|
|
@vm.firewalls.flat_map do |fw|
|
|
view_perm = viewable_fws[fw.ubid]
|
|
(fw.firewall_rules || []).map do |fwr|
|
|
[
|
|
[[fw.name, view_perm ? { link: path(fw)} : {}], fwr.cidr, fwr.display_port_range],
|
|
{ id: "firewall-rule-#{fwr.ubid}" }
|
|
]
|
|
end
|
|
end
|
|
) %>
|
|
<!-- Danger Zone -->
|
|
<div>
|
|
<div class="md:flex md:items-center md:justify-between pb-2 lg:pb-4">
|
|
<div class="min-w-0 flex-1">
|
|
<h3 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-2xl sm:tracking-tight">
|
|
Danger Zone
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
<div class="overflow-hidden rounded-lg shadow ring-1 ring-black ring-opacity-5 bg-white divide-y divide-gray-200">
|
|
<!-- Restart Card -->
|
|
<% if has_permission?("Vm:edit", @vm.id) %>
|
|
<div class="px-4 py-5 sm:p-6">
|
|
<form action="<%= "#{path(@vm)}/restart" %>" role="form" method="POST">
|
|
<%== csrf_tag("#{path(@vm)}/restart") %>
|
|
<div class="sm:flex sm:items-center sm:justify-between">
|
|
<div>
|
|
<h3 class="text-base font-semibold leading-6 text-gray-900">Restart virtual machine</h3>
|
|
<div class="mt-2 text-sm text-gray-500">
|
|
<p>This action will restart the virtual machine, causing it to be temporarily offline.</p>
|
|
</div>
|
|
</div>
|
|
<div id="vm-restart-<%= @vm.ubid %>" class="mt-5 sm:ml-6 sm:mt-0 sm:flex sm:flex-shrink-0 sm:items-center">
|
|
<div class="col-span-12 sm:col-span-2 flex justify-end items-end">
|
|
<%== part("components/form/submit_button", text: "Restart", extra_class: "restart-btn") %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<% end %>
|
|
<!-- Delete Card -->
|
|
<% if has_permission?("Vm:delete", @vm.ubid) %>
|
|
<div class="px-4 py-5 sm:p-6">
|
|
<div class="sm:flex sm:items-center sm:justify-between">
|
|
<div>
|
|
<h3 class="text-base font-semibold leading-6 text-gray-900">Delete virtual machine</h3>
|
|
<div class="mt-2 text-sm text-gray-500">
|
|
<p>This action will permanently delete this virtual machine. Deleted data cannot be recovered. Use it
|
|
carefully.</p>
|
|
</div>
|
|
</div>
|
|
<div id="vm-delete-<%= @vm.ubid %>" class="mt-5 sm:ml-6 sm:mt-0 sm:flex sm:flex-shrink-0 sm:items-center">
|
|
<%== part("components/delete_button", confirmation: @vm.name, redirect: "#{@project_data[:path]}/vm") %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
</div>
|