scheduler for hosting device
Change-Id: Id19ca7a8fa7e81ae3699ed9d2668e7cc5e5726a2
This commit is contained in:
parent
cc37eea591
commit
d23b6ce94f
130
tacker/vm/hosting_device_scheduler.py
Normal file
130
tacker/vm/hosting_device_scheduler.py
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
#
|
||||||
|
# Copyright 2013, 2014 Intel Corporation.
|
||||||
|
# Copyright 2013, 2014 Isaku Yamahata <isaku.yamahata at intel com>
|
||||||
|
# <isaku.yamahata at gmail com>
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# @author: Isaku Yamahata, Intel Corporation.
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
from tacker.db.vm import vm_db
|
||||||
|
from tacker.openstack.common import log as logging
|
||||||
|
from tacker.plugins.common import constants
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ChanceScheduler(object):
|
||||||
|
|
||||||
|
"""Select a Device that can serve a service in a random way."""
|
||||||
|
|
||||||
|
def schedule(self, plugin, context,
|
||||||
|
service_type, service_instance_id, name, service_context):
|
||||||
|
"""
|
||||||
|
:param service_context: list of DeviceServiceContext
|
||||||
|
without service_instance_id
|
||||||
|
[{'network_id': network_id,
|
||||||
|
'subnet_id': subnet_id,
|
||||||
|
'port_id': port_id,
|
||||||
|
'router_id': router_id,
|
||||||
|
'role': role,
|
||||||
|
'index': index},
|
||||||
|
... ]
|
||||||
|
They can be missing or None = don't care
|
||||||
|
"""
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
# Race. prevent from inserting ServiceDeviceBinding
|
||||||
|
|
||||||
|
# select hosting device that is capable of service_type, but
|
||||||
|
# not yet used for it.
|
||||||
|
# i.e.
|
||||||
|
# device.service_type in
|
||||||
|
# [st.service_types for st in
|
||||||
|
# device.template.service_types]
|
||||||
|
# and
|
||||||
|
# device.sevice_type not in
|
||||||
|
# [ls.service_type for ls in device.services]
|
||||||
|
query = (
|
||||||
|
context.session.query(vm_db.Device).
|
||||||
|
filter(vm_db.Device.status == constants.ACTIVE).
|
||||||
|
filter(
|
||||||
|
sa.exists().
|
||||||
|
where(sa.and_(
|
||||||
|
vm_db.Device.template_id == vm_db.DeviceTemplate.id,
|
||||||
|
vm_db.DeviceTemplate.id ==
|
||||||
|
vm_db.ServiceType.template_id,
|
||||||
|
vm_db.ServiceType.service_type == service_type))).
|
||||||
|
filter(
|
||||||
|
~sa.exists().
|
||||||
|
where(sa.and_(
|
||||||
|
vm_db.Device.id ==
|
||||||
|
vm_db.ServiceDeviceBinding.device_id,
|
||||||
|
vm_db.ServiceDeviceBinding.service_instance_id ==
|
||||||
|
vm_db.ServiceInstance.id,
|
||||||
|
vm_db.ServiceInstance.service_type_id ==
|
||||||
|
vm_db.ServiceType.id,
|
||||||
|
vm_db.ServiceType.service_type == service_type))))
|
||||||
|
|
||||||
|
for sc_entry in service_context:
|
||||||
|
network_id = sc_entry.get('network_id')
|
||||||
|
subnet_id = sc_entry.get('subnet_id')
|
||||||
|
port_id = sc_entry.get('port_id')
|
||||||
|
router_id = sc_entry.get('router_id')
|
||||||
|
role = sc_entry.get('role')
|
||||||
|
index = sc_entry.get('index')
|
||||||
|
|
||||||
|
expr = [
|
||||||
|
vm_db.Device.id == vm_db.DeviceServiceContext.device_id]
|
||||||
|
if network_id is not None:
|
||||||
|
expr.append(
|
||||||
|
vm_db.DeviceServiceContext.network_id == network_id)
|
||||||
|
if subnet_id is not None:
|
||||||
|
expr.append(
|
||||||
|
vm_db.DeviceServiceContext.subnet_id == subnet_id)
|
||||||
|
if port_id is not None:
|
||||||
|
expr.append(vm_db.DeviceServiceContext.port_id == port_id)
|
||||||
|
if router_id is not None:
|
||||||
|
expr.append(
|
||||||
|
vm_db.DeviceServiceContext.router_id == router_id)
|
||||||
|
if role is not None:
|
||||||
|
expr.append(vm_db.DeviceServiceContext.role == role)
|
||||||
|
if index is not None:
|
||||||
|
expr.append(vm_db.DeviceServiceContext.index == index)
|
||||||
|
query = query.filter(sa.exists().where(sa.and_(*expr)))
|
||||||
|
|
||||||
|
candidates = query.with_lockmode("update").all()
|
||||||
|
if not candidates:
|
||||||
|
LOG.debug(_('no hosting device supporing %s'), service_type)
|
||||||
|
return
|
||||||
|
device = random.choice(candidates)
|
||||||
|
|
||||||
|
service_type_id = [s.id for s in device.template.service_types
|
||||||
|
if s.service_type == service_type][0]
|
||||||
|
|
||||||
|
service_instance_param = {
|
||||||
|
'name': name,
|
||||||
|
'service_table_id': service_instance_id,
|
||||||
|
'service_type': service_type,
|
||||||
|
'service_type_id': service_type_id,
|
||||||
|
}
|
||||||
|
service_instance_dict = plugin._create_service_instance(
|
||||||
|
context, device.id, service_instance_param, False)
|
||||||
|
return (plugin._make_device_dict(device), service_instance_dict)
|
Loading…
Reference in New Issue
Block a user