zaqar/zaqar/storage/sqlalchemy/flavors.py

161 lines
5.4 KiB
Python

# Copyright (c) 2015 OpenStack Foundation.
#
# 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.
"""flavors: an implementation of the flavor management storage
controller for sqlalchemy.
"""
import oslo_db.exception
import sqlalchemy as sa
from zaqar.storage import base
from zaqar.storage import errors
from zaqar.storage.sqlalchemy import tables
from zaqar.storage.sqlalchemy import utils
class FlavorsController(base.FlavorsBase):
def __init__(self, *args, **kwargs):
super(FlavorsController, self).__init__(*args, **kwargs)
self._pools_ctrl = self.driver.pools_controller
@utils.raises_conn_error
def list(self, project=None, marker=None, limit=10, detailed=False):
marker = marker or ''
# TODO(cpp-cabrera): optimization - limit the columns returned
# when detailed=False by specifying them in the select()
# clause
stmt = sa.sql.select([tables.Flavors]).where(
sa.and_(tables.Flavors.c.name > marker,
tables.Flavors.c.project == project)
)
if limit > 0:
stmt = stmt.limit(limit)
cursor = self.driver.run(stmt)
marker_name = {}
def it():
for cur in cursor:
marker_name['next'] = cur[0]
yield _normalize(cur, detailed=detailed)
yield it()
yield marker_name and marker_name['next']
@utils.raises_conn_error
def get(self, name, project=None, detailed=False):
stmt = sa.sql.select([tables.Flavors]).where(
sa.and_(tables.Flavors.c.name == name,
tables.Flavors.c.project == project)
)
flavor = self.driver.run(stmt).fetchone()
if flavor is None:
raise errors.FlavorDoesNotExist(name)
return _normalize(flavor, detailed)
@utils.raises_conn_error
def create(self, name, pool_group=None, project=None, capabilities=None):
cap = None if capabilities is None else utils.json_encode(capabilities)
try:
if pool_group is not None:
stmt = sa.sql.expression.insert(tables.Flavors).values(
name=name, pool_group=pool_group, project=project,
capabilities=cap
)
else:
stmt = sa.sql.expression.insert(tables.Flavors).values(
name=name, project=project,
capabilities=cap
)
self.driver.run(stmt)
except oslo_db.exception.DBDuplicateEntry:
# NOTE(gengchc2): If you do not use the removal group scheme to
# configure flavor, pool_group can be None..
if pool_group is not None:
flavor_obj = {}
flavor_obj["pool_group"] = pool_group
if not list(self._pools_ctrl.get_pools_by_flavor(flavor_obj)):
raise errors.PoolGroupDoesNotExist(pool_group)
# TODO(flaper87): merge update/create into a single
# method with introduction of upsert
self.update(name, pool_group=pool_group,
project=project,
capabilities=capabilities)
@utils.raises_conn_error
def exists(self, name, project=None):
stmt = sa.sql.select([tables.Flavors.c.name]).where(
sa.and_(tables.Flavors.c.name == name,
tables.Flavors.c.project == project)
).limit(1)
return self.driver.run(stmt).fetchone() is not None
@utils.raises_conn_error
def update(self, name, project=None, pool_group=None, capabilities=None):
fields = {}
if capabilities is not None:
fields['capabilities'] = capabilities
if pool_group is not None:
fields['pool_group'] = pool_group
assert fields, '`pool_group` or `capabilities` not found in kwargs'
if 'capabilities' in fields:
fields['capabilities'] = utils.json_encode(fields['capabilities'])
stmt = sa.sql.update(tables.Flavors).where(
sa.and_(tables.Flavors.c.name == name,
tables.Flavors.c.project == project)).values(**fields)
res = self.driver.run(stmt)
if res.rowcount == 0:
raise errors.FlavorDoesNotExist(name)
@utils.raises_conn_error
def delete(self, name, project=None):
stmt = sa.sql.expression.delete(tables.Flavors).where(
sa.and_(tables.Flavors.c.name == name,
tables.Flavors.c.project == project)
)
self.driver.run(stmt)
@utils.raises_conn_error
def drop_all(self):
stmt = sa.sql.expression.delete(tables.Flavors)
self.driver.run(stmt)
def _normalize(flavor, detailed=False):
ret = {
'name': flavor[0],
'pool_group': flavor[2],
}
if detailed:
capabilities = flavor[3]
ret['capabilities'] = (utils.json_decode(capabilities)
if capabilities else {})
return ret