Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make libnetwork understand pluginv2. #1472

Merged
merged 2 commits into from
Sep 28, 2016
Merged

Conversation

anusha-ragunathan
Copy link
Contributor

As part of daemon init, network and ipam drivers are passed a
pluginstore object that implements the plugin/getter interface. Use this
interface methods in libnetwork to interact with network plugins. This
interface provides the new and improved pluginv2 functionality and falls
back to pluginv1 (legacy) if necessary.

Signed-off-by: Anusha Ragunathan anusha@docker.com

@anusha-ragunathan
Copy link
Contributor Author

Companion PR to moby/moby#26860.

@@ -163,7 +165,7 @@ type initializer struct {
}

// New creates a new instance of network controller.
func New(cfgOptions ...config.Option) (NetworkController, error) {
func New(getter getter.PluginGetter, cfgOptions ...config.Option) (NetworkController, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getter.PluginGetter can be one of the config.Option. That will save the New API from changing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, please see if you can pass the plugin getter via a config option setter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -144,7 +144,7 @@ func newDriver() *driver {
}

// Init registers a new instance of bridge driver
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
func Init(dc driverapi.DriverCallback, ps interface{}, config map[string]interface{}) error {
Copy link
Contributor

@mavenugo mavenugo Sep 26, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this an interface{} ? why cant it be the concrete type ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plugingetter is only used in remote driver code. So it can be abstracted from other code paths. i.e bridge code doesnt need to know about a plugingetter, since it doesnt use it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it. Can you instead use the above DriverCallback for this purpose ?
You can return the plugingetter as a GetPluginGetter API as part of DriverCallback.
BTW, Controller implements DriverCallback and hence you can get this done cleanly without having to change the Init API signature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PluginGetter naturally falls in DriverRegistry rather than the Controller. I've made necessary updates.

}
})
} else {
plugins.Handle(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callback function seems identical. Can you pls reuse it instead of duplicating it here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

})
} else {
plugins.Handle(ipamapi.PluginEndpointType, func(name string, client *plugins.Client) {
a := newAllocator(name, client)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@mavenugo
Copy link
Contributor

@anusha-ragunathan thanks for the vendor updates. Are these changes done to be in sync with docker/docker ?

@anusha-ragunathan
Copy link
Contributor Author

@mavenugo : vendor update has 2 fold reason. 1. get the docker/docker/plugin/getter package 2. syncup with docker/docker

Copy link
Contributor

@mavenugo mavenugo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the vendor update again :-)

@aboch can u pls check if the vendoring work is fine ?

@@ -144,7 +144,7 @@ func newDriver() *driver {
}

// Init registers a new instance of bridge driver
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
func Init(dc driverapi.DriverCallback, ps interface{}, config map[string]interface{}) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it. Can you instead use the above DriverCallback for this purpose ?
You can return the plugingetter as a GetPluginGetter API as part of DriverCallback.
BTW, Controller implements DriverCallback and hence you can get this done cleanly without having to change the Init API signature.

@anusha-ragunathan
Copy link
Contributor Author

anusha-ragunathan commented Sep 26, 2016

CI failure on

--- FAIL: TestCreateMultipleNetworks (0.13s)
    bridge_test.go:468: iptables failed: iptables --wait -nvL DOCKER-ISOLATION: iptables: No chain/target/match by that name.

The test is not on the gh open issues and looks unrelated to the PR. I can open an issue if necessary.

@mavenugo
Copy link
Contributor

@anusha-ragunathan thats alright. can u pls address the comments ? I will check what is going on with the test failure.

@aboch
Copy link
Contributor

aboch commented Sep 27, 2016

@anusha-ragunathan
Please take care of these failures:

./macvlan_test.go:34: not enough arguments in call to Init
./macvlan_test.go:41: not enough arguments in call to Init
./macvlan_test.go:52: not enough arguments in call to Init

Run make to run all the tests offline.

@anusha-ragunathan
Copy link
Contributor Author

@aboch : I did, before opening the PR, but ran into errors modprobing ipvsadm although the package is installed and ip_vs is modprobed. A strange error where the test container cannot find modprobe and ipvsadm in $PATH, although its present. I'm debugging that right now.

@anusha-ragunathan
Copy link
Contributor Author

There were 2 libnetwork test containers that were stuck causing modprobe, ipvsadm PATH errors. Removing those fixed the issue, but now modprobe is unable to open modules.dep.bin. Rebooting host doesnt help. File exists on host.

$ ls -als /lib/modules/3.19.0-6 
8-generic/modules.dep.bin                                                                              
604 -rw-r--r-- 1 root root 618268 Sep 10 10:13 /lib/modules/3.19.0-68-generic/modules.dep.bin

RUN TestGetFamily
--- FAIL: TestGetFamily (0.00s)
Location: ipvs_test.go:124
Error: No error is expected but got no such file or directory

=== RUN TestService
WARN[0000] Could not load necessary modules for IPSEC rules: Running modprobe xfrm_user failed with message: modprobe: ERROR: ../libkmod/libkmod.c:557 kmod_search_moddep() could not open moddep file '/lib/modules/3.19.0-68-generic/modules.dep.bin', error: exit status 1
WARN[0000] Running modprobe ip_vs failed with message: modprobe: ERROR: ../libkmod/libkmod.c:557 kmod_search_moddep() could not open moddep file '/lib/modules/3.19.0-68-generic/modules.dep.bin', error: exit status 1
ERRO[0000] Could not get ipvs family information from the kernel. It is possible that ipvs is not enabled in your kernel. Native loadbalancing will not work until this is fixed.
--- FAIL: TestService (0.01s)
Location: ipvs_test.go:91
Error: No error is expected but got exit status 127

=== RUN TestDestination
WARN[0000] Could not load necessary modules for IPSEC rules: Running modprobe xfrm_user failed with message: modprobe: ERROR: ../libkmod/libkmod.c:557 kmod_search_moddep() could not open moddep file '/lib/modules/3.19.0-68-generic/modules.dep.bin', error: exit status 1
--- FAIL: TestDestination (0.04s)
Location: ipvs_test.go:91
Error: No error is expected but got exit status 127

@aboch
Copy link
Contributor

aboch commented Sep 27, 2016

@anusha-ragunathan
try first to export CIRCLECI then run make

For now, do not worry for the local make failures, just take care of the compiling issues in macvlan test code, and re-push.

If you want to run the CI locally, run make circle-ci

})
func Init(dc driverapi.DriverCallback, ps interface{}, config map[string]interface{}) error {
// Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
if ps != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please define a local function pointer which will point to ps.(plugingetter.PluginGetter) if ps != nil, plugins.Handle() otherwise

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@@ -37,7 +37,7 @@ type DrvRegistry struct {
// Functors definition

// InitFunc defines the driver initialization function signature.
type InitFunc func(driverapi.DriverCallback, map[string]interface{}) error
type InitFunc func(driverapi.DriverCallback, interface{}, map[string]interface{}) error
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to have the plugin getter be a member of DrvRegistry ?
At the end all the remote drivers register with the registry, he can hold the plugin getter for them to be called in the init function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, DrvRegistry is where PluginGetter belongs. Updated.

@@ -192,12 +195,12 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
dcfg = c.makeDriverConfig(i.ntype)
}

if err := drvRegistry.AddDriver(i.ntype, i.fn, dcfg); err != nil {
if err := drvRegistry.AddDriver(i.ntype, i.fn, dcfg, c.plugingetter); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you store the plugin getter in the drvRegistry, AddDriver() does prototype does not need to change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I've also split the PR into godep vendoring and plugin related code, so its easier to review.

Signed-off-by: Anusha Ragunathan <anusha@docker.com>
@@ -1074,7 +1078,7 @@ func (c *controller) loadDriver(networkType string) error {
}

func (c *controller) loadIPAMDriver(name string) error {
if _, err := plugins.Get(name, ipamapi.PluginEndpointType); err != nil {
if _, err := c.plugingetter.Get(name, ipamapi.PluginEndpointType, getter.LOOKUP); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we can modify to c.driverRegistry.GetPluginGetter().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c has to implement a GetPluginGetter to satisy DriverAPICallback which is a wrapper to drvRegistry.GetPluginGetter(). So this will be c.GetPluginGetter()

@@ -154,6 +155,7 @@ type controller struct {
agentInitDone chan struct{}
keys []*types.EncryptionKey
clusterConfigAvailable bool
plugingetter getter.PluginGetter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we no longer need this member in controller, rather we can just keep it confined to drvRegistry

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes indeed

@@ -29,7 +29,15 @@ func newDriver(name string, client *plugins.Client) driverapi.Driver {
// Init makes sure a remote driver is registered when a network driver
// plugin is activated.
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
plugins.Handle(driverapi.NetworkPluginEndpointType, func(name string, client *plugins.Client) {
var handleFunc func(string, func(string, *plugins.Client))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could just rewrite the whole block as:

handleFunc := plugins.Handle
if pg := dc.GetPluginGetter(); pg != nil {
    handleFunc = pg.Handle
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

ipamDrivers ipamTable
dfn DriverNotifyFunc
ifn IPAMNotifyFunc
plugingetter getter.PluginGetter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow the camel case convention as in ipamDrivers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes! Done.

@@ -30,7 +30,15 @@ func newAllocator(name string, client *plugins.Client) ipamapi.Ipam {

// Init registers a remote ipam when its plugin is activated
func Init(cb ipamapi.Callback, l, g interface{}) error {
plugins.Handle(ipamapi.PluginEndpointType, func(name string, client *plugins.Client) {
var handleFunc func(string, func(string, *plugins.Client))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, you should be able to reduce the footprint of this change, make it less verbose.

@anusha-ragunathan
Copy link
Contributor Author

CI failure on #1385

As part of daemon init, network and ipam drivers are passed a
pluginstore object that implements the plugin/getter interface. Use this
interface methods in libnetwork to interact with network plugins. This
interface provides the new and improved pluginv2 functionality and falls
back to pluginv1 (legacy) if necessary.

Signed-off-by: Anusha Ragunathan <anusha@docker.com>
@aboch
Copy link
Contributor

aboch commented Sep 27, 2016

LGTM

@mavenugo
Copy link
Contributor

@anusha-ragunathan thanks for taking care of all the comments. LGTM

@mavenugo mavenugo merged commit d34488a into moby:master Sep 28, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants