[lxc-devel] [lxd/master] Bugfixes
stgraber on Github
lxc-bot at linuxcontainers.org
Wed Mar 16 21:59:25 UTC 2016
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160316/2c69bda6/attachment.bin>
-------------- next part --------------
From 4c2678bf2e68c90dcde7d3fdf5b37e24f461aff8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 16 Mar 2016 15:52:33 -0400
Subject: [PATCH 1/4] More strictly parse remote URLs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #1763
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxc/remote.go | 24 ++++++++++++---------
po/lxd.pot | 69 +++++++++++++++++++++++++++++++++++------------------------
2 files changed, 55 insertions(+), 38 deletions(-)
diff --git a/lxc/remote.go b/lxc/remote.go
index 0c9cbca..6f54717 100644
--- a/lxc/remote.go
+++ b/lxc/remote.go
@@ -79,7 +79,7 @@ func getRemoteCertificate(address string) (*x509.Certificate, error) {
// Retrieve the certificate
if resp.TLS == nil || len(resp.TLS.PeerCertificates) == 0 {
- return nil, fmt.Errorf("Unable to read remote TLS certificate")
+ return nil, fmt.Errorf(i18n.G("Unable to read remote TLS certificate"))
}
return resp.TLS.PeerCertificates[0], nil
@@ -95,24 +95,28 @@ func (c *remoteCmd) addServer(config *lxd.Config, server string, addr string, ac
config.Remotes = make(map[string]lxd.RemoteConfig)
}
- // Fast track simplestreams
- if protocol == "simplestreams" {
- config.Remotes[server] = lxd.RemoteConfig{Addr: addr, Public: true, Protocol: protocol}
- return nil
- }
-
/* Complex remote URL parsing */
remoteURL, err := url.Parse(addr)
if err != nil {
return err
}
+ // Fast track simplestreams
+ if protocol == "simplestreams" {
+ if remoteURL.Scheme != "https" {
+ return fmt.Errorf(i18n.G("Only https URLs are supported for simplestreams"))
+ }
+
+ config.Remotes[server] = lxd.RemoteConfig{Addr: addr, Public: true, Protocol: protocol}
+ return nil
+ }
+
if remoteURL.Scheme != "" {
if remoteURL.Scheme != "unix" && remoteURL.Scheme != "https" {
- rScheme = "https"
- } else {
- rScheme = remoteURL.Scheme
+ return fmt.Errorf(i18n.G("Invalid URL scheme \"%s\" in \"%s\""), remoteURL.Scheme, addr)
}
+
+ rScheme = remoteURL.Scheme
} else if addr[0] == '/' {
rScheme = "unix"
} else {
diff --git a/po/lxd.pot b/po/lxd.pot
index 66686ae..c2ec8cf 100644
--- a/po/lxd.pot
+++ b/po/lxd.pot
@@ -7,7 +7,7 @@
msgid ""
msgstr "Project-Id-Version: lxd\n"
"Report-Msgid-Bugs-To: lxc-devel at lists.linuxcontainers.org\n"
- "POT-Creation-Date: 2016-03-02 19:53-0500\n"
+ "POT-Creation-Date: 2016-03-16 15:52-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
"Language-Team: LANGUAGE <LL at li.org>\n"
@@ -90,11 +90,11 @@ msgstr ""
msgid "ARCHITECTURE"
msgstr ""
-#: lxc/remote.go:52
+#: lxc/remote.go:53
msgid "Accept certificate"
msgstr ""
-#: lxc/remote.go:216
+#: lxc/remote.go:250
#, c-format
msgid "Admin password for %s: "
msgstr ""
@@ -143,7 +143,7 @@ msgstr ""
msgid "Cannot provide container name to list"
msgstr ""
-#: lxc/remote.go:166
+#: lxc/remote.go:200
#, c-format
msgid "Certificate fingerprint: %x"
msgstr ""
@@ -155,7 +155,7 @@ msgid "Changes state of one or more containers to %s.\n"
"lxc %s <name> [<name>...]"
msgstr ""
-#: lxc/remote.go:239
+#: lxc/remote.go:273
msgid "Client certificate stored at server: "
msgstr ""
@@ -205,7 +205,7 @@ msgstr ""
msgid "Copying the image: %s"
msgstr ""
-#: lxc/remote.go:181
+#: lxc/remote.go:215
msgid "Could not create server cert dir"
msgstr ""
@@ -251,12 +251,12 @@ msgid "Delete containers or container snapshots.\n"
"Destroy containers or snapshots with any attached data (configuration, snapshots, ...)."
msgstr ""
-#: lxc/config.go:606
+#: lxc/config.go:610
#, c-format
msgid "Device %s added to %s"
msgstr ""
-#: lxc/config.go:634
+#: lxc/config.go:640
#, c-format
msgid "Device %s removed from %s"
msgstr ""
@@ -384,6 +384,11 @@ msgid "Initialize a container from a particular image.\n"
"lxc init ubuntu u1"
msgstr ""
+#: lxc/remote.go:116
+#, c-format
+msgid "Invalid URL scheme \"%s\" in \"%s\""
+msgstr ""
+
#: lxc/init.go:30 lxc/init.go:35
msgid "Invalid configuration key"
msgstr ""
@@ -552,7 +557,7 @@ msgid "Manage files on a container.\n"
"<source> in the case of pull, <target> in the case of push and <file> in the case of edit are <container name>/<path>"
msgstr ""
-#: lxc/remote.go:38
+#: lxc/remote.go:39
msgid "Manage remote LXD servers.\n"
"\n"
"lxc remote add <name> <url> [--accept-certificate] [--password=PASSWORD]\n"
@@ -660,11 +665,11 @@ msgstr ""
msgid "Must supply container name for: "
msgstr ""
-#: lxc/list.go:338 lxc/remote.go:323
+#: lxc/list.go:338 lxc/remote.go:357
msgid "NAME"
msgstr ""
-#: lxc/remote.go:297 lxc/remote.go:302
+#: lxc/remote.go:331 lxc/remote.go:336
msgid "NO"
msgstr ""
@@ -685,6 +690,10 @@ msgstr ""
msgid "No fingerprint specified."
msgstr ""
+#: lxc/remote.go:107
+msgid "Only https URLs are supported for simplestreams"
+msgstr ""
+
#: lxc/image.go:397
msgid "Only https:// is supported for remote image import."
msgstr ""
@@ -714,11 +723,11 @@ msgstr ""
msgid "PROFILES"
msgstr ""
-#: lxc/remote.go:325
+#: lxc/remote.go:359
msgid "PROTOCOL"
msgstr ""
-#: lxc/image.go:592 lxc/remote.go:326
+#: lxc/image.go:592 lxc/remote.go:360
msgid "PUBLIC"
msgstr ""
@@ -804,7 +813,7 @@ msgstr ""
msgid "Properties:"
msgstr ""
-#: lxc/remote.go:55
+#: lxc/remote.go:56
msgid "Public image server"
msgstr ""
@@ -819,7 +828,7 @@ msgid "Publish containers as images.\n"
"lxc publish [remote:]container [remote:] [--alias=ALIAS]... [prop-key=prop-value]..."
msgstr ""
-#: lxc/remote.go:53
+#: lxc/remote.go:54
msgid "Remote admin password"
msgstr ""
@@ -849,19 +858,19 @@ msgstr ""
msgid "STATE"
msgstr ""
-#: lxc/remote.go:327
+#: lxc/remote.go:361
msgid "STATIC"
msgstr ""
-#: lxc/remote.go:174
+#: lxc/remote.go:208
msgid "Server certificate NACKed by user"
msgstr ""
-#: lxc/remote.go:236
+#: lxc/remote.go:270
msgid "Server doesn't trust us after adding our cert"
msgstr ""
-#: lxc/remote.go:54
+#: lxc/remote.go:55
msgid "Server protocol (lxd or simplestreams)"
msgstr ""
@@ -979,10 +988,14 @@ msgstr ""
msgid "UPLOAD DATE"
msgstr ""
-#: lxc/remote.go:324
+#: lxc/remote.go:358
msgid "URL"
msgstr ""
+#: lxc/remote.go:82
+msgid "Unable to read remote TLS certificate"
+msgstr ""
+
#: lxc/image.go:323
#, c-format
msgid "Uploaded: %s"
@@ -1013,7 +1026,7 @@ msgstr ""
msgid "Whether to show the expanded configuration"
msgstr ""
-#: lxc/remote.go:299 lxc/remote.go:304
+#: lxc/remote.go:333 lxc/remote.go:338
msgid "YES"
msgstr ""
@@ -1033,11 +1046,11 @@ msgstr ""
msgid "can't copy to the same container name"
msgstr ""
-#: lxc/remote.go:287
+#: lxc/remote.go:321
msgid "can't remove the default remote"
msgstr ""
-#: lxc/remote.go:313
+#: lxc/remote.go:347
msgid "default"
msgstr ""
@@ -1075,7 +1088,7 @@ msgstr ""
msgid "not all the profiles from the source exist on the target"
msgstr ""
-#: lxc/remote.go:167
+#: lxc/remote.go:201
msgid "ok (y/n)?"
msgstr ""
@@ -1084,22 +1097,22 @@ msgstr ""
msgid "processing aliases failed %s\n"
msgstr ""
-#: lxc/remote.go:349
+#: lxc/remote.go:383
#, c-format
msgid "remote %s already exists"
msgstr ""
-#: lxc/remote.go:279 lxc/remote.go:341 lxc/remote.go:376 lxc/remote.go:392
+#: lxc/remote.go:313 lxc/remote.go:375 lxc/remote.go:410 lxc/remote.go:426
#, c-format
msgid "remote %s doesn't exist"
msgstr ""
-#: lxc/remote.go:262
+#: lxc/remote.go:296
#, c-format
msgid "remote %s exists as <%s>"
msgstr ""
-#: lxc/remote.go:283 lxc/remote.go:345 lxc/remote.go:380
+#: lxc/remote.go:317 lxc/remote.go:379 lxc/remote.go:414
#, c-format
msgid "remote %s is static and cannot be modified"
msgstr ""
From 4c19e958f613d01f83bad42eaaa9296d4abb86f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 16 Mar 2016 17:17:39 -0400
Subject: [PATCH 2/4] Fix devlxd access outside of an exec session
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #1751
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/devlxd.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lxd/devlxd.go b/lxd/devlxd.go
index ecb28e8..ce8b00a 100644
--- a/lxd/devlxd.go
+++ b/lxd/devlxd.go
@@ -297,7 +297,7 @@ func findContainerForPid(pid int32, d *Daemon) (container, error) {
if strings.HasPrefix(string(cmdline), "[lxc monitor]") {
// container names can't have spaces
parts := strings.Split(string(cmdline), " ")
- name := parts[len(parts)-1]
+ name := strings.TrimSuffix(parts[len(parts)-1], "\x00")
return containerLoadByName(d, name)
}
From 689d722e17808bed8899fc6ebaa22e013044b7ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 16 Mar 2016 17:42:13 -0400
Subject: [PATCH 3/4] Restrict /dev/lxd to uid 0 in the container
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #1751
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/devlxd.go | 42 +++++++++++++++++++++++++++++++-----------
1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/lxd/devlxd.go b/lxd/devlxd.go
index ce8b00a..8991a67 100644
--- a/lxd/devlxd.go
+++ b/lxd/devlxd.go
@@ -85,18 +85,32 @@ var handlers = []devLxdHandler{
func hoistReq(f func(container, *http.Request) *devLxdResponse, d *Daemon) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
conn := extractUnderlyingConn(w)
- pid, ok := pidMapper.m[conn]
+ cred, ok := pidMapper.m[conn]
if !ok {
http.Error(w, pidNotInContainerErr.Error(), 500)
return
}
- c, err := findContainerForPid(pid, d)
+ c, err := findContainerForPid(cred.pid, d)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
+ // Access control
+ rootUid := int64(0)
+
+ idmapset, err := c.LastIdmapSet()
+ if err == nil && idmapset != nil {
+ uid, _ := idmapset.ShiftIntoNs(0, 0)
+ rootUid = int64(uid)
+ }
+
+ if rootUid != cred.uid {
+ http.Error(w, "Access denied for non-root user", 401)
+ return
+ }
+
resp := f(c, r)
if resp.code != http.StatusOK {
http.Error(w, fmt.Sprintf("%s", resp.content), resp.code)
@@ -185,21 +199,27 @@ func devLxdServer(d *Daemon) *http.Server {
* from our http handlers, since there appears to be no way to pass information
* around here.
*/
-var pidMapper = ConnPidMapper{m: map[*net.UnixConn]int32{}}
+var pidMapper = ConnPidMapper{m: map[*net.UnixConn]*ucred{}}
+
+type ucred struct {
+ pid int32
+ uid int64
+ gid int64
+}
type ConnPidMapper struct {
- m map[*net.UnixConn]int32
+ m map[*net.UnixConn]*ucred
}
func (m *ConnPidMapper) ConnStateHandler(conn net.Conn, state http.ConnState) {
unixConn := conn.(*net.UnixConn)
switch state {
case http.StateNew:
- pid, err := getPid(unixConn)
+ cred, err := getCred(unixConn)
if err != nil {
- shared.Debugf("Error getting pid for conn %s", err)
+ shared.Debugf("Error getting ucred for conn %s", err)
} else {
- m.m[unixConn] = pid
+ m.m[unixConn] = cred
}
case http.StateActive:
return
@@ -234,15 +254,15 @@ func extractUnderlyingFd(unixConnPtr *net.UnixConn) int {
return int(fd.Int())
}
-func getPid(conn *net.UnixConn) (int32, error) {
+func getCred(conn *net.UnixConn) (*ucred, error) {
fd := extractUnderlyingFd(conn)
- _, _, pid, err := getUcred(fd)
+ uid, gid, pid, err := getUcred(fd)
if err != nil {
- return 0, err
+ return nil, err
}
- return pid, nil
+ return &ucred{pid, int64(uid), int64(gid)}, nil
}
/*
From dea6b959e9a8173af63a8c974aaf1097b5eb6bfb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 16 Mar 2016 17:58:40 -0400
Subject: [PATCH 4/4] Return better errors for public and simplestream remotes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #1762
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
client.go | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
lxc/remote.go | 4 +-
2 files changed, 201 insertions(+), 13 deletions(-)
diff --git a/client.go b/client.go
index 7decf89..9d4716f 100644
--- a/client.go
+++ b/client.go
@@ -493,18 +493,11 @@ func (c *Client) url(elem ...string) string {
}
func (c *Client) GetServerConfig() (*Response, error) {
- return c.baseGet(c.url(shared.APIVersion))
-}
-
-func (c *Client) Finger() error {
- shared.Debugf("Fingering the daemon")
- _, err := c.GetServerConfig()
- if err != nil {
- return err
+ if c.Remote.Protocol == "simplestreams" {
+ return nil, fmt.Errorf("This function isn't supported by simplestreams remote.")
}
- shared.Debugf("Pong received")
- return nil
+ return c.baseGet(c.url(shared.APIVersion))
}
func (c *Client) AmTrusted() bool {
@@ -550,6 +543,10 @@ func (c *Client) IsPublic() bool {
}
func (c *Client) ListContainers() ([]shared.ContainerInfo, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
resp, err := c.get("containers?recursion=1")
if err != nil {
return nil, err
@@ -827,6 +824,10 @@ func (c *Client) ExportImage(image string, target string) (string, error) {
}
func (c *Client) PostImageURL(imageFile string, public bool, aliases []string) (string, error) {
+ if c.Remote.Public {
+ return "", fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
source := shared.Jmap{
"type": "url",
"mode": "pull",
@@ -865,6 +866,10 @@ func (c *Client) PostImageURL(imageFile string, public bool, aliases []string) (
}
func (c *Client) PostImage(imageFile string, rootfsFile string, properties []string, public bool, aliases []string, progressHandler func(percent int)) (string, error) {
+ if c.Remote.Public {
+ return "", fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
uri := c.url(shared.APIVersion, "images")
var err error
@@ -1030,6 +1035,10 @@ func (c *Client) GetImageInfo(image string) (*shared.ImageInfo, error) {
}
func (c *Client) PutImageInfo(name string, p shared.BriefImageInfo) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
_, err := c.put(fmt.Sprintf("images/%s", name), p, Sync)
return err
}
@@ -1053,11 +1062,19 @@ func (c *Client) ListImages() ([]shared.ImageInfo, error) {
}
func (c *Client) DeleteImage(image string) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
_, err := c.delete(fmt.Sprintf("images/%s", image), nil, Sync)
return err
}
func (c *Client) PostAlias(alias string, desc string, target string) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
body := shared.Jmap{"description": desc, "target": target, "name": alias}
_, err := c.post("images/aliases", body, Sync)
@@ -1065,6 +1082,10 @@ func (c *Client) PostAlias(alias string, desc string, target string) error {
}
func (c *Client) DeleteAlias(alias string) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
_, err := c.delete(fmt.Sprintf("images/aliases/%s", alias), nil, Sync)
return err
}
@@ -1089,6 +1110,10 @@ func (c *Client) ListAliases() (shared.ImageAliases, error) {
}
func (c *Client) CertificateList() ([]shared.CertInfo, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
resp, err := c.get("certificates?recursion=1")
if err != nil {
return nil, err
@@ -1103,6 +1128,10 @@ func (c *Client) CertificateList() ([]shared.CertInfo, error) {
}
func (c *Client) AddMyCertToServer(pwd string) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
body := shared.Jmap{"type": "client", "password": pwd}
_, err := c.post("certificates", body, Sync)
@@ -1110,12 +1139,20 @@ func (c *Client) AddMyCertToServer(pwd string) error {
}
func (c *Client) CertificateAdd(cert *x509.Certificate, name string) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
b64 := base64.StdEncoding.EncodeToString(cert.Raw)
_, err := c.post("certificates", shared.Jmap{"type": "client", "certificate": b64, "name": name}, Sync)
return err
}
func (c *Client) CertificateRemove(fingerprint string) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
_, err := c.delete(fmt.Sprintf("certificates/%s", fingerprint), nil, Sync)
return err
}
@@ -1156,6 +1193,10 @@ func (c *Client) GetAlias(alias string) string {
// Init creates a container from either a fingerprint or an alias; you must
// provide at least one.
func (c *Client) Init(name string, imgremote string, image string, profiles *[]string, config map[string]string, ephem bool) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
var tmpremote *Client
var err error
@@ -1291,6 +1332,10 @@ func (c *Client) Init(name string, imgremote string, image string, profiles *[]s
}
func (c *Client) LocalCopy(source string, name string, config map[string]string, profiles []string, ephemeral bool) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
body := shared.Jmap{
"source": shared.Jmap{
"type": "copy",
@@ -1306,6 +1351,10 @@ func (c *Client) LocalCopy(source string, name string, config map[string]string,
}
func (c *Client) Monitor(types []string, handler func(interface{})) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
url := c.BaseWSURL + path.Join("/", "1.0", "events")
if len(types) != 0 {
url += "?type=" + strings.Join(types, ",")
@@ -1343,6 +1392,10 @@ func (c *Client) Exec(name string, cmd []string, env map[string]string,
stdin io.ReadCloser, stdout io.WriteCloser,
stderr io.WriteCloser, controlHandler func(*Client, *websocket.Conn)) (int, error) {
+ if c.Remote.Public {
+ return -1, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
body := shared.Jmap{
"command": cmd,
"wait-for-websocket": true,
@@ -1453,6 +1506,10 @@ func (c *Client) Exec(name string, cmd []string, env map[string]string,
}
func (c *Client) Action(name string, action shared.ContainerAction, timeout int, force bool, stateful bool) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
body := shared.Jmap{
"action": action,
"timeout": timeout,
@@ -1466,6 +1523,10 @@ func (c *Client) Action(name string, action shared.ContainerAction, timeout int,
}
func (c *Client) Delete(name string) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
var url string
s := strings.SplitN(name, "/", 2)
if len(s) == 2 {
@@ -1493,6 +1554,10 @@ func (c *Client) ServerStatus() (*shared.ServerState, error) {
}
func (c *Client) ContainerInfo(name string) (*shared.ContainerInfo, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
ct := shared.ContainerInfo{}
resp, err := c.get(fmt.Sprintf("containers/%s", name))
@@ -1508,6 +1573,10 @@ func (c *Client) ContainerInfo(name string) (*shared.ContainerInfo, error) {
}
func (c *Client) ContainerState(name string) (*shared.ContainerState, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
ct := shared.ContainerState{}
resp, err := c.get(fmt.Sprintf("containers/%s/state", name))
@@ -1523,6 +1592,10 @@ func (c *Client) ContainerState(name string) (*shared.ContainerState, error) {
}
func (c *Client) GetLog(container string, log string) (io.Reader, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
uri := c.url(shared.APIVersion, "containers", container, "logs", log)
resp, err := c.getRaw(uri)
if err != nil {
@@ -1533,6 +1606,10 @@ func (c *Client) GetLog(container string, log string) (io.Reader, error) {
}
func (c *Client) ProfileConfig(name string) (*shared.ProfileConfig, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
ct := shared.ProfileConfig{}
resp, err := c.get(fmt.Sprintf("profiles/%s", name))
@@ -1548,6 +1625,10 @@ func (c *Client) ProfileConfig(name string) (*shared.ProfileConfig, error) {
}
func (c *Client) PushFile(container string, p string, gid int, uid int, mode os.FileMode, buf io.ReadSeeker) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
query := url.Values{"path": []string{p}}
uri := c.url(shared.APIVersion, "containers", container, "files") + "?" + query.Encode()
@@ -1571,6 +1652,10 @@ func (c *Client) PushFile(container string, p string, gid int, uid int, mode os.
}
func (c *Client) PullFile(container string, p string) (int, int, os.FileMode, io.ReadCloser, error) {
+ if c.Remote.Public {
+ return 0, 0, 0, nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
uri := c.url(shared.APIVersion, "containers", container, "files")
query := url.Values{"path": []string{p}}
@@ -1585,6 +1670,10 @@ func (c *Client) PullFile(container string, p string) (int, int, os.FileMode, io
}
func (c *Client) GetMigrationSourceWS(container string) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
body := shared.Jmap{"migration": true}
url := fmt.Sprintf("containers/%s", container)
if shared.IsSnapshot(container) {
@@ -1600,6 +1689,10 @@ func (c *Client) GetMigrationSourceWS(container string) (*Response, error) {
}
func (c *Client) MigrateFrom(name string, operation string, certificate string, secrets map[string]string, architecture string, config map[string]string, devices shared.Devices, profiles []string, baseImage string, ephemeral bool) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
source := shared.Jmap{
"type": "migration",
"mode": "pull",
@@ -1622,6 +1715,10 @@ func (c *Client) MigrateFrom(name string, operation string, certificate string,
}
func (c *Client) Rename(name string, newName string) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
oldNameParts := strings.SplitN(name, "/", 2)
newNameParts := strings.SplitN(newName, "/", 2)
if len(oldNameParts) != len(newNameParts) {
@@ -1672,16 +1769,28 @@ func (c *Client) WaitForSuccess(waitURL string) error {
}
func (c *Client) RestoreSnapshot(container string, snapshotName string, stateful bool) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
body := shared.Jmap{"restore": snapshotName, "stateful": stateful}
return c.put(fmt.Sprintf("containers/%s", container), body, Async)
}
func (c *Client) Snapshot(container string, snapshotName string, stateful bool) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
body := shared.Jmap{"name": snapshotName, "stateful": stateful}
return c.post(fmt.Sprintf("containers/%s/snapshots", container), body, Async)
}
func (c *Client) ListSnapshots(container string) ([]shared.SnapshotInfo, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
qUrl := fmt.Sprintf("containers/%s/snapshots?recursion=1", container)
resp, err := c.get(qUrl)
if err != nil {
@@ -1721,6 +1830,10 @@ func (c *Client) GetServerConfigString() ([]string, error) {
}
func (c *Client) SetServerConfig(key string, value string) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
ss, err := c.ServerStatus()
if err != nil {
return nil, err
@@ -1732,6 +1845,10 @@ func (c *Client) SetServerConfig(key string, value string) (*Response, error) {
}
func (c *Client) UpdateServerConfig(ss shared.BriefServerState) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
return c.put("", ss, Sync)
}
@@ -1739,6 +1856,10 @@ func (c *Client) UpdateServerConfig(ss shared.BriefServerState) (*Response, erro
* return string array representing a container's full configuration
*/
func (c *Client) GetContainerConfig(container string) ([]string, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
var resp []string
st, err := c.ContainerInfo(container)
@@ -1759,6 +1880,10 @@ func (c *Client) GetContainerConfig(container string) ([]string, error) {
}
func (c *Client) SetContainerConfig(container, key, value string) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ContainerInfo(container)
if err != nil {
return err
@@ -1784,6 +1909,10 @@ func (c *Client) SetContainerConfig(container, key, value string) error {
}
func (c *Client) UpdateContainerConfig(container string, st shared.BriefContainerInfo) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
resp, err := c.put(fmt.Sprintf("containers/%s", container), st, Async)
if err != nil {
return err
@@ -1793,6 +1922,10 @@ func (c *Client) UpdateContainerConfig(container string, st shared.BriefContaine
}
func (c *Client) ProfileCreate(p string) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
body := shared.Jmap{"name": p}
_, err := c.post("profiles", body, Sync)
@@ -1800,11 +1933,19 @@ func (c *Client) ProfileCreate(p string) error {
}
func (c *Client) ProfileDelete(p string) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
_, err := c.delete(fmt.Sprintf("profiles/%s", p), nil, Sync)
return err
}
func (c *Client) GetProfileConfig(profile string) (map[string]string, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ProfileConfig(profile)
if err != nil {
return nil, err
@@ -1814,6 +1955,10 @@ func (c *Client) GetProfileConfig(profile string) (map[string]string, error) {
}
func (c *Client) SetProfileConfigItem(profile, key, value string) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ProfileConfig(profile)
if err != nil {
shared.Debugf("Error getting profile %s to update", profile)
@@ -1831,6 +1976,10 @@ func (c *Client) SetProfileConfigItem(profile, key, value string) error {
}
func (c *Client) PutProfile(name string, profile shared.ProfileConfig) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
if profile.Name != name {
return fmt.Errorf("Cannot change profile name")
}
@@ -1840,6 +1989,10 @@ func (c *Client) PutProfile(name string, profile shared.ProfileConfig) error {
}
func (c *Client) ListProfiles() ([]string, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
resp, err := c.get("profiles")
if err != nil {
return nil, err
@@ -1877,6 +2030,10 @@ func (c *Client) ListProfiles() ([]string, error) {
}
func (c *Client) ApplyProfile(container, profile string) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ContainerInfo(container)
if err != nil {
return nil, err
@@ -1888,6 +2045,10 @@ func (c *Client) ApplyProfile(container, profile string) (*Response, error) {
}
func (c *Client) ContainerDeviceDelete(container, devname string) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ContainerInfo(container)
if err != nil {
return nil, err
@@ -1899,6 +2060,10 @@ func (c *Client) ContainerDeviceDelete(container, devname string) (*Response, er
}
func (c *Client) ContainerDeviceAdd(container, devname, devtype string, props []string) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ContainerInfo(container)
if err != nil {
return nil, err
@@ -1930,6 +2095,10 @@ func (c *Client) ContainerDeviceAdd(container, devname, devtype string, props []
}
func (c *Client) ContainerListDevices(container string) ([]string, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ContainerInfo(container)
if err != nil {
return nil, err
@@ -1942,6 +2111,10 @@ func (c *Client) ContainerListDevices(container string) ([]string, error) {
}
func (c *Client) ProfileDeviceDelete(profile, devname string) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ProfileConfig(profile)
if err != nil {
return nil, err
@@ -1957,6 +2130,10 @@ func (c *Client) ProfileDeviceDelete(profile, devname string) (*Response, error)
}
func (c *Client) ProfileDeviceAdd(profile, devname, devtype string, props []string) (*Response, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ProfileConfig(profile)
if err != nil {
return nil, err
@@ -1985,6 +2162,10 @@ func (c *Client) ProfileDeviceAdd(profile, devname, devtype string, props []stri
}
func (c *Client) ProfileListDevices(profile string) ([]string, error) {
+ if c.Remote.Public {
+ return nil, fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ProfileConfig(profile)
if err != nil {
return nil, err
@@ -1994,7 +2175,6 @@ func (c *Client) ProfileListDevices(profile string) ([]string, error) {
devs = append(devs, fmt.Sprintf("%s: %s", n, d["type"]))
}
return devs, nil
-
}
// WebsocketDial attempts to dial a websocket to a LXD instance, parsing
@@ -2015,6 +2195,10 @@ func WebsocketDial(dialer websocket.Dialer, url string) (*websocket.Conn, error)
}
func (c *Client) ProfileCopy(name, newname string, dest *Client) error {
+ if c.Remote.Public {
+ return fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
st, err := c.ProfileConfig(name)
if err != nil {
return err
@@ -2043,6 +2227,10 @@ func (c *Client) AsyncWaitMeta(resp *Response) (*shared.Jmap, error) {
}
func (c *Client) ImageFromContainer(cname string, public bool, aliases []string, properties map[string]string) (string, error) {
+ if c.Remote.Public {
+ return "", fmt.Errorf("This function isn't supported by public remotes.")
+ }
+
source := shared.Jmap{"type": "container", "name": cname}
if shared.IsSnapshot(cname) {
source["type"] = "snapshot"
diff --git a/lxc/remote.go b/lxc/remote.go
index 6f54717..8a7b5a3 100644
--- a/lxc/remote.go
+++ b/lxc/remote.go
@@ -184,7 +184,7 @@ func (c *remoteCmd) addServer(config *lxd.Config, server string, addr string, ac
var certificate *x509.Certificate
/* Attempt to connect using the system root CA */
- err = d.Finger()
+ _, err = d.GetServerConfig()
if err != nil {
// Failed to connect using the system CA, so retrieve the remote certificate
certificate, err = getRemoteCertificate(addr)
@@ -234,7 +234,7 @@ func (c *remoteCmd) addServer(config *lxd.Config, server string, addr string, ac
if d.IsPublic() || public {
config.Remotes[server] = lxd.RemoteConfig{Addr: addr, Public: true}
- if err := d.Finger(); err != nil {
+ if _, err := d.GetServerConfig(); err != nil {
return err
}
More information about the lxc-devel
mailing list