Exemplo n.º 1
0
 def _configure_manager(self):
     """
     Creates the Manager instances to handle monitoring.
     """
     self._entity_manager = CloudMonitorEntityManager(self,
             uri_base="entities", resource_class=CloudMonitorEntity,
             response_key=None, plural_response_key=None)
     self._check_type_manager = BaseManager(self,
             uri_base="check_types", resource_class=CloudMonitorCheckType,
             response_key=None, plural_response_key=None)
     self._monitoring_zone_manager = BaseManager(self,
             uri_base="monitoring_zones", resource_class=CloudMonitorZone,
             response_key=None, plural_response_key=None)
     self._notification_manager = CloudMonitorNotificationManager(self,
             uri_base="notifications",
             resource_class=CloudMonitorNotification,
             response_key=None, plural_response_key=None)
     self._notification_plan_manager = CloudMonitorNotificationPlanManager(
             self, uri_base="notification_plans",
             resource_class=CloudMonitorNotificationPlan,
             response_key=None, plural_response_key=None)
     self._changelog_manager = CloudMonitorChangelogManager(self,
             uri_base="changelogs/alarms", resource_class=None,
             response_key=None, plural_response_key=None)
     self._overview_manager = CloudMonitorOverviewManager(self,
             uri_base="views/overview", resource_class=None,
             response_key="value", plural_response_key=None)
Exemplo n.º 2
0
 def _configure_manager(self):
     """
     Creates the Manager instances to handle monitoring.
     """
     self._entity_manager = CloudMonitorEntityManager(self,
             uri_base="entities", resource_class=CloudMonitorEntity,
             response_key=None, plural_response_key=None)
     self._check_type_manager = _PaginationManager(self,
             uri_base="check_types", resource_class=CloudMonitorCheckType,
             response_key=None, plural_response_key=None)
     self._monitoring_zone_manager = BaseManager(self,
             uri_base="monitoring_zones", resource_class=CloudMonitorZone,
             response_key=None, plural_response_key=None)
     self._notification_manager = CloudMonitorNotificationManager(self,
             uri_base="notifications",
             resource_class=CloudMonitorNotification,
             response_key=None, plural_response_key=None)
     self._notification_plan_manager = CloudMonitorNotificationPlanManager(
             self, uri_base="notification_plans",
             resource_class=CloudMonitorNotificationPlan,
             response_key=None, plural_response_key=None)
     self._changelog_manager = _EntityFilteringManger(self,
             uri_base="changelogs/alarms", resource_class=None,
             response_key=None, plural_response_key=None)
     self._overview_manager = _EntityFilteringManger(self,
             uri_base="views/overview", resource_class=None,
             response_key="value", plural_response_key=None)
Exemplo n.º 3
0
 def __init__(self, *args, **kwargs):
     super(CloudDatabaseInstance, self).__init__(*args, **kwargs)
     self._database_manager = BaseManager(self.manager.api,
             resource_class=CloudDatabaseDatabase, response_key="database",
             uri_base="instances/%s/databases" % self.id)
     self._user_manager = BaseManager(self.manager.api,
             resource_class=CloudDatabaseUser, response_key="user",
             uri_base="instances/%s/users" % self.id)
Exemplo n.º 4
0
 def _configure_manager(self):
     """
     Create the manager to handle the instances, and also another
     to handle flavors.
     """
     self._manager = BaseManager(self, resource_class=CloudBlockStorageVolume,
            response_key="volume", uri_base="volumes")
     self._types_manager = BaseManager(self, resource_class=CloudBlockStorageVolumeType,
            response_key="volume_type", uri_base="types")
     self._snaps_manager = BaseManager(self, resource_class=CloudBlockStorageSnapshot,
            response_key="snapshot", uri_base="snapshots")
Exemplo n.º 5
0
 def _configure_manager(self):
     """
     Creates a manager to handle the instances, and another
     to handle flavors.
     """
     self._manager = BaseManager(self,
                                 resource_class=CloudDatabaseInstance,
                                 response_key="instance",
                                 uri_base="instances")
     self._flavor_manager = BaseManager(self,
                                        resource_class=CloudDatabaseFlavor,
                                        response_key="flavor",
                                        uri_base="flavors")
Exemplo n.º 6
0
 def __init__(self, *args, **kwargs):
     super(CloudBlockStorageVolume, self).__init__(*args, **kwargs)
     try:
         region = self.manager.api.region_name
         self._nova_volumes = pyrax.connect_to_cloudservers(region).volumes
     except AttributeError:
         # This will happen in unit testing, where the full pyrax
         # namespace is not exposed. In that situation, there is
         # no need for the reference anyway
         pass
     self._snapshot_manager = BaseManager(self.manager.api,
             resource_class=CloudBlockStorageSnapshot,
             response_key="snapshot", uri_base="snapshots")
Exemplo n.º 7
0
 def __init__(self, *args, **kwargs):
     super(CloudDatabaseInstance, self).__init__(*args, **kwargs)
     self._database_manager = BaseManager(self.manager.api,
             resource_class=CloudDatabaseDatabase, response_key="database",
             uri_base="instances/%s/databases" % self.id)
     self._user_manager = BaseManager(self.manager.api,
             resource_class=CloudDatabaseUser, response_key="user",
             uri_base="instances/%s/users" % self.id)
     # Remove the lazy load
     if not self.loaded:
         self.get()
         # Make the volume into an accessible object instead of a dict
         self.volume = CloudDatabaseVolume(self, self.volume)
Exemplo n.º 8
0
 def _configure_manager(self):
     """
     Create the manager to handle the instances, and also another
     to handle flavors.
     """
     self._manager = BaseManager(self,
             resource_class=CloudBlockStorageVolume, response_key="volume",
             uri_base="volumes")
     self._types_manager = BaseManager(self,
             resource_class=CloudBlockStorageVolumeType,
             response_key="volume_type", uri_base="types")
     self._snaps_manager = BaseManager(self,
             resource_class=CloudBlockStorageSnapshot,
             response_key="snapshot", uri_base="snapshots")
Exemplo n.º 9
0
 def __init__(self, *args, **kwargs):
     super(CloudDatabaseInstance, self).__init__(*args, **kwargs)
     self._database_manager = BaseManager(
         self.manager.api,
         resource_class=CloudDatabaseDatabase,
         response_key="database",
         uri_base="instances/%s/databases" % self.id)
     self._user_manager = BaseManager(self.manager.api,
                                      resource_class=CloudDatabaseUser,
                                      response_key="user",
                                      uri_base="instances/%s/users" %
                                      self.id)
     # Remove the lazy load
     if not self.loaded:
         self.get()
         # Make the volume into an accessible object instead of a dict
         self.volume = CloudDatabaseVolume(self, self.volume)
Exemplo n.º 10
0
 def _configure_manager(self):
     """
     Creates a manager to handle the instances, and another
     to handle flavors.
     """
     self._manager = BaseManager(self, resource_class=CloudDatabaseInstance,
            response_key="instance", uri_base="instances")
     self._flavor_manager = BaseManager(self,
             resource_class=CloudDatabaseFlavor, response_key="flavor",
             uri_base="flavors")
Exemplo n.º 11
0
 def _configure_manager(self):
     """Create a manager to handle RackConnect operations."""
     self._network_manager = BaseManager(
         self, resource_class=Network, uri_base="cloud_networks",
     )
     self._load_balancer_pool_manager = LoadBalancerPoolManager(
         self, resource_class=LoadBalancerPool,
         uri_base="load_balancer_pools"
     )
     self._public_ip_manager = PublicIPManager(
         self, resource_class=PublicIP, uri_base="public_ips",
     )
Exemplo n.º 12
0
 def _configure_manager(self):
     """
     Creates the Manager instance to handle networks.
     """
     self._entity_manager = CloudMonitorEntityManager(self,
             uri_base="entities", resource_class=CloudMonitorEntity,
             response_key=None, plural_response_key=None)
     self._check_type_manager = BaseManager(self,
             uri_base="check_types", resource_class=CloudMonitorCheckType,
             response_key=None, plural_response_key=None)
     self._monitoring_zone_manager = BaseManager(self,
             uri_base="monitoring_zones", resource_class=CloudMonitorZone,
             response_key=None, plural_response_key=None)
     self._notification_manager = CloudMonitorNotificationManager(self,
             uri_base="notifications",
             resource_class=CloudMonitorNotification,
             response_key=None, plural_response_key=None)
     self._notification_plan_manager = CloudMonitorNotificationPlanManager(
             self, uri_base="notification_plans",
             resource_class=CloudMonitorNotificationPlan,
             response_key=None, plural_response_key=None)
Exemplo n.º 13
0
 def __init__(self, *args, **kwargs):
     super(CloudBlockStorageVolume, self).__init__(*args, **kwargs)
     try:
         self._nova_volumes = pyrax.cloudservers.volumes
     except AttributeError:
         # This will happen in unit testing, where the full pyrax
         # namespace is not exposed. In that situation, there is
         # no need for the reference anyway
         pass
     self._snapshot_manager = BaseManager(self.manager.api,
             resource_class=CloudBlockStorageSnapshot,
             response_key="snapshot", uri_base="snapshots")
