Skip to content
This repository has been archived by the owner on Dec 7, 2023. It is now read-only.

Commit

Permalink
Merge pull request #300 from twelho/extenal-startup
Browse files Browse the repository at this point in the history
Runtime state set by Ignite (StartVM), ignite-spawn only handles shutdown
  • Loading branch information
luxas authored Aug 8, 2019
2 parents 501de78 + 94f7149 commit 6a40c22
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 57 deletions.
54 changes: 16 additions & 38 deletions cmd/ignite-spawn/ignite-spawn.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ package main

import (
"fmt"
"net"
"os"
"path"

log "github.com/sirupsen/logrus"
api "github.com/weaveworks/ignite/pkg/apis/ignite"
"github.com/weaveworks/ignite/pkg/apis/ignite/scheme"
meta "github.com/weaveworks/ignite/pkg/apis/meta/v1alpha1"
"github.com/weaveworks/ignite/pkg/constants"
"github.com/weaveworks/ignite/pkg/container"
dmcleanup "github.com/weaveworks/ignite/pkg/dmlegacy/cleanup"
Expand All @@ -28,11 +26,13 @@ func decodeVM(vmID string) (*api.VM, error) {
if err != nil {
return nil, err
}

vm, ok := obj.(*api.VM)
if !ok {
return nil, fmt.Errorf("object couldn't be converted to VM")
}
// Explicitely set the GVK on this object

// Explicitly set the GVK on this object
vm.SetGroupVersionKind(api.SchemeGroupVersion.WithKind(api.KindVM.Title()))
return vm, nil
}
Expand All @@ -47,20 +47,14 @@ func StartVM(vm *api.VM) error {
// Serve DHCP requests for those interfaces
// This function returns the available IP addresses that are being
// served over DHCP now
ipAddrs, err := container.StartDHCPServers(vm, dhcpIfaces)
if err != nil {
if err = container.StartDHCPServers(vm, dhcpIfaces); err != nil {
return err
}

// Serve metrics over an unix socket in the VM's own directory
metricsSocket := path.Join(vm.ObjectPath(), constants.PROMETHEUS_SOCKET)
serveMetrics(metricsSocket)

// Update the VM status and IP address information
if err := patchRunning(vm, ipAddrs); err != nil {
return fmt.Errorf("failed to patch VM state: %v", err)
}

// Patches the VM object to set state to stopped, and clear IP addresses
defer patchStopped(vm)

Expand All @@ -71,7 +65,7 @@ func StartVM(vm *api.VM) error {
defer os.Remove(metricsSocket)

// Execute Firecracker
if err := container.ExecuteFirecracker(vm, dhcpIfaces); err != nil {
if err = container.ExecuteFirecracker(vm, dhcpIfaces); err != nil {
return fmt.Errorf("runtime error for VM %q: %v", vm.GetUID(), err)
}

Expand All @@ -80,40 +74,24 @@ func StartVM(vm *api.VM) error {

func serveMetrics(metricsSocket string) {
go func() {
// create a new registry and http.Server. don't register custom metrics to the registry quite yet
// Create a new registry and http.Server. Don't register custom metrics to the registry quite yet.
_, server := prometheus.New()
if err := prometheus.ServeOnSocket(server, metricsSocket); err != nil {
log.Errorf("prometheus server was stopped with error: %v", err)
}
}()
}

func patchRunning(vm *api.VM, ipAddrs []net.IP) error {
return patchVM(vm, func(patchVM *api.VM) error {
patchVM.Status.Running = true
patchVM.Status.IPAddresses = ipAddrs
return nil
})
}

// TODO: Get rid of this with the daemon architecture
func patchStopped(vm *api.VM) error {
return patchVM(vm, func(patchVM *api.VM) error {
patchVM.Status.Running = false
patchVM.Status.IPAddresses = nil
patchVM.Status.Runtime = nil
patchVM.Status.StartTime = nil
return nil
})
}

func patchVM(vm *api.VM, fn func(*api.VM) error) error {
patch, err := patchutil.Create(vm, func(obj meta.Object) error {
patchVM := obj.(*api.VM)
return fn(patchVM)
})
if err != nil {
return err
}
// Perform the patch
/*
Perform a static patch, setting the following:
vm.status.running = false
vm.status.ipAddresses = nil
vm.status.runtime = nil
vm.status.startTime = nil
*/

patch := []byte(`{"status":{"running":false,"ipAddresses":null,"runtime":null,"startTime":null}}`)
return patchutil.ApplyOnFile(constants.IGNITE_SPAWN_VM_FILE_PATH, patch, vm.GroupVersionKind())
}
12 changes: 4 additions & 8 deletions pkg/container/dhcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,19 @@ var leaseDuration, _ = time.ParseDuration(constants.DHCP_INFINITE_LEASE) // Infi

// StartDHCPServers starts multiple DHCP servers for the VM, one per interface
// It returns the IP addresses that the API object may post in .status, and a potential error
func StartDHCPServers(vm *api.VM, dhcpIfaces []DHCPInterface) ([]net.IP, error) {
func StartDHCPServers(vm *api.VM, dhcpIfaces []DHCPInterface) error {
// Generate the MAC addresses for the VM's adapters
macAddresses := make([]string, 0, len(dhcpIfaces))
if err := util.NewMAC(&macAddresses); err != nil {
return nil, fmt.Errorf("failed to generate MAC addresses: %v", err)
return fmt.Errorf("failed to generate MAC addresses: %v", err)
}

// Fetch the DNS servers given to the container
clientConfig, err := dns.ClientConfigFromFile("/etc/resolv.conf")
if err != nil {
return nil, fmt.Errorf("failed to get DNS configuration: %v", err)
return fmt.Errorf("failed to get DNS configuration: %v", err)
}

var ipAddrs []net.IP
for i := range dhcpIfaces {
dhcpIface := &dhcpIfaces[i]
// Set the VM hostname to the VM ID
Expand All @@ -43,9 +42,6 @@ func StartDHCPServers(vm *api.VM, dhcpIfaces []DHCPInterface) ([]net.IP, error)
// Add the DNS servers from the container
dhcpIface.SetDNSServers(clientConfig.Servers)

// Register what IP address this VM has in the API object
ipAddrs = append(ipAddrs, dhcpIface.VMIPNet.IP)

go func() {
log.Infof("Starting DHCP server for interface %q (%s)\n", dhcpIface.Bridge, dhcpIface.VMIPNet.IP)
if err := dhcpIface.StartBlockingServer(); err != nil {
Expand All @@ -54,7 +50,7 @@ func StartDHCPServers(vm *api.VM, dhcpIfaces []DHCPInterface) ([]net.IP, error)
}()
}

return ipAddrs, nil
return nil
}

type DHCPInterface struct {
Expand Down
19 changes: 14 additions & 5 deletions pkg/operations/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,21 @@ func StartVM(vm *api.VM, debug bool) error {
return err
}

// TODO: Enable this when ignite-spawn doesn't write to the file anymore
//if err := providers.Client.VMs().Set(vm); err != nil {
// return err
//}
// This is used to fetch the IP address the runtime gives to the VM container
// TODO: This needs to be handled differently for CNI, the IP address will be blank
result, err := providers.Runtime.InspectContainer(containerID)
if err != nil {
return fmt.Errorf("failed to inspect container for VM %q: %v", vm.GetUID(), err)
}

return nil
// Append the runtime IP address of the VM to its state
vm.Status.IPAddresses = append(vm.Status.IPAddresses, result.IPAddress)

// Set the VM's status to running
vm.Status.Running = true

// Write the state changes
return providers.Client.VMs().Set(vm)
}

func verifyPulled(image string) error {
Expand Down
8 changes: 5 additions & 3 deletions pkg/runtime/docker/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"net"
"time"

"github.com/docker/docker/api/types"
Expand Down Expand Up @@ -79,9 +80,10 @@ func (dc *dockerClient) InspectContainer(container string) (*runtime.ContainerIn
}

return &runtime.ContainerInspectResult{
ID: res.ID,
Image: res.Image,
Status: res.State.Status,
ID: res.ID,
Image: res.Image,
Status: res.State.Status,
IPAddress: net.ParseIP(res.NetworkSettings.IPAddress),
}, nil
}

Expand Down
8 changes: 5 additions & 3 deletions pkg/runtime/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package runtime

import (
"io"
"net"
"time"

meta "github.com/weaveworks/ignite/pkg/apis/meta/v1alpha1"
Expand All @@ -14,9 +15,10 @@ type ImageInspectResult struct {
}

type ContainerInspectResult struct {
ID string
Image string
Status string
ID string
Image string
Status string
IPAddress net.IP
}

type Bind struct {
Expand Down

0 comments on commit 6a40c22

Please sign in to comment.