Browse Source

Merge "decouple neutron db models and ovo for neutron-lib"

Zuul 1 year ago
parent
commit
9b7cd99a76
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