Exemplo n.º 14
0
class CloudDatabaseInstance(BaseResource):
    """
    This class represents a MySQL instance in the cloud. 
    """
    def __init__(self, *args, **kwargs):
        super(CloudDatabaseInstance, self).__init__(*args, **kwargs)
        self._database_manager = BaseManager(self.manager.api,
                resource_class=CloudDatabaseDatabase, response_key="database",
                uri_base="instances/%s/databases" % self.id)
        self._user_manager = BaseManager(self.manager.api,
                resource_class=CloudDatabaseUser, response_key="user",
                uri_base="instances/%s/users" % self.id)


    def list_databases(self):
        """Returns a list of the names of all databases for this instance."""
        return self._database_manager.list()


    def list_users(self):
        """Returns a list of the names of all users for this instance."""
        return self._user_manager.list()


    def get_database(self, name):
        """
        Finds the database in this instance with the specified name, and
        returns a CloudDatabaseDatabase object. If no match is found, a
        NoSuchDatabase exception is raised.
        """
        try:
            return [db for db in self.list_databases()
                    if db.name == name][0]
        except IndexError:
            raise exc.NoSuchDatabase("No database by the name '%s' exists." % name)


    def get_user(self, name):
        """
        Finds the user in this instance with the specified name, and
        returns a CloudDatabaseUser object. If no match is found, a
        NoSuchDatabaseUser exception is raised.
        """
        try:
            return [user for user in self.list_users()
                    if user.name == name][0]
        except IndexError:
            raise exc.NoSuchDatabaseUser("No user by the name '%s' exists." % name)


    def create_database(self, name, character_set=None, collate=None):
        """
        Creates a database with the specified name. If a database with
        that name already exists, a BadRequest (400) exception will
        be raised.
        """
        if character_set is None:
            character_set = "utf8"
        if collate is None:
            collate = "utf8_general_ci"
        # Note that passing in non-None values is required for the _create_body
        # method to distinguish between this and the request to create and instance.
        self._database_manager.create(name=name, character_set=character_set,
                collate=collate, return_none=True)
        # Since the API doesn't return the info for creating the database object, we
        # have to do it manually.
        return self._database_manager.find(name=name)


    def create_user(self, name, password, database_names):
        """
        Creates a user with the specified name and password, and gives that
        user access to the specified database(s).

        If a user with
        that name already exists, a BadRequest (400) exception will
        be raised.
        """
        if not isinstance(database_names, list):
            database_names = [database_names]
        # The API only accepts names, not DB objects
        database_names = [db if isinstance(db, basestring) else db.name
                for db in database_names]
        # Note that passing in non-None values is required for the create_body
        # method to distinguish between this and the request to create and instance.
        self._user_manager.create(name=name, password=password,
                database_names=database_names, return_none=True)
        # Since the API doesn't return the info for creating the user object, we
        # have to do it manually.
        return self._user_manager.find(name=name)


    def _get_name(self, name_or_obj):
        """
        For convenience, many methods accept either an object or the name
        of the object as a parameter, but need the name to send to the
        API. This method handles that conversion.
        """
        if isinstance(name_or_obj, basestring):
            return name_or_obj
        try:
            return name_or_obj.name
        except AttributeError:
            msg = "The object '%s' does not have a 'name' attribute." % name_or_obj
            raise exc.MissingName(msg)


    def delete_database(self, name_or_obj):
        """
        Deletes the specified database. If no database by that name
        exists, no exception will be raised; instead, nothing at all
        is done.
        """
        name = self._get_name(name_or_obj)
        self._database_manager.delete(name)


    def delete_user(self, name_or_obj):
        """
        Deletes the specified user. If no user by that name
        exists, no exception will be raised; instead, nothing at all
        is done.
        """
        name = self._get_name(name_or_obj)
        self._user_manager.delete(name)


    def enable_root_user(self):
        """
        Enables login from any host for the root user and provides
        the user with a generated root password.
        """
        uri = "/instances/%s/root" % self.id
        resp, body = self.manager.api.method_post(uri)
        return body["user"]["password"]


    def root_user_status(self):
        """
        Returns True or False, depending on whether the root user
        for this instance has been enabled.
        """
        uri = "/instances/%s/root" % self.id
        resp, body = self.manager.api.method_get(uri)
        return body["rootEnabled"]


    def restart(self):
        """Restarts this instance."""
        self.manager.action(self, "restart")


    def resize(self, flavor):
        """Set the size of this instance to a different flavor."""
        # We need the flavorRef, not the flavor or size.
        flavorRef = self.manager.api._get_flavor_ref(flavor)
        body = {"flavorRef": flavorRef}
        self.manager.action(self, "resize", body=body)


    def resize_volume(self, size):
        """Changes the size of the volume for this instance."""
        curr_size = self.volume.get("size")
        if size <= curr_size:
            raise exc.InvalidVolumeResize("The new volume size must be larger than the current volume size of '%s'." % curr_size)
        body = {"volume": {"size": size}}
        self.manager.action(self, "resize", body=body)


    def _get_flavor(self):
        try:
            ret = self._flavor
        except AttributeError:
            ret = self._flavor = CloudDatabaseFlavor(self.manager.api._flavor_manager, {})
        return ret

    def _set_flavor(self, flavor):
        if isinstance(flavor, dict):
            self._flavor = CloudDatabaseFlavor(self.manager.api._flavor_manager, flavor)
        else:
            # Must be an instance
            self._flavor = flavor

    flavor = property(_get_flavor, _set_flavor)
Exemplo n.º 15
0
class CloudDatabaseClient(BaseClient):
    """
    This is the primary class for interacting with Cloud Databases.
    """
    name = "Cloud Databases"

    def _configure_manager(self):
        """
        Creates a manager to handle the instances, and another
        to handle flavors.
        """
        self._manager = CloudDatabaseManager(
            self,
            resource_class=CloudDatabaseInstance,
            response_key="instance",
            uri_base="instances")
        self._flavor_manager = BaseManager(self,
                                           resource_class=CloudDatabaseFlavor,
                                           response_key="flavor",
                                           uri_base="flavors")
        self._backup_manager = CloudDatabaseBackupManager(
            self,
            resource_class=CloudDatabaseBackup,
            response_key="backup",
            uri_base="backups")

    @assure_instance
    def list_databases(self, instance, limit=None, marker=None):
        """Returns all databases for the specified instance."""
        return instance.list_databases(limit=limit, marker=marker)

    @assure_instance
    def create_database(self,
                        instance,
                        name,
                        character_set=None,
                        collate=None):
        """Creates a database with the specified name on the given instance."""
        return instance.create_database(name,
                                        character_set=character_set,
                                        collate=collate)

    @assure_instance
    def get_database(self, instance, name):
        """
        Finds the database in the given instance with the specified name, and
        returns a CloudDatabaseDatabase object. If no match is found, a
        NoSuchDatabase exception is raised.
        """
        return instance.get_database(name)

    @assure_instance
    def delete_database(self, instance, name):
        """Deletes the database by name on the given instance."""
        return instance.delete_database(name)

    @assure_instance
    def list_users(self, instance, limit=None, marker=None):
        """Returns all users for the specified instance."""
        return instance.list_users(limit=limit, marker=marker)

    @assure_instance
    def create_user(self, instance, name, password, database_names, host=None):
        """
        Creates a user with the specified name and password, and gives that
        user access to the specified database(s).
        """
        return instance.create_user(name=name,
                                    password=password,
                                    database_names=database_names,
                                    host=host)

    @assure_instance
    def get_user(self, instance, name):
        """
        Finds the user in the given instance with the specified name, and
        returns a CloudDatabaseUser object. If no match is found, a
        NoSuchUser exception is raised.
        """
        return instance.get_user(name)

    @assure_instance
    def delete_user(self, instance, name):
        """Deletes the user by name on the given instance."""
        return instance.delete_user(name)

    @assure_instance
    def change_user_password(self, instance, user, new_pass):
        """
        Changes the password for the user of the specified instance to the
        supplied value.

        Returns None upon success; raises PasswordChangeFailed if the call
        does not complete successfully.
        """
        return instance.change_user_password(user, new_pass)

    @assure_instance
    def update_user(self, instance, user, name=None, password=None, host=None):
        """
        Allows you to change one or more of the user's username, password, or
        host.
        """
        return instance.update_user(user,
                                    name=name,
                                    password=password,
                                    host=host)

    @assure_instance
    def list_user_access(self, instance, user):
        """
        Returns a list of all database names for which the specified user
        has access rights on the specified instance.
        """
        return instance.list_user_access(user)

    @assure_instance
    def grant_user_access(self, instance, user, db_names, strict=True):
        """
        Gives access to the databases listed in `db_names` to the user
        on the specified instance.
        """
        return instance.grant_user_access(user, db_names, strict=strict)

    @assure_instance
    def revoke_user_access(self, instance, user, db_names, strict=True):
        """
        Revokes access to the databases listed in `db_names` for the user
        on the specified instance.
        """
        return instance.revoke_user_access(user, db_names, strict=strict)

    @assure_instance
    def enable_root_user(self, instance):
        """
        This enables login from any host for the root user and provides
        the user with a generated root password.
        """
        return instance.enable_root_user()

    @assure_instance
    def root_user_status(self, instance):
        """Returns True if the given instance is root-enabled."""
        return instance.root_user_status()

    @assure_instance
    def restart(self, instance):
        """Restarts the instance."""
        return instance.restart()

    @assure_instance
    def resize(self, instance, flavor):
        """Sets the size of the instance to a different flavor."""
        return instance.resize(flavor)

    def get_limits(self):
        """Not implemented in Cloud Databases."""
        raise NotImplementedError(
            "Limits are not available for Cloud Databases")

    def list_flavors(self, limit=None, marker=None):
        """Returns a list of all available Flavors."""
        return self._flavor_manager.list(limit=limit, marker=marker)

    def get_flavor(self, flavor_id):
        """Returns a specific Flavor object by ID."""
        return self._flavor_manager.get(flavor_id)

    def _get_flavor_ref(self, flavor):
        """
        Flavors are odd in that the API expects an href link, not an ID, as with
        nearly every other resource. This method takes either a
        CloudDatabaseFlavor object, a flavor ID, a RAM size, or a flavor name,
        and uses that to determine the appropriate href.
        """
        flavor_obj = None
        if isinstance(flavor, CloudDatabaseFlavor):
            flavor_obj = flavor
        elif isinstance(flavor, int):
            # They passed an ID or a size
            try:
                flavor_obj = self.get_flavor(flavor)
            except exc.NotFound:
                # Must be either a size or bad ID, which will
                # be handled below
                pass
        if flavor_obj is None:
            # Try flavor name
            flavors = self.list_flavors()
            try:
                flavor_obj = [flav for flav in flavors
                              if flav.name == flavor][0]
            except IndexError:
                # No such name; try matching RAM
                try:
                    flavor_obj = [
                        flav for flav in flavors if flav.ram == flavor
                    ][0]
                except IndexError:
                    raise exc.FlavorNotFound("Could not determine flavor from "
                                             "'%s'." % flavor)
        # OK, we have a Flavor object. Get the href
        href = [
            link["href"] for link in flavor_obj.links if link["rel"] == "self"
        ][0]
        return href

    def list_backups(self, instance=None, limit=20, marker=0):
        """
        Returns a paginated list of backups by default, or just for a particular
        instance.
        """
        return self._backup_manager.list(instance=instance,
                                         limit=limit,
                                         marker=marker)

    def get_backup(self, backup):
        """
        Returns the CloudDatabaseBackup instance for a given ID.
        """
        return self._backup_manager.get(backup)

    def delete_backup(self, backup):
        """
        Deletes the CloudDatabaseBackup instance for a given ID.
        """
        return self._backup_manager.delete(backup)

    @assure_instance
    def create_backup(self, instance, name, description=None):
        """
        Creates a backup of the specified instance, giving it the specified
        name along with an optional description.
        """
        return instance.create_backup(name, description=description)

    def restore_backup(self, backup, name, flavor, volume):
        """
        Restores a backup to a new database instance. You must supply a backup
        (either the ID or a CloudDatabaseBackup object), a name for the new
        instance, as well as a flavor and size (in GB) for the instance.
        """
        return self._manager.restore_backup(backup, name, flavor, volume)
