Exemple #1
0
 def test_service(self):
     sot = database_service.DatabaseService()
     self.assertEqual("rax:database", sot.service_type)
     self.assertEqual("public", sot.interface)
     self.assertIsNone(sot.region)
     self.assertEqual("cloudDatabases", sot.service_name)
     self.assertEqual(1, len(sot.valid_versions))
     self.assertEqual("v1", sot.valid_versions[0].module)
     self.assertEqual("v1.0", sot.valid_versions[0].path)
Exemple #2
0
class Configuration(resource.Resource):
    base_path = '/configurations'
    resource_key = "configuration"
    resources_key = "configurations"
    service = database_service.DatabaseService()

    # capabilities
    allow_create = True
    allow_delete = True
    allow_list = True
    allow_retrieve = True
    allow_update = True
    patch_update = True

    # Properties
    #: The name of this configuration
    name = resource.prop("name")
    #: The id of this configuration
    id = resource.prop("id")
    #: Dictionary of datastore details, with  `type` and `version` keys
    datastore = resource.prop("datastore", type=dict)
    #: The values for the configuration.
    values = resource.prop("values", type=dict)
    #: The name of the datastore
    datastore_name = resource.prop("datastore_name")
    #: The version name of the datastore
    datastore_version_name = resource.prop("datastore_version_name")
    #: The version id of the datastore
    datastore_version_id = resource.prop("datastore_version_id")
    #: The last time this configuration was updated
    updated_at = resource.prop("updated")
    #: The time when this configuration was created
    created_at = resource.prop("created")
    #: A description of this datastore
    description = resource.prop("description")

    def update(self, session, prepend_key=True, has_body=False):
        # Only try to update if we actually have anything to update.
        if not any([self._body.dirty, self._header.dirty]):
            return self

        request = self._prepare_request(prepend_key=prepend_key)

        response = session.patch(request.uri,
                                 endpoint_filter=self.service,
                                 json=request.body,
                                 headers=request.headers)

        self._translate_response(response, has_body=has_body)
        return self

    def instances(self):
        yield
Exemple #3
0
class BackupSchedule(resource.Resource):
    id_attribute = 'id'
    base_path = 'schedules'
    resources_key = "schedules"
    service = database_service.DatabaseService()

    # capabilities
    allow_create = True
    allow_delete = True
    allow_list = True
    allow_retrieve = True
    allow_update = True

    # Properties
    #: Action (backup)
    action = resource.prop('action')
    #: Creation time
    created_at = resource.prop('created')
    #: Last scheduled run
    last_run = resource.prop('last_scheduled')
    #: Next scheduled run
    next_run = resource.prop('next_run')
    #: The instance ID of the source
    source_instance = resource.prop('instance_id', type=instance.Instance)
    #: Scheduled day of the month
    start_day_of_month_at = resource.prop('day_of_month')
    #: Scheduled day of the week
    start_day_of_week_at = resource.prop('day_of_week')
    #: Scheduled hour of the day
    start_hour_at = resource.prop('hour')
    #: Scheduled minute of the hour
    start_minute_at = resource.prop('minute')
    #: Scheduled month of the year
    start_month_at = resource.prop('month')
    #: Update time
    updated_at = resource.prop('updated')
