8950b033364df7b4081e8f0fa5b6231f2b2fc88f — Louis Solofrizzo 6 months ago 7aa7a7e 1.2
api: Enable vms, and asynchronous listing

Signed-off-by: Louis Solofrizzo <lsolofrizzo@online.net>
M api/CMakeLists.txt => api/CMakeLists.txt +1 -0
@@ 11,6 11,7 @@ ssh.go
      instance.go
      images.go
+     jobs.go
  )
  
  upload_artifacts(cisco cisco-api x86_64)

M api/database.go => api/database.go +2 -0
@@ 48,6 48,8 @@ User         uint
  	Type         string
  	Status       string
+ 	Ipv6         string
+ 	LXCStatus    string
  }
  
  type DbIpv4 struct {

M api/images.go => api/images.go +12 -5
@@ 41,14 41,21 @@ for _, img := range images {
  		if img.Public {
  			if len(img.Aliases) > 0 {
+ 				var isVm bool = false
  				array := strings.Split(img.Aliases[0].Name, "/")
- 				array = array[:len(array)-1]
+ 				if array[len(array)-1] == "vm" {
+ 					array = array[:len(array)-2]
+ 					isVm = true
+ 				} else {
+ 					array = array[:len(array)-1]
+ 				}
  
  				result = append(result, cisco.Image{
- 					Name:         strings.Join(array, "/"),
- 					Architecture: img.Architecture,
- 					Fingerprint:  img.Fingerprint,
- 					Size:         img.Size,
+ 					Name:           strings.Join(array, "/"),
+ 					Architecture:   img.Architecture,
+ 					Fingerprint:    img.Fingerprint,
+ 					Size:           img.Size,
+ 					VirtualMachine: isVm,
  				})
  			}
  		}

M api/instance.go => api/instance.go +38 -36
@@ 14,7 14,6 @@ func instance_list(ctx iris.Context) {
  	var entries []DbInstance
  	var result []cisco.Instance
- 	var ipv6 string
  
  	user := ctx.Values().Get("User")
  	DB.Find(&entries, "user = ?", user)


@@ 22,28 21,11 @@ for _, instance := range entries {
  		var ipv4 DbIpv4
  		var status string
- 		ipv6 = ""
  
  		DB.Find(&ipv4, "instance = ?", instance.Uuid)
  
  		if instance.Status == "LXD" {
- 			inst, _, err := Context.LXD.GetInstanceState("LF" + instance.Uuid)
- 
- 			if err != nil {
- 				APIError(ctx, 500, err.Error())
- 				return
- 			}
- 
- 			for _, net := range inst.Network {
- 				for _, addr := range net.Addresses {
- 					if addr.Family == "inet6" && !strings.HasPrefix(addr.Address, "fe80") && addr.Scope != "local" {
- 						ipv6 = addr.Address
- 						break
- 					}
- 				}
- 			}
- 
- 			status = inst.Status
+ 			status = instance.LXCStatus
  		} else {
  			status = instance.Status
  		}


@@ 56,7 38,7 @@ Architecture: instance.Architecture,
  			Ipv4:         ipv4.IP,
  			Status:       status,
- 			Ipv6:         ipv6,
+ 			Ipv6:         instance.Ipv6,
  			Type:         instance.Type,
  		})
  	}


@@ 144,9 126,9 @@ return errors.New("The specified Instance Type is not valid")
  	}
  
