-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathREADME.neutron_integration.txt
218 lines (159 loc) · 7.94 KB
/
README.neutron_integration.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
Introduction
------------
Since Neutron, mostly through its ML2 plugin, can handle a variety of
underlying network topologies, which would be modeled using different
ZenPacks, we provide a generic mechanism for these zenpacks to provide
a mapping between neutron components, like networks and ports, and the related
zenpack components, such as bridge groups and interfaces.
These mappings are many-to-many, to support a variety of implementation
strategies.
Throughout this file, the term "implementation" refers to components modeled
in a different zenpack, and "core" to those neutron components modeled
by OpenStackInfrastructure.
Integration Keys
----------------
The key function of an Neutron Implementation plugin is to provide a mapping
of neutron objects and the underlying "Implementation Components"
(that is, components within other zenpacks that correspond to configuration
that is done by a neutron core or ML2 mechanism driver)
This is accomplished by defining functions that take these components
as input and return opaque "integration key" values, such that when the two
keys match, that neutron component correspond to that implementation
component.
This mapping is many-to-many and can map any neutron component to any
component which implements the INeutronImplementationComponent
interface.
The integration key is a string of any format as long as the same value
can be generated on both sides (neutron and implementation) and is
appropriately unique to identify a specific component.
Plain text is generally preferred over a MD5 sum or other opaque value,
simply for ease of debugging, but any value is acceptable.
NOTE: Integration keys must always be prefixed with the plugin name,
followed by a ':'. For example:
"ml2.myswitch:10.0.0.1|network|mynetwork-e63ab524-736f-4dd9-a712-97228862d0ea"
Neutron Implementation Plugin
-----------------------------
You must also supply a neutron implementation adapter, for example, in a file called openstack_neutron.py, in your zenpack:
from zope.interface import implements
from zope.event import notify
from Products.Zuul.catalog.events import IndexingEvent
from Products.Zuul.interfaces import ICatalogTool
from ZenPacks.zenoss.OpenStackInfrastructure.interfaces import INeutronImplementationPlugin
from ZenPacks.zenoss.OpenStackInfrastructure.neutron_integration import BaseNeutronImplementationPlugin, split_list
class MySwitchNeutronImplementationPlugin(BaseNeutronImplementationPlugin):
implements(INeutronImplementationPlugin)
@classmethod
def ini_required(cls):
return [('plugins/ml2/ml2_conf.ini', 'ml2_myswitch', 'management_server_ips')]
@classmethod
def ini_process(cls, filename, section_name, option_name, value):
# The management server IPs are specified as a comma-separated list.
# we transform this to an actual list so that we can refer to it that
# way elsewhere.
if option_name == 'management_server_ips':
return split_list(value)
return value
# So in this example, the IP address comes from an INI file, and the "netId"
# on the neutron network is expected to match the "title" on the implementation zenpack's
# Network component
def getNetworkIntegrationKeys(self, network):
ip_addresses = network.device().ini_get(('plugins/ml2/ml2_conf.ini', 'ml2_myswitch', 'management_server_ip'))
keys = []
# in this example, there can be multiple management servers, and the
# same network is expected to appear on any or all of them. So
# we return multiple integration keys, one for each possible
# server:
for ip_address in ip_addresses:
keyvalues = (
ip_address,
'network',
self.netId,
)
keys.append('ml2.myswitch:' + '|'.join(keyvalues))
return keys
@classmethod
def reindex_implementation_components(cls, dmd):
device_class = dmd.Devices.getOrganizer('/Devices/MySwitch')
results = ICatalogTool(device_class).search(
('ZenPacks.zenoss.MySwitch.Network.Network',)
)
for brain in results:
obj = brain.getObject()
obj.index_object()
notify(IndexingEvent(obj))
Make sure OpenStackInfrastructure's meta.zcml has an entry for Neutron integration:
<!-- OpenStack Integration features -->
<provides feature="openstack_neutron_integration" />
Register your plugin in the zenpack's configure.zcml file as follows:
<!-- OpenStack Cinder integration -->
<configure zcml:condition="installed ZenPacks.zenoss.OpenStackInfrastructure.interfaces">
<!-- Guard Against Older OSI that lacks Cinder -->
<configure zcml:condition="have openstack_neutron_integration">
<utility
name="ml2.myswitch"
factory=".openstack_cinder.MySwitchNeutronImplementationPlugin"
provides="ZenPacks.zenoss.OpenStackInfrastructure.interfaces.INeutronImplementationPlugin"
/>
</configure>
</configure>
Note that the name specified must be of one of the two forms:
* neutron core plugin name
* ml2.<neutron ml2 mechanism name>
This same name must also be used as a prefix in all integration keys returned
by the plugin get*IntegrationKeys and component getNeutronIntegrationKeys
methods.
Implementation Components
-------------------------
For components that implement an openstack neutron components:
Each component class to implement INeutronImplementationPlugin when the
OpenStackInfrastructure zenpack is installed:
from zope.interface import implements
try:
from ZenPacks.zenoss.OpenStackInfrastructure.interfaces import INeutronImplementationComponent
from ZenPacks.zenoss.OpenStackInfrastructure.neutron_integration import index_implementation_object, unindex_implementation_object
openstack = True
except ImportError:
openstack = False
class Network(DeviceComponent):
if openstack:
implements(INeutronImplementationComponent)
# The "integration key(s)" for this component must be made up of
# a set of values that uniquely identify this resource and are
# known to both this zenpack and the openstack zenpack. They may
# involve modeled properties, zProperties, and values from the neutron
# configuration files on the openstack host.
def getNeutronIntegrationKeys(self):
keyvalues = (
self.device().zMyNetworkManagerIpAddress,
'network',
self.title
)
return ['ml2.myswitch' + '|'.join(keyvalues)]
def index_object(self, idxs=None):
super(Network, self).index_object(idxs=idxs)
if openstack:
index_implementation_object(self)
def unindex_object(self):
super(Network, self).unindex_object()
if openstack:
unindex_implementation_object(self)
Indexing Concerns
-----------------
The indexes used to map between neutron core and implementation components
are maintained in the usual way, with index_object. However, if the
integration key is derived from values stored elsewhere (so that the key should
change even though the component did not), you must ensure that index_object is
called explicitly.
This is handled for ini values on the core components automatically, but if your
plugin refers to other values which could change and are not either properties
of that component or ini values, you may find that the catalog is not updated
when it should be.
If this is unavoidable, it may be required to modify the OpenStackInfrastructure
zenpack to support your use case.
Impact Support
--------------
The impacts_by relationship from the implementation component to the core
component is provided automatically, but it is your responsibility to
provide the impacts relationship from the other zenpack into openstack.
To do this, your impact adapter should call the function 'get_neutron_components'
from ZenPacks.zenoss.OpenStackInfrastructure.neutron_integration.