def _add_updatable_args(parser): parser.add_argument( '--name', help=_('Name of this router type.')) parser.add_argument( '--description', help=_('Description of this router type.')) parser.add_argument( '--ha-enabled', dest='ha_enabled_by_default', action='store_true', help=_('Make HA enabled for the router type.'), default=argparse.SUPPRESS) parser.add_argument( '--ha_enabled', dest='ha_enabled_by_default', action='store_true', help=argparse.SUPPRESS, default=argparse.SUPPRESS) parser.add_argument( '--unshared', dest='shared', action='store_false', help=_('Make router type NOT shared among tenants.'), default=argparse.SUPPRESS) parser.add_argument( '--slot-need', help=_('Number of slots routers of this type consumes.')) parser.add_argument( '--slot_need', help=argparse.SUPPRESS)
def _agent_registration(self): """Register this agent with the server. This method registers the cfg agent with the neutron server so hosting devices can be assigned to it. In case the server is not ready to accept registration (it sends a False) then we retry registration for `MAX_REGISTRATION_ATTEMPTS` with a delay of `REGISTRATION_RETRY_DELAY`. If there is no server response or a failure to register after the required number of attempts, the agent stops itself. """ for attempts in range(MAX_REGISTRATION_ATTEMPTS): context = n_context.get_admin_context_without_session() self.send_agent_report(self.agent_state, context) res = self.devmgr_rpc.register_for_duty(context) if res is True: LOG.info(_LI("[Agent registration] Agent successfully " "registered")) return elif res is False: LOG.warning(_LW("[Agent registration] Neutron server said " "that device manager was not ready. Retrying " "in %0.2f seconds "), REGISTRATION_RETRY_DELAY) time.sleep(REGISTRATION_RETRY_DELAY) elif res is None: LOG.error(_LE("[Agent registration] Neutron server said that " "no device manager was found. Cannot continue. " "Exiting!")) raise SystemExit(_("Cfg Agent exiting")) LOG.error(_LE("[Agent registration] %d unsuccessful registration " "attempts. Exiting!"), MAX_REGISTRATION_ATTEMPTS) raise SystemExit(_("Cfg Agent exiting"))
def add_known_arguments(self, parser): # adding admin_state_up here so that it is available for update only # as it is True by default and not meaningful in the create operation parser.add_argument( "--admin-state-up", dest="admin_state_up", action="store_true", help=_("Set hosting device administratively up."), default=argparse.SUPPRESS, ) parser.add_argument( "--admin_state_up", dest="admin_state_up", action="store_true", help=argparse.SUPPRESS, default=argparse.SUPPRESS, ) # adding no_auto_delete here so that it is available for update only # as auto_delete is False by default and not meaningful in the create # operation parser.add_argument( "--no-auto-delete", dest="auto_delete", action="store_false", help=_("Exempt hosting device from automated life cycle " "management."), default=argparse.SUPPRESS, ) parser.add_argument( "--no_auto_delete", dest="auto_delete", action="store_false", help=argparse.SUPPRESS, default=argparse.SUPPRESS, ) _add_updatable_args(parser)
def get_parser(self, prog_name): parser = super(AddRouterToHostingDevice, self).get_parser(prog_name) parser.add_argument( 'hosting_device', help=_('Name or id of the hosting device.')) parser.add_argument( 'router', help=_('Name or id of router to add.')) return parser
def get_parser(self, prog_name): parser = super(HostingDeviceDisassociateFromConfigAgent, self).get_parser(prog_name) parser.add_argument( 'config_agent_id', help=_('Id of the Cisco configuration agent.')) parser.add_argument( 'hosting_device', help=_('Name or id of hosting device to disassociate.')) return parser
def verify_resource_dict(res_dict, is_create, attr_info): """Verifies required attributes are in resource dictionary, res_dict. Also checking that an attribute is only specified if it is allowed for the given operation (create/update). Attribute with default values are considered to be optional. This function contains code taken from function 'prepare_request_body' in attributes.py. """ if not bc_attr.IS_PRE_NEWTON and 'tenant_id' in res_dict: res_dict['project_id'] = res_dict['tenant_id'] if is_create: # POST for attr, attr_vals in six.iteritems(attr_info): if attr_vals['allow_post']: if 'default' not in attr_vals and attr not in res_dict: msg = _("Failed to parse request. Required attribute '%s' " "not specified") % attr raise webob.exc.HTTPBadRequest(msg) res_dict[attr] = res_dict.get(attr, attr_vals.get('default')) else: if attr in res_dict: msg = _("Attribute '%s' not allowed in POST") % attr raise webob.exc.HTTPBadRequest(msg) else: # PUT for attr, attr_vals in six.iteritems(attr_info): if attr in res_dict and not attr_vals['allow_put']: msg = _("Cannot update read-only attribute %s") % attr raise webob.exc.HTTPBadRequest(msg) for attr, attr_vals in six.iteritems(attr_info): if (attr not in res_dict or res_dict[attr] is bc_attr.ATTR_NOT_SPECIFIED): continue # Convert values if necessary if 'convert_to' in attr_vals: res_dict[attr] = attr_vals['convert_to'](res_dict[attr]) # Check that configured values are correct if 'validate' not in attr_vals: continue for rule in attr_vals['validate']: _ensure_format(rule, attr, res_dict) res = attributes.validators[rule](res_dict[attr], attr_vals['validate'][rule]) if res: msg_dict = dict(attr=attr, reason=res) msg = (_("Invalid input for %(attr)s. Reason: %(reason)s.") % msg_dict) raise webob.exc.HTTPBadRequest(msg) return res_dict
def _parse_nexus_vni_range(self, tunnel_range): """Raise an exception for invalid tunnel range or malformed range.""" for ident in tunnel_range: if not self._is_valid_nexus_vni(ident): raise exc.NetworkTunnelRangeError( tunnel_range=tunnel_range, error=_("%(id)s is not a valid Nexus VNI value.") % {'id': ident}) if tunnel_range[1] < tunnel_range[0]: raise exc.NetworkTunnelRangeError( tunnel_range=tunnel_range, error=_("End of tunnel range is less than start of " "tunnel range."))
def add_known_arguments(self, parser): _add_updatable_args(parser) parser.add_argument("--id", help=_("Id for this hosting device.")) parser.add_argument("--management-port", help=_("Neutron port used for management of hosting device.")) parser.add_argument("--management_port", help=argparse.SUPPRESS) parser.add_argument("--cfg-agent-id", help=_("Config agent to handle the hosting device.")) parser.add_argument("--cfg_agent_id", help=argparse.SUPPRESS) parser.add_argument("name", metavar="NAME", help=_("Name of hosting device to create.")) parser.add_argument( "template_id", metavar="TEMPLATE", help=_("Hosting device template template to associate " "hosting device with."), )
def _create_multi_ucsm_dicts(self): """Creates a dictionary of all UCS Manager data from config.""" multi_parser = cfg.MultiConfigParser() read_ok = multi_parser.read(cfg.CONF.config_file) if len(read_ok) != len(cfg.CONF.config_file): raise cfg.Error(_('Some config files were not parsed properly')) for parsed_file in multi_parser.parsed: for parsed_item in parsed_file.keys(): dev_id, sep, dev_ip = parsed_item.partition(':') dev_ip = dev_ip.strip() if dev_id.lower() == 'ml2_cisco_ucsm_ip': ucsm_info = [] eth_port_list = [] for dev_key, value in parsed_file[parsed_item].items(): config_item = dev_key.lower() if config_item == 'ucsm_virtio_eth_ports': for eth_port in value[0].split(','): eth_port_list.append( const.ETH_PREFIX + str(eth_port).strip()) self.ucsm_port_dict[dev_ip] = eth_port_list elif config_item == 'sp_template_list': self._parse_sp_template_list(dev_ip, value) self.sp_template_mode = True elif config_item == 'vnic_template_list': self._parse_vnic_template_list(dev_ip, value) self.vnic_template_mode = True else: ucsm_info.append(value[0]) self.ucsm_dict[dev_ip] = ucsm_info self.multi_ucsm_mode = True
def _build_flow_expr_str(flow_dict, cmd): flow_expr_arr = [] actions = None if cmd == 'add': flow_expr_arr.append("hard_timeout=%s" % flow_dict.pop('hard_timeout', '0')) flow_expr_arr.append("idle_timeout=%s" % flow_dict.pop('idle_timeout', '0')) flow_expr_arr.append("priority=%s" % flow_dict.pop('priority', '1')) elif 'priority' in flow_dict: msg = "Cannot match priority on flow deletion or modification" raise dfae.InvalidInput(error_message=msg) if cmd != 'del': if "actions" not in flow_dict: msg = _("Must specify one or more actions on flow addition" " or modification") raise dfae.InvalidInput(error_message=msg) actions = "actions=%s" % flow_dict.pop('actions') for key, value in six.iteritems(flow_dict): if key == 'proto': flow_expr_arr.append(value) else: flow_expr_arr.append("%s=%s" % (key, str(value))) if actions: flow_expr_arr.append(actions) return ','.join(flow_expr_arr)
def _create_multi_ucsm_dicts(self): """Creates a dictionary of all UCS Manager data from config.""" multi_parser = cfg.MultiConfigParser() read_ok = multi_parser.read(cfg.CONF.config_file) if len(read_ok) != len(cfg.CONF.config_file): raise cfg.Error(_('Some config files were not parsed properly')) for parsed_file in multi_parser.parsed: for parsed_item in parsed_file.keys(): dev_id, sep, dev_ip = parsed_item.partition(':') if dev_id.lower() == 'ml2_cisco_ucsm_ip': ucsm_info = [] eth_ports = [] eth_port_list = [] for dev_key, value in parsed_file[parsed_item].items(): if dev_key != 'ucsm_virtio_eth_ports': ucsm_info.append(value[0]) else: eth_ports = value[0].split(',') for eth_port in eth_ports: eth_port_list.append( const.ETH_PREFIX + str(eth_port)) self.ucsm_dict[dev_ip] = ucsm_info self.ucsm_port_dict[dev_ip] = eth_port_list
def parse_ucsm_host_config(): sp_dict = {} host_dict = {} if cfg.CONF.ml2_cisco_ucsm.ucsm_host_list: host_config_list = cfg.CONF.ml2_cisco_ucsm.ucsm_host_list for host in host_config_list: hostname, sep, service_profile = host.partition(':') if not sep or not service_profile: raise cfg.Error(_("UCS Mech Driver: Invalid Host Service " "Profile config: %s") % host) key = (cfg.CONF.ml2_cisco_ucsm.ucsm_ip, hostname) if '/' not in service_profile: # Assuming the service profile is at the root level # and the path is not specified. This option # allows backward compatability with earlier config # format sp_dict[key] = (const.SERVICE_PROFILE_PATH_PREFIX + service_profile.strip()) else: # Assuming the complete path to Service Profile has # been provided in the config. The Service Profile # could be in an sub-org. sp_dict[key] = service_profile.strip() LOG.debug('Service Profile for %s is %s', hostname, sp_dict.get(key)) host_dict[hostname] = cfg.CONF.ml2_cisco_ucsm.ucsm_ip return sp_dict, host_dict
def dequeue(self, qname): if qname not in self._queues: raise ValueError(_("queue %s is not defined"), qname) try: return self._queues[qname].get(block=False) except Queue.Empty: return None
def get_parser(self, prog_name): parser = super(HostingDeviceHandledByConfigAgentList, self).get_parser(prog_name) parser.add_argument( 'config_agent_id', help=_('Id of the Cisco configuration agent to query.')) return parser
def get_plugin(self): plugin = manager.NeutronManager.get_service_plugins().get( svc_constants.L3_ROUTER_NAT) if not plugin: LOG.error(_LE('No L3 router service plugin registered to ' 'handle routertype-aware scheduling')) msg = _('The resource could not be found.') raise webob.exc.HTTPNotFound(msg) return plugin
def __init__(self): """Create a single UCSM or Multi-UCSM dict.""" self._create_multi_ucsm_dicts() if cfg.CONF.ml2_cisco_ucsm.ucsm_ip and not self.ucsm_dict: self._create_single_ucsm_dicts() if not self.ucsm_dict: raise cfg.Error(_('Insufficient UCS Manager configuration has ' 'been provided to the plugin'))
def get_plugin(self): plugin = manager.NeutronManager.get_service_plugins().get( cisco_constants.DEVICE_MANAGER) if not plugin: LOG.error(_LE('No Device manager service plugin registered to ' 'handle hosting device scheduling')) msg = _('The resource could not be found.') raise webob.exc.HTTPNotFound(msg) return plugin
def parse_pci_vendor_config(): vendor_list = [] vendor_config_list = cfg.CONF.ml2_cisco_ucsm.supported_pci_devs for vendor in vendor_config_list: vendor_product = vendor.split(':') if len(vendor_product) != 2: raise cfg.Error(_("UCS Mech Driver: Invalid PCI device " "config: %s") % vendor) vendor_list.append(vendor) return vendor_list
def add_known_arguments(self, parser): # adding enable here so that it is available for update only as it is # True by default and not meaningful in the create operation parser.add_argument( '--enabled', dest='enabled', action='store_true', help=_('Make the hosting device template enabled.'), default=argparse.SUPPRESS) _add_updatable_args(parser)
def register(self, observer): LOG.debug("Attaching observer: %(ob)s to subject: %(sub)s", {'ob': observer.__class__.__name__, 'sub': self.__class__.__name__}) if observer not in self._observers: self._observers.append(observer) else: raise ValueError(_("Observer: %(ob)s is already registered to " "subject: %(sub)s"), {'ob': observer.__class__.__name__, 'sub': self.__class__.__name__})
def unregister(self, observer): LOG.debug("Dettaching observer: %(ob)s from subject: %(sub)s", {'ob': observer.__class__.__name__, 'sub': self.__class__.__name__}) if observer in self._observers: self._observers.remove(observer) else: raise ValueError(_("Observer: %(ob)s is not attached to " "subject: %(sub)s"), {'ob': observer.__class__.__name__, 'sub': self.__class__.__name__})
def parse_virtio_eth_ports(): eth_port_list = [] if not cfg.CONF.ml2_cisco_ucsm.ucsm_virtio_eth_ports: raise cfg.Error(_("UCS Mech Driver: Ethernet Port List " "not provided. Cannot properly support " "Neutron virtual ports on this setup.")) for eth_port in cfg.CONF.ml2_cisco_ucsm.ucsm_virtio_eth_ports: eth_port_list.append(const.ETH_PREFIX + str(eth_port).strip()) return eth_port_list
def parse_ucsm_host_config(): host_dict = {} if cfg.CONF.ml2_cisco_ucsm.ucsm_host_list: host_config_list = cfg.CONF.ml2_cisco_ucsm.ucsm_host_list for host in host_config_list: host_sp = host.split(':') if len(host_sp) != 2: raise cfg.Error(_("UCS Mech Driver: Invalid Host Service " "Profile config: %s") % host) key = host_sp[0] host_dict[key] = host_sp[1] return host_dict
def add_known_arguments(self, parser): _add_updatable_args(parser) parser.add_argument( '--id', help=_('Id for this router type.')) parser.add_argument( 'template_id', metavar='TEMPLATE', help=_('Hosting device template to associate router type with.')) parser.add_argument( 'scheduler', metavar='SCHEDULER', help=_('Scheduler module to use for routers of this router type.')) parser.add_argument( 'driver', metavar='PLUGIN_DRIVER', help=_('Driver module to use in plugin for routers of this router ' 'type.')) parser.add_argument( 'cfg_agent_service_helper', metavar='SERVICE_HELPER', help=_('Service helper in config agent to use for routers of this ' 'router type.')) parser.add_argument( 'cfg_agent_driver', metavar='AGENT_DRIVER', help=_('Device driver in config agent to use for routers of this ' 'router type.'))
def _get_router_for_floatingip(self, context, internal_port, internal_subnet_id, external_network_id): """We need to over-load this function so that we only return the user visible router and never its redundancy routers (as they never have floatingips associated with them). """ subnet = self._core_plugin._get_subnet(context, internal_subnet_id) if not subnet['gateway_ip']: msg = (_('Cannot add floating IP to port on subnet %s ' 'which has no gateway_ip') % internal_subnet_id) raise n_exc.BadRequest(resource='floatingip', msg=msg) gw_port = orm.aliased(models_v2.Port, name="gw_port") routerport_qry = context.session.query( l3_db.RouterPort.router_id, models_v2.IPAllocation.ip_address).join( models_v2.Port, models_v2.IPAllocation).filter( models_v2.Port.network_id == internal_port['network_id'], l3_db.RouterPort.port_type.in_( l3_constants.ROUTER_INTERFACE_OWNERS), models_v2.IPAllocation.subnet_id == internal_subnet_id ).join(gw_port, gw_port.device_id == l3_db.RouterPort.router_id).filter( gw_port.network_id == external_network_id).distinct() # Ensure that redundancy routers (in a ha group) are not returned, # since only the user visible router should have floatingips. # This can be done by checking that the id of routers does not # appear in the 'redundancy_router_id' column in the # 'cisco_router_redundancy_bindings' table. routerport_qry = routerport_qry.outerjoin( RouterRedundancyBinding, RouterRedundancyBinding.redundancy_router_id == l3_db.RouterPort.router_id) routerport_qry = routerport_qry.filter( RouterRedundancyBinding.redundancy_router_id == expr.null()) first_router_id = None for router_id, interface_ip in routerport_qry: if interface_ip == subnet['gateway_ip']: return router_id if not first_router_id: first_router_id = router_id if first_router_id: return first_router_id raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet_id, external_network_id=external_network_id, port_id=internal_port['id'])
def parse_ucsm_host_config(): sp_dict = {} host_dict = {} if cfg.CONF.ml2_cisco_ucsm.ucsm_host_list: host_config_list = cfg.CONF.ml2_cisco_ucsm.ucsm_host_list for host in host_config_list: hostname, sep, service_profile = host.partition(':') if not sep or not service_profile: raise cfg.Error(_("UCS Mech Driver: Invalid Host Service " "Profile config: %s") % host) key = (cfg.CONF.ml2_cisco_ucsm.ucsm_ip, hostname) sp_dict[key] = service_profile host_dict[hostname] = cfg.CONF.ml2_cisco_ucsm.ucsm_ip return sp_dict, host_dict
def take_action(self, parsed_args): self.log.debug('run(%s)' % parsed_args) neutron_client = self.get_client() neutron_client.format = parsed_args.request_format _id_hd = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'hosting_device', parsed_args.hosting_device) _id_r = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'router', parsed_args.router) self.add_router_to_hosting_device(neutron_client, _id_hd, {'router_id': _id_r}) print(_('Added router \'%(router)s\' to hosting device \'%(hd)s\'') % { 'router': parsed_args.router, 'hd': parsed_args.hosting_device}, file=self.app.stdout, end='') return [], []
def _parse_vnic_template_list(self, ucsm_ip, vnic_template_config): vnic_template_mapping = [] for vnic_template_temp in vnic_template_config: vnic_template_mapping = vnic_template_temp.split() for mapping in vnic_template_mapping: physnet, sep, vnic_template = mapping.partition(':') if not sep or not vnic_template: raise cfg.Error(_("UCS Mech Driver: Invalid VNIC Template " "config: %s") % physnet) vnic_template_path, sep, vnic_template_name = ( vnic_template.partition(':')) if not vnic_template_path: vnic_template_path = const.VNIC_TEMPLATE_PARENT_DN if not vnic_template_name: raise cfg.Error(_("UCS Mech Driver: Invalid VNIC Template " "name for physnet: %s") % physnet) key = (ucsm_ip, physnet) value = (vnic_template_path, vnic_template_name) self.vnic_template_dict[key] = value LOG.debug('VNIC Template key: %s, value: %s', key, value)
def execute(self, parsed_args): self.log.debug('run(%s)' % parsed_args) neutron_client = self.get_client() neutron_client.format = parsed_args.request_format _id_hd = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'hosting_device', parsed_args.hosting_device) _id_r = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'router', parsed_args.router) self.remove_router_from_hosting_device(neutron_client, _id_hd, _id_r) print(_('Removed router \'%(router)s\' from hosting device \'%(hd)s\'') % {'router': parsed_args.router, 'hd': parsed_args.hosting_device}, file=self.app.stdout, end='') return [], []
def execute(self, parsed_args): self.log.debug('run(%s)' % parsed_args) neutron_client = self.get_client() neutron_client.format = parsed_args.request_format _id_hd = neutronV20.find_resourceid_by_name_or_id( neutron_client, 'hosting_device', parsed_args.hosting_device) self.disassociate_hosting_device_with_config_agent( neutron_client, parsed_args.config_agent_id, _id_hd) print(_('Disassociated hosting device \'%(hd)s\' from Cisco ' 'configuration agent \'%(agent)s\'') % { 'hd': parsed_args.hosting_device, 'agent': parsed_args.config_agent_id}, file=self.app.stdout, end='') return [], []
class AciDriverConfigMissingGatewayIp(n_exc.BadRequest): message = _("The ACI Driver config is missing a gateway_ip " "parameter for %(ext_net)s.")
class AciDriverConfigMissingSegmentationId(n_exc.BadRequest): message = _("The ACI Driver config is missing a segmentation_id " "parameter for %(ext_net)s.")
class UcsmConnectFailed(exceptions.NeutronException): message = _("Unable to connect to UCS Manager %(ucsm_ip)s. " "Reason: %(exc)s.")
class UcsmConfigReadFailed(exceptions.NeutronException): message = _("Unable to read config from UCS Manager %(ucsm_ip)s. " "Reason: %(exc)s.")
class InvalidCfgAgent(agent_exceptions.AgentNotFound): message = _("Agent %(agent_id)s is not a Cisco cfg agent or has been " "disabled")
class HostingDeviceSchedulingFailed(exceptions.Conflict): message = _("Failed to assign hosting device %(hosting_device_id)s to " "Cisco cfg agent %(agent_id)s.")
class DriverNotFound(DriverException): message = _("Driver not found for %(resource)s id:%(id)s.")
class DriverNotExist(DriverException): message = _("Driver %(driver)s does not exist.")
class CSR1kvUnknownValueException(DriverException): """CSR1kv Exception thrown when an unknown value is received.""" message = (_("Data in attribute: %(attribute)s does not correspond to " "expected value. Value received is %(value)s. "))
class CSR1kvMissingInterfaceException(DriverException): """Configuration exception thrown when modifying the running config.""" message = (_("Interface corresponding to port:%(id)s and mac-address:%(" "mac)s is missing in the CSR. Cannot proceed with interface" "config."))
from networking_cisco.plugins.cisco.common import cisco_constants from networking_cisco.plugins.cisco.db.device_manager import hd_models from networking_cisco.plugins.cisco.db.l3 import l3_models from networking_cisco.plugins.cisco.extensions import routertypeawarescheduler LOG = logging.getLogger(__name__) AGENT_TYPE_CFG = cisco_constants.AGENT_TYPE_CFG AGENT_TYPE_L3_CFG = cisco_constants.AGENT_TYPE_L3_CFG ROUTER_TYPE_AWARE_SCHEDULER_OPTS = [ cfg.StrOpt('router_type_aware_scheduler_driver', default='networking_cisco.plugins.cisco.l3.schedulers.' 'l3_routertype_aware_agent_scheduler.' 'L3RouterTypeAwareScheduler', help=_('Driver to use for router type-aware scheduling of ' 'router to a default L3 agent')), cfg.BoolOpt('auto_schedule', default=True, help=_('Set to True if routers are to be automatically ' 'scheduled by default')), cfg.BoolOpt('share_hosting_device', default=True, help=_('Set to True if routers can share hosts with routers ' 'owned by other tenants by default')), ] cfg.CONF.register_opts(ROUTER_TYPE_AWARE_SCHEDULER_OPTS, "routing") class L3RouterTypeAwareSchedulerDbMixin( l3_agentschedulers_db.L3AgentSchedulerDbMixin):
class ConnectionException(DriverException): """Connection exception when connecting to IOS XE hosting device.""" message = (_("Failed connecting to Device. Reason: %(reason)s. " "Connection params are User:%(user)s, Host:%(host)s, " "Port:%(port)s, Device timeout:%(timeout)s."))
class InitializationException(DriverException): """Exception when initialization of Routing Driver object.""" message = (_("Critical device parameter missing. Failed initializing " "routing driver object."))
class DriverNotSetForMissingParameter(DriverException): message = _("Driver cannot be set for missing parameter:%(p)s.")
class HostingDeviceAssignedToCfgAgent(exceptions.Conflict): message = _("The hosting device %(hosting_device_id)s is already assigned " "to Cisco cfg agent %(agent_id)s.")
class HAParamsMissingException(DriverException): """MissingParams exception thrown when HA params are missing""" message = (_("For router: %(r_id)s and port: %(p_id)s, HA_ENABLED is set, " "but port ha info is missing. Port details: %(port)s"))
class UcsmDisconnectFailed(exceptions.NeutronException): message = _("Disconnect to UCS Manager %(ucsm_ip)s failed. " "Reason: %(exc)s.")
from neutron.db import agentschedulers_db from neutron.extensions import agent as ext_agent from networking_cisco._i18n import _, _LI from networking_cisco.plugins.cisco.common import (cisco_constants as c_constants) from networking_cisco.plugins.cisco.db.device_manager.hd_models import ( HostingDevice) from networking_cisco.plugins.cisco.extensions import ciscocfgagentscheduler LOG = logging.getLogger(__name__) COMPOSITE_AGENTS_SCHEDULER_OPTS = [ cfg.IntOpt('cfg_agent_down_time', default=30, help=_('Seconds of no status update until a cfg agent ' 'is considered down.')), cfg.StrOpt('configuration_agent_scheduler_driver', default='networking_cisco.plugins.cisco.device_manager.' 'scheduler.hosting_device_cfg_agent_scheduler.' 'HostingDeviceCfgAgentScheduler', help=_('Driver to use for scheduling hosting device to a Cisco ' 'configuration agent')), cfg.IntOpt('cfg_agent_monitoring_interval', default=20, help=("Maximal time (in seconds) between checks of config " "agent status")) ] cfg.CONF.register_opts(COMPOSITE_AGENTS_SCHEDULER_OPTS, "general")
class UcsmConfigDeleteFailed(exceptions.NeutronException): message = _("Failed to delete %(config)s on UCS Manager %(ucsm_ip)s. " "Reason: %(exc)s.")
class DriverNotFound(nexception.NotFound): message = _("Driver %(driver)s does not exist")
DEBUG_STATS_MIN_WRITE_INTERVAL = 30 MONITOR_INTERVAL = 1 CLEANUP_INTERVAL = 30 STALE_REQUEST_TMO = 120 RECV_BUFFER_SIZE = 4096 NS_RELAY_PENDING = 'NS_RELAY_PENDING' NS_RELAY_RUNNING = 'NS_RELAY_RUNNING' NS_RELAY_DELETING = 'NS_RELAY_DELETING' NS_PREFIX = 'qdhcp' DNS_SERVER_PORT = 53 RLIMIT_NOFILE_LIMIT = 16384 OPTS = [ cfg.StrOpt('external_interface', default='lo', help=_('Interface for communicating with DHCP/DNS server.')), cfg.StrOpt('dns_server_addr', default='127.0.0.1', help=_('DNS server IP address.')), cfg.IntOpt('dns_server_port', default=53, help=_('DNS server UDP port number.')), cfg.BoolOpt('enable_dns_stats', default=False, help=_('Enable DNS stats.')), cfg.IntOpt('dns_stats_interval', default=60, help=_('DNS stats polling interval.')) ] class DnsRelayAgent(object):
# # 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_cisco._i18n import _ ml2_cisco_opts = [ cfg.StrOpt('vlan_name_prefix', default='q-', help=_("VLAN Name prefix")), cfg.BoolOpt('svi_round_robin', default=False, help=_("Distribute SVI interfaces over all switches")), cfg.StrOpt('managed_physical_network', help=_("The physical network managed by the switches.")), cfg.StrOpt('provider_vlan_name_prefix', default='p-', help=_("VLAN Name prefix for provider vlans")), cfg.BoolOpt('persistent_switch_config', default=False, help=_("To make Nexus configuration persistent")), cfg.BoolOpt('never_cache_ssh_connection', default=False, help=_("Prevent caching ssh connections to Nexus device")), cfg.IntOpt('switch_heartbeat_time', default=0, help=_("Periodic time to check switch connection. (0=disabled)")), cfg.BoolOpt('provider_vlan_auto_create', default=True, help=_('Provider VLANs are automatically created as needed ' 'on the Nexus switch')),
class AciDriverNoAciDriverInstalledOrConfigured(n_exc.BadRequest): message = _("The ACI plugin driver is either not installed or " "the neutron configuration is incorrect.")
class CiscoCfgAgent(manager.Manager): """Cisco Cfg Agent. This class defines a generic configuration agent for cisco devices which implement network services in the cloud backend. It is based on the (reference) l3-agent, but has been enhanced to support multiple services in addition to routing. The agent acts like as a container for services and does not do any service specific processing or configuration itself. All service specific processing is delegated to service helpers which the agent loads. Thus routing specific updates are processed by the routing service helper, firewall by firewall helper etc. A further layer of abstraction is implemented by using device drivers for encapsulating all configuration operations of a service on a device. Device drivers are specific to a particular device/service VM eg: CSR1kv. The main entry points in this class are the `process_services()` and `_backlog_task()` . """ target = oslo_messaging.Target(version='1.1') OPTS = [ cfg.IntOpt('rpc_loop_interval', default=10, help=_("Interval when the process_services() loop " "executes in seconds. This is when the config agent " "lets each service helper to process its neutron " "resources.")), cfg.StrOpt('routing_svc_helper_class', default='networking_cisco.plugins.cisco.cfg_agent.' 'service_helpers.routing_svc_helper.' 'RoutingServiceHelper', help=_("Path of the routing service helper class.")), cfg.BoolOpt('enable_heartbeat', default=False, help=_("If enabled, the agent will maintain a heartbeat " "against its hosting-devices. If a device dies " "and recovers, the agent will then trigger a " "configuration resync.")), ] def __init__(self, host, conf=None): self.conf = conf or cfg.CONF self._dev_status = device_status.DeviceStatus() self._dev_status.enable_heartbeat = ( self.conf.cfg_agent.enable_heartbeat) self.context = n_context.get_admin_context_without_session() self._initialize_rpc(host) self._initialize_service_helpers(host) self._start_periodic_tasks() super(CiscoCfgAgent, self).__init__(host=self.conf.host) def _initialize_rpc(self, host): self.devmgr_rpc = CiscoDeviceManagementApi( c_constants.DEVICE_MANAGER_PLUGIN, host) def _initialize_service_helpers(self, host): svc_helper_class = self.conf.cfg_agent.routing_svc_helper_class try: self.routing_service_helper = importutils.import_object( svc_helper_class, host, self.conf, self) except ImportError as e: LOG.warning( _LW("Error in loading routing service helper. Class " "specified is %(class)s. Reason:%(reason)s"), { 'class': self.conf.cfg_agent.routing_svc_helper_class, 'reason': e }) self.routing_service_helper = None def _start_periodic_tasks(self): self.loop = loopingcall.FixedIntervalLoopingCall(self.process_services) self.loop.start(interval=self.conf.cfg_agent.rpc_loop_interval) def after_start(self): LOG.info(_LI("Cisco cfg agent started")) def get_routing_service_helper(self): return self.routing_service_helper ## Periodic tasks ## @periodic_task.periodic_task def _backlog_task(self, context): """Process backlogged devices.""" LOG.debug("Processing backlog.") self._process_backlogged_hosting_devices(context) ## Main orchestrator ## @lockutils.synchronized('cisco-cfg-agent', 'neutron-') def process_services(self, device_ids=None, removed_devices_info=None): """Process services managed by this config agent. This method is invoked by any of three scenarios. 1. Invoked by a periodic task running every `RPC_LOOP_INTERVAL` seconds. This is the most common scenario. In this mode, the method is called without any arguments. 2. Called by the `_process_backlogged_hosting_devices()` as part of the backlog processing task. In this mode, a list of device_ids are passed as arguments. These are the list of backlogged hosting devices that are now reachable and we want to sync services on them. 3. Called by the `hosting_devices_removed()` method. This is when the config agent has received a notification from the plugin that some hosting devices are going to be removed. The payload contains the details of the hosting devices and the associated neutron resources on them which should be processed and removed. To avoid race conditions with these scenarios, this function is protected by a lock. This method goes on to invoke `process_service()` on the different service helpers. :param device_ids : List of devices that are now available and needs to be processed :param removed_devices_info: Info about the hosting devices which are going to be removed and details of the resources hosted on them. Expected Format: { 'hosting_data': {'hd_id1': {'routers': [id1, id2, ...]}, 'hd_id2': {'routers': [id3, id4, ...]}, ...}, 'deconfigure': True/False } :return: None """ LOG.debug("Processing services started") # Now we process only routing service, additional services will be # added in future if self.routing_service_helper: self.routing_service_helper.process_service( device_ids, removed_devices_info) else: LOG.warning(_LW("No routing service helper loaded")) LOG.debug("Processing services completed") def _process_backlogged_hosting_devices(self, context): """Process currently backlogged devices. Go through the currently backlogged devices and process them. For devices which are now reachable (compared to last time), we call `process_services()` passing the now reachable device's id. For devices which have passed the `hosting_device_dead_timeout` and hence presumed dead, execute a RPC to the plugin informing that. heartbeat revision res['reachable'] - hosting device went from Unknown to Active state process_services(...) res['revived'] - hosting device went from Dead to Active inform device manager that the hosting device is now responsive res['dead'] - hosting device went from Unknown to Dead inform device manager that the hosting device is non-responding :param context: RPC context :return: None """ res = self._dev_status.check_backlogged_hosting_devices() if res['reachable']: self.process_services(device_ids=res['reachable']) if res['revived']: LOG.debug("Reporting revived hosting devices: %s " % res['revived']) # trigger a sync only on the revived hosting-devices if (self.conf.cfg_agent.enable_heartbeat is True): self.process_services(device_ids=res['revived']) if res['dead']: LOG.debug("Reporting dead hosting devices: %s", res['dead']) self.devmgr_rpc.report_dead_hosting_devices(context, hd_ids=res['dead']) def agent_updated(self, context, payload): """Deal with agent updated RPC message.""" try: if payload['admin_state_up']: #TODO(hareeshp): implement agent updated handling pass except KeyError as e: LOG.error( _LE("Invalid payload format for received RPC message " "`agent_updated`. Error is %(error)s. Payload is " "%(payload)s"), { 'error': e, 'payload': payload }) def hosting_devices_assigned_to_cfg_agent(self, context, payload): """Deal with hosting devices assigned to this config agent.""" LOG.debug("Got hosting device assigned, payload: %s" % payload) try: if payload['hosting_device_ids']: #TODO(hareeshp): implement assignment of hosting devices self.routing_service_helper.fullsync = True except KeyError as e: LOG.error( _LE("Invalid payload format for received RPC message " "`hosting_devices_assigned_to_cfg_agent`. Error is " "%(error)s. Payload is %(payload)s"), { 'error': e, 'payload': payload }) def hosting_devices_unassigned_from_cfg_agent(self, context, payload): """Deal with hosting devices unassigned from this config agent.""" try: if payload['hosting_device_ids']: #TODO(hareeshp): implement unassignment of hosting devices pass except KeyError as e: LOG.error( _LE("Invalid payload format for received RPC message " "`hosting_devices_unassigned_from_cfg_agent`. Error " "is %(error)s. Payload is %(payload)s"), { 'error': e, 'payload': payload }) def hosting_devices_removed(self, context, payload): """Deal with hosting device removed RPC message.""" try: if payload['hosting_data']: if payload['hosting_data'].keys(): self.process_services(removed_devices_info=payload) except KeyError as e: LOG.error( _LE("Invalid payload format for received RPC message " "`hosting_devices_removed`. Error is %(error)s. " "Payload is %(payload)s"), { 'error': e, 'payload': payload }) def get_assigned_hosting_devices(self): context = n_context.get_admin_context_without_session() res = self.devmgr_rpc.get_hosting_devices_for_agent(context) return res def get_hosting_device_configuration(self, context, payload): LOG.debug('Processing request to fetching running config') hd_id = payload['hosting_device_id'] svc_helper = self.routing_service_helper if hd_id and svc_helper: LOG.debug('Fetching running config for %s' % hd_id) drv = svc_helper.driver_manager.get_driver_for_hosting_device( hd_id) rc = drv.get_configuration() if rc: LOG.debug('Fetched %(chars)d characters long running config ' 'for %(hd_id)s' % { 'chars': len(rc), 'hd_id': hd_id }) return rc LOG.debug('Unable to get running config') return
class AciDriverConfigMissingCidrExposed(n_exc.BadRequest): message = _("The ACI Driver config is missing a cidr_exposed " "parameter for %(ext_net)s.")
from neutron.agent.linux import dhcp from neutron.agent.linux import ip_lib from neutron.agent.linux import utils from oslo_config import cfg from oslo_log import log as logging from networking_cisco.plugins.cisco.cpnr import model from networking_cisco._i18n import _, _LE, _LW LOG = logging.getLogger(__name__) GREENPOOL_SIZE = 10 OPTS = [ cfg.StrOpt('http_server', default="localhost:8080", help=_('External HTTP server, should conform to ' '<server_name:port> format.')), cfg.StrOpt('http_username', default='cpnradmin', help=_('HTTP server username.')), cfg.StrOpt('http_password', default='cpnradmin', secret=True, help=_('HTTP server password.')), cfg.BoolOpt('insecure', default=False, help=_('Indicate if insecure mode is used. When set to ' 'true, SSL certificates are not verified.')), cfg.ListOpt('upstream_dns_servers', default=[], help=_('Comma-separated list of the DNS servers ' 'which will be used as forwarders.')),
class AciDriverConfigInvalidFileFormat(n_exc.BadRequest): message = _("The ACI Driver config file format is invalid")
class HostingDeviceNotAssignedToCfgAgent(exceptions.NotFound): message = _("The hosting device %(hosting_device_id)s is currently not " "assigned to Cisco cfg agent %(agent_id)s.")
class CSR1kvConfigException(DriverException): """Configuration exception thrown when modifying the running config.""" message = (_("Error executing snippet:%(snippet)s. " "Hosting device:%(dev_id)s Mgmt IP:%(ip)s " "ErrorType:%(type)s ErrorTag:%(tag)s Config string:%(" "confstr)s."))
class DriverExpectedKeyNotSetException(DriverException): """An attribute expected to be set by plugin is missing""" message = (_("Value for expected key: %(key)s is missing." "Driver cannot proceed"))