~ubuntu-branches/ubuntu/quantal/nova/quantal-proposed

« back to all changes in this revision

Viewing changes to nova/db/sqlalchemy/api.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-08-16 14:04:11 UTC
  • mto: This revision was merged to the branch mainline in revision 84.
  • Revision ID: package-import@ubuntu.com-20120816140411-0mr4n241wmk30t9l
Tags: upstream-2012.2~f3
ImportĀ upstreamĀ versionĀ 2012.2~f3

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
"""Implementation of SQLAlchemy backend."""
21
21
 
 
22
import collections
22
23
import copy
23
24
import datetime
24
25
import functools
25
 
import re
26
26
import warnings
27
27
 
28
28
from nova import block_device
29
 
from nova.compute import aggregate_states
30
29
from nova.compute import vm_states
31
30
from nova import db
32
31
from nova.db.sqlalchemy import models
44
43
from sqlalchemy.sql.expression import asc
45
44
from sqlalchemy.sql.expression import desc
46
45
from sqlalchemy.sql.expression import literal_column
47
 
from sqlalchemy.sql.expression import or_
48
46
from sqlalchemy.sql import func
49
47
 
50
48
FLAGS = flags.FLAGS
247
245
        # OK, filtering on this key; what value do we search for?
248
246
        value = filters.pop(key)
249
247
 
250
 
        if isinstance(value, (list, tuple, set, frozenset)):
 
248
        if key == 'metadata':
 
249
            column_attr = getattr(model, key)
 
250
            if isinstance(value, list):
 
251
                for item in value:
 
252
                    for k, v in item.iteritems():
 
253
                        query = query.filter(column_attr.any(key=k))
 
254
                        query = query.filter(column_attr.any(value=v))
 
255
 
 
256
            else:
 
257
                for k, v in value.iteritems():
 
258
                    query = query.filter(column_attr.any(key=k))
 
259
                    query = query.filter(column_attr.any(value=v))
 
260
        elif isinstance(value, (list, tuple, set, frozenset)):
251
261
            # Looking for values in a list; apply to query directly
252
262
            column_attr = getattr(model, key)
253
263
            query = query.filter(column_attr.in_(value))
283
293
        self.conditions = conditions
284
294
 
285
295
    def apply(self, model, query):
286
 
        clauses = []
287
296
        for key, condition in self.conditions.iteritems():
288
297
            for clause in condition.clauses(getattr(model, key)):
289
298
                query = query.filter(clause)
632
641
    return compute_node
633
642
 
634
643
 
 
644
def compute_node_statistics(context):
 
645
    """Compute statistics over all compute nodes."""
 
646
    result = model_query(context,
 
647
                         func.count(models.ComputeNode.id),
 
648
                         func.sum(models.ComputeNode.vcpus),
 
649
                         func.sum(models.ComputeNode.memory_mb),
 
650
                         func.sum(models.ComputeNode.local_gb),
 
651
                         func.sum(models.ComputeNode.vcpus_used),
 
652
                         func.sum(models.ComputeNode.memory_mb_used),
 
653
                         func.sum(models.ComputeNode.local_gb_used),
 
654
                         func.sum(models.ComputeNode.free_ram_mb),
 
655
                         func.sum(models.ComputeNode.free_disk_gb),
 
656
                         func.sum(models.ComputeNode.current_workload),
 
657
                         func.sum(models.ComputeNode.running_vms),
 
658
                         func.sum(models.ComputeNode.disk_available_least),
 
659
                         read_deleted="no").first()
 
660
 
 
661
    # Build a dict of the info--making no assumptions about result
 
662
    fields = ('count', 'vcpus', 'memory_mb', 'local_gb', 'vcpus_used',
 
663
              'memory_mb_used', 'local_gb_used', 'free_ram_mb', 'free_disk_gb',
 
664
              'current_workload', 'running_vms', 'disk_available_least')
 
665
    return dict((field, int(result[idx] or 0))
 
666
                for idx, field in enumerate(fields))
 
667
 
 
668
 
635
669
###################
636
670
 
637
671
 
695
729
 
696
730
@require_context
697
731
def floating_ip_get_pools(context):
698
 
    session = get_session()
699
732
    pools = []
700
 
    for result in session.query(models.FloatingIp.pool).distinct():
 
733
    for result in model_query(context, models.FloatingIp.pool).distinct():
701
734
        pools.append({'name': result[0]})
702
735
    return pools
703
736
 
724
757
 
725
758
 
726
759
@require_context
727
 
def floating_ip_create(context, values):
 
760
def floating_ip_bulk_create(context, ips):
 
761
    session = get_session()
 
762
    with session.begin():
 
763
        for ip in ips:
 
764
            floating_ip_create(context, ip, session)
 
765
 
 
766
 
 
767
@require_context
 
768
def floating_ip_create(context, values, session=None):
 
769
    if not session:
 
770
        session = get_session()
 
771
 
728
772
    floating_ip_ref = models.FloatingIp()
729
773
    floating_ip_ref.update(values)
730
 
    floating_ip_ref.save()
 
774
 
 
775
    # check uniqueness for not deleted addresses
 
776
    if not floating_ip_ref.deleted:
 
777
        try:
 
778
            floating_ip = floating_ip_get_by_address(context,
 
779
                                                     floating_ip_ref.address,
 
780
                                                     session)
 
781
        except exception.FloatingIpNotFoundForAddress:
 
782
            pass
 
783
        else:
 
784
            if floating_ip.id != floating_ip_ref.id:
 
785
                raise exception.FloatingIpExists(**dict(floating_ip_ref))
 
786
 
 
787
    floating_ip_ref.save(session=session)
731
788
    return floating_ip_ref['address']
732
789
 
733
790
 
958
1015
    session = get_session()
959
1016
    records = model_query(context, models.DNSDomain,
960
1017
                  session=session, read_deleted="no").\
961
 
                  with_lockmode('update').all()
 
1018
                  all()
962
1019
    domains = []
963
1020
    for record in records:
964
1021
        domains.append(record.domain)
970
1027
 
971
1028
 
972
1029
@require_admin_context
973
 
