def delete(self, instance_uuid=None, instance_from_db_virt=None): db.add_event('instance', instance_uuid, 'API DELETE', None, None, None) instance_networks = [] for iface in list(db.get_instance_interfaces(instance_uuid)): if not iface['network_uuid'] in instance_networks: instance_networks.append(iface['network_uuid']) host_networks = [] for inst in list(db.get_instances(local_only=True)): if not inst['uuid'] == instance_uuid: for iface in db.get_instance_interfaces(inst['uuid']): if not iface['network_uuid'] in host_networks: host_networks.append(iface['network_uuid']) instance_from_db_virt.delete() for network in instance_networks: n = net.from_db(network) if n: if network in host_networks: with util.RecordedOperation('deallocate ip address', instance_from_db_virt) as _: n.update_dhcp() else: with util.RecordedOperation('remove network', n) as _: n.delete()
def _find_most_matching_networks(self, requested_networks, candidates): candidates_network_matches = {} for node in candidates: candidates_network_matches[node] = 0 present_networks = [] for inst in list(db.get_instances(only_node=node)): for iface in db.get_instance_interfaces(inst['uuid']): if not iface['network_uuid'] in present_networks: present_networks.append(iface['network_uuid']) for network in present_networks: if network in requested_networks: candidates_network_matches[node] += 1 candidates_by_network_matches = {} for node in candidates: matches = candidates_network_matches[node] candidates_by_network_matches.setdefault(matches, []) candidates_by_network_matches[matches].append(node) if len(candidates_by_network_matches) == 0: return candidates max_matches = max(candidates_by_network_matches.keys()) return candidates_by_network_matches[max_matches]
def delete(self): with util.RecordedOperation('delete domain', self) as _: try: self.power_off() instance = self._get_domain() instance.undefine() except Exception: pass with util.RecordedOperation('delete disks', self) as _: try: shutil.rmtree(self.instance_path) except Exception: pass with util.RecordedOperation('release network addreses', self) as _: for ni in db.get_instance_interfaces(self.db_entry['uuid']): with db.get_lock('sf/ipmanager/%s' % ni['network_uuid'], ttl=120) as _: ipm = db.get_ipmanager(ni['network_uuid']) ipm.release(ni['ipv4']) db.persist_ipmanager(ni['network_uuid'], ipm.save()) db.update_instance_state(self.db_entry['uuid'], 'deleted') db.free_console_port(self.db_entry['console_port']) db.free_console_port(self.db_entry['vdi_port'])
def _create_domain_xml(self): """Create the domain XML for the instance.""" if os.path.exists(self.xml_file): return with open( os.path.join(config.parsed.get('STORAGE_PATH'), 'libvirt.tmpl')) as f: t = jinja2.Template(f.read()) networks = [] for iface in list(db.get_instance_interfaces(self.db_entry['uuid'])): n = net.from_db(iface['network_uuid']) networks.append({ 'macaddr': iface['macaddr'], 'bridge': n.subst_dict()['vx_bridge'], 'model': iface['model'] }) # NOTE(mikal): the database stores memory allocations in MB, but the domain # XML takes them in KB. That wouldn't be worth a comment here if I hadn't # spent _ages_ finding a bug related to it. xml = t.render(uuid=self.db_entry['uuid'], memory=self.db_entry['memory'] * 1024, vcpus=self.db_entry['cpus'], disks=self.db_entry['block_devices']['devices'], networks=networks, instance_path=self.instance_path, console_port=self.db_entry['console_port'], vdi_port=self.db_entry['vdi_port']) with open(self.xml_file, 'w') as f: f.write(xml)
def delete(self): with util.RecordedOperation('delete domain', self): try: self.power_off() instance = self._get_domain() if instance: instance.undefine() except Exception as e: util.ignore_exception('instance delete', e) with util.RecordedOperation('delete disks', self): try: if os.path.exists(self.instance_path): shutil.rmtree(self.instance_path) except Exception as e: util.ignore_exception('instance delete', e) with util.RecordedOperation('release network addresses', self): for ni in db.get_instance_interfaces(self.db_entry['uuid']): db.update_network_interface_state(ni['uuid'], 'deleted') with db.get_lock('ipmanager', None, ni['network_uuid'], ttl=120, op='Instance delete'): ipm = db.get_ipmanager(ni['network_uuid']) ipm.release(ni['ipv4']) db.persist_ipmanager(ni['network_uuid'], ipm.save()) db.free_console_port(self.db_entry['console_port']) db.free_console_port(self.db_entry['vdi_port'])
def _create_domain_xml(self): """Create the domain XML for the instance.""" if os.path.exists(self.xml_file): return with open( os.path.join(config.parsed.get('STORAGE_PATH'), 'libvirt.tmpl')) as f: t = jinja2.Template(f.read()) networks = [] for iface in list(db.get_instance_interfaces(self.db_entry['uuid'])): n = net.from_db(iface['network_uuid']) networks.append({ 'macaddr': iface['macaddr'], 'bridge': n.subst_dict()['vx_bridge'] }) xml = t.render(uuid=self.db_entry['uuid'], memory=self.db_entry['memory'] * 1024, vcpus=self.db_entry['cpus'], disks=self.db_entry['block_devices']['devices'], networks=networks, network_model=config.parsed.get('NETWORK_MODEL'), instance_path=self.instance_path, console_port=self.db_entry['console_port'], vdi_port=self.db_entry['vdi_port']) with open(self.xml_file, 'w') as f: f.write(xml)
def restore_instances(): # Ensure all instances for this node are defined networks = [] instances = [] for inst in list( db.get_instances(only_node=config.parsed.get('NODE_NAME'))): for iface in db.get_instance_interfaces(inst['uuid']): if not iface['network_uuid'] in networks: networks.append(iface['network_uuid']) instances.append(inst['uuid']) with util.RecordedOperation('restore networks', None) as _: for network in networks: try: n = net.from_db(network) LOG.info('%s Restoring network' % n) n.create() n.ensure_mesh() n.update_dhcp() except Exception as e: LOG.error('%s Failed to restore network: %s' % (n, e)) with util.RecordedOperation('restore instances', None) as _: for instance in instances: try: i = virt.from_db(instance) LOG.info('%s Restoring instance' % i) i.create() except Exception as e: LOG.error('%s Failed to restore instance: %s' % (i, e)) db.update_instance_state(instance, 'error')
def instance_start(instance_uuid, network): log = LOG.withField('instance', instance_uuid) with db.get_lock('instance', None, instance_uuid, ttl=900, timeout=120, op='Instance start') as lock: instance = virt.from_db(instance_uuid) # Collect the networks nets = {} for netdesc in network: if netdesc['network_uuid'] not in nets: n = net.from_db(netdesc['network_uuid']) if not n: db.enqueue_instance_error(instance_uuid, 'missing network') return nets[netdesc['network_uuid']] = n # Create the networks with util.RecordedOperation('ensure networks exist', instance): for network_uuid in nets: n = nets[network_uuid] try: n.create() n.ensure_mesh() n.update_dhcp() except exceptions.DeadNetwork as e: log.withField( 'network', n).warning('Instance tried to use dead network') db.enqueue_instance_error( instance_uuid, 'tried to use dead network: %s' % e) return # Allocate console and VDI ports instance.allocate_instance_ports() # Now we can start the instance libvirt = util.get_libvirt() try: with util.RecordedOperation('instance creation', instance): instance.create(lock=lock) except libvirt.libvirtError as e: code = e.get_error_code() if code in (libvirt.VIR_ERR_CONFIG_UNSUPPORTED, libvirt.VIR_ERR_XML_ERROR): db.enqueue_instance_error(instance_uuid, 'instance failed to start: %s' % e) return for iface in db.get_instance_interfaces(instance_uuid): db.update_network_interface_state(iface['uuid'], 'created')
def delete(self, instance_uuid=None, instance_from_db=None, instance_from_db_virt=None): # Check if instance has already been deleted if instance_from_db['state'] == 'deleted': return error(404, 'instance not found') with db.get_lock('/sf/instance/%s' % instance_uuid) as _: db.add_event('instance', instance_uuid, 'api', 'delete', None, None) instance_networks = [] for iface in list(db.get_instance_interfaces(instance_uuid)): if not iface['network_uuid'] in instance_networks: instance_networks.append(iface['network_uuid']) db.update_network_interface_state(iface['uuid'], 'deleted') host_networks = [] for inst in list( db.get_instances( only_node=config.parsed.get('NODE_NAME'))): if not inst['uuid'] == instance_uuid: for iface in db.get_instance_interfaces(inst['uuid']): if not iface['network_uuid'] in host_networks: host_networks.append(iface['network_uuid']) instance_from_db_virt.delete() for network in instance_networks: n = net.from_db(network) if n: if network in host_networks: with util.RecordedOperation( 'deallocate ip address', instance_from_db_virt) as _: n.update_dhcp() else: with util.RecordedOperation('remove network', n) as _: n.delete()
def instance_delete(instance_uuid): with db.get_lock('instance', None, instance_uuid, timeout=120, op='Instance delete'): db.add_event('instance', instance_uuid, 'queued', 'delete', None, None) # Create list of networks used by instance instance_networks = [] for iface in list(db.get_instance_interfaces(instance_uuid)): if not iface['network_uuid'] in instance_networks: instance_networks.append(iface['network_uuid']) # Create list of networks used by all other instances host_networks = [] for inst in list( db.get_instances(only_node=config.parsed.get('NODE_NAME'))): if not inst['uuid'] == instance_uuid: for iface in db.get_instance_interfaces(inst['uuid']): if not iface['network_uuid'] in host_networks: host_networks.append(iface['network_uuid']) instance_from_db_virt = virt.from_db(instance_uuid) if instance_from_db_virt: instance_from_db_virt.delete() # Check each network used by the deleted instance for network in instance_networks: n = net.from_db(network) if n: # If network used by another instance, only update if network in host_networks: with util.RecordedOperation('deallocate ip address', instance_from_db_virt): n.update_dhcp() else: # Network not used by any other instance therefore delete with util.RecordedOperation('remove network', n): n.delete()
def run(self): while True: time.sleep(30) # We do not reap unused networks from the network node, as they might be # in use for instances on other hypervisor nodes. if config.parsed.get('NODE_IP') != config.parsed.get('NETWORK_NODE_IP'): host_networks = [] for inst in list(db.get_instances(only_node=config.parsed.get('NODE_NAME'))): for iface in db.get_instance_interfaces(inst['uuid']): if not iface['network_uuid'] in host_networks: host_networks.append(iface['network_uuid']) for network in host_networks: n = net.from_db(network) n.ensure_mesh()
def restore_instances(): # Ensure all instances for this node are defined networks = [] instances = [] for inst in list( db.get_instances(only_node=config.parsed.get('NODE_NAME'))): for iface in db.get_instance_interfaces(inst['uuid']): if not iface['network_uuid'] in networks: networks.append(iface['network_uuid']) instances.append(inst['uuid']) with util.RecordedOperation('restore networks', None): for network in networks: try: n = net.from_db(network) LOG.withObj(n).info('Restoring network') n.create() n.ensure_mesh() n.update_dhcp() except Exception as e: util.ignore_exception('restore network %s' % network, e) with util.RecordedOperation('restore instances', None): for instance in instances: try: with db.get_lock('instance', None, instance, ttl=120, timeout=120, op='Instance restore'): i = virt.from_db(instance) if not i: continue started = ['on', 'transition-to-on', 'initial', 'unknown'] if i.db_entry.get('power_state', 'unknown') not in started: continue LOG.withObj(i).info('Restoring instance') i.create() except Exception as e: util.ignore_exception('restore instance %s' % instance, e) db.enqueue_instance_error( instance, 'exception while restoring instance on daemon restart')
def instance_start(instance_uuid, network): with db.get_lock('instance', None, instance_uuid, ttl=900) as lock: instance = virt.from_db(instance_uuid) # Collect the networks nets = {} for netdesc in network: if netdesc['network_uuid'] not in nets: n = net.from_db(netdesc['network_uuid']) if not n: db.enqueue_instance_delete(config.parsed.get('NODE_NAME'), instance_uuid, 'error', 'missing network') return nets[netdesc['network_uuid']] = n # Create the networks with util.RecordedOperation('ensure networks exist', instance): for network_uuid in nets: n = nets[network_uuid] n.create() n.ensure_mesh() n.update_dhcp() # Now we can start the isntance libvirt = util.get_libvirt() try: with util.RecordedOperation('instance creation', instance): instance.create(lock=lock) except libvirt.libvirtError as e: code = e.get_error_code() if code in (libvirt.VIR_ERR_CONFIG_UNSUPPORTED, libvirt.VIR_ERR_XML_ERROR): db.enqueue_instance_delete(config.parsed.get('NODE_NAME'), instance_uuid, 'error', 'instance failed to start') return for iface in db.get_instance_interfaces(instance_uuid): db.update_network_interface_state(iface['uuid'], 'created')
def delete(self): with util.RecordedOperation('delete domain', self) as _: try: self.power_off() except: pass with util.RecordedOperation('delete disks', self) as _: try: shutil.rmtree(self.instance_path) except: pass with util.RecordedOperation('release network addreses', self) as _: for ni in db.get_instance_interfaces(self.db_entry['uuid']): n = net.from_db(ni['network_uuid']) n.ipmanager.release(ni['ipv4']) n.persist_ipmanager() db.delete_instance(self.db_entry['uuid'])
def _find_most_matching_networks(self, requested_networks, candidates): if not candidates: return [] # Find number of matching networks on each node candidates_network_matches = {} for node in candidates: candidates_network_matches[node] = 0 # Make a list of networks for the node present_networks = [] for inst in list(db.get_instances(only_node=node)): for iface in db.get_instance_interfaces(inst['uuid']): if not iface['network_uuid'] in present_networks: present_networks.append(iface['network_uuid']) # Count the requested networks present on this node for network in present_networks: if network in requested_networks: candidates_network_matches[node] += 1 # Store candidate nodes keyed by number of matches candidates_by_network_matches = {} for node in candidates: matches = candidates_network_matches[node] candidates_by_network_matches.setdefault(matches, []).append(node) # Find maximum matches of networks on a node max_matches = max(candidates_by_network_matches.keys()) # Check that the maximum is not just the network node. # (Network node always has every network.) net_node = db.get_network_node()['fqdn'] if (max_matches == 1 and candidates_by_network_matches[max_matches][0] == net_node): # No preference, all candidates are a reasonable choice return candidates # Return list of candidates that has maximum networks return candidates_by_network_matches[max_matches]
def restore_instances(): # Ensure all instances for this node are defined networks = [] instances = [] for inst in list(db.get_instances(local_only=True)): for iface in db.get_instance_interfaces(inst['uuid']): if not iface['network_uuid'] in networks: networks.append(iface['network_uuid']) instances.append(inst['uuid']) with util.RecordedOperation('restore networks', None) as _: for network in networks: LOG.info('Restoring network %s' % network) n = net.from_db(network) n.create() n.ensure_mesh() n.update_dhcp() with util.RecordedOperation('restore instances', None) as _: for instance in instances: LOG.info('Restoring instance %s' % instance) i = virt.from_db(instance) i.create()
def _make_config_drive(self, disk_path): """Create a config drive""" # NOTE(mikal): with a big nod at https://gist.github.com/pshchelo/378f3c4e7d18441878b9652e9478233f iso = pycdlib.PyCdlib() iso.new(interchange_level=4, joliet=True, rock_ridge='1.09', vol_ident='config-2') # We're only going to pretend to do the most recent OpenStack version iso.add_directory('/openstack', rr_name='openstack', joliet_path='/openstack') iso.add_directory('/openstack/2017-02-22', rr_name='2017-02-22', joliet_path='/openstack/2017-02-22') iso.add_directory('/openstack/latest', rr_name='latest', joliet_path='/openstack/latest') # meta_data.json md = json.dumps({ 'random_seed': base64.b64encode(os.urandom(512)).decode('ascii'), 'uuid': self.db_entry['uuid'], 'availability_zone': config.parsed.get('ZONE'), 'hostname': '%s.local' % self.db_entry['name'], 'launch_index': 0, 'devices': [], 'project_id': None, 'name': self.db_entry['name'], 'public_keys': { 'mykey': self.db_entry['ssh_key'] } }).encode('ascii') iso.add_fp(io.BytesIO(md), len(md), '/openstack/latest/meta_data.json;1', rr_name='meta_data.json', joliet_path='/openstack/latest/meta_data.json') iso.add_fp(io.BytesIO(md), len(md), '/openstack/2017-02-22/meta_data.json;2', rr_name='meta_data.json', joliet_path='/openstack/2017-02-22/meta_data.json') # user_data if self.db_entry['user_data']: user_data = base64.b64decode(self.db_entry['user_data']) iso.add_fp(io.BytesIO(user_data), len(user_data), '/openstack/latest/user_data', rr_name='user_data', joliet_path='/openstack/latest/user_data.json') iso.add_fp(io.BytesIO(user_data), len(user_data), '/openstack/2017-02-22/user_data', rr_name='user_data', joliet_path='/openstack/2017-02-22/user_data.json') # network_data.json nd = { 'links': [], 'networks': [], 'services': [{ 'address': '8.8.8.8', 'type': 'dns' }] } seen_networks = [] for iface in db.get_instance_interfaces(self.db_entry['uuid']): devname = 'eth%d' % iface['order'] nd['links'].append({ 'ethernet_mac_address': iface['macaddr'], 'id': devname, 'name': devname, 'mtu': 1450, 'type': 'vif', 'vif_id': iface['uuid'] }) if not iface['network_uuid'] in seen_networks: n = net.from_db(iface['network_uuid']) nd['networks'].append({ 'id': iface['network_uuid'], 'link': devname, 'type': 'ipv4', 'ip_address': iface['ipv4'], 'netmask': str(n.netmask), 'routes': [{ 'network': '0.0.0.0', 'netmask': '0.0.0.0', 'gateway': str(n.router) }], 'network_id': iface['network_uuid'] }) seen_networks.append(iface['network_uuid']) nd_encoded = json.dumps(nd).encode('ascii') iso.add_fp(io.BytesIO(nd_encoded), len(nd_encoded), '/openstack/latest/network_data.json;3', rr_name='network_data.json', joliet_path='/openstack/latest/vendor_data.json') iso.add_fp(io.BytesIO(nd_encoded), len(nd_encoded), '/openstack/2017-02-22/network_data.json;4', rr_name='network_data.json', joliet_path='/openstack/2017-02-22/vendor_data.json') # empty vendor_data.json and vendor_data2.json vd = '{}'.encode('ascii') iso.add_fp(io.BytesIO(vd), len(vd), '/openstack/latest/vendor_data.json;5', rr_name='vendor_data.json', joliet_path='/openstack/latest/vendor_data.json') iso.add_fp(io.BytesIO(vd), len(vd), '/openstack/2017-02-22/vendor_data.json;6', rr_name='vendor_data.json', joliet_path='/openstack/2017-02-22/vendor_data.json') iso.add_fp(io.BytesIO(vd), len(vd), '/openstack/latest/vendor_data2.json;7', rr_name='vendor_data2.json', joliet_path='/openstack/latest/vendor_data2.json') iso.add_fp(io.BytesIO(vd), len(vd), '/openstack/2017-02-22/vendor_data2.json;8', rr_name='vendor_data2.json', joliet_path='/openstack/2017-02-22/vendor_data2.json') # Dump to disk iso.write(disk_path) iso.close()
def post(self, name=None, cpus=None, memory=None, network=None, disk=None, ssh_key=None, user_data=None, placed_on=None, namespace=None, instance_uuid=None): global SCHEDULER # We need to sanitise the name so its safe for DNS name = re.sub(r'([^a-zA-Z0-9_\-])', '', name) if not namespace: namespace = get_jwt_identity() # If accessing a foreign namespace, we need to be an admin if get_jwt_identity() not in [namespace, 'system']: return error( 401, 'only admins can create resources in a different namespace') # The instance needs to exist in the DB before network interfaces are created if not instance_uuid: instance_uuid = str(uuid.uuid4()) db.add_event('instance', instance_uuid, 'uuid allocated', None, None, None) # Create instance object instance = virt.from_db(instance_uuid) if instance: if get_jwt_identity() not in [ instance.db_entry['namespace'], 'system' ]: LOG.info('instance(%s): instance not found, ownership test' % instance_uuid) return error(404, 'instance not found') if not instance: instance = virt.from_definition(uuid=instance_uuid, name=name, disks=disk, memory_mb=memory, vcpus=cpus, ssh_key=ssh_key, user_data=user_data, owner=namespace) if not SCHEDULER: SCHEDULER = scheduler.Scheduler() # Have we been placed? if not placed_on: candidates = SCHEDULER.place_instance(instance, network) if len(candidates) == 0: db.add_event('instance', instance_uuid, 'schedule', 'failed', None, 'insufficient resources') db.update_instance_state(instance_uuid, 'error') return error(507, 'insufficient capacity') placed_on = candidates[0] db.place_instance(instance_uuid, placed_on) db.add_event('instance', instance_uuid, 'placement', None, None, placed_on) else: try: candidates = SCHEDULER.place_instance(instance, network, candidates=[placed_on]) if len(candidates) == 0: db.add_event('instance', instance_uuid, 'schedule', 'failed', None, 'insufficient resources') db.update_instance_state(instance_uuid, 'error') return error(507, 'insufficient capacity') except scheduler.CandidateNodeNotFoundException as e: return error(404, 'node not found: %s' % e) # Have we been placed on a different node? if not placed_on == config.parsed.get('NODE_NAME'): body = flask_get_post_body() body['placed_on'] = placed_on body['instance_uuid'] = instance_uuid body['namespace'] = namespace token = util.get_api_token( 'http://%s:%d' % (placed_on, config.parsed.get('API_PORT')), namespace=namespace) r = requests.request('POST', 'http://%s:%d/instances' % (placed_on, config.parsed.get('API_PORT')), data=json.dumps(body), headers={ 'Authorization': token, 'User-Agent': util.get_user_agent() }) LOG.info('Returning proxied request: %d, %s' % (r.status_code, r.text)) resp = flask.Response(r.text, mimetype='application/json') resp.status_code = r.status_code return resp # Check we can get the required IPs nets = {} allocations = {} def error_with_cleanup(status_code, message): for network_uuid in allocations: n = net.from_db(network_uuid) for addr, _ in allocations[network_uuid]: with db.get_lock('sf/ipmanager/%s' % n.uuid, ttl=120) as _: ipm = db.get_ipmanager(n.uuid) ipm.release(addr) db.persist_ipmanager(n.uuid, ipm.save()) return error(status_code, message) order = 0 if network: for netdesc in network: if 'network_uuid' not in netdesc or not netdesc['network_uuid']: return error_with_cleanup(404, 'network not specified') if netdesc['network_uuid'] not in nets: n = net.from_db(netdesc['network_uuid']) if not n: return error_with_cleanup( 404, 'network %s not found' % netdesc['network_uuid']) nets[netdesc['network_uuid']] = n n.create() with db.get_lock('sf/ipmanager/%s' % netdesc['network_uuid'], ttl=120) as _: db.add_event('network', netdesc['network_uuid'], 'allocate address', None, None, instance_uuid) allocations.setdefault(netdesc['network_uuid'], []) ipm = db.get_ipmanager(netdesc['network_uuid']) if 'address' not in netdesc or not netdesc['address']: netdesc['address'] = ipm.get_random_free_address() else: if not ipm.reserve(netdesc['address']): return error_with_cleanup( 409, 'address %s in use' % netdesc['address']) db.persist_ipmanager(netdesc['network_uuid'], ipm.save()) allocations[netdesc['network_uuid']].append( (netdesc['address'], order)) if 'model' not in netdesc or not netdesc['model']: netdesc['model'] = 'virtio' db.create_network_interface(str(uuid.uuid4()), netdesc, instance_uuid, order) order += 1 # Initialise metadata db.persist_metadata('instance', instance_uuid, {}) # Now we can start the instance with db.get_lock('sf/instance/%s' % instance.db_entry['uuid'], ttl=900) as lock: with util.RecordedOperation('ensure networks exist', instance) as _: for network_uuid in nets: n = nets[network_uuid] n.ensure_mesh() n.update_dhcp() with util.RecordedOperation('instance creation', instance) as _: instance.create(lock=lock) for iface in db.get_instance_interfaces(instance.db_entry['uuid']): db.update_network_interface_state(iface['uuid'], 'created') return db.get_instance(instance_uuid)
def get(self, instance_uuid=None, instance_from_db=None): db.add_event('instance', instance_uuid, 'api', 'get interfaces', None, None) return list(db.get_instance_interfaces(instance_uuid))
def _maintain_networks(self): LOG.info('Maintaining networks') # Discover what networks are present _, _, vxid_to_mac = util.discover_interfaces() # Determine what networks we should be on host_networks = [] seen_vxids = [] if not util.is_network_node(): # For normal nodes, just the ones we have instances for for inst in list(db.get_instances(only_node=config.parsed.get('NODE_NAME'))): for iface in db.get_instance_interfaces(inst['uuid']): if not iface['network_uuid'] in host_networks: host_networks.append(iface['network_uuid']) else: # For network nodes, its all networks for n in db.get_networks(): host_networks.append(n['uuid']) # Network nodes also look for interfaces for absent instances # and delete them for ni in db.get_network_interfaces(n['uuid']): inst = db.get_instance(ni['instance_uuid']) if (not inst or inst.get('state', 'unknown') in ['deleted', 'error', 'unknown']): db.hard_delete_network_interface(ni['uuid']) LOG.withInstance( ni['instance_uuid']).withNetworkInterface( ni['uuid']).info('Hard deleted stray network interface') # Ensure we are on every network we have a host for for network in host_networks: try: n = net.from_db(network) if not n: continue if n.db_entry['state_updated'] - time.time() < 60: # Network state changed in the last minute, punt for now continue if not n.is_okay(): LOG.withObj(n).info('Recreating not okay network') n.create() n.ensure_mesh() seen_vxids.append(n.vxlan_id) except exceptions.LockException as e: LOG.warning( 'Failed to acquire lock while maintaining networks: %s' % e) # Determine if there are any extra vxids extra_vxids = set(vxid_to_mac.keys()) - set(seen_vxids) # Delete "deleted" SF networks and log unknown vxlans if extra_vxids: LOG.withField('vxids', extra_vxids).warning( 'Extra vxlans present!') # Determine the network uuids for those vxids # vxid_to_uuid = {} # for n in db.get_networks(): # vxid_to_uuid[n['vxid']] = n['uuid'] # for extra in extra_vxids: # if extra in vxid_to_uuid: # with db.get_lock('network', None, vxid_to_uuid[extra], # ttl=120, op='Network reap VXLAN'): # n = net.from_db(vxid_to_uuid[extra]) # n.delete() # LOG.info('Extra vxlan %s (network %s) removed.' # % (extra, vxid_to_uuid[extra])) # else: # LOG.error('Extra vxlan %s does not map to any network.' # % extra) # And record vxids in the database db.persist_node_vxid_mapping( config.parsed.get('NODE_NAME'), vxid_to_mac)
def get(self, instance_uuid=None, instance_from_db=None): return list(db.get_instance_interfaces(instance_uuid))