198 lines
6.1 KiB
Python
198 lines
6.1 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright 2010 United States Government as represented by the
|
|
# Administrator of the National Aeronautics and Space Administration.
|
|
# All Rights Reserved.
|
|
# Copyright (c) 2010 Citrix Systems, Inc.
|
|
# Copyright 2011 Ken Pepple
|
|
#
|
|
# 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.
|
|
|
|
"""Built-in instance properties."""
|
|
|
|
import re
|
|
import uuid
|
|
|
|
from nova import context
|
|
from nova import db
|
|
from nova import exception
|
|
from nova.openstack.common import cfg
|
|
from nova.openstack.common import log as logging
|
|
from nova import utils
|
|
|
|
CONF = cfg.CONF
|
|
CONF.import_opt('default_instance_type', 'nova.config')
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
INVALID_NAME_REGEX = re.compile("[^\w\.\- ]")
|
|
|
|
|
|
def create(name, memory, vcpus, root_gb, ephemeral_gb=None, flavorid=None,
|
|
swap=None, rxtx_factor=None, is_public=True):
|
|
"""Creates instance types."""
|
|
|
|
if flavorid is None:
|
|
flavorid = uuid.uuid4()
|
|
if swap is None:
|
|
swap = 0
|
|
if rxtx_factor is None:
|
|
rxtx_factor = 1
|
|
if ephemeral_gb is None:
|
|
ephemeral_gb = 0
|
|
|
|
kwargs = {
|
|
'memory_mb': memory,
|
|
'vcpus': vcpus,
|
|
'root_gb': root_gb,
|
|
'ephemeral_gb': ephemeral_gb,
|
|
'swap': swap,
|
|
'rxtx_factor': rxtx_factor,
|
|
}
|
|
|
|
# ensure name does not contain any special characters
|
|
invalid_name = INVALID_NAME_REGEX.search(name)
|
|
if invalid_name:
|
|
msg = _("names can only contain [a-zA-Z0-9_.- ]")
|
|
raise exception.InvalidInput(reason=msg)
|
|
|
|
# ensure some attributes are integers and greater than or equal to 0
|
|
for option in kwargs:
|
|
try:
|
|
kwargs[option] = int(kwargs[option])
|
|
assert kwargs[option] >= 0
|
|
except (ValueError, AssertionError):
|
|
msg = _("create arguments must be positive integers")
|
|
raise exception.InvalidInput(reason=msg)
|
|
|
|
# some value are required to be nonzero, not just positive
|
|
for option in ['memory_mb', 'vcpus']:
|
|
try:
|
|
assert kwargs[option] > 0
|
|
except AssertionError:
|
|
msg = _("create arguments must be positive integers")
|
|
raise exception.InvalidInput(reason=msg)
|
|
|
|
kwargs['name'] = name
|
|
# NOTE(vish): Internally, flavorid is stored as a string but it comes
|
|
# in through json as an integer, so we convert it here.
|
|
kwargs['flavorid'] = unicode(flavorid)
|
|
|
|
# ensure is_public attribute is boolean
|
|
if not utils.is_valid_boolstr(is_public):
|
|
msg = _("is_public must be a boolean")
|
|
raise exception.InvalidInput(reason=msg)
|
|
kwargs['is_public'] = utils.bool_from_str(is_public)
|
|
|
|
try:
|
|
return db.instance_type_create(context.get_admin_context(), kwargs)
|
|
except exception.DBError, e:
|
|
LOG.exception(_('DB error: %s') % e)
|
|
raise exception.InstanceTypeCreateFailed()
|
|
|
|
|
|
def destroy(name):
|
|
"""Marks instance types as deleted."""
|
|
try:
|
|
assert name is not None
|
|
db.instance_type_destroy(context.get_admin_context(), name)
|
|
except (AssertionError, exception.NotFound):
|
|
LOG.exception(_('Instance type %s not found for deletion') % name)
|
|
raise exception.InstanceTypeNotFoundByName(instance_type_name=name)
|
|
|
|
|
|
def get_all_types(ctxt=None, inactive=False, filters=None):
|
|
"""Get all non-deleted instance_types.
|
|
|
|
Pass true as argument if you want deleted instance types returned also.
|
|
"""
|
|
if ctxt is None:
|
|
ctxt = context.get_admin_context()
|
|
|
|
inst_types = db.instance_type_get_all(
|
|
ctxt, inactive=inactive, filters=filters)
|
|
|
|
inst_type_dict = {}
|
|
for inst_type in inst_types:
|
|
inst_type_dict[inst_type['name']] = inst_type
|
|
return inst_type_dict
|
|
|
|
get_all_flavors = get_all_types
|
|
|
|
|
|
def get_default_instance_type():
|
|
"""Get the default instance type."""
|
|
name = CONF.default_instance_type
|
|
return get_instance_type_by_name(name)
|
|
|
|
|
|
def get_instance_type(instance_type_id, ctxt=None, inactive=False):
|
|
"""Retrieves single instance type by id."""
|
|
if instance_type_id is None:
|
|
return get_default_instance_type()
|
|
|
|
if ctxt is None:
|
|
ctxt = context.get_admin_context()
|
|
|
|
if inactive:
|
|
ctxt = ctxt.elevated(read_deleted="yes")
|
|
|
|
return db.instance_type_get(ctxt, instance_type_id)
|
|
|
|
|
|
def get_instance_type_by_name(name, ctxt=None):
|
|
"""Retrieves single instance type by name."""
|
|
if name is None:
|
|
return get_default_instance_type()
|
|
|
|
if ctxt is None:
|
|
ctxt = context.get_admin_context()
|
|
|
|
return db.instance_type_get_by_name(ctxt, name)
|
|
|
|
|
|
# TODO(termie): flavor-specific code should probably be in the API that uses
|
|
# flavors.
|
|
def get_instance_type_by_flavor_id(flavorid, ctxt=None, read_deleted="yes"):
|
|
"""Retrieve instance type by flavorid.
|
|
|
|
:raises: FlavorNotFound
|
|
"""
|
|
if ctxt is None:
|
|
ctxt = context.get_admin_context(read_deleted=read_deleted)
|
|
|
|
return db.instance_type_get_by_flavor_id(ctxt, flavorid)
|
|
|
|
|
|
def get_instance_type_access_by_flavor_id(flavorid, ctxt=None):
|
|
"""Retrieve instance type access list by flavor id"""
|
|
if ctxt is None:
|
|
ctxt = context.get_admin_context()
|
|
|
|
return db.instance_type_access_get_by_flavor_id(ctxt, flavorid)
|
|
|
|
|
|
def add_instance_type_access(flavorid, projectid, ctxt=None):
|
|
"""Add instance type access for project"""
|
|
if ctxt is None:
|
|
ctxt = context.get_admin_context()
|
|
|
|
return db.instance_type_access_add(ctxt, flavorid, projectid)
|
|
|
|
|
|
def remove_instance_type_access(flavorid, projectid, ctxt=None):
|
|
"""Remove instance type access for project"""
|
|
if ctxt is None:
|
|
ctxt = context.get_admin_context()
|
|
|
|
return db.instance_type_access_remove(ctxt, flavorid, projectid)
|