Exemplo n.º 16
0
class CloudDatabaseClient(BaseClient):
    """
    This is the primary class for interacting with Cloud Databases.
    """
    def _configure_manager(self):
        """
        Creates a manager to handle the instances, and another
        to handle flavors.
        """
        self._manager = BaseManager(self, resource_class=CloudDatabaseInstance,
               response_key="instance", uri_base="instances")
        self._flavor_manager = BaseManager(self,
                resource_class=CloudDatabaseFlavor, response_key="flavor",
                uri_base="flavors")


    @assure_instance
    def list_databases(self, instance):
        """Returns all databases for the specified instance."""
        return instance.list_databases()


    @assure_instance
    def create_database(self, instance, name, character_set=None,
            collate=None):
        """Creates a database with the specified name on the given instance."""
        return instance.create_database(name, character_set=character_set,
                collate=collate)


    @assure_instance
    def get_database(self, instance, name):
        """
        Finds the database in the given instance with the specified name, and
        returns a CloudDatabaseDatabase object. If no match is found, a
        NoSuchDatabase exception is raised.
        """
        return instance.get_database(name)


    @assure_instance
    def delete_database(self, instance, name):
        """Deletes the database by name on the given instance."""
        return instance.delete_database(name)


    @assure_instance
    def list_users(self, instance):
        """Returns all users for the specified instance."""
        return instance.list_users()


    @assure_instance
    def create_user(self, instance, name, password, database_names):
        """
        Creates a user with the specified name and password, and gives that
        user access to the specified database(s).
        """
        return instance.create_user(name=name, password=password,
                database_names=database_names)


    @assure_instance
    def get_user(self, instance, name):
        """
        Finds the user in the given instance with the specified name, and
        returns a CloudDatabaseUser object. If no match is found, a
        NoSuchUser exception is raised.
        """
        return instance.get_user(name)


    @assure_instance
    def delete_user(self, instance, name):
        """Deletes the user by name on the given instance."""
        return instance.delete_user(name)


    @assure_instance
    def enable_root_user(self, instance):
        """
        This enables login from any host for the root user and provides
        the user with a generated root password.
        """
        return instance.enable_root_user()


    @assure_instance
    def root_user_status(self, instance):
        """Returns True if the given instance is root-enabled."""
        return instance.root_user_status()


    @assure_instance
    def restart(self, instance):
        """Restarts the instance."""
        return instance.restart()


    @assure_instance
    def resize(self, instance, flavor):
        """Sets the size of the instance to a different flavor."""
        return instance.resize(flavor)


    def list_flavors(self):
        """Returns a list of all available Flavors."""
        return self._flavor_manager.list()


    def get_flavor(self, flavor_id):
        """Returns a specific Flavor object by ID."""
        return self._flavor_manager.get(flavor_id)


    def _get_flavor_ref(self, flavor):
        """
        Flavors are odd in that the API expects an href link, not
        an ID, as with nearly every other resource. This method
        takes either a CloudDatabaseFlavor object, a flavor ID,
        a RAM size, or a flavor name, and uses that to determine
        the appropriate href.
        """
        flavor_obj = None
        if isinstance(flavor, CloudDatabaseFlavor):
            flavor_obj = flavor
        elif isinstance(flavor, int):
            # They passed an ID or a size
            try:
                flavor_obj = self.get_flavor(flavor)
            except exc.NotFound:
                # Must be either a size or bad ID, which will
                # be handled below
                pass
        if flavor_obj is None:
            # Try flavor name
            flavors = self.list_flavors()
            try:
                flavor_obj = [flav for flav in flavors
                        if flav.name == flavor][0]
            except IndexError:
                # No such name; try matching RAM
                try:
                    flavor_obj = [flav for flav in flavors
                            if flav.ram == flavor][0]
                except IndexError:
                   raise exc.FlavorNotFound("Could not determine flavor from '%s'." % flavor)
        # OK, we have a Flavor object. Get the href
        href = [link["href"] for link in flavor_obj.links
                if link["rel"] == "self"][0]
        return href


    def _create_body(self, name, flavor=None, volume=None, databases=None,
            users=None, character_set=None, collate=None, password=None,
            database_names=None):
        """
        Used to create the dict required to create any of the following:
            A database instance
            A database for an instance
            A user for an instance
        """
        if character_set is not None:
            # Creating a database
            body = {"databases": [
                    {"name": name,
                    "character_set": character_set,
                    "collate": collate,
                    }]}
        elif password is not None:
            # Creating a user
            db_dicts = [{"name": db} for db in database_names]
            body = {"users": [
                    {"name": name,
                    "password": password,
                    "databases": db_dicts,
                    }]}
        else:
            if flavor is None:
                flavor = 1
            flavor_ref = self._get_flavor_ref(flavor)
            if volume is None:
                volume = 1
            if databases is None:
                databases = []
            if users is None:
                users = []
            body = {"instance": {
                    "name": name,
                    "flavorRef": flavor_ref,
                    "volume": {"size": volume},
                    "databases": databases,
                    "users": users,
                    }}
        return body
Exemplo n.º 17
0
class RackConnectClient(BaseClient):
    """A client to interact with RackConnected resources."""

    name = "RackConnect"

    def _configure_manager(self):
        """Create a manager to handle RackConnect operations."""
        self._network_manager = BaseManager(
            self, resource_class=Network, uri_base="cloud_networks",
        )
        self._load_balancer_pool_manager = LoadBalancerPoolManager(
            self, resource_class=LoadBalancerPool,
            uri_base="load_balancer_pools"
        )
        self._public_ip_manager = PublicIPManager(
            self, resource_class=PublicIP, uri_base="public_ips",
        )

    def get_network(self, network):
        return self._network_manager.get(network)

    def list_networks(self):
        return self._network_manager.list()

    def list_load_balancer_pools(self):
        return self._load_balancer_pool_manager.list()

    def get_load_balancer_pool(self, pool):
        return self._load_balancer_pool_manager.get(pool)

    def list_pool_nodes(self, pool):
        return self._load_balancer_pool_manager.get_pool_nodes(pool)

    def create_pool_node(self, pool, server):
        return self._load_balancer_pool_manager.add_pool_node(pool, server)

    def get_pool_node(self, pool, node):
        return self._load_balancer_pool_manager.get_pool_node(pool, node)

    def delete_pool_node(self, pool, node):
        return self._load_balancer_pool_manager.delete_pool_node(pool, node)

    def create_public_ip(self, public_ip):
        return self._public_ip_manager.add_public_ip(public_ip)

    def list_public_ips(self):
        return self._public_ip_manager.list()

    def get_public_ip(self, public_ip):
        return self._public_ip_manager.get(public_ip)

    def get_public_ips_for_server(self, server):
        return self._public_ip_manager.get_ip_for_server(server)

    def delete_public_ip(self, public_ip):
        return self._public_ip_manager.delete_public_ip(public_ip)

    #################################################################
    # The following methods are defined in the generic client class,
    # but don't have meaning in RackConnect, as there is not a single
    # resource that defines this module.
    #################################################################
    def list(self, limit=None, marker=None):
        """Not applicable in RackConnect."""
        raise NotImplementedError

    def get(self, item):
        """Not applicable in RackConnect."""
        raise NotImplementedError

    def create(self, *args, **kwargs):
        """Not applicable in RackConnect."""
        raise NotImplementedError

    def delete(self, item):
        """Not applicable in RackConnect."""
        raise NotImplementedError

    def find(self, **kwargs):
        """Not applicable in RackConnect."""
        raise NotImplementedError

    def findall(self, **kwargs):
        """Not applicable in RackConnect."""
        raise NotImplementedError
Exemplo n.º 18
0
class CloudDatabaseClient(BaseClient):
    """
    This is the primary class for interacting with Cloud Databases.
    """
    def _configure_manager(self):
        """
        Creates a manager to handle the instances, and another
        to handle flavors.
        """
        self._manager = BaseManager(self,
                                    resource_class=CloudDatabaseInstance,
                                    response_key="instance",
                                    uri_base="instances")
        self._flavor_manager = BaseManager(self,
                                           resource_class=CloudDatabaseFlavor,
                                           response_key="flavor",
                                           uri_base="flavors")

    @assure_instance
    def list_databases(self, instance):
        """Returns all databases for the specified instance."""
        return instance.list_databases()

    @assure_instance
    def create_database(self,
                        instance,
                        name,
                        character_set=None,
                        collate=None):
        """Creates a database with the specified name on the given instance."""
        return instance.create_database(name,
                                        character_set=character_set,
                                        collate=collate)

    @assure_instance
    def get_database(self, instance, name):
        """
        Finds the database in the given instance with the specified name, and
        returns a CloudDatabaseDatabase object. If no match is found, a
        NoSuchDatabase exception is raised.
        """
        return instance.get_database(name)

    @assure_instance
    def delete_database(self, instance, name):
        """Deletes the database by name on the given instance."""
        return instance.delete_database(name)

    @assure_instance
    def list_users(self, instance):
        """Returns all users for the specified instance."""
        return instance.list_users()

    @assure_instance
    def create_user(self, instance, name, password, database_names):
        """
        Creates a user with the specified name and password, and gives that
        user access to the specified database(s).
        """
        return instance.create_user(name=name,
                                    password=password,
                                    database_names=database_names)

    @assure_instance
    def get_user(self, instance, name):
        """
        Finds the user in the given instance with the specified name, and
        returns a CloudDatabaseUser object. If no match is found, a
        NoSuchUser exception is raised.
        """
        return instance.get_user(name)

    @assure_instance
    def delete_user(self, instance, name):
        """Deletes the user by name on the given instance."""
        return instance.delete_user(name)

    @assure_instance
    def enable_root_user(self, instance):
        """
        This enables login from any host for the root user and provides
        the user with a generated root password.
        """
        return instance.enable_root_user()

    @assure_instance
    def root_user_status(self, instance):
        """Returns True if the given instance is root-enabled."""
        return instance.root_user_status()

    @assure_instance
    def restart(self, instance):
        """Restarts the instance."""
        return instance.restart()

    @assure_instance
    def resize(self, instance, flavor):
        """Sets the size of the instance to a different flavor."""
        return instance.resize(flavor)

    def list_flavors(self):
        """Returns a list of all available Flavors."""
        return self._flavor_manager.list()

    def get_flavor(self, flavor_id):
        """Returns a specific Flavor object by ID."""
        return self._flavor_manager.get(flavor_id)

    def _get_flavor_ref(self, flavor):
        """
        Flavors are odd in that the API expects an href link, not an ID, as with
        nearly every other resource. This method takes either a
        CloudDatabaseFlavor object, a flavor ID, a RAM size, or a flavor name,
        and uses that to determine the appropriate href.
        """
        flavor_obj = None
        if isinstance(flavor, CloudDatabaseFlavor):
            flavor_obj = flavor
        elif isinstance(flavor, int):
            # They passed an ID or a size
            try:
                flavor_obj = self.get_flavor(flavor)
            except exc.NotFound:
                # Must be either a size or bad ID, which will
                # be handled below
                pass
        if flavor_obj is None:
            # Try flavor name
            flavors = self.list_flavors()
            try:
                flavor_obj = [flav for flav in flavors
                              if flav.name == flavor][0]
            except IndexError:
                # No such name; try matching RAM
                try:
                    flavor_obj = [
                        flav for flav in flavors if flav.ram == flavor
                    ][0]
                except IndexError:
                    raise exc.FlavorNotFound("Could not determine flavor from "
                                             "'%s'." % flavor)
        # OK, we have a Flavor object. Get the href
        href = [
            link["href"] for link in flavor_obj.links if link["rel"] == "self"
        ][0]
        return href

    def _create_body(self,
                     name,
                     flavor=None,
                     volume=None,
                     databases=None,
                     users=None,
                     character_set=None,
                     collate=None,
                     password=None,
                     database_names=None):
        """
        Used to create the dict required to create any of the following:
            A database instance
            A database for an instance
            A user for an instance
        """
        if character_set is not None:
            # Creating a database
            body = {
                "databases": [{
                    "name": name,
                    "character_set": character_set,
                    "collate": collate,
                }]
            }
        elif password is not None:
            # Creating a user
            db_dicts = [{"name": db} for db in database_names]
            body = {
                "users": [{
                    "name": name,
                    "password": password,
                    "databases": db_dicts,
                }]
            }
        else:
            if flavor is None:
                flavor = 1
            flavor_ref = self._get_flavor_ref(flavor)
            if volume is None:
                volume = 1
            if databases is None:
                databases = []
            if users is None:
                users = []
            body = {
                "instance": {
                    "name": name,
                    "flavorRef": flavor_ref,
                    "volume": {
                        "size": volume
                    },
                    "databases": databases,
                    "users": users,
                }
            }
        return body
Exemplo n.º 19
0
class CloudBlockStorageClient(BaseClient):
    """
    This is the primary class for interacting with Cloud Block Storage.
    """
    name = "Cloud Block Storage"

    def _configure_manager(self):
        """
        Create the manager to handle the instances, and also another
        to handle flavors.
        """
        self._manager = CloudBlockStorageManager(self,
                resource_class=CloudBlockStorageVolume, response_key="volume",
                uri_base="volumes")
        self._types_manager = BaseManager(self,
                resource_class=CloudBlockStorageVolumeType,
                response_key="volume_type", uri_base="types")
        self._snapshot_manager = CloudBlockStorageSnapshotManager(self,
                resource_class=CloudBlockStorageSnapshot,
                response_key="snapshot", uri_base="snapshots")


    def list_types(self):
        """Returns a list of all available volume types."""
        return self._types_manager.list()


    def list_snapshots(self):
        """Returns a list of all snapshots."""
        return self._snapshot_manager.list()


    @assure_volume
    def attach_to_instance(self, volume, instance, mountpoint):
        """Attaches the volume to the specified instance at the mountpoint."""
        return volume.attach_to_instance(instance, mountpoint)


    @assure_volume
    def detach(self, volume):
        """Detaches the volume from whatever device it is attached to."""
        return volume.detach()


    @assure_volume
    def delete_volume(self, volume, force=False):
        """Deletes the volume."""
        return volume.delete(force=force)


    @assure_volume
    def create_snapshot(self, volume, name=None, description=None, force=False):
        """
        Creates a snapshot of the volume, with an optional name and description.

        Normally snapshots will not happen if the volume is attached. To
        override this default behavior, pass force=True.
        """
        return self._snapshot_manager.create(volume=volume, name=name,
                description=description, force=force)


    @assure_snapshot
    def delete_snapshot(self, snapshot):
        """Deletes the snapshot."""
        return snapshot.delete()
