octavia/octavia/controller/worker/amphora_rate_limit.py

97 lines
4.0 KiB
Python

# Copyright 2016 Hewlett-Packard Development Company, L.P.
#
# 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.
#
import time
from oslo_config import cfg
from oslo_log import log as logging
from octavia.common import exceptions
from octavia.db import api as db_apis
from octavia.db import repositories as repo
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
CONF.import_group('haproxy_amphora', 'octavia.common.config')
class AmphoraBuildRateLimit(object):
def __init__(self):
self.amp_build_slots_repo = repo.AmphoraBuildSlotsRepository()
self.amp_build_req_repo = repo.AmphoraBuildReqRepository()
def add_to_build_request_queue(self, amphora_id, build_priority):
self.amp_build_req_repo.add_to_build_queue(
db_apis.get_session(),
amphora_id=amphora_id,
priority=build_priority)
LOG.debug("Added build request for %s to the queue", amphora_id)
self.wait_for_build_slot(amphora_id)
def has_build_slot(self):
build_rate_limit = CONF.haproxy_amphora.build_rate_limit
session = db_apis.get_session()
with session.begin(subtransactions=True):
used_build_slots = (self.amp_build_slots_repo
.get_used_build_slots_count(session))
available_build_slots = build_rate_limit - used_build_slots
LOG.debug("Available build slots %d", available_build_slots)
return available_build_slots > 0
def has_highest_priority(self, amphora_id):
session = db_apis.get_session()
with session.begin(subtransactions=True):
highest_priority_build_req = (
self.amp_build_req_repo.get_highest_priority_build_req(
session))
LOG.debug("Highest priority req: %s, Current req: %s",
highest_priority_build_req, amphora_id)
return amphora_id == highest_priority_build_req
def update_build_status_and_available_build_slots(self, amphora_id):
session = db_apis.get_session()
with session.begin(subtransactions=True):
self.amp_build_slots_repo.update_count(session, action='increment')
self.amp_build_req_repo.update_req_status(session, amphora_id)
def remove_from_build_req_queue(self, amphora_id):
session = db_apis.get_session()
with session.begin(subtransactions=True):
self.amp_build_req_repo.delete(session, amphora_id=amphora_id)
self.amp_build_slots_repo.update_count(session, action='decrement')
LOG.debug("Removed request for %s from queue"
" and released the build slot", amphora_id)
def remove_all_from_build_req_queue(self):
session = db_apis.get_session()
with session.begin(subtransactions=True):
self.amp_build_req_repo.delete_all(session)
self.amp_build_slots_repo.update_count(session, action='reset')
LOG.debug("Removed all the build requests and "
"released the build slots")
def wait_for_build_slot(self, amphora_id):
LOG.debug("Waiting for a build slot")
for i in range(CONF.haproxy_amphora.build_active_retries):
if (self.has_build_slot() and
self.has_highest_priority(amphora_id)):
self.update_build_status_and_available_build_slots(amphora_id)
return
time.sleep(CONF.haproxy_amphora.build_retry_interval)
self.remove_all_from_build_req_queue()
raise exceptions.ComputeBuildQueueTimeoutException()