From e5095b06d5f7f8b718d3729120b1cd971177a2ea Mon Sep 17 00:00:00 2001 From: Dan Wendlandt Date: Tue, 13 Dec 2011 12:54:02 -0800 Subject: [PATCH] blueprint operational-status-ovs-plugin Implements operational status API for OVS plugin. Uses existing database model for operational status. For network, status is always up. For a port, status is down unless there is an agent that indicates that the port is active on its compute host. Updated: use Salvatore's config hook to set default op-status for OVS in OVS run_tests.py Updated: fixed issue in _make_port_dict() found by Brad. Change-Id: I0560cbde9dc69bd4211d9aaf12cef204df2f7664 --- .../openvswitch/agent/ovs_quantum_agent.py | 22 +++++-- .../plugins/openvswitch/ovs_quantum_plugin.py | 63 ++++++++++--------- quantum/plugins/openvswitch/run_tests.py | 10 ++- 3 files changed, 56 insertions(+), 39 deletions(-) diff --git a/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py b/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py index de39ad9bda8..6609a687486 100755 --- a/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py +++ b/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py @@ -25,9 +25,12 @@ import time import signal from optparse import OptionParser +from sqlalchemy.ext.sqlsoup import SqlSoup from subprocess import * -from sqlalchemy.ext.sqlsoup import SqlSoup + +OP_STATUS_UP = "UP" +OP_STATUS_DOWN = "DOWN" # A class to represent a VIF (i.e., a port that has 'iface-id' and 'vif-mac' @@ -199,7 +202,7 @@ class OVSQuantumAgent: except: ports = [] for port in ports: - all_bindings[port.interface_id] = port.network_id + all_bindings[port.interface_id] = port vlan_bindings = {} try: @@ -215,7 +218,8 @@ class OVSQuantumAgent: for p in vif_ports: new_vif_ports[p.vif_id] = p if p.vif_id in all_bindings: - new_local_bindings[p.vif_id] = all_bindings[p.vif_id] + net_id = all_bindings[p.vif_id].network_id + new_local_bindings[p.vif_id] = net_id else: # no binding, put him on the 'dead vlan' self.int_br.set_db_attribute("Port", p.port_name, "tag", @@ -231,23 +235,31 @@ class OVSQuantumAgent: LOG.info("Removing binding to net-id = %s for %s" % (old_b, str(p))) self.port_unbound(p, True) + if p.vif_id in all_bindings: + all_bindings[p.vif_id].op_status = OP_STATUS_DOWN if new_b is not None: # If we don't have a binding we have to stick it on # the dead vlan - vlan_id = vlan_bindings.get(all_bindings[p.vif_id], - "4095") + net_id = all_bindings[p.vif_id].network_id + vlan_id = vlan_bindings.get(net_id, "4095") self.port_bound(p, vlan_id) + if p.vif_id in all_bindings: + all_bindings[p.vif_id].op_status = OP_STATUS_UP LOG.info("Adding binding to net-id = %s " \ "for %s on vlan %s" % (new_b, str(p), vlan_id)) + for vif_id in old_vif_ports.keys(): if vif_id not in new_vif_ports: LOG.info("Port Disappeared: %s" % vif_id) if vif_id in old_local_bindings: old_b = old_local_bindings[vif_id] self.port_unbound(old_vif_ports[vif_id], False) + if vif_id in all_bindings: + all_bindings[vif_id].op_status = OP_STATUS_DOWN old_vif_ports = new_vif_ports old_local_bindings = new_local_bindings + db.commit() time.sleep(2) if __name__ == "__main__": diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.py b/quantum/plugins/openvswitch/ovs_quantum_plugin.py index 3b882e5f956..d87b17a726b 100644 --- a/quantum/plugins/openvswitch/ovs_quantum_plugin.py +++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.py @@ -23,6 +23,7 @@ from optparse import OptionParser import os import sys +from quantum.api.api_common import OperationalStatus from quantum.common import exceptions as q_exc from quantum.common.config import find_config_file from quantum.quantum_plugin_base import QuantumPluginBase @@ -102,22 +103,26 @@ class OVSQuantumPlugin(QuantumPluginBase): nets = [] for x in db.network_list(tenant_id): LOG.debug("Adding network: %s" % x.uuid) - nets.append(self._make_net_dict(str(x.uuid), x.name, None)) + nets.append(self._make_net_dict(str(x.uuid), x.name, + None, x.op_status)) return nets - def _make_net_dict(self, net_id, net_name, ports): + def _make_net_dict(self, net_id, net_name, ports, op_status): res = {'net-id': net_id, - 'net-name': net_name} + 'net-name': net_name, + 'net-op-status': op_status} if ports: res['net-ports'] = ports return res def create_network(self, tenant_id, net_name, **kwargs): - net = db.network_create(tenant_id, net_name) + net = db.network_create(tenant_id, net_name, + op_status=OperationalStatus.UP) LOG.debug("Created network: %s" % net) vlan_id = self.vmap.acquire(str(net.uuid)) ovs_db.add_vlan_binding(vlan_id, str(net.uuid)) - return self._make_net_dict(str(net.uuid), net.name, []) + return self._make_net_dict(str(net.uuid), net.name, [], + net.op_status) def delete_network(self, tenant_id, net_id): net = db.network_get(net_id) @@ -129,43 +134,46 @@ class OVSQuantumPlugin(QuantumPluginBase): net = db.network_destroy(net_id) ovs_db.remove_vlan_binding(net_id) self.vmap.release(net_id) - return self._make_net_dict(str(net.uuid), net.name, []) + return self._make_net_dict(str(net.uuid), net.name, [], + net.op_status) def get_network_details(self, tenant_id, net_id): net = db.network_get(net_id) ports = self.get_all_ports(tenant_id, net_id) - return self._make_net_dict(str(net.uuid), net.name, ports) + return self._make_net_dict(str(net.uuid), net.name, + ports, net.op_status) def update_network(self, tenant_id, net_id, **kwargs): net = db.network_update(net_id, tenant_id, **kwargs) - return self._make_net_dict(str(net.uuid), net.name, None) + return self._make_net_dict(str(net.uuid), net.name, + None, net.op_status) - def _make_port_dict(self, port_id, port_state, net_id, attachment): - return {'port-id': port_id, - 'port-state': port_state, - 'net-id': net_id, - 'attachment': attachment} + def _make_port_dict(self, port): + if port.state == "ACTIVE": + op_status = port.op_status + else: + op_status = OperationalStatus.DOWN + + return {'port-id': str(port.uuid), + 'port-state': port.state, + 'port-op-status': op_status, + 'net-id': port.network_id, + 'attachment': port.interface_id} def get_all_ports(self, tenant_id, net_id): ids = [] ports = db.port_list(net_id) - for p in ports: - LOG.debug("Appending port: %s" % p.uuid) - d = self._make_port_dict(str(p.uuid), p.state, p.network_id, - p.interface_id) - ids.append(d) - return ids + return [{'port-id': str(p.uuid)} for p in ports] def create_port(self, tenant_id, net_id, port_state=None, **kwargs): LOG.debug("Creating port with network_id: %s" % net_id) - port = db.port_create(net_id, port_state) - return self._make_port_dict(str(port.uuid), port.state, - port.network_id, port.interface_id) + port = db.port_create(net_id, port_state, + op_status=OperationalStatus.DOWN) + return self._make_port_dict(port) def delete_port(self, tenant_id, net_id, port_id): port = db.port_destroy(port_id, net_id) - return self._make_port_dict(str(port.uuid), port.state, - port.network_id, port.interface_id) + return self._make_port_dict(port) def update_port(self, tenant_id, net_id, port_id, **kwargs): """ @@ -174,19 +182,18 @@ class OVSQuantumPlugin(QuantumPluginBase): LOG.debug("update_port() called\n") port = db.port_get(port_id, net_id) db.port_update(port_id, net_id, **kwargs) - return self._make_port_dict(str(port.uuid), port.state, - port.network_id, port.interface_id) + return self._make_port_dict(port) def get_port_details(self, tenant_id, net_id, port_id): port = db.port_get(port_id, net_id) - return self._make_port_dict(str(port.uuid), port.state, - port.network_id, port.interface_id) + return self._make_port_dict(port) def plug_interface(self, tenant_id, net_id, port_id, remote_iface_id): db.port_set_attachment(port_id, net_id, remote_iface_id) def unplug_interface(self, tenant_id, net_id, port_id): db.port_set_attachment(port_id, net_id, "") + db.port_update(port_id, net_id, op_status=OperationalStatus.DOWN) def get_interface_details(self, tenant_id, net_id, port_id): res = db.port_get(port_id, net_id) diff --git a/quantum/plugins/openvswitch/run_tests.py b/quantum/plugins/openvswitch/run_tests.py index 9649efa0d87..b01ba765d6f 100644 --- a/quantum/plugins/openvswitch/run_tests.py +++ b/quantum/plugins/openvswitch/run_tests.py @@ -37,9 +37,10 @@ from nose import core sys.path.append(os.getcwd()) sys.path.append(os.path.dirname(__file__)) -import quantum.tests.unit +from quantum.api.api_common import OperationalStatus from quantum.common.test_lib import run_tests, test_config +import quantum.tests.unit from tests.unit.test_vlan_map import VlanMapTest if __name__ == '__main__': @@ -49,12 +50,9 @@ if __name__ == '__main__': # we should only invoked the tests once invoke_once = len(sys.argv) > 1 - # NOTE (salvatore-orlando): - # please update default values for operational status according to - # the plugin behavior. test_config['plugin_name'] = "ovs_quantum_plugin.OVSQuantumPlugin" - test_config['default_net_op_status'] = "UNKNOWN" - test_config['default_port_op_status'] = "UNKNOWN" + test_config['default_net_op_status'] = OperationalStatus.UP + test_config['default_port_op_status'] = OperationalStatus.DOWN cwd = os.getcwd() c = config.Config(stream=sys.stdout,