From aee6d03c03add5fca426e5a0930d18824e79b55c Mon Sep 17 00:00:00 2001 From: lvdongbing Date: Thu, 4 Aug 2016 02:56:57 -0400 Subject: [PATCH] Add os.cinder.volume plugin Change-Id: I0a465fbb1763fd84f95dbe8898788bcea9811fd4 --- bilean/drivers/base.py | 1 + bilean/drivers/openstack/__init__.py | 2 + bilean/drivers/openstack/cinder_v2.py | 37 ++++++++ bilean/plugins/os/cinder/__init__.py | 0 bilean/plugins/os/cinder/volume.py | 131 ++++++++++++++++++++++++++ etc/bilean/policy.json | 5 +- etc/bilean/resource_definitions.yaml | 2 +- setup.cfg | 1 + 8 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 bilean/drivers/openstack/cinder_v2.py create mode 100644 bilean/plugins/os/cinder/__init__.py create mode 100644 bilean/plugins/os/cinder/volume.py diff --git a/bilean/drivers/base.py b/bilean/drivers/base.py index 33112b7..3922ce5 100644 --- a/bilean/drivers/base.py +++ b/bilean/drivers/base.py @@ -51,3 +51,4 @@ class BileanDriver(object): self.compute = backend.compute self.network = backend.network self.identity = backend.identity + self.block_store = backend.block_store diff --git a/bilean/drivers/openstack/__init__.py b/bilean/drivers/openstack/__init__.py index 2123d30..029a004 100644 --- a/bilean/drivers/openstack/__init__.py +++ b/bilean/drivers/openstack/__init__.py @@ -10,6 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. +from bilean.drivers.openstack import cinder_v2 from bilean.drivers.openstack import keystone_v3 from bilean.drivers.openstack import neutron_v2 from bilean.drivers.openstack import nova_v2 @@ -18,3 +19,4 @@ from bilean.drivers.openstack import nova_v2 compute = nova_v2.NovaClient identity = keystone_v3.KeystoneClient network = neutron_v2.NeutronClient +block_store = cinder_v2.CinderClient diff --git a/bilean/drivers/openstack/cinder_v2.py b/bilean/drivers/openstack/cinder_v2.py new file mode 100644 index 0000000..cd9432b --- /dev/null +++ b/bilean/drivers/openstack/cinder_v2.py @@ -0,0 +1,37 @@ +# 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 oslo_log import log + +from bilean.drivers import base +from bilean.drivers.openstack import sdk + +LOG = log.getLogger(__name__) + + +class CinderClient(base.DriverBase): + '''Cinder V2 driver.''' + + def __init__(self, params=None): + super(CinderClient, self).__init__(params) + self.conn = sdk.create_connection(self.conn_params) + + @sdk.translate_exception + def volume_get(self, volume): + '''Get a single volume.''' + return self.conn.block_store.get_volume(volume) + + @sdk.translate_exception + def volume_delete(self, volume, ignore_missing=True): + '''Delete a volume.''' + self.conn.block_store.delete_volume(volume, + ignore_missing=ignore_missing) diff --git a/bilean/plugins/os/cinder/__init__.py b/bilean/plugins/os/cinder/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bilean/plugins/os/cinder/volume.py b/bilean/plugins/os/cinder/volume.py new file mode 100644 index 0000000..ab8c6a5 --- /dev/null +++ b/bilean/plugins/os/cinder/volume.py @@ -0,0 +1,131 @@ +# 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. + +import six + +from oslo_log import log as logging + +from bilean.common import exception +from bilean.common.i18n import _ +from bilean.common.i18n import _LE +from bilean.common import schema +from bilean.db import api as db_api +from bilean.drivers import base as driver_base +from bilean.plugins import base + +LOG = logging.getLogger(__name__) + + +class VolumeRule(base.Rule): + '''Rule for an OpenStack Cinder volume.''' + + KEYS = ( + PRICE_MAPPING, UNIT, + ) = ( + 'price_mapping', 'unit', + ) + + PM_KEYS = ( + START, END, PRICE, + ) = ( + 'start', 'end', 'price', + ) + + AVAILABLE_UNIT = ( + PER_HOUR, PER_SEC, + ) = ( + 'per_hour', 'per_sec', + ) + + properties_schema = { + PRICE_MAPPING: schema.List( + _('A list specifying the prices.'), + schema=schema.Map( + _('A map specifying the pricce of each volume capacity ' + 'interval.'), + schema={ + START: schema.Integer( + _('Start volume capacity.'), + ), + END: schema.Integer( + _('End volume capacity.'), + ), + PRICE: schema.Integer( + _('Price of this interval.'), + ), + } + ), + required=True, + updatable=True, + ), + UNIT: schema.String( + _('Unit of price, per_hour or per_sec.'), + default='per_hour', + ), + } + + def get_price(self, resource): + '''Get the price of resource in seconds. + + If no exact price found, 0 will be returned. + + :param: resource: Resource object to find price. + ''' + size = int(resource.properties.get('size')) + if not size: + raise exception.Error(msg='Size of volume should be provided to ' + 'get price.') + p_mapping = self.properties.get(self.PRICE_MAPPING) + for pm in p_mapping: + if size >= pm.get(self.START) and size <= pm.get(self.END): + price = pm.get(self.PRICE) + if self.PER_HOUR == self.properties.get(self.UNIT) and price > 0: + price = price * 1.0 / 3600 + return price + + +class VolumeResource(base.Resource): + '''Resource for an OpenStack Cinder volume.''' + + @classmethod + def do_check(context, user): + '''Communicate with other services and check user's resources. + + This would be a period job of user to check if there are any missing + actions, and then make correction. + ''' + # TODO(ldb) + return NotImplemented + + def do_delete(self, context, ignore_missing=True, timeout=None): + '''Delete resource from other services.''' + + # Delete resource from db + db_api.resource_delete(context, self.id) + + # Delete resource from cinder + cinderclient = driver_base.BileanDriver().block_store() + try: + cinderclient.volume_delete(self.id, ignore_missing=ignore_missing) + except Exception as ex: + LOG.error(_LE('Error: %s'), six.text_type(ex)) + return False + + return True + + +class VolumePlugin(base.Plugin): + '''Plugin for Openstack Nova server.''' + + RuleClass = VolumeRule + ResourceClass = VolumeResource + notification_exchanges = ['openstack'] diff --git a/etc/bilean/policy.json b/etc/bilean/policy.json index 0832f1e..d4760fa 100644 --- a/etc/bilean/policy.json +++ b/etc/bilean/policy.json @@ -19,5 +19,8 @@ "policies:index": "role:admin", "policies:create": "role:admin", "policies:get": "role:admin", - "policies:action": "role:admin" + "policies:action": "role:admin", + + "consumptions:index": "", + "consumptions:statistics": "", } diff --git a/etc/bilean/resource_definitions.yaml b/etc/bilean/resource_definitions.yaml index 4ea5561..8fb3799 100644 --- a/etc/bilean/resource_definitions.yaml +++ b/etc/bilean/resource_definitions.yaml @@ -8,7 +8,7 @@ fields: payload.instance_id - event_type: volume.*.end resources: - - resource_type: volume + - resource_type: os.cinder.volume traits: size: fields: payload.size diff --git a/setup.cfg b/setup.cfg index 3293f1f..6793259 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,6 +42,7 @@ bilean.drivers = bilean.plugins = os.nova.server = bilean.plugins.os.nova.server:ServerPlugin + os.cinder.volume = bilean.plugins.os.cinder.volume:VolumePlugin [global] setup-hooks =