The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/1766

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===

From 4c2678bf2e68c90dcde7d3fdf5b37e24f461aff8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@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 <stgra...@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@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@ADDRESS>\n"
         "Language-Team: LANGUAGE <l...@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?= <stgra...@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 <stgra...@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?= <stgra...@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 <stgra...@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?= <stgra...@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 <stgra...@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
                }
 
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to