~zulcss/ubuntu/precise/quantum/trunk

« back to all changes in this revision

Viewing changes to quantum/plugins/ryu/ryu_quantum_plugin.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:
16
16
#    under the License.
17
17
# @author: Isaku Yamahata
18
18
 
19
 
import logging
20
 
 
21
19
from ryu.app import client
 
20
from ryu.app.client import ignore_http_not_found
22
21
from ryu.app import rest_nw_id
 
22
from sqlalchemy.exc import IntegrityError
 
23
from sqlalchemy.orm import exc as orm_exc
23
24
 
 
25
from quantum.common import constants as q_const
24
26
from quantum.common import exceptions as q_exc
25
27
from quantum.common import topics
26
28
from quantum.db import api as db
27
29
from quantum.db import db_base_plugin_v2
 
30
from quantum.db.dhcp_rpc_base import DhcpRpcCallbackMixin
28
31
from quantum.db import l3_db
29
32
from quantum.db import models_v2
30
 
from quantum.db.dhcp_rpc_base import DhcpRpcCallbackMixin
31
33
from quantum.openstack.common import cfg
 
34
from quantum.openstack.common import log as logging
32
35
from quantum.openstack.common import rpc
33
36
from quantum.openstack.common.rpc import dispatcher
34
 
from quantum.plugins.ryu import ofp_service_type
35
37
from quantum.plugins.ryu.common import config
36
38
from quantum.plugins.ryu.db import api_v2 as db_api_v2
 
39
from quantum.plugins.ryu import ofp_service_type
 
40
 
37
41
 
38
42
LOG = logging.getLogger(__name__)
39
43
 
50
54
        options.update({"reconnect_interval": reconnect_interval})
51
55
        db.configure_db(options)
52
56
 
 
57
        self.tunnel_key = db_api_v2.TunnelKey(
 
58
            cfg.CONF.OVS.tunnel_key_min, cfg.CONF.OVS.tunnel_key_max)
53
59
        ofp_con_host = cfg.CONF.OVS.openflow_controller
54
60
        ofp_api_host = cfg.CONF.OVS.openflow_rest_api
55
61
 
56
62
        if ofp_con_host is None or ofp_api_host is None:
57
 
            raise q_exc.Invalid("invalid configuration. check ryu.ini")
 
63
            raise q_exc.Invalid(_('invalid configuration. check ryu.ini'))
58
64
 
59
65
        hosts = [(ofp_con_host, ofp_service_type.CONTROLLER),
60
66
                 (ofp_api_host, ofp_service_type.REST_API)]
61
67
        db_api_v2.set_ofp_servers(hosts)
62
68
 
63
69
        self.client = client.OFPClient(ofp_api_host)
64
 
        self.client.update_network(rest_nw_id.NW_ID_EXTERNAL)
 
70
        self.tun_client = client.TunnelClient(ofp_api_host)
 
71
        for nw_id in rest_nw_id.RESERVED_NETWORK_IDS:
 
72
            if nw_id != rest_nw_id.NW_ID_UNKNOWN:
 
73
                self.client.update_network(nw_id)
65
74
        self._setup_rpc()
66
75
 
67
76
        # register known all network list on startup
75
84
        self.conn.consume_in_thread()
76
85
 
77
86
    def _create_all_tenant_network(self):
78
 
        networks = db_api_v2.network_all_tenant_list()
79
 
        for net in networks:
 
87
        for net in db_api_v2.network_all_tenant_list():
80
88
            self.client.update_network(net.id)
 
89
        for tun in self.tunnel_key.all_list():
 
90
            self.tun_client.update_tunnel_key(tun.network_id, tun.tunnel_key)
 
91
        session = db.get_session()
 
92
        for port_binding in db_api_v2.port_binding_all_list(session):
 
93
            network_id = port_binding.network_id
 
94
            dpid = port_binding.dpid
 
95
            port_no = port_binding.port_no
 
96
            try:
 
97
                port = session.query(models_v2.Port).filter(
 
98
                    models_v2.Port.id == port_binding.port_id).one()
 
99
            except orm_exc.NoResultFound:
 
100
                continue
 
101
            except orm_exc.MultipleResultsFound:
 
102
                continue
 
103
 
 
104
            self.client.update_port(network_id, dpid, port_no)
 
105
            self.client.update_mac(network_id, dpid, port_no, port.mac_address)
 
106
 
 
107
    def _client_create_network(self, net_id, tunnel_key):
 
108
        self.client.create_network(net_id)
 
109
        self.tun_client.create_tunnel_key(net_id, tunnel_key)
 
110
 
 
111
    def _client_delete_network(self, net_id):
 
112
        client.ignore_http_not_found(
 
113
            lambda: self.client.delete_network(net_id))
 
114
        client.ignore_http_not_found(
 
115
            lambda: self.tun_client.delete_tunnel_key(net_id))
