<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'>Hi Tim,<BR> <BR>As we discussed, here is the very first draft of the builtin proposal for discussion<BR>in the meeting tomorrow. Tried to address many of your comments. Others<BR>need a bit of discussion.<BR> <BR>Prabhakar<BR><br> <BR><div>> Date: Thu, 27 Mar 2014 08:27:59 -0700<br>> From: thinrichs@vmware.com<br>> To: openstack-dev@lists.openstack.org<br>> Subject: Re: [openstack-dev] [Congress] Policy types<br>> <br>> Hi Prabhakar,<br>> <br>> I looked into this a while back.  pydatalog is a cool project, and I'd like to find time to study some of its algorithms and architecture a bit more.  <br>> <br>> The reason we rolled our own version of Datalog is that we knew we'd want the freedom to try out non-standard Datalog algorithms, and there are algorithms we will likely need that aren't usually included (query rewriting, skolemization, conversion to DNF, etc.).  I suppose we could have modified pydatalog, but given that it is basically an extension to Python, it seemed there would be significant overhead in figuring out the code, making sure to keep our changes compatible with the old, etc.  Rolling our own gives us the freedom to build exactly what we need with minimal distractions, which is important since we won't really know what we need until we start getting feedback from users.  <br>> <br>> But like I said, there are probably some good ideas in there, so if the way they deal with builtins is useful to us, great!  I'd just keep in mind that the benefit of using Datalog instead of Python is mainly that it *limits* what policy authors can say (without limiting it too much).  <br>> <br>> Tim<br>> <br>> ----- Original Message -----<br>> | From: "prabhakar Kudva" <nandavarpk@hotmail.com><br>> | To: "OpenStack Development Mailing List (not for usage questions)" <openstack-dev@lists.openstack.org><br>> | Sent: Wednesday, March 26, 2014 9:04:22 AM<br>> | Subject: Re: [openstack-dev] [Congress] Policy types<br>> | <br>> | Hi Tim, All,<br>> |  <br>> | As I was preparing the background for the proposal for the<br>> | __Congress_builtins__,<br>> | came across this link which uses Datalog with Python, and provides<br>> | data integration facilities through SQLAlchemy.  The tool seems to have been<br>> | used (from the web page claim) in production:<br>> | Just want to run it by everyone to see if this is connected or useful in our<br>> | builtin<br>> | capability, and anything we can glean from it:<br>> |  <br>> | https://urldefense.proofpoint.com/v1/url?u=https://pypi.python.org/pypi/pyDatalog&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=WvQzzQA4hxW34TMc13h1FgKQQSxHsa1RgBpgfI5lO2U%3D%0A&s=6028d309c9c709635828e7dd33c3f614db1b6989544e05ad6a21da2e646144fe<br>> | <br>> |  https://urldefense.proofpoint.com/v1/url?u=https://sites.google.com/site/pydatalog/&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=WvQzzQA4hxW34TMc13h1FgKQQSxHsa1RgBpgfI5lO2U%3D%0A&s=fb152fdc60b5925bb47145dd54973b8184a2b47fb51c28cc86afd6ecbe02b2c5<br>> |  <br>> | https://urldefense.proofpoint.com/v1/url?u=https://sites.google.com/site/pydatalog/home/datalog-applications&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=WvQzzQA4hxW34TMc13h1FgKQQSxHsa1RgBpgfI5lO2U%3D%0A&s=a4cb6eed4bf9d7d0a0bfa811c3c8d72f64b973924697f0e5e9e00681403a7664<br>> |  <br>> | Thanks,<br>> |  <br>> | Prabhakar<br>> |  <br>> | > Date: Tue, 18 Mar 2014 12:56:10 -0700<br>> | > From: thinrichs@vmware.com<br>> | > To: openstack-dev@lists.openstack.org<br>> | > CC: rajdeepd@vmware.com<br>> | > Subject: Re: [openstack-dev] [Congress] Policy types<br>> | > <br>> | > Hi Prabhakar,<br>> | > <br>> | > Found time for a more detailed response.  Comments are inline.<br>> | > <br>> | > Tim<br>> | > <br>> | > ----- Original Message -----<br>> | > | From: "Tim Hinrichs" <thinrichs@vmware.com><br>> | > | To: "OpenStack Development Mailing List (not for usage questions)"<br>> | > | <openstack-dev@lists.openstack.org><br>> | > | Sent: Tuesday, March 18, 2014 9:31:34 AM<br>> | > | Subject: Re: [openstack-dev] [Congress] Policy types<br>> | > | <br>> | > | Hi Prabhakar,<br>> | > | <br>> | > | No IRC meeting this week.  Our IRC is every *other* week, and we had it<br>> | > | last<br>> | > | week.<br>> | > | <br>> | > | Though there's been enough activity of late that maybe we should consider<br>> | > | making it weekly.<br>> | > | <br>> | > | I'll address the rest later.<br>> | > | <br>> | > | Tim<br>> | > | <br>> | > | ----- Original Message -----<br>> | > | | From: "prabhakar Kudva" <nandavarpk@hotmail.com><br>> | > | | To: "OpenStack Development Mailing List (not for usage questions)"<br>> | > | | <openstack-dev@lists.openstack.org><br>> | > | | Sent: Monday, March 17, 2014 7:45:53 PM<br>> | > | | Subject: Re: [openstack-dev] [Congress] Policy types<br>> | > | | <br>> | > | | Hi Tim,<br>> | > | |  <br>> | > | | Definitely would like to learn more about the Data Integration<br>> | > | | component<br>> | > | | and how best to contribute. Can't find it in the latest git, perhaps we<br>> | > | | can<br>> | > | | discuss during the meeting tomorrow. Where can I find some code and/or<br>> | > | | document?<br>> | > <br>> | > There are no docs yet, and the only code in git is a quick-and-dirty<br>> | > ActiveDirectory integration.  But conceptually there are two pieces of the<br>> | > data integration story.<br>> | > <br>> | > 1. We're representing the data stored in each cloud service (that is<br>> | > pertinent to policy) as a collection of TABLES.  Each table is a<br>> | > collection of rows that all have the same number of columns.  Each value<br>> | > in the table is a scalar (number or string).<br>> | > <br>> | > If you look at the last IRC, Rajdeep has started working on translating<br>> | > Neutron data into this table format.  There are a couple of emails on the<br>> | > mailing list as well where we had some discussion.  Here's his change set.<br>> | > <br>> | > https://urldefense.proofpoint.com/v1/url?u=https://review.openstack.org/%23/c/77835/&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=WvQzzQA4hxW34TMc13h1FgKQQSxHsa1RgBpgfI5lO2U%3D%0A&s=7ca1c47ce75bd3fd3a4f5792d43bd3f1a74209eae6ea8e41f45aa0832e53c7e4<br>> | > <br>> | > 2. The policy engine will need to ask for the contents of tables (or<br>> | > updates to tables).  Or have the contents/updates pushed to it<br>> | > periodically.  The infrastructure for doing this is what Peter (pballand)<br>> | > volunteered to do in IRC last week.  Let's wait on this to see what he has<br>> | > to say.<br>> | > <br>> | > <br>> | > <br>> | > | |  <br>> | > | | I like the idea of using an 'evauate' wrapper.  And the idea of a<br>> | > | | builtin<br>> | > | | library of functions.  Having strict rules for builtins and an evaluate<br>> | > | | wrapper<br>> | > | | to do type checking (primitive or builtin) and so on reduces the silent<br>> | > | | errors or weird outcomes.<br>> | > | |  <br>> | > | | I also agree, raw python using methods like 'calleable' (or other ways<br>> | > | | of checking if the function can be called in python) may not always<br>> | > | | give<br>> | > | | definitive answers. Even the definition of callable says, that a True<br>> | > | | only<br>> | > | | says that the object 'appears' calleable.<br>> | > | |  <br>> | > | | So silent and weird problems are possible if we try to execute. On the<br>> | > | | other<br>> | > | | hand,<br>> | > | | if we are looking at module which contains only user defined functions<br>> | > | | or<br>> | > | | builtine<br>> | > | | , i.e., there  are strict rules to what exactly constitute<br>> | > | | allowed-functions,<br>> | > | | then there<br>> | > | | is a higher likelihood that it is correct.  But still a likelihood.<br>> | > <br>> | > Agreed: errors will always be possible.  The policy engine will treat them<br>> | > as failures (i.e. won't "re-throw" the error), so we just want to help the<br>> | > policy-writer as much as we can.<br>> | > <br>> | > | |  <br>> | > | | I like the 'evaluate' idea which could do the checking within<br>> | > | | to make sure the function is indeed calleable, and silent and weird<br>> | > | | side<br>> | > | | effects<br>> | > | | are filtered inside the 'evaluate'. In addition, it can do checking if<br>> | > | | it<br>> | > | | is<br>> | > | | a  primitive or some other valid format. Needs more thought on this.<br>> | > | |  <br>> | > | | Let's discuss implementation paths if possible at the meeting. Would<br>> | > | | like<br>> | > | | to<br>> | > | | carve out a small implementation goal either in the 'data integration'<br>> | > | | line<br>> | > | | or<br>> | > | | the discussion above.<br>> | > <br>> | > <br>> | > Great!<br>> | > <br>> | > One option is to coordinate with rajdeep and see if there's an OS component<br>> | > that you'd like to try to turn into tables.  His code is an example of<br>> | > what you'd be writing.<br>> | > <br>> | > Or you could put together a proposal for adding Python builtins to the<br>> | > policy engine.  One thing to think about is that we'd want to make it easy<br>> | > to add additional builtins.  We'd also need to figure out what the syntax<br>> | > would look like from the policy-writer's point of view.  Here I've seen<br>> | > two options:<br>> | > <br>> | > // +, *, and lt are builtins<br>> | > p(x, y, z) :- q(x), r(z) (3*x)+2=y, lt(y, z)<br>> | > <br>> | > // builtins are forced to look like any other table.<br>> | > p(x, y, z) :- q(x), r(z), *(3, x, w), +(w, 2, y), lt(y, z)<br>> | > <br>> | > <br>> | > The latter is a bit clunky, but it makes it easier to implement the policy<br>> | > engine.<br>> | > <br>> | > Tim<br>> | > <br>> | >    <br>> | > <br>> | > | |  <br>> | > | | Prabhakar<br>> | > | |  <br>> | > | |  <br>> | > | |  <br>> | > | | <br>> | > | |  <br>> | > | | > Date: Mon, 17 Mar 2014 08:57:05 -0700<br>> | > | | > From: thinrichs@vmware.com<br>> | > | | > To: openstack-dev@lists.openstack.org<br>> | > | | > Subject: Re: [openstack-dev] [Congress] Policy types<br>> | > | | > <br>> | > | | > Hi Prabhakar,<br>> | > | | > <br>> | > | | > One big piece we're missing in terms of code right now is the Data<br>> | > | | > Integration component.  The job of this component is to integrate<br>> | > | | > data<br>> | > | | > sources available in the cloud so that tables like<br>> | > | | > nova:virtual_machine,<br>> | > | | > neutron:owner, etc. reflect the information stored in Nova, Neutron,<br>> | > | | > etc.<br>> | > | | > Rajdeep is making progress on that (he's got some code up on review<br>> | > | | > that<br>> | > | | > we're iterating on), and Peter had worked on integrating AD a while<br>> | > | | > back.<br>> | > | | > <br>> | > | | > Typically I've seen the Python functions (which I usually call<br>> | > | | > 'builtins')<br>> | > | | > integrated into a Datalog system have explicit declarations (e.g.<br>> | > | | > inputs,<br>> | > | | > outputs, etc.).  This is good if we need to do deeper analysis of the<br>> | > | | > policy (which is one of the reasons to use a policy language) and<br>> | > | | > typically requires information about how that builtin works.<br>> | > | | > <br>> | > | | > I dug through some old (Lisp) code to see how I've done this in the<br>> | > | | > past.<br>> | > | | > <br>> | > | | > // (defbuiltin <datalog-name> <lisp-function> <list of types of args><br>> | > | | > <list<br>> | > | | > of types of returns> [<internal>])<br>> | > | | > (defbuiltin plus + (integer integer) integer)<br>> | > | | > (defbuiltin minus - (integer integer) integer)<br>> | > | | > (defbuiltin times * (integer integer) integer)<br>> | > | | > (defbuiltin div (lambda (x y) (floor (/ x y))) (integer integer)<br>> | > | | > integer)<br>> | > | | > (defbuiltin lt numlessp (integer integer) nil)<br>> | > | | > (defbuiltin lte numleqp (integer integer) nil)<br>> | > | | > (defbuiltin gte numgeqp (integer integer) nil)<br>> | > | | > (defbuiltin gt numgreaterp (integer integer) nil)<br>> | > | | > <br>> | > | | > But maybe you're right in that we could do away with these explicit<br>> | > | | > declarations and just assume that everything that (i) is calleable,<br>> | > | | > (ii)<br>> | > | | > not managed by the Data Integration component, and (iii) does not<br>> | > | | > appear<br>> | > | | > in the head of a rule is a builtin.  My only worry is that I could<br>> | > | | > imagine<br>> | > | | > silent and weird problems showing up, e.g. someone forgot to define a<br>> | > | | > table with rules and there happens to be a function in Python by that<br>> | > | | > name.  Or someone supplies the wrong number of arguments, and we just<br>> | > | | > get<br>> | > | | > an error from Python, which we'd have no direct way to communicate to<br>> | > | | > the<br>> | > | | > policy-writer, i.e. there's no compile-time argument-length checking.<br>> | > | | > <br>> | > | | > The other thing I've seen done is to have a single builtin 'evaluate'<br>> | > | | > that<br>> | > | | > lets us call an arbitrary Python function, e.g.<br>> | > | | > <br>> | > | | > p(x, y) :- q(x), evaluate(mypyfunc(x), y)<br>> | > | | > <br>> | > | | > Then we wouldn't need to declare the functions.  Errors would still<br>> | > | | > be<br>> | > | | > silent.  But it would be clear whether we were using a Python<br>> | > | | > function or<br>> | > | | > not.<br>> | > | | > <br>> | > | | > Thoughts?<br>> | > | | > Tim<br>> | > | | > <br>> | > | | > <br>> | > | | > <br>> | > | | > <br>> | > | | > ----- Original Message -----<br>> | > | | > | From: "prabhakar Kudva" <nandavarpk@hotmail.com><br>> | > | | > | To: "OpenStack Development Mailing List (not for usage questions)"<br>> | > | | > | <openstack-dev@lists.openstack.org><br>> | > | | > | Sent: Saturday, March 15, 2014 8:28:27 PM<br>> | > | | > | Subject: Re: [openstack-dev] [Congress] Policy types<br>> | > | | > | <br>> | > | | > | <br>> | > | | > | <br>> | > | | > | Hi Tim,<br>> | > | | > | <br>> | > | | > | Here is a small change I wanted to try in runtime.py<br>> | > | | > | It may already exist in MaterializedViewTheory, but wasn't clear to<br>> | > | | > | me.<br>> | > | | > | Checking to see if this is something that:1. makes sense 2. already<br>> | > | | > | exists<br>> | > | | > | 3. worth implementing? in that order.<br>> | > | | > | <br>> | > | | > | Let's take the example from private_public_network.classify<br>> | > | | > | <br>> | > | | > | error(vm) :- nova:virtual_machine(vm), nova:network(vm, network),<br>> | > | | > | not neutron:public_network(network),<br>> | > | | > | neutron:owner(network, netowner), nova:owner(vm, vmowner), not<br>> | > | | > | same_group(netowner, vmowner)<br>> | > | | > | <br>> | > | | > | same_group(user1, user2) :- cms:group(user1, group),<br>> | > | | > | cms:group(user2,<br>> | > | | > | group)<br>> | > | | > | <br>> | > | | > | nova:virtual_machine("vm1")<br>> | > | | > | nova:virtual_machine("vm2")<br>> | > | | > | nova:virtual_machine("vm3")<br>> | > | | > | nova:network("vm1", "net_private")<br>> | > | | > | nova:network("vm2", "net_public")<br>> | > | | > | neutron:public_network("net_public")<br>> | > | | > | nova:owner("vm1", "tim")<br>> | > | | > | nova:owner("vm2", "pete")<br>> | > | | > | nova:owner("vm3", "pierre")<br>> | > | | > | neutron:owner("net_private", "martin")<br>> | > | | > | <br>> | > | | > | <br>> | > | | > | In this example, if as in Scenario 1:<br>> | > | | > | <br>> | > | | > | Cloud services at our disposal:<br>> | > | | > | nova:virtual_machine(vm)<br>> | > | | > | nova:network(vm, network)<br>> | > | | > | nova:owner(vm, owner)<br>> | > | | > | neutron:public_network(network)<br>> | > | | > | neutron:owner(network, owner)<br>> | > | | > | cms:group(user, group)<br>> | > | | > | <br>> | > | | > | are all python functions called through some nova/neutron api,<br>> | > | | > | then, we just execute them to get a true/false value in runtime.py<br>> | > | | > | They should be first checked to make sure they are python functions<br>> | > | | > | and<br>> | > | | > | not condition primitives using 'callable' and os.dir or some such<br>> | > | | > | combination.<br>> | > | | > | <br>> | > | | > | If not, and they are assertions made in the file, not directly<br>> | > | | > | related to OS<br>> | > | | > | state, then in Scenario 2<br>> | > | | > | <br>> | > | | > | nova:owner("vm1", "tim")<br>> | > | | > | nova:owner("vm2", "pete")<br>> | > | | > | nova:owner("vm3", "pierre")<br>> | > | | > | <br>> | > | | > | Are assertions made in the file. In a dynamic environment,<br>> | > | | > | a python function could query an OS client to actually find the<br>> | > | | > | current owner,<br>> | > | | > | since some other OS command could have been used to change the<br>> | > | | > | owner<br>> | > | | > | without an entry being made in this file, i.e., without explicitly<br>> | > | | > | informing Congres.<br>> | > | | > | This may not occur currently with vms, but may be implemented<br>> | > | | > | in a future release. Similar other examples are possible<br>> | > | | > | https://urldefense.proofpoint.com/v1/url?u=https://ask.openstack.org/en/question/5582/how-to-change-ownership-between-tenants-of-volume/&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=d%2Bh3pVuaRTb%2BTqwqUiF3b5p6jMziF19D3RFSqwM9hKw%3D%0A&s=6da252434cf8f03e99ab04dcc042d3eb646b7c4ea0390b9d0b96f04534d05574<br>> | > | | > | https://urldefense.proofpoint.com/v1/url?u=https://blueprints.launchpad.net/cinder/%2Bspec/volume-transfer&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=d%2Bh3pVuaRTb%2BTqwqUiF3b5p6jMziF19D3RFSqwM9hKw%3D%0A&s=dd07239a911392850af6d2ea72ecce3ea39997c1c93c7f235868a4919144296e<br>> | > | | > | <br>> | > | | > | <br>> | > | | > | So, I was thinking that python_nova_owner("vm1"), is first checked<br>> | > | | > | as<br>> | > | | > | a python<br>> | > | | > | function which calls the appropriate OS client to check the current<br>> | > | | > | owner.<br>> | > | | > | As in nova:owner("vm1", python_nova_owner("vm1"))<br>> | > | | > | <br>> | > | | > | So, in runtime.py, in either scenario, condition primitives are<br>> | > | | > | first<br>> | > | | > | checked to<br>> | > | | > | see if it they are callable<br>> | > | | > | python functions (by using python 'callable' with os.dir). In which<br>> | > | | > | case, it is<br>> | > | | > | executed to get the name of the owner. All non-callable primitives<br>> | > | | > | are assumed<br>> | > | | > | assumed to be congress and/or datalog primitives, and unified<br>> | > | | > | through<br>> | > | | > | the<br>> | > | | > | Materializedviewtheory.<br>> | > | | > | <br>> | > | | > | <br>> | > | | > | Thanks,<br>> | > | | > | <br>> | > | | > | <br>> | > | | > | > Date: Thu, 13 Mar 2014 08:55:24 -0700<br>> | > | | > | > From: thinrichs@vmware.com<br>> | > | | > | > To: openstack-dev@lists.openstack.org<br>> | > | | > | > Subject: Re: [openstack-dev] [Congress] Policy types<br>> | > | | > | > <br>> | > | | > | > Hi Prabhakar,<br>> | > | | > | > <br>> | > | | > | > I'm not sure the functionality is split between 'policy' and<br>> | > | | > | > 'server' as cleanly as you describe.<br>> | > | | > | > <br>> | > | | > | > The 'policy' directory contains the Policy Engine. At its core,<br>> | > | | > | > the<br>> | > | | > | > policy engine has a generic Datalog implementation that could<br>> | > | | > | > feasibly be used by other OS components. (I don't want to think<br>> | > | | > | > about pulling it out into Oslo though. There are just too many<br>> | > | | > | > other things going on and no demand yet.) But there are also<br>> | > | | > | > Congress-specific things in that directory, e.g. the class<br>> | > | | > | > Runtime<br>> | > | | > | > in policy/runtime.py will be the one that we hook up external API<br>> | > | | > | > calls to.<br>> | > | | > | > <br>> | > | | > | > The 'server' directory contains the code for the API web server<br>> | > | | > | > that calls into the Runtime class.<br>> | > | | > | > <br>> | > | | > | > So if you're digging through code, I'd suggest focusing on the<br>> | > | | > | > 'policy' directory and looking at compile.py (responsible for<br>> | > | | > | > converting Datalog rules written as strings into an internal<br>> | > | | > | > representation) and runtime.py (responsible for everything else).<br>> | > | | > | > The docs I mentioned in the IRC should have a decent explanation<br>> | > | | > | > of the functions in Runtime that the API web server will hook<br>> | > | | > | > into.<br>> | > | | > | > <br>> | > | | > | > Be warned though that unless someone raises some serious<br>> | > | | > | > objections<br>> | > | | > | > to the proposal that started this thread, we'll be removing some<br>> | > | | > | > of the more complicated functions from Runtime. The compile.py<br>> | > | | > | > code won't change (much). All of the 3 new theories will be<br>> | > | | > | > instances of MaterializedViewTheory. That's also the code that<br>> | > | | > | > must change to add in the Python functions we talked about (more<br>> | > | | > | > specifically see MaterializedViewTheory::propagate_rule(), which<br>> | > | | > | > calls TopDownTheory::top_down_evaluation(), which is what will<br>> | > | | > | > need modification).<br>> | > | | > | > <br>> | > | | > | > Tim<br>> | > | | > | > <br>> | > | | > | > <br>> | > | | > | > <br>> | > | | > | > <br>> | > | | > | > ----- Original Message -----<br>> | > | | > | > | From: "prabhakar Kudva" <nandavarpk@hotmail.com><br>> | > | | > | > | To: "OpenStack Development Mailing List (not for usage<br>> | > | | > | > | questions)" <openstack-dev@lists.openstack.org><br>> | > | | > | > | Sent: Wednesday, March 12, 2014 1:38:55 PM<br>> | > | | > | > | Subject: Re: [openstack-dev] [Congress] Policy types<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | Hi Tim,<br>> | > | | > | > | <br>> | > | | > | > | Thanks for your comments.<br>> | > | | > | > | Would be happy to contribute to the propsal and code.<br>> | > | | > | > | <br>> | > | | > | > | The existing code already reflects the thoughts below, and got<br>> | > | | > | > | me<br>> | > | | > | > | in the line of ideas. Please orrect me if I am wrong as I am<br>> | > | | > | > | learning with these discussions:<br>> | > | | > | > | <br>> | > | | > | > | One part (reflected by code in "policy" directory is the<br>> | > | | > | > | generic<br>> | > | | > | > | "condition-> action engine" which could take logic primitives<br>> | > | | > | > | and<br>> | > | | > | > | (in the future) python functions, evaluate the conditions and<br>> | > | | > | > | execute the action. This portable core engine be used for any<br>> | > | | > | > | kind of<br>> | > | | > | > | policy enforcement<br>> | > | | > | > | (as by other OS projects), such as for data center monitoring<br>> | > | | > | > | and<br>> | > | | > | > | repair,<br>> | > | | > | > | service level enforcement, compliance policies, optimization<br>> | > | | > | > | (energy,<br>> | > | | > | > | performance) etc... at any level of the stack. This core engine<br>> | > | | > | > | seems<br>> | > | | > | > | possibly<br>> | > | | > | > | a combination of logic reasoning/unification and python<br>> | > | | > | > | function<br>> | > | | > | > | evaluation, and python code actions.<br>> | > | | > | > | <br>> | > | | > | > | Second part (reflected by code in "server") are the<br>> | > | | > | > | applications<br>> | > | | > | > | for various purposes. These could be project specific, task<br>> | > | | > | > | specific.<br>> | > | | > | > | We could add a diverse set of examples. The example I have<br>> | > | | > | > | worked<br>> | > | | > | > | with seems closer to compliance (as in net owner, vm owner<br>> | > | | > | > | check),<br>> | > | | > | > | and we will add more.<br>> | > | | > | > | <br>> | > | | > | > | Prabhakar<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | Date: Wed, 12 Mar 2014 12:33:35 -0700<br>> | > | | > | > | From: thinrichs@vmware.com<br>> | > | | > | > | To: openstack-dev@lists.openstack.org<br>> | > | | > | > | Subject: Re: [openstack-dev] [Congress] Policy types<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | Hi Prabhakar,<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | Thanks for the feedback. I'd be interested to hear what other<br>> | > | | > | > | policy<br>> | > | | > | > | types you have in mind.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | To answer your questions...<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | We're planning on extending our policy language in such a way<br>> | > | | > | > | that<br>> | > | | > | > | you can use Python functions as conditions ("<atom>" in the<br>> | > | | > | > | grammar)<br>> | > | | > | > | in rules. That's on my todo-list but didn't mention it<br>> | > | | > | > | yesterday<br>> | > | | > | > | as<br>> | > | | > | > | we were short on time. There will be some syntactic<br>> | > | | > | > | restrictions<br>> | > | | > | > | so<br>> | > | | > | > | that we can properly execute those Python functions (i.e. we<br>> | > | | > | > | need<br>> | > | | > | > | to<br>> | > | | > | > | always be able to compute the inputs to the function). I had<br>> | > | | > | > | thought<br>> | > | | > | > | it was just an implementation detail I hadn't gotten around to<br>> | > | | > | > | (all<br>> | > | | > | > | Datalog implementations I've seen have such things), but it<br>> | > | | > | > | sounds<br>> | > | | > | > | like it's worth writing up a proposal and sending it around<br>> | > | | > | > | before<br>> | > | | > | > | implementing. If that's a pressing concern for you, let me know<br>> | > | | > | > | and<br>> | > | | > | > | I'll bump it up the stack (a little). If you'd like, feel free<br>> | > | | > | > | to<br>> | > | | > | > | draft a proposal (or remind me to do it once in a while).<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | As for actions, I typically think of them as API calls to other<br>> | > | | > | > | OS<br>> | > | | > | > | components like Nova. But they could just as easily be Python<br>> | > | | > | > | functions. But I would want to avoid an action that changes<br>> | > | | > | > | Congress's internal data structures directly (e.g. adding a new<br>> | > | | > | > | policy statement). Such actions have caused trouble in the past<br>> | > | | > | > | for<br>> | > | | > | > | policy languages (though for declarative programming languages<br>> | > | | > | > | like<br>> | > | | > | > | Prolog they are less problematic). I don't think there's anyway<br>> | > | | > | > | we<br>> | > | | > | > | can stop people from creating such actions, but I think we<br>> | > | | > | > | should<br>> | > | | > | > | advocate against them.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | Tim<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | From: "prabhakar Kudva" <nandavarpk@hotmail.com><br>> | > | | > | > | To: "OpenStack Development Mailing List (not for usage<br>> | > | | > | > | questions)"<br>> | > | | > | > | <openstack-dev@lists.openstack.org><br>> | > | | > | > | Sent: Wednesday, March 12, 2014 11:34:04 AM<br>> | > | | > | > | Subject: Re: [openstack-dev] [Congress] Policy types<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | Hi Tim, All,<br>> | > | | > | > | <br>> | > | | > | > | I was in the discussion yesterday (kudva), and would like to<br>> | > | | > | > | start<br>> | > | | > | > | gradually<br>> | > | | > | > | contributing to the code base.<br>> | > | | > | > | <br>> | > | | > | > | So, this discussion below is based on my limited exploration of<br>> | > | | > | > | Congress<br>> | > | | > | > | code, running it. I am trying some small pieces to implement to<br>> | > | | > | > | familiarize.<br>> | > | | > | > | Please view it as such. As I start adding code, I am sure, my<br>> | > | | > | > | thoughts will<br>> | > | | > | > | be more evolved.<br>> | > | | > | > | <br>> | > | | > | > | I agree with the three types you outline. I also agree that<br>> | > | | > | > | these<br>> | > | | > | > | will grow.<br>> | > | | > | > | We are already thinking of expanding congress for various other<br>> | > | | > | > | types<br>> | > | | > | > | of<br>> | > | | > | > | policies. But those would be a manageable start.<br>> | > | | > | > | <br>> | > | | > | > | Regarding the comment below. I was wondering if all conditions,<br>> | > | | > | > | and<br>> | > | | > | > | actions<br>> | > | | > | > | could be both:<br>> | > | | > | > | 1. python functions (for conditions they eval<br>> | > | | > | > | 2. policy primitives.<br>> | > | | > | > | <br>> | > | | > | > | The advantage of 1, is that it is just executed and a True or<br>> | > | | > | > | False<br>> | > | | > | > | returned<br>> | > | | > | > | by Python for conditions. For actions, python functions are<br>> | > | | > | > | executed<br>> | > | | > | > | to respond to conditions.<br>> | > | | > | > | This controls the growth of policies and adding more<br>> | > | | > | > | primitives,<br>> | > | | > | > | and<br>> | > | | > | > | makes it flexible (say<br>> | > | | > | > | to use alarms, monitors, os clients, nova actions etc).<br>> | > | | > | > | <br>> | > | | > | > | The advantage of 2, is the ability to use unification (as in<br>> | > | | > | > | unify.py) and do<br>> | > | | > | > | some logic reduction. This gives us the full strength of<br>> | > | | > | > | extensive<br>> | > | | > | > | and mature<br>> | > | | > | > | logic reasoning and reduction methods.<br>> | > | | > | > | <br>> | > | | > | > | One possibility is that it checks which one the two it is and<br>> | > | | > | > | does<br>> | > | | > | > | the appropriate<br>> | > | | > | > | evaluation for condition and action.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | >There are drawbacks to this proposal as well.<br>> | > | | > | > | >- We will have 3 separate policies that are conceptually very<br>> | > | | > | > | >similar. As the policies grow larger, it will become<br>> | > | | > | > | >>increasingly<br>> | > | | > | > | >difficult to keep the policies synchronized. This problem can<br>> | > | | > | > | >be<br>> | > | | > | > | >mitigated to some extent by having >all 3 share a library of<br>> | > | | > | > | >policy<br>> | > | | > | > | >statements that they all apply in different ways (and such a<br>> | > | | > | > | >library mechanism is >already implemented).<br>> | > | | > | > | >- As cloud services change their behavior, policies may need<br>> | > | | > | > | >to<br>> | > | | > | > | >be<br>> | > | | > | > | >re-written. For example, right now Nova does >not consult<br>> | > | | > | > | >Congress<br>> | > | | > | > | >before creating a VM; thus, to enforce policy surrounding VMs,<br>> | > | | > | > | >the<br>> | > | | > | > | >best we could do is >write a Condition-Action policy that<br>> | > | | > | > | >adjusts<br>> | > | | > | > | >VM configuration when it learns about new VMs being created.<br>> | > | | > | > | >If<br>> | > | | > | > | >we<br>> | > | | > | > | >>later make Nova consult with Congress before creating a VM,<br>> | > | | > | > | >>we<br>> | > | | > | > | >need to write an Access-control policy that puts >the proper<br>> | > | | > | > | >controls in place.<br>> | > | | > | > | Thanks,<br>> | > | | > | > | <br>> | > | | > | > | Prabhakar Kudva<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | Date: Wed, 12 Mar 2014 10:05:23 -0700<br>> | > | | > | > | From: thinrichs@vmware.com<br>> | > | | > | > | To: openstack-dev@lists.openstack.org<br>> | > | | > | > | Subject: [openstack-dev] [Congress] Policy types<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | Hi all,<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | We started a discussion on IRC yesterday that I'd like to<br>> | > | | > | > | continue.<br>> | > | | > | > | The main question is what kind of policy does a Congress user<br>> | > | | > | > | actually write? I can see three options. The first two focus on<br>> | > | | > | > | actions (API calls that make changes to the state of the cloud)<br>> | > | | > | > | and<br>> | > | | > | > | the last focuses on just the cloud state. (By "state of the<br>> | > | | > | > | cloud" I<br>> | > | | > | > | mean all the information Congress can see about all the cloud<br>> | > | | > | > | services it is managing, e.g. all the information we can get<br>> | > | | > | > | through<br>> | > | | > | > | API calls to Nova, Neutron, Cinder, Heat, ...).<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | 1) Access Control (e.g. Linux, XACML, AD): which *actions* can<br>> | > | | > | > | be<br>> | > | | > | > | performed by other cloud services (for each state of the cloud)<br>> | > | | > | > | 2) Condition Action: which *actions* Congress should execute<br>> | > | | > | > | (for<br>> | > | | > | > | each state of the cloud)<br>> | > | | > | > | 3) Classification (currently supported in Congress): which<br>> | > | | > | > | *states*<br>> | > | | > | > | violate real-world policy. [For those of you who have read<br>> | > | | > | > | docs/white-papers/etc. I'm using "Classification" in this note<br>> | > | | > | > | to<br>> | > | | > | > | mean the combination of the current "Classification" and<br>> | > | | > | > | "Action<br>> | > | | > | > | Description" policies.]<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | The important observation is that each of these policies could<br>> | > | | > | > | contain different information from each of the others.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | - Access Control vs Condition Action. The Access Control policy<br>> | > | | > | > | tells<br>> | > | | > | > | *other cloud services* which actions they are *allowed* to<br>> | > | | > | > | execute.<br>> | > | | > | > | The Condition Action policy tells *Congress* which actions it<br>> | > | | > | > | *must*<br>> | > | | > | > | execute. These policies differ because they constrain different<br>> | > | | > | > | sets<br>> | > | | > | > | of cloud services.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | - Access Control vs. Classification. The Access Control policy<br>> | > | | > | > | might<br>> | > | | > | > | permit some users to violate the Classification policy in some<br>> | > | | > | > | situations (e.g. to fix violation A, we might need to cause<br>> | > | | > | > | violation B before eliminating both). These policies differ<br>> | > | | > | > | because<br>> | > | | > | > | a violation in one policy might be be a violation in the other.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | - Classification vs. Condition Action. The Classification<br>> | > | | > | > | policy<br>> | > | | > | > | might imply which actions *could* eliminate a given violation,<br>> | > | | > | > | but<br>> | > | | > | > | the Condition Action policy would dictate which of those<br>> | > | | > | > | actions<br>> | > | | > | > | *should* be executed (e.g. the Classification policy might tell<br>> | > | | > | > | us<br>> | > | | > | > | that disconnecting a network and deleting a VM would both<br>> | > | | > | > | eliminate<br>> | > | | > | > | a particular violation, but the Condition Action policy would<br>> | > | | > | > | tell<br>> | > | | > | > | us which to choose). And the Condition Action policy need not<br>> | > | | > | > | eliminate all the violations present in the Classification<br>> | > | | > | > | policy.<br>> | > | | > | > | Again these policies differ because a violation in one policy<br>> | > | | > | > | might<br>> | > | | > | > | not be a violation in the other.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | I'm proposing that for the first release of Congress we support<br>> | > | | > | > | all 3<br>> | > | | > | > | of these policies. When a user inserts/deletes a policy<br>> | > | | > | > | statement,<br>> | > | | > | > | she chooses which policy it belongs to. All would be written in<br>> | > | | > | > | basically the same syntax but would be used in 3 different<br>> | > | | > | > | scenarios:<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | - Prevention: If a component wants to consult Congress before<br>> | > | | > | > | taking<br>> | > | | > | > | action to see if that action is allowed, Congress checks the<br>> | > | | > | > | Access<br>> | > | | > | > | Control policy.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | - Reaction: When Congress learns of a change in the cloud's<br>> | > | | > | > | state, it<br>> | > | | > | > | checks the Condition Action policy to see which actions should<br>> | > | | > | > | be<br>> | > | | > | > | executed (if any).<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | - Monitoring: If a user wants to simply check if the cloud's<br>> | > | | > | > | state is<br>> | > | | > | > | in compliance and monitor compliance over time, she writes and<br>> | > | | > | > | queries the Classification policy.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | There are several benefits to this proposal.<br>> | > | | > | > | - It allows users to choose any of the policy types, if they<br>> | > | | > | > | only<br>> | > | | > | > | want one of them. From our discussions with potential users,<br>> | > | | > | > | most<br>> | > | | > | > | seem to want one of these 3 policy types (and are uninterested<br>> | > | | > | > | in<br>> | > | | > | > | the others).<br>> | > | | > | > | - It makes the introduction to Congress relatively simple. We<br>> | > | | > | > | describe 3 different uses of policy (Prevention, Reaction,<br>> | > | | > | > | Monitoring) and then explain which policy to use in which case.<br>> | > | | > | > | <br>> | > | | > | > | - This allows us to focus on implementing a single<br>> | > | | > | > | policy-engine<br>> | > | | > | > | technology (a Datalog policy language and evaluation<br>> | > | | > | > | algorithms),<br>> | > | | > | > | which gives us the opportunity to make it solid.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | There are drawbacks to this proposal as well.<br>> | > | | > | > | - We will have 3 separate policies that are conceptually very<br>> | > | | > | > | similar. As the policies grow larger, it will become<br>> | > | | > | > | increasingly<br>> | > | | > | > | difficult to keep the policies synchronized. This problem can<br>> | > | | > | > | be<br>> | > | | > | > | mitigated to some extent by having all 3 share a library of<br>> | > | | > | > | policy<br>> | > | | > | > | statements that they all apply in different ways (and such a<br>> | > | | > | > | library<br>> | > | | > | > | mechanism is already implemented).<br>> | > | | > | > | - As cloud services change their behavior, policies may need to<br>> | > | | > | > | be<br>> | > | | > | > | re-written. For example, right now Nova does not consult<br>> | > | | > | > | Congress<br>> | > | | > | > | before creating a VM; thus, to enforce policy surrounding VMs,<br>> | > | | > | > | the<br>> | > | | > | > | best we could do is write a Condition-Action policy that<br>> | > | | > | > | adjusts<br>> | > | | > | > | VM<br>> | > | | > | > | configuration when it learns about new VMs being created. If we<br>> | > | | > | > | later make Nova consult with Congress before creating a VM, we<br>> | > | | > | > | need<br>> | > | | > | > | to write an Access-control policy that puts the proper controls<br>> | > | | > | > | in<br>> | > | | > | > | place.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | These drawbacks were the original motivation for supporting<br>> | > | | > | > | only<br>> | > | | > | > | the<br>> | > | | > | > | Classification policy and attempting to derive the Access<br>> | > | | > | > | Control<br>> | > | | > | > | and Condition Action policies from it. But given that we can't<br>> | > | | > | > | always derive the proper Access Control and Condition Action<br>> | > | | > | > | policies from the Classification policy, we will eventually<br>> | > | | > | > | need<br>> | > | | > | > | support for all 3. In addition, the technical complexity of<br>> | > | | > | > | supporting all 3 is much lower than supporting just the<br>> | > | | > | > | Classification policy and deriving the others.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | I'll stop there for now.<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | Comments, thoughts, questions?<br>> | > | | > | > | Tim<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | _______________________________________________ OpenStack-dev<br>> | > | | > | > | mailing<br>> | > | | > | > | list OpenStack-dev@lists.openstack.org<br>> | > | | > | > | https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=d%2Bh3pVuaRTb%2BTqwqUiF3b5p6jMziF19D3RFSqwM9hKw%3D%0A&s=7d10f41d7960d2203631d1d1f67e80dcd6c1a0f845607674d244601a0b251883<br>> | > | | > | > | _______________________________________________<br>> | > | | > | > | OpenStack-dev mailing list<br>> | > | | > | > | OpenStack-dev@lists.openstack.org<br>> | > | | > | > | https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=4QiYdqIhBIaa%2FY1uu8c2Wq%2F92NWfXkaUvJLsncl4ccI%3D%0A&s=a18a843e031ec87277e04caa8396b5cf71bc7a2e5252247084abacf0b9e51409<br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | <br>> | > | | > | > | _______________________________________________ OpenStack-dev<br>> | > | | > | > | mailing<br>> | > | | > | > | list OpenStack-dev@lists.openstack.org<br>> | > | | > | > | https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=d%2Bh3pVuaRTb%2BTqwqUiF3b5p6jMziF19D3RFSqwM9hKw%3D%0A&s=7d10f41d7960d2203631d1d1f67e80dcd6c1a0f845607674d244601a0b251883<br>> | > | | > | > | _______________________________________________<br>> | > | | > | > | OpenStack-dev mailing list<br>> | > | | > | > | OpenStack-dev@lists.openstack.org<br>> | > | | > | > | https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=SMheq3u5q7x9wYFjxnNx6C%2F9lZgxydUP452rygu28MY%3D%0A&s=5c1cf9f3a5adc86ce59d2bf582891e0da033394f43a6ffa72127843c8cf78f80<br>> | > | | > | > | <br>> | > | | > | > <br>> | > | | > | > _______________________________________________<br>> | > | | > | > OpenStack-dev mailing list<br>> | > | | > | > OpenStack-dev@lists.openstack.org<br>> | > | | > | > https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=d%2Bh3pVuaRTb%2BTqwqUiF3b5p6jMziF19D3RFSqwM9hKw%3D%0A&s=7d10f41d7960d2203631d1d1f67e80dcd6c1a0f845607674d244601a0b251883<br>> | > | | > | <br>> | > | | > | _______________________________________________<br>> | > | | > | OpenStack-dev mailing list<br>> | > | | > | OpenStack-dev@lists.openstack.org<br>> | > | | > | https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=QvFCD7z%2FP29TE6KUtbaOJzeGxlOtxzdiGCdlm1LkcOY%3D%0A&s=8f7ec7cc8312dd84709bc99d725e9934b5403a43e8f1f2d02c638e504009ea71<br>> | > | | > | <br>> | > | | > <br>> | > | | > _______________________________________________<br>> | > | | > OpenStack-dev mailing list<br>> | > | | > OpenStack-dev@lists.openstack.org<br>> | > | | > https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=d%2Bh3pVuaRTb%2BTqwqUiF3b5p6jMziF19D3RFSqwM9hKw%3D%0A&s=7d10f41d7960d2203631d1d1f67e80dcd6c1a0f845607674d244601a0b251883<br>> | > | |                                        <br>> | > | | _______________________________________________<br>> | > | | OpenStack-dev mailing list<br>> | > | | OpenStack-dev@lists.openstack.org<br>> | > | | https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=d%2Bh3pVuaRTb%2BTqwqUiF3b5p6jMziF19D3RFSqwM9hKw%3D%0A&s=7d10f41d7960d2203631d1d1f67e80dcd6c1a0f845607674d244601a0b251883<br>> | > | |<br>> | > <br>> | > _______________________________________________<br>> | > OpenStack-dev mailing list<br>> | > OpenStack-dev@lists.openstack.org<br>> | > https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=WvQzzQA4hxW34TMc13h1FgKQQSxHsa1RgBpgfI5lO2U%3D%0A&s=c879337f1ccc468fda5b5ff7083a06047d4d202298247be87e4257a84312d77d<br>> |                                       <br>> | _______________________________________________<br>> | OpenStack-dev mailing list<br>> | OpenStack-dev@lists.openstack.org<br>> | https://urldefense.proofpoint.com/v1/url?u=http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=%2FZ35AkRhp2kCW4Q3MPeE%2BxY2bqaf%2FKm29ZfiqAKXxeo%3D%0A&m=WvQzzQA4hxW34TMc13h1FgKQQSxHsa1RgBpgfI5lO2U%3D%0A&s=c879337f1ccc468fda5b5ff7083a06047d4d202298247be87e4257a84312d77d<br>> | <br>> <br>> _______________________________________________<br>> OpenStack-dev mailing list<br>> OpenStack-dev@lists.openstack.org<br>> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev<br></div>                                    </div></body>
</html>