Esempio n. 1
0
    def wrapper(*args, **kwargs):
        if 'network_uuid' in kwargs:
            kwargs['network_from_db'] = db.get_network(
                kwargs['network_uuid'])
        if not kwargs.get('network_from_db'):
            return error(404, 'network not found')

        return func(*args, **kwargs)
Esempio n. 2
0
def from_db(uuid):
    dbnet = db.get_network(uuid)
    if not dbnet:
        return None
    if dbnet['state'] == 'deleted':
        LOG.withNetwork(uuid).info('Network is deleted, returning None.')
        return None
    return Network(dbnet)
Esempio n. 3
0
    def wrapper(*args, **kwargs):
        if 'network_uuid' in kwargs:
            kwargs['network_from_db'] = db.get_network(kwargs['network_uuid'])
        if not kwargs.get('network_from_db'):
            logutil.info([net.ThinNetwork(kwargs['network_uuid'])],
                         'Network not found, missing or deleted')
            return error(404, 'network not found')

        return func(*args, **kwargs)
Esempio n. 4
0
    def wrapper(*args, **kwargs):
        if 'network_uuid' in kwargs:
            kwargs['network_from_db'] = db.get_network(kwargs['network_uuid'])
        if not kwargs.get('network_from_db'):
            LOG.info('network(%s): network not found, genuinely missing' %
                     kwargs['network_uuid'])
            return error(404, 'network not found')

        return func(*args, **kwargs)
Esempio n. 5
0
    def is_dead(self):
        """Check if the network is deleted or being deleted, or in error.

        First, update the object model to the ensure latest configuration. Some
        callers will wait on a lock before calling this function. In this case
        we definitely need to update the in-memory object model.
        """
        # TODO(andy): To be improved when object model mirrors Image class
        self.db_entry = db.get_network(self.db_entry['uuid'])

        return self.db_entry['state'] in ('deleted', 'deleting', 'error')
Esempio n. 6
0
def from_db(uuid):
    dbnet = db.get_network(uuid)
    if not dbnet:
        return None

    return Network(uuid=dbnet['uuid'],
                   vxlan_id=dbnet['vxid'],
                   provide_dhcp=dbnet['provide_dhcp'],
                   provide_nat=dbnet['provide_nat'],
                   ipblock=dbnet['netblock'],
                   physical_nic=config.parsed.get('NODE_EGRESS_NIC'),
                   floating_gateway=dbnet['floating_gateway'],
                   namespace=dbnet['namespace'])
Esempio n. 7
0
def from_db(uuid):
    # TODO(andy): The whole system of unlocked in-memory objects needs to be
    # revisited. This lock avoids the network being deleted between the DB load
    # in the get_network() call and Network.__init__() loading the IPManager
    # from the DB. Under extreme load testing, instance starts on the same
    # network will have multi-second start delays due to lock contention .
    with db.get_lock('network',
                     None,
                     uuid,
                     ttl=10,
                     timeout=120,
                     op='Object load from DB'):
        dbnet = db.get_network(uuid)
        if not dbnet:
            return None
        if dbnet['state'] in ('deleted', 'deleting'):
            LOG.withNetwork(uuid).info('Network is deleted, returning None.')
            return None
        return Network(dbnet)
Esempio n. 8
0
def from_db(uuid):
    dbnet = db.get_network(uuid)
    if not dbnet:
        return None

    n = Network(uuid=dbnet['uuid'],
                vxlan_id=dbnet['vxid'],
                provide_dhcp=dbnet['provide_dhcp'],
                provide_nat=dbnet['provide_nat'],
                ipblock=dbnet['netblock'],
                physical_nic=config.parsed.get('NODE_EGRESS_NIC'),
                floating_gateway=dbnet['floating_gateway'],
                namespace=dbnet['namespace'])

    if dbnet['state'] == 'deleted':
        logutil.info([n], 'Netowrk is deleted, returning None.')
        return None

    return n
Esempio n. 9
0
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()
Esempio n. 10
0
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')))