def list_cached_networks(self): """Returns networks stored in database for a specific cloud""" # FIXME: Move these imports to the top of the file when circular # import issues are resolved from mist.api.networks.models import Network return Network.objects(cloud=self.cloud, missing_since=None)
def list_networks(self): """Lists all Networks present on the Cloud. Fetches all Networks via libcloud, applies cloud-specific processing, and syncs the state of the database with the state of the Cloud. Subclasses SHOULD NOT override or extend this method. There are instead a number of methods that are called from this method, to allow subclasses to modify the data according to the specific of their cloud type. These methods currently are: `self._list_networks__cidr_range` `self._list_networks__postparse_network` More private methods may be added in the future. Subclasses that require special handling should override this, by default, dummy method. """ # FIXME: Move these imports to the top of the file when circular # import issues are resolved from mist.api.networks.models import Network, NETWORKS libcloud_nets = self.cloud.ctl.compute.connection.ex_list_networks() # List of Network mongoengine objects to be returned to the API. networks = [] for net in libcloud_nets: try: network = Network.objects.get(cloud=self.cloud, network_id=net.id) except Network.DoesNotExist: network = NETWORKS[self.provider](cloud=self.cloud, network_id=net.id) network.name = net.name network.extra = copy.copy(net.extra) # Get the Network's CIDR. try: network.cidr = self._list_networks__cidr_range(network, net) except Exception as exc: log.exception('Failed to get CIDR of %s: %s', network, exc) # Apply cloud-specific processing. try: self._list_networks__postparse_network(network, net) except Exception as exc: log.exception('Error post-parsing %s: %s', network, exc) # Ensure JSON-encoding. for key, value in network.extra.iteritems(): try: json.dumps(value) except TypeError: network.extra[key] = str(value) try: network.save() except mongoengine.errors.ValidationError as exc: log.error("Error updating %s: %s", network, exc.to_dict()) raise mist.api.exceptions.BadRequestError({ "msg": exc.message, "errors": exc.to_dict() }) except mongoengine.errors.NotUniqueError as exc: log.error("Network %s is not unique: %s", network.name, exc) raise mist.api.exceptions.NetworkExistsError() networks.append(network) # Delete existing networks not returned by libcloud. All associated # Subnets will also be deleted. Network.objects(cloud=self.cloud, id__nin=[n.id for n in networks]).delete() return networks
def _list_networks(self): """Lists all Networks present on the Cloud. Fetches all Networks via libcloud, applies cloud-specific processing, and syncs the state of the database with the state of the Cloud. Subclasses SHOULD NOT override or extend this method. There are instead a number of methods that are called from this method, to allow subclasses to modify the data according to the specific of their cloud type. These methods currently are: `self._list_networks__cidr_range` `self._list_networks__postparse_network` More private methods may be added in the future. Subclasses that require special handling should override this, by default, dummy method. """ # FIXME: Move these imports to the top of the file when circular # import issues are resolved from mist.api.networks.models import Network, NETWORKS try: libcloud_nets = self._list_networks__fetch_networks() except ConnectionError as e: raise mist.api.exceptions.CloudUnavailableError(e) # in case of ARM, we need to attach the network to a resource group if self.cloud.ctl.provider in ['azure_arm']: connection = self.cloud.ctl.compute.connection r_groups = connection.ex_list_resource_groups() else: r_groups = [] # List of Network mongoengine objects to be returned to the API. networks, new_networks = [], [] for net in libcloud_nets: try: network = Network.objects.get(cloud=self.cloud, network_id=net.id) except Network.DoesNotExist: network = NETWORKS[self.provider](cloud=self.cloud, network_id=net.id) new_networks.append(network) network.name = net.name network.extra = copy.copy(net.extra) network.missing_since = None # Get the Network's CIDR. try: network.cidr = self._list_networks__cidr_range(network, net) except Exception as exc: log.exception('Failed to get CIDR of %s: %s', network, exc) # Apply cloud-specific processing. try: self._list_networks__postparse_network(network, net, r_groups) except Exception as exc: log.exception('Error post-parsing %s: %s', network, exc) # Ensure JSON-encoding. for key, value in network.extra.items(): try: json.dumps(value) except TypeError: network.extra[key] = str(value) try: network.save() except mongoengine.errors.ValidationError as exc: log.error("Error updating %s: %s", network, exc.to_dict()) raise mist.api.exceptions.BadRequestError({ "msg": str(exc), "errors": exc.to_dict() }) except mongoengine.errors.NotUniqueError as exc: log.error("Network %s is not unique: %s", network.name, exc) raise mist.api.exceptions.NetworkExistsError() networks.append(network) # Set missing_since for networks not returned by libcloud. Network.objects(cloud=self.cloud, id__nin=[n.id for n in networks], missing_since=None).update( missing_since=datetime.datetime.utcnow()) # Update RBAC Mappings given the list of new networks. self.cloud.owner.mapper.update(new_networks, asynchronous=False) return networks