def get(self, name): """ Get a network named "name" and return some data about it. """ try: network = self.driver.ex_get_network(name) except ResourceNotFoundError as not_found: logger.info("Caught exception trying to get network: %s", not_found) return None return canonicalize_network_info(network)
def get(self, network, subnetwork_name): """ Get a group of subnetworks in "network" named "subnetwork_name". """ logger.info('Discovering subnetwork %s, %s', network.name, subnetwork_name) full_name = "%s-%s" % (network.name, subnetwork_name) all_subnetworks = self.driver.ex_list_subnetworks() subnets = [sn for sn in all_subnetworks if sn.network.name == network.name and sn.name == full_name] return [canonicalize_subnetwork_info(sn) for sn in subnets]
def remove(self, source, destination, port): """ Remove path between two services on a given port. """ logger.info('Removing path from %s to %s on port %s', source, destination, port) firewall_name = "bu-%s-%s-%s" % (destination.network.name, destination.name, port) def remove_from_ranges(to_remove, address_ranges): logger.info("Removing %s from %s", to_remove, address_ranges) resulting_ranges = [] if not address_ranges: return None for address_range in address_ranges: remove_net = ipaddress.IPv4Network(to_remove) address_range_network = ipaddress.IPv4Network(address_range) if remove_net.overlaps(address_range_network): if remove_net.prefixlen > address_range_network.prefixlen: new_range_networks = address_range_network.address_exclude( remove_net) resulting_ranges.extend([ str(new_range_network) for new_range_network in new_range_networks ]) else: resulting_ranges.extend([str(address_range_network)]) logger.info("New ranges: %s", resulting_ranges) return resulting_ranges try: firewall = self.driver.ex_get_firewall(firewall_name) if isinstance(source, CidrBlock): firewall.source_ranges = remove_from_ranges( source.cidr_block, firewall.source_ranges) else: source_tag = "%s-%s" % (source.network.name, source.name) if firewall.source_tags: firewall.source_tags = [ tag for tag in firewall.source_tags if tag != source_tag ] except ResourceNotFoundError: logger.info("Firewall %s doesn't exist", firewall_name) return None # We need this because the default is to add "0.0.0.0/0" if these aren't set, which is bad. if not firewall.source_tags and not firewall.source_ranges: return self.driver.ex_destroy_firewall(firewall) return self.driver.ex_update_firewall(firewall)
def add(self, source, destination, port): """ Add path between two services on a given port. """ logger.info('Adding path from %s to %s on port %s', source, destination, port) rules = [{"IPProtocol": "tcp", "ports": [int(port)]}] src_tags, dest_tags, src_ranges, _ = self._extract_service_info( source, destination) firewall_name = "bu-%s-%s-%s" % (destination.network.name, destination.name, port) try: firewall = self.driver.ex_get_firewall(firewall_name) if isinstance(source, CidrBlock): if not firewall.source_ranges: firewall.source_ranges = [] firewall.source_ranges.append(str(source.cidr_block)) logger.info(firewall.source_ranges) if isinstance(source, Service): if not firewall.source_tags: firewall.source_tags = [] source_tag = "%s-%s" % (source.network.name, source.name) firewall.source_tags.append(source_tag) logger.info(firewall.source_tags) firewall = self.driver.ex_update_firewall(firewall) except ResourceNotFoundError: logger.info("Firewall %s not found, creating.", firewall_name) firewall = self.driver.ex_create_firewall( firewall_name, allowed=rules, network=destination.network.name, source_ranges=src_ranges, source_tags=src_tags, target_tags=dest_tags) return Path(destination.network, source, destination, "tcp", port)
def delete_firewall(self, network_name, subnetwork_name): """ Delete the firewall corresponding to the service described by "network_name" and "subnetwork_name". """ firewalls = self.driver.ex_list_firewalls() tag = "%s-%s" % (network_name, subnetwork_name) for firewall in firewalls: if not firewall.source_tags and not firewall.target_tags: continue if firewall.source_tags: if tag in firewall.source_tags: logger.info("Deleting firewall %s because of source tag: %s", firewall, tag) self.driver.ex_destroy_firewall(firewall) if firewall.target_tags: if tag in firewall.target_tags: logger.info("Deleting firewall %s because of target tag: %s", firewall, tag) self.driver.ex_destroy_firewall(firewall)
def list(self): """ List all subnetworks. """ logger.info('Listing subnetworks') subnets = self.driver.ex_list_subnetworks() subnets_info = {} for subnet in subnets: if subnet.network.name == "default": continue subnetwork_name = subnet.name.replace("%s-" % subnet.network.name, "") if subnet.network.name not in subnets_info: subnets_info[subnet.network.name] = {} if subnetwork_name not in subnets_info[subnet.network.name]: subnets_info[subnet.network.name][subnetwork_name] = [] subnets_info[subnet.network.name][subnetwork_name].append( canonicalize_subnetwork_info(subnet)) logger.info('Found subnetworks: %s', subnets_info) return subnets_info
def remove_from_ranges(to_remove, address_ranges): logger.info("Removing %s from %s", to_remove, address_ranges) resulting_ranges = [] if not address_ranges: return None for address_range in address_ranges: remove_net = ipaddress.IPv4Network(to_remove) address_range_network = ipaddress.IPv4Network(address_range) if remove_net.overlaps(address_range_network): if remove_net.prefixlen > address_range_network.prefixlen: new_range_networks = address_range_network.address_exclude( remove_net) resulting_ranges.extend([ str(new_range_network) for new_range_network in new_range_networks ]) else: resulting_ranges.extend([str(address_range_network)]) logger.info("New ranges: %s", resulting_ranges) return resulting_ranges
def destroy(self, network_name, subnetwork_name): """ Destroy a group of subnetworks named "subnetwork_name" in "network_name". """ logger.info('Destroying subnetwork group %s, %s', network_name, subnetwork_name) full_name = "%s-%s" % (network_name, subnetwork_name) all_subnetworks = self.driver.ex_list_subnetworks() subnets = [sn for sn in all_subnetworks if sn.network.name == network_name and sn.name == full_name] region = DEFAULT_REGION destroy_results = [] for subnet in subnets: try: logger.info('Destroying subnetwork %s', subnet.name) subnet_info = self.driver.ex_get_subnetwork(subnet.name, region) except ResourceNotFoundError as not_found: logger.info("Caught exception destroying subnetwork, " "ignoring: %s", not_found) return True destroy_results.append(self.driver.ex_destroy_subnetwork( subnet_info)) return destroy_results
def destroy(self, service): """ Destroy a service described by "service". """ logger.info('Destroying service: %s', service) destroy_results = [] for node in self.driver.list_nodes(): metadata = node.extra.get("metadata", {}).get("items", []) node_network_name = None node_subnetwork_name = None for item in metadata: logger.debug("Found metadata item %s for node %s", item, node) if item["key"] == "network": node_network_name = item["value"] if item["key"] == "subnetwork": node_subnetwork_name = item["value"] if (service.network.name == node_network_name and service.name == node_subnetwork_name): logger.info('Destroying instance: %s', node.name) destroy_results.append(self.driver.destroy_node(node)) subnetwork_destroy = self.subnetwork.destroy(service.network.name, service.name) self.firewalls.delete_firewall(service.network.name, service.name) return {"Subnetwork": subnetwork_destroy, "Instances": destroy_results}
def create(self, network, service_name, blueprint, template_vars, count): """ Create a service in "network" named "service_name" with blueprint file at "blueprint". """ logger.info( 'Creating service %s, %s with blueprint %s and ' 'template_vars %s', network.name, service_name, blueprint, template_vars) self.subnetwork.create(network.name, service_name, blueprint=blueprint) instances_blueprint = ServiceBlueprint(blueprint, template_vars) az_count = instances_blueprint.availability_zone_count() availability_zones = list( itertools.islice(self._get_availability_zones(), az_count)) if len(availability_zones) < az_count: raise DisallowedOperationException( "Do not have %s availability zones: %s" % (az_count, availability_zones)) instance_count = az_count if count: instance_count = count def get_image(image_specifier): images = [ image for image in self.driver.list_images() if re.match(image_specifier, image.name) ] if not images: raise DisallowedOperationException( "Could not find image named %s" % image_specifier) if len(images) > 1: raise DisallowedOperationException( "Found multiple images for specifier %s: %s" % (image_specifier, images)) return images[0] image = get_image(instances_blueprint.image()) instance_type = get_fitting_instance(self, blueprint) for availability_zone, instance_num in zip( itertools.cycle(availability_zones), range(0, instance_count)): full_subnetwork_name = "%s-%s" % (network.name, service_name) instance_name = "%s-%s" % (full_subnetwork_name, instance_num) metadata = [{ "key": "startup-script", "value": instances_blueprint.runtime_scripts() }, { "key": "network", "value": network.name }, { "key": "subnetwork", "value": service_name }] logger.info('Creating instance %s in zone %s', instance_name, availability_zone) self.driver.create_node(instance_name, instance_type, image, location=availability_zone, ex_network=network.name, ex_subnetwork=full_subnetwork_name, external_ip="ephemeral", ex_metadata=metadata, ex_tags=[full_subnetwork_name]) return self.get(network, service_name)