Exemplo n.º 20
0
class CloudDatabaseInstance(BaseResource):
    """
    This class represents a MySQL instance in the cloud.
    """
    def __init__(self, *args, **kwargs):
        super(CloudDatabaseInstance, self).__init__(*args, **kwargs)
        self._database_manager = BaseManager(
            self.manager.api,
            resource_class=CloudDatabaseDatabase,
            response_key="database",
            uri_base="instances/%s/databases" % self.id)
        self._user_manager = BaseManager(self.manager.api,
                                         resource_class=CloudDatabaseUser,
                                         response_key="user",
                                         uri_base="instances/%s/users" %
                                         self.id)
        # Remove the lazy load
        if not self.loaded:
            self.get()
            # Make the volume into an accessible object instead of a dict
            self.volume = CloudDatabaseVolume(self, self.volume)

    def list_databases(self):
        """Returns a list of the names of all databases for this instance."""
        return self._database_manager.list()

    def list_users(self):
        """Returns a list of the names of all users for this instance."""
        return self._user_manager.list()

    def get_database(self, name):
        """
        Finds the database in this instance with the specified name, and
        returns a CloudDatabaseDatabase object. If no match is found, a
        NoSuchDatabase exception is raised.
        """
        try:
            return [db for db in self.list_databases() if db.name == name][0]
        except IndexError:
            raise exc.NoSuchDatabase("No database by the name '%s' exists." %
                                     name)

    def get_user(self, name):
        """
        Finds the user in this instance with the specified name, and
        returns a CloudDatabaseUser object. If no match is found, a
        NoSuchDatabaseUser exception is raised.
        """
        try:
            return [user for user in self.list_users() if user.name == name][0]
        except IndexError:
            raise exc.NoSuchDatabaseUser("No user by the name '%s' exists." %
                                         name)

    def create_database(self, name, character_set=None, collate=None):
        """
        Creates a database with the specified name. If a database with
        that name already exists, a BadRequest (400) exception will
        be raised.
        """
        if character_set is None:
            character_set = "utf8"
        if collate is None:
            collate = "utf8_general_ci"
        # Note that passing in non-None values is required for the _create_body
        # method to distinguish between this and the request to create and
        # instance.
        self._database_manager.create(name=name,
                                      character_set=character_set,
                                      collate=collate,
                                      return_none=True)
        # Since the API doesn't return the info for creating the database
        # object, we have to do it manually.
        return self._database_manager.find(name=name)

    def create_user(self, name, password, database_names):
        """
        Creates a user with the specified name and password, and gives that
        user access to the specified database(s).

        If a user with
        that name already exists, a BadRequest (400) exception will
        be raised.
        """
        if not isinstance(database_names, list):
            database_names = [database_names]
        # The API only accepts names, not DB objects
        database_names = [
            db if isinstance(db, basestring) else db.name
            for db in database_names
        ]
        # Note that passing in non-None values is required for the create_body
        # method to distinguish between this and the request to create and
        # instance.
        self._user_manager.create(name=name,
                                  password=password,
                                  database_names=database_names,
                                  return_none=True)
        # Since the API doesn't return the info for creating the user object, we
        # have to do it manually.
        return self._user_manager.find(name=name)

    def _get_name(self, name_or_obj):
        """
        For convenience, many methods accept either an object or the name
        of the object as a parameter, but need the name to send to the
        API. This method handles that conversion.
        """
        if isinstance(name_or_obj, basestring):
            return name_or_obj
        try:
            return name_or_obj.name
        except AttributeError:
            msg = "The object '%s' does not have a 'name' attribute." % name_or_obj
            raise exc.MissingName(msg)

    def delete_database(self, name_or_obj):
        """
        Deletes the specified database. If no database by that name
        exists, no exception will be raised; instead, nothing at all
        is done.
        """
        name = self._get_name(name_or_obj)
        self._database_manager.delete(name)

    def delete_user(self, name_or_obj):
        """
        Deletes the specified user. If no user by that name
        exists, no exception will be raised; instead, nothing at all
        is done.
        """
        name = self._get_name(name_or_obj)
        self._user_manager.delete(name)

    def enable_root_user(self):
        """
        Enables login from any host for the root user and provides
        the user with a generated root password.
        """
        uri = "/instances/%s/root" % self.id
        resp, body = self.manager.api.method_post(uri)
        return body["user"]["password"]

    def root_user_status(self):
        """
        Returns True or False, depending on whether the root user
        for this instance has been enabled.
        """
        uri = "/instances/%s/root" % self.id
        resp, body = self.manager.api.method_get(uri)
        return body["rootEnabled"]

    def restart(self):
        """Restarts this instance."""
        self.manager.action(self, "restart")

    def resize(self, flavor):
        """Set the size of this instance to a different flavor."""
        # We need the flavorRef, not the flavor or size.
        flavorRef = self.manager.api._get_flavor_ref(flavor)
        body = {"flavorRef": flavorRef}
        self.manager.action(self, "resize", body=body)

    def resize_volume(self, size):
        """Changes the size of the volume for this instance."""
        curr_size = self.volume.size
        if size <= curr_size:
            raise exc.InvalidVolumeResize(
                "The new volume size must be larger "
                "than the current volume size of '%s'." % curr_size)
        body = {"volume": {"size": size}}
        self.manager.action(self, "resize", body=body)

    def _get_flavor(self):
        try:
            ret = self._flavor
        except AttributeError:
            ret = self._flavor = CloudDatabaseFlavor(
                self.manager.api._flavor_manager, {})
        return ret

    def _set_flavor(self, flavor):
        if isinstance(flavor, dict):
            self._flavor = CloudDatabaseFlavor(
                self.manager.api._flavor_manager, flavor)
        else:
            # Must be an instance
            self._flavor = flavor

    flavor = property(_get_flavor, _set_flavor)
Exemplo n.º 21
0
class CloudBlockStorageVolume(BaseResource):
    """
    This class represents a Block Storage volume.
    """
    def __init__(self, *args, **kwargs):
        super(CloudBlockStorageVolume, self).__init__(*args, **kwargs)
        try:
            region = self.manager.api.region_name
            self._nova_volumes = pyrax.connect_to_cloudservers(region).volumes
        except AttributeError:
            # This will happen in unit testing, where the full pyrax
            # namespace is not exposed. In that situation, there is
            # no need for the reference anyway
            pass
        self._snapshot_manager = BaseManager(self.manager.api,
                resource_class=CloudBlockStorageSnapshot,
                response_key="snapshot", uri_base="snapshots")


    def attach_to_instance(self, instance, mountpoint):
        """
        Attaches this volume to the cloud server instance at the
        specified mountpoint. This requires a call to the cloud servers
        API; it cannot be done directly.
        """
        instance_id = _resolve_id(instance)
        try:
            resp = self._nova_volumes.create_server_volume(instance_id,
                    self.id, mountpoint)
        except Exception as e:
            raise exc.VolumeAttachmentFailed("%s" % e)


    def detach(self):
        """
        Detaches this volume from any device it may be attached to. If it
        is not attached, nothing happens.
        """
        attachments = self.attachments
        if not attachments:
            # Not attached; no error needed, just return
            return
        # A volume can only be attached to one device at a time, but for some
        # reason this is a list instead of a singular value
        att = attachments[0]
        instance_id = att["server_id"]
        attachment_id = att["id"]
        try:
            self._nova_volumes.delete_server_volume(instance_id, attachment_id)
        except Exception as e:
            raise exc.VolumeDetachmentFailed("%s" % e)


    def delete(self, force=False):
        """
        Volumes cannot be deleted if either a) they are attached to a device, or
        b) they have any snapshots. This method overrides the base delete()
        method to both better handle these failures, and also to offer a 'force'
        option. When 'force' is True, the volume is detached, and any dependent
        snapshots are deleted before calling the volume's delete.
        """
        if force:
            self.detach()
            self.delete_all_snapshots()
        try:
            super(CloudBlockStorageVolume, self).delete()
        except exc.VolumeNotAvailable:
            # Notify the user? Record it somewhere?
            # For now, just re-raise
            raise


    def create_snapshot(self, name=None, description=None, force=False):
        """
        Creates a snapshot of this volume, with an optional name and
        description.

        Normally snapshots will not happen if the volume is attached. To
        override this default behavior, pass force=True.
        """
        name = name or ""
        description = description or ""
        # Note that passing in non-None values is required for the _create_body
        # method to distinguish between this and the request to create and
        # instance.
        try:
            snap = self._snapshot_manager.create(volume=self, name=name,
                    description=description, force=force)
        except exc.BadRequest as e:
            msg = str(e)
            if "Invalid volume: must be available" in msg:
                # The volume for the snapshot was attached.
                raise exc.VolumeNotAvailable("Cannot create a snapshot from an "
                        "attached volume. Detach the volume before trying again, "
                        "or pass 'force=True' to the create_snapshot() call.")
            else:
                # Some other error
                raise
        except exc.ClientException as e:
            if e.code == 409:
                if "Request conflicts with in-progress" in str(e):
                    raise exc.VolumeNotAvailable("The volume is current "
                            "creating a snapshot. You must wait until that "
                            "completes before attempting to create an "
                            "additional snapshot.")
                else:
                    raise
            else:
                raise
        return snap


    def list_snapshots(self):
        """
        Returns a list of all snapshots of this volume.
        """
        return [snap for snap in self._snapshot_manager.list()
                if snap.volume_id == self.id]


    def delete_all_snapshots(self):
        """
        Locates all snapshots of this volume and deletes them.
        """
        for snap in self.list_snapshots():
            snap.delete()


    def _get_name(self):
        return self.display_name

    def _set_name(self, val):
        self.display_name = val

    name = property(_get_name, _set_name, None,
            "Convenience for referencing the display_name.")

    def _get_description(self):
        return self.display_description

    def _set_description(self, val):
        self.display_description = val

    description = property(_get_description, _set_description, None,
            "Convenience for referencing the display_description.")