81
116
 
82
117
    def create_network(self, context, network):
83
118
        session = context.session
84
119
        with session.begin(subtransactions=True):
85
120
            net = super(RyuQuantumPluginV2, self).create_network(context,
86
121
                                                                 network)
87
 
            self.client.create_network(net['id'])
88
122
            self._process_l3_create(context, network['network'], net['id'])
89
123
            self._extend_network_dict_l3(context, net)
 
124
 
 
125
            tunnel_key = self.tunnel_key.allocate(session, net['id'])
 
126
            try:
 
127
                self._client_create_network(net['id'], tunnel_key)
 
128
            except:
 
129
                self._client_delete_network(net['id'])
 
130
                raise
 
131
 
90
132
        return net
91
133
 
92
134
    def update_network(self, context, id, network):
99
141
        return net
100
142
 
101
143
    def delete_network(self, context, id):
 
144
        self._client_delete_network(id)
102
145
        session = context.session
103
146
        with session.begin(subtransactions=True):
 
147
            self.tunnel_key.delete(session, id)
104
148
            super(RyuQuantumPluginV2, self).delete_network(context, id)
105
 
            self.client.delete_network(id)
106
149
 
107
150
    def get_network(self, context, id, fields=None):
108
151
        net = super(RyuQuantumPluginV2, self).get_network(context, id, None)
119
162
        return [self._fields(net, fields) for net in nets]
120
163
 
121
164
    def delete_port(self, context, id, l3_port_check=True):
 
165
        with context.session.begin(subtransactions=True):
 
166
            port = self._get_port(context, id)
 
167
            net_id = port.network_id
 
168
            try:
 
169
                port_binding = db_api_v2.port_binding_destroy(context.session,
 
170
                                                              port.id, net_id)
 
171
                datapath_id = port_binding.dpid
 
172
                port_no = port_binding.port_no
 
173
                ignore_http_not_found(
 
174
                    lambda: self.client.delete_port(net_id, datapath_id,
 
175
                                                    port_no))
 
176
            except q_exc.PortNotFound:
 
177
                pass
 
178
 
122
179
        # if needed, check to see if this is a port owned by
123
180
        # and l3-router. If so, we should prevent deletion.
124
181
        if l3_port_check:
125
182
            self.prevent_l3_port_deletion(context, id)
126
183
        self.disassociate_floatingips(context, id)
127
184
        return super(RyuQuantumPluginV2, self).delete_port(context, id)
 
185
 
 
186
    def update_port(self, context, id, port):
 
187
        p = super(RyuQuantumPluginV2, self).update_port(context, id, port)
 
188
        net_id = p['network_id']
 
189
        mac_address = p['mac_address']
 
190
 
 
191
        deleted = port['port'].get('deleted', False)
 
192
        if deleted:
 
193
            session = context.session
 
194
            try:
 
195
                db_api_v2.port_binding_destroy(session, id, net_id)
 
196
            except q_exc.PortNotFound:
 
197
                pass
 
198
            db_api_v2.set_port_status(session, id, q_const.PORT_STATUS_DOWN)
 
199
            return p
 
200
 
 
201
        datapath_id = port['port'].get('datapath_id', None)
 
202
        port_no = port['port'].get('port_no', None)
 
203
        if datapath_id is None or port_no is None:
 
204
            LOG.debug('p %s', p)
 
205
            return p
 
206
 
 
207
        try:
 
208
            port_binding = db_api_v2.port_binding_get(id, net_id)
 
209
        except orm_exc.NoResultFound:
 
210
            try:
 
211
                db_api_v2.port_binding_create(id, net_id, datapath_id, port_no)
 
212
            except IntegrityError:
 
213
                # TODO:XXX should do transaction?
 
214
                return p
 
215
            else:
 
216
                self.client.create_port(net_id, datapath_id, port_no)
 
217
                self.client.create_mac(net_id, datapath_id, port_no,
 
218
                                       mac_address)
 
219
        else:
 
220
            if (port_binding.dpid != datapath_id or
 
221
                    port_binding.port_no != port_no):
 
222
                variables = {'datapath_id': datapath_id,
 
223
                             'port_no': port_no,
 
224
                             'port_binding_dpid': port_binding.dpid,
 
225
                             'port_binding_port_no': port_binding.port_no}
 
226
                raise q_exc.InvalidInput(
 
227
                    error_message=_('invalid (datapath_id, port_no) '
 
228
                                    'is requested'
 
229
                                    '(%(datapath_id)s, %(port_no)s), acutal'
 
230
                                    '(%(port_binding_dpid)s, '
 
231
                                    '%(port_binding_port_no)s)') % variables)
 
232
            self.client.update_network(net_id)
 
233
            self.client.update_port(net_id, datapath_id, port_no)
 
234
            self.client.update_mac(net_id, datapath_id, port_no, mac_address)
 
235
        return p