{"action":"created","comment":{"url":"https://api.github.com/repos/docker/libnetwork/pulls/comments/31804650","id":31804650,"diff_hunk":"@@ -1,18 +1,191 @@\n Remote Drivers\n ==============\n \n-The remote driver package provides the integration point for dynamically-registered drivers.\n+The `drivers.remote` package provides the integration point for dynamically-registered drivers. Unlike the other driver packages, it does not provide a single implementation of a driver; rather, it provides a proxy for remote driver processes, which are registered and communicate with LibNetwork via the Docker plugin package.\n \n-## LibNetwork Integration\n+## LibNetwork integration with the Docker `plugins` package\n \n-When LibNetwork initialises the `Remote` package with the `Init()` function, it passes a `DriverCallback` as a parameter, which implements the `RegisterDriver()`. The Remote Driver package can use this interface to register any of the `Dynamic` Drivers/Plugins with LibNetwork's `NetworkController`.\n+When LibNetwork initialises the `drivers.remote` package with the `Init()` function, it passes a `DriverCallback` as a parameter, which implements `RegisterDriver()`. The remote driver package uses this interface to register remote drivers with LibNetwork's `NetworkController`, by supplying it in a `plugins.Handle` callback.\n \n-This design ensures that the implementation details (TBD) of Dynamic Driver Registration mechanism is completely owned by the inbuilt-Remote driver, and it doesn't expose any of the driver layer to the North of LibNetwork (none of the LibNetwork client APIs are impacted).\n+The callback is invoked when a driver is loaded with the `plugins.Get` API call. How that comes about is out of scope here (but it might be, for instance, when that driver is mentioned by the user).\n+\n+This design ensures that the details of driver registration mechanism are owned by the remote driver package, and it doesn't expose any of the driver layer to the North of LibNetwork.\n \n ## Implementation\n \n-The actual implementation of how the Inbuilt Remote Driver registers with the Dynamic Driver is Work-In-Progress. But, the Design Goal is to Honor the bigger goals of LibNetwork by keeping it Highly modular and make sure that LibNetwork is fully composable in nature. \n+The remote driver implementation uses a `plugins.Client` to communicate with the remote driver process. The `driverapi.Driver` methods are implemented as RPCs over the plugin client.\n+\n+The payloads of these RPCs are mostly direct translations into JSON of the arguments given to the method. There are some exceptions to account for the use of the interfaces `EndpointInfo` and `JoinInfo`, and data types that do not serialise to JSON well (e.g., `net.IPNet`). The protocol is detailed below under \"Protocol\".\n \n ## Usage\n \n-The In-Built Remote Driver follows all the rules of any other In-Built Driver and has exactly the same Driver APIs exposed. LibNetwork will also support driver-specific `options` and User-supplied `Labels` which the Dynamic Drivers can make use for its operations.\n+A remote driver proxy follows all the rules of any other in-built driver and has exactly the same `Driver` interface exposed. LibNetwork will also support driver-specific `options` and user-supplied `labels` which may influence the behaviour of a remote driver process.\n+\n+## Protocol\n+\n+The remote driver protocol is a set of RPCs, issued as HTTP POSTs with JSON payloads. The proxy issues requests, and the remote driver process is expected to respond usually with a JSON payload of its own, although in some cases these are empty maps.\n+\n+### Errors\n+\n+If the remote process cannot decode, or otherwise detects a syntactic problem with the HTTP request or payload, it must respond with an HTTP error status (4xx or 5xx).\n+\n+If the remote process can decode the request, but cannot complete the operation, it must send a response in the form\n+\n+    {\n+        \"Err\": string\n+    }\n+\n+The string value supplied may appear in logs, so should not include confidential information.\n+\n+### Handshake\n+\n+When loaded, a remote driver process receives an HTTP POST on the URL `/Plugin.Activate` with no payload. It must respond with a manifest of the form\n+\n+    {\n+        \"Implements\": [\"NetworkDriver\"]\n+    }\n+\n+Other entries in the list value are allowed; `\"NetworkDriver\"` indicates that the plugin should be registered with LibNetwork as a driver.\n+\n+### Create network\n+\n+When the proxy is asked to create a network, the remote process shall receive a POST to the URL `/NetworkDriver.CreateNetwork` of the form\n+\n+    {\n+        \"NetworkID\": string,\n+        \"Options\": {\n+            ...\n+        }\n+    }\n+\n+The `NetworkID` value is generated by LibNetwork. The `Options` value is the arbitrary map given to the proxy by LibNetwork.\n+\n+The response indicating success is empty:\n+\n+    `{}`\n+\n+### Delete network\n+\n+When a network owned by the remote driver is deleted, the remote process shall receive a POST to the URL `/NetworkDriver.DeleteNetwork` of the form\n+\n+    {\n+        \"NetworkID\": string\n+    }\n+\n+The success response is empty:\n+\n+    {}\n+\n+### Create endpoint\n+\n+When the proxy is asked to create an endpoint, the remote process shall receive a POST to the URL `/NetworkDriver.CreateEndpoint` of the form\n+\n+    {\n+        \"NetworkID\": string,\n+        \"EndpointID\": string,\n+        \"Options\": {\n+            ...\n+        },\n+        \"Interfaces\": [{\n+            \"ID\": int,\n+            \"Address\": string,\n+            \"AddressIPv6\": string,\n+            \"MacAddress\": string\n+        }, ...]\n+    }\n+\n+The `NetworkID` is the generated identifier for the network to which the endpoint belongs; the `EndpointID` is a generated identifier for the endpoint.\n+\n+`Options` is an arbitrary map as supplied to the proxy.\n+\n+The `Interfaces` value is a list with values of the form given. The fields in the `Interfaces` entries may be empty; and the `Interfaces` list itself may be empty. If supplied, `Address` is an IPv4 address and subnet in CIDR notation; e.g., `\"192.168.34.12/16\"`. If supplied, `AddressIPv6` is an IPv6 address and subnet in CIDR notation. `MacAddress` is a MAC address as a string; e.g., `\"6e:75:32:60:44:c9\"`.","path":"docs/remote.md","position":107,"original_position":107,"commit_id":"85d8690f4923d8f7d295cb4788b25a2e9a585f15","original_commit_id":"50b7c900cc15b36a14eeefb151f4b53a89bb7bc5","user":{"login":"mavenugo","id":5056191,"avatar_url":"https://avatars.githubusercontent.com/u/5056191?v=3","gravatar_id":"","url":"https://api.github.com/users/mavenugo","html_url":"https://github.com/mavenugo","followers_url":"https://api.github.com/users/mavenugo/followers","following_url":"https://api.github.com/users/mavenugo/following{/other_user}","gists_url":"https://api.github.com/users/mavenugo/gists{/gist_id}","starred_url":"https://api.github.com/users/mavenugo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mavenugo/subscriptions","organizations_url":"https://api.github.com/users/mavenugo/orgs","repos_url":"https://api.github.com/users/mavenugo/repos","events_url":"https://api.github.com/users/mavenugo/events{/privacy}","received_events_url":"https://api.github.com/users/mavenugo/received_events","type":"User","site_admin":false},"body":"works for me.","created_at":"2015-06-05T11:15:42Z","updated_at":"2015-06-05T11:15:42Z","html_url":"https://github.com/docker/libnetwork/pull/192#discussion_r31804650","pull_request_url":"https://api.github.com/repos/docker/libnetwork/pulls/192","_links":{"self":{"href":"https://api.github.com/repos/docker/libnetwork/pulls/comments/31804650"},"html":{"href":"https://github.com/docker/libnetwork/pull/192#discussion_r31804650"},"pull_request":{"href":"https://api.github.com/repos/docker/libnetwork/pulls/192"}}},"pull_request":{"url":"https://api.github.com/repos/docker/libnetwork/pulls/192","id":35958538,"html_url":"https://github.com/docker/libnetwork/pull/192","diff_url":"https://github.com/docker/libnetwork/pull/192.diff","patch_url":"https://github.com/docker/libnetwork/pull/192.patch","issue_url":"https://api.github.com/repos/docker/libnetwork/issues/192","number":192,"state":"open","locked":false,"title":"Document the remote driver protocol","user":{"login":"squaremo","id":62033,"avatar_url":"https://avatars.githubusercontent.com/u/62033?v=3","gravatar_id":"","url":"https://api.github.com/users/squaremo","html_url":"https://github.com/squaremo","followers_url":"https://api.github.com/users/squaremo/followers","following_url":"https://api.github.com/users/squaremo/following{/other_user}","gists_url":"https://api.github.com/users/squaremo/gists{/gist_id}","starred_url":"https://api.github.com/users/squaremo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/squaremo/subscriptions","organizations_url":"https://api.github.com/users/squaremo/orgs","repos_url":"https://api.github.com/users/squaremo/repos","events_url":"https://api.github.com/users/squaremo/events{/privacy}","received_events_url":"https://api.github.com/users/squaremo/received_events","type":"User","site_admin":false},"body":"And some minor updates to the preceding text.\r\n\r\nSigned-off-by: Michael Bridgen <mikeb@squaremobius.net>","created_at":"2015-05-21T17:38:13Z","updated_at":"2015-06-05T11:15:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8d89acce83c0ee50ec0a4d1aae832be6ed2f1fc7","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/docker/libnetwork/pulls/192/commits","review_comments_url":"https://api.github.com/repos/docker/libnetwork/pulls/192/comments","review_comment_url":"https://api.github.com/repos/docker/libnetwork/pulls/comments{/number}","comments_url":"https://api.github.com/repos/docker/libnetwork/issues/192/comments","statuses_url":"https://api.github.com/repos/docker/libnetwork/statuses/85d8690f4923d8f7d295cb4788b25a2e9a585f15","head":{"label":"squaremo:remote_driver_docs","ref":"remote_driver_docs","sha":"85d8690f4923d8f7d295cb4788b25a2e9a585f15","user":{"login":"squaremo","id":62033,"avatar_url":"https://avatars.githubusercontent.com/u/62033?v=3","gravatar_id":"","url":"https://api.github.com/users/squaremo","html_url":"https://github.com/squaremo","followers_url":"https://api.github.com/users/squaremo/followers","following_url":"https://api.github.com/users/squaremo/following{/other_user}","gists_url":"https://api.github.com/users/squaremo/gists{/gist_id}","starred_url":"https://api.github.com/users/squaremo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/squaremo/subscriptions","organizations_url":"https://api.github.com/users/squaremo/orgs","repos_url":"https://api.github.com/users/squaremo/repos","events_url":"https://api.github.com/users/squaremo/events{/privacy}","received_events_url":"https://api.github.com/users/squaremo/received_events","type":"User","site_admin":false},"repo":{"id":35114108,"name":"libnetwork","full_name":"squaremo/libnetwork","owner":{"login":"squaremo","id":62033,"avatar_url":"https://avatars.githubusercontent.com/u/62033?v=3","gravatar_id":"","url":"https://api.github.com/users/squaremo","html_url":"https://github.com/squaremo","followers_url":"https://api.github.com/users/squaremo/followers","following_url":"https://api.github.com/users/squaremo/following{/other_user}","gists_url":"https://api.github.com/users/squaremo/gists{/gist_id}","starred_url":"https://api.github.com/users/squaremo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/squaremo/subscriptions","organizations_url":"https://api.github.com/users/squaremo/orgs","repos_url":"https://api.github.com/users/squaremo/repos","events_url":"https://api.github.com/users/squaremo/events{/privacy}","received_events_url":"https://api.github.com/users/squaremo/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/squaremo/libnetwork","description":"networking for containers","fork":true,"url":"https://api.github.com/repos/squaremo/libnetwork","forks_url":"https://api.github.com/repos/squaremo/libnetwork/forks","keys_url":"https://api.github.com/repos/squaremo/libnetwork/keys{/key_id}","collaborators_url":"https://api.github.com/repos/squaremo/libnetwork/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/squaremo/libnetwork/teams","hooks_url":"https://api.github.com/repos/squaremo/libnetwork/hooks","issue_events_url":"https://api.github.com/repos/squaremo/libnetwork/issues/events{/number}","events_url":"https://api.github.com/repos/squaremo/libnetwork/events","assignees_url":"https://api.github.com/repos/squaremo/libnetwork/assignees{/user}","branches_url":"https://api.github.com/repos/squaremo/libnetwork/branches{/branch}","tags_url":"https://api.github.com/repos/squaremo/libnetwork/tags","blobs_url":"https://api.github.com/repos/squaremo/libnetwork/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/squaremo/libnetwork/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/squaremo/libnetwork/git/refs{/sha}","trees_url":"https://api.github.com/repos/squaremo/libnetwork/git/trees{/sha}","statuses_url":"https://api.github.com/repos/squaremo/libnetwork/statuses/{sha}","languages_url":"https://api.github.com/repos/squaremo/libnetwork/languages","stargazers_url":"https://api.github.com/repos/squaremo/libnetwork/stargazers","contributors_url":"https://api.github.com/repos/squaremo/libnetwork/contributors","subscribers_url":"https://api.github.com/repos/squaremo/libnetwork/subscribers","subscription_url":"https://api.github.com/repos/squaremo/libnetwork/subscription","commits_url":"https://api.github.com/repos/squaremo/libnetwork/commits{/sha}","git_commits_url":"https://api.github.com/repos/squaremo/libnetwork/git/commits{/sha}","comments_url":"https://api.github.com/repos/squaremo/libnetwork/comments{/number}","issue_comment_url":"https://api.github.com/repos/squaremo/libnetwork/issues/comments{/number}","contents_url":"https://api.github.com/repos/squaremo/libnetwork/contents/{+path}","compare_url":"https://api.github.com/repos/squaremo/libnetwork/compare/{base}...{head}","merges_url":"https://api.github.com/repos/squaremo/libnetwork/merges","archive_url":"https://api.github.com/repos/squaremo/libnetwork/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/squaremo/libnetwork/downloads","issues_url":"https://api.github.com/repos/squaremo/libnetwork/issues{/number}","pulls_url":"https://api.github.com/repos/squaremo/libnetwork/pulls{/number}","milestones_url":"https://api.github.com/repos/squaremo/libnetwork/milestones{/number}","notifications_url":"https://api.github.com/repos/squaremo/libnetwork/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/squaremo/libnetwork/labels{/name}","releases_url":"https://api.github.com/repos/squaremo/libnetwork/releases{/id}","created_at":"2015-05-05T17:32:11Z","updated_at":"2015-05-05T17:32:12Z","pushed_at":"2015-06-05T10:27:39Z","git_url":"git://github.com/squaremo/libnetwork.git","ssh_url":"git@github.com:squaremo/libnetwork.git","clone_url":"https://github.com/squaremo/libnetwork.git","svn_url":"https://github.com/squaremo/libnetwork","homepage":"","size":1194,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"docker:master","ref":"master","sha":"0d3a8c16fcafd94c71005adadc6f604ab11c32e0","user":{"login":"docker","id":5429470,"avatar_url":"https://avatars.githubusercontent.com/u/5429470?v=3","gravatar_id":"","url":"https://api.github.com/users/docker","html_url":"https://github.com/docker","followers_url":"https://api.github.com/users/docker/followers","following_url":"https://api.github.com/users/docker/following{/other_user}","gists_url":"https://api.github.com/users/docker/gists{/gist_id}","starred_url":"https://api.github.com/users/docker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/docker/subscriptions","organizations_url":"https://api.github.com/users/docker/orgs","repos_url":"https://api.github.com/users/docker/repos","events_url":"https://api.github.com/users/docker/events{/privacy}","received_events_url":"https://api.github.com/users/docker/received_events","type":"Organization","site_admin":false},"repo":{"id":31046054,"name":"libnetwork","full_name":"docker/libnetwork","owner":{"login":"docker","id":5429470,"avatar_url":"https://avatars.githubusercontent.com/u/5429470?v=3","gravatar_id":"","url":"https://api.github.com/users/docker","html_url":"https://github.com/docker","followers_url":"https://api.github.com/users/docker/followers","following_url":"https://api.github.com/users/docker/following{/other_user}","gists_url":"https://api.github.com/users/docker/gists{/gist_id}","starred_url":"https://api.github.com/users/docker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/docker/subscriptions","organizations_url":"https://api.github.com/users/docker/orgs","repos_url":"https://api.github.com/users/docker/repos","events_url":"https://api.github.com/users/docker/events{/privacy}","received_events_url":"https://api.github.com/users/docker/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/docker/libnetwork","description":"networking for containers","fork":false,"url":"https://api.github.com/repos/docker/libnetwork","forks_url":"https://api.github.com/repos/docker/libnetwork/forks","keys_url":"https://api.github.com/repos/docker/libnetwork/keys{/key_id}","collaborators_url":"https://api.github.com/repos/docker/libnetwork/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/docker/libnetwork/teams","hooks_url":"https://api.github.com/repos/docker/libnetwork/hooks","issue_events_url":"https://api.github.com/repos/docker/libnetwork/issues/events{/number}","events_url":"https://api.github.com/repos/docker/libnetwork/events","assignees_url":"https://api.github.com/repos/docker/libnetwork/assignees{/user}","branches_url":"https://api.github.com/repos/docker/libnetwork/branches{/branch}","tags_url":"https://api.github.com/repos/docker/libnetwork/tags","blobs_url":"https://api.github.com/repos/docker/libnetwork/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/docker/libnetwork/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/docker/libnetwork/git/refs{/sha}","trees_url":"https://api.github.com/repos/docker/libnetwork/git/trees{/sha}","statuses_url":"https://api.github.com/repos/docker/libnetwork/statuses/{sha}","languages_url":"https://api.github.com/repos/docker/libnetwork/languages","stargazers_url":"https://api.github.com/repos/docker/libnetwork/stargazers","contributors_url":"https://api.github.com/repos/docker/libnetwork/contributors","subscribers_url":"https://api.github.com/repos/docker/libnetwork/subscribers","subscription_url":"https://api.github.com/repos/docker/libnetwork/subscription","commits_url":"https://api.github.com/repos/docker/libnetwork/commits{/sha}","git_commits_url":"https://api.github.com/repos/docker/libnetwork/git/commits{/sha}","comments_url":"https://api.github.com/repos/docker/libnetwork/comments{/number}","issue_comment_url":"https://api.github.com/repos/docker/libnetwork/issues/comments{/number}","contents_url":"https://api.github.com/repos/docker/libnetwork/contents/{+path}","compare_url":"https://api.github.com/repos/docker/libnetwork/compare/{base}...{head}","merges_url":"https://api.github.com/repos/docker/libnetwork/merges","archive_url":"https://api.github.com/repos/docker/libnetwork/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/docker/libnetwork/downloads","issues_url":"https://api.github.com/repos/docker/libnetwork/issues{/number}","pulls_url":"https://api.github.com/repos/docker/libnetwork/pulls{/number}","milestones_url":"https://api.github.com/repos/docker/libnetwork/milestones{/number}","notifications_url":"https://api.github.com/repos/docker/libnetwork/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/docker/libnetwork/labels{/name}","releases_url":"https://api.github.com/repos/docker/libnetwork/releases{/id}","created_at":"2015-02-20T01:20:15Z","updated_at":"2015-06-04T17:12:12Z","pushed_at":"2015-06-05T10:27:39Z","git_url":"git://github.com/docker/libnetwork.git","ssh_url":"git@github.com:docker/libnetwork.git","clone_url":"https://github.com/docker/libnetwork.git","svn_url":"https://github.com/docker/libnetwork","homepage":"","size":7251,"stargazers_count":253,"watchers_count":253,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":72,"mirror_url":null,"open_issues_count":41,"forks":72,"open_issues":41,"watchers":253,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/docker/libnetwork/pulls/192"},"html":{"href":"https://github.com/docker/libnetwork/pull/192"},"issue":{"href":"https://api.github.com/repos/docker/libnetwork/issues/192"},"comments":{"href":"https://api.github.com/repos/docker/libnetwork/issues/192/comments"},"review_comments":{"href":"https://api.github.com/repos/docker/libnetwork/pulls/192/comments"},"review_comment":{"href":"https://api.github.com/repos/docker/libnetwork/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/docker/libnetwork/pulls/192/commits"},"statuses":{"href":"https://api.github.com/repos/docker/libnetwork/statuses/85d8690f4923d8f7d295cb4788b25a2e9a585f15"}}}}