Exemplo n.º 22
0
class CloudMonitorClient(BaseClient):
    """
    This is the base client for creating and managing Cloud Monitoring.
    """

    def __init__(self, *args, **kwargs):
        super(CloudMonitorClient, self).__init__(*args, **kwargs)
        self.name = "Cloud Monitoring"


    def _configure_manager(self):
        """
        Creates the Manager instances to handle monitoring.
        """
        self._entity_manager = CloudMonitorEntityManager(self,
                uri_base="entities", resource_class=CloudMonitorEntity,
                response_key=None, plural_response_key=None)
        self._check_type_manager = BaseManager(self,
                uri_base="check_types", resource_class=CloudMonitorCheckType,
                response_key=None, plural_response_key=None)
        self._monitoring_zone_manager = BaseManager(self,
                uri_base="monitoring_zones", resource_class=CloudMonitorZone,
                response_key=None, plural_response_key=None)
        self._notification_manager = CloudMonitorNotificationManager(self,
                uri_base="notifications",
                resource_class=CloudMonitorNotification,
                response_key=None, plural_response_key=None)
        self._notification_plan_manager = CloudMonitorNotificationPlanManager(
                self, uri_base="notification_plans",
                resource_class=CloudMonitorNotificationPlan,
                response_key=None, plural_response_key=None)
        self._changelog_manager = CloudMonitorChangelogManager(self,
                uri_base="changelogs/alarms", resource_class=None,
                response_key=None, plural_response_key=None)
        self._overview_manager = CloudMonitorOverviewManager(self,
                uri_base="views/overview", resource_class=None,
                response_key="value", plural_response_key=None)


    def get_account(self):
        """
        Returns a dict with the following keys: id, webhook_token, and metadata.
        """
        resp, resp_body = self.method_get("/account")
        return resp_body


    def get_audits(self):
        """
        Every write operation performed against the API (PUT, POST or DELETE)
        generates an audit record that is stored for 30 days. Audits record a
        variety of information about the request including the method, URL,
        headers, query string, transaction ID, the request body and the
        response code. They also store information about the action performed
        including a JSON list of the previous state of any modified objects.
        For example, if you perform an update on an entity, this will record
        the state of the entity before modification.
        """
        resp, resp_body = self.method_get("/audits")
        return resp_body["values"]


    def list_entities(self):
        return self._entity_manager.list()


    def get_entity(self, entity):
        return self._entity_manager.get(entity)


    def create_entity(self, label=None, name=None, agent=None,
            ip_addresses=None, metadata=None):
        # NOTE: passing a non-None value for ip_addresses is required so that
        # the _create_body() method can distinguish this as a request for a
        # body dict for entities.
        ip_addresses = ip_addresses or {}
        resp = self._entity_manager.create(label=label, name=name, agent=agent,
                ip_addresses=ip_addresses, metadata=metadata,
                return_response=True)
        if resp.status_code == 201:
            ent_id = resp.headers["x-object-id"]
            return self.get_entity(ent_id)


    def update_entity(self, entity, agent=None, metadata=None):
        """
        Only the agent_id and metadata are able to be updated via the API.
        """
        self._entity_manager.update_entity(entity, agent=agent,
                metadata=metadata)


    def delete_entity(self, entity):
        """Deletes the specified entity."""
        self._entity_manager.delete(entity)


    def list_check_types(self):
        return self._check_type_manager.list()


    def get_check_type(self, check_type):
        return self._check_type_manager.get(check_type)


    def list_checks(self, entity):
        return self._entity_manager.list_checks(entity)


    def create_check(self, entity, label=None, name=None, check_type=None,
            disabled=False, metadata=None, details=None,
            monitoring_zones_poll=None, timeout=None, period=None,
            target_alias=None, target_hostname=None, target_receiver=None,
            test_only=False, include_debug=False):
        """
        Creates a check on the entity with the specified attributes. The
        'details' parameter should be a dict with the keys as the option name,
        and the value as the desired setting.
        """
        return self._entity_manager.create_check(entity, label=label,
                name=name, check_type=check_type, disabled=disabled,
                metadata=metadata, details=details,
                monitoring_zones_poll=monitoring_zones_poll, timeout=timeout,
                period=period, target_alias=target_alias,
                target_hostname=target_hostname,
                target_receiver=target_receiver, test_only=test_only,
                include_debug=include_debug)


    def get_check(self, entity, check):
        """Returns the current check for the given entity."""
        return self._entity_manager.get_check(entity, check)


    def find_all_checks(self, entity, **kwargs):
        """
        Finds all checks for a given entity with attributes matching
        ``**kwargs``.

        This isn't very efficient: it loads the entire list then filters on
        the Python side.
        """
        return self._entity_manager.find_all_checks(entity, **kwargs)


    def update_check(self, entity, check, label=None, name=None, disabled=None,
            metadata=None, monitoring_zones_poll=None, timeout=None,
            period=None, target_alias=None, target_hostname=None,
            target_receiver=None):
        """
        Updates an existing check with any of the parameters.
        """
        self._entity_manager.update_check(entity, check, label=label,
                name=name, disabled=disabled, metadata=metadata,
                monitoring_zones_poll=monitoring_zones_poll, timeout=timeout,
                period=period, target_alias=target_alias,
                target_hostname=target_hostname,
                target_receiver=target_receiver)


    def delete_check(self, entity, check):
        """
        Deletes the specified check from the entity.
        """
        return self._entity_manager.delete_check(entity, check)


    def list_metrics(self, entity, check):
        """
        Returns a list of all the metrics associated with the specified check.
        """
        return self._entity_manager.list_metrics(entity, check)


    def get_metric_data_points(self, entity, check, metric, start, end,
            points=None, resolution=None, stats=None):
        """
        Returns the data points for a given metric for the given period. The
        'start' and 'end' times must be specified; they can be be either Python
        date/datetime values, or a Unix timestamp.

        The 'points' parameter represents the number of points to return. The
        'resolution' parameter represents the granularity of the data. You must
        specify either 'points' or 'resolution'. The allowed values for
        resolution are:
            FULL
            MIN5
            MIN20
            MIN60
            MIN240
            MIN1440

        Finally, the 'stats' parameter specifies the stats you want returned.
        By default only the 'average' is returned. You omit this parameter,
        pass in a single value, or pass in a list of values. The allowed values
        are:
            average
            variance
            min
            max
        """
        return self._entity_manager.get_metric_data_points(entity, check,
                metric, start, end, points=points, resolution=resolution,
                stats=stats)


    def list_notifications(self):
        """Returns a list of all defined notifications."""
        return self._notification_manager.list()


    def get_notification(self, notification_id):
        """
        Returns the CloudMonitorNotification object for the specified ID.
        """
        return self._notification_manager.get(notification_id)


    def test_notification(self, notification=None, notification_type=None,
            details=None):
        """
        This allows you to test either an existing notification, or a potential
        notification before creating it. The actual notification comes from the
        same server where the actual alert messages come from. This allow you
        to, among other things, verify that your firewall is configured
        properly.

        To test an existing notification, pass it as the 'notification'
        parameter and leave the other parameters empty. To pre-test a
        notification before creating it, leave 'notification' empty, but pass
        in the 'notification_type' and 'details'.
        """
        return self._notification_manager.test_notification(
                notification=notification, notification_type=notification_type,
                details=details)


    def create_notification(self, notification_type, label=None, name=None,
            details=None):
        """
        Defines a notification for handling an alarm.
        """
        return self._notification_manager.create(notification_type,
                label=label, name=name, details=details)


    def update_notification(self, notification, details):
        """
        Updates the specified notification with the supplied details.
        """
        return self._notification_manager.update_notification(notification,
                details)


    def delete_notification(self, notification):
        """
        Deletes the specified notification.
        """
        return self._notification_manager.delete(notification)


    def create_notification_plan(self, label=None, name=None,
            critical_state=None, ok_state=None, warning_state=None):
        """
        Creates a notification plan to be executed when a monitoring check
        triggers an alarm.
        """
        return self._notification_plan_manager.create(label=label, name=name,
                critical_state=critical_state, ok_state=ok_state,
                warning_state=warning_state)


    def list_notification_plans(self):
        """
        Returns a list of all defined notification plans.
        """
        return self._notification_plan_manager.list()


    def get_notification_plan(self, notification_plan_id):
        """
        Returns the CloudMonitorNotificationPlan object for the specified ID.
        """
        return self._notification_plan_manager.get(notification_plan_id)


    def delete_notification_plan(self, notification_plan):
        """
        Deletes the specified notification plan.
        """
        return self._notification_plan_manager.delete(notification_plan)


    def create_alarm(self, entity, check, notification_plan, criteria=None,
            disabled=False, label=None, name=None, metadata=None):
        """
        Creates an alarm that binds the check on the given entity with a
        notification plan.
        """
        return self._entity_manager.create_alarm(entity, check,
            notification_plan, criteria=criteria, disabled=disabled,
            label=label, name=name, metadata=metadata)


    def update_alarm(self, entity, alarm, criteria=None, disabled=False,
            label=None, name=None, metadata=None):
        """
        Updates an existing alarm on the given entity.
        """
        return self._entity_manager.update_alarm(entity, alarm,
                criteria=criteria, disabled=disabled, label=label, name=name,
                metadata=metadata)


    def list_alarms(self, entity):
        """
        Returns a list of all the alarms created on the specified entity.
        """
        return self._entity_manager.list_alarms(entity)


    def get_alarm(self, entity, alarm_id):
        """
        Returns the alarm with the specified ID for the entity.
        """
        return self._entity_manager.get_alarm(entity, alarm_id)


    def delete_alarm(self, entity, alarm):
        """
        Deletes the specified alarm.
        """
        return self._entity_manager.delete_alarm(entity, alarm)


    def list_notification_types(self):
        return self._notification_manager.list_types()


    def get_notification_type(self, nt_id):
        return self._notification_manager.get_type(nt_id)


    def list_monitoring_zones(self):
        """
        Returns a list of all available monitoring zones.
        """
        return self._monitoring_zone_manager.list()


    def get_monitoring_zone(self, mz_id):
        """
        Returns the monitoring zone for the given ID.
        """
        return self._monitoring_zone_manager.get(mz_id)


    def get_changelogs(self, entity=None):
        """
        Returns a dictionary containing the changelogs. The monitoring service
        records changelogs for alarm statuses.

        You may supply an entity to filter the results to show only the alarms
        for the specified entity.
        """
        return self._changelog_manager.list(entity=entity)


    def get_overview(self, entity=None):
        """
        Returns a dictionary containing the overview information.

        Views contain a combination of data that usually includes multiple,
        different objects. The primary purpose of a view is to save API calls
        and make data retrieval more efficient. Instead of doing multiple API
        calls and then combining the result yourself, you can perform a single
        API call against the view endpoint.

        You may supply an entity to filter the results to show only the data
        for the specified entity.
        """
        return self._overview_manager.list(entity=entity)


    #################################################################
    # The following methods are defined in the generic client class,
    # but don't have meaning in monitoring, as there is not a single
    # resource that defines this module.
    #################################################################
    def list(self, limit=None, marker=None):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError

    def get(self, item):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError

    def create(self, *args, **kwargs):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError

    def delete(self, item):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError

    def find(self, **kwargs):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError

    def findall(self, **kwargs):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError
Exemplo n.º 23
0
class CloudDatabaseClient(BaseClient):
    """
    This is the primary class for interacting with Cloud Databases.
    """
    name = "Cloud Databases"

    def _configure_manager(self):
        """
        Creates a manager to handle the instances, and another
        to handle flavors.
        """
        self._manager = CloudDatabaseManager(self,
                resource_class=CloudDatabaseInstance, response_key="instance",
                uri_base="instances")
        self._flavor_manager = BaseManager(self,
                resource_class=CloudDatabaseFlavor, response_key="flavor",
                uri_base="flavors")
        self._backup_manager = CloudDatabaseBackupManager(self,
                resource_class=CloudDatabaseBackup, response_key="backup",
                uri_base="backups")


    @assure_instance
    def list_databases(self, instance, limit=None, marker=None):
        """Returns all databases for the specified instance."""
        return instance.list_databases(limit=limit, marker=marker)


    @assure_instance
    def create_database(self, instance, name, character_set=None,
            collate=None):
        """Creates a database with the specified name on the given instance."""
        return instance.create_database(name, character_set=character_set,
                collate=collate)


    @assure_instance
    def get_database(self, instance, name):
        """
        Finds the database in the given instance with the specified name, and
        returns a CloudDatabaseDatabase object. If no match is found, a
        NoSuchDatabase exception is raised.
        """
        return instance.get_database(name)


    @assure_instance
    def delete_database(self, instance, name):
        """Deletes the database by name on the given instance."""
        return instance.delete_database(name)


    @assure_instance
    def list_users(self, instance, limit=None, marker=None):
        """Returns all users for the specified instance."""
        return instance.list_users(limit=limit, marker=marker)


    @assure_instance
    def create_user(self, instance, name, password, database_names, host=None):
        """
        Creates a user with the specified name and password, and gives that
        user access to the specified database(s).
        """
        return instance.create_user(name=name, password=password,
                database_names=database_names, host=host)


    @assure_instance
    def get_user(self, instance, name):
        """
        Finds the user in the given instance with the specified name, and
        returns a CloudDatabaseUser object. If no match is found, a
        NoSuchUser exception is raised.
        """
        return instance.get_user(name)


    @assure_instance
    def delete_user(self, instance, name):
        """Deletes the user by name on the given instance."""
        return instance.delete_user(name)


    @assure_instance
    def change_user_password(self, instance, user, new_pass):
        """
        Changes the password for the user of the specified instance to the
        supplied value.

        Returns None upon success; raises PasswordChangeFailed if the call
        does not complete successfully.
        """
        return instance.change_user_password(user, new_pass)


    @assure_instance
    def update_user(self, instance, user, name=None, password=None, host=None):
        """
        Allows you to change one or more of the user's username, password, or
        host.
        """
        return instance.update_user(user, name=name, password=password,
                host=host)


    @assure_instance
    def list_user_access(self, instance, user):
        """
        Returns a list of all database names for which the specified user
        has access rights on the specified instance.
        """
        return instance.list_user_access(user)


    @assure_instance
    def grant_user_access(self, instance, user, db_names, strict=True):
        """
        Gives access to the databases listed in `db_names` to the user
        on the specified instance.
        """
        return instance.grant_user_access(user, db_names, strict=strict)


    @assure_instance
    def revoke_user_access(self, instance, user, db_names, strict=True):
        """
        Revokes access to the databases listed in `db_names` for the user
        on the specified instance.
        """
        return instance.revoke_user_access(user, db_names, strict=strict)


    @assure_instance
    def enable_root_user(self, instance):
        """
        This enables login from any host for the root user and provides
        the user with a generated root password.
        """
        return instance.enable_root_user()


    @assure_instance
    def root_user_status(self, instance):
        """Returns True if the given instance is root-enabled."""
        return instance.root_user_status()


    @assure_instance
    def restart(self, instance):
        """Restarts the instance."""
        return instance.restart()


    @assure_instance
    def resize(self, instance, flavor):
        """Sets the size of the instance to a different flavor."""
        return instance.resize(flavor)


    def get_limits(self):
        """Not implemented in Cloud Databases."""
        raise NotImplementedError("Limits are not available for Cloud Databases")


    def list_flavors(self, limit=None, marker=None):
        """Returns a list of all available Flavors."""
        return self._flavor_manager.list(limit=limit, marker=marker)


    def get_flavor(self, flavor_id):
        """Returns a specific Flavor object by ID."""
        return self._flavor_manager.get(flavor_id)


    def _get_flavor_ref(self, flavor):
        """
        Flavors are odd in that the API expects an href link, not an ID, as with
        nearly every other resource. This method takes either a
        CloudDatabaseFlavor object, a flavor ID, a RAM size, or a flavor name,
        and uses that to determine the appropriate href.
        """
        flavor_obj = None
        if isinstance(flavor, CloudDatabaseFlavor):
            flavor_obj = flavor
        elif isinstance(flavor, int):
            # They passed an ID or a size
            try:
                flavor_obj = self.get_flavor(flavor)
            except exc.NotFound:
                # Must be either a size or bad ID, which will
                # be handled below
                pass
        if flavor_obj is None:
            # Try flavor name
            flavors = self.list_flavors()
            try:
                flavor_obj = [flav for flav in flavors
                        if flav.name == flavor][0]
            except IndexError:
                # No such name; try matching RAM
                try:
                    flavor_obj = [flav for flav in flavors
                            if flav.ram == flavor][0]
                except IndexError:
                    raise exc.FlavorNotFound("Could not determine flavor from "
                            "'%s'." % flavor)
        # OK, we have a Flavor object. Get the href
        href = [link["href"] for link in flavor_obj.links
                if link["rel"] == "self"][0]
        return href


    def list_backups(self, instance=None):
        """
        Returns a list of all backups by default, or just for a particular
        instance.
        """
        return self._backup_manager.list(instance=instance)


    def get_backup(self, backup):
        """
        Returns the CloudDatabaseBackup instance for a given ID.
        """
        return self._backup_manager.get(backup)


    def delete_backup(self, backup):
        """
        Deletes the CloudDatabaseBackup instance for a given ID.
        """
        return self._backup_manager.delete(backup)


    @assure_instance
    def create_backup(self, instance, name, description=None):
        """
        Creates a backup of the specified instance, giving it the specified
        name along with an optional description.
        """
        return instance.create_backup(name, description=description)


    def restore_backup(self, backup, name, flavor, volume):
        """
        Restores a backup to a new database instance. You must supply a backup
        (either the ID or a CloudDatabaseBackup object), a name for the new
        instance, as well as a flavor and size (in GB) for the instance.
        """
        return self._manager.restore_backup(backup, name, flavor, volume)
Exemplo n.º 24
0
class CloudMonitorClient(BaseClient):
    """
    This is the base client for creating and managing Cloud Monitoring.
    """

    def __init__(self, *args, **kwargs):
        super(CloudMonitorClient, self).__init__(*args, **kwargs)
        self.name = "Cloud Monitoring"


    def _configure_manager(self):
        """
        Creates the Manager instances to handle monitoring.
        """
        self._entity_manager = CloudMonitorEntityManager(self,
                uri_base="entities", resource_class=CloudMonitorEntity,
                response_key=None, plural_response_key=None)
        self._check_type_manager = _PaginationManager(self,
                uri_base="check_types", resource_class=CloudMonitorCheckType,
                response_key=None, plural_response_key=None)
        self._monitoring_zone_manager = BaseManager(self,
                uri_base="monitoring_zones", resource_class=CloudMonitorZone,
                response_key=None, plural_response_key=None)
        self._notification_manager = CloudMonitorNotificationManager(self,
                uri_base="notifications",
                resource_class=CloudMonitorNotification,
                response_key=None, plural_response_key=None)
        self._notification_plan_manager = CloudMonitorNotificationPlanManager(
                self, uri_base="notification_plans",
                resource_class=CloudMonitorNotificationPlan,
                response_key=None, plural_response_key=None)
        self._changelog_manager = _EntityFilteringManger(self,
                uri_base="changelogs/alarms", resource_class=None,
                response_key=None, plural_response_key=None)
        self._overview_manager = _EntityFilteringManger(self,
                uri_base="views/overview", resource_class=None,
                response_key="value", plural_response_key=None)


    def get_account(self):
        """
        Returns a dict with the following keys: id, webhook_token, and metadata.
        """
        resp, resp_body = self.method_get("/account")
        return resp_body


    def get_audits(self):
        """
        Every write operation performed against the API (PUT, POST or DELETE)
        generates an audit record that is stored for 30 days. Audits record a
        variety of information about the request including the method, URL,
        headers, query string, transaction ID, the request body and the
        response code. They also store information about the action performed
        including a JSON list of the previous state of any modified objects.
        For example, if you perform an update on an entity, this will record
        the state of the entity before modification.
        """
        resp, resp_body = self.method_get("/audits")
        return resp_body["values"]


    def list_entities(self, limit=None, marker=None, return_next=False):
        return self._entity_manager.list(limit=limit, marker=marker,
                return_next=return_next)


    def get_entity(self, entity):
        return self._entity_manager.get(entity)


    def create_entity(self, label=None, name=None, agent=None,
            ip_addresses=None, metadata=None):
        # NOTE: passing a non-None value for ip_addresses is required so that
        # the _create_body() method can distinguish this as a request for a
        # body dict for entities.
        ip_addresses = ip_addresses or {}
        resp = self._entity_manager.create(label=label, name=name, agent=agent,
                ip_addresses=ip_addresses, metadata=metadata,
                return_response=True)
        if resp.status_code == 201:
            ent_id = resp.headers["x-object-id"]
            return self.get_entity(ent_id)


    def update_entity(self, entity, agent=None, metadata=None):
        """
        Only the agent_id and metadata are able to be updated via the API.
        """
        self._entity_manager.update_entity(entity, agent=agent,
                metadata=metadata)


    def delete_entity(self, entity):
        """Deletes the specified entity."""
        self._entity_manager.delete(entity)


    def list_check_types(self, limit=None, marker=None, return_next=False):
        return self._check_type_manager.list(limit=limit, marker=marker,
                return_next=return_next)


    def get_check_type(self, check_type):
        return self._check_type_manager.get(check_type)


    @assure_entity
    def list_checks(self, entity, limit=None, marker=None, return_next=False):
        return entity.list_checks(limit=limit, marker=marker,
                return_next=return_next)


    @assure_entity
    def create_check(self, entity, label=None, name=None, check_type=None,
            disabled=False, metadata=None, details=None,
            monitoring_zones_poll=None, timeout=None, period=None,
            target_alias=None, target_hostname=None, target_receiver=None,
            test_only=False, include_debug=False):
        """
        Creates a check on the entity with the specified attributes. The
        'details' parameter should be a dict with the keys as the option name,
        and the value as the desired setting.
        """
        return entity.create_check(label=label, name=name,
                check_type=check_type, disabled=disabled, metadata=metadata,
                details=details, monitoring_zones_poll=monitoring_zones_poll,
                timeout=timeout, period=period, target_alias=target_alias,
                target_hostname=target_hostname,
                target_receiver=target_receiver, test_only=test_only,
                include_debug=include_debug)


    @assure_entity
    def get_check(self, entity, check):
        """Returns the current check for the given entity."""
        return entity.get_check(check)


    @assure_entity
    def find_all_checks(self, entity, **kwargs):
        """
        Finds all checks for a given entity with attributes matching
        ``**kwargs``.

        This isn't very efficient: it loads the entire list then filters on
        the Python side.
        """
        return entity.find_all_checks(**kwargs)


    @assure_entity
    def update_check(self, entity, check, label=None, name=None, disabled=None,
            metadata=None, monitoring_zones_poll=None, timeout=None,
            period=None, target_alias=None, target_hostname=None,
            target_receiver=None):
        """
        Updates an existing check with any of the parameters.
        """
        entity.update_check(check, label=label, name=name, disabled=disabled,
                metadata=metadata, monitoring_zones_poll=monitoring_zones_poll,
                timeout=timeout, period=period, target_alias=target_alias,
                target_hostname=target_hostname,
                target_receiver=target_receiver)


    @assure_entity
    def delete_check(self, entity, check):
        """
        Deletes the specified check from the entity.
        """
        return entity.delete_check(check)


    @assure_entity
    def list_metrics(self, entity, check, limit=None, marker=None,
            return_next=False):
        """
        Returns a list of all the metrics associated with the specified check.
        """
        return entity.list_metrics(check, limit=limit, marker=marker,
                return_next=return_next)


    @assure_entity
    def get_metric_data_points(self, entity, check, metric, start, end,
            points=None, resolution=None, stats=None):
        """
        Returns the data points for a given metric for the given period. The
        'start' and 'end' times must be specified; they can be be either Python
        date/datetime values, or a Unix timestamp.

        The 'points' parameter represents the number of points to return. The
        'resolution' parameter represents the granularity of the data. You must
        specify either 'points' or 'resolution'. The allowed values for
        resolution are:
            FULL
            MIN5
            MIN20
            MIN60
            MIN240
            MIN1440

        Finally, the 'stats' parameter specifies the stats you want returned.
        By default only the 'average' is returned. You omit this parameter,
        pass in a single value, or pass in a list of values. The allowed values
        are:
            average
            variance
            min
            max
        """
        return entity.get_metric_data_points(check, metric, start, end,
                points=points, resolution=resolution, stats=stats)


    def list_notifications(self):
        """Returns a list of all defined notifications."""
        return self._notification_manager.list()


    def get_notification(self, notification_id):
        """
        Returns the CloudMonitorNotification object for the specified ID.
        """
        return self._notification_manager.get(notification_id)


    def test_notification(self, notification=None, notification_type=None,
            details=None):
        """
        This allows you to test either an existing notification, or a potential
        notification before creating it. The actual notification comes from the
        same server where the actual alert messages come from. This allow you
        to, among other things, verify that your firewall is configured
        properly.

        To test an existing notification, pass it as the 'notification'
        parameter and leave the other parameters empty. To pre-test a
        notification before creating it, leave 'notification' empty, but pass
        in the 'notification_type' and 'details'.
        """
        return self._notification_manager.test_notification(
                notification=notification, notification_type=notification_type,
                details=details)


    def create_notification(self, notification_type, label=None, name=None,
            details=None):
        """
        Defines a notification for handling an alarm.
        """
        return self._notification_manager.create(notification_type,
                label=label, name=name, details=details)


    def update_notification(self, notification, details):
        """
        Updates the specified notification with the supplied details.
        """
        return self._notification_manager.update_notification(notification,
                details)


    def delete_notification(self, notification):
        """
        Deletes the specified notification.
        """
        return self._notification_manager.delete(notification)


    def create_notification_plan(self, label=None, name=None,
            critical_state=None, ok_state=None, warning_state=None):
        """
        Creates a notification plan to be executed when a monitoring check
        triggers an alarm.
        """
        return self._notification_plan_manager.create(label=label, name=name,
                critical_state=critical_state, ok_state=ok_state,
                warning_state=warning_state)


    def list_notification_plans(self):
        """
        Returns a list of all defined notification plans.
        """
        return self._notification_plan_manager.list()


    def get_notification_plan(self, notification_plan_id):
        """
        Returns the CloudMonitorNotificationPlan object for the specified ID.
        """
        return self._notification_plan_manager.get(notification_plan_id)


    def delete_notification_plan(self, notification_plan):
        """
        Deletes the specified notification plan.
        """
        return self._notification_plan_manager.delete(notification_plan)


    def create_alarm(self, entity, check, notification_plan, criteria=None,
            disabled=False, label=None, name=None, metadata=None):
        """
        Creates an alarm that binds the check on the given entity with a
        notification plan.
        """
        return self._entity_manager.create_alarm(entity, check,
            notification_plan, criteria=criteria, disabled=disabled,
            label=label, name=name, metadata=metadata)


    def update_alarm(self, entity, alarm, criteria=None, disabled=False,
            label=None, name=None, metadata=None):
        """
        Updates an existing alarm on the given entity.
        """
        return self._entity_manager.update_alarm(entity, alarm,
                criteria=criteria, disabled=disabled, label=label, name=name,
                metadata=metadata)


    @assure_entity
    def list_alarms(self, entity, limit=None, marker=None, return_next=False):
        """
        Returns a list of all the alarms created on the specified entity.
        """
        return entity.list_alarms(limit=limit, marker=marker,
                return_next=return_next)


    def get_alarm(self, entity, alarm_id):
        """
        Returns the alarm with the specified ID for the entity.
        """
        return self._entity_manager.get_alarm(entity, alarm_id)


    def delete_alarm(self, entity, alarm):
        """
        Deletes the specified alarm.
        """
        return self._entity_manager.delete_alarm(entity, alarm)


    def list_notification_types(self):
        return self._notification_manager.list_types()


    def get_notification_type(self, nt_id):
        return self._notification_manager.get_type(nt_id)


    def list_monitoring_zones(self):
        """
        Returns a list of all available monitoring zones.
        """
        return self._monitoring_zone_manager.list()


    def get_monitoring_zone(self, mz_id):
        """
        Returns the monitoring zone for the given ID.
        """
        return self._monitoring_zone_manager.get(mz_id)


    def get_changelogs(self, entity=None):
        """
        Returns a dictionary containing the changelogs. The monitoring service
        records changelogs for alarm statuses.

        You may supply an entity to filter the results to show only the alarms
        for the specified entity.
        """
        return self._changelog_manager.list(entity=entity)


    def get_overview(self, entity=None):
        """
        Returns a dictionary containing the overview information.

        Views contain a combination of data that usually includes multiple,
        different objects. The primary purpose of a view is to save API calls
        and make data retrieval more efficient. Instead of doing multiple API
        calls and then combining the result yourself, you can perform a single
        API call against the view endpoint.

        You may supply an entity to filter the results to show only the data
        for the specified entity.
        """
        return self._overview_manager.list(entity=entity)


    #################################################################
    # The following methods are defined in the generic client class,
    # but don't have meaning in monitoring, as there is not a single
    # resource that defines this module.
    #################################################################
    def list(self, limit=None, marker=None):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError

    def get(self, item):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError

    def create(self, *args, **kwargs):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError

    def delete(self, item):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError

    def find(self, **kwargs):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError

    def findall(self, **kwargs):
        """Not applicable in Cloud Monitoring."""
        raise NotImplementedError
