Browse Source

decouple neutron db models and ovo for neutron-lib

This spec provides details on how we can break consumer dependencies
on neutron's database model as well as object imports by
exposing neutron objects as entry points that are discoverable and
loadable from neutron-lib. This spec is part of a set of specs related
to decoupling the db for neutron-lib (see patch topic).

Change-Id: I079d06502e6e7b1e20aea882979b0ecd9106eaeb
Boden R 1 year ago
parent
commit
3df6e5c811
1 changed files with 143 additions and 0 deletions
  1. 143
    0
      specs/rocky/neutronlib-decouple-models.rst

+ 143
- 0
specs/rocky/neutronlib-decouple-models.rst View File

@@ -0,0 +1,143 @@
1
+..
2
+ This work is licensed under a Creative Commons Attribution 3.0 Unported
3
+ License.
4
+
5
+ http://creativecommons.org/licenses/by/3.0/legalcode
6
+
7
+==================================================
8
+Decoupling database imports/access for neutron-lib
9
+==================================================
10
+
11
+This work is not related to an enhancement request and therefore doesn't have
12
+a RFE. Rather the intent herein is to discuss how we decouple ``neutron.db``
13
+and related database imports/access as part of the overall neutron-lib effort.
14
+
15
+Current neutron database access can be broken into the following high-level
16
+categories:
17
+
18
+- Database API & Utilities
19
+- Core & Extension Database Mixins
20
+- Database Resource Models
21
+- Database Migration
22
+
23
+As the database access patterns span a wide range of logic/code, a set of specs
24
+will be proposed each focusing on a single access pattern.
25
+
26
+This spec specifically address Database Resource Model access.
27
+
28
+For current neutron-lib related blueprints, see [1]_ and [2]_.
29
+
30
+
31
+Problem Description
32
+===================
33
+
34
+As part of our neutron-lib effort, we need to decouple out-of-tree networking
35
+projects that depend on (e.g. ``import``) neutron. However, today a large
36
+number of neutron consumers import database related neutron modules including
37
+models [3]_ [4]_.
38
+
39
+Access to database models by consumers is typically used for:
40
+
41
+- Defining relationships between neutron and other project models. Note that
42
+  while string names can be used when defining a relationship, this is not
43
+  a viable solution for all cases due to [8]_.
44
+- Building queries using models and/or their fields. With the introduction of
45
+  versioned objects, consumers can effectively query using methods on objects.
46
+  Therefore the deliverables of this spec enable such an approach by making
47
+  versioned objects accessible via neutron-lib.
48
+- Importing models to have them available for database tools. This includes
49
+  database migration tools, so while this spec doesn't directly solve
50
+  the migration access, it needs to lay a foundation for it (covered in a
51
+  separate spec).
52
+
53
+The intent of this spec is to propose how we can provide access to database
54
+models without direct neutron imports by means of a bridge in neutron-lib
55
+thereby breaking consumer's dependencies on neutron's internal database
56
+models.
57
+
58
+Proposed Change
59
+===============
60
+
61
+While one foreseeable solution would be to publish models using
62
+discoverable entry points (stevedore) or register them using a factory,
63
+these models must be versioned to allow consumers to determine compatibility.
64
+Without versioning the underlying model can change without the consumers
65
+knowledge, thereby breaking them.
66
+
67
+Implementing versioned models is simple enough with some new facility, however
68
+we already have such a versioning scheme; neutron versioned objects. Neutron
69
+objects already contain a reference to the underlying model as well as a
70
+version number that's incremented as the model changes [5]_. Therefore if we
71
+can provide a way for consumers to get at neutron objects, they have access to
72
+a version, corresponding model, etc..
73
+
74
+This spec proposes we use a simple entry point scheme whereby all versioned
75
+objects are defined as entry points that can then be looked up and handed
76
+out by some bridging logic in neutron-lib. More specifically:
77
+
78
+- Neutron versioned objects can be "published" via an entry point in
79
+  ``setup.cfg`` where each entry point is a versioned object class. This
80
+  exposes the objects to neutron-lib that can be discovered and loaded with
81
+  ``stevedore``.
82
+- A simple API in neutron-lib allowing consumers to retrieve versioned objects
83
+  at runtime. In it's basic form a consumer asks for an object of type ``X``,
84
+  whereupon neutron-lib looks it up from the entry point and returns the
85
+  concrete object class to the consumer (e.g. ``load_class('Port')`` looks up
86
+  and returns the versioned object class for ``Port``).
87
+- If consumers need to create instances of the versioned object(s) returned
88
+  from neutron-lib, they can invoke it's constructor directly to create a
89
+  new instance. Since versioned object constructor's are based on the object's
90
+  ``fields`` and the ``fields`` are tied to the model, consumers can query
91
+  the object's ``VERSION`` to determine compatibility with the constructor.
92
+
93
+The snippet below illustrates the API from a consumers point of view::
94
+
95
+    from neutron_lib.objects import registry
96
+    # .. other imports
97
+
98
+    # Loading the object from neutron-lib uses stevedore to find the requested
99
+    # object. Also note that under the covers the model is imported since the
100
+    # concrete versioned object must import the model to ref it.
101
+    port_ovo = registry.load_class(constants.PORT)
102
+
103
+    if port_ovo.VERSION > '1.1':
104
+        raise UnsupportedException("Can't use port objects greater than 1.1")
105
+
106
+    # It's just an OVO class, so we can use it's static/class methods directly
107
+    a_port = port_ovo.get_object(...)
108
+
109
+    # Create a new versioned object; it's VERSION determines the constructor's
110
+    # supported kwargs so consumers can detect compatibility
111
+    new_port = port_ovo(context, project_id=...)
112
+
113
+As mentioned earlier, while this solution doesn't completely solve database
114
+migration access, it paves the way as we now have a way to find and load
115
+versioned objects which must import the respective model.
116
+
117
+Using this scheme, we should be able to eliminate consumers imports for:
118
+
119
+- Existing ``neutron.objects`` imports [6]_. Consumers now get their object from
120
+  the neutron-lib API provided herein.
121
+- Building queries; version objects have methods allowing consumers to
122
+  effectively query and there should be no need to build direct queries in
123
+  consumers otherwise.
124
+
125
+In addition, the rollout of this functionality should have minimal impact to
126
+the main code paths; the only real change in neutron is to expose the objects
127
+via ``setup.cfg``. The neutron-lib logic can be implemented, tested and rolled
128
+out independently thereby reducing risk.
129
+
130
+For a sample proof of concept, see the patches on [7]_ that use this approach
131
+to remove/use versioned objects in a few of the vmware-nsx modules.
132
+
133
+References
134
+==========
135
+
136
+.. [1] https://blueprints.launchpad.net/neutron/+spec/neutron-lib-networking-ovn
137
+.. [2] https://blueprints.launchpad.net/neutron/+spec/neutron-lib-dynr
138
+.. [3] http://codesearch.openstack.org/?q=from%20neutron.db.model
139
+.. [4] http://codesearch.openstack.org/?q=from%20neutron.db%20import%20model
140
+.. [5] https://docs.openstack.org/neutron/latest/contributor/internals/objects_usage.html
141
+.. [6] http://codesearch.openstack.org/?q=from%20neutron.objects
142
+.. [7] https://review.openstack.org/#/q/topic:bp/neutronlib-decouple-db
143
+.. [8] https://stackoverflow.com/questions/45534903/python-sqlalchemy-attributeerror-mapper

Loading…
Cancel
Save