def _remove_from_switch(self, port, network): host = port[portbindings.HOST_ID] port_id = port['id'] for _switch_id in self.switches: with self.sync_thread_lock: db_port = db.db_get_port(network.network_id, port_id, _switch_id, host) if not db_port: continue vni = db_port.vni actions = [ HOSTS_URL.format( scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=network.bridge_name, vlanid=network.segmentation_id, host=host ), ] if (vni != INVALID_VNI) and (network.segmentation_id != vni): actions.append( VXLAN_URL.format( scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=network.bridge_name, vlanid=network.segmentation_id, vni=vni ) ) for action in actions: try: resp = requests.delete(action) if resp.status_code != requests.codes.ok: msg = (_("Error (%(code)s) delete port for %(host)s on" " switch %(switch_id)s") % {'code': resp.status_code, 'host': host, 'switch_id': _switch_id}) LOG.info(msg) except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch (%(switch_id)s)." " HTTP Error %(error)s") % {'switch_id': _switch_id, 'error': error}) LOG.info(msg) with self.sync_thread_lock: db.db_delete_port(network.network_id, port_id, _switch_id, host)
def main(): common_config.init(sys.argv[1:]) common_config.setup_logging() cumulus_config.register_options() cumulus_agent = CumulusAgent() try: cumulus_agent.start() except Exception as e: LOG.exception(_LE("Error in Cumulus agent service.")) sys.exit(_("ERROR: %s.") % e)
def check_switch_connections(self): for switch_id in self._mech_driver.switches: try: resp = requests.get(SWITCH_HASH_ID_URL.format( scheme=self._mech_driver.scheme, base=switch_id, port=self._mech_driver.protocol_port), auth=(self._mech_driver.username, self._mech_driver.password), verify=False) if resp.status_code != requests.codes.ok: msg = (_("Switch (%(switch_id)s) is unresponsive." " HTTP Error %(error)d") % { 'switch_id': switch_id, 'error': resp.status_code }) LOG.info(msg) self._mech_driver.switch_info[switch_id, 'state'] = \ SwitchState.inactive self._mech_driver.switch_info[switch_id, 'replay'] = False self._mech_driver.switch_info[switch_id, 'hash_id'] = \ INVALID_HASH_ID else: data = resp.json() if data != self._mech_driver.switch_info[switch_id, 'hash_id']: self._mech_driver.switch_info[switch_id, 'state'] = \ SwitchState.active self._mech_driver.switch_info[switch_id, 'replay'] = \ True self._mech_driver.switch_info[switch_id, 'hash_id'] = \ data except requests.exceptions.RequestException: self._mech_driver.switch_info[switch_id, 'state'] = \ SwitchState.inactive self._mech_driver.switch_info[switch_id, 'replay'] = False self._mech_driver.switch_info[switch_id, 'hash_id'] = \ INVALID_HASH_ID
def __init__(self, interface_mappings, polling_interval): super(HPBLinuxBridgeNeutronAgentRPC, self).__init__(interface_mappings, polling_interval) dm = DiscoveryManager(Shell(DEFAULT_ROOT_HELPER)) for physnet, interface in interface_mappings.iteritems(): neighbor = dm.find_neighbor_for_interface(interface) if neighbor: self.agent_state['configurations']['switch_name'] = \ neighbor['name'] self.agent_state['configurations']['switch_mgmt_ip'] = \ neighbor['mgmt-ip'] break else: msg = (_("Unable to find %(nbr)s for interface %(intf)s") % { 'nbr': physnet, 'intf': interface }) LOG.error(msg)
def delete_network_postcommit(self, context): network_id = context.current['id'] tenant_id = context.current['tenant_id'] segments = context.network_segments vlan_id = segments[0]['segmentation_id'] with self.sync_thread_lock: bridge_name = db.db_get_bridge_name(tenant_id, network_id) # remove vxlan from all hosts - a little unpleasant for _switch_id in self.switches: try: resp = requests.delete( NETWORKS_URL.format( scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=bridge_name, vlanid=vlan_id ) ) if resp.status_code != requests.codes.ok: LOG.info( _LI('Error during network delete. HTTP Error:%d'), resp.status_code ) except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch (%(switch_id)s)." " HTTP Error %(error)s") % {'switch_id': _switch_id, 'error': error}) LOG.info(msg) with self.sync_thread_lock: db.db_delete_network(tenant_id, network_id)
def create_network_postcommit(self, context): network = context.current network_id = network['id'] tenant_id = network['tenant_id'] segments = context.network_segments vlan_id = segments[0]['segmentation_id'] with self.sync_thread_lock: bridge_name = db.db_get_bridge_name(tenant_id, network_id) if bridge_name: for _switch_id in self.switches: try: resp = requests.put( NETWORKS_URL.format( scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=bridge_name, vlanid=vlan_id ), data=json.dumps( {'spf': self.switch_info[_switch_id, 'spf_enable'], 'newbridge': self.switch_info[_switch_id, 'new_bridge']}) ) if resp.status_code != requests.codes.ok: raise MechanismDriverError() except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch (%(switch_id)s)." " HTTP Error %(error)s") % {'switch_id': _switch_id, 'error': error}) LOG.info(msg)
# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from oslo_config import cfg from networking_cumulus._i18n import _ CUMULUS_DRIVER_OPTS = [ cfg.StrOpt('scheme', default='https', help=_('Scheme for base URL for the Cumulus ML2 API')), cfg.IntOpt('protocol_port', default='8080', help=_('Protocol port for base URL for the Cumulus ML2 API')), cfg.StrOpt('username', default='cumulus', help=_('username for Cumulus switch')), cfg.StrOpt('password', default='CumulusLinux!', help=_('password for Cumulus switch')), cfg.ListOpt('switches', default=[], help=_('list of switch name/ip and remote switch port ' 'connected to this compute node')), cfg.IntOpt('sync_time', default=30,
def replay_to_switch(self, switch_id, bridge_name, port, vlan): try: resp = requests.put( NETWORKS_URL.format( scheme=self.scheme, base=switch_id, port=self.protocol_port, bridge=bridge_name, vlanid=vlan ), data=json.dumps({'spf': self.switch_info[switch_id, 'spf_enable'], 'newbridge': self.switch_info[switch_id, 'new_bridge']}) ) if resp.status_code != requests.codes.ok: msg = (_("Error %(code)d replay to switch %(switch_id)s.") % {'code': resp.status_code, 'switch_id': switch_id}) LOG.info(msg) return resp.status_code except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch %(switch_id)s." " HTTP Error %(error)s") % {'switch_id': switch_id, 'error': error}) LOG.info(msg) actions = [ HOSTS_URL.format( scheme=self.scheme, base=switch_id, port=self.protocol_port, bridge=bridge_name, vlanid=vlan, host=port.host_id ), ] if (port.vni != INVALID_VNI) and (port.vni != vlan): actions.append( VXLAN_URL.format( scheme=self.scheme, base=switch_id, port=self.protocol_port, bridge=bridge_name, vlanid=vlan, vni=port.vni ) ) for action in actions: try: resp = requests.put(action) if resp.status_code != requests.codes.ok: msg = (_("Error %(code)d replay to switch %(switch_id)s") % {'code': resp.status_code, 'switch_id': switch_id}) LOG.info(msg) return resp.status_code except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch (%(switch_id)s)." " HTTP Error %(error)s") % {'switch_id': switch_id, 'error': error}) LOG.info(msg) return requests.codes.ok
def _add_to_switch(self, context, network): port = context.current device_id = port['device_id'] device_owner = port['device_owner'] host = port[portbindings.HOST_ID] if not hasattr(context, 'top_bound_segment'): return if not context.top_bound_segment: return vni = context.top_bound_segment['segmentation_id'] vlan_id = context.bottom_bound_segment['segmentation_id'] if not (host and device_id and device_owner): return for _switch_id in self.switches: actions = [ HOSTS_URL.format( scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=network.bridge_name, vlanid=vlan_id, host=host ), ] if context.top_bound_segment != context.bottom_bound_segment: actions.append( VXLAN_URL.format( scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=network.bridge_name, vlanid=vlan_id, vni=vni ) ) for action in actions: try: resp = requests.put(action) if resp.status_code != requests.codes.ok: msg = (_("Error (%(code)s) update port for %(host)s on" " switch %(switch_id)s") % {'code': resp.status_code, 'host': host, 'switch_id': _switch_id}) LOG.info(msg) return resp.status_code # raise MechanismDriverError() except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch (%(switch_id)s)." " HTTP Error %(error)s") % {'switch_id': _switch_id, 'error': error}) LOG.info(msg)
from enum import Enum from oslo_config import cfg from oslo_log import log as logging import requests from neutron.extensions import portbindings from neutron.plugins.ml2.common.exceptions import MechanismDriverError from neutron.plugins.ml2 import driver_api as api from networking_cumulus._i18n import _, _LI from networking_cumulus.mech_driver import config # noqa from networking_cumulus.mech_driver import db LOG = logging.getLogger(__name__) NETWORKS_URL = _('{scheme}://{base}:{port}/ml2/v1/bridge/{bridge}/{vlanid}') HOSTS_URL = \ _('{scheme}://{base}:{port}/ml2/v1/bridge/{bridge}/{vlanid}/hosts/{host}') VXLAN_URL = \ _('{scheme}://{base}:{port}/ml2/v1/bridge/{bridge}/{vlanid}/vxlan/{vni}') SWITCH_HASH_ID_URL = _('{scheme}://{base}:{port}/ml2/v1/hash') NEW_BRIDGE_NAME = _('bridge') OLD_BRIDGE_NAME_PREFIX = _('br') class SwitchState(Enum): inactive = 1 active = 2
import sys from oslo_config import cfg from oslo_log import log as logging from neutron.common import config as common_config from neutron.common import utils as neutron_utils from neutron.plugins.linuxbridge.agent import linuxbridge_neutron_agent as lna from utils.discovery import DiscoveryManager from utils.misc import Shell from networking_cumulus._i18n import _, _LE, _LI DEFAULT_ROOT_HELPER = _('sudo') LOG = logging.getLogger(__name__) class HPBLinuxBridgeNeutronAgentRPC(lna.LinuxBridgeNeutronAgentRPC): def __init__(self, interface_mappings, polling_interval): super(HPBLinuxBridgeNeutronAgentRPC, self).__init__(interface_mappings, polling_interval) dm = DiscoveryManager(Shell(DEFAULT_ROOT_HELPER)) for physnet, interface in interface_mappings.iteritems(): neighbor = dm.find_neighbor_for_interface(interface) if neighbor: self.agent_state['configurations']['switch_name'] = \
def replay_to_switch(self, switch_id, bridge_name, port, seg_id): is_vxlan = (db.db_get_seg_type(port.network_id) == va.const.TYPE_VXLAN) try: resp = requests.put(NETWORKS_URL.format(scheme=self.scheme, base=switch_id, port=self.protocol_port, bridge=bridge_name, vlanid=port.vni), data=json.dumps({ 'spf': self.switch_info[switch_id, 'spf_enable'], 'newbridge': self.switch_info[switch_id, 'new_bridge'] }), auth=(self.username, self.password), verify=False) if resp.status_code != requests.codes.ok: msg = (_("Error %(code)d replay to switch %(switch_id)s.") % { 'code': resp.status_code, 'switch_id': switch_id }) LOG.info(msg) return resp.status_code except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch %(switch_id)s." " HTTP Error %(error)s") % { 'switch_id': switch_id, 'error': error }) LOG.info(msg) actions = [ HOSTS_URL.format(scheme=self.scheme, base=switch_id, port=self.protocol_port, bridge=bridge_name, vlanid=port.vni, host=port.host_id), ] if is_vxlan and (seg_id != INVALID_VNI): actions.append( VXLAN_URL.format(scheme=self.scheme, base=switch_id, port=self.protocol_port, bridge=bridge_name, vlanid=port.vni, vni=seg_id)) for action in actions: try: resp = requests.put(action, auth=(self.username, self.password), verify=False) if resp.status_code != requests.codes.ok: msg = (_("Error %(code)d replay to switch %(switch_id)s") % { 'code': resp.status_code, 'switch_id': switch_id }) LOG.info(msg) return resp.status_code except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch (%(switch_id)s)." " HTTP Error %(error)s") % { 'switch_id': switch_id, 'error': error }) LOG.info(msg) return requests.codes.ok
def _remove_from_switch(self, port, network, remove_net, vlan_id): host = port[va.portbindings.HOST_ID] port_id = port['id'] with self.sync_thread_lock: is_vxlan = (db.db_get_seg_type( network.network_id) == va.const.TYPE_VXLAN) for _switch_id in self.switches: actions = [ HOSTS_URL.format(scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=network.bridge_name, vlanid=vlan_id, host=host), ] if is_vxlan: actions.append( VXLAN_URL.format(scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=network.bridge_name, vlanid=vlan_id, vni=network.segmentation_id)) for action in actions: try: resp = requests.delete(action, auth=(self.username, self.password), verify=False) if resp.status_code != requests.codes.ok: msg = (_("Error (%(code)s) delete port for %(host)s on" " switch %(switch_id)s") % { 'code': resp.status_code, 'host': host, 'switch_id': _switch_id }) LOG.info(msg) except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch (%(switch_id)s)." " HTTP Error %(error)s") % { 'switch_id': _switch_id, 'error': error }) LOG.info(msg) with self.sync_thread_lock: db.db_delete_port(network.network_id, port_id, _switch_id, host) if remove_net: try: resp = requests.delete(NETWORKS_URL.format( scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=network.bridge_name, vlanid=vlan_id), auth=(self.username, self.password), verify=False) if resp.status_code != requests.codes.ok: LOG.info( _LI('Error during network delete. HTTP Error:%d'), resp.status_code) except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch (%(switch_id)s)." " HTTP Error %(error)s") % { 'switch_id': _switch_id, 'error': error }) LOG.info(msg)
def _add_to_switch(self, context, network): port = context.current device_id = port['device_id'] device_owner = port['device_owner'] host = port[va.portbindings.HOST_ID] if not (host and device_id and device_owner): return vlan_id, vni, is_vxlan = (self._get_segment_ids(context)) if vlan_id == INVALID_VLAN_ID: LOG.debug("No segmentation id found for network %s", network.network_id) return for _switch_id in self.switches: try: resp = requests.put( NETWORKS_URL.format(scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=network.bridge_name, vlanid=vlan_id), data=json.dumps({ 'spf': self.switch_info[_switch_id, 'spf_enable'], 'newbridge': self.switch_info[_switch_id, 'new_bridge'] }), auth=(self.username, self.password), verify=False) if resp.status_code != requests.codes.ok: msg = (_("Error (%(code)s) network add for %(network)s on" " switch %(switch_id)s") % { 'code': resp.status_code, 'network': network.network_id, 'switch_id': _switch_id }) LOG.info(msg) raise MechanismDriverError() except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch (%(switch_id)s)." " HTTP Error %(error)s") % { 'switch_id': _switch_id, 'error': error }) LOG.info(msg) continue actions = [ HOSTS_URL.format(scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=network.bridge_name, vlanid=vlan_id, host=host), ] if is_vxlan: actions.append( VXLAN_URL.format(scheme=self.scheme, base=_switch_id, port=self.protocol_port, bridge=network.bridge_name, vlanid=vlan_id, vni=vni)) for action in actions: try: resp = requests.put(action, auth=(self.username, self.password), verify=False) if resp.status_code != requests.codes.ok: msg = (_("Error (%(code)s) add port for %(host)s on" " switch %(switch_id)s") % { 'code': resp.status_code, 'host': host, 'switch_id': _switch_id }) LOG.info(msg) return resp.status_code # raise MechanismDriverError() except requests.exceptions.RequestException as error: msg = (_("Error connecting to switch (%(switch_id)s)." " HTTP Error %(error)s") % { 'switch_id': _switch_id, 'error': error }) LOG.info(msg)