Repository navigation
v0.2.2a (base image generator bugfix, code reform)
This is an alpha patch release of v0.2.2. API requests are identical.
You can download and use same client app from v0.2.2-RELEASE.
Some bugfix was applied to server configuration scripts.
Code has been refactorized to clearer style:
See linux_virt_unit submodule's incus_unit/change_container_status.go:
// ChangeState changes the state of a container (start, stop, restart, pause).
func ChangeState(tag string, newState string) error {
log.Printf("ChangeState: Request to change state of container '%s' to '%s'.", tag, newState)
// Update the container status in MongoDB
_, err := db.ContainerInfoCollection.UpdateOne(
context.Background(),
bson.M{"TAG": tag},
bson.D{{"$set", bson.M{"vmstatus": newState}}},
)
if err != nil {
log.Printf("ChangeState: MongoDB update failed for tag '%s' to state '%s': %v", tag, newState, err)
return fmt.Errorf("failed to update container status in DB: %w", err)
}
log.Printf("ChangeState: MongoDB status updated for tag '%s' to '%s'.", tag, newState)
// Get the Incus instance information
inst, _, err := IncusCli.GetInstance(tag)
if err != nil {
log.Printf("ChangeState: Failed to get Incus instance information for tag '%s': %v", tag, err)
return fmt.Errorf("failed to get Incus instance: %w", err)
}
log.Printf("ChangeState: Current status of Incus instance '%s': %s.", tag, inst.Status)
// Handle state change
req := api.InstanceStatePut{
Action: newState,
Timeout: 30,
Force : true,
}
op, err := IncusCli.UpdateInstanceState(tag, req, "")
if err != nil {
log.Printf("ChangeState: Incus %s request failed for tag '%s': %v", newState, tag, err)
return fmt.Errorf("failed to request Incus %s: %w", newState, err)
}
log.Printf("ChangeState: Incus %s request sent for tag '%s'.", newState, tag)
// Wait for the Incus operation to complete
err = op.Wait()
if err != nil {
log.Printf("ChangeState: Incus operation %s wait failed for tag '%s': %v", newState, tag, err)
return fmt.Errorf("failed to wait for Incus %s: %w", newState, err)
}
log.Printf("ChangeState: Incus operation %s completed for tag '%s'.", newState, tag)
// Update DB status after Incus operation
_, err = db.ContainerInfoCollection.UpdateOne(
context.Background(),
bson.M{"TAG": tag},
bson.D{{"$set", bson.M{"vmstatus": inst.Status}}},
)
if err != nil {
log.Printf("ChangeState: MongoDB update to %s failed for tag '%s': %v", newState, tag, err)
return fmt.Errorf("failed to update container status to %s in DB: %w", newState, err)
}
log.Printf("ChangeState: MongoDB status updated to %s for tag '%s'.", newState, tag)
return nil
}```
Duplicated code implementations are deleted, and unified without dirty if-else conditions.
Also, see here: incus_unit/handle_container_state_change.go
```go
func ChangeStateHandler(state string) http.HandlerFunc {
return func(wr http.ResponseWriter, req *http.Request) {
tagBytes, err := io.ReadAll(req.Body)
if err != nil {
log.Printf("%s: Failed to read request body: %v", state, err)
http.Error(wr, err.Error(), http.StatusBadRequest)
return
}
Tag := strings.Trim(string(tagBytes), "\"")
log.Printf("%s: Received request to stop container with tag '%s'.", state, Tag)
err = ChangeState(Tag, state)
if err != nil {
log.Printf("%s: ChangeState failed for tag '%s': %v", state, Tag, err)
http.Error(wr, err.Error(), http.StatusInternalServerError)
return
}
wr.WriteHeader(http.StatusOK)
wr.Write([]byte(fmt.Sprintf("%s command sent for container '%s'", state, Tag)))
}
}```
Endpoint handler is generated by this function.
Actual application from http_request module is:
```go
linux_virt_unit.LinuxVirtualizationAPIRouter.HandleFunc("/stop", incus_unit.ChangeStateHandler("stop")).Methods("POST")
linux_virt_unit.LinuxVirtualizationAPIRouter.HandleFunc("/start", incus_unit.ChangeStateHandler("start")).Methods("POST")
linux_virt_unit.LinuxVirtualizationAPIRouter.HandleFunc("/pause", incus_unit.ChangeStateHandler("freeze")).Methods("POST")
linux_virt_unit.LinuxVirtualizationAPIRouter.HandleFunc("/resume", incus_unit.ChangeStateHandler("unfreeze")).Methods("POST")
linux_virt_unit.LinuxVirtualizationAPIRouter.HandleFunc("/restart", incus_unit.ChangeStateHandler("restart")).Methods("POST")Now code form is much more integrated by functional demands.
Also, see this utility at utils/make_base_images.sh:
elif incus exec "$container_name" -- grep -qi 'slackware' /etc/os-release; then
incus exec "$container_name" -- sh -c "slackpkg clean-cache"
incus exec "$container_name" -- sh -c "slackpkg update gpg"
incus exec "$container_name" -- sh -c "slackpkg update"
incus exec "$container_name" -- sh -c "slackpkg install openssh sudo"
incus exec "$container_name" -- sh -c "sed -i '\$d' /etc/slackpkg/slackpkg.conf"
incus exec "$container_name" -- sh -c "sed -i '\$d' /etc/slackpkg/slackpkg.conf"
(...)gpg update should go first.
Previous script has this problem:
update with old gpg->update gpg->md5 checksum mismatch.
From the perspective of user input:
Saw automated logs with slackpkg update->typed YES into gpg update interaction->md5 mismatch->image generation failed.
With this bugpatch, slackware image should work fine.
Also, in conSSH.sh:
(...)
if ! test -f /usr/bin/systemctl;
then
if test -d /etc/rc.d;
then
chmod +x /etc/rc.d/rc.sshd
/etc/rc.d/rc.sshd restart
elif test -d /etc/init.d;
then
chmod +x /etc/rc.d/rc.sshd
/etc/init.d/ssh restart
else
chmod +x /etc/*.d/*ssh*
/etc/*.d/*ssh* restart
fi
else
systemctl restart sshd
systemctl restart ssh
systemctl enable ssh
systemctl enable sshd
fi
(...)ssh execute permission added.
Without this, when rebooting server, since secure shell is automatically disabled, you would not be able to connect into remote incus container. This is not a good behavior.