def main(): try: # Initialise the logging with default parameters. common.default_logging() # Load config # FIXME: old felix used argparse but that's not in Python 2.6, so # hard-coded path. try: config = Config("/etc/calico/felix.cfg") except: # Attempt to open a log file, ignoring any errors it gets, before # we raise the exception. try: common.complete_logging("/var/log/calico/felix.log", logging.DEBUG, logging.DEBUG, logging.DEBUG) except: pass raise _log.info("Felix initializing") gevent.spawn(_main_greenlet, config).join() # Should never return except BaseException: # Make absolutely sure that we exit by asking the OS to terminate our # process. We don't want to let a stray background thread keep us # alive. _log.exception("Felix exiting due to exception") os._exit(1) raise # Unreachable but keeps the linter happy about the broad except.
def _finish_update(self, final=False): """ Config has been completely read. Called twice - once after reading from environment and config file (so we should be able to access etcd), and once after reading from etcd (so we have all the config ready to go). Responsible for : - storing the parameters in the relevant fields in the structure - validating the configuration is valid (for this stage in the process) - updating logging parameters Note that we complete the logging even before etcd configuration changes are read. Hence, for example, if logging to file is turned on after reading environment variables and config file, then the log file is created and logging to it starts - even if later on etcd configuration turns the file off. That's because we must log if etcd configuration load fails, and not having the log file early enough is worse. :param final: Have we completed (rather than just read env and config file) """ self.ETCD_ADDR = self.parameters["EtcdAddr"].value self.HOSTNAME = self.parameters["FelixHostname"].value self.STARTUP_CLEANUP_DELAY = self.parameters[ "StartupCleanupDelay"].value self.RESYNC_INTERVAL = self.parameters["PeriodicResyncInterval"].value self.REFRESH_INTERVAL = self.parameters[ "IptablesRefreshInterval"].value self.METADATA_IP = self.parameters["MetadataAddr"].value self.METADATA_PORT = self.parameters["MetadataPort"].value self.IFACE_PREFIX = self.parameters["InterfacePrefix"].value self.DEFAULT_INPUT_CHAIN_ACTION = \ self.parameters["DefaultEndpointToHostAction"].value self.LOGFILE = self.parameters["LogFilePath"].value self.LOGLEVFILE = self.parameters["LogSeverityFile"].value self.LOGLEVSYS = self.parameters["LogSeveritySys"].value self.LOGLEVSCR = self.parameters["LogSeverityScreen"].value self.IP_IN_IP_ENABLED = self.parameters["IpInIpEnabled"].value self.IP_IN_IP_MTU = self.parameters["IpInIpMtu"].value self.REPORTING_INTERVAL_SECS = self.parameters[ "ReportingIntervalSecs"].value self.REPORTING_TTL_SECS = self.parameters["ReportingTTLSecs"].value self.REPORT_ENDPOINT_STATUS = \ self.parameters["EndpointReportingEnabled"].value self.ENDPOINT_REPORT_DELAY = \ self.parameters["EndpointReportingDelaySecs"].value self.MAX_IPSET_SIZE = self.parameters["MaxIpsetSize"].value self._validate_cfg(final=final) # Update logging. common.complete_logging(self.LOGFILE, self.LOGLEVFILE, self.LOGLEVSYS, self.LOGLEVSCR) if final: # Log configuration - the whole lot of it. for name, parameter in self.parameters.iteritems(): log.info("Parameter %s (%s) has value %r read from %s", name, parameter.description, parameter.value, parameter.active_source)
def _finish_update(self, final=False): """ Config has been completely read. Called twice - once after reading from environment and config file (so we should be able to access etcd), and once after reading from etcd (so we have all the config ready to go). Responsible for : - storing the parameters in the relevant fields in the structure - validating the configuration is valid (for this stage in the process) - updating logging parameters Note that we complete the logging even before etcd configuration changes are read. Hence, for example, if logging to file is turned on after reading environment variables and config file, then the log file is created and logging to it starts - even if later on etcd configuration turns the file off. That's because we must log if etcd configuration load fails, and not having the log file early enough is worse. :param final: Have we completed (rather than just read env and config file) """ self.ETCD_ADDR = self.parameters["EtcdAddr"].value self.HOSTNAME = self.parameters["FelixHostname"].value self.STARTUP_CLEANUP_DELAY = self.parameters["StartupCleanupDelay"].value self.RESYNC_INTERVAL = self.parameters["PeriodicResyncInterval"].value self.REFRESH_INTERVAL = self.parameters["IptablesRefreshInterval"].value self.METADATA_IP = self.parameters["MetadataAddr"].value self.METADATA_PORT = self.parameters["MetadataPort"].value self.IFACE_PREFIX = self.parameters["InterfacePrefix"].value self.DEFAULT_INPUT_CHAIN_ACTION = \ self.parameters["DefaultEndpointToHostAction"].value self.LOGFILE = self.parameters["LogFilePath"].value self.LOGLEVFILE = self.parameters["LogSeverityFile"].value self.LOGLEVSYS = self.parameters["LogSeveritySys"].value self.LOGLEVSCR = self.parameters["LogSeverityScreen"].value self.IP_IN_IP_ENABLED = self.parameters["IpInIpEnabled"].value self.IP_IN_IP_MTU = self.parameters["IpInIpMtu"].value self.REPORTING_INTERVAL_SECS = self.parameters["ReportingIntervalSecs"].value self.REPORTING_TTL_SECS = self.parameters["ReportingTTLSecs"].value self._validate_cfg(final=final) # Update logging. common.complete_logging(self.LOGFILE, self.LOGLEVFILE, self.LOGLEVSYS, self.LOGLEVSCR) if final: # Log configuration - the whole lot of it. for name, parameter in self.parameters.iteritems(): log.info("Parameter %s (%s) has value %r read from %s", name, parameter.description, parameter.value, parameter.active_source)
def _handle_config(self, msg): """ Handle config message from Felix. Called from the reader thread. """ complete_logging(msg[MSG_KEY_LOG_FILE], file_level=msg[MSG_KEY_SEV_FILE], syslog_level=msg[MSG_KEY_SEV_SYSLOG], stream_level=msg[MSG_KEY_SEV_SCREEN], gevent_in_use=False) self._config_received.set() _log.info("Received config from Felix: %s", msg)
def _handle_config(self, msg): """ Handle config message from Felix. Called from the reader thread. """ complete_logging(msg[MSG_KEY_LOG_FILE], file_level=msg[MSG_KEY_SEV_FILE], syslog_level=msg[MSG_KEY_SEV_SYSLOG], stream_level=msg[MSG_KEY_SEV_SCREEN], gevent_in_use=False) if msg[MSG_KEY_PROM_PORT]: _log.info("Prometheus metrics enabled, starting driver metrics" "server on port %s", msg[MSG_KEY_PROM_PORT]) start_http_server(msg[MSG_KEY_PROM_PORT]) self._config_received.set() _log.info("Received config from Felix: %s", msg)
def main(): # Initialise the logging with default parameters. common.default_logging(gevent_in_use=True) # Create configuration, reading defaults from file if it exists. parser = optparse.OptionParser() parser.add_option('-c', '--config-file', dest='config_file', help="configuration file to use", default="/etc/calico/felix.cfg") options, args = parser.parse_args() try: config = Config(options.config_file) except Exception: # Config loading error, and not just invalid parameters (from optparse) # as they generate a SystemExit. Attempt to open a log file, ignoring # any errors it gets, before we raise the exception. try: common.complete_logging("/var/log/calico/felix.log", logging.DEBUG, logging.DEBUG, logging.DEBUG, gevent_in_use=True) except Exception: pass # Log the exception with logging in whatever state we managed to get it # to, then reraise it, taking Felix down. _log.exception("Exception loading configuration") raise _log.info("Felix initializing") try: gevent.spawn(_main_greenlet, config).join() # Should never return except Exception: # Make absolutely sure that we exit by asking the OS to terminate our # process. We don't want to let a stray background thread keep us # alive. _log.exception("Felix exiting due to exception") os._exit(1) raise # Unreachable but keeps the linter happy about the broad except.
def load_config(self): _log.info("Waiting for etcd to be ready and for config to be present.") configured = False while not configured: self._reconnect() self.wait_for_ready() try: config_dict = self._load_config_dict() except (EtcdKeyNotFound, EtcdException): _log.exception("Failed to read config. Will retry.") gevent.sleep(RETRY_DELAY) continue self.config.update_config(config_dict) common.complete_logging(self.config.LOGFILE, self.config.LOGLEVFILE, self.config.LOGLEVSYS, self.config.LOGLEVSCR) configured = True
def _finish_update(self, final=False): """ Config has been completely read. Called twice - once after reading from environment and config file (so we should be able to access etcd), and once after reading from etcd (so we have all the config ready to go). Responsible for : - storing the parameters in the relevant fields in the structure - validating the configuration is valid (for this stage in the process) - updating logging parameters (if this is the final call) :param final: Have we completed (rather than just read env and config file) """ self.ETCD_ADDR = self.parameters["EtcdAddr"].value self.HOSTNAME = self.parameters["FelixHostname"].value self.STARTUP_CLEANUP_DELAY = self.parameters["StartupCleanupDelay"].value self.METADATA_IP = self.parameters["MetadataAddr"].value self.METADATA_PORT = self.parameters["MetadataPort"].value self.IFACE_PREFIX = self.parameters["InterfacePrefix"].value self.LOGFILE = self.parameters["LogFilePath"].value self.LOGLEVFILE = self.parameters["LogSeverityFile"].value self.LOGLEVSYS = self.parameters["LogSeveritySys"].value self.LOGLEVSCR = self.parameters["LogSeverityScreen"].value self._validate_cfg(final=final) if final: # Update logging. common.complete_logging(self.LOGFILE, self.LOGLEVFILE, self.LOGLEVSYS, self.LOGLEVSCR) # Log configuration - the whole lot of it. for name, parameter in self.parameters.iteritems(): log.info("Parameter %s (%s) has value %r read from %s", name, parameter.description, parameter.value, parameter.active_source)
def _finish_update(self, final=False): """ Config has been completely read. Called twice - once after reading from environment and config file (so we should be able to access etcd), and once after reading from etcd (so we have all the config ready to go). Responsible for : - storing the parameters in the relevant fields in the structure - validating the configuration is valid (for this stage in the process) - updating logging parameters Note that we complete the logging even before etcd configuration changes are read. Hence, for example, if logging to file is turned on after reading environment variables and config file, then the log file is created and logging to it starts - even if later on etcd configuration turns the file off. That's because we must log if etcd configuration load fails, and not having the log file early enough is worse. :param final: Have we completed (rather than just read env and config file) """ self.ETCD_ADDR = self.parameters["EtcdAddr"].value self.HOSTNAME = self.parameters["FelixHostname"].value self.ETCD_SCHEME = self.parameters["EtcdScheme"].value self.ETCD_KEY_FILE = self.parameters["EtcdKeyFile"].value self.ETCD_CERT_FILE = self.parameters["EtcdCertFile"].value self.ETCD_CA_FILE = self.parameters["EtcdCaFile"].value self.STARTUP_CLEANUP_DELAY = \ self.parameters["StartupCleanupDelay"].value self.RESYNC_INTERVAL = self.parameters["PeriodicResyncInterval"].value self.REFRESH_INTERVAL = \ self.parameters["IptablesRefreshInterval"].value self.METADATA_IP = self.parameters["MetadataAddr"].value self.METADATA_PORT = self.parameters["MetadataPort"].value self.IFACE_PREFIX = self.parameters["InterfacePrefix"].value self.DEFAULT_INPUT_CHAIN_ACTION = \ self.parameters["DefaultEndpointToHostAction"].value self.LOGFILE = self.parameters["LogFilePath"].value self.DRIVERLOGFILE = self.parameters["EtcdDriverLogFilePath"].value self.LOGLEVFILE = self.parameters["LogSeverityFile"].value self.LOGLEVSYS = self.parameters["LogSeveritySys"].value self.LOGLEVSCR = self.parameters["LogSeverityScreen"].value self.IP_IN_IP_ENABLED = self.parameters["IpInIpEnabled"].value self.IP_IN_IP_MTU = self.parameters["IpInIpMtu"].value self.IP_IN_IP_ADDR = self.parameters["IpInIpTunnelAddr"].value self.REPORTING_INTERVAL_SECS = \ self.parameters["ReportingIntervalSecs"].value self.REPORTING_TTL_SECS = self.parameters["ReportingTTLSecs"].value self.REPORT_ENDPOINT_STATUS = \ self.parameters["EndpointReportingEnabled"].value self.ENDPOINT_REPORT_DELAY = \ self.parameters["EndpointReportingDelaySecs"].value self.MAX_IPSET_SIZE = self.parameters["MaxIpsetSize"].value self.IPTABLES_GENERATOR_PLUGIN = \ self.parameters["IptablesGeneratorPlugin"].value self.IPTABLES_MARK_MASK =\ self.parameters["IptablesMarkMask"].value self._validate_cfg(final=final) # Now the config has been validated, generate the IPTables mark masks # we'll actually use internally. mark_mask = self.IPTABLES_MARK_MASK # Extract the least significant bit and use it as the accept mask. next_mask = mark_mask & (mark_mask - 1) self.IPTABLES_MARK_ACCEPT = "0x%x" % (mark_mask - next_mask) mark_mask = next_mask for plugin in self.plugins.itervalues(): # Plugins don't get loaded and registered until we've read config # from the environment and file. This means that they don't get # passed config until the final time through this function. assert final, "Plugins should only be loaded on the final " \ "config pass" plugin.store_and_validate_config(self) # Update logging. common.complete_logging(self.LOGFILE, self.LOGLEVFILE, self.LOGLEVSYS, self.LOGLEVSCR, gevent_in_use=True) if final: # Log configuration - the whole lot of it. for name, parameter in self.parameters.iteritems(): log.info("Parameter %s (%s) has value %r read from %s", name, parameter.description, parameter.value, parameter.active_source)
def __init__(self, config_path, context): # Get some configuration. self.config = Config(config_path) # Complete logging initialisation, now we have config. common.complete_logging(self.config.LOGFILE, self.config.LOGLEVFILE, self.config.LOGLEVSYS, self.config.LOGLEVSCR) # We have restarted and set up logs - tell the world. log.error("Felix starting (version: %s)", pkg_resources.get_distribution('calico')) # The ZeroMQ context for this Felix. self.zmq_context = context # The hostname of the machine on which this Felix is running. self.hostname = self.config.HOSTNAME # The sockets owned by this Felix, keyed off their socket type. self.sockets = {} # The endpoints managed by this Felix, keyed off their UUID. self.endpoints = {} # Set of UUIDs of endpoints that need to be retried (the interface did # not exist when the ENDPOINTCREATED was received). self.ep_retry = set() # Properties for handling resynchronization. # # resync_id is a UUID for the resync, passed on the API. It ensures # that we can correlate ENDPOINTCREATED requests with resyncs. If this # field is None, then no resync is in progress, and neither resync_recd # nor resync_expected is meaningful. self.resync_id = None # resync_recd counts all of the ENDPOINTCREATED requests received for # this resync, so we know when they have all arrived. self.resync_recd = None # resync_expected is the number of ENDPOINTCREATED requests that are # going to be sent for this resync, as reported in the resync # response. This is None if that response has not yet been received. self.resync_expected = None # resync_time is always defined once the first resync has been sent. It # is the time, in integer milliseconds since the epoch, of the sending # of the last resync. This is used to detect when it is time for # another resync. Note that integers in python automatically convert # from 32 to 64 bits when they are too large, and so we do not have to # worry about overflowing for many thousands of years yet. self.resync_time = None # Interface prefix. Only present after first resync response received. self.iface_prefix = None # Build a dispatch table for handling various messages. self.handlers = { Message.TYPE_HEARTBEAT: self.handle_heartbeat, Message.TYPE_EP_CR: self.handle_endpointcreated, Message.TYPE_EP_UP: self.handle_endpointupdated, Message.TYPE_EP_RM: self.handle_endpointdestroyed, Message.TYPE_RESYNC: self.handle_resyncstate, Message.TYPE_GET_ACL: self.handle_getaclstate, Message.TYPE_ACL_UPD: self.handle_aclupdate, } # Initiate our connections. self.connect_to_plugin() self.connect_to_acl_manager() # Grab a new iptables state. self.iptables_state = fiptables.TableState() # Begin full endpoint resync. We do not resync ACLs, since we resync # the ACLs for each endpoint when we are get an ENDPOINTCREATED in the # endpoint resync (and doing it now when we don't know of any endpoints # would just be a noop anyway). self.resync_endpoints()
def main(): # Parse command line args. parser = argparse.ArgumentParser(description='Calico ACL Manager') parser.add_argument('-c', '--config-file', dest='config_file') args = parser.parse_args() log_defaults = {'LogFilePath': None, 'LogSeverityFile': 'INFO', 'LogSeveritySys': 'ERROR', 'LogSeverityScreen': 'ERROR', 'LocalAddress': '*' } # Read config file. config = ConfigParser.ConfigParser(log_defaults) config.read(args.config_file or 'acl_manager.cfg') plugin_address = config.get('global', 'PluginAddress') local_address = config.get('global', 'LocalAddress') log_file_path = config.get('log', 'LogFilePath') log_file_level = config.get('log', 'LogSeverityFile') log_syslog_level = config.get('log', 'LogSeveritySys') log_stream_level = config.get('log', 'LogSeverityScreen') # Convert log level names into python log levels. loglevels = {"none": None, "debug": logging.DEBUG, "info": logging.INFO, "warn": logging.WARNING, "warning": logging.WARNING, "err": logging.ERROR, "error": logging.ERROR, "crit": logging.CRITICAL, "critical": logging.CRITICAL} file_level = loglevels[log_file_level.lower()] syslog_level = loglevels[log_syslog_level.lower()] stream_level = loglevels[log_stream_level.lower()] # Configure logging. common.default_logging() common.complete_logging(logfile=log_file_path, file_level=file_level, syslog_level=syslog_level, stream_level=stream_level) log.error("ACL Manager starting (version: %s)", pkg_resources.get_distribution('calico')) # Create ZeroMQ context. context = zmq.Context() log.info("pyzmq version is %s" % zmq.pyzmq_version()) # Create and start components. acl_store = ACLStore() network_store = NetworkStore() publisher = ACLPublisher(context, acl_store, local_address) acl_store.start(publisher) processor = RuleProcessor(acl_store, network_store) network_store.add_processor(processor) subscriber = NetworkSubscriber(context, network_store, plugin_address)
def _finish_update(self, final=False): """ Config has been completely read. Called twice so that plugins have a chance to add their config parameters. Responsible for : - storing the parameters in the relevant fields in the structure - validating the configuration is valid (for this stage in the process) - updating logging parameters :param final: Have we completed (rather than just read env and config file) """ self.HOSTNAME = self.parameters["FelixHostname"].value self.STARTUP_CLEANUP_DELAY = \ self.parameters["StartupCleanupDelay"].value self.RESYNC_INTERVAL = self.parameters["PeriodicResyncInterval"].value self.REFRESH_INTERVAL = \ self.parameters["IptablesRefreshInterval"].value self.HOST_IF_POLL_INTERVAL_SECS = \ self.parameters["HostInterfacePollInterval"].value self.METADATA_IP = self.parameters["MetadataAddr"].value self.METADATA_PORT = self.parameters["MetadataPort"].value self.IFACE_PREFIX = self.parameters["InterfacePrefix"].value self.DEFAULT_INPUT_CHAIN_ACTION = \ self.parameters["DefaultEndpointToHostAction"].value self.LOGFILE = self.parameters["LogFilePath"].value self.LOGLEVFILE = self.parameters["LogSeverityFile"].value self.LOGLEVSYS = self.parameters["LogSeveritySys"].value self.LOGLEVSCR = self.parameters["LogSeverityScreen"].value self.IP_IN_IP_ENABLED = self.parameters["IpInIpEnabled"].value self.IP_IN_IP_MTU = self.parameters["IpInIpMtu"].value self.IP_IN_IP_ADDR = self.parameters["IpInIpTunnelAddr"].value self.REPORTING_INTERVAL_SECS = \ self.parameters["ReportingIntervalSecs"].value self.REPORT_ENDPOINT_STATUS = \ self.parameters["EndpointReportingEnabled"].value self.MAX_IPSET_SIZE = self.parameters["MaxIpsetSize"].value self.IPTABLES_GENERATOR_PLUGIN = \ self.parameters["IptablesGeneratorPlugin"].value self.IPTABLES_MARK_MASK =\ self.parameters["IptablesMarkMask"].value self.PROM_METRICS_ENABLED = \ self.parameters["PrometheusMetricsEnabled"].value self.PROM_METRICS_DRIVER_PORT = \ self.parameters["DataplaneDriverPrometheusMetricsPort"].value self.FAILSAFE_INBOUND_PORTS = \ self.parameters["FailsafeInboundHostPorts"].value self.FAILSAFE_OUTBOUND_PORTS = \ self.parameters["FailsafeOutboundHostPorts"].value self.ACTION_ON_DROP = self.parameters["DropActionOverride"].value self.LOG_PREFIX = self.parameters["LogPrefix"].value self.IGNORE_LOOSE_RPF = self.parameters["IgnoreLooseRPF"].value self.IPV6_SUPPORT = self.parameters["Ipv6Support"].value.lower() self.CHAIN_INSERT_MODE = self.parameters["ChainInsertMode"].value self._validate_cfg(final=final) # Now calculate config options that rely on parameter validation. # Generate the IPTables mark masks we'll actually use internally. # From least to most significant bits of the mask we use them for: # - signalling that a profile accepted a packet # - signalling that a packet should move to the next policy tier. mark_mask = self.IPTABLES_MARK_MASK set_bits = find_set_bits(mark_mask) self.IPTABLES_MARK_ACCEPT = "0x%x" % next(set_bits) self.IPTABLES_MARK_NEXT_TIER = "0x%x" % next(set_bits) self.IPTABLES_MARK_ENDPOINTS = "0x%x" % next(set_bits) for plugin in self.plugins.itervalues(): # Plugins don't get loaded and registered until we've read config # from the environment and file. This means that they don't get # passed config until the final time through this function. assert final, "Plugins should only be loaded on the final " \ "config pass" plugin.store_and_validate_config(self) # Update logging. common.complete_logging(self.LOGFILE, self.LOGLEVFILE, self.LOGLEVSYS, self.LOGLEVSCR, gevent_in_use=True) if final: # Log configuration - the whole lot of it. for name, parameter in self.parameters.iteritems(): log.info("Parameter %s (%s) has value %r", name, parameter.description, parameter.value)
def _finish_update(self, final=False): """ Config has been completely read. Called twice - once after reading from environment and config file (so we should be able to access etcd), and once after reading from etcd (so we have all the config ready to go). Responsible for : - storing the parameters in the relevant fields in the structure - validating the configuration is valid (for this stage in the process) - updating logging parameters Note that we complete the logging even before etcd configuration changes are read. Hence, for example, if logging to file is turned on after reading environment variables and config file, then the log file is created and logging to it starts - even if later on etcd configuration turns the file off. That's because we must log if etcd configuration load fails, and not having the log file early enough is worse. :param final: Have we completed (rather than just read env and config file) """ self.HOSTNAME = self.parameters["FelixHostname"].value self.ETCD_SCHEME = self.parameters["EtcdScheme"].value self.ETCD_ENDPOINTS = self.parameters["EtcdEndpoints"].value self.ETCD_KEY_FILE = self.parameters["EtcdKeyFile"].value self.ETCD_CERT_FILE = self.parameters["EtcdCertFile"].value self.ETCD_CA_FILE = self.parameters["EtcdCaFile"].value self.STARTUP_CLEANUP_DELAY = \ self.parameters["StartupCleanupDelay"].value self.RESYNC_INTERVAL = self.parameters["PeriodicResyncInterval"].value self.REFRESH_INTERVAL = \ self.parameters["IptablesRefreshInterval"].value self.HOST_IF_POLL_INTERVAL_SECS = \ self.parameters["HostInterfacePollInterval"].value self.METADATA_IP = self.parameters["MetadataAddr"].value self.METADATA_PORT = self.parameters["MetadataPort"].value self.IFACE_PREFIX = self.parameters["InterfacePrefix"].value self.DEFAULT_INPUT_CHAIN_ACTION = \ self.parameters["DefaultEndpointToHostAction"].value self.LOGFILE = self.parameters["LogFilePath"].value self.DRIVERLOGFILE = self.parameters["EtcdDriverLogFilePath"].value self.LOGLEVFILE = self.parameters["LogSeverityFile"].value self.LOGLEVSYS = self.parameters["LogSeveritySys"].value self.LOGLEVSCR = self.parameters["LogSeverityScreen"].value self.IP_IN_IP_ENABLED = self.parameters["IpInIpEnabled"].value self.IP_IN_IP_MTU = self.parameters["IpInIpMtu"].value self.IP_IN_IP_ADDR = self.parameters["IpInIpTunnelAddr"].value self.REPORTING_INTERVAL_SECS = \ self.parameters["ReportingIntervalSecs"].value self.REPORTING_TTL_SECS = self.parameters["ReportingTTLSecs"].value self.REPORT_ENDPOINT_STATUS = \ self.parameters["EndpointReportingEnabled"].value self.ENDPOINT_REPORT_DELAY = \ self.parameters["EndpointReportingDelaySecs"].value self.MAX_IPSET_SIZE = self.parameters["MaxIpsetSize"].value self.IPTABLES_GENERATOR_PLUGIN = \ self.parameters["IptablesGeneratorPlugin"].value self.IPTABLES_MARK_MASK =\ self.parameters["IptablesMarkMask"].value self.PROM_METRICS_ENABLED = \ self.parameters["PrometheusMetricsEnabled"].value self.PROM_METRICS_PORT = \ self.parameters["PrometheusMetricsPort"].value self.PROM_METRICS_DRIVER_PORT = \ self.parameters["EtcdDriverPrometheusMetricsPort"].value self.FAILSAFE_INBOUND_PORTS = \ self.parameters["FailsafeInboundHostPorts"].value self.FAILSAFE_OUTBOUND_PORTS = \ self.parameters["FailsafeOutboundHostPorts"].value self.ACTION_ON_DROP = self.parameters["DropActionOverride"].value self.IGNORE_LOOSE_RPF = self.parameters["IgnoreLooseRPF"].value self.CLUSTER_GUID = self.parameters["ClusterGUID"].value self.USAGE_REPORT = self.parameters["UsageReportingEnabled"].value self._validate_cfg(final=final) # Now calculate config options that rely on parameter validation. # Determine the ETCD addresses to use. endpoints = [x.strip() for x in self.ETCD_ENDPOINTS.split(",")] if len(endpoints[0]) > 0: self.ETCD_SCHEME = endpoints[0].split("://")[0] self.ETCD_ADDRS = [e.split("://")[1] for e in endpoints] else: self.ETCD_SCHEME = self.parameters["EtcdScheme"].value self.ETCD_ADDRS = [self.parameters["EtcdAddr"].value] # Generate the IPTables mark masks we'll actually use internally. # From least to most significant bits of the mask we use them for: # - signalling that a profile accepted a packet # - signalling that a packet should move to the next policy tier. mark_mask = self.IPTABLES_MARK_MASK set_bits = find_set_bits(mark_mask) self.IPTABLES_MARK_ACCEPT = "0x%x" % next(set_bits) self.IPTABLES_MARK_NEXT_TIER = "0x%x" % next(set_bits) for plugin in self.plugins.itervalues(): # Plugins don't get loaded and registered until we've read config # from the environment and file. This means that they don't get # passed config until the final time through this function. assert final, "Plugins should only be loaded on the final " \ "config pass" plugin.store_and_validate_config(self) # Update logging. common.complete_logging(self.LOGFILE, self.LOGLEVFILE, self.LOGLEVSYS, self.LOGLEVSCR, gevent_in_use=True) if final: # Log configuration - the whole lot of it. for name, parameter in self.parameters.iteritems(): log.info("Parameter %s (%s) has value %r read from %s", name, parameter.description, parameter.value, parameter.active_source)
def _finish_update(self, final=False): """ Config has been completely read. Called twice - once after reading from environment and config file (so we should be able to access etcd), and once after reading from etcd (so we have all the config ready to go). Responsible for : - storing the parameters in the relevant fields in the structure - validating the configuration is valid (for this stage in the process) - updating logging parameters Note that we complete the logging even before etcd configuration changes are read. Hence, for example, if logging to file is turned on after reading environment variables and config file, then the log file is created and logging to it starts - even if later on etcd configuration turns the file off. That's because we must log if etcd configuration load fails, and not having the log file early enough is worse. :param final: Have we completed (rather than just read env and config file) """ self.HOSTNAME = self.parameters["FelixHostname"].value self.ETCD_SCHEME = self.parameters["EtcdScheme"].value self.ETCD_ENDPOINTS = self.parameters["EtcdEndpoints"].value self.ETCD_KEY_FILE = self.parameters["EtcdKeyFile"].value self.ETCD_CERT_FILE = self.parameters["EtcdCertFile"].value self.ETCD_CA_FILE = self.parameters["EtcdCaFile"].value self.STARTUP_CLEANUP_DELAY = \ self.parameters["StartupCleanupDelay"].value self.RESYNC_INTERVAL = self.parameters["PeriodicResyncInterval"].value self.REFRESH_INTERVAL = \ self.parameters["IptablesRefreshInterval"].value self.HOST_IF_POLL_INTERVAL_SECS = \ self.parameters["HostInterfacePollInterval"].value self.METADATA_IP = self.parameters["MetadataAddr"].value self.METADATA_PORT = self.parameters["MetadataPort"].value self.IFACE_PREFIX = self.parameters["InterfacePrefix"].value self.DEFAULT_INPUT_CHAIN_ACTION = \ self.parameters["DefaultEndpointToHostAction"].value self.LOGFILE = self.parameters["LogFilePath"].value self.DRIVERLOGFILE = self.parameters["EtcdDriverLogFilePath"].value self.LOGLEVFILE = self.parameters["LogSeverityFile"].value self.LOGLEVSYS = self.parameters["LogSeveritySys"].value self.LOGLEVSCR = self.parameters["LogSeverityScreen"].value self.IP_IN_IP_ENABLED = self.parameters["IpInIpEnabled"].value self.IP_IN_IP_MTU = self.parameters["IpInIpMtu"].value self.IP_IN_IP_ADDR = self.parameters["IpInIpTunnelAddr"].value self.REPORTING_INTERVAL_SECS = \ self.parameters["ReportingIntervalSecs"].value self.REPORTING_TTL_SECS = self.parameters["ReportingTTLSecs"].value self.REPORT_ENDPOINT_STATUS = \ self.parameters["EndpointReportingEnabled"].value self.ENDPOINT_REPORT_DELAY = \ self.parameters["EndpointReportingDelaySecs"].value self.MAX_IPSET_SIZE = self.parameters["MaxIpsetSize"].value self.IPTABLES_GENERATOR_PLUGIN = \ self.parameters["IptablesGeneratorPlugin"].value self.IPTABLES_MARK_MASK =\ self.parameters["IptablesMarkMask"].value self.PROM_METRICS_ENABLED = \ self.parameters["PrometheusMetricsEnabled"].value self.PROM_METRICS_PORT = \ self.parameters["PrometheusMetricsPort"].value self.PROM_METRICS_DRIVER_PORT = \ self.parameters["EtcdDriverPrometheusMetricsPort"].value self.FAILSAFE_INBOUND_PORTS = \ self.parameters["FailsafeInboundHostPorts"].value self.FAILSAFE_OUTBOUND_PORTS = \ self.parameters["FailsafeOutboundHostPorts"].value self._validate_cfg(final=final) # Now calculate config options that rely on parameter validation. # Determine the ETCD addresses to use. endpoints = [x.strip() for x in self.ETCD_ENDPOINTS.split(",")] if len(endpoints[0]) > 0: self.ETCD_SCHEME = endpoints[0].split("://")[0] self.ETCD_ADDRS = [e.split("://")[1] for e in endpoints] else: self.ETCD_SCHEME = self.parameters["EtcdScheme"].value self.ETCD_ADDRS = [self.parameters["EtcdAddr"].value] # Generate the IPTables mark masks we'll actually use internally. # From least to most significant bits of the mask we use them for: # - signalling that a profile accepted a packet # - signalling that a packet should move to the next policy tier. mark_mask = self.IPTABLES_MARK_MASK set_bits = find_set_bits(mark_mask) self.IPTABLES_MARK_ACCEPT = "0x%x" % next(set_bits) self.IPTABLES_MARK_NEXT_TIER = "0x%x" % next(set_bits) for plugin in self.plugins.itervalues(): # Plugins don't get loaded and registered until we've read config # from the environment and file. This means that they don't get # passed config until the final time through this function. assert final, "Plugins should only be loaded on the final " \ "config pass" plugin.store_and_validate_config(self) # Update logging. common.complete_logging(self.LOGFILE, self.LOGLEVFILE, self.LOGLEVSYS, self.LOGLEVSCR, gevent_in_use=True) if final: # Log configuration - the whole lot of it. for name, parameter in self.parameters.iteritems(): log.info("Parameter %s (%s) has value %r read from %s", name, parameter.description, parameter.value, parameter.active_source)