Esempio n. 1
0
func showImages(images []shared.ImageInfo) error {
	data := [][]string{}
	for _, image := range images {
		shortest := shortestAlias(image.Aliases)
		if len(image.Aliases) > 1 {
			shortest = fmt.Sprintf("%s (%d more)", shortest, len(image.Aliases)-1)
		}
		fp := image.Fingerprint[0:12]
		public := "no"
		description := findDescription(image.Properties)
		if image.Public == 1 {
			public = "yes"
		}
		const layout = "Jan 2, 2006 at 3:04pm (MST)"
		uploaded := time.Unix(image.UploadDate, 0).Format(layout)
		arch, _ := shared.ArchitectureName(image.Architecture)
		data = append(data, []string{shortest, fp, public, description, arch, uploaded})
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"ALIAS", "FINGERPRINT", "PUBLIC", "DESCRIPTION", "ARCH", "UPLOAD DATE"})

	for _, v := range data {
		table.Append(v)
	}
	table.Render()

	return nil
}
Esempio n. 2
0
func (c *imageCmd) run(config *lxd.Config, args []string) error {
	var remote string

	if len(args) < 1 {
		return errArgs
	}

	switch args[0] {
	case "alias":
		if len(args) < 2 {
			return errArgs
		}
		return doImageAlias(config, args)

	case "copy":
		/* copy [<remote>:]<image> [<rmeote>:]<image> */
		if len(args) != 3 {
			return errArgs
		}
		remote, inName := config.ParseRemoteAndContainer(args[1])
		if inName == "" {
			return errArgs
		}
		destRemote, outName := config.ParseRemoteAndContainer(args[2])
		if outName != "" {
			return errArgs
		}
		d, err := lxd.NewClient(config, remote)
		if err != nil {
			return err
		}
		dest, err := lxd.NewClient(config, destRemote)
		if err != nil {
			return err
		}
		image := dereferenceAlias(d, inName)
		return d.CopyImage(image, dest, copyAliases, addAliases, publicImage)

	case "delete":
		/* delete [<remote>:]<image> */
		if len(args) < 2 {
			return errArgs
		}
		remote, inName := config.ParseRemoteAndContainer(args[1])
		if inName == "" {
			return errArgs
		}
		d, err := lxd.NewClient(config, remote)
		if err != nil {
			return err
		}
		image := dereferenceAlias(d, inName)
		err = d.DeleteImage(image)
		return err

	case "info":
		if len(args) < 2 {
			return errArgs
		}
		remote, inName := config.ParseRemoteAndContainer(args[1])
		if inName == "" {
			return errArgs
		}
		d, err := lxd.NewClient(config, remote)
		if err != nil {
			return err
		}

		image := dereferenceAlias(d, inName)
		info, err := d.GetImageInfo(image)
		if err != nil {
			return err
		}
		fmt.Printf(gettext.Gettext("Fingerprint: %s\n"), info.Fingerprint)
		public := "no"
		if info.Public == 1 {
			public = "yes"
		}
		fmt.Printf(gettext.Gettext("Size: %.2vMB\n"), float64(info.Size)/1024.0/1024.0)
		arch, _ := shared.ArchitectureName(info.Architecture)
		fmt.Printf(gettext.Gettext("Architecture: %s\n"), arch)
		fmt.Printf(gettext.Gettext("Public: %s\n"), public)
		fmt.Printf(gettext.Gettext("Timestamps:\n"))
		const layout = "2006/01/02 15:04 UTC"
		if info.CreationDate != 0 {
			fmt.Printf("    Created: %s\n", time.Unix(info.CreationDate, 0).UTC().Format(layout))
		}
		fmt.Printf("    Uploaded: %s\n", time.Unix(info.UploadDate, 0).UTC().Format(layout))
		if info.ExpiryDate != 0 {
			fmt.Printf("    Expires: %s\n", time.Unix(info.ExpiryDate, 0).UTC().Format(layout))
		} else {
			fmt.Printf("    Expires: never\n")
		}
		fmt.Printf(gettext.Gettext("Properties:\n"))
		for key, value := range info.Properties {
			fmt.Printf("    %s: %s\n", key, value)
		}
		fmt.Printf(gettext.Gettext("Aliases:\n"))
		for _, alias := range info.Aliases {
			fmt.Printf("    - %s\n", alias.Name)
		}
		return nil

	case "import":
		if len(args) < 2 {
			return errArgs
		}
		imagefile := args[1]

		var properties []string
		if len(args) > 2 {
			split := strings.Split(args[2], "=")
			if len(split) == 1 {
				remote, _ = config.ParseRemoteAndContainer(args[2])
				if len(args) > 3 {
					properties = args[3:]
				} else {
					properties = []string{}
				}
			} else {
				properties = args[2:]
			}
		} else {
			remote = ""
			properties = []string{}
		}

		d, err := lxd.NewClient(config, remote)
		if err != nil {
			return err
		}

		fingerprint, err := d.PostImage(imagefile, properties, publicImage, addAliases)
		if err != nil {
			return err
		}

		fmt.Printf(gettext.Gettext("Image imported with fingerprint: %s\n"), fingerprint)

		return nil

	case "list":
		if len(args) > 1 {
			remote, _ = config.ParseRemoteAndContainer(args[1])
		} else {
			remote = ""
		}

		d, err := lxd.NewClient(config, remote)
		if err != nil {
			return err
		}

		images, err := d.ListImages()
		if err != nil {
			return err
		}

		return showImages(images)

	case "edit":
		if len(args) < 2 {
			return errArgs
		}
		remote, inName := config.ParseRemoteAndContainer(args[1])
		if inName == "" {
			return errArgs
		}
		d, err := lxd.NewClient(config, remote)
		if err != nil {
			return err
		}

		image := dereferenceAlias(d, inName)
		if image == "" {
			image = inName
		}

		if !terminal.IsTerminal(syscall.Stdin) {
			contents, err := ioutil.ReadAll(os.Stdin)
			if err != nil {
				return err
			}

			newdata := shared.ImageProperties{}
			err = yaml.Unmarshal(contents, &newdata)
			if err != nil {
				return err
			}
			return d.PutImageProperties(image, newdata)
		}

		info, err := d.GetImageInfo(image)
		if err != nil {
			return err
		}

		properties := info.Properties
		editor := os.Getenv("VISUAL")
		if editor == "" {
			editor = os.Getenv("EDITOR")
			if editor == "" {
				editor = "vi"
			}
		}
		data, err := yaml.Marshal(&properties)
		f, err := ioutil.TempFile("", "lxd_lxc_image_")
		if err != nil {
			return err
		}
		fname := f.Name()
		if err = f.Chmod(0600); err != nil {
			f.Close()
			os.Remove(fname)
			return err
		}
		f.Write([]byte(imageEditHelp))
		f.Write(data)
		f.Close()
		defer os.Remove(fname)

		for {
			cmd := exec.Command(editor, fname)
			cmd.Stdin = os.Stdin
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err = cmd.Run()
			if err != nil {
				return err
			}
			contents, err := ioutil.ReadFile(fname)
			if err != nil {
				return err
			}
			newdata := shared.ImageProperties{}
			err = yaml.Unmarshal(contents, &newdata)
			if err != nil {
				fmt.Fprintf(os.Stderr, gettext.Gettext("YAML parse error %v\n"), err)
				fmt.Printf("Press enter to play again ")
				_, err := os.Stdin.Read(make([]byte, 1))
				if err != nil {
					return err
				}

				continue
			}
			err = d.PutImageProperties(image, newdata)
			break
		}

		return err

	case "export":
		if len(args) < 2 {
			return errArgs
		}

		remote, inName := config.ParseRemoteAndContainer(args[1])
		if inName == "" {
			return errArgs
		}
		d, err := lxd.NewClient(config, remote)
		if err != nil {
			return err
		}

		image := dereferenceAlias(d, inName)

		target := "."
		if len(args) > 2 {
			target = args[2]
		}
		_, outfile, err := d.ExportImage(image, target)
		if err != nil {
			return err
		}

		if target != "-" {
			fmt.Printf("Output is in %s\n", outfile)
		}
		return nil

	case "show":
		if len(args) < 2 {
			return errArgs
		}
		remote, inName := config.ParseRemoteAndContainer(args[1])
		if inName == "" {
			return errArgs
		}
		d, err := lxd.NewClient(config, remote)
		if err != nil {
			return err
		}

		image := dereferenceAlias(d, inName)
		info, err := d.GetImageInfo(image)
		if err != nil {
			return err
		}

		properties := info.Properties

		data, err := yaml.Marshal(&properties)
		fmt.Printf("%s", data)
		return err

	default:
		return fmt.Errorf(gettext.Gettext("Unknown image command %s"), args[0])
	}
}