127 lines
5.0 KiB
Python
127 lines
5.0 KiB
Python
# 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 cinderclient import exceptions as cinder_exception
|
|
from manilaclient.common.apiclient import exceptions as manila_exception
|
|
from oslo_log import log as logging
|
|
|
|
from fuxi.common import constants
|
|
from fuxi import exceptions
|
|
from fuxi.i18n import _
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class StateMonitor(object):
|
|
"""Monitor the status of Volume.
|
|
|
|
Because of some volume operation is asynchronous, such as creating Cinder
|
|
volume, this volume could be used for next stop util reached an desired
|
|
state.
|
|
"""
|
|
def __init__(self, client, expected_obj,
|
|
desired_state,
|
|
transient_states=(),
|
|
time_limit=constants.MONITOR_STATE_TIMEOUT,
|
|
time_delay=1):
|
|
self.client = client
|
|
self.expected_obj = expected_obj
|
|
self.desired_state = desired_state
|
|
self.transient_states = transient_states
|
|
self.time_limit = time_limit
|
|
self.start_time = time.time()
|
|
self.time_delay = time_delay
|
|
|
|
def _reached_desired_state(self, current_state):
|
|
if current_state == self.desired_state:
|
|
return True
|
|
elif current_state in self.transient_states:
|
|
idx = self.transient_states.index(current_state)
|
|
if idx > 0:
|
|
self.transient_states = self.transient_states[idx:]
|
|
return False
|
|
else:
|
|
msg = _("Unexpected state while waiting for volume. "
|
|
"Expected Volume: {0}, "
|
|
"Expected State: {1}, "
|
|
"Reached State: {2}").format(self.expected_obj,
|
|
self.desired_state,
|
|
current_state)
|
|
LOG.error(msg)
|
|
raise exceptions.UnexpectedStateException(msg)
|
|
|
|
def monitor_cinder_volume(self):
|
|
while True:
|
|
try:
|
|
volume = self.client.volumes.get(self.expected_obj.id)
|
|
except cinder_exception.ClientException:
|
|
elapsed_time = time.time() - self.start_time
|
|
if elapsed_time > self.time_limit:
|
|
msg = ("Timed out while waiting for volume. "
|
|
"Expected Volume: {0}, "
|
|
"Expected State: {1}, "
|
|
"Elapsed Time: {2}").format(self.expected_obj,
|
|
self.desired_state,
|
|
elapsed_time)
|
|
LOG.error(msg)
|
|
raise exceptions.TimeoutException(msg)
|
|
raise
|
|
|
|
if self._reached_desired_state(volume.status):
|
|
return volume
|
|
|
|
time.sleep(self.time_delay)
|
|
|
|
def monitor_manila_share(self):
|
|
while True:
|
|
try:
|
|
share = self.client.shares.get(self.expected_obj.id)
|
|
except manila_exception.ClientException:
|
|
elapsed_time = time.time() - self.start_time
|
|
if elapsed_time > self.time_limit:
|
|
msg = ("Timed out while waiting for share. "
|
|
"Expected Share: {0}, "
|
|
"Expected State: {1}, "
|
|
"Elapsed Time: {2}").format(self.expected_obj,
|
|
self.desired_state,
|
|
elapsed_time)
|
|
raise exceptions.TimeoutException(msg)
|
|
raise
|
|
|
|
if self._reached_desired_state(share.status):
|
|
return share
|
|
|
|
time.sleep(self.time_delay)
|
|
|
|
def monitor_share_access(self, access_type, access_to):
|
|
while True:
|
|
try:
|
|
al = self.client.shares.access_list(self.expected_obj.id)
|
|
except manila_exception.ClientException:
|
|
elapsed_time = time.time() - self.start_time
|
|
if elapsed_time > self.time_limit:
|
|
msg = ("Timed out while waiting for share access. "
|
|
"Expected State: {0}, "
|
|
"Elapsed Time: {1}").format(self.desired_state,
|
|
elapsed_time)
|
|
raise exceptions.TimeoutException(msg)
|
|
raise
|
|
|
|
for a in al:
|
|
if a.access_type == access_type and a.access_to == access_to:
|
|
if self._reached_desired_state(a.state):
|
|
return self.expected_obj
|
|
|
|
time.sleep(self.time_delay)
|