class HighAvailabilityInstance(resource.Resource):
    base_path = 'ha'
    resource_key = 'ha_instance'
    resources_key = 'ha_instances'
    service = database_service.DatabaseService()

    # capabilities
    allow_create = True
    allow_delete = True
    allow_list = True
    allow_retrieve = True
    allow_update = True

    # Properties
    #: Access control lists. *Type: list*
    acls = resource.prop('acls', type=list)
    #: Datastore type and version. *Type: dict*
    datastore = resource.prop('datastore', type=dict)
    #: A dictionary with details on the flavor this server is running.
    #: The dictionary includes a key for the ``id`` of the flavor, as well
    #: as a ``links`` key, which includes a list of relevant links for this
    #: flavor. *Type: flavor.Flavor*
    flavor = resource.prop('flavor', type=flavor.Flavor)
    #: Name of High Availability instance
    name = resource.prop('name')
    #: Networks. *Type: list*
    networks = resource.prop('networks', type=list)
    #: Replica instances. *Type: list*
    replicas = resource.prop('replicas', type=list)
    #: Replica sources. *Type: list*
    replica_source = resource.prop('replica_source', type=list)
    #: The source instance ID for a backup
    source_instance = resource.prop('instance_id')
    #: The state this HA instance is in. Valid values include:
    status = resource.prop('state')
    #: Volumes. *Type: dict*
    volume = resource.prop('volume', type=dict)
    #: The configuration ID for this instance. *Type: string*
    configuration_id = resource.prop('configuration')
    #: The status of scheduled backups. *Type: dict*
    scheduled_backup = resource.prop('scheduled_backup')

    @classmethod
    def _get_create_body(cls, attrs):
        return {'ha': attrs}

    def add_acl(self, session, cidr):
        """Add Access Control List (ACL)

        :param session: The session to use for making this request.
        :param str cidr: Specifies a CIDR notated IPV4 address.
        :type session: :class:`~openstack.session.Session`
        :returns: ``None``
        """
        body = {"address": cidr}
        url = utils.urljoin(self.base_path, self.id, 'acls')
        session.post(url, service=self.service, json=body)

    def delete_acl(self, session, cidr):
        """Delete Access Control List (ACL)

        :param session: The session to use for making this request.
        :param str cidr: Specifies a CIDR notated IPV4 address.
        :type session: :class:`~openstack.session.Session`
        :returns: ``None``
        """
        url = utils.urljoin(self.base_path, self.id, 'acls', cidr)
        session.delete(url, service=self.service)

    def get_acls(self, session):
        """Get Access Control Lists (ACLs)

        :param session: The session to use for making this request.
        :type session: :class:`~openstack.session.Session`
        :returns: ``dict``
        """
        url = utils.urljoin(self.base_path, self.id, 'acls')
        resp = session.get(url, service=self.service).body
        return resp['acls']

    def get_backups(self, session):
        """Lists backups for the HA instance

        :param session: The session to use for making this request.
        :type session: :class:`~openstack.session.Session`
        :returns: ``list``
        """
        url = utils.urljoin(self.base_path, self.id, 'backups')
        resp = session.get(url, service=self.service).body
        return resp['backups']

    def add_replica(self, session, name, flavor_reference, volume_size):
        """Add a replica node to the HA group

        For the duration of this action, the HA instance goes into the
        ``ADDING_REPLICA`` state as a result of this action. It switches back
        to ``ACTIVE`` once the operation is complete. Adding a new replica node
        would restart the ``mha`` manager service (which monitors the
        source/replica instances to trigger failover) and the haproxy service
        on the load balancer nodes.

        :param session: The session to use for making this request.
        :param str name: Name of the replica instance.
        :param str flavor_reference: The flavor ID.
        :param str volume_size: The volume size.
        :type session: :class:`~openstack.session.Session`
        :returns: ``None``
        """
        body = {"add_replica": {"replica_details":
                {"volume": {"size": volume_size},
                 "flavorRef": flavor_reference,
                 "name": name}}}
        url = utils.urljoin(self.base_path, self.id, 'action')
        session.post(url, service=self.service, json=body)

    def remove_replica(self, session, replica_id):
        """Remove/detach a replica node from the HA group

        Detaching a replica from the HA setup will cause a MySQL service
        restart on the detached instance.

        For the duration of this action, the HA instance goes into the
        ``REMOVING_REPLICA`` state as a result of this action. It switches back
        to ``ACTIVE`` once the operation is complete. The instance that is
        detached also goes into a ``DETACH_REPLICA`` state when it is being
        disabled as a replica and switches back to ``ACTIVE`` once detached.
        Removing a replica node would restart the ``mha`` manager service
        (which monitors the source/replica instances to trigger failover) and
        the haproxy service on the load balancer nodes.

        :param session: The session to use for making this request.
        :param str replica_id: The attached replica ID to detach.
        :type session: :class:`~openstack.session.Session`
        :returns: ``None``
        """
        body = {"remove_replica": replica_id}
        url = utils.urljoin(self.base_path, self.id, 'action')
        session.post(url, service=self.service, json=body)

    def resize(self, session, flavor_reference):
        """Resize the HA instance

        For the duration of this action, the HA instance goes into a
        ``RESIZING_FLAVOR`` state and switches back to ``ACTIVE`` once the
        action is complete. Resizing the flavor of the HA cluster would restart
        the ``mha`` manager service (which monitors the source/replica
        instances to trigger failover) and the haproxy service on the
        load balancer nodes.

        :param session: The session to use for making this request.
        :param str flavor_reference: The flavor ID.
        :type session: :class:`~openstack.session.Session`
        :returns: ``None``
        """

        body = {'resize': {'flavorRef': flavor_reference}}
        url = utils.urljoin(self.base_path, self.id, 'action')
        session.post(url, service=self.service, json=body)

    def resize_volume(self, session, volume_size):
        """Resize the volume attached to the HA instance

        Only increasing the size is allowed. Resize down is prevented.

        For the duration of this action, the HA instance goes into a
        ``RESIZING_VOLUME`` state and switches back to ``ACTIVE`` once the
        action is complete across the entire HA cluster. Resizing the flavor of
        the HA cluster would restart the ``mha`` manager service (which
        monitors the source/replica instances to trigger failover) and the
        haproxy service on the load balancer nodes.

        :param session: The session to use for making this request.
        :param str volume_size: The volume size.
        :type session: :class:`~openstack.session.Session`
        :returns: ``None``
        """
        body = {'resize': {'volume': volume_size}}
        url = utils.urljoin(self.base_path, self.id, 'action')
        session.post(url, service=self.service, json=body)

    def restart(self, session):
        """Restart the database instance

        :param session: The session to use for making this request.
        :type session: :class:`~openstack.session.Session`
        :returns: ``None``
        """
        body = {'restart': {}}
        url = utils.urljoin(self.base_path, self.id, 'action')
        session.post(url, endpoint_filter=self.service, json=body)

    def add_configuration(self, session, configuration_id):
        """Adds a specified configuration group to the HA Instance.

        :param session: The session to use for making this request.
        :param str configuration_id: The configuration group ID.
        :type session: :class:`~openstack.session.Session`
        :returns: ``None``
        """
        body = {'ha_instance': {'configuration_id': configuration_id}}
        url = utils.urljoin(self.base_path, self.id)
        session.patch(url, endpoint_filter=self.service, json=body)

    def remove_configuration(self, session):
        """Removes a specified configuration group from the HA Instance.

        :param session: The session to use for making this request.
        :param str configuration_id: The configuration group ID.
        :type session: :class:`~openstack.session.Session`
        :returns: ``None``
        """
        body = {'ha_instance': {'configuration_id': ''}}
        url = utils.urljoin(self.base_path, self.id)
        session.patch(url, endpoint_filter=self.service, json=body)
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from openstack.database.v1 import _proxy
from openstack.database.v1 import database
from openstack.database.v1 import flavor
from openstack.database.v1 import instance
from openstack.database.v1 import user