Exemplo n.º 25
0
class CloudBlockStorageClient(BaseClient):
    """
    This is the primary class for interacting with Cloud Block Storage.
    """
    def _configure_manager(self):
        """
        Create the manager to handle the instances, and also another
        to handle flavors.
        """
        self._manager = BaseManager(self,
                resource_class=CloudBlockStorageVolume, response_key="volume",
                uri_base="volumes")
        self._types_manager = BaseManager(self,
                resource_class=CloudBlockStorageVolumeType,
                response_key="volume_type", uri_base="types")
        self._snaps_manager = BaseManager(self,
                resource_class=CloudBlockStorageSnapshot,
                response_key="snapshot", uri_base="snapshots")


    def create(self, name="", size=None, volume_type=None, description=None,
             metadata=None, snapshot_id=None, availability_zone=None):
        """
        Makes sure that the size is passed and is within allowed values.
        """
        if not isinstance(size, (int, long)) or not (
                MIN_SIZE <= size <= MAX_SIZE):
            raise exc.InvalidSize("Volume sizes must be integers between "
                    "%s and %s." % (MIN_SIZE, MAX_SIZE))
        return super(CloudBlockStorageClient, self).create(name, size=size,
                volume_type=volume_type, description=description,
                metadata=metadata, snapshot_id=snapshot_id,
                availability_zone=availability_zone)


    def list_types(self):
        """Returns a list of all available volume types."""
        return self._types_manager.list()


    def list_snapshots(self):
        """Returns a list of all snapshots."""
        return self._snaps_manager.list()


    def _create_body(self, name, size=None, volume_type=None, description=None,
             metadata=None, snapshot_id=None, availability_zone=None,
             volume=None, force=False):
        """
        Used to create the dict required to create any of the following:
            A new volume
            A new snapshot
        """
        if size is not None:
            # Creating a volume
            if not isinstance(size, (int, long)) or not (
                    MIN_SIZE <= size <= MAX_SIZE):
                raise exc.InvalidSize("Volume sizes must be integers between "
                        "%s and %s." % (MIN_SIZE, MAX_SIZE))
            if volume_type is None:
                volume_type = "SATA"
            if description is None:
                description = ""
            if metadata is None:
                metadata = {}
            body = {"volume": {
                    "size": size,
                    "snapshot_id": snapshot_id,
                    "display_name": name,
                    "display_description": description,
                    "volume_type": volume_type,
                    "metadata": metadata,
                    "availability_zone": availability_zone,
                    }}
        else:
            # Creating a snapshot
            body = {"snapshot": {
                    "display_name": name,
                    "display_description": description,
                    "volume_id": volume.id,
                    "force": str(force).lower(),
                 }}
        return body


    @assure_volume
    def attach_to_instance(self, volume, instance, mountpoint):
        """Attaches the volume to the specified instance at the mountpoint."""
        return volume.attach_to_instance(instance, mountpoint)


    @assure_volume
    def detach(self, volume):
        """Detaches the volume from whatever device it is attached to."""
        return volume.detach()


    @assure_volume
    def delete_volume(self, volume, force=False):
        """Deletes the volume."""
        return volume.delete(force=force)


    @assure_volume
    def create_snapshot(self, volume, name=None, description=None, force=False):
        """
        Creates a snapshot of the volume, with an optional name and description.

        Normally snapshots will not happen if the volume is attached. To
        override this default behavior, pass force=True.
        """
        return volume.create_snapshot(name=name, description=description,
                force=force)


    @assure_snapshot
    def delete_snapshot(self, snapshot):
        """Deletes the snapshot."""
        return snapshot.delete()
Exemplo n.º 26
0
class CloudBlockStorageVolume(BaseResource):
    """
    This class represents a Block Storage volume.
    """
    def __init__(self, *args, **kwargs):
        super(CloudBlockStorageVolume, self).__init__(*args, **kwargs)
        try:
            self._nova_volumes = pyrax.cloudservers.volumes
        except AttributeError:
            # This will happen in unit testing, where the full pyrax
            # namespace is not exposed. In that situation, there is
            # no need for the reference anyway
            pass
        self._snapshot_manager = BaseManager(self.manager.api,
                resource_class=CloudBlockStorageSnapshot,
                response_key="snapshot", uri_base="snapshots")


    def attach_to_instance(self, instance, mountpoint):
        """
        Attaches this volume to the cloud server instance at the
        specified mountpoint. This requires a call to the cloud servers
        API; it cannot be done directly.
        """
        instance_id = _resolve_id(instance)
        resp = self._nova_volumes.create_server_volume(instance_id,
                self.id, mountpoint)
        # The response should be a volume reference to this volume.
        return resp.id == self.id


    def detach(self):
        """
        Detaches this volume from any device it may be attached to. If it
        is not attached, nothing happens.
        """
        attachments = self.attachments
        if not attachments:
            # Not attached; no error needed, just return
            return
        # A volume can only be attached to one device at a time, but for some
        # reason this is a list instead of a singular value
        att = attachments[0]
        instance_id = att["server_id"]
        attachment_id = att["id"]
        self._nova_volumes.delete_server_volume(instance_id, attachment_id)


    def delete(self, force=False):
        """
        Volumes cannot be deleted if either a) they are attached to a device, or
        b) they have any snapshots. This method overrides the base delete()
        method to both better handle these failures, and also to offer a 'force'
        option. When 'force' is True, the volume is detached, and any dependent
        snapshots are deleted before calling the volume's delete.
        """
        if force:
            self.detach()
            self.delete_all_snapshots()
        try:
            super(CloudBlockStorageVolume, self).delete()
        except exc.VolumeNotAvailable:
            # Notify the user? Record it somewhere?
            # For now, just re-raise
            raise


    def create_snapshot(self, name=None, description=None, force=False):
        """
        Creates a snapshot of this volume, with an optional name and
        description.

        Normally snapshots will not happen if the volume is attached. To
        override this default behavior, pass force=True.
        """
        name = name or ""
        description = description or ""
        # Note that passing in non-None values is required for the _create_body
        # method to distinguish between this and the request to create and
        # instance.
        try:
            snap = self._snapshot_manager.create(volume=self, name=name,
                    description=description, force=force)
        except exc.BadRequest as e:
            msg = str(e)
            if "Invalid volume: must be available" in msg:
                # The volume for the snapshot was attached.
                raise exc.VolumeNotAvailable("Cannot create a snapshot from an "
                        "attached volume. Detach the volume before trying again, "
                        "or pass 'force=True' to the create_snapshot() call.")
            else:
                # Some other error
                raise
        except exc.ClientException as e:
            if e.code == 409:
                if "Request conflicts with in-progress" in str(e):
                    raise exc.VolumeNotAvailable("The volume is current "
                            "creating a snapshot. You must wait until that "
                            "completes before attempting to create an "
                            "additional snapshot.")
                else:
                    raise
            else:
                raise
        return snap


    def list_snapshots(self):
        """
        Returns a list of all snapshots of this volume.
        """
        return [snap for snap in self._snapshot_manager.list()
                if snap.volume_id == self.id]


    def delete_all_snapshots(self):
        """
        Locates all snapshots of this volume and deletes them.
        """
        for snap in self.list_snapshots():
            snap.delete()


    def _get_name(self):
        return self.display_name

    def _set_name(self, val):
        self.display_name = val

    name = property(_get_name, _set_name, None,
            "Convenience for referencing the display_name.")

    def _get_description(self):
        return self.display_description

    def _set_description(self, val):
        self.display_description = val

    description = property(_get_description, _set_description, None,
            "Convenience for referencing the display_description.")
