Support datastore types

implements blueprint db-type-version

Change-Id: I5dec99c44393c04d86c1a8e19c0b3ca59329fd87
This commit is contained in:
Andrey Shestakov
2013-10-15 00:21:44 +03:00
parent d06fadd876
commit 8e4bfa723d
8 changed files with 298 additions and 4 deletions

View File

@@ -308,6 +308,8 @@ class Dbaas(object):
from troveclient.v1.backups import Backups
from troveclient.v1.security_groups import SecurityGroups
from troveclient.v1.security_groups import SecurityGroupRules
from troveclient.v1.datastores import Datastores
from troveclient.v1.datastores import DatastoreVersions
from troveclient.v1.storage import StorageInfo
from troveclient.v1.management import Management
from troveclient.v1.management import MgmtFlavors
@@ -334,6 +336,8 @@ class Dbaas(object):
self.backups = Backups(self)
self.security_groups = SecurityGroups(self)
self.security_group_rules = SecurityGroupRules(self)
self.datastores = Datastores(self)
self.datastore_versions = DatastoreVersions(self)
self.storage = StorageInfo(self)
self.management = Management(self)
self.mgmt_flavor = MgmtFlavors(self)

View File

@@ -20,7 +20,9 @@ LISTIFY = {
"attachments": [[]],
"limits": [[]],
"security_groups": [[]],
"backups": [[]]
"backups": [[]],
"datastores": [[]],
"datastore_versions": [[]]
}

View File

@@ -0,0 +1,131 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack Foundation
# Copyright 2013 Mirantis, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# 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 testtools import TestCase
from mock import Mock
from troveclient.v1 import datastores
from troveclient import base
"""
Unit tests for datastores.py
"""
class DatastoreTest(TestCase):
def setUp(self):
super(DatastoreTest, self).setUp()
self.orig__init = datastores.Datastore.__init__
datastores.Datastore.__init__ = Mock(return_value=None)
self.datastore = datastores.Datastore()
self.datastore.manager = Mock()
def tearDown(self):
super(DatastoreTest, self).tearDown()
datastores.Datastore.__init__ = self.orig__init
def test___repr__(self):
self.datastore.name = "datastore-1"
self.assertEqual('<Datastore: datastore-1>',
self.datastore.__repr__())
class DatastoresTest(TestCase):
def setUp(self):
super(DatastoresTest, self).setUp()
self.orig__init = datastores.Datastores.__init__
datastores.Datastores.__init__ = Mock(return_value=None)
self.datastores = datastores.Datastores()
self.datastores.api = Mock()
self.datastores.api.client = Mock()
self.datastores.resource_class = Mock(return_value="ds-1")
self.orig_base_getid = base.getid
base.getid = Mock(return_value="datastore1")
def tearDown(self):
super(DatastoresTest, self).tearDown()
datastores.Datastores.__init__ = self.orig__init
base.getid = self.orig_base_getid
def test_list(self):
def side_effect_func(path, inst, limit, marker):
return path, inst, limit, marker
self.datastores._list = Mock(side_effect=side_effect_func)
limit = "test-limit"
marker = "test-marker"
expected = ("/datastores", "datastores", limit, marker)
self.assertEqual(expected, self.datastores.list(limit, marker))
def test_get(self):
def side_effect_func(path, inst):
return path, inst
self.datastores._get = Mock(side_effect=side_effect_func)
self.assertEqual(('/datastores/datastore1',
'datastore'),
self.datastores.get(1))
class DatastoreVersionsTest(TestCase):
def setUp(self):
super(DatastoreVersionsTest, self).setUp()
self.orig__init = datastores.DatastoreVersions.__init__
datastores.DatastoreVersions.__init__ = Mock(return_value=None)
self.datastore_versions = datastores.DatastoreVersions()
self.datastore_versions.api = Mock()
self.datastore_versions.api.client = Mock()
self.datastore_versions.resource_class = Mock(
return_value="ds_version-1")
self.orig_base_getid = base.getid
base.getid = Mock(return_value="datastore_version1")
def tearDown(self):
super(DatastoreVersionsTest, self).tearDown()
datastores.DatastoreVersions.__init__ = self.orig__init
base.getid = self.orig_base_getid
def test_list(self):
def side_effect_func(path, inst, limit, marker):
return path, inst, limit, marker
self.datastore_versions._list = Mock(side_effect=side_effect_func)
limit = "test-limit"
marker = "test-marker"
expected = ("/datastores/datastore1/versions",
"versions", limit, marker)
self.assertEqual(expected, self.datastore_versions.list(
"datastore1", limit, marker))
def test_get(self):
def side_effect_func(path, inst):
return path, inst
self.datastore_versions._get = Mock(side_effect=side_effect_func)
self.assertEqual(('/datastores/datastore1/versions/'
'datastore_version1',
'version'),
self.datastore_versions.get("datastore1",
"datastore_version1"))

