예제 #1
0
 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)
예제 #2
0
    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
예제 #3
0
    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