def fixed_ip_associate(context, address, instance_id, network_id=None,
 
1030
def fixed_ip_associate(context, address, instance_uuid, network_id=None,
974
1031
                       reserved=False):
975
1032
    """Keyword arguments:
976
1033
    reserved -- should be a boolean value(True or False), exact value will be
977
1034
    used to filter on the fixed ip address
978
1035
    """
 
1036
    if not utils.is_uuid_like(instance_uuid):
 
1037
        raise exception.InvalidUUID(uuid=instance_uuid)
 
1038
 
979
1039
    session = get_session()
980
1040
    with session.begin():
981
1041
        network_or_none = or_(models.FixedIp.network_id == network_id,
992
1052
        if fixed_ip_ref is None:
993
1053
            raise exception.FixedIpNotFoundForNetwork(address=address,
994
1054
                                            network_id=network_id)
995
 
        if fixed_ip_ref.instance_id:
 
1055
        if fixed_ip_ref.instance_uuid:
996
1056
            raise exception.FixedIpAlreadyInUse(address=address)
997
1057
 
998
1058
        if not fixed_ip_ref.network_id:
999
1059
            fixed_ip_ref.network_id = network_id
1000
 
        fixed_ip_ref.instance_id = instance_id
 
1060
        fixed_ip_ref.instance_uuid = instance_uuid
1001
1061
        session.add(fixed_ip_ref)
1002
1062
    return fixed_ip_ref['address']
1003
1063
 
1004
1064
 
1005
1065
@require_admin_context
1006
 
def fixed_ip_associate_pool(context, network_id, instance_id=None, host=None):
 
1066
def fixed_ip_associate_pool(context, network_id, instance_uuid=None,
 
1067
                            host=None):
 
1068
    if instance_uuid and not utils.is_uuid_like(instance_uuid):
 
1069
        raise exception.InvalidUUID(uuid=instance_uuid)
 
1070
 
1007
1071
    session = get_session()
1008
1072
    with session.begin():
1009
1073
        network_or_none = or_(models.FixedIp.network_id == network_id,
1012
1076
                                   read_deleted="no").\
1013
1077
                               filter(network_or_none).\
1014
1078
                               filter_by(reserved=False).\
1015
 
                               filter_by(instance_id=None).\
 
1079
                               filter_by(instance_uuid=None).\
1016
1080
                               filter_by(host=None).\
1017
1081
                               with_lockmode('update').\
1018
1082
                               first()
1024
1088
        if fixed_ip_ref['network_id'] is None:
1025
1089
            fixed_ip_ref['network'] = network_id
1026
1090
 
1027
 
        if instance_id:
1028
 
            fixed_ip_ref['instance_id'] = instance_id
 
1091
        if instance_uuid:
 
1092
            fixed_ip_ref['instance_uuid'] = instance_uuid
1029
1093
 
1030
1094
        if host:
1031
1095
            fixed_ip_ref['host'] = host
1058
1122
        fixed_ip_ref = fixed_ip_get_by_address(context,
1059
1123
                                               address,
1060
1124
                                               session=session)
1061
 
        fixed_ip_ref['instance_id'] = None
 
1125
        fixed_ip_ref['instance_uuid'] = None
1062
1126
        fixed_ip_ref.save(session=session)
1063
1127
 
1064
1128
 
1079
1143
                     join((models.Network,
1080
1144
                           models.Network.id == models.FixedIp.network_id)).\
1081
1145
                     join((models.Instance,
1082
 
                           models.Instance.id == models.FixedIp.instance_id)).\
 
1146
                           models.Instance.uuid == \
 
1147
                               models.FixedIp.instance_uuid)).\
1083
1148
                     filter(host_filter).\
1084
1149
                     all()
1085
1150
    fixed_ip_ids = [fip[0] for fip in result]
1087
1152
        return 0
1088
1153
    result = model_query(context, models.FixedIp, session=session).\
1089
1154
                     filter(models.FixedIp.id.in_(fixed_ip_ids)).\