Exemplo n.º 27
0
class CloudBlockStorageClient(BaseClient):
    """
    This is the primary class for interacting with Cloud Block Storage.
    """
    name = "Cloud Block Storage"

    def _configure_manager(self):
        """
        Create the manager to handle the instances, and also another
        to handle flavors.
        """
        self._manager = CloudBlockStorageManager(self,
                resource_class=CloudBlockStorageVolume, response_key="volume",
                uri_base="volumes")
        self._types_manager = BaseManager(self,
                resource_class=CloudBlockStorageVolumeType,
                response_key="volume_type", uri_base="types")
        self._snapshot_manager = CloudBlockStorageSnapshotManager(self,
                resource_class=CloudBlockStorageSnapshot,
                response_key="snapshot", uri_base="snapshots")


    def list_types(self):
        """Returns a list of all available volume types."""
        return self._types_manager.list()


    def list_snapshots(self):
        """Returns a list of all snapshots."""
        return self._snapshot_manager.list()


    @assure_volume
    def attach_to_instance(self, volume, instance, mountpoint):
        """Attaches the volume to the specified instance at the mountpoint."""
        return volume.attach_to_instance(instance, mountpoint)


    @assure_volume
    def detach(self, volume):
        """Detaches the volume from whatever device it is attached to."""
        return volume.detach()


    @assure_volume
    def delete_volume(self, volume, force=False):
        """Deletes the volume."""
        return volume.delete(force=force)


    @assure_volume
    def create_snapshot(self, volume, name=None, description=None, force=False):
        """
        Creates a snapshot of the volume, with an optional name and description.

        Normally snapshots will not happen if the volume is attached. To
        override this default behavior, pass force=True.
        """
        return self._snapshot_manager.create(volume=volume, name=name,
                description=description, force=force)


    @assure_snapshot
    def delete_snapshot(self, snapshot):
        """Deletes the snapshot."""
        return snapshot.delete()
Exemplo n.º 28
0
class CloudBlockStorageClient(BaseClient):
    """
    This is the primary class for interacting with Cloud Block Storage.
    """
    name = "Cloud Block Storage"

    def _configure_manager(self):
        """
        Create the manager to handle the instances, and also another
        to handle flavors.
        """
        self._manager = CloudBlockStorageManager(
            self,
            resource_class=CloudBlockStorageVolume,
            response_key="volume",
            uri_base="volumes")
        self._types_manager = BaseManager(
            self,
            resource_class=CloudBlockStorageVolumeType,
            response_key="volume_type",
            uri_base="types")
        self._snapshot_manager = CloudBlockStorageSnapshotManager(
            self,
            resource_class=CloudBlockStorageSnapshot,
            response_key="snapshot",
            uri_base="snapshots")

    def list_types(self):
        """Returns a list of all available volume types."""
        return self._types_manager.list()

    def list_snapshots(self):
        """Returns a list of all snapshots."""
        return self._snapshot_manager.list()

    @assure_volume
    def attach_to_instance(self, volume, instance, mountpoint):
        """Attaches the volume to the specified instance at the mountpoint."""
        return volume.attach_to_instance(instance, mountpoint)

    @assure_volume
    def detach(self, volume):
        """Detaches the volume from whatever device it is attached to."""
        return volume.detach()

    @assure_volume
    def delete_volume(self, volume, force=False):
        """Deletes the volume."""
        return volume.delete(force=force)

    @assure_volume
    def update(self, volume, display_name=None, display_description=None):
        """
        Update the specified values on the specified volume. You may specify
        one or more values to update. If no values are specified as non-None,
        the call is a no-op; no exception will be raised.
        """
        return volume.update(display_name=display_name,
                             display_description=display_description)

    def rename(self, volume, name):
        """
        Allows for direct renaming of an existing volume.
        """
        return self.update(volume, display_name=name)

    @assure_volume
    def create_snapshot(self,
                        volume,
                        name=None,
                        description=None,
                        force=False):
        """
        Creates a snapshot of the volume, with an optional name and description.

        Normally snapshots will not happen if the volume is attached. To
        override this default behavior, pass force=True.
        """
        return self._snapshot_manager.create(volume=volume,
                                             name=name,
                                             description=description,
                                             force=force)

    def get_snapshot(self, snapshot):
        """
        Returns the snapshot with the specified snapshot ID value.
        """
        return self._snapshot_manager.get(snapshot)

    @assure_snapshot
    def delete_snapshot(self, snapshot):
        """Deletes the snapshot."""
        return snapshot.delete()

    @assure_snapshot
    def update_snapshot(self,
                        snapshot,
                        display_name=None,
                        display_description=None):
        """
        Update the specified values on the specified snapshot. You may specify
        one or more values to update.
        """
        return snapshot.update(display_name=display_name,
                               display_description=display_description)

    def rename_snapshot(self, snapshot, name):
        """
        Allows for direct renaming of an existing snapshot.
        """
        return self.update_snapshot(snapshot, display_name=name)
Exemplo n.º 29
0
class CloudBlockStorageClient(BaseClient):
    """
    This is the primary class for interacting with Cloud Block Storage.
    """
    name = "Cloud Block Storage"

    def _configure_manager(self):
        """
        Create the manager to handle the instances, and also another
        to handle flavors.
        """
        self._manager = CloudBlockStorageManager(
            self,
            resource_class=CloudBlockStorageVolume,
            response_key="volume",
            uri_base="volumes")
        self._types_manager = BaseManager(
            self,
            resource_class=CloudBlockStorageVolumeType,
            response_key="volume_type",
            uri_base="types")
        self._snapshot_manager = CloudBlockStorageSnapshotManager(
            self,
            resource_class=CloudBlockStorageSnapshot,
            response_key="snapshot",
            uri_base="snapshots")

    def create(self,
               name="",
               size=None,
               volume_type=None,
               description=None,
               metadata=None,
               snapshot_id=None,
               availability_zone=None):
        """
        Makes sure that the size is passed and is within allowed values.
        """
        if not isinstance(size,
                          (int, long)) or not (MIN_SIZE <= size <= MAX_SIZE):
            raise exc.InvalidSize("Volume sizes must be integers between "
                                  "%s and %s." % (MIN_SIZE, MAX_SIZE))
        return super(CloudBlockStorageClient,
                     self).create(name,
                                  size=size,
                                  volume_type=volume_type,
                                  description=description,
                                  metadata=metadata,
                                  snapshot_id=snapshot_id,
                                  availability_zone=availability_zone)

    def list_types(self):
        """Returns a list of all available volume types."""
        return self._types_manager.list()

    def list_snapshots(self):
        """Returns a list of all snapshots."""
        return self._snapshot_manager.list()

    @assure_volume
    def attach_to_instance(self, volume, instance, mountpoint):
        """Attaches the volume to the specified instance at the mountpoint."""
        return volume.attach_to_instance(instance, mountpoint)

    @assure_volume
    def detach(self, volume):
        """Detaches the volume from whatever device it is attached to."""
        return volume.detach()

    @assure_volume
    def delete_volume(self, volume, force=False):
        """Deletes the volume."""
        return volume.delete(force=force)

    @assure_volume
    def create_snapshot(self,
                        volume,
                        name=None,
                        description=None,
                        force=False):
        """
        Creates a snapshot of the volume, with an optional name and description.

        Normally snapshots will not happen if the volume is attached. To
        override this default behavior, pass force=True.
        """
        return self._snapshot_manager.create(volume=volume,
                                             name=name,
                                             description=description,
                                             force=force)

    @assure_snapshot
    def delete_snapshot(self, snapshot):
        """Deletes the snapshot."""
        return snapshot.delete()
Exemplo n.º 30
0
class CloudBlockStorageClient(BaseClient):
    """
    This is the primary class for interacting with Cloud Block Storage.
    """
    name = "Cloud Block Storage"

    def _configure_manager(self):
        """
        Create the manager to handle the instances, and also another
        to handle flavors.
        """
        self._manager = CloudBlockStorageManager(self,
                resource_class=CloudBlockStorageVolume, response_key="volume",
                uri_base="volumes")
        self._types_manager = BaseManager(self,
                resource_class=CloudBlockStorageVolumeType,
                response_key="volume_type", uri_base="types")
        self._snapshot_manager = CloudBlockStorageSnapshotManager(self,
                resource_class=CloudBlockStorageSnapshot,
                response_key="snapshot", uri_base="snapshots")


    def list_types(self):
        """Returns a list of all available volume types."""
        return self._types_manager.list()


    def list_snapshots(self):
        """Returns a list of all snapshots."""
        return self._snapshot_manager.list()


    @assure_volume
    def attach_to_instance(self, volume, instance, mountpoint):
        """Attaches the volume to the specified instance at the mountpoint."""
        return volume.attach_to_instance(instance, mountpoint)


    @assure_volume
    def detach(self, volume):
        """Detaches the volume from whatever device it is attached to."""
        return volume.detach()


    @assure_volume
    def delete_volume(self, volume, force=False):
        """Deletes the volume."""
        return volume.delete(force=force)


    @assure_volume
    def update(self, volume, display_name=None, display_description=None):
        """
        Update the specified values on the specified volume. You may specify
        one or more values to update. If no values are specified as non-None,
        the call is a no-op; no exception will be raised.
        """
        return volume.update(display_name=display_name,
                display_description=display_description)


    def rename(self, volume, name):
        """
        Allows for direct renaming of an existing volume.
        """
        return self.update(volume, display_name=name)


    @assure_volume
    def create_snapshot(self, volume, name=None, description=None, force=False):
        """
        Creates a snapshot of the volume, with an optional name and description.

        Normally snapshots will not happen if the volume is attached. To
        override this default behavior, pass force=True.
        """
        return self._snapshot_manager.create(volume=volume, name=name,
                description=description, force=force)


    def get_snapshot(self, snapshot):
        """
        Returns the snapshot with the specified snapshot ID value.
        """
        return self._snapshot_manager.get(snapshot)


    @assure_snapshot
    def delete_snapshot(self, snapshot):
        """Deletes the snapshot."""
        return snapshot.delete()


    @assure_snapshot
    def update_snapshot(self, snapshot, display_name=None,
            display_description=None):
        """
        Update the specified values on the specified snapshot. You may specify
        one or more values to update.
        """
        return snapshot.update(display_name=display_name,
                display_description=display_description)


    def rename_snapshot(self, snapshot, name):
        """
        Allows for direct renaming of an existing snapshot.
        """
        return self.update_snapshot(snapshot, display_name=name)