def main(): global DAEMON_IMPLEMENTATIONS global DAEMON_PIDS setproctitle.setproctitle(daemon.process_name('main')) # Log configuration on startup for key, value in config.dict().items(): LOG.info('Configuration item %s = %s' % (key, value)) daemon.set_log_level(LOG, 'main') # Check in early and often, also reset processing queue items db.clear_stale_locks() db.see_this_node() db.restart_queues() def _start_daemon(d): pid = os.fork() if pid == 0: DAEMON_IMPLEMENTATIONS[d].Monitor(d).run() DAEMON_PIDS[pid] = d LOG.withField('pid', pid).info('Started %s' % d) # Resource usage publisher, we need this early because scheduling decisions # might happen quite early on. _start_daemon('resources') # If I am the network node, I need some setup if util.is_network_node(): # Bootstrap the floating network in the Networks table floating_network = db.get_network('floating') if not floating_network: db.create_floating_network(config.get('FLOATING_NETWORK')) floating_network = net.from_db('floating') subst = { 'physical_bridge': util.get_safe_interface_name('phy-br-%s' % config.get('NODE_EGRESS_NIC')), 'physical_nic': config.get('NODE_EGRESS_NIC') } if not util.check_for_interface(subst['physical_bridge']): # NOTE(mikal): Adding the physical interface to the physical bridge # is considered outside the scope of the orchestration software as # it will cause the node to lose network connectivity. So instead # all we do is create a bridge if it doesn't exist and the wire # everything up to it. We can do egress NAT in that state, even if # floating IPs don't work. with util.RecordedOperation('create physical bridge', None): # No locking as read only ipm = db.get_ipmanager('floating') subst['master_float'] = ipm.get_address_at_index(1) subst['netmask'] = ipm.netmask util.create_interface(subst['physical_bridge'], 'bridge', '') util.execute(None, 'ip link set %(physical_bridge)s up' % subst) util.execute( None, 'ip addr add %(master_float)s/%(netmask)s ' 'dev %(physical_bridge)s' % subst) util.execute( None, 'iptables -A FORWARD -o %(physical_nic)s ' '-i %(physical_bridge)s -j ACCEPT' % subst) util.execute( None, 'iptables -A FORWARD -i %(physical_nic)s ' '-o %(physical_bridge)s -j ACCEPT' % subst) util.execute( None, 'iptables -t nat -A POSTROUTING ' '-o %(physical_nic)s -j MASQUERADE' % subst) def _audit_daemons(): running_daemons = [] for pid in DAEMON_PIDS: running_daemons.append(DAEMON_PIDS[pid]) for d in DAEMON_IMPLEMENTATIONS: if d not in running_daemons: _start_daemon(d) for d in DAEMON_PIDS: if not psutil.pid_exists(d): LOG.warning('%s pid is missing, restarting' % DAEMON_PIDS[d]) _start_daemon(DAEMON_PIDS[d]) _audit_daemons() restore_instances() while True: time.sleep(10) wpid, _ = os.waitpid(-1, os.WNOHANG) while wpid != 0: LOG.warning('%s died (pid %d)' % (DAEMON_PIDS.get(wpid, 'unknown'), wpid)) del DAEMON_PIDS[wpid] wpid, _ = os.waitpid(-1, os.WNOHANG) _audit_daemons() db.see_this_node()
def main(): # Log configuration on startup for key in config.parsed.config: LOG.info('Configuration item %s = %s' % (key, config.parsed.get(key))) # Check in early and often db.see_this_node() # Resource usage publisher, we need this early because scheduling decisions # might happen quite early on. resource_pid = os.fork() if resource_pid == 0: resource_daemon.monitor().run() # If I am the network node, I need some setup if config.parsed.get('NODE_IP') == config.parsed.get('NETWORK_NODE_IP'): # Bootstrap the floating network in the Networks table floating_network = db.get_network('floating') if not floating_network: db.create_floating_network(config.parsed.get('FLOATING_NETWORK')) floating_network = net.from_db('floating') subst = { 'physical_bridge': 'phy-br-%s' % config.parsed.get('NODE_EGRESS_NIC'), 'physical_nic': config.parsed.get('NODE_EGRESS_NIC') } if not util.check_for_interface(subst['physical_bridge']): # NOTE(mikal): Adding the physical interface to the physical bridge # is considered outside the scope of the orchestration software as it # will cause the node to lose network connectivity. So instead all we # do is create a bridge if it doesn't exist and the wire everything up # to it. We can do egress NAT in that state, even if floating IPs # don't work. with util.RecordedOperation('create physical bridge', 'startup') as _: # No locking as read only ipm = db.get_ipmanager('floating') subst['master_float'] = ipm.get_address_at_index(1) subst['netmask'] = ipm.netmask processutils.execute( 'ip link add %(physical_bridge)s type bridge' % subst, shell=True) processutils.execute('ip link set %(physical_bridge)s up' % subst, shell=True) processutils.execute( 'ip addr add %(master_float)s/%(netmask)s dev %(physical_bridge)s' % subst, shell=True) processutils.execute( 'iptables -A FORWARD -o %(physical_nic)s -i %(physical_bridge)s -j ACCEPT' % subst, shell=True) processutils.execute( 'iptables -A FORWARD -i %(physical_nic)s -o %(physical_bridge)s -j ACCEPT' % subst, shell=True) processutils.execute( 'iptables -t nat -A POSTROUTING -o %(physical_nic)s -j MASQUERADE' % subst, shell=True) # Network mesh maintenance net_pid = os.fork() if net_pid == 0: net_daemon.monitor().run() # Old object deleter cleaner_pid = os.fork() if cleaner_pid == 0: cleaner_daemon.monitor().run() # REST API external_api_pid = os.fork() if external_api_pid == 0: external_api_daemon.monitor().run() # Triggers trigger_pid = os.fork() if trigger_pid == 0: trigger_daemon.monitor().run() setproctitle.setproctitle('sf main') LOG.info('network monitor pid is %d' % net_pid) LOG.info('external api pid is %d' % external_api_pid) LOG.info('resources monitor pid is %d' % resource_pid) LOG.info('cleaner pid is %d' % cleaner_pid) LOG.info('trigger pid is %d' % trigger_pid) restore_instances() procnames = { external_api_pid: 'external api', net_pid: 'network monitor', resource_pid: 'resource monitor', cleaner_pid: 'cleaner' } while True: time.sleep(10) wpid, _ = os.waitpid(-1, os.WNOHANG) if wpid != 0: LOG.warning('Subprocess %d (%s) died' % (wpid, procnames.get(wpid, 'unknown')))