From 8a6d5126612ea5360d4331f6c344b1f9f8155218 Mon Sep 17 00:00:00 2001 From: Scott Baker Date: Wed, 7 Aug 2013 18:57:15 -0700 Subject: [PATCH] save_network, delete_network, and refresh_networks functions --- planetstack/openstack/driver.py | 30 +++++-- planetstack/openstack/manager.py | 149 ++++++++++++++++++++++++++++++- 2 files changed, 168 insertions(+), 11 deletions(-) diff --git a/planetstack/openstack/driver.py b/planetstack/openstack/driver.py index b6b6d48..c4f2fd6 100644 --- a/planetstack/openstack/driver.py +++ b/planetstack/openstack/driver.py @@ -18,12 +18,12 @@ class OpenStackDriver: else: self.shell = OpenStackClient() - def create_role(self, name): + def create_role(self, name): roles = self.shell.keystone.roles.findall(name=name) if not roles: role = self.shell.keystone.roles.create(name) else: - role = roles[0] + role = roles[0] return role def delete_role(self, filter): @@ -56,7 +56,7 @@ class OpenStackDriver: for tenant in tenants: # nova does not automatically delete the tenant's instances # so we manually delete instances before deleteing the tenant - instances = self.shell.nova_db.instance_get_all_by_filters(ctx, + instances = self.shell.nova_db.instance_get_all_by_filters(ctx, {'project_id': tenant.id}, 'id', 'asc') client = OpenStackClient(tenant=tenant.name) driver = OpenStackDriver(client=client) @@ -210,7 +210,7 @@ class OpenStackDriver: for snet in subnets: if snet['cidr'] == cidr_ip and snet['network_id'] == network_id: subnet = snet - + if not subnet: allocation_pools = [{'start': start, 'end': end}] subnet = {'subnet': {'name': name, @@ -218,7 +218,7 @@ class OpenStackDriver: 'ip_version': ip_version, 'cidr': cidr_ip, 'dns_nameservers': ['8.8.8.8', '8.8.4.4'], - 'allocation_pools': allocation_pools}} + 'allocation_pools': allocation_pools}} subnet = self.shell.quantum.create_subnet(subnet)['subnet'] self.add_external_route(subnet) # TODO: Add route to external network @@ -328,9 +328,22 @@ class OpenStackDriver: keys = self.shell.nova.keypairs.findall(id=id) for key in keys: self.shell.nova.keypairs.delete(key) - return 1 + return 1 + + def get_private_networks(self, tenant=None): + if not tenant: + tenant = self.shell.nova.tenant + tenant = self.shell.keystone.tenants.find(name=tenant) + search_opts = {"tenant_id": tenant.id, "shared": False} + private_networks = self.shell.quantum.list_networks(**search_opts) + return private_networks + + def get_shared_networks(self): + search_opts = {"shared": True} + shared_networks = self.shell.quantum.list_networks(**search_opts) + return shared_networks - def spawn_instance(self, name, key_name=None, hostname=None, image_id=None, security_group=None, pubkeys=[]): + def spawn_instance(self, name, key_name=None, hostname=None, image_id=None, security_group=None, pubkeys=[], networks=None): flavor_name = self.config.nova_default_flavor flavor = self.shell.nova.flavors.find(name=flavor_name) #if not image: @@ -354,7 +367,8 @@ class OpenStackDriver: security_group = security_group, files=files, scheduler_hints=hints, - availability_zone=availability_zone) + availability_zone=availability_zone, + networks=networks) return server def destroy_instance(self, id): diff --git a/planetstack/openstack/manager.py b/planetstack/openstack/manager.py index 3ae7dea..7990269 100644 --- a/planetstack/openstack/manager.py +++ b/planetstack/openstack/manager.py @@ -301,17 +301,35 @@ class OpenStackManager: #del_route = 'route del -net %s' % self.cidr #commands.getstatusoutput(del_route) + def get_requested_networks(self, slice): + network_ids = [x.network_id for x in slice.networks.all()] + + if slice.network_id is not None: + network_ids.append(slice.network_id) + + networks = [] + for network_id in network_ids: + networks.append({"uuid": network_id}) + + return networks + @require_enabled def save_sliver(self, sliver): if not sliver.instance_id: + if (sliver.slice.name == "smbaker-slice-8") or (sliver.slice.name.startswith("smbaker-slice-net")): + # only inflict this pain on myself, for now... + requested_networks = self.get_requested_networks(sliver.slice) + else: + requested_networks = None slice_memberships = SliceMembership.objects.filter(slice=sliver.slice) pubkeys = [sm.user.public_key for sm in slice_memberships if sm.user.public_key] - pubkeys.append(sliver.creator.public_key) + pubkeys.append(sliver.creator.public_key) instance = self.driver.spawn_instance(name=sliver.name, key_name = sliver.creator.keyname, image_id = sliver.image.image_id, hostname = sliver.node.name, - pubkeys = pubkeys ) + pubkeys = pubkeys, + networks = requested_networks ) sliver.instance_id = instance.id sliver.instance_name = getattr(instance, 'OS-EXT-SRV-ATTR:instance_name') @@ -368,7 +386,7 @@ class OpenStackManager: from core.models.image import Image # collect local images images = Image.objects.all() - images_dict = {} + images_dict = {} for image in images: images_dict[image.name] = image @@ -391,4 +409,129 @@ class OpenStackManager: old_image_names = set(images_dict.keys()).difference(glance_images_dict.keys()) Image.objects.filter(name__in=old_image_names).delete() + @require_enabled + def save_network(self, network): + if not network.network_id: + network_name = network.name + + # create network + os_network = self.driver.create_network(network_name) + network.network_id = os_network['id'] + + # create router + router = self.driver.create_router(network_name) + network.router_id = router['id'] + + # create subnet + next_subnet = self.get_next_subnet() + cidr = str(next_subnet.cidr) + ip_version = next_subnet.version + start = str(next_subnet[2]) + end = str(next_subnet[-2]) + subnet = self.driver.create_subnet(name=network_name, + network_id = network.network_id, + cidr_ip = cidr, + ip_version = ip_version, + start = start, + end = end) + network.subnet = cidr + network.subnet_id = subnet['id'] + # add subnet as interface to slice's router + self.driver.add_router_interface(router['id'], subnet['id']) + # add external route + self.driver.add_external_route(subnet) + + network.save() + network.enacted = datetime.now() + network.save(update_fields=['enacted']) + + def delete_network(self, network): + if (network.router_id) and (network.subnet_id): + self.driver.delete_router_interface(network.router_id, network.subnet_id) + if network.subnet_id: + self.driver.delete_subnet(network.subnet_id) + if network.router_id: + self.driver.delete_router(network.router_id) + if network.network_id: + self.driver.delete_network(network.network_id) + + def find_or_make_template_for_network(self, name): + """ Given a network name, try to guess the right template for it """ + + # templates for networks we may encounter + if name=='nat-net': + template_dict = {"name": "private-nat", "visibility": "private", "translation": "nat"} + elif name=='sharednet1': + template_dict = {"name": "dedicated-public", "visibility": "public", "translation": "none"} + else: + template_dict = {"name": "private", "visibility": "private", "translation": "none"} + + # if we have an existing template return it + templates = NetworkTemplate.objects.filter(name=template_dict["name"]) + if templates: + return templates[0] + + template = NetworkTemplate(**template_dict) + template.save() + return template + + def refresh_networks(self): + # get a list of all networks in the model + + networks = Network.objects.all() + networks_by_name = {} + networks_by_id = {} + for network in networks: + networks_by_name[network.name] = network + networks_by_id[network.network_id] = network + + # Get a list of all shared networks in OS + + os_networks = self.driver.shell.quantum.list_networks()['networks'] + os_networks_by_name = {} + os_networks_by_id = {} + for os_network in os_networks: + os_networks_by_name[os_network['name']] = os_network + os_networks_by_id[os_network['id']] = os_network + + for (uuid, os_network) in os_networks_by_id.items(): + #print "checking OS network", os_network['name'] + if (os_network['shared']) and (uuid not in networks_by_id): + # Only automatically create shared networks. This is for Andy's + # nat-net and sharednet1. + + owner_slice = Slice.objects.get(tenant_id = os_network['tenant_id']) + template = self.find_or_make_template_for_network(os_network['name']) + + # Make a best-effort attempt to figure out the subnet. If we + # cannot determine the subnet, then leave those fields blank. + subnet_id = None + subnet = None + if os_network['subnets']: + subnet_id = os_network['subnets'][0] + os_subnets = self.driver.shell.quantum.list_subnets(id=subnet_id)['subnets'] + if os_subnets: + subnet = os_subnets[0]['cidr'] + + if owner_slice: + #print "creating model object for OS network", os_network['name'] + new_network = Network(name = os_network['name'], + template = template, + owner = owner_slice, + network_id = uuid, + subnet_id = subnet_id) + new_network.save() + + for (network_id, network) in networks_by_id.items(): + # If the network disappeared from OS, then reset its network_id to None + if (network.network_id is not None) and (network.network_id not in os_networks_by_id): + network.network_id = None + + # If no OS object exists, then saving the network will create one + if (network.network_id is None): + #print "creating OS network for", network.name + self.save_network(network) + else: + pass #print "network", network.name, "has its OS object" + -- 2.43.0