~zulcss/ubuntu/precise/quantum/trunk

« back to all changes in this revision

Viewing changes to quantum/plugins/metaplugin/agent/ovs_quantum_agent.py

  • Committer: Chuck Short
  • Date: 2012-11-26 19:51:11 UTC
  • mfrom: (26.1.1 raring-proposed)
  • Revision ID: zulcss@ubuntu.com-20121126195111-jnz2cr4xi6whemw2
* New upstream release for the Ubuntu Cloud Archive.
* debian/patches/*: Refreshed for opening of Grizzly.
* New upstream release.
* debian/rules: FTFBS if there is missing binaries.
* debian/quantum-server.install: Add quantum-debug.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
 
# Copyright 2011 Nicira Networks, Inc.
4
 
# All Rights Reserved.
5
 
#
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
9
 
#
10
 
#         http://www.apache.org/licenses/LICENSE-2.0
11
 
#
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
16
 
#    under the License.
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.
22
 
 
23
 
import logging
24
 
import sys
25
 
import time
26
 
 
27
 
from sqlalchemy.ext import sqlsoup
28
 
 
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
35
 
 
36
 
logging.basicConfig()
37
 
LOG = logging.getLogger(__name__)
38
 
 
39
 
# A placeholder for dead vlans.
40
 
DEAD_VLAN_TAG = "4095"
41
 
 
42
 
 
43
 
class MetaOVSQuantumAgent(OVSQuantumAgent):
44
 
 
45
 
    def daemon_loop(self, db_connection_url):
46
 
        '''Main processing loop for Non-Tunneling Agent.
47
 
 
48
 
        :param options: database information - in the event need to reconnect
49
 
        '''
50
 
        self.local_vlan_map = {}
51
 
        old_local_bindings = {}
52
 
        old_vif_ports = {}
53
 
        db_connected = False
54
 
 
55
 
        while True:
56
 
            if not db_connected:
57
 
                time.sleep(self.reconnect_interval)
58
 
                db = sqlsoup.SqlSoup(db_connection_url)
59
 
                db_connected = True
60
 
                LOG.info("Connecting to database \"%s\" on %s" %
61
 
                         (db.engine.url.database, db.engine.url.host))
62
 
 
63
 
            all_bindings = {}
64
 
            try:
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()
72
 
            except Exception, e:
73
 
                LOG.info("Unable to get port bindings! Exception: %s" % e)
74
 
                db_connected = False
75
 
                continue
76
 
 
77
 
            for port in ports:
78
 
                if self.target_v2_api:
79
 
                    all_bindings[port.id] = port
80
 
                else:
81
 
                    all_bindings[port.interface_id] = port
82
 
 
83
 
            vlan_bindings = {}
84
 
            try:
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()
92
 
            except Exception, e:
93
 
                LOG.info("Unable to get vlan bindings! Exception: %s" % e)
94
 
                db_connected = False
95
 
                continue
96
 
 
97
 
            for bind in vlan_binds:
98
 
                vlan_bindings[bind.network_id] = bind.vlan_id
99
 
 
100
 
            new_vif_ports = {}
101
 
            new_local_bindings = {}
102
 
            vif_ports = self.int_br.get_vif_ports()
103
 
            for p in 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
108
 
                else:
109
 
                    # no binding, put him on the 'dead vlan'
110
 
                    self.int_br.set_db_attribute("Port", p.port_name, "tag",
111
 
                                                 DEAD_VLAN_TAG)
112
 
                    self.int_br.add_flow(priority=2,
113
 
                                         in_port=p.ofport,
114
 
                                         actions="drop")
115
 
 
116
 
                old_b = old_local_bindings.get(p.vif_id, None)
117
 
                new_b = new_local_bindings.get(p.vif_id, None)
118
 
 
119
 
                if old_b != new_b:
120
 
                    if old_b is not None:
121
 
                        LOG.info("Removing binding to net-id = %s for %s"
122
 
                                 % (old_b, str(p)))
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
129
 
                        # the dead vlan
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))
139
 
 
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)
149
 
 
150
 
            old_vif_ports = new_vif_ports
151
 
            old_local_bindings = new_local_bindings
152
 
            try:
153
 
                db.commit()
154
 
            except Exception, e:
155
 
                LOG.info("Unable to commit to database! Exception: %s" % e)
156
 
                db.rollback()
157
 
                old_local_bindings = {}
158
 
                old_vif_ports = {}
159
 
 
160
 
            time.sleep(self.polling_interval)
161
 
 
162
 
 
163
 
def main():
164
 
    cfg.CONF(args=sys.argv, project='quantum')
165
 
 
166
 
    # (TODO) gary - swap with common logging
167
 
    logging_config.setup_logging(cfg.CONF)
168
 
 
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
176
 
 
177
 
    # Determine API Version to use
178
 
    target_v2_api = cfg.CONF.AGENT.target_v2_api
179
 
 
180
 
    # Get parameters for OVSQuantumAgent.
181
 
    plugin = MetaOVSQuantumAgent(integ_br, root_helper, polling_interval,
182
 
                                 reconnect_interval, target_v2_api)
183
 
 
184
 
    # Start everything.
185
 
    plugin.daemon_loop(db_connection_url)
186
 
 
187
 
    sys.exit(0)
188
 
 
189
 
if __name__ == "__main__":
190
 
    main()