View File

@@ -90,13 +90,18 @@ class InstancesTest(TestCase):
self.instances._create = Mock(side_effect=side_effect_func)
p, b, i = self.instances.create("test-name", 103, "test-volume",
['db1', 'db2'], ['u1', 'u2'])
['db1', 'db2'], ['u1', 'u2'],
datastore="datastore",
datastore_version="datastore-version")
self.assertEqual("/instances", p)
self.assertEqual("instance", i)
self.assertEqual(['db1', 'db2'], b["instance"]["databases"])
self.assertEqual(['u1', 'u2'], b["instance"]["users"])
self.assertEqual("test-name", b["instance"]["name"])
self.assertEqual("test-volume", b["instance"]["volume"])
self.assertEqual("datastore", b["instance"]["datastore"]["type"])
self.assertEqual("datastore-version",
b["instance"]["datastore"]["version"])
self.assertEqual(103, b["instance"]["flavorRef"])
def test__list(self):

View File

@@ -28,6 +28,8 @@ from troveclient.v1.quota import Quotas
from troveclient.v1.backups import Backups
from troveclient.v1.security_groups import SecurityGroups
from troveclient.v1.security_groups import SecurityGroupRules
from troveclient.v1.datastores import Datastores
from troveclient.v1.datastores import DatastoreVersions
from troveclient.v1.storage import StorageInfo
from troveclient.v1.management import Management
from troveclient.v1.management import MgmtFlavors
@@ -71,6 +73,8 @@ class Client(object):
self.root = Root(self)
self.security_group_rules = SecurityGroupRules(self)
self.security_groups = SecurityGroups(self)
self.datastores = Datastores(self)
self.datastore_versions = DatastoreVersions(self)
#self.hosts = Hosts(self)
#self.quota = Quotas(self)

View File

@@ -0,0 +1,93 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack Foundation
# Copyright 2013 Mirantis, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# 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 troveclient import base
from troveclient.common import check_for_exceptions
from troveclient.common import limit_url
from troveclient.common import Paginated
from troveclient.openstack.common.apiclient import exceptions
from troveclient.openstack.common.py3kcompat import urlutils
class Datastore(base.Resource):
def __repr__(self):
return "<Datastore: %s>" % self.name
class DatastoreVersion(base.Resource):
def __repr__(self):
return "<DatastoreVersion: %s>" % self.name
class Datastores(base.ManagerWithFind):
"""
Manage :class:`Datastore` resources.
"""
resource_class = Datastore
def __repr__(self):
return "<Datastore Manager at %s>" % id(self)
def list(self, limit=None, marker=None):
"""
Get a list of all datastores.
:rtype: list of :class:`Datastore`.
"""
return self._list("/datastores", "datastores", limit, marker)
def get(self, datastore):
"""
Get a specific datastore.
:rtype: :class:`Datastore`
"""
return self._get("/datastores/%s" % base.getid(datastore),
"datastore")
class DatastoreVersions(base.ManagerWithFind):
"""
Manage :class:`DatastoreVersion` resources.
"""
resource_class = DatastoreVersion
def __repr__(self):
return "<DatastoreVersions Manager at %s>" % id(self)
def list(self, datastore, limit=None, marker=None):
"""
Get a list of all datastore versions.
:rtype: list of :class:`DatastoreVersion`.
"""
return self._list("/datastores/%s/versions" % datastore,
"versions", limit, marker)
def get(self, datastore, datastore_version):
"""
Get a specific datastore version.
:rtype: :class:`DatastoreVersion`
"""
return self._get("/datastores/%s/versions/%s" %
(datastore, base.getid(datastore_version)),
"version")

