2
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright 2011 Nicira Networks, Inc.
6
# Licensed under the Apache License, Version 2.0 (the "License"); you may
7
# not use this file except in compliance with the License. You may obtain
8
# a copy of the License at
10
# http://www.apache.org/licenses/LICENSE-2.0
12
# Unless required by applicable law or agreed to in writing, software
13
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
# License for the specific language governing permissions and limitations
17
# @author: Somik Behera, Nicira Networks, Inc.
18
# @author: Brad Hall, Nicira Networks, Inc.
19
# @author: Dan Wendlandt, Nicira Networks, Inc.
20
# @author: Dave Lapsley, Nicira Networks, Inc.
21
# @author: Aaron Rosen, Nicira Networks, Inc.
27
from sqlalchemy.ext import sqlsoup
29
from quantum.agent.linux import ovs_lib
30
from quantum.common import config as logging_config
31
from quantum.common import constants
32
from quantum.openstack.common import cfg
33
from quantum.plugins.openvswitch.common import config
34
from quantum.plugins.openvswitch.agent.ovs_quantum_agent import OVSQuantumAgent
37
LOG = logging.getLogger(__name__)
39
# A placeholder for dead vlans.
40
DEAD_VLAN_TAG = "4095"
43
class MetaOVSQuantumAgent(OVSQuantumAgent):
45
def daemon_loop(self, db_connection_url):
46
'''Main processing loop for Non-Tunneling Agent.
48
:param options: database information - in the event need to reconnect
50
self.local_vlan_map = {}
51
old_local_bindings = {}
57
time.sleep(self.reconnect_interval)
58
db = sqlsoup.SqlSoup(db_connection_url)
60
LOG.info("Connecting to database \"%s\" on %s" %
61
(db.engine.url.database, db.engine.url.host))
65
flavor_key = db.flavors.network_id
66
port_key = db.ports.network_id
67
query = db.session.query(db.ports)
68
joined = query.join((db.flavors,
69
flavor_key == port_key))
70
where = db.flavors.flavor == 'openvswitch'
71
ports = joined.filter(where).all()
73
LOG.info("Unable to get port bindings! Exception: %s" % e)
78
if self.target_v2_api:
79
all_bindings[port.id] = port
81
all_bindings[port.interface_id] = port
85
flavor_key = db.flavors.network_id
86
vlan_key = db.vlan_bindings.network_id
87
query = db.session.query(db.vlan_bindings)
88
joined = query.join((db.flavors,
89
flavor_key == vlan_key))
90
where = db.flavors.flavor == 'openvswitch'
91
vlan_binds = joined.filter(where).all()
93
LOG.info("Unable to get vlan bindings! Exception: %s" % e)
97
for bind in vlan_binds:
98
vlan_bindings[bind.network_id] = bind.vlan_id
101
new_local_bindings = {}
102
vif_ports = self.int_br.get_vif_ports()
104
new_vif_ports[p.vif_id] = p
105
if p.vif_id in all_bindings:
106
net_id = all_bindings[p.vif_id].network_id
107
new_local_bindings[p.vif_id] = net_id
109
# no binding, put him on the 'dead vlan'
110
self.int_br.set_db_attribute("Port", p.port_name, "tag",
112
self.int_br.add_flow(priority=2,
116
old_b = old_local_bindings.get(p.vif_id, None)
117
new_b = new_local_bindings.get(p.vif_id, None)
120
if old_b is not None:
121
LOG.info("Removing binding to net-id = %s for %s"
123
self.port_unbound(p, True)
124
if p.vif_id in all_bindings:
125
all_bindings[p.vif_id].status = (
126
constants.PORT_STATUS_DOWN)
127
if new_b is not None:
128
# If we don't have a binding we have to stick it on
130
net_id = all_bindings[p.vif_id].network_id
131
vlan_id = vlan_bindings.get(net_id, DEAD_VLAN_TAG)
132
self.port_bound(p, vlan_id)
133
if p.vif_id in all_bindings:
134
all_bindings[p.vif_id].status = (
135
constants.PORT_STATUS_ACTIVE)
136
LOG.info(("Adding binding to net-id = %s "
137
"for %s on vlan %s") %
138
(new_b, str(p), vlan_id))
140
for vif_id in old_vif_ports:
141
if vif_id not in new_vif_ports:
142
LOG.info("Port Disappeared: %s" % vif_id)
143
if vif_id in old_local_bindings:
144
old_b = old_local_bindings[vif_id]
145
self.port_unbound(old_vif_ports[vif_id], False)
146
if vif_id in all_bindings:
147
all_bindings[vif_id].status = (
148
constants.PORT_STATUS_DOWN)
150
old_vif_ports = new_vif_ports
151
old_local_bindings = new_local_bindings
155
LOG.info("Unable to commit to database! Exception: %s" % e)
157
old_local_bindings = {}
160
time.sleep(self.polling_interval)
164
cfg.CONF(args=sys.argv, project='quantum')
166
# (TODO) gary - swap with common logging
167
logging_config.setup_logging(cfg.CONF)
169
# Determine which agent type to use.
170
enable_tunneling = cfg.CONF.OVS.enable_tunneling
171
integ_br = cfg.CONF.OVS.integration_bridge
172
db_connection_url = cfg.CONF.DATABASE.sql_connection
173
polling_interval = cfg.CONF.AGENT.polling_interval
174
reconnect_interval = cfg.CONF.DATABASE.reconnect_interval
175
root_helper = cfg.CONF.AGENT.root_helper
177
# Determine API Version to use
178
target_v2_api = cfg.CONF.AGENT.target_v2_api
180
# Get parameters for OVSQuantumAgent.
181
plugin = MetaOVSQuantumAgent(integ_br, root_helper, polling_interval,
182
reconnect_interval, target_v2_api)
185
plugin.daemon_loop(db_connection_url)
189
if __name__ == "__main__":