1090
 
                     update({'instance_id': None,
 
1155
                     update({'instance_uuid': None,
1091
1156
                             'leased': False,
1092
1157
                             'updated_at': timeutils.utcnow()},
1093
1158
                             synchronize_session='fetch')
1104
1169
 
1105
1170
    # FIXME(sirp): shouldn't we just use project_only here to restrict the
1106
1171
    # results?
1107
 
    if is_user_context(context) and result['instance_id'] is not None:
1108
 
        instance = instance_get(context, result['instance_id'], session)
 
1172
    if is_user_context(context) and result['instance_uuid'] is not None:
 
1173
        instance = instance_get_by_uuid(context, result['instance_uuid'],
 
1174
                                        session)
1109
1175
        authorize_project_context(context, instance.project_id)
1110
1176
 
1111
1177
    return result
1132
1198
 
1133
1199
    # NOTE(sirp): shouldn't we just use project_only here to restrict the
1134
1200
    # results?
1135
 
    if is_user_context(context) and result['instance_id'] is not None:
1136
 
        instance = instance_get(context, result['instance_id'], session)
 
1201
    if is_user_context(context) and result['instance_uuid'] is not None:
 
1202
        instance = instance_get_by_uuid(context, result['instance_uuid'],
 
1203
                                        session)
1137
1204
        authorize_project_context(context, instance.project_id)
1138
1205
 
1139
1206
    return result
1140
1207
 
1141
1208
 
1142
1209
@require_context
1143
 
def fixed_ip_get_by_instance(context, instance_id):
 
1210
def fixed_ip_get_by_instance(context, instance_uuid):
 
1211
    if not utils.is_uuid_like(instance_uuid):
 
1212
        raise exception.InvalidUUID(uuid=instance_uuid)
 
1213
 
1144
1214
    result = model_query(context, models.FixedIp, read_deleted="no").\
1145
 
                 filter_by(instance_id=instance_id).\
 
1215
                 filter_by(instance_uuid=instance_uuid).\
1146
1216
                 all()
1147
1217
 
1148
1218
    if not result:
1149
 
        raise exception.FixedIpNotFoundForInstance(instance_id=instance_id)
 
1219
        raise exception.FixedIpNotFoundForInstance(instance_uuid=instance_uuid)
1150
1220
 
1151
1221
    return result
1152
1222
 
1252
1322
 
1253
1323
 
1254
1324
@require_context
1255
 
@require_instance_exists
1256
 
def virtual_interface_get_by_instance(context, instance_id):
 
1325
@require_instance_exists_using_uuid
 
1326
def virtual_interface_get_by_instance(context, instance_uuid):
1257
1327
    """Gets all virtual interfaces for instance.
1258
1328
 
1259
 
    :param instance_id: = id of the instance to retrieve vifs for
 
1329
    :param instance_uuid: = uuid of the instance to retrieve vifs for
1260
1330
    """
1261
1331
    vif_refs = _virtual_interface_query(context).\
1262
 
                       filter_by(instance_id=instance_id).\
 
1332
                       filter_by(instance_uuid=instance_uuid).\
1263
1333
                       all()
1264
1334
    return vif_refs
1265
1335
 
1266
1336
 
1267
1337
@require_context
1268
 
def virtual_interface_get_by_instance_and_network(context, instance_id,
1269
 
                                                           network_id):
 
1338
def virtual_interface_get_by_instance_and_network(context, instance_uuid,
 
1339
                                                  network_id):
1270
1340
    """Gets virtual interface for instance that's associated with network."""
1271
1341
    vif_ref = _virtual_interface_query(context).\
1272
 
                      filter_by(instance_id=instance_id).\
 
1342
                      filter_by(instance_uuid=instance_uuid).\
1273
1343
                      filter_by(network_id=network_id).\
1274
1344
                      first()
1275
1345
    return vif_ref
1288
1358
 
1289
1359
 
1290
1360
@require_context
1291
 
def virtual_interface_delete_by_instance(context, instance_id):
 
1361
def virtual_interface_delete_by_instance(context, instance_uuid):
1292
1362
    """Delete virtual interface records that are associated
1293
1363
    with the instance given by instance_id.
1294
1364
 
1295
 
    :param instance_id: = id of instance
 
1365
    :param instance_uuid: = uuid of instance
1296
1366
    """
1297
 
    vif_refs = virtual_interface_get_by_instance(context, instance_id)
 
1367
    vif_refs = virtual_interface_get_by_instance(context, instance_uuid)
1298
1368
    for vif_ref in vif_refs:
1299
1369
        virtual_interface_delete(context, vif_ref['id'])
1300
1370
 
1410
1480
                update({'deleted': True,
1411
1481
                        'deleted_at': timeutils.utcnow(),
1412
1482
                        'updated_at': literal_column('updated_at')})
1413
 
        session.query(models.InstanceMetadata).\
1414
 
                filter_by(instance_uuid=instance_ref['uuid']).\
1415
 
                update({'deleted': True,
1416
 
                        'deleted_at': timeutils.utcnow(),
1417
 
                        'updated_at': literal_column('updated_at')})
1418
 
        session.query(models.InstanceSystemMetadata).\
1419
 
                filter_by(instance_uuid=instance_ref['uuid']).\
1420
 
                update({'deleted': True,
1421
 
                        'deleted_at': timeutils.utcnow(),
1422
 
                        'updated_at': literal_column('updated_at')})
1423
 
        session.query(models.BlockDeviceMapping).\
1424
 
                filter_by(instance_uuid=instance_ref['uuid']).\
1425
 
                update({'deleted': True,
1426
 
                        'deleted_at': timeutils.utcnow(),
1427
 
                        'updated_at': literal_column('updated_at')})
1428
1483
 
1429
1484
        instance_info_cache_delete(context, instance_ref['uuid'],
1430
1485
                                   session=session)
1482
1537
    will be returned by default, unless there's a filter that says
1483
1538
    otherwise"""
1484
1539
 
1485
 
    def _regexp_filter_by_metadata(instance, meta):
1486
 
        inst_metadata = [{node['key']: node['value']}
1487
 
                         for node in instance['metadata']]
1488
 
        if isinstance(meta, list):
1489
 
            for node in meta:
1490
 
                if node not in inst_metadata:
1491
 
                    return False
1492
 
        elif isinstance(meta, dict):
1493
 
            for k, v in meta.iteritems():
1494
 
                if {k: v} not in inst_metadata:
1495
 
                    return False
1496
 
        return True
1497
 
 
1498
 
    def _regexp_filter_by_column(instance, filter_name, filter_re):
1499
 
        try:
1500
 
            v = getattr(instance, filter_name)
1501
 
        except AttributeError:
1502
 
            return True
1503
 
        if v and filter_re.match(str(v)):
1504
 
            return True
1505
 
        return False
1506
 
 
1507
1540
    sort_fn = {'desc': desc, 'asc': asc}
1508
1541
 
1509
1542
    session = get_session()
1545
1578
    # Filters for exact matches that we can do along with the SQL query...
1546
1579
    # For other filters that don't match this, we will do regexp matching
1547
1580
    exact_match_filter_names = ['project_id', 'user_id', 'image_ref',
1548
 
            'vm_state', 'instance_type_id', 'uuid']
 
1581
                                'vm_state', 'instance_type_id', 'uuid',
 
1582
                                'metadata']
1549
1583
 
1550
1584
    # Filter the query
1551
1585
    query_prefix = exact_filter(query_prefix, models.Instance,
1552
1586
                                filters, exact_match_filter_names)
1553
1587
 
 
1588
    query_prefix = regex_filter(query_prefix, models.Instance, filters)
1554
1589
    instances = query_prefix.all()
1555
 
    if not instances:
1556
 
        return []
1557
 
 
1558
 
    # Now filter on everything else for regexp matching..
1559
 
    # For filters not in the list, we'll attempt to use the filter_name
1560
 
    # as a column name in Instance..
1561
 
    regexp_filter_funcs = {}
1562
 
 
 
1590
    return instances
 
1591
 
 
1592
 
 
1593
def regex_filter(query, model, filters):
 
1594
    """Applies regular expression filtering to a query.
 
1595
 
 
1596
    Returns the updated query.
 
1597
 
 
1598
    :param query: query to apply filters to
 
1599
    :param model: model object the query applies to
 
1600
    :param filters: dictionary of filters with regex values
 
1601
    """
 
1602
 
 
1603
    regexp_op_map = {
 
1604
        'postgresql': '~',
 
1605
        'mysql': 'REGEXP',
 
1606
        'oracle': 'REGEXP_LIKE',
 
1607
        'sqlite': 'REGEXP'
 
1608
    }
 
1609
    db_string = FLAGS.sql_connection.split(':')[0].split('+')[0]
 
1610
    db_regexp_op = regexp_op_map.get(db_string, 'LIKE')
1563
1611
    for filter_name in filters.iterkeys():
1564
 
        filter_func = regexp_filter_funcs.get(filter_name, None)
1565
 
        filter_re = re.compile(str(filters[filter_name]))
1566
 
        if filter_func:
1567
 
            filter_l = lambda instance: filter_func(instance, filter_re)
1568
 
        elif filter_name == 'metadata':
1569
 
            filter_l = lambda instance: _regexp_filter_by_metadata(instance,
1570
 
                    filters[filter_name])
1571
 
        else:
1572
 
            filter_l = lambda instance: _regexp_filter_by_column(instance,
1573
 
                    filter_name, filter_re)
1574
 
        instances = filter(filter_l, instances)
1575
 
        if not instances:
1576
 
            break
1577
 
 
1578
 
    return instances
 
1612
        try:
 
1613
            column_attr = getattr(model, filter_name)
 
1614
        except AttributeError:
 
1615
            continue
 
1616
        if 'property' == type(column_attr).__name__:
 
1617
            continue
 
1618
        query = query.filter(column_attr.op(db_regexp_op)(
 
1619
                                    str(filters[filter_name])))
 
1620
    return query
1579
1621
 
1580
1622
 
1581
1623
@require_context
1582
 
def instance_get_active_by_window(context, begin, end=None, project_id=None):
 
1624
def instance_get_active_by_window(context, begin, end=None,
 
1625
                                  project_id=None, host=None):
1583
1626
    """Return instances that were active during window."""
1584
1627
    session = get_session()
1585
1628
    query = session.query(models.Instance)
1590
1633
        query = query.filter(models.Instance.launched_at < end)
1591
1634
    if project_id:
1592
1635
        query = query.filter_by(project_id=project_id)
 
1636
    if host:
 
1637
        query = query.filter_by(host=host)
1593
1638
 
1594
1639
    return query.all()
1595
1640
 
1596
1641
 
1597
1642
@require_admin_context
1598
1643
def instance_get_active_by_window_joined(context, begin, end=None,
1599
 
                                         project_id=None):
 
1644
                                         project_id=None, host=None):
1600
1645
    """Return instances and joins that were active during window."""
1601
1646
    session = get_session()
1602
1647
    query = session.query(models.Instance)
1611
1656
        query = query.filter(models.Instance.launched_at < end)
1612
1657
    if project_id:
1613
1658
        query = query.filter_by(project_id=project_id)
 
1659
    if host:
 
1660
        query = query.filter_by(host=host)
1614
1661
 
1615
1662
    return query.all()
1616
1663
 
1657
1704
#                go away
1658
1705
@require_context
1659
1706
def instance_get_floating_address(context, instance_id):
1660
 
    fixed_ips = fixed_ip_get_by_instance(context, instance_id)
 
1707
    instance = instance_get(context, instance_id)
 
1708
    fixed_ips = fixed_ip_get_by_instance(context, instance['uuid'])
 
1709
 
1661
1710
    if not fixed_ips:
1662
1711
        return None
 
1712
 
1663
1713
    # NOTE(tr3buchet): this only gets the first fixed_ip
1664
1714
    # won't find floating ips associated with other fixed_ips
1665
1715
    floating_ips = floating_ip_get_by_fixed_address(context,
1860
1910
    session = session or get_session()
1861
1911
    info_cache = instance_info_cache_get(context, instance_uuid,
1862
1912
                                         session=session)
1863
 
 
1864
1913
    if info_cache:
 
1914
        # NOTE(tr3buchet): let's leave it alone if it's already deleted
 
1915
        if info_cache['deleted']:
 
1916
            return info_cache
 
1917
 
1865
1918
        info_cache.update(values)
1866
1919
        info_cache.save(session=session)
1867
1920
    else:
1950
2003
 
1951
2004
 
1952
2005
@require_admin_context
1953
 
def network_associate(context, project_id, force=False):
 
2006
def network_associate(context, project_id, network_id=None, force=False):
1954
2007
    """Associate a project with a network.
1955
2008
 
1956
2009
    called by project_get_networks under certain conditions
1968
2021
    session = get_session()
1969
2022
    with session.begin():
1970
2023
 
1971
 
        def network_query(project_filter):
 
2024
        def network_query(project_filter, id=None):
 
2025
            filter_kwargs = {'project_id': project_filter}
 
2026
            if id is not None:
 
2027
                filter_kwargs['id'] = id
1972
2028
            return model_query(context, models.Network, session=session,
1973
2029
                              read_deleted="no").\
1974
 
                           filter_by(project_id=project_filter).\
 
2030
                           filter_by(**filter_kwargs).\
1975
2031
                           with_lockmode('update').\
1976
2032
                           first()
1977
2033
 
1984
2040
            # with a new network
1985
2041
 
1986
2042
            # get new network
1987
 
            network_ref = network_query(None)
 
2043
            network_ref = network_query(None, network_id)
1988
2044
            if not network_ref:
1989
2045
                raise db.NoMoreNetworks()
1990
2046
 
2133
2189
    vif_and = and_(models.VirtualInterface.id ==
2134
2190
                   models.FixedIp.virtual_interface_id,
2135
2191
                   models.VirtualInterface.deleted == False)
2136
 
    inst_and = and_(models.Instance.id == models.FixedIp.instance_id,
 
2192
    inst_and = and_(models.Instance.uuid == models.FixedIp.instance_uuid,
2137
2193
                    models.Instance.deleted == False)
2138
2194
    session = get_session()
2139
2195
    query = session.query(models.FixedIp.address,
2140
 
                          models.FixedIp.instance_id,
 
2196
                          models.FixedIp.instance_uuid,
2141
2197
                          models.FixedIp.network_id,
2142
2198
                          models.FixedIp.virtual_interface_id,
2143
2199
                          models.VirtualInterface.address,
2149
2205
                          filter(models.FixedIp.allocated == True).\
2150
2206
                          join((models.VirtualInterface, vif_and)).\
2151
2207
                          join((models.Instance, inst_and)).\
2152
 
                          filter(models.FixedIp.instance_id != None).\
 
2208
                          filter(models.FixedIp.instance_uuid != None).\
2153
2209
                          filter(models.FixedIp.virtual_interface_id != None)
2154
2210
    if host:
2155
2211
        query = query.filter(models.Instance.host == host)
2158
2214
    for datum in result:
2159
2215
        cleaned = {}
2160
2216
        cleaned['address'] = datum[0]
2161
 
        cleaned['instance_id'] = datum[1]
 
2217
        cleaned['instance_uuid'] = datum[1]
2162
2218
        cleaned['network_id'] = datum[2]
2163
2219
        cleaned['vif_id'] = datum[3]
2164
2220
        cleaned['vif_address'] = datum[4]
2306
2362
###################
2307
2363
 
2308
2364
 
2309
 
@require_admin_context
2310
 
def auth_token_destroy(context, token_id):
2311
 
    session = get_session()
2312
 
    with session.begin():
2313
 
        token_ref = auth_token_get(context, token_id, session=session)
2314
 
        token_ref.delete(session=session)
2315
 
 
2316
 
 
2317
 
@require_admin_context
2318
 
def auth_token_get(context, token_hash, session=None):
2319
 
    result = model_query(context, models.AuthToken, session=session).\
2320
 
                  filter_by(token_hash=token_hash).\
2321
 
                  first()
2322
 
 
2323
 
    if not result:
2324
 
        raise exception.AuthTokenNotFound(token=token_hash)
2325
 
 
2326
 
    return result
2327
 
 
2328
 
 
2329
 
@require_admin_context
2330
 
def auth_token_update(context, token_hash, values):
2331
 
    session = get_session()
2332
 
    with session.begin():
2333
 
        token_ref = auth_token_get(context, token_hash, session=session)
2334
 
        token_ref.update(values)
2335
 
        token_ref.save(session=session)
2336
 
 
2337
 
 
2338
 
@require_admin_context
2339
 
def auth_token_create(context, token):
2340
 
    tk = models.AuthToken()
2341
 
    tk.update(token)
2342
 
    tk.save()
2343
 
    return tk
2344
 
 
2345
 
 
2346
 
###################
2347
 
 
2348
 
 
2349
2365
@require_context
2350
2366
def quota_get(context, project_id, resource, session=None):
2351
2367
    result = model_query(context, models.Quota, session=session,
2510
2526
 
2511
2527
@require_admin_context
2512
2528
def quota_usage_create(context, project_id, resource, in_use, reserved,
2513
 
                       until_refresh, session=None, save=True):
 
2529
                       until_refresh, session=None):
2514
2530
    quota_usage_ref = models.QuotaUsage()
2515
2531
    quota_usage_ref.project_id = project_id
2516
2532
    quota_usage_ref.resource = resource
2517
2533
    quota_usage_ref.in_use = in_use
2518
2534
    quota_usage_ref.reserved = reserved
2519
2535
    quota_usage_ref.until_refresh = until_refresh
2520
 
 
2521
 
    # Allow us to hold the save operation until later; keeps the
2522
 
    # transaction in quota_reserve() from breaking too early
2523
 
    if save:
2524
 
        quota_usage_ref.save(session=session)
 
2536
    quota_usage_ref.save(session=session)
2525
2537
 
2526
2538
    return quota_usage_ref
2527
2539
 
2592
2604
                       expire, session=None):
2593
2605
    reservation_ref = models.Reservation()
2594
2606
    reservation_ref.uuid = uuid
2595
 
    reservation_ref.usage = usage
 
2607
    reservation_ref.usage_id = usage['id']
2596
2608
    reservation_ref.project_id = project_id
2597
2609
    reservation_ref.resource = resource
2598
2610
    reservation_ref.delta = delta
2612
2624
###################
2613
2625
 
2614
2626
 
2615
 
def _get_quota_usages(context, session, keys):
 
2627
# NOTE(johannes): The quota code uses SQL locking to ensure races don't
 
2628
# cause under or over counting of resources. To avoid deadlocks, this
 
2629
# code always acquires the lock on quota_usages before acquiring the lock
 
2630
# on reservations.
 
2631
 
 
2632
def _get_quota_usages(context, session):
2616
2633
    # Broken out for testability
2617
2634
    rows = model_query(context, models.QuotaUsage,
2618
2635
                       read_deleted="no",
2619
2636
                       session=session).\
2620
2637
                   filter_by(project_id=context.project_id).\
2621
 
                   filter(models.QuotaUsage.resource.in_(keys)).\
2622
2638
                   with_lockmode('update').\
2623
2639
                   all()
2624
2640
    return dict((row.resource, row) for row in rows)
2631
2647
    session = get_session()
2632
2648
    with session.begin():
2633
2649
        # Get the current usages
2634
 
        usages = _get_quota_usages(context, session, deltas.keys())
 
2650
        usages = _get_quota_usages(context, session)
2635
2651
 
2636
2652
        # Handle usage refresh
2637
2653
        work = set(deltas.keys())
2641
2657
            # Do we need to refresh the usage?
2642
2658
            refresh = False
2643
2659
            if resource not in usages:
2644
 
                # Note we're inhibiting save...
2645
2660
                usages[resource] = quota_usage_create(elevated,
2646
2661
                                                      context.project_id,
2647
2662
                                                      resource,
2648
2663
                                                      0, 0,
2649
2664
                                                      until_refresh or None,
2650
 
                                                      session=session,
2651
 
                                                      save=False)
 
2665
                                                      session=session)
2652
2666
                refresh = True
2653
2667
            elif usages[resource].in_use < 0:
2654
2668
                # Negative in_use count indicates a desync, so try to
2671
2685
                for res, in_use in updates.items():
2672
2686
                    # Make sure we have a destination for the usage!
2673
2687
                    if res not in usages:
2674
 
                        # Note we're inhibiting save...
2675
2688
                        usages[res] = quota_usage_create(elevated,
2676
2689
                                                         context.project_id,
2677
2690
                                                         res,
2678
2691
                                                         0, 0,
2679
2692
                                                         until_refresh or None,
2680
 
                                                         session=session,
2681
 
                                                         save=False)
 
2693
                                                         session=session)
2682
2694
 
2683
2695
                    # Update the usage
2684
2696
                    usages[res].in_use = in_use
2767
2779
    return model_query(context, models.Reservation,
2768
2780
                       read_deleted="no",
2769
2781
                       session=session).\
2770
 
                   options(joinedload('usage')).\
2771
2782
                   filter(models.Reservation.uuid.in_(reservations)).\
2772
2783
                   with_lockmode('update').\
2773
2784
                   all()
2777
2788
def reservation_commit(context, reservations):
2778
2789
    session = get_session()
2779
2790
    with session.begin():
 
2791
        usages = _get_quota_usages(context, session)
 
2792
 
2780
2793
        for reservation in _quota_reservations(session, context, reservations):
 
2794
            usage = usages[reservation.resource]
2781
2795
            if reservation.delta >= 0:
2782
 
                reservation.usage.reserved -= reservation.delta
2783
 
            reservation.usage.in_use += reservation.delta
 
2796
                usage.reserved -= reservation.delta
 
2797
            usage.in_use += reservation.delta
2784
2798
 
2785
 
            reservation.usage.save(session=session)
2786
2799
            reservation.delete(session=session)
2787
2800
 
 
2801
        for usage in usages.values():
 
2802
            usage.save(session=session)
 
2803
 
2788
2804
 
2789
2805
@require_context
2790
2806
def reservation_rollback(context, reservations):
2791
2807
    session = get_session()
2792
2808
    with session.begin():
 
2809
        usages = _get_quota_usages(context, session)
 
2810
 
2793
2811
        for reservation in _quota_reservations(session, context, reservations):
 
2812
            usage = usages[reservation.resource]
2794
2813
            if reservation.delta >= 0:
2795
 
                reservation.usage.reserved -= reservation.delta
2796
 
                reservation.usage.save(session=session)
 
2814
                usage.reserved -= reservation.delta
2797
2815
 
2798
2816
            reservation.delete(session=session)
2799
2817
 
 
2818
        for usage in usages.values():
 
2819
            usage.save(session=session)
 
2820
 
2800
2821
 
2801
2822
@require_admin_context
2802
2823
def quota_destroy_all_by_project(context, project_id):
3059
3080
                    first()
3060
3081
 
3061
3082
    if not result:
3062
 
        raise exception.VolumeNotFound(uuid=volume_id)
 
3083
        raise exception.VolumeNotFound(volume_id=volume_id)
3063
3084
 
3064
3085
    return result['id']
3065
3086
 
3071
3092
                    first()
3072
3093
 
3073
3094
    if not result:
3074
 
        raise exception.VolumeNotFound(ec2_id=ec2_id)
 
3095
        raise exception.VolumeNotFound(volume_id=ec2_id)
3075
3096
 
3076
3097
    return result['uuid']
3077
3098
 
3096
3117
                    first()
3097
3118
 
3098
3119
    if not result:
3099
 
        raise exception.SnapshotNotFound(uuid=snapshot_id)
 
3120
        raise exception.SnapshotNotFound(snapshot_id=snapshot_id)
3100
3121
 
3101
3122
    return result['id']
3102
3123
 
3108
3129
                    first()
3109
3130
 
3110
3131
    if not result:
3111
 
        raise exception.SnapshotNotFound(ec2_id=ec2_id)
 
3132
        raise exception.SnapshotNotFound(snapshot_id=ec2_id)
3112
3133
 
3113
3134
    return result['uuid']
3114
3135
 
3264
3285
 
3265
3286
 
3266
3287
def _block_device_mapping_get_query(context, session=None):
3267
 
    return model_query(context, models.BlockDeviceMapping, session=session,
3268
 
                       read_deleted="no")
 
3288
    return model_query(context, models.BlockDeviceMapping, session=session)
3269
3289
 
3270
3290
 
3271
3291
@require_context
3348
3368
                    'updated_at': literal_column('updated_at')})