from rackspace.database import database_service
from rackspace.database.v1 import backup
from rackspace.database.v1 import backup_schedule
from rackspace.database.v1 import high_availability_instance

database.Database.service = database_service.DatabaseService()
flavor.Flavor.service = database_service.DatabaseService()
instance.Instance.service = database_service.DatabaseService()
user.User.service = database_service.DatabaseService()


class Proxy(_proxy.Proxy):
    def __init__(self, session):
        super(Proxy, self).__init__(session)

    def backups(self, **query):
        """Return a generator of database backups

        :param kwargs \*\*query: Optional query parameters to be sent to limit
                                 the resources being returned.
class Backup(resource.Resource):
    base_path = 'backups'
    resource_key = 'backup'
    resources_key = "backups"
    service = database_service.DatabaseService()

    # capabilities
    allow_create = True
    allow_delete = True
    allow_list = True
    allow_retrieve = True
    allow_update = False

    # Properties
    #: Creation time
    created_at = resource.prop('created')
    #: Datastore type and version. *Type: dict*
    datastore = resource.prop('datastore', type=dict)
    #: Long form description
    description = resource.prop('description')
    #: Full public Cloud Files URI where backups are stored
    destination = resource.prop('locationRef')
    #: Indicates if the backup is automated. Valid values include:
    #: ``0``: False
    #: ``1``: True
    is_automated = resource.prop('is_automated', type=int)
    #: Name of backup
    name = resource.prop('name')
    #: Flavor of original instance
    instance_flavor = resource.prop('flavor_ram')
    #: The source instance ID for a backup. *Type: Instance*
    instance_id = resource.prop('instance_id', type=instance.Instance)
    #: Volume size of original instance. *Type: int*
    instance_volume_size = resource.prop('volume_size', type=int)
    #: Size of backup in GB. *Type: float*
    size = resource.prop('size', type=float)
    #: Specifies the source type (instance/ha) and source id (instanceID/haID)
    source = resource.prop('source', type=dict)
    #: The state this instance is in. Valid values include:
    #: ``NEW``: A new backup task was created
    #: ``BUILDING``: The backup task is currently running
    #: ``COMPLETED``: The backup task was successfully completed
    #: ``FAILED``: The backup task failed to complete successfully
    #: ``DELETE_FAILED``: The backup task failed to delete Cloud Files objects
    status = resource.prop('status')
    #: Backup type. Valid values include:
    #: ``InnoBackupEx``: InnoDB datastore backup
    type = resource.prop('type')
    #: Update time
    updated_at = resource.prop('updated')

    def restore(self, session, **attrs):
        """Creates a new database instance from this backup.

        Refer to Create instance for details on other options available during
        the creation of a new instance. All users/passwords/access that were on
        the instance at the time of the backup will be restored along with the
        databases. You can create new users or databases if you want, but they
        cannot be the same as the ones from the instance that was backed up.
        You can restore from an incremental backup the same as from a full
        backup. The system automatically restores all parents first,
        and then applies the incremental backup.

        :param session: The session to use for making this request.
        :param dict attrs: Keyword arguments which will be used to create
                           a :class:`~rackspace.database.v1.backup.Backup`,
                           comprised of the properties on the Backup class.
        :type session: :class:`~openstack.session.Session`
        :returns: ``dict``
        """
        body = {"instance": {"restorePoint": {"backupRef": self.id}}}
        body.update(attrs)
        resp = session.post('instances', service=self.service, json=body).body
        return resp['instance']