- 	op, err := Context.LXD.CreateContainer(api.ContainersPost{
+ 	op, err := Context.LXD.CreateInstance(api.InstancesPost{
  		Name: "LF" + instance.Uuid,
- 		ContainerPut: api.ContainerPut{
+ 		InstancePut: api.InstancePut{
  			Architecture: instanceType.Architecture,
  			Config: map[string]string{
  				"limits.cpu":    strconv.Itoa(instanceType.CPU),


@@ 161,10 143,11 @@ },
  			},
  		},
- 		Source: api.ContainerSource{
+ 		Source: api.InstanceSource{
  			Type:  "image",
  			Alias: instance.OS,
  		},
+ 		Type: api.InstanceType(instanceType.Type),
  	})
  
  	if err != nil {


@@ 184,6 167,7 @@ func instance_new(ctx iris.Context) {
  	var instance cisco.InstanceNew
  	var entry DbInstance
+ 	var originalOS string
  
  	ctx.ReadJSON(&instance)
  	if instance.Name == "" {


@@ 206,12 190,17 @@ return
  	}
  
+ 	originalOS = instance.OS
  	if arch == "x86_64" {
  		instance.OS += "/intel"
  	} else if arch == "arm" {
  		instance.OS += "/arm"
  	}
  
+ 	if instance.Type[0] == 'V' {
+ 		instance.OS += "/vm"
+ 	}
+ 
  	if OSIsValid(ctx, instance.OS) != nil {
  		return
  	}


@@ 261,7 250,7 @@   	instance.OS = strings.Join(array, "/")
  	DB.Model(&entry).Update("status", "LXD")
- 	DB.Model(&entry).Update("os", instance.OS)
+ 	DB.Model(&entry).Update("os", originalOS)
  	ctx.StatusCode(iris.StatusCreated)
  }
  


@@ 292,12 281,12 @@ return
  	}
  
- 	reqState := api.ContainerStatePut{
+ 	reqState := api.InstanceStatePut{
  		Action:  "start",
  		Timeout: -1,
  	}
  
- 	op, err := Context.LXD.UpdateContainerState("LF"+entry.Uuid, reqState, "")
+ 	op, err := Context.LXD.UpdateInstanceState("LF"+entry.Uuid, reqState, "")
  	if err != nil {
  		APIError(ctx, 503, "Error: "+err.Error())
  		return


@@ 337,12 326,12 @@ return
  	}
  
- 	reqState := api.ContainerStatePut{
+ 	reqState := api.InstanceStatePut{
  		Action:  "stop",
  		Timeout: -1,
  	}
  
- 	op, err := Context.LXD.UpdateContainerState("LF"+entry.Uuid, reqState, "")
+ 	op, err := Context.LXD.UpdateInstanceState("LF"+entry.Uuid, reqState, "")
  	if err != nil {
  		APIError(ctx, 503, "Error: "+err.Error())
  		return


@@ 373,7 362,7 @@   	DB.Model(&entry).Update("status", "Deleting")
  
- 	op, err := Context.LXD.DeleteContainer("LF" + entry.Uuid)
+ 	op, err := Context.LXD.DeleteInstance("LF" + entry.Uuid)
  	if err != nil {
  		APIError(ctx, 503, "Error: "+err.Error())
  		return


@@ 407,6 396,18 @@ ctx.WriteString(entry.Name)
  }
  
+ func instance_uuid(ctx iris.Context) {
+ 	var entry DbInstance
+ 
+ 	DB.First(&entry, "ipv6 = ?", ctx.Request().Header["X-Real-Ip"])
+ 	if entry.ID == 0 {
+ 		APIError(ctx, 404, "Can't find the specified instance")
+ 		return
+ 	}
+ 
+ 	ctx.WriteString(entry.Uuid)
+ }
+ 
  func instance_keys(ctx iris.Context) {
  	var entry DbInstance
  	var keys []DbSSHKey


@@ 479,15 480,15 @@ return
  	}
  
- 	inst, _, err := Context.LXD.GetContainer("LF" + entry.Uuid)
+ 	inst, _, err := Context.LXD.GetInstance("LF" + entry.Uuid)
  	if err != nil {
  		APIError(ctx, 503, "Error: "+err.Error())
  		return
  	}
  
- 	inst.ContainerPut.Devices["root"]["size"] = strconv.Itoa(int(size.Size)) + "GB"
+ 	inst.InstancePut.Devices["root"]["size"] = strconv.Itoa(int(size.Size)) + "GB"
  
- 	op, err := Context.LXD.UpdateContainer("LF"+entry.Uuid, inst.ContainerPut, "")
+ 	op, err := Context.LXD.UpdateInstance("LF"+entry.Uuid, inst.InstancePut, "")
  	if err != nil {
  		APIError(ctx, 503, "Error: "+err.Error())
  		return


@@ 537,16 538,16 @@ return
  	}
  
- 	inst, _, err := Context.LXD.GetContainer("LF" + entry.Uuid)
+ 	inst, _, err := Context.LXD.GetInstance("LF" + entry.Uuid)
  	if err != nil {
  		APIError(ctx, 503, "Error: "+err.Error())
  		return
  	}
  
- 	inst.ContainerPut.Config["limits.cpu"] = strconv.Itoa(instanceType.CPU)
- 	inst.ContainerPut.Config["limits.memory"] = strconv.Itoa(instanceType.Memory) + "MB"
+ 	inst.InstancePut.Config["limits.cpu"] = strconv.Itoa(instanceType.CPU)
+ 	inst.InstancePut.Config["limits.memory"] = strconv.Itoa(instanceType.Memory) + "MB"
  
- 	op, err := Context.LXD.UpdateContainer("LF"+entry.Uuid, inst.ContainerPut, "")
+ 	op, err := Context.LXD.UpdateInstance("LF"+entry.Uuid, inst.InstancePut, "")
  	if err != nil {
  		APIError(ctx, 503, "Error: "+err.Error())
  		return


@@ 595,6 596,7 @@ app.Delete("/instance/{name:string}", APIAuth, instance_delete)
  	app.Get("/instance/keys/{name:string}", instance_keys)
  	app.Get("/instance/name/{name:string}", instance_name)
+ 	app.Get("/instance/uuid", instance_uuid)
  	app.Get("/instance/types", APIAuth, instance_types)
  	app.Put("/instance/size/{name:string}", APIAuth, instance_size)
  	app.Put("/instance/type/{name:string}", APIAuth, instance_type)

A api/jobs.go => api/jobs.go +50 -0
@@ 0,0 1,50 @@
+ package main
+ 
+ import (
+ 	"fmt"
+ 	"github.com/lxc/lxd/shared/api"
+ 	"strings"
+ 	"time"
+ )
+ 
+ func instance_update_ipv6() {
+ 	var entries []DbInstance
+ 
+ 	for {
+ 		DB.Find(&entries)
+ 		for _, instance := range entries {
+ 			var ipv6 string = ""
+ 
+ 			if instance.Status == "LXD" {
+ 				c1 := make(chan *api.InstanceState, 1)
+ 				go func() {
+ 					inst, _, err := Context.LXD.GetInstanceState("LF" + instance.Uuid)
+ 
+ 					if err != nil {
+ 						fmt.Printf("Error: %s\n", err)
+ 						return
+ 					}
+ 					c1 <- inst
+ 				}()
+ 
+ 				select {
+ 				case inst := <-c1:
+ 					for _, net := range inst.Network {
+ 						for _, addr := range net.Addresses {
+ 							if addr.Family == "inet6" && !strings.HasPrefix(addr.Address, "fe80") && addr.Scope != "local" {
+ 								ipv6 = addr.Address
+ 								break
+ 							}
+ 						}
+ 					}
+ 
+ 					if ipv6 != "" {
+ 						DB.Model(&instance).Update("ipv6", ipv6)
+ 					}
+ 					DB.Model(&instance).Update("lxc_status", inst.Status)
+ 				case <-time.After(30 * time.Second):
+ 				}
+ 			}
+ 		}
+ 	}
+ }

M api/main.go => api/main.go +2 -0
@@ 164,5 164,7 @@ InitInstanceRoutes(app)
  	InitImageRoutes(app)
  
+ 	go instance_update_ipv6()
+ 
  	app.Run(iris.Addr(Config.Http.Address))
  }

M csc/cmd/image/list.go => csc/cmd/image/list.go +8 -2
@@ 23,10 23,16 @@ }
  
  		table := tablewriter.NewWriter(os.Stdout)
- 		table.SetHeader([]string{"Name", "Fingerprint", "Architecture", "Size"})
+ 		table.SetHeader([]string{"Name", "Fingerprint", "Architecture", "Size", "Type"})
  
  		for _, img := range images {
- 			table.Append([]string{img.Name, img.Fingerprint, img.Architecture, strconv.FormatInt(int64(img.Size), 10)})
+ 			var Type string = "Container"
+ 
+ 			if img.VirtualMachine == true {
+ 				Type = "Virtual-Machine"
+ 			}
+ 
+ 			table.Append([]string{img.Name, img.Fingerprint, img.Architecture, strconv.FormatInt(int64(img.Size), 10), Type})
  		}
  
  		table.Render()

A deploy/configuration/qemu.yml => deploy/configuration/qemu.yml +16 -0
@@ 0,0 1,16 @@
+ - name: Qemu installation
+   hosts: "*intel*"
+   tasks:
+   - name: Install QEMU
+     apt:
+       name:
+         - qemu
+         - ovmf
+       state: present
+       update_cache: yes
+ 
+   - name: Symlink EFI blob
+     file:
+       src: /usr/share/OVMF/OVMF_VARS.fd
+       dest: /usr/share/OVMF/OVMF_VARS.ms.fd
+       state: link

M deploy/lxd/fast-install.yml => deploy/lxd/fast-install.yml +2 -0
@@ 19,6 19,8 @@ dst: /usr/lib/libdqlite.so.0
        - src: intel/libsqlite3.so
          dst: /usr/lib/libsqlite3.so.0
+       - src: intel/lxd-agent
+         dst: /usr/bin/lxd-agent
  
    - name: Remove system sqlite
      file:

M deploy/lxd/install.yml => deploy/lxd/install.yml +2 -0
@@ 86,3 86,5 @@ dest: libdqlite.so
        - src: /usr/local/src/deps/sqlite/.libs/libsqlite3.so
          dest: libsqlite3.so
+       - src: /usr/local/src/bin/lxd-agent
+         dest: lxd-agent

M sdk/image.go => sdk/image.go +5 -4
@@ 5,10 5,11 @@ )
  
  type Image struct {
- 	Name         string `json:"name"`
- 	Architecture string `json:"architecture"`
- 	Fingerprint  string `json:"fingerprint"`
- 	Size         int64  `json:"size"`
+ 	Name           string `json:"name"`
+ 	Architecture   string `json:"architecture"`
+ 	Fingerprint    string `json:"fingerprint"`
+ 	Size           int64  `json:"size"`
+ 	VirtualMachine bool   `json:"vm"`
  }
  
  func ListImage() ([]Image, error) {