Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 56 additions & 35 deletions internal/app/server/routes/boot/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/labstack/echo/v4"
"github.com/pkg/errors"
"github.com/sargassum-world/godest"
"github.com/sargassum-world/godest/turbostreams"

ipc "github.com/openUC2/device-admin/internal/app/ipc/boot"
sh "github.com/openUC2/device-admin/internal/app/server/handling"
Expand Down Expand Up @@ -59,53 +60,73 @@ func (h *Handlers) HandleBootGet() echo.HandlerFunc {
}

func (h *Handlers) HandleBootPost() echo.HandlerFunc {
st := "boot/shutdown-progress.partial.tmpl"
h.r.MustHave(st)
return func(c echo.Context) error {
// Parse params
state := c.FormValue("state")
redirectTarget := c.FormValue("redirect-target")

// Run queries
ctx := c.Request().Context()
switch state {
default:
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf(
"invalid boot state %s", state,
))
case "soft-rebooted":
if err := shutdownViaSidecar(ctx, "SoftReboot", h.scc, h.l); err != nil {
if sdErr := h.sdc.SoftReboot(ctx); err != nil {
return errors.Wrapf(
sdErr, "couldn't soft-reboot through sidecar (%s) or directly", err.Error(),
)
}
h.l.Warnf("soft-rebooted directly after failure to soft-reboot through sidecar", err)
if err := shutdown(ctx, state, h.scc, h.sdc, h.l); err != nil {
return err
}
// Redirect user
if turbostreams.Accepted(c.Request().Header) {
return h.r.TurboStream(
c.Response(),
turbostreams.Message{
Action: turbostreams.ActionAppend,
Target: "boot_buttons",
Template: st,
Data: map[string]any{
"state": state,
},
},
)
}
return c.Redirect(http.StatusSeeOther, redirectTarget)
}
}

func shutdown(
ctx context.Context, state string, scc *sc.Client, sdc *sd.Client, l godest.Logger,
) error {
switch state {
default:
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf(
"invalid boot state %s", state,
))
case "soft-rebooted":
if err := shutdownViaSidecar(ctx, "SoftReboot", scc, l); err != nil {
if sdErr := sdc.SoftReboot(ctx); err != nil {
return errors.Wrapf(
sdErr, "couldn't soft-reboot through sidecar (%s) or directly", err.Error(),
)
}
// Redirect user
return c.Redirect(http.StatusSeeOther, redirectTarget)
case "rebooted":
if err := shutdownViaSidecar(ctx, "Reboot", h.scc, h.l); err != nil {
if sdErr := h.sdc.Reboot(ctx); err != nil {
return errors.Wrapf(
sdErr, "couldn't reboot through sidecar (%s) or directly", err.Error(),
)
}
h.l.Warnf("rebooted directly after failure to reboot through sidecar", err)
l.Warnf("soft-rebooted directly after failure to soft-reboot through sidecar", err)
}
case "rebooted":
if err := shutdownViaSidecar(ctx, "Reboot", scc, l); err != nil {
if sdErr := sdc.Reboot(ctx); err != nil {
return errors.Wrapf(
sdErr, "couldn't reboot through sidecar (%s) or directly", err.Error(),
)
}
// Redirect user
return c.Redirect(http.StatusSeeOther, redirectTarget)
case "powered-off":
if err := shutdownViaSidecar(ctx, "Poweroff", h.scc, h.l); err != nil {
if sdErr := h.sdc.Poweroff(ctx); err != nil {
return errors.Wrapf(
sdErr, "couldn't power-off through sidecar (%s) or directly", err.Error(),
)
}
h.l.Warnf("powered-off directly after failure to power-off through sidecar", err)
l.Warnf("rebooted directly after failure to reboot through sidecar", err)
}
case "powered-off":
if err := shutdownViaSidecar(ctx, "Poweroff", scc, l); err != nil {
if sdErr := sdc.Poweroff(ctx); err != nil {
return errors.Wrapf(
sdErr, "couldn't power-off through sidecar (%s) or directly", err.Error(),
)
}
// Redirect user
return c.Redirect(http.StatusSeeOther, redirectTarget)
l.Warnf("powered-off directly after failure to power-off through sidecar", err)
}
}
return nil
}

func shutdownViaSidecar(ctx context.Context, method string, scc *sc.Client, l godest.Logger) error {
Expand Down
18 changes: 8 additions & 10 deletions web/templates/boot/index.minimal.page.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,14 @@
{{end}}

<section class="section content">
<div class="field is-grouped">
{{
template "shared/boot/buttons.partial.tmpl" dict
"basePath" .Meta.BasePath
"redirectTarget" (urlJoin (dict
"path" .Meta.Path
"query" .Meta.Form.Encode
))
}}
</div>
{{
template "shared/boot/buttons.partial.tmpl" dict
"basePath" .Meta.BasePath
"redirectTarget" (urlJoin (dict
"path" .Meta.Path
"query" .Meta.Form.Encode
))
}}
</section>
</main>
{{end}}
18 changes: 8 additions & 10 deletions web/templates/boot/index.page.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,14 @@
A soft reboot speeds up the reboot process by leaving the OS kernel running, while
a full reboot includes a full restart of the kernel and hardware:
</p>
<div class="field is-grouped">
{{
template "shared/boot/buttons.partial.tmpl" dict
"basePath" .Meta.BasePath
"redirectTarget" (urlJoin (dict
"path" .Meta.Path
"query" .Meta.Form.Encode
))
}}
</div>
{{
template "shared/boot/buttons.partial.tmpl" dict
"basePath" .Meta.BasePath
"redirectTarget" (urlJoin (dict
"path" .Meta.Path
"query" .Meta.Form.Encode
))
}}
</section>
</main>
{{end}}
12 changes: 12 additions & 0 deletions web/templates/boot/shutdown-progress.partial.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{$state := get . "state"}}

<article class="message is-info mb-3">
<div class="message-body">
{{if eq $state "powered-off"}}
Shutting down...
{{else}}
Rebooting...
{{end}}
</div>
</article>

18 changes: 8 additions & 10 deletions web/templates/home/index.page.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,14 @@
A soft reboot speeds up the reboot process by leaving the OS kernel running, while
a full reboot includes a full restart of the kernel and hardware:
</p>
<div class="field is-grouped">
{{
template "shared/boot/buttons.partial.tmpl" dict
"basePath" .Meta.BasePath
"redirectTarget" (urlJoin (dict
"path" .Meta.Path
"query" .Meta.Form.Encode
))
}}
</div>
{{
template "shared/boot/buttons.partial.tmpl" dict
"basePath" .Meta.BasePath
"redirectTarget" (urlJoin (dict
"path" .Meta.Path
"query" .Meta.Form.Encode
))
}}
</div>
</section>
</main>
Expand Down
116 changes: 60 additions & 56 deletions web/templates/shared/boot/buttons.partial.tmpl
Original file line number Diff line number Diff line change
@@ -1,60 +1,64 @@
{{$basePath := (get . "basePath")}}
{{$redirectTarget := (get . "redirectTarget")}}

<div class="control">
<form
action="{{$basePath}}boot"
method="POST"
data-controller="form-submission"
data-action="submit->form-submission#submit"
data-form-submission-target="submitter"
class="mb-3"
>
<input type="hidden" name="state" value="soft-rebooted">
<input type="hidden" name="redirect-target" value="{{$redirectTarget}}">
<input
class="button is-primary"
type="submit"
value="Soft reboot"
data-form-submission-target="submit"
>
</form>
</div>
<div class="control">
<form
action="{{$basePath}}boot"
method="POST"
data-controller="form-submission"
data-action="submit->form-submission#submit"
data-form-submission-target="submitter"
class="mb-3"
>
<input type="hidden" name="state" value="rebooted">
<input type="hidden" name="redirect-target" value="{{$redirectTarget}}">
<input
class="button is-primary"
type="submit"
value="Full reboot"
data-form-submission-target="submit"
>
</form>
</div>
<div class="control">
<form
action="{{$basePath}}boot"
method="POST"
data-controller="form-submission"
data-action="submit->form-submission#submit"
data-form-submission-target="submitter"
class="mb-3"
>
<input type="hidden" name="state" value="powered-off">
<input type="hidden" name="redirect-target" value="{{$redirectTarget}}">
<input
class="button is-primary"
type="submit"
value="Shut down"
data-form-submission-target="submit"
>
</form>
<div id="boot_buttons">
<div class="field is-grouped">
<div class="control">
<form
action="{{$basePath}}boot"
method="POST"
data-controller="form-submission"
data-action="submit->form-submission#submit"
data-form-submission-target="submitter"
class="mb-3"
>
<input type="hidden" name="state" value="soft-rebooted">
<input type="hidden" name="redirect-target" value="{{$redirectTarget}}">
<input
class="button is-primary"
type="submit"
value="Soft reboot"
data-form-submission-target="submit"
>
</form>
</div>
<div class="control">
<form
action="{{$basePath}}boot"
method="POST"
data-controller="form-submission"
data-action="submit->form-submission#submit"
data-form-submission-target="submitter"
class="mb-3"
>
<input type="hidden" name="state" value="rebooted">
<input type="hidden" name="redirect-target" value="{{$redirectTarget}}">
<input
class="button is-primary"
type="submit"
value="Full reboot"
data-form-submission-target="submit"
>
</form>
</div>
<div class="control">
<form
action="{{$basePath}}boot"
method="POST"
data-controller="form-submission"
data-action="submit->form-submission#submit"
data-form-submission-target="submitter"
class="mb-3"
>
<input type="hidden" name="state" value="powered-off">
<input type="hidden" name="redirect-target" value="{{$redirectTarget}}">
<input
class="button is-primary"
type="submit"
value="Shut down"
data-form-submission-target="submit"
>
</form>
</div>
</div>
</div>
Loading