3349
3369
 
3350
3370
 
 
3371
@require_context
 
3372
def block_device_mapping_destroy_by_instance_and_device(context, instance_uuid,
 
3373
                                                        device_name):
 
3374
    session = get_session()
 
3375
    with session.begin():
 
3376
        _block_device_mapping_get_query(context, session=session).\
 
3377
            filter_by(instance_uuid=instance_uuid).\
 
3378
            filter_by(device_name=device_name).\
 
3379
            update({'deleted': True,
 
3380
                    'deleted_at': timeutils.utcnow(),
 
3381
                    'updated_at': literal_column('updated_at')})
 
3382
 
 
3383
 
3351
3384
###################
3352
3385
 
3353
3386
def _security_group_get_query(context, session=None, read_deleted=None,
3553
3586
def security_group_rule_get_by_security_group(context, security_group_id,
3554
3587
                                              session=None):
3555
3588
    return _security_group_rule_get_query(context, session=session).\
3556
 
                         filter_by(parent_group_id=security_group_id).\
3557
 
                         options(joinedload_all('grantee_group.instances')).\
3558
 
                         all()
 
3589
            filter_by(parent_group_id=security_group_id).\
 
3590
            options(joinedload_all('grantee_group.instances.instance_type')).\
 
3591
            all()
3559
3592
 
3560
3593
 
3561
3594
@require_context
3624
3657
###################
3625
3658
 
3626
3659
 
3627
 
@require_admin_context
3628
 
def user_get(context, id, session=None):
3629
 
    result = model_query(context, models.User, session=session).\
3630
 
                     filter_by(id=id).\
3631
 
                     first()
3632
 
 
3633
 
    if not result:
3634
 
        raise exception.UserNotFound(user_id=id)
3635
 
 
3636
 
    return result
3637
 
 
3638
 
 
3639
 
@require_admin_context
3640
 
def user_get_by_access_key(context, access_key, session=None):
3641
 
    result = model_query(context, models.User, session=session).\
3642
 
                   filter_by(access_key=access_key).\
3643
 
                   first()
3644
 
 
3645
 
    if not result:
3646
 
        raise exception.AccessKeyNotFound(access_key=access_key)
3647
 
 
3648
 
    return result
3649
 
 
3650
 
 
3651
 
@require_admin_context
3652
 
def user_create(context, values):
3653
 
    user_ref = models.User()
3654
 
    user_ref.update(values)
3655
 
    user_ref.save()
3656
 
    return user_ref
3657
 
 
3658
 
 
3659
 
@require_admin_context
3660
 
def user_delete(context, id):
3661
 
    session = get_session()
3662
 
    with session.begin():
3663
 
        session.query(models.UserProjectAssociation).\
3664
 
                filter_by(user_id=id).\
3665
 
                delete()
3666
 
        session.query(models.UserRoleAssociation).\
3667
 
                filter_by(user_id=id).\
3668
 
                delete()
3669
 
        session.query(models.UserProjectRoleAssociation).\
3670
 
                filter_by(user_id=id).\
3671
 
                delete()
3672
 
        user_ref = user_get(context, id, session=session)
3673
 
        session.delete(user_ref)
3674
 
 
3675
 
 
3676
 
def user_get_all(context):
3677
 
    return model_query(context, models.User).all()
3678
 
 
3679
 
 
3680
 
def user_get_roles(context, user_id):
3681
 
    session = get_session()
3682
 
    with session.begin():
3683
 
        user_ref = user_get(context, user_id, session=session)
3684
 
        return [role.role for role in user_ref['roles']]
3685
 
 
3686
 
 
3687
 
def user_get_roles_for_project(context, user_id, project_id):
3688
 
    session = get_session()
3689
 
    with session.begin():
3690
 
        res = session.query(models.UserProjectRoleAssociation).\
3691
 
                   filter_by(user_id=user_id).\
3692
 
                   filter_by(project_id=project_id).\
3693
 
                   all()
3694
 
        return [association.role for association in res]
3695
 
 
3696
 
 
3697
 
def user_remove_project_role(context, user_id, project_id, role):
3698
 
    session = get_session()
3699
 
    with session.begin():
3700
 
        session.query(models.UserProjectRoleAssociation).\
3701
 
                filter_by(user_id=user_id).\
3702
 
                filter_by(project_id=project_id).\
3703
 
                filter_by(role=role).\
3704
 
                delete()
3705
 
 
3706
 
 
3707
 
def user_remove_role(context, user_id, role):
3708
 
    session = get_session()
3709
 
    with session.begin():
3710
 
        res = session.query(models.UserRoleAssociation).\
3711
 
                    filter_by(user_id=user_id).\
3712
 
                    filter_by(role=role).\
3713
 
                    all()
3714
 
        for role in res:
3715
 
            session.delete(role)
3716
 
 
3717
 
 
3718
 
def user_add_role(context, user_id, role):
3719
 
    session = get_session()
3720
 
    with session.begin():
3721
 
        user_ref = user_get(context, user_id, session=session)
3722
 
        models.UserRoleAssociation(user=user_ref, role=role).\
3723
 
               save(session=session)
3724
 
 
3725
 
 
3726
 
def user_add_project_role(context, user_id, project_id, role):
3727
 
    session = get_session()
3728
 
    with session.begin():
3729
 
        user_ref = user_get(context, user_id, session=session)
3730
 
        project_ref = project_get(context, project_id, session=session)
3731
 
        models.UserProjectRoleAssociation(user_id=user_ref['id'],
3732
 
                                          project_id=project_ref['id'],
3733
 
                                          role=role).save(session=session)
3734
 
 
3735
 
 
3736
 
def user_update(context, user_id, values):
3737
 
    session = get_session()
3738
 
    with session.begin():
3739
 
        user_ref = user_get(context, user_id, session=session)
3740
 
        user_ref.update(values)
3741
 
        user_ref.save(session=session)
3742
 
 
3743
 
 
3744
 
###################
3745
 
 
3746
 
 
3747
 
def project_create(context, values):
3748
 
    project_ref = models.Project()
3749
 
    project_ref.update(values)
3750
 
    project_ref.save()
3751
 
    return project_ref
3752
 
 
3753
 
 
3754
 
def project_add_member(context, project_id, user_id):
3755
 
    session = get_session()
3756
 
    with session.begin():
3757
 
        project_ref = project_get(context, project_id, session=session)
3758
 
        user_ref = user_get(context, user_id, session=session)
3759
 
 
3760
 
        project_ref.members += [user_ref]
3761
 
        project_ref.save(session=session)
3762
 
 
3763
 
 
3764
 
def project_get(context, id, session=None):
3765
 
    result = model_query(context, models.Project, session=session,
3766
 
                         read_deleted="no").\
3767
 
                     filter_by(id=id).\
3768
 
                     options(joinedload_all('members')).\
3769
 
                     first()
3770
 
 
3771
 
    if not result:
3772
 
        raise exception.ProjectNotFound(project_id=id)
3773
 
 
3774
 
    return result
3775
 
 
3776
 
 
3777
 
def project_get_all(context):
3778
 
    return model_query(context, models.Project).\
3779
 
                   options(joinedload_all('members')).\
3780
 
                   all()
3781
 
 
3782
 
 
3783
 
def project_get_by_user(context, user_id):
3784
 
    user = model_query(context, models.User).\
3785
 
                   filter_by(id=user_id).\
3786
 
                   options(joinedload_all('projects')).\
3787
 
                   first()
3788
 
 
3789
 
    if not user:
3790
 
        raise exception.UserNotFound(user_id=user_id)
3791
 
 
3792
 
    return user.projects
3793
 
 
3794
 
 
3795
 
def project_remove_member(context, project_id, user_id):
3796
 
    session = get_session()
3797
 
    project = project_get(context, project_id, session=session)
3798
 
    user = user_get(context, user_id, session=session)
3799
 
 
3800
 
    if user in project.members:
3801
 
        project.members.remove(user)
3802
 
        project.save(session=session)
3803
 
 
3804
 
 
3805
 
def project_update(context, project_id, values):
3806
 
    session = get_session()
3807
 
    with session.begin():
3808
 
        project_ref = project_get(context, project_id, session=session)
3809
 
        project_ref.update(values)
3810
 
        project_ref.save(session=session)
3811
 
 
3812
 
 
3813
 
def project_delete(context, id):
3814
 
    session = get_session()
3815
 
    with session.begin():
3816
 
        session.query(models.UserProjectAssociation).\
3817
 
                filter_by(project_id=id).\
3818
 
                delete()
3819
 
        session.query(models.UserProjectRoleAssociation).\
3820
 
                filter_by(project_id=id).\
3821
 
                delete()
3822
 
        project_ref = project_get(context, id, session=session)
3823
 
        session.delete(project_ref)
3824
 
 
3825
 
 
3826
3660
@require_context
3827
3661
def project_get_networks(context, project_id, associate=True):
3828
3662
    # NOTE(tr3buchet): as before this function will associate
3890
3724
 
3891
3725
 
3892
3726
@require_admin_context
3893
 
def migration_get_all_unconfirmed(context, confirm_window, session=None):
 
3727
def migration_get_unconfirmed_by_dest_compute(context, confirm_window,
 
3728
        dest_compute, session=None):
3894
3729
    confirm_window = (timeutils.utcnow() -
3895
3730
                      datetime.timedelta(seconds=confirm_window))
3896
3731
 
3898
3733
                       read_deleted="yes").\
