def use_thin_logic(share_type): # NOTE(xyang): To preserve the existing behavior, we use thin logic # to evaluate in two cases: # 1) 'thin_provisioning' is not set in extra specs (This is for # backward compatibility. If not set, the scheduler behaves # the same as before this bug fix). # 2) 'thin_provisioning' is set in extra specs and it is # '<is> True' or 'True'. # Otherwise we use the thick logic to evaluate. use_thin_logic = True thin_spec = None try: thin_spec = share_type.get('extra_specs', {}).get('thin_provisioning') if thin_spec is None: thin_spec = share_type.get( 'extra_specs', {}).get('capabilities:thin_provisioning') # NOTE(xyang) 'use_thin_logic' and 'thin_provisioning' are NOT # the same thing. The first purpose of "use_thin_logic" is to # preserve the existing scheduler behavior if 'thin_provisioning' # is NOT in extra_specs (if thin_spec is None, use_thin_logic # should be True). The second purpose of 'use_thin_logic' # is to honor 'thin_provisioning' if it is in extra specs (if # thin_spec is set to True, use_thin_logic should be True; if # thin_spec is set to False, use_thin_logic should be False). use_thin_logic = strutils.bool_from_string( thin_spec, strict=True) if thin_spec is not None else True except ValueError: # Check if the value of thin_spec is '<is> True'. if thin_spec is not None and not extra_specs_ops.match( True, thin_spec): use_thin_logic = False return use_thin_logic
def use_thin_logic(share_type): # NOTE(xyang): To preserve the existing behavior, we use thin logic # to evaluate in two cases: # 1) 'thin_provisioning' is not set in extra specs (This is for # backward compatibility. If not set, the scheduler behaves # the same as before this bug fix). # 2) 'thin_provisioning' is set in extra specs and it is # '<is> True' or 'True'. # Otherwise we use the thick logic to evaluate. use_thin_logic = True thin_spec = None try: thin_spec = share_type.get('extra_specs', {}).get( 'thin_provisioning') if thin_spec is None: thin_spec = share_type.get('extra_specs', {}).get( 'capabilities:thin_provisioning') # NOTE(xyang) 'use_thin_logic' and 'thin_provisioning' are NOT # the same thing. The first purpose of "use_thin_logic" is to # preserve the existing scheduler behavior if 'thin_provisioning' # is NOT in extra_specs (if thin_spec is None, use_thin_logic # should be True). The second purpose of 'use_thin_logic' # is to honor 'thin_provisioning' if it is in extra specs (if # thin_spec is set to True, use_thin_logic should be True; if # thin_spec is set to False, use_thin_logic should be False). use_thin_logic = strutils.bool_from_string( thin_spec, strict=True) if thin_spec is not None else True except ValueError: # Check if the value of thin_spec is '<is> True'. if thin_spec is not None and not extra_specs_ops.match( True, thin_spec): use_thin_logic = False return use_thin_logic
def capabilities_satisfied(capabilities, extra_specs): # These extra-specs are not capabilities for matching hosts ignored_extra_specs = ( 'availability_zones', 'capabilities:availability_zones', ) for key, req in extra_specs.items(): # Ignore some extra_specs if told to if key in ignored_extra_specs: continue # Either not scoped format, or in capabilities scope scope = key.split(':') # Ignore scoped (such as vendor-specific) capabilities if len(scope) > 1 and scope[0] != "capabilities": continue # Strip off prefix if spec started with 'capabilities:' elif scope[0] == "capabilities": del scope[0] cap = capabilities for index in range(len(scope)): try: cap = cap.get(scope[index]) except AttributeError: cap = None if cap is None: LOG.debug( "Host doesn't provide capability '%(cap)s' " "listed in the extra specs", {'cap': scope[index]}) return False # Make all capability values a list so we can handle lists cap_list = [cap] if not isinstance(cap, list) else cap # Loop through capability values looking for any match for cap_value in cap_list: if extra_specs_ops.match(cap_value, req): break else: # Nothing matched, so bail out LOG.debug( 'Share type extra spec requirement ' '"%(key)s=%(req)s" does not match reported ' 'capability "%(cap)s"', { 'key': key, 'req': req, 'cap': cap }) return False return True
def _satisfies_extra_specs(self, capabilities, resource_type): """Compare capabilities against extra specs. Check that the capabilities provided by the services satisfy the extra specs associated with the resource type. """ extra_specs = resource_type.get('extra_specs', []) if not extra_specs: return True for key, req in extra_specs.items(): # Either not scoped format, or in capabilities scope scope = key.split(':') # Ignore scoped (such as vendor-specific) capabilities if len(scope) > 1 and scope[0] != "capabilities": continue # Strip off prefix if spec started with 'capabilities:' elif scope[0] == "capabilities": del scope[0] cap = capabilities for index in range(len(scope)): try: cap = cap.get(scope[index]) except AttributeError: cap = None if cap is None: LOG.debug( "Host doesn't provide capability '%(cap)s' " "listed in the extra specs", {'cap': scope[index]}) return False # Make all capability values a list so we can handle lists cap_list = [cap] if not isinstance(cap, list) else cap # Loop through capability values looking for any match for cap_value in cap_list: if extra_specs_ops.match(cap_value, req): break else: # Nothing matched, so bail out LOG.debug( 'Share type extra spec requirement ' '"%(key)s=%(req)s" does not match reported ' 'capability "%(cap)s"', { 'key': key, 'req': req, 'cap': cap }) return False return True
def _satisfies_extra_specs(self, capabilities, resource_type): """Compare capabilities against extra specs. Check that the capabilities provided by the services satisfy the extra specs associated with the resource type. """ extra_specs = resource_type.get('extra_specs', []) if not extra_specs: return True for key, req in extra_specs.items(): # Either not scoped format, or in capabilities scope scope = key.split(':') # Ignore scoped (such as vendor-specific) capabilities if len(scope) > 1 and scope[0] != "capabilities": continue # Strip off prefix if spec started with 'capabilities:' elif scope[0] == "capabilities": del scope[0] cap = capabilities for index in range(len(scope)): try: cap = cap.get(scope[index]) except AttributeError: cap = None if cap is None: LOG.debug("Host doesn't provide capability '%(cap)s' " "listed in the extra specs", {'cap': scope[index]}) return False # Make all capability values a list so we can handle lists cap_list = [cap] if not isinstance(cap, list) else cap # Loop through capability values looking for any match for cap_value in cap_list: if extra_specs_ops.match(cap_value, req): break else: # Nothing matched, so bail out LOG.debug('Share type extra spec requirement ' '"%(key)s=%(req)s" does not match reported ' 'capability "%(cap)s"', {'key': key, 'req': req, 'cap': cap}) return False return True
def _do_extra_specs_ops_test(self, value, req, matches): assertion = self.assertTrue if matches else self.assertFalse assertion(extra_specs_ops.match(value, req))