func (c *Client) ProfileDeviceAdd(profile, devname, devtype string, props []string) (*Response, error) { st, err := c.ProfileConfig(profile) if err != nil { return nil, err } newdev := shared.Device{} for _, p := range props { results := strings.SplitN(p, "=", 2) if len(results) != 2 { return nil, fmt.Errorf(gettext.Gettext("no value found in %q"), p) } k := results[0] v := results[1] newdev[k] = v } if st.Devices != nil && st.Devices.ContainsName(devname) { return nil, fmt.Errorf(gettext.Gettext("device already exists")) } newdev["type"] = devtype if st.Devices == nil { st.Devices = shared.Devices{} } st.Devices[devname] = newdev body := shared.Jmap{"config": st.Config, "name": st.Name, "devices": st.Devices} return c.put(fmt.Sprintf("profiles/%s", profile), body, Sync) }
func init() { // bind app domain gettext.BindTextdomain("hello", "local", nil) gettext.Textdomain("hello") // $(LC_MESSAGES) or $(LANG) or empty fmt.Println(gettext.Gettext("Gettext in init.")) fmt.Println(gettext.PGettext("main.init", "Gettext in init.")) hi.SayHi() // Output(depends on local environment): // ? // ? // ? // ? // set simple chinese gettext.SetLocale("zh_CN") // simple chinese fmt.Println(gettext.Gettext("Gettext in init.")) fmt.Println(gettext.PGettext("main.init", "Gettext in init.")) hi.SayHi() // Output: // Init函数中的Gettext. // Init函数中的Gettext. // 来自"Hi"包的问候: 你好, 世界! // 来自"Hi"包的问候: 你好, 世界! }
func execIfAliases(config *lxd.Config, origArgs []string) { newArgs := []string{} expandedAlias := false for _, arg := range origArgs { changed := false for k, v := range config.Aliases { if k == arg { expandedAlias = true changed = true newArgs = append(newArgs, strings.Split(v, " ")...) break } } if !changed { newArgs = append(newArgs, arg) } } if expandedAlias { path, err := exec.LookPath(origArgs[0]) if err != nil { fmt.Fprintf(os.Stderr, gettext.Gettext("processing aliases failed %s\n"), err) os.Exit(5) } ret := syscall.Exec(path, newArgs, syscall.Environ()) fmt.Fprintf(os.Stderr, gettext.Gettext("processing aliases failed %s\n"), ret) os.Exit(5) } }
func (c *launchCmd) flags() { massage_args() gnuflag.Var(&profArgs, "profile", "Profile to apply to the new container") gnuflag.Var(&profArgs, "p", "Profile to apply to the new container") gnuflag.BoolVar(&ephem, "ephemeral", false, gettext.Gettext("Ephemeral container")) gnuflag.BoolVar(&ephem, "e", false, gettext.Gettext("Ephemeral container")) }
// GroupId is an adaption from https://codereview.appspot.com/4589049. func GroupId(name string) (int, error) { var grp C.struct_group var result *C.struct_group bufSize := C.size_t(C.sysconf(C._SC_GETGR_R_SIZE_MAX)) buf := C.malloc(bufSize) if buf == nil { return -1, fmt.Errorf(gettext.Gettext("allocation failed")) } defer C.free(buf) // mygetgrgid_r is a wrapper around getgrgid_r to // to avoid using gid_t because C.gid_t(gid) for // unknown reasons doesn't work on linux. rv := C.getgrnam_r(C.CString(name), &grp, (*C.char)(buf), bufSize, &result) if rv != 0 { return -1, fmt.Errorf(gettext.Gettext("failed group lookup: %s"), syscall.Errno(rv)) } if result == nil { return -1, fmt.Errorf(gettext.Gettext("unknown group %s"), name) } return int(C.int(result.gr_gid)), nil }
func main() { if err := run(); err != nil { // The action we take depends on the error we get. msg := fmt.Sprintf(gettext.Gettext("error: %v\n"), err) switch t := err.(type) { case *url.Error: switch u := t.Err.(type) { case *net.OpError: if u.Op == "dial" && u.Net == "unix" { switch errno := u.Err.(type) { case syscall.Errno: switch errno { case syscall.ENOENT: msg = gettext.Gettext("LXD socket not found; is LXD running?\n") case syscall.ECONNREFUSED: msg = gettext.Gettext("Connection refused; is LXD running?\n") case syscall.EACCES: msg = gettext.Gettext("Permisson denied, are you in the lxd group?\n") default: msg = fmt.Sprintf("%d %s\n", uintptr(errno), errno.Error()) } } } } } fmt.Fprintf(os.Stderr, msg) os.Exit(1) } }
func main() { if err := run(); err != nil { // The action we take depends on the error we get. switch t := err.(type) { case *url.Error: shared.Debugf("url.Error caught in main(). Op: %s, URL: %s, Err: %s\n", t.Op, t.URL, t.Err) switch u := t.Err.(type) { case *net.OpError: shared.Debugf("Inner error type is a net.OpError: Op: %s Net: %s Addr: %s Err: %T", u.Op, u.Net, u.Addr, u.Err) if u.Op == "dial" && u.Net == "unix" { // The unix socket we are trying to conect to is refusing our connection attempt. Perhaps the server is not running? // Let's at least tell the user about it, since it's hard to get information on wether something is actually listening. fmt.Fprintf(os.Stderr, fmt.Sprintf(gettext.Gettext("Cannot connect to unix socket at %s Is the server running?\n"), u.Addr)) os.Exit(1) } default: shared.Debugf("url.Error's inner Err type is %T", u) } default: shared.Debugf("Error caught in main: %T\n", t) } fmt.Fprintf(os.Stderr, gettext.Gettext("error: %v\n"), err) os.Exit(1) } }
func (c *actionCmd) run(config *lxd.Config, args []string) error { if len(args) == 0 { return errArgs } for _, nameArg := range args { remote, name := config.ParseRemoteAndContainer(nameArg) d, err := lxd.NewClient(config, remote) if err != nil { return err } resp, err := d.Action(name, c.action, timeout, force) if err != nil { return err } if resp.Type != lxd.Async { return fmt.Errorf(gettext.Gettext("bad result type from action")) } if err := d.WaitForSuccess(resp.Operation); err != nil { return fmt.Errorf("%s\n"+gettext.Gettext("Try `lxc info --show-log %s` for more info"), err, name) } } return nil }
func (c *helpCmd) run(_ *lxd.Config, args []string) error { if len(args) > 0 { for _, name := range args { cmd, ok := commands[name] if !ok { fmt.Fprintf(os.Stderr, gettext.Gettext("error: unknown command: %s\n"), name) } else { fmt.Fprintf(os.Stderr, cmd.usage()) } } return nil } fmt.Println(gettext.Gettext("Usage: lxc [subcommand] [options]\nAvailable commands:\n")) var names []string for name := range commands { names = append(names, name) } sort.Strings(names) for _, name := range names { cmd := commands[name] if showAll || cmd.showByDefault() { fmt.Printf("\t%-10s - %s\n", name, summaryLine(cmd.usage())) } } fmt.Println() if !showAll { fmt.Println(gettext.Gettext("Options:")) fmt.Println(" --all " + gettext.Gettext("Print less common commands.")) } return nil }
func (c *publishCmd) run(config *lxd.Config, args []string) error { var cRemote string var cName string iName := "" iRemote := "" properties := map[string]string{} firstprop := 1 // first property is arg[2] if arg[1] is image remote, else arg[1] if len(args) < 1 { return errArgs } cRemote, cName = config.ParseRemoteAndContainer(args[0]) if len(args) >= 2 && !strings.Contains(args[1], "=") { firstprop = 2 iRemote, iName = config.ParseRemoteAndContainer(args[1]) } else { iRemote, iName = config.ParseRemoteAndContainer("") } if cName == "" { return fmt.Errorf(gettext.Gettext("Container name is mandatory")) } if iName != "" { return fmt.Errorf(gettext.Gettext("There is no \"image name\". Did you want an alias?")) } if cRemote != iRemote { /* * Get the source remote to export the container over a websocket, * pass that ws to the dest remote, and have it import it as an * image */ return fmt.Errorf(gettext.Gettext("Publish to remote server is not supported yet")) } d, err := lxd.NewClient(config, iRemote) if err != nil { return err } for i := firstprop; i < len(args); i++ { entry := strings.SplitN(args[i], "=", 2) if len(entry) < 2 { return errArgs } properties[entry[0]] = entry[1] } fp, err := d.ImageFromContainer(cName, makePublic, pAliases, properties) if err == nil { fmt.Printf(gettext.Gettext("Container published with fingerprint %s")+"\n", fp) } return err }
func showImages(images []shared.ImageInfo) error { data := [][]string{} for _, image := range images { shortest := shortestAlias(image.Aliases) if len(image.Aliases) > 1 { shortest = fmt.Sprintf(gettext.Gettext("%s (%d more)"), shortest, len(image.Aliases)-1) } fp := image.Fingerprint[0:12] public := gettext.Gettext("no") description := findDescription(image.Properties) if shared.InterfaceToBool(image.Public) { public = gettext.Gettext("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.SetColWidth(50) table.SetHeader([]string{ gettext.Gettext("ALIAS"), gettext.Gettext("FINGERPRINT"), gettext.Gettext("PUBLIC"), gettext.Gettext("DESCRIPTION"), gettext.Gettext("ARCH"), gettext.Gettext("UPLOAD DATE")}) sort.Sort(ByName(data)) table.AppendBulk(data) table.Render() return nil }
func doProfileApply(client *lxd.Client, c string, p string) error { resp, err := client.ApplyProfile(c, p) if err == nil { if p == "" { p = gettext.Gettext("(none)") } fmt.Printf(gettext.Gettext("Profile %s applied to %s")+"\n", p, c) } else { return err } return client.WaitForSuccess(resp.Operation) }
func (c *configCmd) usage() string { return gettext.Gettext( "Manage configuration.\n" + "\n" + "lxc config device add <container> <name> <type> [key=value]...\n" + " Add a device to a container\n" + "lxc config device list <container> List devices for container\n" + "lxc config device show <container> Show full device details for container\n" + "lxc config device remove <container> <name> Remove device from container\n" + "lxc config edit <container> Edit container configuration in external editor\n" + "lxc config get <container> key Get configuration key\n" + "lxc config set <container> key value Set container configuration key\n" + "lxc config unset <container> key Unset container configuration key\n" + "lxc config set key value Set server configuration key\n" + "lxc config unset key Unset server configuration key\n" + "lxc config show <container> Show container configuration\n" + "lxc config trust list [remote] List all trusted certs.\n" + "lxc config trust add [remote] [certfile.crt] Add certfile.crt to trusted hosts.\n" + "lxc config trust remove [remote] [hostname|fingerprint]\n" + " Remove the cert from trusted hosts.\n" + "\n" + "Examples:\n" + "To mount host's /share/c1 onto /opt in the container:\n" + "\tlxc config device add container1 mntdir disk source=/share/c1 path=opt\n" + "To set an lxc config value:\n" + "\tlxc config set <container> raw.lxc 'lxc.aa_allow_incomplete = 1'\n" + "To set the server trust password:\n" + "\tlxc config set core.trust_password blah\n") }
func (c *imageCmd) usage() string { return gettext.Gettext( `Manipulate container images. lxc image import <tarball> [rootfs tarball] [target] [--public] [--created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] [prop=value] lxc image copy [remote:]<image> <remote>: [--alias=ALIAS].. [--copy-alias] [--public] lxc image delete [remote:]<image> lxc image edit [remote:]<image> lxc image export [remote:]<image> lxc image info [remote:]<image> lxc image list [remote:] [filter] lxc image show [remote:]<image> Lists the images at specified remote, or local images. Filters are not yet supported. lxc image alias create <alias> <target> lxc image alias delete <alias> lxc image alias list [remote:] Create, delete, list image aliases. Example: lxc remote add store2 images.linuxcontainers.org lxc image alias list store2:`) }
func (c *snapshotCmd) run(config *lxd.Config, args []string) error { if len(args) < 1 { return errArgs } var snapname string if len(args) < 2 { snapname = "" } else { snapname = args[1] } remote, name := config.ParseRemoteAndContainer(args[0]) d, err := lxd.NewClient(config, remote) if err != nil { return err } // we don't allow '/' in snapshot names if shared.IsSnapshot(snapname) { return fmt.Errorf(gettext.Gettext("'/' not allowed in snapshot name\n")) } resp, err := d.Snapshot(name, snapname, c.stateful) if err != nil { return err } return d.WaitForSuccess(resp.Operation) }
func doProfileCreate(client *lxd.Client, p string) error { err := client.ProfileCreate(p) if err == nil { fmt.Printf(gettext.Gettext("Profile %s created\n"), p) } return err }
func (c *Client) baseGet(getUrl string) (*Response, error) { req, err := http.NewRequest("GET", getUrl, nil) if err != nil { return nil, err } req.Header.Set("User-Agent", shared.UserAgent) resp, err := c.http.Do(req) if err != nil { return nil, err } if c.scert != nil && resp.TLS != nil { if !bytes.Equal(resp.TLS.PeerCertificates[0].Raw, c.scert.Raw) { pUrl, _ := url.Parse(getUrl) return nil, fmt.Errorf(gettext.Gettext("Server certificate for host %s has changed. Add correct certificate or remove certificate in %s"), pUrl.Host, ConfigPath("servercerts")) } } if c.scertDigestSet == false && resp.TLS != nil { c.scertWire = resp.TLS.PeerCertificates[0] c.scertIntermediates = x509.NewCertPool() for _, cert := range resp.TLS.PeerCertificates { c.scertIntermediates.AddCert(cert) } c.scertDigest = sha256.Sum256(resp.TLS.PeerCertificates[0].Raw) c.scertDigestSet = true } return HoistResponse(resp, Sync) }
func unixDial(networ, addr string) (net.Conn, error) { var raddr *net.UnixAddr var err error if addr == "unix.socket:80" { raddr, err = net.ResolveUnixAddr("unix", shared.VarPath("unix.socket")) if err != nil { return nil, fmt.Errorf(gettext.Gettext("cannot resolve unix socket address: %v"), err) } } else { // TODO - I think this is dead code raddr, err = net.ResolveUnixAddr("unix", addr) if err != nil { return nil, fmt.Errorf(gettext.Gettext("cannot resolve unix socket address: %v"), err) } } return net.DialUnix("unix", nil, raddr) }
func (c *Client) ImageFromContainer(cname string, public bool, aliases []string, properties map[string]string) (string, error) { source := shared.Jmap{"type": "container", "name": cname} if shared.IsSnapshot(cname) { source["type"] = "snapshot" } body := shared.Jmap{"public": public, "source": source, "properties": properties} resp, err := c.post("images", body, Async) if err != nil { return "", err } jmap, err := c.AsyncWaitMeta(resp) if err != nil { return "", err } fingerprint, err := jmap.GetString("fingerprint") if err != nil { return "", err } /* add new aliases */ for _, alias := range aliases { c.DeleteAlias(alias) err = c.PostAlias(alias, alias, fingerprint) if err != nil { fmt.Printf(gettext.Gettext("Error adding alias %s")+"\n", alias) } } return fingerprint, nil }
func (c *Client) ContainerDeviceAdd(container, devname, devtype string, props []string) (*Response, error) { st, err := c.ContainerStatus(container, false) if err != nil { return nil, err } newdev := shared.Device{} for _, p := range props { results := strings.SplitN(p, "=", 2) if len(results) != 2 { return nil, fmt.Errorf(gettext.Gettext("no value found in %q\n"), p) } k := results[0] v := results[1] newdev[k] = v } newdev["type"] = devtype if st.Devices == nil { st.Devices = shared.Devices{} } st.Devices[devname] = newdev body := shared.Jmap{"config": st.Config, "profiles": st.Profiles, "name": st.Name, "devices": st.Devices} return c.put(fmt.Sprintf("containers/%s", container), body, Async) }
func (c *configCmd) usage() string { return gettext.Gettext( "Manage configuration.\n" + "\n" + "lxc config device add <[remote:]container> <name> <type> [key=value]...\n" + " Add a device to a container\n" + "lxc config device list [remote:]<container> List devices for container\n" + "lxc config device show [remote:]<container> Show full device details for container\n" + "lxc config device remove [remote:]<container> <name> Remove device from container\n" + "lxc config edit [remote:]<container> Edit container configuration in external editor\n" + "lxc config get [remote:]<container> key Get configuration key\n" + "lxc config set [remote:]<container> key value Set container configuration key\n" + "lxc config unset [remote:]<container> key Unset container configuration key\n" + "lxc config set key value Set server configuration key\n" + "lxc config unset key Unset server configuration key\n" + "lxc config show [remote:]<container> Show container configuration\n" + "lxc config trust list [remote] List all trusted certs.\n" + "lxc config trust add [remote] <certfile.crt> Add certfile.crt to trusted hosts.\n" + "lxc config trust remove [remote] [hostname|fingerprint]\n" + " Remove the cert from trusted hosts.\n" + "\n" + "Examples:\n" + "To mount host's /share/c1 onto /opt in the container:\n" + "\tlxc config device add [remote:]container1 <device-name> disk source=/share/c1 path=opt\n" + "To set an lxc config value:\n" + "\tlxc config set [remote:]<container> raw.lxc 'lxc.aa_allow_incomplete = 1'\n" + "To listen on IPv4 and IPv6 port 8443 (you can omit the 8443 its the default):\n" + "\tlxc config set core.https_address [::]:8443\n" + "To set the server trust password:\n" + "\tlxc config set core.trust_password blah\n") }
func (c *profileCmd) usage() string { return gettext.Gettext( `Manage configuration profiles. lxc profile list [filters] List available profiles. lxc profile show <profile> Show details of a profile. lxc profile create <profile> Create a profile. lxc profile edit <profile> Edit profile in external editor. lxc profile copy <profile> <remote> Copy the profile to the specified remote. lxc profile set <profile> <key> <value> Set profile configuration. lxc profile delete <profile> Delete a profile. lxc profile apply <container> <profiles> Apply a comma-separated list of profiles to a container, in order. All profiles passed in this call (and only those) will be applied to the specified container. Example: lxc profile apply foo default,bar # Apply default and bar lxc profile apply foo default # Only default is active lxc profile apply '' # no profiles are applied anymore lxc profile apply bar,default # Apply default second now Devices: lxc profile device list <profile> List devices in the given profile. lxc profile device show <profile> Show full device details in the given profile. lxc profile device remove <profile> <name> Remove a device from a profile. lxc profile device add <profile name> <device name> <device type> [key=value]... Add a profile device, such as a disk or a nic, to the containers using the specified profile.`) }
func doProfileDelete(client *lxd.Client, p string) error { err := client.ProfileDelete(p) if err == nil { fmt.Printf(gettext.Gettext("Profile %s deleted")+"\n", p) } return err }
func deviceRm(config *lxd.Config, which string, args []string) error { if len(args) < 4 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[2]) client, err := lxd.NewClient(config, remote) if err != nil { return err } devname := args[3] var resp *lxd.Response if which == "profile" { resp, err = client.ProfileDeviceDelete(name, devname) } else { resp, err = client.ContainerDeviceDelete(name, devname) } if err != nil { return err } fmt.Printf(gettext.Gettext("Device %s removed from %s\n"), devname, name) if which == "profile" { return nil } return client.WaitForSuccess(resp.Operation) }
func deviceAdd(config *lxd.Config, which string, args []string) error { if len(args) < 5 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[2]) client, err := lxd.NewClient(config, remote) if err != nil { return err } devname := args[3] devtype := args[4] var props []string if len(args) > 5 { props = args[5:] } else { props = []string{} } var resp *lxd.Response if which == "profile" { resp, err = client.ProfileDeviceAdd(name, devname, devtype, props) } else { resp, err = client.ContainerDeviceAdd(name, devname, devtype, props) } if err != nil { return err } fmt.Printf(gettext.Gettext("Device %s added to %s\n"), devname, name) if which == "profile" { return nil } return client.WaitForSuccess(resp.Operation) }
func containerInfo(d *lxd.Client, name string, showLog bool) error { ct, err := d.ContainerStatus(name) if err != nil { return err } fmt.Printf(gettext.Gettext("Name: %s")+"\n", ct.Name) fmt.Printf(gettext.Gettext("Status: %s")+"\n", ct.Status.Status) if ct.Status.Init != 0 { fmt.Printf(gettext.Gettext("Init: %d")+"\n", ct.Status.Init) fmt.Printf(gettext.Gettext("Processcount: %d")+"\n", ct.Status.Processcount) fmt.Printf(gettext.Gettext("Ips:") + "\n") foundone := false for _, ip := range ct.Status.Ips { vethStr := "" if ip.HostVeth != "" { vethStr = fmt.Sprintf("\t%s", ip.HostVeth) } fmt.Printf(" %s:\t%s\t%s%s\n", ip.Interface, ip.Protocol, ip.Address, vethStr) foundone = true } if !foundone { fmt.Println(gettext.Gettext("(none)")) } } // List snapshots first_snapshot := true snaps, err := d.ListSnapshots(name) if err != nil { return nil } for _, snap := range snaps { if first_snapshot { fmt.Println(gettext.Gettext("Snapshots:")) } fmt.Printf(" %s\n", snap) first_snapshot = false } if showLog { log, err := d.GetLog(name, "lxc.log") if err != nil { return err } stuff, err := ioutil.ReadAll(log) if err != nil { return err } fmt.Printf("\n"+gettext.Gettext("Log:")+"\n\n%s\n", string(stuff)) } return nil }
func (c *infoCmd) usage() string { return gettext.Gettext( `List information on containers. This will support remotes and images as well, but only containers for now. lxc info [<remote>:]container [--show-log]`) }
func (c *Client) PutProfile(name string, profile shared.ProfileConfig) error { if profile.Name != name { return fmt.Errorf(gettext.Gettext("Cannot change profile name")) } body := shared.Jmap{"name": name, "config": profile.Config, "devices": profile.Devices} _, err := c.put(fmt.Sprintf("profiles/%s", name), body, Sync) return err }
func (c *deleteCmd) usage() string { return gettext.Gettext( `Delete containers or container snapshots. lxc delete [remote:]<container>[/<snapshot>] [remote:][<container>[/<snapshot>]...] Destroy containers or snapshots with any attached data (configuration, snapshots, ...).`) }
func (c *execCmd) run(config *lxd.Config, args []string) error { if len(args) < 2 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[0]) d, err := lxd.NewClient(config, remote) if err != nil { return err } env := map[string]string{"HOME": "/root", "USER": "******"} myEnv := os.Environ() for _, ent := range myEnv { if strings.HasPrefix(ent, "TERM=") { env["TERM"] = ent[len("TERM="):] } } for _, arg := range envArgs { pieces := strings.SplitN(arg, "=", 2) value := "" if len(pieces) > 1 { value = pieces[1] } env[pieces[0]] = value } cfd := syscall.Stdout var oldttystate *terminal.State if terminal.IsTerminal(cfd) { oldttystate, err = terminal.MakeRaw(cfd) if err != nil { return err } defer terminal.Restore(cfd, oldttystate) } ret, err := d.Exec(name, args[1:], env, os.Stdin, os.Stdout, os.Stderr) if err != nil { return err } if oldttystate != nil { /* A bit of a special case here: we want to exit with the same code as * the process inside the container, so we explicitly exit here * instead of returning an error. * * Additionally, since os.Exit() exits without running deferred * functions, we restore the terminal explicitly. */ terminal.Restore(cfd, oldttystate) } /* we get the result of waitpid() here so we need to transform it */ os.Exit(ret >> 8) return fmt.Errorf(gettext.Gettext("unreachable return reached")) }