3899
3734
            filter(models.Migration.updated_at <= confirm_window).\
3900
3735
            filter_by(status="finished").\
 
3736
            filter_by(dest_compute=dest_compute).\
3901
3737
            all()
3902
3738
 
3903
3739
 
4161
3997
 
4162
3998
 
4163
3999
@require_context
4164
 
@require_instance_exists_using_uuid
4165
4000
def instance_metadata_get(context, instance_uuid):
4166
4001
    rows = _instance_metadata_get_query(context, instance_uuid).all()
4167
4002
 
4173
4008
 
4174
4009
 
4175
4010
@require_context
4176
 
@require_instance_exists_using_uuid
4177
4011
def instance_metadata_delete(context, instance_uuid, key):
4178
4012
    _instance_metadata_get_query(context, instance_uuid).\
4179
4013
        filter_by(key=key).\
4183
4017
 
4184
4018
 
4185
4019
@require_context
4186
 
@require_instance_exists_using_uuid
4187
4020
def instance_metadata_get_item(context, instance_uuid, key, session=None):
4188
4021
    result = _instance_metadata_get_query(
4189
4022
                            context, instance_uuid, session=session).\
4198
4031
 
4199
4032
 
4200
4033
@require_context
4201
 
@require_instance_exists_using_uuid
4202
4034
def instance_metadata_update(context, instance_uuid, metadata, delete):
4203
4035
    session = get_session()
