Playing with QueueController

My current task is to shift QueueController from Data to Control plane, at present it is in data plane[1] But I am stuck in between and here putting the situation. flaper87, vkmc and I are thinking to get the solution. Here I am putting my thoughts and efforts for same. Btw you already know flaper87 is my mentor and vkmc is another OpenStack hacker.

So I read code of different classes that reside under zaqar/storage like DriverBase, DataDriverBase, ControlDriverBase, Queue etc; both control and data plane are part of storage layer of zaqar, so we need to look there only atm. For this task main class at present is DataDriverBase and we need to shift its queue_controller()method into ControlDriver. This queue_controller which is inside zaqar.storage.base.DataDriverBase, is an abstract method. So I went to look for its implementation in the classes that have inherited DataDriverBase. And found that driver.py of all different datastores which zaqar support atm, that is mongodb, redis and sqlalchemy, have implementation of queue_controller inside driver.DataDriver class and also pooling.py and pipeling.py have its implementation which are inside same package zaqar/storage where base.py resides.

Mostly we will talk further for mongodb datastore, most of the similar stuff will apply for redis and sqlalchemy.

So we can’t just directly shift queue_controller into ControlDriver from DataDriver, we need to think how to fix queue_controller’s dependencies inside DataDriverBase. Then I realized, the main task is that ‘data plane should not have direct access to QueueController’, rather if data plane want it, it should come thorough control plane. So, just changed the definition of queue_controller() inside DataDriver(and all the places where queue_controller is implemented and directly accessing controllers.QueueController) such that now it call the newly defined mehtod queue_controller of ControlDriver, and this newly defined queue_controller method of ControlDriver will do the tasks that queue_controller of DataDriver was doing; so the code snippet are as follow:

Inside zaqar.storage.mongodb.DataDriver, before any change:

@decorators.lazy_property(write=False)
def queue_controller(self):
    return controllers.QueueController(self)

and now afater modification:
@decorators.lazy_property(write=False)
def queue_controller(self):
    return ControlDriver(self.conf, self.cache).queue_controller

and newly added queue_controller() inside ControlDriver looks as:
@decorators.lazy_property(write=False)
def queue_controller(self):
    return controllers.QueueController(self)

Now we need to manage all other penguins which got disturbed due to this change, so here starts the Real Game!

One thing that is easy to catch is now we need an instance of ControlDriver inside DataDriver, for this first I have created a new instance of ControlDriver inside queue_controller() of DataDriver and from it directly calling ControlDriver’s queue_controller(), the code for DataDriver’s queue_controller looks like the code snippet 2.

But later falper87 suggested that probably we need to create this ControlDriver instance outside the DataDriver. Like creating it in the bootstrap step and passing it to the DataDriver is the right thing to do. This will not create new ControlDriver each time whenever DataDriver.queue_controller() call is made. So now queue_controller() of DataDriver looks something like pasted below:

@decorators.lazy_property(write=False)
def queue_controller(self):
    return self.control_driver.queue_controller

No doubt this has changed init() of DriverBase, DataDriverBase, DataDriver and other related classes, all the test cases corresponds to same.  But we have managed them successfully.

Then we need queues_database() inside ControlDriver also from DataDriver, as QueueController is dependent on it. Now how I got to know about it is by looking at QueueCotroller’s definition3. So just shifted queues_database() into ControlDriver from DataDriver. Now while running the tests, got loooooooooooooot many errors, and it was expected as their would be many penguins that got disturbed. We have solved many errors, they are now less than half that were actually generated in starting, but still there are many yet to resolve.

The main error that we are facing right now is *’ControlDriver' object has no attribute 'message_controller'*. Okay, so it says that ControlDriver should have message_controller, why it occurred is obvious, somewhere QueueController would need it because before adding queue_controller to ControlDriver this was not an issue. So solution is just put message_controller inside ControlDriver too as it is in DataDriver.

No that will not be logically correct, message_controller is something that should not be in ControlDriver, it is not a part of control plane. So now what to do? Let us see where does QueueController need it – Few methods(like delete() and stats()) of QueueController need message_controller 4.

So now we need the access of message_controller in QueueController. We can’t directly access message_controller without DataDriver object, as again it won’t be logically correct. If we pass a DataDriver object into ControlDriver or QueueController it will be a circular loop and we will be in trap as we already need ControlDriver instance for DataDriver instance.

This is the whole problem whose solution is yet to find.

Playing with QueueController