4493 lines
144 KiB
Python
4493 lines
144 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright (c) 2011 X.commerce, a business unit of eBay Inc.
|
|
# Copyright 2010 United States Government as represented by the
|
|
# Administrator of the National Aeronautics and Space Administration.
|
|
# 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.
|
|
|
|
"""Implementation of SQLAlchemy backend."""
|
|
|
|
import datetime
|
|
import functools
|
|
import re
|
|
import warnings
|
|
|
|
from nova import block_device
|
|
from nova import db
|
|
from nova import exception
|
|
from nova import flags
|
|
from nova import utils
|
|
from nova import log as logging
|
|
from nova.compute import aggregate_states
|
|
from nova.compute import vm_states
|
|
from nova.db.sqlalchemy import models
|
|
from nova.db.sqlalchemy.session import get_session
|
|
from sqlalchemy import and_
|
|
from sqlalchemy import or_
|
|
from sqlalchemy.exc import IntegrityError
|
|
from sqlalchemy.orm import joinedload
|
|
from sqlalchemy.orm import joinedload_all
|
|
from sqlalchemy.sql import func
|
|
from sqlalchemy.sql.expression import desc
|
|
from sqlalchemy.sql.expression import literal_column
|
|
|
|
FLAGS = flags.FLAGS
|
|
flags.DECLARE('reserved_host_disk_mb', 'nova.scheduler.host_manager')
|
|
flags.DECLARE('reserved_host_memory_mb', 'nova.scheduler.host_manager')
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def is_admin_context(context):
|
|
"""Indicates if the request context is an administrator."""
|
|
if not context:
|
|
warnings.warn(_('Use of empty request context is deprecated'),
|
|
DeprecationWarning)
|
|
raise Exception('die')
|
|
return context.is_admin
|
|
|
|
|
|
def is_user_context(context):
|
|
"""Indicates if the request context is a normal user."""
|
|
if not context:
|
|
return False
|
|
if context.is_admin:
|
|
return False
|
|
if not context.user_id or not context.project_id:
|
|
return False
|
|
return True
|
|
|
|
|
|
def authorize_project_context(context, project_id):
|
|
"""Ensures a request has permission to access the given project."""
|
|
if is_user_context(context):
|
|
if not context.project_id:
|
|
raise exception.NotAuthorized()
|
|
elif context.project_id != project_id:
|
|
raise exception.NotAuthorized()
|
|
|
|
|
|
def authorize_user_context(context, user_id):
|
|
"""Ensures a request has permission to access the given user."""
|
|
if is_user_context(context):
|
|
if not context.user_id:
|
|
raise exception.NotAuthorized()
|
|
elif context.user_id != user_id:
|
|
raise exception.NotAuthorized()
|
|
|
|
|
|
def require_admin_context(f):
|
|
"""Decorator to require admin request context.
|
|
|
|
The first argument to the wrapped function must be the context.
|
|
|
|
"""
|
|
|
|
def wrapper(*args, **kwargs):
|
|
if not is_admin_context(args[0]):
|
|
raise exception.AdminRequired()
|
|
return f(*args, **kwargs)
|
|
return wrapper
|
|
|
|
|
|
def require_context(f):
|
|
"""Decorator to require *any* user or admin context.
|
|
|
|
This does no authorization for user or project access matching, see
|
|
:py:func:`authorize_project_context` and
|
|
:py:func:`authorize_user_context`.
|
|
|
|
The first argument to the wrapped function must be the context.
|
|
|
|
"""
|
|
|
|
def wrapper(*args, **kwargs):
|
|
if not is_admin_context(args[0]) and not is_user_context(args[0]):
|
|
raise exception.NotAuthorized()
|
|
return f(*args, **kwargs)
|
|
return wrapper
|
|
|
|
|
|
def require_instance_exists(f):
|
|
"""Decorator to require the specified instance to exist.
|
|
|
|
Requires the wrapped function to use context and instance_id as
|
|
their first two arguments.
|
|
"""
|
|
|
|
def wrapper(context, instance_id, *args, **kwargs):
|
|
db.instance_get(context, instance_id)
|
|
return f(context, instance_id, *args, **kwargs)
|
|
wrapper.__name__ = f.__name__
|
|
return wrapper
|
|
|
|
|
|
def require_volume_exists(f):
|
|
"""Decorator to require the specified volume to exist.
|
|
|
|
Requires the wrapped function to use context and volume_id as
|
|
their first two arguments.
|
|
"""
|
|
|
|
def wrapper(context, volume_id, *args, **kwargs):
|
|
db.volume_get(context, volume_id)
|
|
return f(context, volume_id, *args, **kwargs)
|
|
wrapper.__name__ = f.__name__
|
|
return wrapper
|
|
|
|
|
|
def require_aggregate_exists(f):
|
|
"""Decorator to require the specified aggregate to exist.
|
|
|
|
Requires the wrapped function to use context and aggregate_id as
|
|
their first two arguments.
|
|
"""
|
|
|
|
@functools.wraps(f)
|
|
def wrapper(context, aggregate_id, *args, **kwargs):
|
|
db.aggregate_get(context, aggregate_id)
|
|
return f(context, aggregate_id, *args, **kwargs)
|
|
return wrapper
|
|
|
|
|
|
def model_query(context, *args, **kwargs):
|
|
"""Query helper that accounts for context's `read_deleted` field.
|
|
|
|
:param context: context to query under
|
|
:param session: if present, the session to use
|
|
:param read_deleted: if present, overrides context's read_deleted field.
|
|
:param project_only: if present and context is user-type, then restrict
|
|
query to match the context's project_id.
|
|
"""
|
|
session = kwargs.get('session') or get_session()
|
|
read_deleted = kwargs.get('read_deleted') or context.read_deleted
|
|
project_only = kwargs.get('project_only')
|
|
|
|
query = session.query(*args)
|
|
|
|
if read_deleted == 'no':
|
|
query = query.filter_by(deleted=False)
|
|
elif read_deleted == 'yes':
|
|
pass # omit the filter to include deleted and active
|
|
elif read_deleted == 'only':
|
|
query = query.filter_by(deleted=True)
|
|
else:
|
|
raise Exception(
|
|
_("Unrecognized read_deleted value '%s'") % read_deleted)
|
|
|
|
if project_only and is_user_context(context):
|
|
query = query.filter_by(project_id=context.project_id)
|
|
|
|
return query
|
|
|
|
|
|
def exact_filter(query, model, filters, legal_keys):
|
|
"""Applies exact match filtering to a query.
|
|
|
|
Returns the updated query. Modifies filters argument to remove
|
|
filters consumed.
|
|
|
|
:param query: query to apply filters to
|
|
:param model: model object the query applies to, for IN-style
|
|
filtering
|
|
:param filters: dictionary of filters; values that are lists,
|
|
tuples, sets, or frozensets cause an 'IN' test to
|
|
be performed, while exact matching ('==' operator)
|
|
is used for other values
|
|
:param legal_keys: list of keys to apply exact filtering to
|
|
"""
|
|
|
|
filter_dict = {}
|
|
|
|
# Walk through all the keys
|
|
for key in legal_keys:
|
|
# Skip ones we're not filtering on
|
|
if key not in filters:
|
|
continue
|
|
|
|
# OK, filtering on this key; what value do we search for?
|
|
value = filters.pop(key)
|
|
|
|
if isinstance(value, (list, tuple, set, frozenset)):
|
|
# Looking for values in a list; apply to query directly
|
|
column_attr = getattr(model, key)
|
|
query = query.filter(column_attr.in_(value))
|
|
else:
|
|
# OK, simple exact match; save for later
|
|
filter_dict[key] = value
|
|
|
|
# Apply simple exact matches
|
|
if filter_dict:
|
|
query = query.filter_by(**filter_dict)
|
|
|
|
return query
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def service_destroy(context, service_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
service_ref = service_get(context, service_id, session=session)
|
|
service_ref.delete(session=session)
|
|
|
|
if service_ref.topic == 'compute' and service_ref.compute_node:
|
|
for c in service_ref.compute_node:
|
|
c.delete(session=session)
|
|
|
|
|
|
@require_admin_context
|
|
def service_get(context, service_id, session=None):
|
|
result = model_query(context, models.Service, session=session).\
|
|
options(joinedload('compute_node')).\
|
|
filter_by(id=service_id).\
|
|
first()
|
|
if not result:
|
|
raise exception.ServiceNotFound(service_id=service_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def service_get_all(context, disabled=None):
|
|
query = model_query(context, models.Service)
|
|
|
|
if disabled is not None:
|
|
query = query.filter_by(disabled=disabled)
|
|
|
|
return query.all()
|
|
|
|
|
|
@require_admin_context
|
|
def service_get_all_by_topic(context, topic):
|
|
return model_query(context, models.Service, read_deleted="no").\
|
|
filter_by(disabled=False).\
|
|
filter_by(topic=topic).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def service_get_by_host_and_topic(context, host, topic):
|
|
return model_query(context, models.Service, read_deleted="no").\
|
|
filter_by(disabled=False).\
|
|
filter_by(host=host).\
|
|
filter_by(topic=topic).\
|
|
first()
|
|
|
|
|
|
@require_admin_context
|
|
def service_get_all_by_host(context, host):
|
|
return model_query(context, models.Service, read_deleted="no").\
|
|
filter_by(host=host).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def service_get_all_compute_by_host(context, host):
|
|
result = model_query(context, models.Service, read_deleted="no").\
|
|
options(joinedload('compute_node')).\
|
|
filter_by(host=host).\
|
|
filter_by(topic="compute").\
|
|
all()
|
|
|
|
if not result:
|
|
raise exception.ComputeHostNotFound(host=host)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def _service_get_all_topic_subquery(context, session, topic, subq, label):
|
|
sort_value = getattr(subq.c, label)
|
|
return model_query(context, models.Service,
|
|
func.coalesce(sort_value, 0),
|
|
session=session, read_deleted="no").\
|
|
filter_by(topic=topic).\
|
|
filter_by(disabled=False).\
|
|
outerjoin((subq, models.Service.host == subq.c.host)).\
|
|
order_by(sort_value).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def service_get_all_compute_sorted(context):
|
|
session = get_session()
|
|
with session.begin():
|
|
# NOTE(vish): The intended query is below
|
|
# SELECT services.*, COALESCE(inst_cores.instance_cores,
|
|
# 0)
|
|
# FROM services LEFT OUTER JOIN
|
|
# (SELECT host, SUM(instances.vcpus) AS instance_cores
|
|
# FROM instances GROUP BY host) AS inst_cores
|
|
# ON services.host = inst_cores.host
|
|
topic = 'compute'
|
|
label = 'instance_cores'
|
|
subq = model_query(context, models.Instance.host,
|
|
func.sum(models.Instance.vcpus).label(label),
|
|
session=session, read_deleted="no").\
|
|
group_by(models.Instance.host).\
|
|
subquery()
|
|
return _service_get_all_topic_subquery(context,
|
|
session,
|
|
topic,
|
|
subq,
|
|
label)
|
|
|
|
|
|
@require_admin_context
|
|
def service_get_all_network_sorted(context):
|
|
session = get_session()
|
|
with session.begin():
|
|
topic = 'network'
|
|
label = 'network_count'
|
|
subq = model_query(context, models.Network.host,
|
|
func.count(models.Network.id).label(label),
|
|
session=session, read_deleted="no").\
|
|
group_by(models.Network.host).\
|
|
subquery()
|
|
return _service_get_all_topic_subquery(context,
|
|
session,
|
|
topic,
|
|
subq,
|
|
label)
|
|
|
|
|
|
@require_admin_context
|
|
def service_get_all_volume_sorted(context):
|
|
session = get_session()
|
|
with session.begin():
|
|
topic = 'volume'
|
|
label = 'volume_gigabytes'
|
|
subq = model_query(context, models.Volume.host,
|
|
func.sum(models.Volume.size).label(label),
|
|
session=session, read_deleted="no").\
|
|
group_by(models.Volume.host).\
|
|
subquery()
|
|
return _service_get_all_topic_subquery(context,
|
|
session,
|
|
topic,
|
|
subq,
|
|
label)
|
|
|
|
|
|
@require_admin_context
|
|
def service_get_by_args(context, host, binary):
|
|
result = model_query(context, models.Service).\
|
|
filter_by(host=host).\
|
|
filter_by(binary=binary).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.HostBinaryNotFound(host=host, binary=binary)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def service_create(context, values):
|
|
service_ref = models.Service()
|
|
service_ref.update(values)
|
|
if not FLAGS.enable_new_services:
|
|
service_ref.disabled = True
|
|
service_ref.save()
|
|
return service_ref
|
|
|
|
|
|
@require_admin_context
|
|
def service_update(context, service_id, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
service_ref = service_get(context, service_id, session=session)
|
|
service_ref.update(values)
|
|
service_ref.save(session=session)
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def compute_node_get(context, compute_id, session=None):
|
|
result = model_query(context, models.ComputeNode, session=session).\
|
|
filter_by(id=compute_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.ComputeHostNotFound(host=compute_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def compute_node_get_by_service(context, service_id, session=None):
|
|
if not session:
|
|
session = get_session()
|
|
|
|
result = model_query(context, models.ComputeNode, session=session).\
|
|
filter_by(service_id=service_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.ComputeHostNotFound(host="ServiceID=%s" % service_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def compute_node_get_all(context, session=None):
|
|
return model_query(context, models.ComputeNode, session=session).\
|
|
options(joinedload('service')).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def compute_node_get_for_service(context, service_id):
|
|
return model_query(context, models.ComputeNode).\
|
|
options(joinedload('service')).\
|
|
filter_by(service_id=service_id).\
|
|
first()
|
|
|
|
|
|
def _get_host_utilization(context, host, ram_mb, disk_gb):
|
|
"""Compute the current utilization of a given host."""
|
|
instances = instance_get_all_by_host(context, host)
|
|
vms = len(instances)
|
|
free_ram_mb = ram_mb - FLAGS.reserved_host_memory_mb
|
|
free_disk_gb = disk_gb - (FLAGS.reserved_host_disk_mb * 1024)
|
|
|
|
work = 0
|
|
for instance in instances:
|
|
free_ram_mb -= instance.memory_mb
|
|
free_disk_gb -= instance.root_gb
|
|
free_disk_gb -= instance.ephemeral_gb
|
|
if instance.vm_state in [vm_states.BUILDING, vm_states.REBUILDING,
|
|
vm_states.MIGRATING, vm_states.RESIZING]:
|
|
work += 1
|
|
return dict(free_ram_mb=free_ram_mb,
|
|
free_disk_gb=free_disk_gb,
|
|
current_workload=work,
|
|
running_vms=vms)
|
|
|
|
|
|
def _adjust_compute_node_values_for_utilization(context, values, session):
|
|
service_ref = service_get(context, values['service_id'], session=session)
|
|
host = service_ref['host']
|
|
ram_mb = values['memory_mb']
|
|
disk_gb = values['local_gb']
|
|
values.update(_get_host_utilization(context, host, ram_mb, disk_gb))
|
|
|
|
|
|
@require_admin_context
|
|
def compute_node_create(context, values, session=None):
|
|
"""Creates a new ComputeNode and populates the capacity fields
|
|
with the most recent data."""
|
|
if not session:
|
|
session = get_session()
|
|
|
|
_adjust_compute_node_values_for_utilization(context, values, session)
|
|
with session.begin(subtransactions=True):
|
|
compute_node_ref = models.ComputeNode()
|
|
session.add(compute_node_ref)
|
|
compute_node_ref.update(values)
|
|
return compute_node_ref
|
|
|
|
|
|
@require_admin_context
|
|
def compute_node_update(context, compute_id, values):
|
|
"""Creates a new ComputeNode and populates the capacity fields
|
|
with the most recent data."""
|
|
session = get_session()
|
|
_adjust_compute_node_values_for_utilization(context, values, session)
|
|
with session.begin(subtransactions=True):
|
|
compute_ref = compute_node_get(context, compute_id, session=session)
|
|
compute_ref.update(values)
|
|
compute_ref.save(session=session)
|
|
|
|
|
|
# Note: these operations use with_lockmode() ... so this will only work
|
|
# reliably with engines that support row-level locking
|
|
# (postgres, mysql+innodb and above).
|
|
|
|
def compute_node_get_by_host(context, host):
|
|
"""Get all capacity entries for the given host."""
|
|
session = get_session()
|
|
with session.begin():
|
|
node = session.query(models.ComputeNode).\
|
|
options(joinedload('service')).\
|
|
filter(models.Service.host == host).\
|
|
filter_by(deleted=False).\
|
|
with_lockmode('update')
|
|
return node.first()
|
|
|
|
|
|
def compute_node_capacity_find(context, minimum_ram_mb, minimum_disk_gb):
|
|
"""Get all enabled hosts with enough ram and disk."""
|
|
session = get_session()
|
|
with session.begin():
|
|
return session.query(models.ComputeNode).\
|
|
options(joinedload('service')).\
|
|
filter(models.ComputeNode.free_ram_mb >= minimum_ram_mb).\
|
|
filter(models.ComputeNode.free_disk_gb >= minimum_disk_gb).\
|
|
filter(models.Service.disabled == False).\
|
|
filter_by(deleted=False).\
|
|
with_lockmode('update').all()
|
|
|
|
|
|
def compute_node_utilization_update(context, host, free_ram_mb_delta=0,
|
|
free_disk_gb_delta=0, work_delta=0, vm_delta=0):
|
|
"""Update a specific ComputeNode entry by a series of deltas.
|
|
Do this as a single atomic action and lock the row for the
|
|
duration of the operation. Requires that ComputeNode record exist."""
|
|
session = get_session()
|
|
compute_node = None
|
|
with session.begin(subtransactions=True):
|
|
compute_node = session.query(models.ComputeNode).\
|
|
options(joinedload('service')).\
|
|
filter(models.Service.host == host).\
|
|
filter_by(deleted=False).\
|
|
with_lockmode('update').\
|
|
first()
|
|
if compute_node is None:
|
|
raise exception.NotFound(_("No ComputeNode for %(host)s" %
|
|
locals()))
|
|
|
|
# This table thingy is how we get atomic UPDATE x = x + 1
|
|
# semantics.
|
|
table = models.ComputeNode.__table__
|
|
if free_ram_mb_delta != 0:
|
|
compute_node.free_ram_mb = table.c.free_ram_mb + free_ram_mb_delta
|
|
if free_disk_gb_delta != 0:
|
|
compute_node.free_disk_gb = (table.c.free_disk_gb +
|
|
free_disk_gb_delta)
|
|
if work_delta != 0:
|
|
compute_node.current_workload = (table.c.current_workload +
|
|
work_delta)
|
|
if vm_delta != 0:
|
|
compute_node.running_vms = table.c.running_vms + vm_delta
|
|
return compute_node
|
|
|
|
|
|
def compute_node_utilization_set(context, host, free_ram_mb=None,
|
|
free_disk_gb=None, work=None, vms=None):
|
|
"""Like compute_node_utilization_update() modify a specific host
|
|
entry. But this function will set the metrics absolutely
|
|
(vs. a delta update).
|
|
"""
|
|
session = get_session()
|
|
compute_node = None
|
|
with session.begin(subtransactions=True):
|
|
compute_node = session.query(models.ComputeNode).\
|
|
options(joinedload('service')).\
|
|
filter(models.Service.host == host).\
|
|
filter_by(deleted=False).\
|
|
with_lockmode('update').\
|
|
first()
|
|
if compute_node is None:
|
|
raise exception.NotFound(_("No ComputeNode for %(host)s" %
|
|
locals()))
|
|
|
|
if free_ram_mb != None:
|
|
compute_node.free_ram_mb = free_ram_mb
|
|
if free_disk_gb != None:
|
|
compute_node.free_disk_gb = free_disk_gb
|
|
if work != None:
|
|
compute_node.current_workload = work
|
|
if vms != None:
|
|
compute_node.running_vms = vms
|
|
|
|
return compute_node
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def certificate_get(context, certificate_id, session=None):
|
|
result = model_query(context, models.Certificate, session=session).\
|
|
filter_by(id=certificate_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.CertificateNotFound(certificate_id=certificate_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def certificate_create(context, values):
|
|
certificate_ref = models.Certificate()
|
|
for (key, value) in values.iteritems():
|
|
certificate_ref[key] = value
|
|
certificate_ref.save()
|
|
return certificate_ref
|
|
|
|
|
|
@require_admin_context
|
|
def certificate_destroy(context, certificate_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
certificate_ref = certificate_get(context,
|
|
certificate_id,
|
|
session=session)
|
|
certificate_ref.delete(session=session)
|
|
|
|
|
|
@require_admin_context
|
|
def certificate_get_all_by_project(context, project_id):
|
|
return model_query(context, models.Certificate, read_deleted="no").\
|
|
filter_by(project_id=project_id).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def certificate_get_all_by_user(context, user_id):
|
|
return model_query(context, models.Certificate, read_deleted="no").\
|
|
filter_by(user_id=user_id).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def certificate_get_all_by_user_and_project(context, user_id, project_id):
|
|
return model_query(context, models.Certificate, read_deleted="no").\
|
|
filter_by(user_id=user_id).\
|
|
filter_by(project_id=project_id).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def certificate_update(context, certificate_id, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
certificate_ref = certificate_get(context,
|
|
certificate_id,
|
|
session=session)
|
|
for (key, value) in values.iteritems():
|
|
certificate_ref[key] = value
|
|
certificate_ref.save(session=session)
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_context
|
|
def floating_ip_get(context, id):
|
|
result = model_query(context, models.FloatingIp, project_only=True).\
|
|
filter_by(id=id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.FloatingIpNotFound(id=id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def floating_ip_get_pools(context):
|
|
session = get_session()
|
|
pools = []
|
|
for result in session.query(models.FloatingIp.pool).distinct():
|
|
pools.append({'name': result[0]})
|
|
return pools
|
|
|
|
|
|
@require_context
|
|
def floating_ip_allocate_address(context, project_id, pool):
|
|
authorize_project_context(context, project_id)
|
|
session = get_session()
|
|
with session.begin():
|
|
floating_ip_ref = model_query(context, models.FloatingIp,
|
|
session=session, read_deleted="no").\
|
|
filter_by(fixed_ip_id=None).\
|
|
filter_by(project_id=None).\
|
|
filter_by(pool=pool).\
|
|
with_lockmode('update').\
|
|
first()
|
|
# NOTE(vish): if with_lockmode isn't supported, as in sqlite,
|
|
# then this has concurrency issues
|
|
if not floating_ip_ref:
|
|
raise exception.NoMoreFloatingIps()
|
|
floating_ip_ref['project_id'] = project_id
|
|
session.add(floating_ip_ref)
|
|
return floating_ip_ref['address']
|
|
|
|
|
|
@require_context
|
|
def floating_ip_create(context, values):
|
|
floating_ip_ref = models.FloatingIp()
|
|
floating_ip_ref.update(values)
|
|
floating_ip_ref.save()
|
|
return floating_ip_ref['address']
|
|
|
|
|
|
@require_context
|
|
def floating_ip_count_by_project(context, project_id):
|
|
authorize_project_context(context, project_id)
|
|
# TODO(tr3buchet): why leave auto_assigned floating IPs out?
|
|
return model_query(context, models.FloatingIp, read_deleted="no").\
|
|
filter_by(project_id=project_id).\
|
|
filter_by(auto_assigned=False).\
|
|
count()
|
|
|
|
|
|
@require_context
|
|
def floating_ip_fixed_ip_associate(context, floating_address,
|
|
fixed_address, host):
|
|
session = get_session()
|
|
with session.begin():
|
|
floating_ip_ref = floating_ip_get_by_address(context,
|
|
floating_address,
|
|
session=session)
|
|
fixed_ip_ref = fixed_ip_get_by_address(context,
|
|
fixed_address,
|
|
session=session)
|
|
floating_ip_ref.fixed_ip_id = fixed_ip_ref["id"]
|
|
floating_ip_ref.host = host
|
|
floating_ip_ref.save(session=session)
|
|
|
|
|
|
@require_context
|
|
def floating_ip_deallocate(context, address):
|
|
session = get_session()
|
|
with session.begin():
|
|
floating_ip_ref = floating_ip_get_by_address(context,
|
|
address,
|
|
session=session)
|
|
floating_ip_ref['project_id'] = None
|
|
floating_ip_ref['host'] = None
|
|
floating_ip_ref['auto_assigned'] = False
|
|
floating_ip_ref.save(session=session)
|
|
|
|
|
|
@require_context
|
|
def floating_ip_destroy(context, address):
|
|
session = get_session()
|
|
with session.begin():
|
|
floating_ip_ref = floating_ip_get_by_address(context,
|
|
address,
|
|
session=session)
|
|
floating_ip_ref.delete(session=session)
|
|
|
|
|
|
@require_context
|
|
def floating_ip_disassociate(context, address):
|
|
session = get_session()
|
|
with session.begin():
|
|
floating_ip_ref = floating_ip_get_by_address(context,
|
|
address,
|
|
session=session)
|
|
fixed_ip_ref = fixed_ip_get(context,
|
|
floating_ip_ref['fixed_ip_id'])
|
|
if fixed_ip_ref:
|
|
fixed_ip_address = fixed_ip_ref['address']
|
|
else:
|
|
fixed_ip_address = None
|
|
floating_ip_ref.fixed_ip_id = None
|
|
floating_ip_ref.host = None
|
|
floating_ip_ref.save(session=session)
|
|
return fixed_ip_address
|
|
|
|
|
|
@require_context
|
|
def floating_ip_set_auto_assigned(context, address):
|
|
session = get_session()
|
|
with session.begin():
|
|
floating_ip_ref = floating_ip_get_by_address(context,
|
|
address,
|
|
session=session)
|
|
floating_ip_ref.auto_assigned = True
|
|
floating_ip_ref.save(session=session)
|
|
|
|
|
|
def _floating_ip_get_all(context):
|
|
return model_query(context, models.FloatingIp, read_deleted="no")
|
|
|
|
|
|
@require_admin_context
|
|
def floating_ip_get_all(context):
|
|
floating_ip_refs = _floating_ip_get_all(context).all()
|
|
if not floating_ip_refs:
|
|
raise exception.NoFloatingIpsDefined()
|
|
return floating_ip_refs
|
|
|
|
|
|
@require_admin_context
|
|
def floating_ip_get_all_by_host(context, host):
|
|
floating_ip_refs = _floating_ip_get_all(context).\
|
|
filter_by(host=host).\
|
|
all()
|
|
if not floating_ip_refs:
|
|
raise exception.FloatingIpNotFoundForHost(host=host)
|
|
return floating_ip_refs
|
|
|
|
|
|
@require_context
|
|
def floating_ip_get_all_by_project(context, project_id):
|
|
authorize_project_context(context, project_id)
|
|
# TODO(tr3buchet): why do we not want auto_assigned floating IPs here?
|
|
return _floating_ip_get_all(context).\
|
|
filter_by(project_id=project_id).\
|
|
filter_by(auto_assigned=False).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def floating_ip_get_by_address(context, address, session=None):
|
|
result = model_query(context, models.FloatingIp, session=session).\
|
|
filter_by(address=address).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.FloatingIpNotFoundForAddress(address=address)
|
|
|
|
# If the floating IP has a project ID set, check to make sure
|
|
# the non-admin user has access.
|
|
if result.project_id and is_user_context(context):
|
|
authorize_project_context(context, result.project_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def floating_ip_get_by_fixed_address(context, fixed_address, session=None):
|
|
if not session:
|
|
session = get_session()
|
|
|
|
fixed_ip = fixed_ip_get_by_address(context, fixed_address, session)
|
|
fixed_ip_id = fixed_ip['id']
|
|
|
|
return model_query(context, models.FloatingIp, session=session).\
|
|
filter_by(fixed_ip_id=fixed_ip_id).\
|
|
all()
|
|
|
|
# NOTE(tr3buchet) please don't invent an exception here, empty list is fine
|
|
|
|
|
|
@require_context
|
|
def floating_ip_get_by_fixed_ip_id(context, fixed_ip_id, session=None):
|
|
if not session:
|
|
session = get_session()
|
|
|
|
return model_query(context, models.FloatingIp, session=session).\
|
|
filter_by(fixed_ip_id=fixed_ip_id).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def floating_ip_update(context, address, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
floating_ip_ref = floating_ip_get_by_address(context, address, session)
|
|
for (key, value) in values.iteritems():
|
|
floating_ip_ref[key] = value
|
|
floating_ip_ref.save(session=session)
|
|
|
|
|
|
@require_context
|
|
def _dnsdomain_get(context, session, fqdomain):
|
|
return model_query(context, models.DNSDomain,
|
|
session=session, read_deleted="no").\
|
|
filter_by(domain=fqdomain).\
|
|
with_lockmode('update').\
|
|
first()
|
|
|
|
|
|
@require_context
|
|
def dnsdomain_get(context, fqdomain):
|
|
session = get_session()
|
|
with session.begin():
|
|
return _dnsdomain_get(context, session, fqdomain)
|
|
|
|
|
|
@require_admin_context
|
|
def _dnsdomain_get_or_create(context, session, fqdomain):
|
|
domain_ref = _dnsdomain_get(context, session, fqdomain)
|
|
if not domain_ref:
|
|
dns_ref = models.DNSDomain()
|
|
dns_ref.update({'domain': fqdomain,
|
|
'availability_zone': None,
|
|
'project_id': None})
|
|
return dns_ref
|
|
|
|
return domain_ref
|
|
|
|
|
|
@require_admin_context
|
|
def dnsdomain_register_for_zone(context, fqdomain, zone):
|
|
session = get_session()
|
|
with session.begin():
|
|
domain_ref = _dnsdomain_get_or_create(context, session, fqdomain)
|
|
domain_ref.scope = 'private'
|
|
domain_ref.availability_zone = zone
|
|
domain_ref.save(session=session)
|
|
|
|
|
|
@require_admin_context
|
|
def dnsdomain_register_for_project(context, fqdomain, project):
|
|
session = get_session()
|
|
with session.begin():
|
|
domain_ref = _dnsdomain_get_or_create(context, session, fqdomain)
|
|
domain_ref.scope = 'public'
|
|
domain_ref.project_id = project
|
|
domain_ref.save(session=session)
|
|
|
|
|
|
@require_admin_context
|
|
def dnsdomain_unregister(context, fqdomain):
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.DNSDomain).\
|
|
filter_by(domain=fqdomain).\
|
|
delete()
|
|
|
|
|
|
@require_context
|
|
def dnsdomain_list(context):
|
|
session = get_session()
|
|
records = model_query(context, models.DNSDomain,
|
|
session=session, read_deleted="no").\
|
|
with_lockmode('update').all()
|
|
domains = []
|
|
for record in records:
|
|
domains.append(record.domain)
|
|
|
|
return domains
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def fixed_ip_associate(context, address, instance_id, network_id=None,
|
|
reserved=False):
|
|
"""Keyword arguments:
|
|
reserved -- should be a boolean value(True or False), exact value will be
|
|
used to filter on the fixed ip address
|
|
"""
|
|
session = get_session()
|
|
with session.begin():
|
|
network_or_none = or_(models.FixedIp.network_id == network_id,
|
|
models.FixedIp.network_id == None)
|
|
fixed_ip_ref = model_query(context, models.FixedIp, session=session,
|
|
read_deleted="no").\
|
|
filter(network_or_none).\
|
|
filter_by(reserved=reserved).\
|
|
filter_by(address=address).\
|
|
with_lockmode('update').\
|
|
first()
|
|
# NOTE(vish): if with_lockmode isn't supported, as in sqlite,
|
|
# then this has concurrency issues
|
|
if fixed_ip_ref is None:
|
|
raise exception.FixedIpNotFoundForNetwork(address=address,
|
|
network_id=network_id)
|
|
if fixed_ip_ref.instance is not None:
|
|
raise exception.FixedIpAlreadyInUse(address=address)
|
|
|
|
if not fixed_ip_ref.network:
|
|
fixed_ip_ref.network = network_get(context,
|
|
network_id,
|
|
session=session)
|
|
fixed_ip_ref.instance = instance_get(context,
|
|
instance_id,
|
|
session=session)
|
|
session.add(fixed_ip_ref)
|
|
return fixed_ip_ref['address']
|
|
|
|
|
|
@require_admin_context
|
|
def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None):
|
|
session = get_session()
|
|
with session.begin():
|
|
network_or_none = or_(models.FixedIp.network_id == network_id,
|
|
models.FixedIp.network_id == None)
|
|
fixed_ip_ref = model_query(context, models.FixedIp, session=session,
|
|
read_deleted="no").\
|
|
filter(network_or_none).\
|
|
filter_by(reserved=False).\
|
|
filter_by(instance_id=None).\
|
|
filter_by(host=None).\
|
|
with_lockmode('update').\
|
|
first()
|
|
# NOTE(vish): if with_lockmode isn't supported, as in sqlite,
|
|
# then this has concurrency issues
|
|
if not fixed_ip_ref:
|
|
raise exception.NoMoreFixedIps()
|
|
|
|
if fixed_ip_ref['network_id'] is None:
|
|
fixed_ip_ref['network'] = network_id
|
|
|
|
if instance_id:
|
|
fixed_ip_ref['instance_id'] = instance_id
|
|
|
|
if host:
|
|
fixed_ip_ref['host'] = host
|
|
session.add(fixed_ip_ref)
|
|
return fixed_ip_ref['address']
|
|
|
|
|
|
@require_context
|
|
def fixed_ip_create(context, values):
|
|
fixed_ip_ref = models.FixedIp()
|
|
fixed_ip_ref.update(values)
|
|
fixed_ip_ref.save()
|
|
return fixed_ip_ref['address']
|
|
|
|
|
|
@require_context
|
|
def fixed_ip_bulk_create(context, ips):
|
|
session = get_session()
|
|
with session.begin():
|
|
for ip in ips:
|
|
model = models.FixedIp()
|
|
model.update(ip)
|
|
session.add(model)
|
|
|
|
|
|
@require_context
|
|
def fixed_ip_disassociate(context, address):
|
|
session = get_session()
|
|
with session.begin():
|
|
fixed_ip_ref = fixed_ip_get_by_address(context,
|
|
address,
|
|
session=session)
|
|
fixed_ip_ref['instance_id'] = None
|
|
fixed_ip_ref.save(session=session)
|
|
|
|
|
|
@require_admin_context
|
|
def fixed_ip_disassociate_all_by_timeout(context, host, time):
|
|
session = get_session()
|
|
# NOTE(vish): only update fixed ips that "belong" to this
|
|
# host; i.e. the network host or the instance
|
|
# host matches. Two queries necessary because
|
|
# join with update doesn't work.
|
|
host_filter = or_(and_(models.Instance.host == host,
|
|
models.Network.multi_host == True),
|
|
models.Network.host == host)
|
|
fixed_ips = model_query(context, models.FixedIp.id, session=session,
|
|
read_deleted="yes").\
|
|
filter(models.FixedIp.updated_at < time).\
|
|
filter(models.FixedIp.instance_id != None).\
|
|
filter(models.FixedIp.allocated == False).\
|
|
filter(host_filter).\
|
|
all()
|
|
result = model_query(context, models.FixedIp, session=session,
|
|
read_deleted="yes").\
|
|
filter(models.FixedIp.id.in_(fixed_ips)).\
|
|
update({'instance_id': None,
|
|
'leased': False,
|
|
'updated_at': utils.utcnow()},
|
|
synchronize_session='fetch')
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def fixed_ip_get(context, id, session=None):
|
|
result = model_query(context, models.FixedIp, session=session).\
|
|
filter_by(id=id).\
|
|
first()
|
|
if not result:
|
|
raise exception.FixedIpNotFound(id=id)
|
|
|
|
# FIXME(sirp): shouldn't we just use project_only here to restrict the
|
|
# results?
|
|
if is_user_context(context) and result['instance_id'] is not None:
|
|
instance = instance_get(context, result['instance_id'], session)
|
|
authorize_project_context(context, instance.project_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def fixed_ip_get_all(context, session=None):
|
|
result = model_query(context, models.FixedIp, session=session,
|
|
read_deleted="yes").\
|
|
all()
|
|
if not result:
|
|
raise exception.NoFixedIpsDefined()
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def fixed_ip_get_by_address(context, address, session=None):
|
|
result = model_query(context, models.FixedIp, session=session,
|
|
read_deleted="yes").\
|
|
filter_by(address=address).\
|
|
first()
|
|
if not result:
|
|
raise exception.FixedIpNotFoundForAddress(address=address)
|
|
|
|
# NOTE(sirp): shouldn't we just use project_only here to restrict the
|
|
# results?
|
|
if is_user_context(context) and result['instance_id'] is not None:
|
|
instance = instance_get(context, result['instance_id'], session)
|
|
authorize_project_context(context, instance.project_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def fixed_ip_get_by_instance(context, instance_id):
|
|
result = model_query(context, models.FixedIp, read_deleted="no").\
|
|
filter_by(instance_id=instance_id).\
|
|
all()
|
|
|
|
if not result:
|
|
raise exception.FixedIpNotFoundForInstance(instance_id=instance_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def fixed_ip_get_by_network_host(context, network_id, host):
|
|
result = model_query(context, models.FixedIp, read_deleted="no").\
|
|
filter_by(network_id=network_id).\
|
|
filter_by(host=host).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.FixedIpNotFoundForNetworkHost(network_id=network_id,
|
|
host=host)
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def fixed_ips_by_virtual_interface(context, vif_id):
|
|
result = model_query(context, models.FixedIp, read_deleted="no").\
|
|
filter_by(virtual_interface_id=vif_id).\
|
|
all()
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def fixed_ip_get_network(context, address):
|
|
fixed_ip_ref = fixed_ip_get_by_address(context, address)
|
|
return fixed_ip_ref.network
|
|
|
|
|
|
@require_context
|
|
def fixed_ip_update(context, address, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
fixed_ip_ref = fixed_ip_get_by_address(context,
|
|
address,
|
|
session=session)
|
|
fixed_ip_ref.update(values)
|
|
fixed_ip_ref.save(session=session)
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_context
|
|
def virtual_interface_create(context, values):
|
|
"""Create a new virtual interface record in the database.
|
|
|
|
:param values: = dict containing column values
|
|
"""
|
|
try:
|
|
vif_ref = models.VirtualInterface()
|
|
vif_ref.update(values)
|
|
vif_ref.save()
|
|
except IntegrityError:
|
|
raise exception.VirtualInterfaceCreateException()
|
|
|
|
return vif_ref
|
|
|
|
|
|
@require_context
|
|
def virtual_interface_update(context, vif_id, values):
|
|
"""Update a virtual interface record in the database.
|
|
|
|
:param vif_id: = id of virtual interface to update
|
|
:param values: = values to update
|
|
"""
|
|
session = get_session()
|
|
with session.begin():
|
|
vif_ref = virtual_interface_get(context, vif_id, session=session)
|
|
vif_ref.update(values)
|
|
vif_ref.save(session=session)
|
|
return vif_ref
|
|
|
|
|
|
@require_context
|
|
def _virtual_interface_query(context, session=None):
|
|
return model_query(context, models.VirtualInterface, session=session,
|
|
read_deleted="yes")
|
|
|
|
|
|
@require_context
|
|
def virtual_interface_get(context, vif_id, session=None):
|
|
"""Gets a virtual interface from the table.
|
|
|
|
:param vif_id: = id of the virtual interface
|
|
"""
|
|
vif_ref = _virtual_interface_query(context, session=session).\
|
|
filter_by(id=vif_id).\
|
|
first()
|
|
return vif_ref
|
|
|
|
|
|
@require_context
|
|
def virtual_interface_get_by_address(context, address):
|
|
"""Gets a virtual interface from the table.
|
|
|
|
:param address: = the address of the interface you're looking to get
|
|
"""
|
|
vif_ref = _virtual_interface_query(context).\
|
|
filter_by(address=address).\
|
|
first()
|
|
return vif_ref
|
|
|
|
|
|
@require_context
|
|
def virtual_interface_get_by_uuid(context, vif_uuid):
|
|
"""Gets a virtual interface from the table.
|
|
|
|
:param vif_uuid: the uuid of the interface you're looking to get
|
|
"""
|
|
vif_ref = _virtual_interface_query(context).\
|
|
filter_by(uuid=vif_uuid).\
|
|
first()
|
|
return vif_ref
|
|
|
|
|
|
@require_context
|
|
@require_instance_exists
|
|
def virtual_interface_get_by_instance(context, instance_id):
|
|
"""Gets all virtual interfaces for instance.
|
|
|
|
:param instance_id: = id of the instance to retrieve vifs for
|
|
"""
|
|
vif_refs = _virtual_interface_query(context).\
|
|
filter_by(instance_id=instance_id).\
|
|
all()
|
|
return vif_refs
|
|
|
|
|
|
@require_context
|
|
def virtual_interface_get_by_instance_and_network(context, instance_id,
|
|
network_id):
|
|
"""Gets virtual interface for instance that's associated with network."""
|
|
vif_ref = _virtual_interface_query(context).\
|
|
filter_by(instance_id=instance_id).\
|
|
filter_by(network_id=network_id).\
|
|
first()
|
|
return vif_ref
|
|
|
|
|
|
@require_admin_context
|
|
def virtual_interface_get_by_network(context, network_id):
|
|
"""Gets all virtual_interface on network.
|
|
|
|
:param network_id: = network to retrieve vifs for
|
|
"""
|
|
vif_refs = _virtual_interface_query(context).\
|
|
filter_by(network_id=network_id).\
|
|
all()
|
|
return vif_refs
|
|
|
|
|
|
@require_context
|
|
def virtual_interface_delete(context, vif_id):
|
|
"""Delete virtual interface record from the database.
|
|
|
|
:param vif_id: = id of vif to delete
|
|
"""
|
|
session = get_session()
|
|
vif_ref = virtual_interface_get(context, vif_id, session)
|
|
with session.begin():
|
|
session.delete(vif_ref)
|
|
|
|
|
|
@require_context
|
|
def virtual_interface_delete_by_instance(context, instance_id):
|
|
"""Delete virtual interface records that are associated
|
|
with the instance given by instance_id.
|
|
|
|
:param instance_id: = id of instance
|
|
"""
|
|
vif_refs = virtual_interface_get_by_instance(context, instance_id)
|
|
for vif_ref in vif_refs:
|
|
virtual_interface_delete(context, vif_ref['id'])
|
|
|
|
|
|
@require_context
|
|
def virtual_interface_get_all(context):
|
|
"""Get all vifs"""
|
|
vif_refs = _virtual_interface_query(context).all()
|
|
return vif_refs
|
|
|
|
|
|
###################
|
|
|
|
|
|
def _metadata_refs(metadata_dict, meta_class):
|
|
metadata_refs = []
|
|
if metadata_dict:
|
|
for k, v in metadata_dict.iteritems():
|
|
metadata_ref = meta_class()
|
|
metadata_ref['key'] = k
|
|
metadata_ref['value'] = v
|
|
metadata_refs.append(metadata_ref)
|
|
return metadata_refs
|
|
|
|
|
|
@require_context
|
|
def instance_create(context, values):
|
|
"""Create a new Instance record in the database.
|
|
|
|
context - request context object
|
|
values - dict containing column values.
|
|
"""
|
|
values['metadata'] = _metadata_refs(values.get('metadata'),
|
|
models.InstanceMetadata)
|
|
instance_ref = models.Instance()
|
|
instance_ref['uuid'] = str(utils.gen_uuid())
|
|
|
|
instance_ref.update(values)
|
|
|
|
session = get_session()
|
|
with session.begin():
|
|
instance_ref.save(session=session)
|
|
|
|
# and creat the info_cache table entry for instance
|
|
instance_info_cache_create(context, {'instance_id': instance_ref['uuid']})
|
|
|
|
return instance_ref
|
|
|
|
|
|
@require_admin_context
|
|
def instance_data_get_for_project(context, project_id):
|
|
result = model_query(context,
|
|
func.count(models.Instance.id),
|
|
func.sum(models.Instance.vcpus),
|
|
func.sum(models.Instance.memory_mb),
|
|
read_deleted="no").\
|
|
filter_by(project_id=project_id).\
|
|
first()
|
|
# NOTE(vish): convert None to 0
|
|
return (result[0] or 0, result[1] or 0, result[2] or 0)
|
|
|
|
|
|
@require_context
|
|
def instance_destroy(context, instance_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
instance_ref = instance_get(context, instance_id, session=session)
|
|
session.query(models.Instance).\
|
|
filter_by(id=instance_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
session.query(models.SecurityGroupInstanceAssociation).\
|
|
filter_by(instance_id=instance_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
session.query(models.InstanceMetadata).\
|
|
filter_by(instance_id=instance_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
session.query(models.BlockDeviceMapping).\
|
|
filter_by(instance_id=instance_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
instance_info_cache_delete(context, instance_ref['uuid'],
|
|
session=session)
|
|
|
|
|
|
@require_context
|
|
def instance_stop(context, instance_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.Instance).\
|
|
filter_by(id=instance_id).\
|
|
update({'host': None,
|
|
'vm_state': vm_states.STOPPED,
|
|
'task_state': None,
|
|
'updated_at': literal_column('updated_at')})
|
|
session.query(models.SecurityGroupInstanceAssociation).\
|
|
filter_by(instance_id=instance_id).\
|
|
update({'updated_at': literal_column('updated_at')})
|
|
session.query(models.InstanceMetadata).\
|
|
filter_by(instance_id=instance_id).\
|
|
update({'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def instance_get_by_uuid(context, uuid, session=None):
|
|
result = _build_instance_get(context, session=session).\
|
|
filter_by(uuid=uuid).\
|
|
first()
|
|
|
|
if not result:
|
|
# FIXME(sirp): it would be nice if InstanceNotFound would accept a
|
|
# uuid parameter as well
|
|
raise exception.InstanceNotFound(instance_id=uuid)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def instance_get(context, instance_id, session=None):
|
|
result = _build_instance_get(context, session=session).\
|
|
filter_by(id=instance_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.InstanceNotFound(instance_id=instance_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def _build_instance_get(context, session=None):
|
|
return model_query(context, models.Instance, session=session,
|
|
project_only=True).\
|
|
options(joinedload_all('security_groups.rules')).\
|
|
options(joinedload('info_cache')).\
|
|
options(joinedload('volumes')).\
|
|
options(joinedload('metadata')).\
|
|
options(joinedload('instance_type'))
|
|
|
|
|
|
@require_admin_context
|
|
def instance_get_all(context):
|
|
return model_query(context, models.Instance).\
|
|
options(joinedload('info_cache')).\
|
|
options(joinedload('security_groups')).\
|
|
options(joinedload('metadata')).\
|
|
options(joinedload('instance_type')).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def instance_get_all_by_filters(context, filters):
|
|
"""Return instances that match all filters. Deleted instances
|
|
will be returned by default, unless there's a filter that says
|
|
otherwise"""
|
|
|
|
def _regexp_filter_by_metadata(instance, meta):
|
|
inst_metadata = [{node['key']: node['value']}
|
|
for node in instance['metadata']]
|
|
if isinstance(meta, list):
|
|
for node in meta:
|
|
if node not in inst_metadata:
|
|
return False
|
|
elif isinstance(meta, dict):
|
|
for k, v in meta.iteritems():
|
|
if {k: v} not in inst_metadata:
|
|
return False
|
|
return True
|
|
|
|
def _regexp_filter_by_column(instance, filter_name, filter_re):
|
|
try:
|
|
v = getattr(instance, filter_name)
|
|
except AttributeError:
|
|
return True
|
|
if v and filter_re.match(str(v)):
|
|
return True
|
|
return False
|
|
|
|
session = get_session()
|
|
query_prefix = session.query(models.Instance).\
|
|
options(joinedload('info_cache')).\
|
|
options(joinedload('security_groups')).\
|
|
options(joinedload('metadata')).\
|
|
options(joinedload('instance_type')).\
|
|
order_by(desc(models.Instance.created_at))
|
|
|
|
# Make a copy of the filters dictionary to use going forward, as we'll
|
|
# be modifying it and we shouldn't affect the caller's use of it.
|
|
filters = filters.copy()
|
|
|
|
if 'changes-since' in filters:
|
|
changes_since = filters['changes-since']
|
|
query_prefix = query_prefix.\
|
|
filter(models.Instance.updated_at > changes_since)
|
|
|
|
if 'deleted' in filters:
|
|
# Instances can be soft or hard deleted and the query needs to
|
|
# include or exclude both
|
|
if filters.pop('deleted'):
|
|
deleted = or_(models.Instance.deleted == True,
|
|
models.Instance.vm_state == vm_states.SOFT_DELETE)
|
|
query_prefix = query_prefix.filter(deleted)
|
|
else:
|
|
query_prefix = query_prefix.\
|
|
filter_by(deleted=False).\
|
|
filter(models.Instance.vm_state != vm_states.SOFT_DELETE)
|
|
|
|
if not context.is_admin:
|
|
# If we're not admin context, add appropriate filter..
|
|
if context.project_id:
|
|
filters['project_id'] = context.project_id
|
|
else:
|
|
filters['user_id'] = context.user_id
|
|
|
|
# Filters for exact matches that we can do along with the SQL query...
|
|
# For other filters that don't match this, we will do regexp matching
|
|
exact_match_filter_names = ['project_id', 'user_id', 'image_ref',
|
|
'vm_state', 'instance_type_id', 'uuid']
|
|
|
|
# Filter the query
|
|
query_prefix = exact_filter(query_prefix, models.Instance,
|
|
filters, exact_match_filter_names)
|
|
|
|
instances = query_prefix.all()
|
|
if not instances:
|
|
return []
|
|
|
|
# Now filter on everything else for regexp matching..
|
|
# For filters not in the list, we'll attempt to use the filter_name
|
|
# as a column name in Instance..
|
|
regexp_filter_funcs = {}
|
|
|
|
for filter_name in filters.iterkeys():
|
|
filter_func = regexp_filter_funcs.get(filter_name, None)
|
|
filter_re = re.compile(str(filters[filter_name]))
|
|
if filter_func:
|
|
filter_l = lambda instance: filter_func(instance, filter_re)
|
|
elif filter_name == 'metadata':
|
|
filter_l = lambda instance: _regexp_filter_by_metadata(instance,
|
|
filters[filter_name])
|
|
else:
|
|
filter_l = lambda instance: _regexp_filter_by_column(instance,
|
|
filter_name, filter_re)
|
|
instances = filter(filter_l, instances)
|
|
if not instances:
|
|
break
|
|
|
|
return instances
|
|
|
|
|
|
@require_context
|
|
def instance_get_active_by_window(context, begin, end=None, project_id=None):
|
|
"""Return instances that were active during window."""
|
|
session = get_session()
|
|
query = session.query(models.Instance)
|
|
|
|
query = query.filter(or_(models.Instance.terminated_at == None,
|
|
models.Instance.terminated_at > begin))
|
|
if end:
|
|
query = query.filter(models.Instance.launched_at < end)
|
|
if project_id:
|
|
query = query.filter_by(project_id=project_id)
|
|
|
|
return query.all()
|
|
|
|
|
|
@require_admin_context
|
|
def instance_get_active_by_window_joined(context, begin, end=None,
|
|
project_id=None):
|
|
"""Return instances and joins that were active during window."""
|
|
session = get_session()
|
|
query = session.query(models.Instance)
|
|
|
|
query = query.options(joinedload('security_groups')).\
|
|
options(joinedload('instance_type')).\
|
|
filter(or_(models.Instance.terminated_at == None,
|
|
models.Instance.terminated_at > begin))
|
|
if end:
|
|
query = query.filter(models.Instance.launched_at < end)
|
|
if project_id:
|
|
query = query.filter_by(project_id=project_id)
|
|
|
|
return query.all()
|
|
|
|
|
|
@require_admin_context
|
|
def _instance_get_all_query(context, project_only=False):
|
|
return model_query(context, models.Instance, project_only=project_only).\
|
|
options(joinedload('info_cache')).\
|
|
options(joinedload('security_groups')).\
|
|
options(joinedload('metadata')).\
|
|
options(joinedload('instance_type'))
|
|
|
|
|
|
@require_admin_context
|
|
def instance_get_all_by_user(context, user_id):
|
|
return _instance_get_all_query(context).filter_by(user_id=user_id).all()
|
|
|
|
|
|
@require_admin_context
|
|
def instance_get_all_by_host(context, host):
|
|
return _instance_get_all_query(context).filter_by(host=host).all()
|
|
|
|
|
|
@require_context
|
|
def instance_get_all_by_project(context, project_id):
|
|
authorize_project_context(context, project_id)
|
|
return _instance_get_all_query(context).\
|
|
filter_by(project_id=project_id).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def instance_get_all_by_reservation(context, reservation_id):
|
|
return _instance_get_all_query(context, project_only=True).\
|
|
filter_by(reservation_id=reservation_id).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def instance_get_project_vpn(context, project_id):
|
|
return _instance_get_all_query(context).\
|
|
filter_by(project_id=project_id).\
|
|
filter_by(image_ref=str(FLAGS.vpn_image_id)).\
|
|
first()
|
|
|
|
|
|
# NOTE(jkoelker) This is only being left here for compat with floating
|
|
# ips. Currently the network_api doesn't return floaters
|
|
# in network_info. Once it starts return the model. This
|
|
# function and it's call in compute/manager.py on 1829 can
|
|
# go away
|
|
@require_context
|
|
def instance_get_floating_address(context, instance_id):
|
|
fixed_ips = fixed_ip_get_by_instance(context, instance_id)
|
|
if not fixed_ips:
|
|
return None
|
|
# NOTE(tr3buchet): this only gets the first fixed_ip
|
|
# won't find floating ips associated with other fixed_ips
|
|
floating_ips = floating_ip_get_by_fixed_address(context,
|
|
fixed_ips[0]['address'])
|
|
if not floating_ips:
|
|
return None
|
|
# NOTE(vish): this just returns the first floating ip
|
|
return floating_ips[0]['address']
|
|
|
|
|
|
@require_admin_context
|
|
def instance_get_all_hung_in_rebooting(context, reboot_window, session=None):
|
|
reboot_window = datetime.datetime.utcnow() - datetime.timedelta(
|
|
seconds=reboot_window)
|
|
|
|
if not session:
|
|
session = get_session()
|
|
|
|
results = session.query(models.Instance).\
|
|
filter(models.Instance.updated_at <= reboot_window).\
|
|
filter_by(task_state="rebooting").all()
|
|
|
|
return results
|
|
|
|
|
|
@require_context
|
|
def instance_update(context, instance_id, values):
|
|
session = get_session()
|
|
|
|
if utils.is_uuid_like(instance_id):
|
|
instance_ref = instance_get_by_uuid(context, instance_id,
|
|
session=session)
|
|
else:
|
|
instance_ref = instance_get(context, instance_id, session=session)
|
|
|
|
metadata = values.get('metadata')
|
|
if metadata is not None:
|
|
instance_metadata_update(context,
|
|
instance_ref['id'],
|
|
values.pop('metadata'),
|
|
delete=True)
|
|
with session.begin():
|
|
instance_ref.update(values)
|
|
instance_ref.save(session=session)
|
|
|
|
return instance_ref
|
|
|
|
|
|
def instance_add_security_group(context, instance_uuid, security_group_id):
|
|
"""Associate the given security group with the given instance"""
|
|
session = get_session()
|
|
with session.begin():
|
|
instance_ref = instance_get_by_uuid(context, instance_uuid,
|
|
session=session)
|
|
security_group_ref = security_group_get(context,
|
|
security_group_id,
|
|
session=session)
|
|
instance_ref.security_groups += [security_group_ref]
|
|
instance_ref.save(session=session)
|
|
|
|
|
|
@require_context
|
|
def instance_remove_security_group(context, instance_uuid, security_group_id):
|
|
"""Disassociate the given security group from the given instance"""
|
|
session = get_session()
|
|
instance_ref = instance_get_by_uuid(context, instance_uuid,
|
|
session=session)
|
|
session.query(models.SecurityGroupInstanceAssociation).\
|
|
filter_by(instance_id=instance_ref['id']).\
|
|
filter_by(security_group_id=security_group_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def instance_action_create(context, values):
|
|
"""Create an instance action from the values dictionary."""
|
|
action_ref = models.InstanceActions()
|
|
action_ref.update(values)
|
|
|
|
session = get_session()
|
|
with session.begin():
|
|
action_ref.save(session=session)
|
|
return action_ref
|
|
|
|
|
|
@require_admin_context
|
|
def instance_get_actions(context, instance_uuid):
|
|
"""Return the actions associated to the given instance id"""
|
|
session = get_session()
|
|
return session.query(models.InstanceActions).\
|
|
filter_by(instance_uuid=instance_uuid).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def instance_get_id_to_uuid_mapping(context, ids):
|
|
session = get_session()
|
|
instances = session.query(models.Instance).\
|
|
filter(models.Instance.id.in_(ids)).\
|
|
all()
|
|
mapping = {}
|
|
for instance in instances:
|
|
mapping[instance['id']] = instance['uuid']
|
|
return mapping
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_context
|
|
def instance_info_cache_create(context, values):
|
|
"""Create a new instance cache record in the table.
|
|
|
|
:param context: = request context object
|
|
:param values: = dict containing column values
|
|
"""
|
|
info_cache = models.InstanceInfoCache()
|
|
info_cache.update(values)
|
|
|
|
session = get_session()
|
|
with session.begin():
|
|
info_cache.save(session=session)
|
|
return info_cache
|
|
|
|
|
|
@require_context
|
|
def instance_info_cache_get(context, instance_uuid, session=None):
|
|
"""Gets an instance info cache from the table.
|
|
|
|
:param instance_uuid: = uuid of the info cache's instance
|
|
:param session: = optional session object
|
|
"""
|
|
session = session or get_session()
|
|
|
|
info_cache = session.query(models.InstanceInfoCache).\
|
|
filter_by(instance_id=instance_uuid).\
|
|
first()
|
|
return info_cache
|
|
|
|
|
|
@require_context
|
|
def instance_info_cache_update(context, instance_uuid, values,
|
|
session=None):
|
|
"""Update an instance info cache record in the table.
|
|
|
|
:param instance_uuid: = uuid of info cache's instance
|
|
:param values: = dict containing column values to update
|
|
:param session: = optional session object
|
|
"""
|
|
session = session or get_session()
|
|
info_cache = instance_info_cache_get(context, instance_uuid,
|
|
session=session)
|
|
|
|
if info_cache:
|
|
info_cache.update(values)
|
|
info_cache.save(session=session)
|
|
else:
|
|
# NOTE(tr3buchet): just in case someone blows away an instance's
|
|
# cache entry
|
|
values['instance_id'] = instance_uuid
|
|
info_cache = instance_info_cache_create(context, values)
|
|
|
|
return info_cache
|
|
|
|
|
|
@require_context
|
|
def instance_info_cache_delete(context, instance_uuid, session=None):
|
|
"""Deletes an existing instance_info_cache record
|
|
|
|
:param instance_uuid: = uuid of the instance tied to the cache record
|
|
:param session: = optional session object
|
|
"""
|
|
values = {'deleted': True,
|
|
'deleted_at': utils.utcnow()}
|
|
instance_info_cache_update(context, instance_uuid, values, session)
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_context
|
|
def key_pair_create(context, values):
|
|
key_pair_ref = models.KeyPair()
|
|
key_pair_ref.update(values)
|
|
key_pair_ref.save()
|
|
return key_pair_ref
|
|
|
|
|
|
@require_context
|
|
def key_pair_destroy(context, user_id, name):
|
|
authorize_user_context(context, user_id)
|
|
session = get_session()
|
|
with session.begin():
|
|
key_pair_ref = key_pair_get(context, user_id, name, session=session)
|
|
key_pair_ref.delete(session=session)
|
|
|
|
|
|
@require_context
|
|
def key_pair_destroy_all_by_user(context, user_id):
|
|
authorize_user_context(context, user_id)
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.KeyPair).\
|
|
filter_by(user_id=user_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def key_pair_get(context, user_id, name, session=None):
|
|
authorize_user_context(context, user_id)
|
|
result = model_query(context, models.KeyPair, session=session).\
|
|
filter_by(user_id=user_id).\
|
|
filter_by(name=name).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.KeypairNotFound(user_id=user_id, name=name)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def key_pair_get_all_by_user(context, user_id):
|
|
authorize_user_context(context, user_id)
|
|
return model_query(context, models.KeyPair, read_deleted="no").\
|
|
filter_by(user_id=user_id).\
|
|
all()
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def network_associate(context, project_id, force=False):
|
|
"""Associate a project with a network.
|
|
|
|
called by project_get_networks under certain conditions
|
|
and network manager add_network_to_project()
|
|
|
|
only associate if the project doesn't already have a network
|
|
or if force is True
|
|
|
|
force solves race condition where a fresh project has multiple instance
|
|
builds simultaneously picked up by multiple network hosts which attempt
|
|
to associate the project with multiple networks
|
|
force should only be used as a direct consequence of user request
|
|
all automated requests should not use force
|
|
"""
|
|
session = get_session()
|
|
with session.begin():
|
|
|
|
def network_query(project_filter):
|
|
return model_query(context, models.Network, session=session,
|
|
read_deleted="no").\
|
|
filter_by(project_id=project_filter).\
|
|
with_lockmode('update').\
|
|
first()
|
|
|
|
if not force:
|
|
# find out if project has a network
|
|
network_ref = network_query(project_id)
|
|
|
|
if force or not network_ref:
|
|
# in force mode or project doesn't have a network so associate
|
|
# with a new network
|
|
|
|
# get new network
|
|
network_ref = network_query(None)
|
|
if not network_ref:
|
|
raise db.NoMoreNetworks()
|
|
|
|
# associate with network
|
|
# NOTE(vish): if with_lockmode isn't supported, as in sqlite,
|
|
# then this has concurrency issues
|
|
network_ref['project_id'] = project_id
|
|
session.add(network_ref)
|
|
return network_ref
|
|
|
|
|
|
@require_admin_context
|
|
def network_count(context):
|
|
return model_query(context, models.Network).count()
|
|
|
|
|
|
@require_admin_context
|
|
def _network_ips_query(context, network_id):
|
|
return model_query(context, models.FixedIp, read_deleted="no").\
|
|
filter_by(network_id=network_id)
|
|
|
|
|
|
@require_admin_context
|
|
def network_count_allocated_ips(context, network_id):
|
|
return _network_ips_query(context, network_id).\
|
|
filter_by(allocated=True).\
|
|
count()
|
|
|
|
|
|
@require_admin_context
|
|
def network_count_available_ips(context, network_id):
|
|
return _network_ips_query(context, network_id).\
|
|
filter_by(allocated=False).\
|
|
filter_by(reserved=False).\
|
|
count()
|
|
|
|
|
|
@require_admin_context
|
|
def network_count_reserved_ips(context, network_id):
|
|
return _network_ips_query(context, network_id).\
|
|
filter_by(reserved=True).\
|
|
count()
|
|
|
|
|
|
@require_admin_context
|
|
def network_create_safe(context, values):
|
|
network_ref = models.Network()
|
|
network_ref['uuid'] = str(utils.gen_uuid())
|
|
network_ref.update(values)
|
|
try:
|
|
network_ref.save()
|
|
return network_ref
|
|
except IntegrityError:
|
|
return None
|
|
|
|
|
|
@require_admin_context
|
|
def network_delete_safe(context, network_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
network_ref = network_get(context, network_id=network_id,
|
|
session=session)
|
|
session.delete(network_ref)
|
|
|
|
|
|
@require_admin_context
|
|
def network_disassociate(context, network_id):
|
|
network_update(context, network_id, {'project_id': None,
|
|
'host': None})
|
|
|
|
|
|
@require_admin_context
|
|
def network_disassociate_all(context):
|
|
session = get_session()
|
|
session.query(models.Network).\
|
|
update({'project_id': None,
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def network_get(context, network_id, session=None):
|
|
result = model_query(context, models.Network, session=session,
|
|
project_only=True).\
|
|
filter_by(id=network_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.NetworkNotFound(network_id=network_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def network_get_all(context):
|
|
result = model_query(context, models.Network, read_deleted="no").all()
|
|
|
|
if not result:
|
|
raise exception.NoNetworksFound()
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def network_get_all_by_uuids(context, network_uuids, project_id=None):
|
|
project_or_none = or_(models.Network.project_id == project_id,
|
|
models.Network.project_id == None)
|
|
result = model_query(context, models.Network, read_deleted="no").\
|
|
filter(models.Network.uuid.in_(network_uuids)).\
|
|
filter(project_or_none).\
|
|
all()
|
|
|
|
if not result:
|
|
raise exception.NoNetworksFound()
|
|
|
|
#check if host is set to all of the networks
|
|
# returned in the result
|
|
for network in result:
|
|
if network['host'] is None:
|
|
raise exception.NetworkHostNotSet(network_id=network['id'])
|
|
|
|
#check if the result contains all the networks
|
|
#we are looking for
|
|
for network_uuid in network_uuids:
|
|
found = False
|
|
for network in result:
|
|
if network['uuid'] == network_uuid:
|
|
found = True
|
|
break
|
|
if not found:
|
|
if project_id:
|
|
raise exception.NetworkNotFoundForProject(
|
|
network_uuid=network_uuid, project_id=context.project_id)
|
|
raise exception.NetworkNotFound(network_id=network_uuid)
|
|
|
|
return result
|
|
|
|
# NOTE(vish): pylint complains because of the long method name, but
|
|
# it fits with the names of the rest of the methods
|
|
# pylint: disable=C0103
|
|
|
|
|
|
@require_admin_context
|
|
def network_get_associated_fixed_ips(context, network_id):
|
|
# FIXME(sirp): since this returns fixed_ips, this would be better named
|
|
# fixed_ip_get_all_by_network.
|
|
return model_query(context, models.FixedIp, read_deleted="no").\
|
|
filter_by(network_id=network_id).\
|
|
filter(models.FixedIp.instance_id != None).\
|
|
filter(models.FixedIp.virtual_interface_id != None).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def _network_get_query(context, session=None):
|
|
return model_query(context, models.Network, session=session,
|
|
read_deleted="no")
|
|
|
|
|
|
@require_admin_context
|
|
def network_get_by_bridge(context, bridge):
|
|
result = _network_get_query(context).filter_by(bridge=bridge).first()
|
|
|
|
if not result:
|
|
raise exception.NetworkNotFoundForBridge(bridge=bridge)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def network_get_by_uuid(context, uuid):
|
|
result = _network_get_query(context).filter_by(uuid=uuid).first()
|
|
|
|
if not result:
|
|
raise exception.NetworkNotFoundForUUID(uuid=uuid)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def network_get_by_cidr(context, cidr):
|
|
result = _network_get_query(context).\
|
|
filter(or_(models.Network.cidr == cidr,
|
|
models.Network.cidr_v6 == cidr)).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.NetworkNotFoundForCidr(cidr=cidr)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def network_get_by_instance(context, instance_id):
|
|
# note this uses fixed IP to get to instance
|
|
# only works for networks the instance has an IP from
|
|
result = _network_get_query(context).\
|
|
filter_by(instance_id=instance_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.NetworkNotFoundForInstance(instance_id=instance_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def network_get_all_by_instance(context, instance_id):
|
|
result = _network_get_query(context).\
|
|
filter_by(instance_id=instance_id).\
|
|
all()
|
|
|
|
if not result:
|
|
raise exception.NetworkNotFoundForInstance(instance_id=instance_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def network_get_all_by_host(context, host):
|
|
# NOTE(vish): return networks that have host set
|
|
# or that have a fixed ip with host set
|
|
host_filter = or_(models.Network.host == host,
|
|
models.FixedIp.host == host)
|
|
return _network_get_query(context).\
|
|
filter(host_filter).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def network_set_host(context, network_id, host_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
network_ref = _network_get_query(context, session=session).\
|
|
filter_by(id=network_id).\
|
|
with_lockmode('update').\
|
|
first()
|
|
|
|
if not network_ref:
|
|
raise exception.NetworkNotFound(network_id=network_id)
|
|
|
|
# NOTE(vish): if with_lockmode isn't supported, as in sqlite,
|
|
# then this has concurrency issues
|
|
if not network_ref['host']:
|
|
network_ref['host'] = host_id
|
|
session.add(network_ref)
|
|
|
|
return network_ref['host']
|
|
|
|
|
|
@require_context
|
|
def network_update(context, network_id, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
network_ref = network_get(context, network_id, session=session)
|
|
network_ref.update(values)
|
|
network_ref.save(session=session)
|
|
return network_ref
|
|
|
|
|
|
###################
|
|
|
|
|
|
def queue_get_for(context, topic, physical_node_id):
|
|
# FIXME(ja): this should be servername?
|
|
return "%s.%s" % (topic, physical_node_id)
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def iscsi_target_count_by_host(context, host):
|
|
return model_query(context, models.IscsiTarget).\
|
|
filter_by(host=host).\
|
|
count()
|
|
|
|
|
|
@require_admin_context
|
|
def iscsi_target_create_safe(context, values):
|
|
iscsi_target_ref = models.IscsiTarget()
|
|
for (key, value) in values.iteritems():
|
|
iscsi_target_ref[key] = value
|
|
try:
|
|
iscsi_target_ref.save()
|
|
return iscsi_target_ref
|
|
except IntegrityError:
|
|
return None
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def auth_token_destroy(context, token_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
token_ref = auth_token_get(context, token_id, session=session)
|
|
token_ref.delete(session=session)
|
|
|
|
|
|
@require_admin_context
|
|
def auth_token_get(context, token_hash, session=None):
|
|
result = model_query(context, models.AuthToken, session=session).\
|
|
filter_by(token_hash=token_hash).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.AuthTokenNotFound(token=token_hash)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def auth_token_update(context, token_hash, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
token_ref = auth_token_get(context, token_hash, session=session)
|
|
token_ref.update(values)
|
|
token_ref.save(session=session)
|
|
|
|
|
|
@require_admin_context
|
|
def auth_token_create(context, token):
|
|
tk = models.AuthToken()
|
|
tk.update(token)
|
|
tk.save()
|
|
return tk
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_context
|
|
def quota_get(context, project_id, resource, session=None):
|
|
result = model_query(context, models.Quota, session=session,
|
|
read_deleted="no").\
|
|
filter_by(project_id=project_id).\
|
|
filter_by(resource=resource).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.ProjectQuotaNotFound(project_id=project_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def quota_get_all_by_project(context, project_id):
|
|
authorize_project_context(context, project_id)
|
|
|
|
rows = model_query(context, models.Quota, read_deleted="no").\
|
|
filter_by(project_id=project_id).\
|
|
all()
|
|
|
|
result = {'project_id': project_id}
|
|
for row in rows:
|
|
result[row.resource] = row.hard_limit
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def quota_create(context, project_id, resource, limit):
|
|
quota_ref = models.Quota()
|
|
quota_ref.project_id = project_id
|
|
quota_ref.resource = resource
|
|
quota_ref.hard_limit = limit
|
|
quota_ref.save()
|
|
return quota_ref
|
|
|
|
|
|
@require_admin_context
|
|
def quota_update(context, project_id, resource, limit):
|
|
session = get_session()
|
|
with session.begin():
|
|
quota_ref = quota_get(context, project_id, resource, session=session)
|
|
quota_ref.hard_limit = limit
|
|
quota_ref.save(session=session)
|
|
|
|
|
|
@require_admin_context
|
|
def quota_destroy(context, project_id, resource):
|
|
session = get_session()
|
|
with session.begin():
|
|
quota_ref = quota_get(context, project_id, resource, session=session)
|
|
quota_ref.delete(session=session)
|
|
|
|
|
|
@require_admin_context
|
|
def quota_destroy_all_by_project(context, project_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
quotas = model_query(context, models.Quota, session=session,
|
|
read_deleted="no").\
|
|
filter_by(project_id=project_id).\
|
|
all()
|
|
|
|
for quota_ref in quotas:
|
|
quota_ref.delete(session=session)
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def volume_allocate_iscsi_target(context, volume_id, host):
|
|
session = get_session()
|
|
with session.begin():
|
|
iscsi_target_ref = model_query(context, models.IscsiTarget,
|
|
session=session, read_deleted="no").\
|
|
filter_by(volume=None).\
|
|
filter_by(host=host).\
|
|
with_lockmode('update').\
|
|
first()
|
|
|
|
# NOTE(vish): if with_lockmode isn't supported, as in sqlite,
|
|
# then this has concurrency issues
|
|
if not iscsi_target_ref:
|
|
raise db.NoMoreTargets()
|
|
|
|
iscsi_target_ref.volume_id = volume_id
|
|
session.add(iscsi_target_ref)
|
|
|
|
return iscsi_target_ref.target_num
|
|
|
|
|
|
@require_admin_context
|
|
def volume_attached(context, volume_id, instance_id, mountpoint):
|
|
session = get_session()
|
|
with session.begin():
|
|
volume_ref = volume_get(context, volume_id, session=session)
|
|
volume_ref['status'] = 'in-use'
|
|
volume_ref['mountpoint'] = mountpoint
|
|
volume_ref['attach_status'] = 'attached'
|
|
volume_ref.instance = instance_get(context, instance_id,
|
|
session=session)
|
|
volume_ref.save(session=session)
|
|
|
|
|
|
@require_context
|
|
def volume_create(context, values):
|
|
values['volume_metadata'] = _metadata_refs(values.get('metadata'),
|
|
models.VolumeMetadata)
|
|
volume_ref = models.Volume()
|
|
volume_ref.update(values)
|
|
|
|
session = get_session()
|
|
with session.begin():
|
|
volume_ref.save(session=session)
|
|
return volume_ref
|
|
|
|
|
|
@require_admin_context
|
|
def volume_data_get_for_project(context, project_id):
|
|
result = model_query(context,
|
|
func.count(models.Volume.id),
|
|
func.sum(models.Volume.size),
|
|
read_deleted="no").\
|
|
filter_by(project_id=project_id).\
|
|
first()
|
|
|
|
# NOTE(vish): convert None to 0
|
|
return (result[0] or 0, result[1] or 0)
|
|
|
|
|
|
@require_admin_context
|
|
def volume_destroy(context, volume_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.Volume).\
|
|
filter_by(id=volume_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
session.query(models.IscsiTarget).\
|
|
filter_by(volume_id=volume_id).\
|
|
update({'volume_id': None})
|
|
session.query(models.VolumeMetadata).\
|
|
filter_by(volume_id=volume_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_admin_context
|
|
def volume_detached(context, volume_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
volume_ref = volume_get(context, volume_id, session=session)
|
|
volume_ref['status'] = 'available'
|
|
volume_ref['mountpoint'] = None
|
|
volume_ref['attach_status'] = 'detached'
|
|
volume_ref.instance = None
|
|
volume_ref.save(session=session)
|
|
|
|
|
|
@require_context
|
|
def _volume_get_query(context, session=None, project_only=False):
|
|
return model_query(context, models.Volume, session=session,
|
|
project_only=project_only).\
|
|
options(joinedload('instance')).\
|
|
options(joinedload('volume_metadata')).\
|
|
options(joinedload('volume_type'))
|
|
|
|
|
|
@require_context
|
|
def volume_get(context, volume_id, session=None):
|
|
result = _volume_get_query(context, session=session, project_only=True).\
|
|
filter_by(id=volume_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.VolumeNotFound(volume_id=volume_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def volume_get_all(context):
|
|
return _volume_get_query(context).all()
|
|
|
|
|
|
@require_admin_context
|
|
def volume_get_all_by_host(context, host):
|
|
return _volume_get_query(context).filter_by(host=host).all()
|
|
|
|
|
|
@require_admin_context
|
|
def volume_get_all_by_instance(context, instance_id):
|
|
result = model_query(context, models.Volume, read_deleted="no").\
|
|
options(joinedload('volume_metadata')).\
|
|
options(joinedload('volume_type')).\
|
|
filter_by(instance_id=instance_id).\
|
|
all()
|
|
|
|
if not result:
|
|
raise exception.VolumeNotFoundForInstance(instance_id=instance_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def volume_get_all_by_project(context, project_id):
|
|
authorize_project_context(context, project_id)
|
|
return _volume_get_query(context).filter_by(project_id=project_id).all()
|
|
|
|
|
|
@require_admin_context
|
|
def volume_get_instance(context, volume_id):
|
|
result = _volume_get_query(context).filter_by(id=volume_id).first()
|
|
|
|
if not result:
|
|
raise exception.VolumeNotFound(volume_id=volume_id)
|
|
|
|
return result.instance
|
|
|
|
|
|
@require_admin_context
|
|
def volume_get_iscsi_target_num(context, volume_id):
|
|
result = model_query(context, models.IscsiTarget, read_deleted="yes").\
|
|
filter_by(volume_id=volume_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.ISCSITargetNotFoundForVolume(volume_id=volume_id)
|
|
|
|
return result.target_num
|
|
|
|
|
|
@require_context
|
|
def volume_update(context, volume_id, values):
|
|
session = get_session()
|
|
metadata = values.get('metadata')
|
|
if metadata is not None:
|
|
volume_metadata_update(context,
|
|
volume_id,
|
|
values.pop('metadata'),
|
|
delete=True)
|
|
with session.begin():
|
|
volume_ref = volume_get(context, volume_id, session=session)
|
|
volume_ref.update(values)
|
|
volume_ref.save(session=session)
|
|
|
|
|
|
####################
|
|
|
|
def _volume_metadata_get_query(context, volume_id, session=None):
|
|
return model_query(context, models.VolumeMetadata,
|
|
session=session, read_deleted="no").\
|
|
filter_by(volume_id=volume_id)
|
|
|
|
|
|
@require_context
|
|
@require_volume_exists
|
|
def volume_metadata_get(context, volume_id):
|
|
rows = _volume_metadata_get_query(context, volume_id).all()
|
|
result = {}
|
|
for row in rows:
|
|
result[row['key']] = row['value']
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
@require_volume_exists
|
|
def volume_metadata_delete(context, volume_id, key):
|
|
_volume_metadata_get_query(context, volume_id).\
|
|
filter_by(key=key).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
@require_volume_exists
|
|
def volume_metadata_get_item(context, volume_id, key, session=None):
|
|
result = _volume_metadata_get_query(context, volume_id, session=session).\
|
|
filter_by(key=key).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.VolumeMetadataNotFound(metadata_key=key,
|
|
volume_id=volume_id)
|
|
return result
|
|
|
|
|
|
@require_context
|
|
@require_volume_exists
|
|
def volume_metadata_update(context, volume_id, metadata, delete):
|
|
session = get_session()
|
|
|
|
# Set existing metadata to deleted if delete argument is True
|
|
if delete:
|
|
original_metadata = volume_metadata_get(context, volume_id)
|
|
for meta_key, meta_value in original_metadata.iteritems():
|
|
if meta_key not in metadata:
|
|
meta_ref = volume_metadata_get_item(context, volume_id,
|
|
meta_key, session)
|
|
meta_ref.update({'deleted': True})
|
|
meta_ref.save(session=session)
|
|
|
|
meta_ref = None
|
|
|
|
# Now update all existing items with new values, or create new meta objects
|
|
for meta_key, meta_value in metadata.iteritems():
|
|
|
|
# update the value whether it exists or not
|
|
item = {"value": meta_value}
|
|
|
|
try:
|
|
meta_ref = volume_metadata_get_item(context, volume_id,
|
|
meta_key, session)
|
|
except exception.VolumeMetadataNotFound, e:
|
|
meta_ref = models.VolumeMetadata()
|
|
item.update({"key": meta_key, "volume_id": volume_id})
|
|
|
|
meta_ref.update(item)
|
|
meta_ref.save(session=session)
|
|
|
|
return metadata
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_context
|
|
def snapshot_create(context, values):
|
|
snapshot_ref = models.Snapshot()
|
|
snapshot_ref.update(values)
|
|
|
|
session = get_session()
|
|
with session.begin():
|
|
snapshot_ref.save(session=session)
|
|
return snapshot_ref
|
|
|
|
|
|
@require_admin_context
|
|
def snapshot_destroy(context, snapshot_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.Snapshot).\
|
|
filter_by(id=snapshot_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def snapshot_get(context, snapshot_id, session=None):
|
|
result = model_query(context, models.Snapshot, session=session,
|
|
project_only=True).\
|
|
filter_by(id=snapshot_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.SnapshotNotFound(snapshot_id=snapshot_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def snapshot_get_all(context):
|
|
return model_query(context, models.Snapshot).all()
|
|
|
|
|
|
@require_context
|
|
def snapshot_get_all_by_project(context, project_id):
|
|
authorize_project_context(context, project_id)
|
|
return model_query(context, models.Snapshot).\
|
|
filter_by(project_id=project_id).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def snapshot_update(context, snapshot_id, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
snapshot_ref = snapshot_get(context, snapshot_id, session=session)
|
|
snapshot_ref.update(values)
|
|
snapshot_ref.save(session=session)
|
|
|
|
|
|
###################
|
|
|
|
|
|
def _block_device_mapping_get_query(context, session=None):
|
|
return model_query(context, models.BlockDeviceMapping, session=session,
|
|
read_deleted="no")
|
|
|
|
|
|
@require_context
|
|
def block_device_mapping_create(context, values):
|
|
bdm_ref = models.BlockDeviceMapping()
|
|
bdm_ref.update(values)
|
|
|
|
session = get_session()
|
|
with session.begin():
|
|
bdm_ref.save(session=session)
|
|
|
|
|
|
@require_context
|
|
def block_device_mapping_update(context, bdm_id, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
_block_device_mapping_get_query(context, session=session).\
|
|
filter_by(id=bdm_id).\
|
|
update(values)
|
|
|
|
|
|
@require_context
|
|
def block_device_mapping_update_or_create(context, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
result = _block_device_mapping_get_query(context, session=session).\
|
|
filter_by(instance_id=values['instance_id']).\
|
|
filter_by(device_name=values['device_name']).\
|
|
first()
|
|
if not result:
|
|
bdm_ref = models.BlockDeviceMapping()
|
|
bdm_ref.update(values)
|
|
bdm_ref.save(session=session)
|
|
else:
|
|
result.update(values)
|
|
|
|
# NOTE(yamahata): same virtual device name can be specified multiple
|
|
# times. So delete the existing ones.
|
|
virtual_name = values['virtual_name']
|
|
if (virtual_name is not None and
|
|
block_device.is_swap_or_ephemeral(virtual_name)):
|
|
session.query(models.BlockDeviceMapping).\
|
|
filter_by(instance_id=values['instance_id']).\
|
|
filter_by(virtual_name=virtual_name).\
|
|
filter(models.BlockDeviceMapping.device_name !=
|
|
values['device_name']).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def block_device_mapping_get_all_by_instance(context, instance_id):
|
|
return _block_device_mapping_get_query(context).\
|
|
filter_by(instance_id=instance_id).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def block_device_mapping_destroy(context, bdm_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.BlockDeviceMapping).\
|
|
filter_by(id=bdm_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def block_device_mapping_destroy_by_instance_and_volume(context, instance_id,
|
|
volume_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
_block_device_mapping_get_query(context, session=session).\
|
|
filter_by(instance_id=instance_id).\
|
|
filter_by(volume_id=volume_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
###################
|
|
|
|
def _security_group_get_query(context, session=None, read_deleted=None,
|
|
project_only=False):
|
|
return model_query(context, models.SecurityGroup, session=session,
|
|
read_deleted=read_deleted, project_only=project_only).\
|
|
options(joinedload_all('rules'))
|
|
|
|
|
|
@require_context
|
|
def security_group_get_all(context):
|
|
return _security_group_get_query(context).all()
|
|
|
|
|
|
@require_context
|
|
def security_group_get(context, security_group_id, session=None):
|
|
result = _security_group_get_query(context, session=session,
|
|
project_only=True).\
|
|
filter_by(id=security_group_id).\
|
|
options(joinedload_all('instances')).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.SecurityGroupNotFound(
|
|
security_group_id=security_group_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def security_group_get_by_name(context, project_id, group_name):
|
|
result = _security_group_get_query(context, read_deleted="no").\
|
|
filter_by(project_id=project_id).\
|
|
filter_by(name=group_name).\
|
|
options(joinedload_all('instances')).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.SecurityGroupNotFoundForProject(
|
|
project_id=project_id, security_group_id=group_name)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def security_group_get_by_project(context, project_id):
|
|
return _security_group_get_query(context, read_deleted="no").\
|
|
filter_by(project_id=project_id).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def security_group_get_by_instance(context, instance_id):
|
|
return _security_group_get_query(context, read_deleted="no").\
|
|
join(models.SecurityGroup.instances).\
|
|
filter_by(id=instance_id).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def security_group_exists(context, project_id, group_name):
|
|
try:
|
|
group = security_group_get_by_name(context, project_id, group_name)
|
|
return group is not None
|
|
except exception.NotFound:
|
|
return False
|
|
|
|
|
|
@require_context
|
|
def security_group_create(context, values):
|
|
security_group_ref = models.SecurityGroup()
|
|
# FIXME(devcamcar): Unless I do this, rules fails with lazy load exception
|
|
# once save() is called. This will get cleaned up in next orm pass.
|
|
security_group_ref.rules
|
|
security_group_ref.update(values)
|
|
security_group_ref.save()
|
|
return security_group_ref
|
|
|
|
|
|
@require_context
|
|
def security_group_destroy(context, security_group_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.SecurityGroup).\
|
|
filter_by(id=security_group_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
session.query(models.SecurityGroupInstanceAssociation).\
|
|
filter_by(security_group_id=security_group_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
session.query(models.SecurityGroupIngressRule).\
|
|
filter_by(group_id=security_group_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def security_group_destroy_all(context, session=None):
|
|
if not session:
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.SecurityGroup).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
session.query(models.SecurityGroupIngressRule).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
###################
|
|
|
|
|
|
def _security_group_rule_get_query(context, session=None):
|
|
return model_query(context, models.SecurityGroupIngressRule,
|
|
session=session)
|
|
|
|
|
|
@require_context
|
|
def security_group_rule_get(context, security_group_rule_id, session=None):
|
|
result = _security_group_rule_get_query(context, session=session).\
|
|
filter_by(id=security_group_rule_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.SecurityGroupNotFoundForRule(
|
|
rule_id=security_group_rule_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def security_group_rule_get_by_security_group(context, security_group_id,
|
|
session=None):
|
|
return _security_group_rule_get_query(context, session=session).\
|
|
filter_by(parent_group_id=security_group_id).\
|
|
options(joinedload_all('grantee_group.instances')).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def security_group_rule_get_by_security_group_grantee(context,
|
|
security_group_id,
|
|
session=None):
|
|
|
|
return _security_group_rule_get_query(context, session=session).\
|
|
filter_by(group_id=security_group_id).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def security_group_rule_create(context, values):
|
|
security_group_rule_ref = models.SecurityGroupIngressRule()
|
|
security_group_rule_ref.update(values)
|
|
security_group_rule_ref.save()
|
|
return security_group_rule_ref
|
|
|
|
|
|
@require_context
|
|
def security_group_rule_destroy(context, security_group_rule_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
security_group_rule = security_group_rule_get(context,
|
|
security_group_rule_id,
|
|
session=session)
|
|
security_group_rule.delete(session=session)
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def provider_fw_rule_create(context, rule):
|
|
fw_rule_ref = models.ProviderFirewallRule()
|
|
fw_rule_ref.update(rule)
|
|
fw_rule_ref.save()
|
|
return fw_rule_ref
|
|
|
|
|
|
@require_admin_context
|
|
def provider_fw_rule_get_all(context):
|
|
return model_query(context, models.ProviderFirewallRule).all()
|
|
|
|
|
|
@require_admin_context
|
|
def provider_fw_rule_get_all_by_cidr(context, cidr):
|
|
return model_query(context, models.ProviderFirewallRule).\
|
|
filter_by(cidr=cidr).\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def provider_fw_rule_destroy(context, rule_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.ProviderFirewallRule).\
|
|
filter_by(id=rule_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def user_get(context, id, session=None):
|
|
result = model_query(context, models.User, session=session).\
|
|
filter_by(id=id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.UserNotFound(user_id=id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def user_get_by_access_key(context, access_key, session=None):
|
|
result = model_query(context, models.User, session=session).\
|
|
filter_by(access_key=access_key).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.AccessKeyNotFound(access_key=access_key)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def user_create(context, values):
|
|
user_ref = models.User()
|
|
user_ref.update(values)
|
|
user_ref.save()
|
|
return user_ref
|
|
|
|
|
|
@require_admin_context
|
|
def user_delete(context, id):
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.UserProjectAssociation).\
|
|
filter_by(user_id=id).\
|
|
delete()
|
|
session.query(models.UserRoleAssociation).\
|
|
filter_by(user_id=id).\
|
|
delete()
|
|
session.query(models.UserProjectRoleAssociation).\
|
|
filter_by(user_id=id).\
|
|
delete()
|
|
user_ref = user_get(context, id, session=session)
|
|
session.delete(user_ref)
|
|
|
|
|
|
def user_get_all(context):
|
|
return model_query(context, models.User).all()
|
|
|
|
|
|
def user_get_roles(context, user_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
user_ref = user_get(context, user_id, session=session)
|
|
return [role.role for role in user_ref['roles']]
|
|
|
|
|
|
def user_get_roles_for_project(context, user_id, project_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
res = session.query(models.UserProjectRoleAssociation).\
|
|
filter_by(user_id=user_id).\
|
|
filter_by(project_id=project_id).\
|
|
all()
|
|
return [association.role for association in res]
|
|
|
|
|
|
def user_remove_project_role(context, user_id, project_id, role):
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.UserProjectRoleAssociation).\
|
|
filter_by(user_id=user_id).\
|
|
filter_by(project_id=project_id).\
|
|
filter_by(role=role).\
|
|
delete()
|
|
|
|
|
|
def user_remove_role(context, user_id, role):
|
|
session = get_session()
|
|
with session.begin():
|
|
res = session.query(models.UserRoleAssociation).\
|
|
filter_by(user_id=user_id).\
|
|
filter_by(role=role).\
|
|
all()
|
|
for role in res:
|
|
session.delete(role)
|
|
|
|
|
|
def user_add_role(context, user_id, role):
|
|
session = get_session()
|
|
with session.begin():
|
|
user_ref = user_get(context, user_id, session=session)
|
|
models.UserRoleAssociation(user=user_ref, role=role).\
|
|
save(session=session)
|
|
|
|
|
|
def user_add_project_role(context, user_id, project_id, role):
|
|
session = get_session()
|
|
with session.begin():
|
|
user_ref = user_get(context, user_id, session=session)
|
|
project_ref = project_get(context, project_id, session=session)
|
|
models.UserProjectRoleAssociation(user_id=user_ref['id'],
|
|
project_id=project_ref['id'],
|
|
role=role).save(session=session)
|
|
|
|
|
|
def user_update(context, user_id, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
user_ref = user_get(context, user_id, session=session)
|
|
user_ref.update(values)
|
|
user_ref.save(session=session)
|
|
|
|
|
|
###################
|
|
|
|
|
|
def project_create(context, values):
|
|
project_ref = models.Project()
|
|
project_ref.update(values)
|
|
project_ref.save()
|
|
return project_ref
|
|
|
|
|
|
def project_add_member(context, project_id, user_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
project_ref = project_get(context, project_id, session=session)
|
|
user_ref = user_get(context, user_id, session=session)
|
|
|
|
project_ref.members += [user_ref]
|
|
project_ref.save(session=session)
|
|
|
|
|
|
def project_get(context, id, session=None):
|
|
result = model_query(context, models.Project, session=session,
|
|
read_deleted="no").\
|
|
filter_by(id=id).\
|
|
options(joinedload_all('members')).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.ProjectNotFound(project_id=id)
|
|
|
|
return result
|
|
|
|
|
|
def project_get_all(context):
|
|
return model_query(context, models.Project).\
|
|
options(joinedload_all('members')).\
|
|
all()
|
|
|
|
|
|
def project_get_by_user(context, user_id):
|
|
user = model_query(context, models.User).\
|
|
filter_by(id=user_id).\
|
|
options(joinedload_all('projects')).\
|
|
first()
|
|
|
|
if not user:
|
|
raise exception.UserNotFound(user_id=user_id)
|
|
|
|
return user.projects
|
|
|
|
|
|
def project_remove_member(context, project_id, user_id):
|
|
session = get_session()
|
|
project = project_get(context, project_id, session=session)
|
|
user = user_get(context, user_id, session=session)
|
|
|
|
if user in project.members:
|
|
project.members.remove(user)
|
|
project.save(session=session)
|
|
|
|
|
|
def project_update(context, project_id, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
project_ref = project_get(context, project_id, session=session)
|
|
project_ref.update(values)
|
|
project_ref.save(session=session)
|
|
|
|
|
|
def project_delete(context, id):
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.UserProjectAssociation).\
|
|
filter_by(project_id=id).\
|
|
delete()
|
|
session.query(models.UserProjectRoleAssociation).\
|
|
filter_by(project_id=id).\
|
|
delete()
|
|
project_ref = project_get(context, id, session=session)
|
|
session.delete(project_ref)
|
|
|
|
|
|
@require_context
|
|
def project_get_networks(context, project_id, associate=True):
|
|
# NOTE(tr3buchet): as before this function will associate
|
|
# a project with a network if it doesn't have one and
|
|
# associate is true
|
|
result = model_query(context, models.Network, read_deleted="no").\
|
|
filter_by(project_id=project_id).\
|
|
all()
|
|
|
|
if not result:
|
|
if not associate:
|
|
return []
|
|
|
|
return [network_associate(context, project_id)]
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def project_get_networks_v6(context, project_id):
|
|
return project_get_networks(context, project_id)
|
|
|
|
|
|
###################
|
|
|
|
|
|
@require_admin_context
|
|
def migration_create(context, values):
|
|
migration = models.Migration()
|
|
migration.update(values)
|
|
migration.save()
|
|
return migration
|
|
|
|
|
|
@require_admin_context
|
|
def migration_update(context, id, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
migration = migration_get(context, id, session=session)
|
|
migration.update(values)
|
|
migration.save(session=session)
|
|
return migration
|
|
|
|
|
|
@require_admin_context
|
|
def migration_get(context, id, session=None):
|
|
result = model_query(context, models.Migration, session=session,
|
|
read_deleted="yes").\
|
|
filter_by(id=id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.MigrationNotFound(migration_id=id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def migration_get_by_instance_and_status(context, instance_uuid, status):
|
|
result = model_query(context, models.Migration, read_deleted="yes").\
|
|
filter_by(instance_uuid=instance_uuid).\
|
|
filter_by(status=status).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.MigrationNotFoundByStatus(instance_id=instance_uuid,
|
|
status=status)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def migration_get_all_unconfirmed(context, confirm_window, session=None):
|
|
confirm_window = datetime.datetime.utcnow() - datetime.timedelta(
|
|
seconds=confirm_window)
|
|
|
|
return model_query(context, models.Migration, session=session,
|
|
read_deleted="yes").\
|
|
filter(models.Migration.updated_at <= confirm_window).\
|
|
filter_by(status="FINISHED").\
|
|
all()
|
|
|
|
|
|
##################
|
|
|
|
|
|
def console_pool_create(context, values):
|
|
pool = models.ConsolePool()
|
|
pool.update(values)
|
|
pool.save()
|
|
return pool
|
|
|
|
|
|
def console_pool_get(context, pool_id):
|
|
result = model_query(context, models.ConsolePool, read_deleted="no").\
|
|
filter_by(id=pool_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.ConsolePoolNotFound(pool_id=pool_id)
|
|
|
|
return result
|
|
|
|
|
|
def console_pool_get_by_host_type(context, compute_host, host,
|
|
console_type):
|
|
|
|
result = model_query(context, models.ConsolePool, read_deleted="no").\
|
|
filter_by(host=host).\
|
|
filter_by(console_type=console_type).\
|
|
filter_by(compute_host=compute_host).\
|
|
options(joinedload('consoles')).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.ConsolePoolNotFoundForHostType(
|
|
host=host, console_type=console_type,
|
|
compute_host=compute_host)
|
|
|
|
return result
|
|
|
|
|
|
def console_pool_get_all_by_host_type(context, host, console_type):
|
|
return model_query(context, models.ConsolePool, read_deleted="no").\
|
|
filter_by(host=host).\
|
|
filter_by(console_type=console_type).\
|
|
options(joinedload('consoles')).\
|
|
all()
|
|
|
|
|
|
def console_create(context, values):
|
|
console = models.Console()
|
|
console.update(values)
|
|
console.save()
|
|
return console
|
|
|
|
|
|
def console_delete(context, console_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
# NOTE(mdragon): consoles are meant to be transient.
|
|
session.query(models.Console).\
|
|
filter_by(id=console_id).\
|
|
delete()
|
|
|
|
|
|
def console_get_by_pool_instance(context, pool_id, instance_id):
|
|
result = model_query(context, models.Console, read_deleted="yes").\
|
|
filter_by(pool_id=pool_id).\
|
|
filter_by(instance_id=instance_id).\
|
|
options(joinedload('pool')).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.ConsoleNotFoundInPoolForInstance(
|
|
pool_id=pool_id, instance_id=instance_id)
|
|
|
|
return result
|
|
|
|
|
|
def console_get_all_by_instance(context, instance_id):
|
|
return model_query(context, models.Console, read_deleted="yes").\
|
|
filter_by(instance_id=instance_id).\
|
|
all()
|
|
|
|
|
|
def console_get(context, console_id, instance_id=None):
|
|
query = model_query(context, models.Console, read_deleted="yes").\
|
|
filter_by(id=console_id).\
|
|
options(joinedload('pool'))
|
|
|
|
if instance_id is not None:
|
|
query = query.filter_by(instance_id=instance_id)
|
|
|
|
result = query.first()
|
|
|
|
if not result:
|
|
if instance_id:
|
|
raise exception.ConsoleNotFoundForInstance(
|
|
console_id=console_id, instance_id=instance_id)
|
|
else:
|
|
raise exception.ConsoleNotFound(console_id=console_id)
|
|
|
|
return result
|
|
|
|
|
|
##################
|
|
|
|
|
|
@require_admin_context
|
|
def instance_type_create(context, values):
|
|
"""Create a new instance type. In order to pass in extra specs,
|
|
the values dict should contain a 'extra_specs' key/value pair:
|
|
|
|
{'extra_specs' : {'k1': 'v1', 'k2': 'v2', ...}}
|
|
|
|
"""
|
|
session = get_session()
|
|
with session.begin():
|
|
try:
|
|
instance_type_get_by_name(context, values['name'], session)
|
|
raise exception.InstanceTypeExists(name=values['name'])
|
|
except exception.InstanceTypeNotFoundByName:
|
|
pass
|
|
try:
|
|
instance_type_get_by_flavor_id(context, values['flavorid'],
|
|
session)
|
|
raise exception.InstanceTypeExists(name=values['name'])
|
|
except exception.FlavorNotFound:
|
|
pass
|
|
try:
|
|
specs = values.get('extra_specs')
|
|
specs_refs = []
|
|
if specs:
|
|
for k, v in specs.iteritems():
|
|
specs_ref = models.InstanceTypeExtraSpecs()
|
|
specs_ref['key'] = k
|
|
specs_ref['value'] = v
|
|
specs_refs.append(specs_ref)
|
|
values['extra_specs'] = specs_refs
|
|
instance_type_ref = models.InstanceTypes()
|
|
instance_type_ref.update(values)
|
|
instance_type_ref.save(session=session)
|
|
except Exception, e:
|
|
raise exception.DBError(e)
|
|
return _dict_with_extra_specs(instance_type_ref)
|
|
|
|
|
|
def _dict_with_extra_specs(inst_type_query):
|
|
"""Takes an instance, volume, or instance type query returned
|
|
by sqlalchemy and returns it as a dictionary, converting the
|
|
extra_specs entry from a list of dicts:
|
|
|
|
'extra_specs' : [{'key': 'k1', 'value': 'v1', ...}, ...]
|
|
|
|
to a single dict:
|
|
|
|
'extra_specs' : {'k1': 'v1'}
|
|
|
|
"""
|
|
inst_type_dict = dict(inst_type_query)
|
|
extra_specs = dict([(x['key'], x['value'])
|
|
for x in inst_type_query['extra_specs']])
|
|
inst_type_dict['extra_specs'] = extra_specs
|
|
return inst_type_dict
|
|
|
|
|
|
def _instance_type_get_query(context, session=None, read_deleted=None):
|
|
return model_query(context, models.InstanceTypes, session=session,
|
|
read_deleted=read_deleted).\
|
|
options(joinedload('extra_specs'))
|
|
|
|
|
|
@require_context
|
|
def instance_type_get_all(context, inactive=False, filters=None):
|
|
"""
|
|
Returns all instance types.
|
|
"""
|
|
filters = filters or {}
|
|
read_deleted = "yes" if inactive else "no"
|
|
query = _instance_type_get_query(context, read_deleted=read_deleted)
|
|
|
|
if 'min_memory_mb' in filters:
|
|
query = query.filter(
|
|
models.InstanceTypes.memory_mb >= filters['min_memory_mb'])
|
|
if 'min_root_gb' in filters:
|
|
query = query.filter(
|
|
models.InstanceTypes.root_gb >= filters['min_root_gb'])
|
|
|
|
inst_types = query.order_by("name").all()
|
|
|
|
return [_dict_with_extra_specs(i) for i in inst_types]
|
|
|
|
|
|
@require_context
|
|
def instance_type_get(context, id, session=None):
|
|
"""Returns a dict describing specific instance_type"""
|
|
result = _instance_type_get_query(context, session=session).\
|
|
filter_by(id=id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.InstanceTypeNotFound(instance_type_id=id)
|
|
|
|
return _dict_with_extra_specs(result)
|
|
|
|
|
|
@require_context
|
|
def instance_type_get_by_name(context, name, session=None):
|
|
"""Returns a dict describing specific instance_type"""
|
|
result = _instance_type_get_query(context, session=session).\
|
|
filter_by(name=name).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.InstanceTypeNotFoundByName(instance_type_name=name)
|
|
|
|
return _dict_with_extra_specs(result)
|
|
|
|
|
|
@require_context
|
|
def instance_type_get_by_flavor_id(context, flavor_id, session=None):
|
|
"""Returns a dict describing specific flavor_id"""
|
|
result = _instance_type_get_query(context, session=session).\
|
|
filter_by(flavorid=flavor_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.FlavorNotFound(flavor_id=flavor_id)
|
|
|
|
return _dict_with_extra_specs(result)
|
|
|
|
|
|
@require_admin_context
|
|
def instance_type_destroy(context, name):
|
|
"""Marks specific instance_type as deleted"""
|
|
session = get_session()
|
|
with session.begin():
|
|
instance_type_ref = instance_type_get_by_name(context, name,
|
|
session=session)
|
|
instance_type_id = instance_type_ref['id']
|
|
session.query(models.InstanceTypes).\
|
|
filter_by(id=instance_type_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
session.query(models.InstanceTypeExtraSpecs).\
|
|
filter_by(instance_type_id=instance_type_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
####################
|
|
|
|
|
|
@require_admin_context
|
|
def zone_create(context, values):
|
|
zone = models.Zone()
|
|
zone.update(values)
|
|
zone.save()
|
|
return zone
|
|
|
|
|
|
def _zone_get_by_id_query(context, zone_id, session=None):
|
|
return model_query(context, models.Zone, session=session).\
|
|
filter_by(id=zone_id)
|
|
|
|
|
|
@require_admin_context
|
|
def zone_update(context, zone_id, values):
|
|
zone = zone_get(context, zone_id)
|
|
zone.update(values)
|
|
zone.save()
|
|
return zone
|
|
|
|
|
|
@require_admin_context
|
|
def zone_delete(context, zone_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
_zone_get_by_id_query(context, zone_id, session=session).\
|
|
delete()
|
|
|
|
|
|
@require_admin_context
|
|
def zone_get(context, zone_id):
|
|
result = _zone_get_by_id_query(context, zone_id).first()
|
|
|
|
if not result:
|
|
raise exception.ZoneNotFound(zone_id=zone_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def zone_get_all(context):
|
|
return model_query(context, models.Zone, read_deleted="yes").all()
|
|
|
|
|
|
####################
|
|
|
|
|
|
def _instance_metadata_get_query(context, instance_id, session=None):
|
|
return model_query(context, models.InstanceMetadata, session=session,
|
|
read_deleted="no").\
|
|
filter_by(instance_id=instance_id)
|
|
|
|
|
|
@require_context
|
|
@require_instance_exists
|
|
def instance_metadata_get(context, instance_id):
|
|
rows = _instance_metadata_get_query(context, instance_id).all()
|
|
|
|
result = {}
|
|
for row in rows:
|
|
result[row['key']] = row['value']
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
@require_instance_exists
|
|
def instance_metadata_delete(context, instance_id, key):
|
|
_instance_metadata_get_query(context, instance_id).\
|
|
filter_by(key=key).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
@require_instance_exists
|
|
def instance_metadata_get_item(context, instance_id, key, session=None):
|
|
result = _instance_metadata_get_query(
|
|
context, instance_id, session=session).\
|
|
filter_by(key=key).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.InstanceMetadataNotFound(metadata_key=key,
|
|
instance_id=instance_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
@require_instance_exists
|
|
def instance_metadata_update(context, instance_id, metadata, delete):
|
|
session = get_session()
|
|
|
|
# Set existing metadata to deleted if delete argument is True
|
|
if delete:
|
|
original_metadata = instance_metadata_get(context, instance_id)
|
|
for meta_key, meta_value in original_metadata.iteritems():
|
|
if meta_key not in metadata:
|
|
meta_ref = instance_metadata_get_item(context, instance_id,
|
|
meta_key, session)
|
|
meta_ref.update({'deleted': True})
|
|
meta_ref.save(session=session)
|
|
|
|
meta_ref = None
|
|
|
|
# Now update all existing items with new values, or create new meta objects
|
|
for meta_key, meta_value in metadata.iteritems():
|
|
|
|
# update the value whether it exists or not
|
|
item = {"value": meta_value}
|
|
|
|
try:
|
|
meta_ref = instance_metadata_get_item(context, instance_id,
|
|
meta_key, session)
|
|
except exception.InstanceMetadataNotFound, e:
|
|
meta_ref = models.InstanceMetadata()
|
|
item.update({"key": meta_key, "instance_id": instance_id})
|
|
|
|
meta_ref.update(item)
|
|
meta_ref.save(session=session)
|
|
|
|
return metadata
|
|
|
|
|
|
####################
|
|
|
|
|
|
@require_admin_context
|
|
def agent_build_create(context, values):
|
|
agent_build_ref = models.AgentBuild()
|
|
agent_build_ref.update(values)
|
|
agent_build_ref.save()
|
|
return agent_build_ref
|
|
|
|
|
|
@require_admin_context
|
|
def agent_build_get_by_triple(context, hypervisor, os, architecture,
|
|
session=None):
|
|
return model_query(context, models.AgentBuild, session=session,
|
|
read_deleted="no").\
|
|
filter_by(hypervisor=hypervisor).\
|
|
filter_by(os=os).\
|
|
filter_by(architecture=architecture).\
|
|
first()
|
|
|
|
|
|
@require_admin_context
|
|
def agent_build_get_all(context):
|
|
return model_query(context, models.AgentBuild, read_deleted="no").\
|
|
all()
|
|
|
|
|
|
@require_admin_context
|
|
def agent_build_destroy(context, agent_build_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
model_query(context, models.AgentBuild, session=session,
|
|
read_deleted="yes").\
|
|
filter_by(id=agent_build_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_admin_context
|
|
def agent_build_update(context, agent_build_id, values):
|
|
session = get_session()
|
|
with session.begin():
|
|
agent_build_ref = model_query(context, models.AgentBuild,
|
|
session=session, read_deleted="yes").\
|
|
filter_by(id=agent_build_id).\
|
|
first()
|
|
|
|
agent_build_ref.update(values)
|
|
agent_build_ref.save(session=session)
|
|
|
|
|
|
####################
|
|
|
|
@require_context
|
|
def bw_usage_get_by_instance(context, instance_id, start_period):
|
|
return model_query(context, models.BandwidthUsage, read_deleted="yes").\
|
|
filter_by(instance_id=instance_id).\
|
|
filter_by(start_period=start_period).\
|
|
all()
|
|
|
|
|
|
@require_context
|
|
def bw_usage_get_all_by_filters(context, filters):
|
|
"""Return bandwidth usage that matches all filters."""
|
|
|
|
session = get_session()
|
|
query_prefix = session.query(models.BandwidthUsage).\
|
|
order_by(desc(models.BandwidthUsage.created_at))
|
|
|
|
# Make a copy of the filters dictionary to use going forward, as we'll
|
|
# be modifying it and we shouldn't affect the caller's use of it.
|
|
filters = filters.copy()
|
|
|
|
# Filters for exact matches that we can do along with the SQL query.
|
|
exact_match_filter_names = ["instance_id", "network_label",
|
|
"start_period", "last_refreshed", "bw_in", "bw_out"]
|
|
|
|
# Filter the query
|
|
query_prefix = exact_filter(query_prefix, models.BandwidthUsage,
|
|
filters, exact_match_filter_names)
|
|
|
|
return query_prefix.all()
|
|
|
|
|
|
@require_context
|
|
def bw_usage_update(context,
|
|
instance_id,
|
|
mac,
|
|
start_period,
|
|
bw_in, bw_out,
|
|
session=None):
|
|
if not session:
|
|
session = get_session()
|
|
|
|
with session.begin():
|
|
bwusage = model_query(context, models.BandwidthUsage,
|
|
read_deleted="yes").\
|
|
filter_by(instance_id=instance_id).\
|
|
filter_by(start_period=start_period).\
|
|
filter_by(mac=mac).\
|
|
first()
|
|
|
|
if not bwusage:
|
|
bwusage = models.BandwidthUsage()
|
|
bwusage.instance_id = instance_id
|
|
bwusage.start_period = start_period
|
|
bwusage.mac = mac
|
|
|
|
bwusage.last_refreshed = utils.utcnow()
|
|
bwusage.bw_in = bw_in
|
|
bwusage.bw_out = bw_out
|
|
bwusage.save(session=session)
|
|
|
|
|
|
####################
|
|
|
|
|
|
def _instance_type_extra_specs_get_query(context, instance_type_id,
|
|
session=None):
|
|
return model_query(context, models.InstanceTypeExtraSpecs,
|
|
session=session, read_deleted="no").\
|
|
filter_by(instance_type_id=instance_type_id)
|
|
|
|
|
|
@require_context
|
|
def instance_type_extra_specs_get(context, instance_type_id):
|
|
rows = _instance_type_extra_specs_get_query(
|
|
context, instance_type_id).\
|
|
all()
|
|
|
|
result = {}
|
|
for row in rows:
|
|
result[row['key']] = row['value']
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def instance_type_extra_specs_delete(context, instance_type_id, key):
|
|
_instance_type_extra_specs_get_query(
|
|
context, instance_type_id).\
|
|
filter_by(key=key).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def instance_type_extra_specs_get_item(context, instance_type_id, key,
|
|
session=None):
|
|
result = _instance_type_extra_specs_get_query(
|
|
context, instance_type_id, session=session).\
|
|
filter_by(key=key).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.InstanceTypeExtraSpecsNotFound(
|
|
extra_specs_key=key, instance_type_id=instance_type_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def instance_type_extra_specs_update_or_create(context, instance_type_id,
|
|
specs):
|
|
session = get_session()
|
|
spec_ref = None
|
|
for key, value in specs.iteritems():
|
|
try:
|
|
spec_ref = instance_type_extra_specs_get_item(
|
|
context, instance_type_id, key, session)
|
|
except exception.InstanceTypeExtraSpecsNotFound, e:
|
|
spec_ref = models.InstanceTypeExtraSpecs()
|
|
spec_ref.update({"key": key, "value": value,
|
|
"instance_type_id": instance_type_id,
|
|
"deleted": 0})
|
|
spec_ref.save(session=session)
|
|
return specs
|
|
|
|
|
|
##################
|
|
|
|
|
|
@require_admin_context
|
|
def volume_type_create(context, values):
|
|
"""Create a new instance type. In order to pass in extra specs,
|
|
the values dict should contain a 'extra_specs' key/value pair:
|
|
|
|
{'extra_specs' : {'k1': 'v1', 'k2': 'v2', ...}}
|
|
|
|
"""
|
|
session = get_session()
|
|
with session.begin():
|
|
try:
|
|
volume_type_get_by_name(context, values['name'], session)
|
|
raise exception.VolumeTypeExists(name=values['name'])
|
|
except exception.VolumeTypeNotFoundByName:
|
|
pass
|
|
try:
|
|
specs = values.get('extra_specs')
|
|
|
|
values['extra_specs'] = _metadata_refs(values.get('extra_specs'),
|
|
models.VolumeTypeExtraSpecs)
|
|
volume_type_ref = models.VolumeTypes()
|
|
volume_type_ref.update(values)
|
|
volume_type_ref.save()
|
|
except Exception, e:
|
|
raise exception.DBError(e)
|
|
return volume_type_ref
|
|
|
|
|
|
@require_context
|
|
def volume_type_get_all(context, inactive=False, filters=None):
|
|
"""
|
|
Returns a dict describing all volume_types with name as key.
|
|
"""
|
|
filters = filters or {}
|
|
|
|
read_deleted = "yes" if inactive else "no"
|
|
rows = model_query(context, models.VolumeTypes,
|
|
read_deleted=read_deleted).\
|
|
options(joinedload('extra_specs')).\
|
|
order_by("name").\
|
|
all()
|
|
|
|
# TODO(sirp): this patern of converting rows to a result with extra_specs
|
|
# is repeated quite a bit, might be worth creating a method for it
|
|
result = {}
|
|
for row in rows:
|
|
result[row['name']] = _dict_with_extra_specs(row)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def volume_type_get(context, id, session=None):
|
|
"""Returns a dict describing specific volume_type"""
|
|
result = model_query(context, models.VolumeTypes, session=session).\
|
|
options(joinedload('extra_specs')).\
|
|
filter_by(id=id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.VolumeTypeNotFound(volume_type=id)
|
|
|
|
return _dict_with_extra_specs(result)
|
|
|
|
|
|
@require_context
|
|
def volume_type_get_by_name(context, name, session=None):
|
|
"""Returns a dict describing specific volume_type"""
|
|
result = model_query(context, models.VolumeTypes, session=session).\
|
|
options(joinedload('extra_specs')).\
|
|
filter_by(name=name).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.VolumeTypeNotFoundByName(volume_type_name=name)
|
|
else:
|
|
return _dict_with_extra_specs(result)
|
|
|
|
|
|
@require_admin_context
|
|
def volume_type_destroy(context, name):
|
|
session = get_session()
|
|
with session.begin():
|
|
volume_type_ref = volume_type_get_by_name(context, name,
|
|
session=session)
|
|
volume_type_id = volume_type_ref['id']
|
|
session.query(models.VolumeTypes).\
|
|
filter_by(id=volume_type_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
session.query(models.VolumeTypeExtraSpecs).\
|
|
filter_by(volume_type_id=volume_type_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
####################
|
|
|
|
|
|
def _volume_type_extra_specs_query(context, volume_type_id, session=None):
|
|
return model_query(context, models.VolumeTypeExtraSpecs, session=session,
|
|
read_deleted="no").\
|
|
filter_by(volume_type_id=volume_type_id)
|
|
|
|
|
|
@require_context
|
|
def volume_type_extra_specs_get(context, volume_type_id):
|
|
rows = _volume_type_extra_specs_query(context, volume_type_id).\
|
|
all()
|
|
|
|
result = {}
|
|
for row in rows:
|
|
result[row['key']] = row['value']
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def volume_type_extra_specs_delete(context, volume_type_id, key):
|
|
_volume_type_extra_specs_query(context, volume_type_id).\
|
|
filter_by(key=key).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def volume_type_extra_specs_get_item(context, volume_type_id, key,
|
|
session=None):
|
|
result = _volume_type_extra_specs_query(
|
|
context, volume_type_id, session=session).\
|
|
filter_by(key=key).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.VolumeTypeExtraSpecsNotFound(
|
|
extra_specs_key=key, volume_type_id=volume_type_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_context
|
|
def volume_type_extra_specs_update_or_create(context, volume_type_id,
|
|
specs):
|
|
session = get_session()
|
|
spec_ref = None
|
|
for key, value in specs.iteritems():
|
|
try:
|
|
spec_ref = volume_type_extra_specs_get_item(
|
|
context, volume_type_id, key, session)
|
|
except exception.VolumeTypeExtraSpecsNotFound, e:
|
|
spec_ref = models.VolumeTypeExtraSpecs()
|
|
spec_ref.update({"key": key, "value": value,
|
|
"volume_type_id": volume_type_id,
|
|
"deleted": 0})
|
|
spec_ref.save(session=session)
|
|
return specs
|
|
|
|
|
|
####################
|
|
|
|
|
|
def _vsa_get_query(context, session=None, project_only=False):
|
|
return model_query(context, models.VirtualStorageArray, session=session,
|
|
project_only=project_only).\
|
|
options(joinedload('vsa_instance_type'))
|
|
|
|
|
|
@require_admin_context
|
|
def vsa_create(context, values):
|
|
"""
|
|
Creates Virtual Storage Array record.
|
|
"""
|
|
try:
|
|
vsa_ref = models.VirtualStorageArray()
|
|
vsa_ref.update(values)
|
|
vsa_ref.save()
|
|
except Exception, e:
|
|
raise exception.DBError(e)
|
|
return vsa_ref
|
|
|
|
|
|
@require_admin_context
|
|
def vsa_update(context, vsa_id, values):
|
|
"""
|
|
Updates Virtual Storage Array record.
|
|
"""
|
|
session = get_session()
|
|
with session.begin():
|
|
vsa_ref = vsa_get(context, vsa_id, session=session)
|
|
vsa_ref.update(values)
|
|
vsa_ref.save(session=session)
|
|
return vsa_ref
|
|
|
|
|
|
@require_admin_context
|
|
def vsa_destroy(context, vsa_id):
|
|
"""
|
|
Deletes Virtual Storage Array record.
|
|
"""
|
|
session = get_session()
|
|
with session.begin():
|
|
session.query(models.VirtualStorageArray).\
|
|
filter_by(id=vsa_id).\
|
|
update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
|
|
|
|
@require_context
|
|
def vsa_get(context, vsa_id, session=None):
|
|
"""
|
|
Get Virtual Storage Array record by ID.
|
|
"""
|
|
result = _vsa_get_query(context, session=session, project_only=True).\
|
|
filter_by(id=vsa_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.VirtualStorageArrayNotFound(id=vsa_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def vsa_get_all(context):
|
|
"""
|
|
Get all Virtual Storage Array records.
|
|
"""
|
|
return _vsa_get_query(context).all()
|
|
|
|
|
|
@require_context
|
|
def vsa_get_all_by_project(context, project_id):
|
|
"""
|
|
Get all Virtual Storage Array records by project ID.
|
|
"""
|
|
authorize_project_context(context, project_id)
|
|
return _vsa_get_query(context).filter_by(project_id=project_id).all()
|
|
|
|
|
|
####################
|
|
|
|
|
|
def s3_image_get(context, image_id):
|
|
"""Find local s3 image represented by the provided id"""
|
|
result = model_query(context, models.S3Image, read_deleted="yes").\
|
|
filter_by(id=image_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.ImageNotFound(image_id=image_id)
|
|
|
|
return result
|
|
|
|
|
|
def s3_image_get_by_uuid(context, image_uuid):
|
|
"""Find local s3 image represented by the provided uuid"""
|
|
result = model_query(context, models.S3Image, read_deleted="yes").\
|
|
filter_by(uuid=image_uuid).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.ImageNotFound(image_id=image_uuid)
|
|
|
|
return result
|
|
|
|
|
|
def s3_image_create(context, image_uuid):
|
|
"""Create local s3 image represented by provided uuid"""
|
|
try:
|
|
s3_image_ref = models.S3Image()
|
|
s3_image_ref.update({'uuid': image_uuid})
|
|
s3_image_ref.save()
|
|
except Exception, e:
|
|
raise exception.DBError(e)
|
|
|
|
return s3_image_ref
|
|
|
|
|
|
####################
|
|
|
|
|
|
@require_admin_context
|
|
def sm_backend_conf_create(context, values):
|
|
backend_conf = models.SMBackendConf()
|
|
backend_conf.update(values)
|
|
backend_conf.save()
|
|
return backend_conf
|
|
|
|
|
|
@require_admin_context
|
|
def sm_backend_conf_update(context, sm_backend_id, values):
|
|
backend_conf = model_query(context, models.SMBackendConf,
|
|
read_deleted="yes").\
|
|
filter_by(id=sm_backend_id).\
|
|
first()
|
|
|
|
if not backend_conf:
|
|
raise exception.NotFound(
|
|
_("No backend config with id %(sm_backend_id)s") % locals())
|
|
|
|
backend_conf.update(values)
|
|
backend_conf.save()
|
|
return backend_conf
|
|
|
|
|
|
@require_admin_context
|
|
def sm_backend_conf_delete(context, sm_backend_id):
|
|
# FIXME(sirp): for consistency, shouldn't this just mark as deleted with
|
|
# `purge` actually deleting the record?
|
|
session = get_session()
|
|
with session.begin():
|
|
model_query(context, models.SMBackendConf, session=session,
|
|
read_deleted="yes").\
|
|
filter_by(id=sm_backend_id).\
|
|
delete()
|
|
|
|
|
|
@require_admin_context
|
|
def sm_backend_conf_get(context, sm_backend_id):
|
|
result = model_query(context, models.SMBackendConf, read_deleted="yes").\
|
|
filter_by(id=sm_backend_id).\
|
|
first()
|
|
|
|
if not result:
|
|
raise exception.NotFound(_("No backend config with id "
|
|
"%(sm_backend_id)s") % locals())
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def sm_backend_conf_get_by_sr(context, sr_uuid):
|
|
session = get_session()
|
|
# FIXME(sirp): shouldn't this have a `first()` qualifier attached?
|
|
return model_query(context, models.SMBackendConf, read_deleted="yes").\
|
|
filter_by(sr_uuid=sr_uuid)
|
|
|
|
|
|
@require_admin_context
|
|
def sm_backend_conf_get_all(context):
|
|
return model_query(context, models.SMBackendConf, read_deleted="yes").\
|
|
all()
|
|
|
|
|
|
####################
|
|
|
|
|
|
def _sm_flavor_get_query(context, sm_flavor_label, session=None):
|
|
return model_query(context, models.SMFlavors, session=session,
|
|
read_deleted="yes").\
|
|
filter_by(label=sm_flavor_label)
|
|
|
|
|
|
@require_admin_context
|
|
def sm_flavor_create(context, values):
|
|
sm_flavor = models.SMFlavors()
|
|
sm_flavor.update(values)
|
|
sm_flavor.save()
|
|
return sm_flavor
|
|
|
|
|
|
@require_admin_context
|
|
def sm_flavor_update(context, sm_flavor_label, values):
|
|
sm_flavor = sm_flavor_get(context, sm_flavor_label)
|
|
sm_flavor.update(values)
|
|
sm_flavor.save()
|
|
return sm_flavor
|
|
|
|
|
|
@require_admin_context
|
|
def sm_flavor_delete(context, sm_flavor_label):
|
|
session = get_session()
|
|
with session.begin():
|
|
_sm_flavor_get_query(context, sm_flavor_label).delete()
|
|
|
|
|
|
@require_admin_context
|
|
def sm_flavor_get(context, sm_flavor_label):
|
|
result = _sm_flavor_get_query(context, sm_flavor_label).first()
|
|
|
|
if not result:
|
|
raise exception.NotFound(
|
|
_("No sm_flavor called %(sm_flavor)s") % locals())
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
def sm_flavor_get_all(context):
|
|
return model_query(context, models.SMFlavors, read_deleted="yes").all()
|
|
|
|
|
|
###############################
|
|
|
|
|
|
def _sm_volume_get_query(context, volume_id, session=None):
|
|
return model_query(context, models.SMVolume, session=session,
|
|
read_deleted="yes").\
|
|
filter_by(id=volume_id)
|
|
|
|
|
|
def sm_volume_create(context, values):
|
|
sm_volume = models.SMVolume()
|
|
sm_volume.update(values)
|
|
sm_volume.save()
|
|
return sm_volume
|
|
|
|
|
|
def sm_volume_update(context, volume_id, values):
|
|
sm_volume = sm_volume_get(context, volume_id)
|
|
sm_volume.update(values)
|
|
sm_volume.save()
|
|
return sm_volume
|
|
|
|
|
|
def sm_volume_delete(context, volume_id):
|
|
session = get_session()
|
|
with session.begin():
|
|
_sm_volume_get_query(context, volume_id, session=session).delete()
|
|
|
|
|
|
def sm_volume_get(context, volume_id):
|
|
result = _sm_volume_get_query(context, volume_id).first()
|
|
|
|
if not result:
|
|
raise exception.NotFound(
|
|
_("No sm_volume with id %(volume_id)s") % locals())
|
|
|
|
return result
|
|
|
|
|
|
def sm_volume_get_all(context):
|
|
return model_query(context, models.SMVolume, read_deleted="yes").all()
|
|
|
|
|
|
################
|
|
|
|
|
|
def _aggregate_get_query(context, model_class, id_field, id,
|
|
session=None, read_deleted='yes'):
|
|
return model_query(context, model_class, session=session,
|
|
read_deleted=read_deleted).filter(id_field == id)
|
|
|
|
|
|
@require_admin_context
|
|
def aggregate_create(context, values, metadata=None):
|
|
try:
|
|
aggregate = models.Aggregate()
|
|
aggregate.update(values)
|
|
aggregate.operational_state = aggregate_states.CREATED
|
|
aggregate.save()
|
|
except exception.DBError:
|
|
raise exception.AggregateNameExists(aggregate_name=values['name'])
|
|
if metadata:
|
|
aggregate_metadata_add(context, aggregate.id, metadata)
|
|
return aggregate
|
|
|
|
|
|
@require_admin_context
|
|
def aggregate_get(context, aggregate_id, read_deleted='no'):
|
|
aggregate = _aggregate_get_query(context,
|
|
models.Aggregate,
|
|
models.Aggregate.id, aggregate_id,
|
|
read_deleted=read_deleted).first()
|
|
|
|
if not aggregate:
|
|
raise exception.AggregateNotFound(aggregate_id=aggregate_id)
|
|
|
|
return aggregate
|
|
|
|
|
|
@require_admin_context
|
|
def aggregate_update(context, aggregate_id, values):
|
|
session = get_session()
|
|
aggregate = _aggregate_get_query(context,
|
|
models.Aggregate,
|
|
models.Aggregate.id, aggregate_id,
|
|
session=session,
|
|
read_deleted='no').first()
|
|
if aggregate:
|
|
metadata = values.get('metadata')
|
|
if metadata is not None:
|
|
aggregate_metadata_add(context,
|
|
aggregate_id,
|
|
values.pop('metadata'),
|
|
set_delete=True)
|
|
with session.begin():
|
|
aggregate.update(values)
|
|
aggregate.save(session=session)
|
|
values['metadata'] = metadata
|
|
return aggregate
|
|
else:
|
|
raise exception.AggregateNotFound(aggregate_id=aggregate_id)
|
|
|
|
|
|
@require_admin_context
|
|
def aggregate_delete(context, aggregate_id):
|
|
query = _aggregate_get_query(context,
|
|
models.Aggregate,
|
|
models.Aggregate.id, aggregate_id,
|
|
read_deleted='no')
|
|
if query.first():
|
|
query.update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
else:
|
|
raise exception.AggregateNotFound(aggregate_id=aggregate_id)
|
|
|
|
|
|
@require_admin_context
|
|
def aggregate_get_all(context, read_deleted='yes'):
|
|
return model_query(context,
|
|
models.Aggregate,
|
|
read_deleted=read_deleted).all()
|
|
|
|
|
|
@require_admin_context
|
|
@require_aggregate_exists
|
|
def aggregate_metadata_get(context, aggregate_id, read_deleted='no'):
|
|
rows = model_query(context,
|
|
models.AggregateMetadata,
|
|
read_deleted=read_deleted).\
|
|
filter_by(aggregate_id=aggregate_id).all()
|
|
|
|
return dict([(r['key'], r['value']) for r in rows])
|
|
|
|
|
|
@require_admin_context
|
|
@require_aggregate_exists
|
|
def aggregate_metadata_delete(context, aggregate_id, key):
|
|
query = _aggregate_get_query(context,
|
|
models.AggregateMetadata,
|
|
models.AggregateMetadata.aggregate_id,
|
|
aggregate_id, read_deleted='no').\
|
|
filter_by(key=key)
|
|
if query.first():
|
|
query.update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
else:
|
|
raise exception.AggregateMetadataNotFound(aggregate_id=aggregate_id,
|
|
metadata_key=key)
|
|
|
|
|
|
@require_admin_context
|
|
@require_aggregate_exists
|
|
def aggregate_metadata_get_item(context, aggregate_id, key,
|
|
session=None, read_deleted='yes'):
|
|
result = _aggregate_get_query(context,
|
|
models.AggregateMetadata,
|
|
models.AggregateMetadata.aggregate_id,
|
|
aggregate_id, session=session,
|
|
read_deleted=read_deleted).\
|
|
filter_by(key=key).first()
|
|
|
|
if not result:
|
|
raise exception.AggregateMetadataNotFound(metadata_key=key,
|
|
aggregate_id=aggregate_id)
|
|
|
|
return result
|
|
|
|
|
|
@require_admin_context
|
|
@require_aggregate_exists
|
|
def aggregate_metadata_add(context, aggregate_id, metadata, set_delete=False):
|
|
session = get_session()
|
|
|
|
if set_delete:
|
|
original_metadata = aggregate_metadata_get(context, aggregate_id)
|
|
for meta_key, meta_value in original_metadata.iteritems():
|
|
if meta_key not in metadata:
|
|
meta_ref = aggregate_metadata_get_item(context, aggregate_id,
|
|
meta_key, session)
|
|
meta_ref.update({'deleted': True})
|
|
meta_ref.save(session=session)
|
|
|
|
meta_ref = None
|
|
|
|
for meta_key, meta_value in metadata.iteritems():
|
|
item = {"value": meta_value}
|
|
try:
|
|
meta_ref = aggregate_metadata_get_item(context, aggregate_id,
|
|
meta_key, session)
|
|
if meta_ref.deleted:
|
|
item.update({'deleted': False, 'deleted_at': None,
|
|
'updated_at': literal_column('updated_at')})
|
|
except exception.AggregateMetadataNotFound:
|
|
meta_ref = models.AggregateMetadata()
|
|
item.update({"key": meta_key, "aggregate_id": aggregate_id})
|
|
|
|
meta_ref.update(item)
|
|
meta_ref.save(session=session)
|
|
|
|
return metadata
|
|
|
|
|
|
@require_admin_context
|
|
@require_aggregate_exists
|
|
def aggregate_host_get_all(context, aggregate_id, read_deleted='yes'):
|
|
rows = model_query(context,
|
|
models.AggregateHost,
|
|
read_deleted=read_deleted).\
|
|
filter_by(aggregate_id=aggregate_id).all()
|
|
|
|
return [r.host for r in rows]
|
|
|
|
|
|
@require_admin_context
|
|
@require_aggregate_exists
|
|
def aggregate_host_delete(context, aggregate_id, host):
|
|
query = _aggregate_get_query(context,
|
|
models.AggregateHost,
|
|
models.AggregateHost.aggregate_id,
|
|
aggregate_id,
|
|
read_deleted='no').filter_by(host=host)
|
|
if query.first():
|
|
query.update({'deleted': True,
|
|
'deleted_at': utils.utcnow(),
|
|
'updated_at': literal_column('updated_at')})
|
|
else:
|
|
raise exception.AggregateHostNotFound(aggregate_id=aggregate_id,
|
|
host=host)
|
|
|
|
|
|
@require_admin_context
|
|
@require_aggregate_exists
|
|
def aggregate_host_add(context, aggregate_id, host):
|
|
session = get_session()
|
|
host_ref = _aggregate_get_query(context,
|
|
models.AggregateHost,
|
|
models.AggregateHost.aggregate_id,
|
|
aggregate_id,
|
|
session=session,
|
|
read_deleted='yes').\
|
|
filter_by(host=host).first()
|
|
if not host_ref:
|
|
try:
|
|
host_ref = models.AggregateHost()
|
|
values = {"host": host, "aggregate_id": aggregate_id, }
|
|
host_ref.update(values)
|
|
host_ref.save(session=session)
|
|
except exception.DBError:
|
|
raise exception.AggregateHostConflict(host=host)
|
|
elif host_ref.deleted:
|
|
host_ref.update({'deleted': False,
|
|
'deleted_at': None,
|
|
'updated_at': literal_column('updated_at')})
|
|
host_ref.save(session=session)
|
|
else:
|
|
raise exception.AggregateHostExists(host=host,
|
|
aggregate_id=aggregate_id)
|
|
return host_ref
|
|
|
|
|
|
################
|
|
|
|
|
|
def instance_fault_create(context, values):
|
|
"""Create a new InstanceFault."""
|
|
fault_ref = models.InstanceFault()
|
|
fault_ref.update(values)
|
|
fault_ref.save()
|
|
return dict(fault_ref.iteritems())
|
|
|
|
|
|
def instance_fault_get_by_instance_uuids(context, instance_uuids):
|
|
"""Get all instance faults for the provided instance_uuids."""
|
|
rows = model_query(context, models.InstanceFault, read_deleted='no').\
|
|
filter(models.InstanceFault.instance_uuid.in_(
|
|
instance_uuids)).\
|
|
order_by(desc("created_at")).\
|
|
all()
|
|
|
|
output = {}
|
|
for instance_uuid in instance_uuids:
|
|
output[instance_uuid] = []
|
|
|
|
for row in rows:
|
|
data = dict(row.iteritems())
|
|
output[row['instance_uuid']].append(data)
|
|
|
|
return output
|