4204
4036
 
4243
4075
 
4244
4076
 
4245
4077
@require_context
4246
 
@require_instance_exists_using_uuid
4247
4078
def instance_system_metadata_get(context, instance_uuid):
4248
4079
    rows = _instance_system_metadata_get_query(context, instance_uuid).all()
4249
4080
 
4255
4086
 
4256
4087
 
4257
4088
@require_context
4258
 
@require_instance_exists_using_uuid
4259
4089
def instance_system_metadata_delete(context, instance_uuid, key):
4260
4090
    _instance_system_metadata_get_query(context, instance_uuid).\
4261
4091
        filter_by(key=key).\
4279
4109
 
4280
4110
 
4281
4111
@require_context
4282
 
@require_instance_exists_using_uuid
4283
4112
def instance_system_metadata_update(context, instance_uuid, metadata, delete):
4284
4113
    session = get_session()
4285
4114
 
4379
4208
 
4380
4209
 
4381
4210
@require_context
4382
 
def bw_usage_update(context,
4383
 
                    uuid,
4384
 
                    mac,
4385
 
                    start_period,
4386
 
                    bw_in, bw_out,
4387
 
                    session=None):
 
4211
def bw_usage_update(context, uuid, mac, start_period, bw_in, bw_out,
 
4212
                    last_refreshed=None, session=None):