View File

@@ -59,7 +59,8 @@ class Instances(base.ManagerWithFind):
resource_class = Instance
def create(self, name, flavor_id, volume=None, databases=None, users=None,
restorePoint=None, availability_zone=None):
restorePoint=None, availability_zone=None, datastore=None,
datastore_version=None):
"""
Create (boot) a new instance.
"""
@@ -67,6 +68,7 @@ class Instances(base.ManagerWithFind):
"name": name,
"flavorRef": flavor_id
}}
datastore_obj = {}
if volume:
body["instance"]["volume"] = volume
if databases:
@@ -77,6 +79,12 @@ class Instances(base.ManagerWithFind):
body["instance"]["restorePoint"] = restorePoint
if availability_zone:
body["instance"]["availability_zone"] = availability_zone
if datastore:
datastore_obj["type"] = datastore
if datastore_version:
datastore_obj["version"] = datastore_version
if datastore_obj:
body["instance"]["datastore"] = datastore_obj
return self._create("/instances", body, "instance")

View File

@@ -154,6 +154,14 @@ def do_delete(cs, args):
metavar='<availability_zone>',
default=None,
help='The Zone hint to give to nova')
@utils.arg('--datastore',
metavar='<datastore>',
default=None,
help='A datastore name or UUID')
@utils.arg('--datastore_version',
metavar='<datastore_version>',
default=None,
help='A datastore version name or UUID')
@utils.service_type('database')
def do_create(cs, args):
"""Creates a new instance."""
@@ -172,7 +180,9 @@ def do_create(cs, args):
databases=databases,
users=users,
restorePoint=restore_point,
availability_zone=args.availability_zone)
availability_zone=args.availability_zone,
datastore=args.datastore,
datastore_version=args.datastore_version)
instance._info['flavor'] = instance.flavor['id']
if hasattr(instance, 'volume'):
instance._info['volume'] = instance.volume['size']
@@ -509,3 +519,40 @@ def do_secgroup_add_rule(cs, args):
def do_secgroup_delete_rule(cs, args):
"""Deletes a security group rule."""
cs.security_group_rules.delete(args.security_group_rule)
@utils.service_type('database')
def do_datastore_list(cs, args):
"""List all the datastores."""
datastores = cs.datastores.list()
utils.print_list(datastores, ['id', 'name'])
@utils.arg('datastore', metavar='<datastore>',
help='ID of the datastore.')
@utils.service_type('database')
def do_datastore_show(cs, args):
"""Show details of an datastore."""
datastore = cs.datastores.get(args.datastore)
_print_instance(datastore)
@utils.arg('datastore', metavar='<datastore>',
help='ID of the datastore.')
@utils.service_type('database')
def do_datastore_version_list(cs, args):
"""List all the datastore versions."""
datastore_versions = cs.datastore_versions.list(args.datastore)
utils.print_list(datastore_versions, ['id', 'name'])
@utils.arg('datastore', metavar='<datastore>',
help='ID of the datastore.')
@utils.arg('datastore_version', metavar='<datastore_version>',
help='ID of the datastore version.')
@utils.service_type('database')
def do_datastore_version_show(cs, args):
"""Show details of an datastore version."""
datastore_version = cs.datastore_versions.get(args.datastore,
args.datastore_version)
_print_instance(datastore_version)