4388
4213
    if not session:
4389
4214
        session = get_session()
4390
4215
 
 
4216
    if last_refreshed is None:
 
4217
        last_refreshed = timeutils.utcnow()
 
4218
 
 
4219
    # NOTE(comstud): More often than not, we'll be updating records vs
 
4220
    # creating records.  Optimize accordingly, trying to update existing
 
4221
    # records.  Fall back to creation when no rows are updated.
4391
4222
    with session.begin():
4392
 
        bwusage = model_query(context, models.BandwidthUsage,
 
4223
        values = {'last_refreshed': last_refreshed,
 
4224
                  'bw_in': bw_in,
 
4225
                  'bw_out': bw_out}
 
4226
        rows = model_query(context, models.BandwidthUsage,
4393
4227
                              session=session, read_deleted="yes").\
4394
4228
                      filter_by(start_period=start_period).\
4395
4229
                      filter_by(uuid=uuid).\
4396
 
                      first()
4397
 
 
4398
 
        if not bwusage:
4399
 
            bwusage = models.BandwidthUsage()
4400
 
            bwusage.start_period = start_period
4401
 
            bwusage.uuid = uuid
4402
 
            bwusage.mac = mac
4403
 
 
4404
 
        bwusage.last_refreshed = timeutils.utcnow()
 
4230
                      filter_by(mac=mac).\
 
4231
                      update(values, synchronize_session=False)
 
4232
        if rows:
 
4233
            return
 
4234
 
 
4235
        bwusage = models.BandwidthUsage()
 
4236
        bwusage.start_period = start_period
 
4237
        bwusage.uuid = uuid
 
4238
        bwusage.mac = mac
 
4239
        bwusage.last_refreshed = last_refreshed
4405
4240
        bwusage.bw_in = bw_in
4406
4241
        bwusage.bw_out = bw_out
4407
4242
        bwusage.save(session=session)
4410
4245
####################
4411
4246
 
4412
4247
 
4413
 
def _instance_type_extra_specs_get_query(context, instance_type_id,
 
4248
def _instance_type_extra_specs_get_query(context, flavor_id,
4414
4249
                                         session=None):
 
4250
    # Two queries necessary because join with update doesn't work.
 
4251
    t = model_query(context, models.InstanceTypes.id,
 
4252
                    session=session, read_deleted="no").\
 
4253
              filter(models.InstanceTypes.flavorid == flavor_id).\
 
4254
              subquery()
4415
4255
    return model_query(context, models.InstanceTypeExtraSpecs,
4416
4256
                       session=session, read_deleted="no").\
4417
 
                    filter_by(instance_type_id=instance_type_id)
 
4257
                       filter(models.InstanceTypeExtraSpecs.\
 
4258
                              instance_type_id.in_(t))
4418
4259
 
4419
4260
 
4420
4261
@require_context
4421
 
def instance_type_extra_specs_get(context, instance_type_id):
 
4262
def instance_type_extra_specs_get(context, flavor_id):
4422
4263
    rows = _instance_type_extra_specs_get_query(
4423
 
                            context, instance_type_id).\
 
4264
                            context, flavor_id).\
4424
4265
                    all()
4425
4266
 
4426
4267
    result = {}
4431
4272
 
4432
4273
 
4433
4274
@require_context
4434
 
def instance_type_extra_specs_delete(context, instance_type_id, key):
 
4275
def instance_type_extra_specs_delete(context, flavor_id, key):
 
4276
    # Don't need synchronize the session since we will not use the query result
4435
4277
    _instance_type_extra_specs_get_query(
4436
 
                            context, instance_type_id).\
4437
 
        filter_by(key=key).\
 
4278
                            context, flavor_id).\
 
4279
        filter(models.InstanceTypeExtraSpecs.key == key).\
4438
4280
        update({'deleted': True,
4439
4281
                'deleted_at': timeutils.utcnow(),
4440
 
                'updated_at': literal_column('updated_at')})
 
4282
                'updated_at': literal_column('updated_at')},
 
4283
                synchronize_session=False)
4441
4284
 
4442
4285
 
4443
4286
@require_context
4444
 
def instance_type_extra_specs_get_item(context, instance_type_id, key,
 
4287
def instance_type_extra_specs_get_item(context, flavor_id, key,
4445
4288
                                       session=None):
4446
4289
    result = _instance_type_extra_specs_get_query(
4447
 
                            context, instance_type_id, session=session).\
4448
 
                    filter_by(key=key).\
 
4290
                            context, flavor_id, session=session).\
 
4291
                    filter(models.InstanceTypeExtraSpecs.key == key).\
4449
4292
                    first()
4450
 
 
4451
4293
    if not result:
4452
4294
        raise exception.InstanceTypeExtraSpecsNotFound(
4453
 
                extra_specs_key=key, instance_type_id=instance_type_id)
 
4295
                extra_specs_key=key, instance_type_id=flavor_id)
4454
4296
 
4455
4297
    return result
4456
4298
 
4457
4299
 
4458
4300
@require_context
4459
 
def instance_type_extra_specs_update_or_create(context, instance_type_id,
 
4301
def instance_type_extra_specs_update_or_create(context, flavor_id,
4460
4302
                                               specs):
4461
4303
    session = get_session()
4462
4304
    spec_ref = None
 
4305
    instance_type = instance_type_get_by_flavor_id(context, flavor_id)
4463
4306
    for key, value in specs.iteritems():
4464
4307
        try:
4465
4308
            spec_ref = instance_type_extra_specs_get_item(
4466
 
                context, instance_type_id, key, session)
 
4309
                context, flavor_id, key, session)
4467
4310
        except exception.InstanceTypeExtraSpecsNotFound, e:
4468
4311
            spec_ref = models.InstanceTypeExtraSpecs()
4469
4312
        spec_ref.update({"key": key, "value": value,
4470
 
                         "instance_type_id": instance_type_id,
4471
 
                         "deleted": 0})
 
4313
                         "instance_type_id": instance_type["id"],
 
4314
                         "deleted": False})
4472
4315
        spec_ref.save(session=session)
4473
4316
    return specs
4474
4317
 
4492
4335
        except exception.VolumeTypeNotFoundByName:
4493
4336
            pass
4494
4337
        try:
4495
 
            specs = values.get('extra_specs')
4496
 
 
4497
4338
            values['extra_specs'] = _metadata_refs(values.get('extra_specs'),
4498
4339
                                                   models.VolumeTypeExtraSpecs)
4499
4340
            volume_type_ref = models.VolumeTypes()
4649
4490
            spec_ref = models.VolumeTypeExtraSpecs()
4650
4491
        spec_ref.update({"key": key, "value": value,
4651
4492
                         "volume_type_id": volume_type_id,
4652
 
                         "deleted": 0})
 
4493
                         "deleted": False})
4653
4494
        spec_ref.save(session=session)
4654
4495
    return specs
4655
4496
 
4762
4603
 
4763
4604
@require_admin_context
4764
4605
def sm_backend_conf_get_by_sr(context, sr_uuid):
4765
 
    session = get_session()
4766
4606
    result = model_query(context, models.SMBackendConf, read_deleted="yes").\
4767
4607
                         filter_by(sr_uuid=sr_uuid).\
4768
4608
                         first()
4917
4757
                                     values['name'],
4918
4758
                                     session=session,
4919
4759
                                     read_deleted='yes').first()
4920
 
    values.setdefault('operational_state', aggregate_states.CREATED)
4921
4760
    if not aggregate:
4922
4761
        aggregate = models.Aggregate()
4923
4762
        aggregate.update(values)
4948
4787
 
4949
4788
 
4950
4789
@require_admin_context
4951
 
def aggregate_get_by_host(context, host):
4952
 
    aggregate_host = _aggregate_get_query(context,
4953
 
                                          models.AggregateHost,
4954
 
                                          models.AggregateHost.host,
4955
 
                                          host).first()
4956
 
 
4957
 
    if not aggregate_host:
4958
 
        raise exception.AggregateHostNotFound(host=host)
4959
 
 
4960
 
    return aggregate_get(context, aggregate_host.aggregate_id)
 
4790
def aggregate_get_by_host(context, host, key=None):
 
4791
    query = model_query(context, models.Aggregate).join(
 
4792
            "_hosts").filter(models.AggregateHost.host == host)
 
4793
 
 
4794
    if key:
 
4795
        query = query.join("_metadata").filter(
 
4796
        models.AggregateMetadata.key == key)
 
4797
    return query.all()
 
4798
 
 
4799
 
 
4800
@require_admin_context
 
4801
def aggregate_metadata_get_by_host(context, host, key=None):
 
4802
    query = model_query(context, models.Aggregate).join(
 
4803
            "_hosts").filter(models.AggregateHost.host == host).join(
 
4804
            "_metadata")
 
4805
 
 
4806
    if key:
 
4807
        query = query.filter(models.AggregateMetadata.key == key)
 
4808
    rows = query.all()
 
4809
    metadata = collections.defaultdict(set)
 
4810
    for agg in rows:
 
4811
        for kv in agg._metadata:
 
4812
            metadata[kv['key']].add(kv['value'])
 
4813
    return metadata
4961
4814
 
4962
4815
 
4963
4816
@require_admin_context
4993
4846
    if query.first():
4994
4847
        query.update({'deleted': True,
4995
4848
                      'deleted_at': timeutils.utcnow(),
4996
 
                      'operational_state': aggregate_states.DISMISSED,
4997
4849
                      'updated_at': literal_column('updated_at')})
4998
4850
    else:
4999
4851
        raise exception.AggregateNotFound(aggregate_id=aggregate_id)
5119
4971
                                    read_deleted='yes').\
5120
4972
                                    filter_by(host=host).first()
5121
4973
    if not host_ref:
5122
 
        try:
5123
 
            host_ref = models.AggregateHost()
5124
 
            values = {"host": host, "aggregate_id": aggregate_id, }
5125
 
            host_ref.update(values)
5126
 
            host_ref.save(session=session)
5127
 
        except exception.DBError:
5128
 
            raise exception.AggregateHostConflict(host=host)
 
4974
        host_ref = models.AggregateHost()
 
4975
        values = {"host": host, "aggregate_id": aggregate_id, }
 
4976
        host_ref.update(values)
 
4977
        host_ref.save(session=session)
5129
4978
    elif host_ref.deleted:
5130
4979
        host_ref.update({'deleted': False, 'deleted_at': None})
5131
4980
        host_ref.save(session=session)
5189
5038
                    first()
5190
5039
 
5191
5040
    if not result:
5192
 
        raise exception.InstanceNotFound(uuid=instance_id)
 
5041
        raise exception.InstanceNotFound(instance_id=instance_id)
5193
5042
 
5194
5043
    return result['id']
5195
5044
 
5196
5045
 
5197
5046
@require_context
5198
 
def get_instance_uuid_by_ec2_id(context, instance_id, session=None):
 
5047
def get_instance_uuid_by_ec2_id(context, ec2_id, session=None):
5199
5048
    result = _ec2_instance_get_query(context,
5200
5049
                                     session=session).\
5201
 
                    filter_by(id=instance_id).\
 
5050
                    filter_by(id=ec2_id).\
5202
5051
                    first()
5203
5052
 
5204
5053
    if not result:
5205
 
        raise exception.InstanceNotFound(id=instance_id)
 
5054
        raise exception.InstanceNotFound(instance_id=ec2_id)
5206
5055
 
5207
5056
    return result['uuid']
5208
5057
 
5210
5059
@require_context
5211
5060
def _ec2_instance_get_query(context, session=None):
5212
5061
    return model_query(context, models.InstanceIdMapping, session=session)
 
5062
 
 
5063
 
 
5064
@require_admin_context
 
5065
def task_log_get(context, task_name, period_beginning,
 
5066
                 period_ending, host, state=None, session=None):
 
5067
    query = model_query(context, models.TaskLog, session=session).\
 
5068
                     filter_by(task_name=task_name).\
 
5069
                     filter_by(period_beginning=period_beginning).\
 
5070
                     filter_by(period_ending=period_ending).\
 
5071
                     filter_by(host=host)
 
5072
    if state is not None:
 
5073
        query = query.filter_by(state=state)
 
5074
 
 
5075
    return query.first()
 
5076
 
 
5077
 
 
5078
@require_admin_context
 
5079
def task_log_get_all(context, task_name, period_beginning,
 
5080
                 period_ending, host=None, state=None, session=None):
 
5081
    query = model_query(context, models.TaskLog, session=session).\
 
5082
                     filter_by(task_name=task_name).\
 
5083
                     filter_by(period_beginning=period_beginning).\
 
5084
                     filter_by(period_ending=period_ending)
 
5085
    if host is not None:
 
5086
        query = query.filter_by(host=host)
 
5087
    if state is not None:
 
5088
        query = query.filter_by(state=state)
 
5089
    return query.all()
 
5090
 
 
5091
 
 
5092
@require_admin_context
 
5093
def task_log_begin_task(context, task_name,
 
5094
                        period_beginning,
 
5095
                        period_ending,
 
5096
                        host,
 
5097
                        task_items=None,
 
5098
                        message=None,
 
5099
                        session=None):
 
5100
    session = session or get_session()
 
5101
    with session.begin():
 
5102
        task = task_log_get(context, task_name,
 
5103
                            period_beginning,
 
5104
                            period_ending,
 
5105
                            host,
 
5106
                            session=session)
 
5107
        if task:
 
5108
            #It's already run(ning)!
 
5109
            raise exception.TaskAlreadyRunning(task_name=task_name, host=host)
 
5110
        task = models.TaskLog()
 
5111
        task.task_name = task_name
 
5112
        task.period_beginning = period_beginning
 
5113
        task.period_ending = period_ending
 
5114
        task.host = host
 
5115
        task.state = "RUNNING"
 
5116
        if message:
 
5117
            task.message = message
 
5118
        if task_items:
 
5119
            task.task_items = task_items
 
5120
        task.save(session=session)
 
5121
    return task
 
5122
 
 
5123
 
 
5124
@require_admin_context
 
5125
def task_log_end_task(context, task_name,
 
5126
                        period_beginning,
 
5127
                        period_ending,
 
5128
                        host,
 
5129
                        errors,
 
5130
                        message=None,
 
5131
                        session=None):
 
5132
    session = session or get_session()
 
5133
    with session.begin():
 
5134
        task = task_log_get(context, task_name,
 
5135
                            period_beginning,
 
5136
                            period_ending,
 
5137
                            host,
 
5138
                            session=session)
 
5139
        if not task:
 
5140
            #It's not running!
 
5141
            raise exception.TaskNotRunning(task_name=task_name, host=host)
 
5142
        task.state = "DONE"
 
5143
        if message:
 
5144
            task.message = message
 
5145
        task.errors = errors
 
5146
        task.save(session=session)
 
5147
    return task