コード例 #1
0
 def _retrieve_tenant_rn(self, data):
     if isinstance(data, dict):
         if data.keys()[0] == 'tagInst':
             # Retrieve tag parent
             dn = data.values()[0]['attributes']['dn']
             decomposed = apic_client.DNManager().aci_decompose_dn_guess(
                 dn, 'tagInst')
             parent_type = decomposed[1][-2][0]
             data = {
                 parent_type: {
                     'attributes': {
                         'dn': apic_client.DNManager().build(
                             decomposed[1][:-1])}}}
         data = self._aim_converter.convert([data])
         data = data[0] if data else None
     if isinstance(data, resource.AciResourceBase):
         return tree_manager.AimHashTreeMaker().get_root_key(data)
コード例 #2
0
def mock_get_data(inst, dn, **kwargs):
    # Expected kwargs: query_target [subtree], target_subtree_class
    try:
        inst._data_stash
    except Exception:
        inst._data_stash = {}

    dn_mgr = apic_client.DNManager()
    # Decompose the DN, remove the mo/ in front
    decomposed = decompose_aci_dn(dn[3:])
    try:
        # Find the proper root node
        curr = copy.deepcopy(inst._data_stash[decomposed[0][1]])[0]
        for index, part in enumerate(decomposed[1:]):
            # Look at the current's children and find the proper node.
            if part[0] in AMBIGUOUS_TYPES:
                partial_dn = (
                    dn_mgr.build(decomposed[:index + 1]) + '/' +
                    apic_client.ManagedObjectClass.mos_to_prefix[part[0]] +
                    '-' + decomposed[index + 1][1])
            else:
                partial_dn = dn_mgr.build(decomposed[:index + 2])
            for child in curr.values()[0]['children']:
                if child.values()[0]['attributes']['dn'] == partial_dn:
                    curr = child
                    break
            else:
                raise KeyError
        # Curr is the looked up node. Look at the query params to filter the
        # result
        query_target = kwargs.get('query_target', 'self')
        if query_target == 'subtree':
            # Look at the target subtree class
            target_subtree_class = kwargs.get('target_subtree_class',
                                              '').split(',')
            if not target_subtree_class:
                # Return everything
                return _flat_result(curr)
            else:
                # Only return the expected objects
                return [
                    x for x in _flat_result(curr)
                    if x.keys()[0] in target_subtree_class
                ]
        else:
            curr.values()[0].pop('children', [])
            return [curr]
    except KeyError:
        # Simulate 404
        if 'fault' in dn:
            # non existing faults return empty data
            return []
        raise apic_client.cexc.ApicResponseNotOk(request='get',
                                                 status='404',
                                                 reason='Not Found',
                                                 err_text='Not Found',
                                                 err_code='404')
コード例 #3
0
def fv_rs_master_epg_converter(object_dict,
                               otype,
                               helper,
                               source_identity_attributes,
                               destination_identity_attributes,
                               to_aim=True):
    result = []
    if to_aim:
        res_dict = {}
        try:
            id = default_identity_converter(object_dict,
                                            otype,
                                            helper,
                                            to_aim=True)
        except apic_client.DNManager.InvalidNameFormat:
            return []
        for index, attr in enumerate(destination_identity_attributes):
            res_dict[attr] = id[index]
        if object_dict.get('tDn'):
            master_id = apic_client.DNManager().aci_decompose_with_type(
                object_dict['tDn'], 'fvAEPg')
            res_dict['epg_contract_masters'] = [{
                'app_profile_name':
                master_id[1][1],
                'name':
                master_id[2][1]
            }]
        result.append(default_to_resource(res_dict, helper, to_aim=True))
    else:
        for p in object_dict['epg_contract_masters']:
            if p.get('app_profile_name') and p.get('name'):
                try:
                    attr = [
                        object_dict.get('tenant_name'),
                        p.get('app_profile_name'),
                        p.get('name')
                    ]
                    path = apic_client.ManagedObjectClass('fvAEPg').dn(*attr)
                except Exception as e:
                    LOG.error('Failed to make DN for %s with %s: %s',
                              helper['resource'], attr, e)
                    raise
                dn = default_identity_converter(object_dict,
                                                otype,
                                                helper,
                                                extra_attributes=[path],
                                                aci_mo_type=helper['resource'],
                                                to_aim=False)[0]
                result.append({
                    helper['resource']: {
                        'attributes': {
                            'dn': dn,
                            'tDn': path
                        }
                    }
                })
    return result
コード例 #4
0
def decompose_dn(mo_type, dn):
    try:
        return apic_client.DNManager().aci_decompose_dn_guess(dn, mo_type)[1]
    except (apic_client.DNManager.InvalidNameFormat, KeyError,
            apic_client.cexc.ApicManagedObjectNotSupported, IndexError):
        log_ = LOG.warning
        if mo_type == 'faultDelegate':
            log_ = LOG.debug
        log_("Failed to transform DN %s to key for type %s" % (dn, mo_type))
        return
コード例 #5
0
    def root_key_funct(key):
        """Key funct for Tree Maker

        Utility function for TreeManager initialization
        :param tree:
        :return:
        """
        splits = key.split('-', 1)
        mo = apic_client.ManagedObjectClass.prefix_to_mos[splits[0]]
        dn = apic_client.DNManager().build([[mo, splits[-1]]])
        return AimHashTreeMaker._build_hash_tree_key_from_dn(dn, mo)
コード例 #6
0
 def from_dn(cls, dn):
     dn_mgr = apic_client.DNManager()
     try:
         mos_and_rns = dn_mgr.aci_decompose_with_type(dn, cls._aci_mo_name)
         rns = dn_mgr.filter_rns(mos_and_rns)
         if len(rns) < len(cls.identity_attributes):
             raise exc.InvalidDNForAciResource(dn=dn, cls=cls)
         attr = {p[0]: p[1] for p in zip(cls.identity_attributes, rns)}
         return cls(**attr)
     except apic_client.DNManager.InvalidNameFormat:
         raise exc.InvalidDNForAciResource(dn=dn, cls=cls)
コード例 #7
0
    def __init__(self,
                 tenant_name,
                 apic_config,
                 apic_session,
                 ws_context,
                 creation_succeeded=None,
                 creation_failed=None,
                 aim_system_id=None,
                 get_resources=None,
                 *args,
                 **kwargs):
        super(AciTenantManager, self).__init__(*args, **kwargs)
        LOG.info("Init manager for tenant %s" % tenant_name)
        self.get_resources = get_resources
        self.apic_config = apic_config
        # Each tenant has its own sessions
        self.aci_session = apic_session
        self.dn_manager = apic_client.DNManager()
        self.tenant_name = tenant_name
        children_mos = get_children_mos(self.aci_session, self.tenant_name)
        ws_subscription_to = self.apic_config.get_option(
            'websocket_subscription_timeout', 'aim') or DEFAULT_WS_TO
        self.tenant = Root(self.tenant_name,
                           filtered_children=children_mos,
                           rn=self.tenant_name,
                           ws_subscription_to=ws_subscription_to)
        self._state = structured_tree.StructuredHashTree()
        self._operational_state = structured_tree.StructuredHashTree()
        self._monitored_state = structured_tree.StructuredHashTree()
        self.polling_yield = self.apic_config.get_option(
            'aci_tenant_polling_yield', 'aim')
        self.to_aim_converter = converter.AciToAimModelConverter()
        self.to_aci_converter = converter.AimToAciModelConverter()
        self._reset_object_backlog()
        self.tree_builder = tree_manager.HashTreeBuilder(None)
        self.tag_name = aim_system_id or self.apic_config.get_option(
            'aim_system_id', 'aim')
        self.tag_set = set()
        self.failure_log = {}

        def noop(*args, **kwargs):
            pass

        self.creation_succeeded = creation_succeeded or noop
        self.creation_failed = creation_failed or noop
        # Warm bit to avoid rushed synchronization before receiving the first
        # batch of APIC events
        self._warm = False
        self.ws_context = ws_context
        self.recovery_retries = None
        self.max_retries = 5
        self.error_handler = error.APICAPIErrorHandler()
        # For testing purposes
        self.num_loop_runs = float('inf')
コード例 #8
0
 def _check_parent_type(self, aci_object, parent_types):
     dn = list(aci_object.values())[0]['attributes']['dn']
     type = list(aci_object.keys())[0]
     try:
         decomposed = (apic_client.DNManager().aci_decompose_dn_guess(
             dn, type))
     except apic_client.DNManager.InvalidNameFormat:
         LOG.debug("Type %s with DN %s is not supported." % (type, dn))
         return False
     if len(decomposed[1]) <= 1:
         return False
     return decomposed[1][-2][0] in parent_types
コード例 #9
0
 def set_ownership_change(self, to_push):
     to_update = []
     if self.use_annotation:
         for obj in to_push:
             if list(obj.keys())[0].startswith(TAG_KEY):
                 dn = list(obj.values())[0]['attributes']['dn']
                 if dn.endswith('/tag-%s' % self.tag_key):
                     dec = apic_client.DNManager().aci_decompose_dn_guess(
                         dn,
                         list(obj.keys())[0])
                     parent_dec = dec[1][:-1]
                     parent_dn = apic_client.DNManager().build(parent_dec)
                     parent_type = parent_dec[-1][0]
                     to_update.append({
                         parent_type: {
                             'attributes': {
                                 'dn': parent_dn,
                                 'annotation': ''
                             }
                         }
                     })
     return to_push, to_update
コード例 #10
0
 def __init__(self, *args, **kwargs):
     self.filtered_children = kwargs.pop('filtered_children', [])
     rn = kwargs.pop('rn')
     super(Root, self).__init__(*args, **kwargs)
     try:
         rn_base = apic_client.DNManager().get_rn_base(rn)
         if rn.startswith(rn_base):
             self.dn = rn
         else:
             self.dn = rn_base + '/' + rn
     except KeyError:
         self.dn = apic_client.DN_BASE + 'rn'
     self.urls = self._get_instance_subscription_urls()
コード例 #11
0
 def _post_with_transaction(self, to_push, modified=False):
     if not to_push:
         return
     dn_mgr = apic_client.DNManager()
     decompose = dn_mgr.aci_decompose_dn_guess
     with self.aci_session.transaction(top_send=True) as trs:
         for obj in to_push:
             attr = list(obj.values())[0]['attributes']
             if modified:
                 attr['status'] = converter.MODIFIED_STATUS
             mo, parents_rns = decompose(attr.pop('dn'),
                                         list(obj.keys())[0])
             rns = dn_mgr.filter_rns(parents_rns)
             getattr(self.aci_session, mo).create(*rns,
                                                  transaction=trs,
                                                  **attr)
コード例 #12
0
 def __init__(self, *args, **kwargs):
     self.filtered_children = kwargs.pop('filtered_children', [])
     rn = kwargs.pop('rn')
     ws_subscription_to = kwargs.pop('ws_subscription_to')
     super(Root, self).__init__(*args, **kwargs)
     try:
         rn_base = apic_client.DNManager().get_rn_base(rn)
         if rn.startswith(rn_base):
             self.dn = rn
         else:
             self.dn = rn_base + '/' + rn
     except KeyError:
         self.dn = apic_client.DN_BASE + 'rn'
     self.type = apic_client.ManagedObjectClass.prefix_to_mos[rn.split('-')
                                                              [0]]
     self.urls = self._get_instance_subscription_urls(
         ws_subscription_to=ws_subscription_to)
コード例 #13
0
 def _tdn_rs_converter(object_dict,
                       otype,
                       helper,
                       source_identity_attributes,
                       destination_identity_attributes,
                       to_aim=True):
     result = []
     if to_aim:
         # Converting a fvRsDomAtt into an EPG
         res_dict = {}
         try:
             id = default_identity_converter(object_dict,
                                             otype,
                                             helper,
                                             to_aim=True)
         except apic_client.DNManager.InvalidNameFormat:
             return []
         for index, attr in enumerate(destination_identity_attributes):
             res_dict[attr] = id[index]
         tdn = object_dict.get('tDn')
         if tdn:
             dnm = apic_client.DNManager()
             mos_and_rns = dnm.aci_decompose_with_type(tdn, aci_mo)
             rns = dnm.filter_rns(mos_and_rns)
             res_dict.update(dict(zip(aim_attr_list, rns)))
         to_res = helper.get('to_resource', default_to_resource)
         result.append(to_res(res_dict, helper, to_aim=True))
     else:
         dn = default_identity_converter(object_dict,
                                         otype,
                                         helper,
                                         to_aim=False)[0]
         dn_attrs = [
             object_dict[a] for a in aim_attr_list if object_dict.get(a)
         ]
         if len(dn_attrs) == len(aim_attr_list):
             tdn = apic_client.ManagedObjectClass(aci_mo).dn(*dn_attrs)
             result.append({
                 helper['resource']: {
                     'attributes': {
                         'dn': dn,
                         'tDn': tdn
                     }
                 }
             })
     return result
コード例 #14
0
 def _keys_to_bare_aci_objects(self, keys):
     # Transforms hashtree keys into minimal ACI objects
     aci_objects = []
     for key in keys:
         fault_code = None
         key_parts = self._split_key(key)
         mo_type = key_parts[-1][0]
         aci_object = {mo_type: {'attributes': {}}}
         if mo_type == 'faultInst':
             fault_code = key_parts[-1][1]
             key_parts = key_parts[:-1]
         dn = apic_client.DNManager().build(key_parts)
         if fault_code:
             dn += '/fault-%s' % fault_code
             aci_object[mo_type]['attributes']['code'] = fault_code
         aci_object[mo_type]['attributes']['dn'] = dn
         aci_objects.append(aci_object)
     return aci_objects
コード例 #15
0
 def func(object_dict, attribute, to_aim=True):
     if to_aim:
         dn = object_dict.get(attribute)
         if dn:
             dnm = apic_client.DNManager()
             mos_and_rns = dnm.aci_decompose_with_type(dn, aci_mo)
             rns = dnm.filter_rns(mos_and_rns)
             return dict(zip(aim_attr_list, rns))
         else:
             return {}
     else:
         dn_attrs = [
             object_dict[a] for a in aim_attr_list if object_dict.get(a)
         ]
         if len(dn_attrs) == len(aim_attr_list):
             dn = apic_client.ManagedObjectClass(aci_mo).dn(*dn_attrs)
         else:
             dn = ''
         return dn
コード例 #16
0
def get_children_mos(apic_session, root):
    root_type = 'uni'
    try:
        root_type = apic_client.DNManager().get_rn_base(root)
    except KeyError:
        pass
    global CHILDREN_MOS_UNI
    global CHILDREN_MOS_TOPOLOGY
    if root_type in ['uni']:
        if CHILDREN_MOS_UNI is None:
            CHILDREN_MOS_UNI = set()
            for mo in CHILDREN_LIST:
                if mo in apic_client.ManagedObjectClass.supported_mos:
                    mo_name = apic_client.ManagedObjectClass(mo).klass_name
                else:
                    mo_name = mo
                try:
                    # Verify class support
                    apic_session.GET('/mo/uni/tn-common.json?'
                                     'target-subtree-class=%s' % mo_name)
                except apic_exc.ApicResponseNotOk as e:
                    if int(e.err_status) == 400 and int(e.err_code) == 12:
                        continue
                    raise e
                CHILDREN_MOS_UNI.add(mo_name)
        return CHILDREN_MOS_UNI
    elif root_type in ['topology']:
        if CHILDREN_MOS_TOPOLOGY is None:
            CHILDREN_MOS_TOPOLOGY = set()
            for mo in TOPOLOGY_CHILDREN_LIST:
                if mo in apic_client.ManagedObjectClass.supported_mos:
                    mo_name = apic_client.ManagedObjectClass(mo).klass_name
                else:
                    mo_name = mo
                try:
                    apic_session.GET('/node/class/%s.json?' % mo_name)
                except apic_exc.ApicResponseNotOk as e:
                    if int(e.err_status) == 400 and int(e.err_code) == 12:
                        continue
                    raise e
                CHILDREN_MOS_TOPOLOGY.add(mo_name)
        return CHILDREN_MOS_TOPOLOGY
コード例 #17
0
def retrieve_fault_parent(fault_dn, resource_map):
    # external is the DN of the ACI resource
    dn_mgr = apic_client.DNManager()
    mos_rns = dn_mgr.aci_decompose_with_type(fault_dn, ACI_FAULT)[:-1]
    rns = dn_mgr.filter_rns(mos_rns)
    conv_info = None
    step = -1
    while conv_info is None or len(conv_info) > 1:
        aci_klass = mos_rns[step][0]
        conv_info = resource_map[aci_klass]
        step -= 1
    conv_info = conv_info[0]
    klasses = [conv_info['resource']]
    if conv_info.get('alt_resource'):
        klasses.append(conv_info['alt_resource'])
    parents = []
    for klass in klasses:
        a_obj = klass(**{y: rns[x]
                         for x, y in enumerate(klass.identity_attributes)})
        parents.append(a_obj)
    return parents
コード例 #18
0
def default_identity_converter(object_dict,
                               otype,
                               helper,
                               extra_attributes=None,
                               aci_mo_type=None,
                               to_aim=True):
    """Default identity converter

    This converter uses the DN and splits it in its fundamental parts to
    retrieve the identity names.

    :param object_dict: dictionarty of the resource to be converted
    :param otype: Type of the object. Can be an AIM resource class or a
                  APIC class name.
    :param extra_attributes: Ordered list of additional attribute values needed
                             to create the identity attribute
    :param aci_mo_type: ACI ManagedObjectType to use when creating ACI identity
                        attribute
    :param to_aim: Boolean indicating whether we are converting
                   ACI/AIM (True) or AIM/ACI (False)
    :return: list with exactly all the attributes that need to be assigned
    to the resource class 'identity_attributes'
    """
    if to_aim:
        dn_mgr = apic_client.DNManager()
        aci_type = aci_mo_type or otype
        mos_and_rns = dn_mgr.aci_decompose_with_type(object_dict['dn'],
                                                     aci_type)
        return dn_mgr.filter_rns(mos_and_rns)
    else:
        attr = [object_dict[x] for x in otype.identity_attributes]
        if extra_attributes:
            attr.extend(extra_attributes)
        mo_type = aci_mo_type or helper['resource']
        try:
            return [apic_client.ManagedObjectClass(mo_type).dn(*attr)]
        except Exception as e:
            LOG.error('Failed to make DN for %s with %s: %s', mo_type, attr, e)
            raise
コード例 #19
0
 def action(result, aci_object, node):
     if node and not node.dummy:
         # Monitored state transition -> Delete the TAG instead
         LOG.debug("Deleting tag for transitioning object %s",
                   list(aci_object.values())[0]['attributes']['dn'])
         aci_type = 'tagInst'
         dn = list(aci_object.values(
         ))[0]['attributes']['dn'] + '/tag-' + self.aim_system_id
         result.append({aci_type: {'attributes': {'dn': dn}}})
     else:
         # If the parent object was already deleted in the config
         # desired tree then we don't have to send this child deletion
         # to APIC
         dn = list(aci_object.values())[0]['attributes']['dn']
         res_type = list(aci_object.keys())[0]
         dn_mgr = apic_client.DNManager()
         mo, rns = dn_mgr.aci_decompose_dn_guess(dn, res_type)
         if len(rns) > 1:
             parent_dn = dn_mgr.build(rns[:-1])
             parent_type, xxx = rns[-2]
             parent_key = tree_manager.AimHashTreeMaker._dn_to_key(
                 parent_type, parent_dn)
             root = tree_manager.AimHashTreeMaker._extract_root_rn(
                 parent_key)
             config_desire = self.multiverse[
                 base.CONFIG_UNIVERSE]['desired'].state
             node = config_desire[root].find(parent_key)
             if node:
                 result.append(aci_object)
             # Also has to make sure the parent is not in the monitor
             # desired tree before we skip it
             else:
                 mon_desire = self.multiverse[
                     base.MONITOR_UNIVERSE]['desired'].state
                 node = mon_desire[root].find(parent_key)
                 if node:
                     result.append(aci_object)
         else:
             result.append(aci_object)
コード例 #20
0
 def _push_aim_resources(self):
     dn_mgr = apic_client.DNManager()
     decompose = dn_mgr.aci_decompose_dn_guess
     with utils.get_rlock(lcon.ACI_BACKLOG_LOCK_NAME_PREFIX +
                          self.tenant_name):
         while not self.object_backlog.empty():
             request = self.object_backlog.get()
             for method, aim_objects in request.items():
                 # Method will be either "create" or "delete"
                 # sort the aim_objects based on DN first for DELETE method
                 sorted_aim_objs = aim_objects
                 if method == base_universe.DELETE:
                     sorted_aim_objs = sorted(aim_objects,
                                              key=lambda x: list(x.values())
                                              [0]['attributes']['dn'])
                 potential_parent_dn = ' '
                 for aim_object in sorted_aim_objs:
                     # get MO from ACI client, identify it via its DN parts
                     # and push the new body
                     if method == base_universe.DELETE:
                         # If a parent is also being deleted then we don't
                         # have to send those children requests to APIC
                         dn = list(
                             aim_object.values())[0]['attributes']['dn']
                         res_type = list(aim_object.keys())[0]
                         decomposed = decompose(dn, res_type)
                         parent_dn = dn_mgr.build(decomposed[1][:-1])
                         if parent_dn.startswith(potential_parent_dn):
                             continue
                         else:
                             potential_parent_dn = dn
                         to_push = [copy.deepcopy(aim_object)]
                     else:
                         if getattr(aim_object, 'monitored', False):
                             # When pushing to APIC, treat monitored
                             # objects as pre-existing
                             aim_object.monitored = False
                             aim_object.pre_existing = True
                         to_push = self.to_aci_converter.convert(
                             [aim_object])
                     LOG.debug('%s AIM object %s in APIC' %
                               (method, repr(aim_object)))
                     try:
                         if method == base_universe.CREATE:
                             # Set ownership before pushing the request
                             to_push = self.ownership_mgr.set_ownership_key(
                                 to_push)
                             LOG.debug("POSTING into APIC: %s" % to_push)
                             self._post_with_transaction(to_push)
                             self.creation_succeeded(aim_object)
                         else:
                             to_delete, to_update = (
                                 self.ownership_mgr.set_ownership_change(
                                     to_push))
                             LOG.debug("DELETING from APIC: %s" % to_delete)
                             for obj in to_delete:
                                 attr = list(obj.values())[0]['attributes']
                                 self.aci_session.DELETE('/mo/%s.json' %
                                                         attr.pop('dn'))
                             LOG.debug("UPDATING in APIC: %s" % to_update)
                             # Update object ownership
                             self._post_with_transaction(to_update,
                                                         modified=True)
                             if to_update:
                                 self.creation_succeeded(aim_object)
                     except Exception as e:
                         LOG.debug(traceback.format_exc())
                         LOG.error("An error has occurred during %s for "
                                   "object %s: %s" %
                                   (method, aim_object, str(e)))
                         if method == base_universe.CREATE:
                             err_type = (
                                 self.error_handler.analyze_exception(e))
                             # REVISIT(ivar): for now, treat UNKNOWN errors
                             # the same way as OPERATION_TRANSIENT.
                             # Investigate a way to understand when such
                             # errors might require agent restart.
                             self.creation_failed(aim_object, str(e),
                                                  err_type)
コード例 #21
0
 def _push_aim_resources(self):
     with utils.get_rlock(lcon.ACI_BACKLOG_LOCK_NAME_PREFIX +
                          self.tenant_name):
         while not self.object_backlog.empty():
             request = self.object_backlog.get()
             for method, aim_objects in request.iteritems():
                 # Method will be either "create" or "delete"
                 for aim_object in aim_objects:
                     # get MO from ACI client, identify it via its DN parts
                     # and push the new body
                     LOG.debug('%s AIM object %s in APIC' %
                               (method, repr(aim_object)))
                     if method == base_universe.DELETE:
                         to_push = [copy.deepcopy(aim_object)]
                     else:
                         if getattr(aim_object, 'monitored', False):
                             # When pushing to APIC, treat monitored
                             # objects as pre-existing
                             aim_object.monitored = False
                             aim_object.pre_existing = True
                         to_push = self.to_aci_converter.convert(
                             [aim_object])
                     # Set TAGs before pushing the request
                     tags = []
                     if method == base_universe.CREATE:
                         # No need to deal with tags on deletion
                         for obj in to_push:
                             if not obj.keys()[0].startswith(TAG_KEY):
                                 dn = obj.values()[0]['attributes']['dn']
                                 dn += '/tag-%s' % self.tag_name
                                 tags.append({
                                     "tagInst__%s" % obj.keys()[0]: {
                                         "attributes": {
                                             "dn": dn
                                         }
                                     }
                                 })
                     LOG.debug("Pushing %s into APIC: %s" %
                               (method, to_push + tags))
                     # Multiple objects could result from a conversion, push
                     # them in a single transaction
                     dn_mgr = apic_client.DNManager()
                     decompose = dn_mgr.aci_decompose_dn_guess
                     try:
                         if method == base_universe.CREATE:
                             with self.aci_session.transaction(
                                     top_send=True) as trs:
                                 for obj in to_push + tags:
                                     attr = obj.values()[0]['attributes']
                                     mo, parents_rns = decompose(
                                         attr.pop('dn'),
                                         obj.keys()[0])
                                     rns = dn_mgr.filter_rns(parents_rns)
                                     getattr(getattr(self.aci_session, mo),
                                             method)(*rns,
                                                     transaction=trs,
                                                     **attr)
                         else:
                             for obj in to_push + tags:
                                 attr = obj.values()[0]['attributes']
                                 self.aci_session.DELETE('/mo/%s.json' %
                                                         attr.pop('dn'))
                         # Object creation was successful, change object
                         # state
                         if method == base_universe.CREATE:
                             self.creation_succeeded(aim_object)
                     except Exception as e:
                         LOG.debug(traceback.format_exc())
                         LOG.error("An error has occurred during %s for "
                                   "object %s: %s" %
                                   (method, aim_object, e.message))
                         if method == base_universe.CREATE:
                             err_type = (
                                 self.error_handler.analyze_exception(e))
                             # REVISIT(ivar): for now, treat UNKNOWN errors
                             # the same way as OPERATION_TRANSIENT.
                             # Investigate a way to understand when such
                             # errors might require agent restart.
                             self.creation_failed(aim_object, e.message,
                                                  err_type)
コード例 #22
0
    def _manipulate_server_data(self,
                                data,
                                manager=None,
                                add=True,
                                tag=True,
                                create_parents=False):
        removed = None
        manager = manager if manager is not None else self.manager
        try:
            manager.aci_session._data_stash
        except Exception:
            manager.aci_session._data_stash = {}

        def _tag_format(dn):
            return {
                'tagInst': {
                    'attributes': {
                        'dn': (dn + '/tag-' + self.sys_id)
                    },
                    'children': []
                }
            }

        dn_mgr = apic_client.DNManager()
        for resource in copy.deepcopy(data):
            resource.values()[0]['attributes'].pop('status', None)
            data_type = resource.keys()[0]
            if data_type == 'tagInst' and tag and add:
                continue
            decomposed = dn_mgr.aci_decompose_dn_guess(
                resource.values()[0]['attributes']['dn'], data_type)[1]
            if add:
                curr = manager.aci_session._data_stash.setdefault(
                    decomposed[0][1], [])
            else:
                curr = manager.aci_session._data_stash.get(
                    decomposed[0][1], [])
            prev = None
            child_index = None
            last_index = len(decomposed) - 1
            is_new = False
            for out_index, part in enumerate(decomposed):
                # Look at the current's children and find the proper node.
                # if not found, it's a new node
                if part[0] in AMBIGUOUS_TYPES:
                    partial_dn = (
                        dn_mgr.build(decomposed[:out_index]) + '/' +
                        apic_client.ManagedObjectClass.mos_to_prefix[part[0]] +
                        '-' + decomposed[out_index][1])
                else:
                    partial_dn = dn_mgr.build(decomposed[:out_index + 1])

                for index, child in enumerate(curr):
                    if child.values()[0]['attributes']['dn'] == partial_dn:
                        child_index = index
                        prev = curr
                        curr = child.values()[0]['children']
                        break
                else:
                    if add:
                        if out_index < last_index:
                            # Parent is missing
                            if create_parents:
                                next = {
                                    part[0]: {
                                        'attributes': {
                                            'dn': partial_dn
                                        },
                                        'children': [] if not tag else
                                        [_tag_format(partial_dn)]
                                    }
                                }
                                curr.append(next)
                                prev = curr
                                curr = next[part[0]]['children']
                            else:
                                raise apic_client.cexc.ApicResponseNotOk(
                                    status=400,
                                    reason='bad request',
                                    request='create',
                                    err_code=104,
                                    err_text='bad request')
                        else:
                            # Append newly created object
                            obj = {
                                part[0]: {
                                    'attributes': {
                                        'dn': partial_dn
                                    },
                                    'children': []
                                    if not tag else [_tag_format(partial_dn)]
                                }
                            }
                            curr.append(obj)
                            resource.values()[0].pop('children', None)
                            obj[part[0]].update(resource.values()[0])
                            is_new = True
                    else:
                        # Not found
                        return
            # Update body
            if not add:
                if child_index is not None:
                    removed = prev.pop(child_index)
                    if prev is manager.aci_session._data_stash[decomposed[0]
                                                               [1]]:
                        # Tenant is now empty
                        manager.aci_session._data_stash.pop(decomposed[0][1])
                else:
                    # Root node
                    removed = manager.aci_session._data_stash.pop(
                        decomposed[0][1])
            elif child_index is not None and not is_new:
                children = prev[child_index].values()[0]['children']
                prev[child_index].update(resource)
                prev[child_index].values()[0]['children'] = children
        return removed
コード例 #23
0
 def _extract_root_rn(root_key):
     root_split = root_key[0].split('|')
     return apic_client.DNManager().build([root_split]).split('/')[-1]
コード例 #24
0
    def retrieve_aci_objects(self, events):
        result = {}

        for event in events:
            resource = list(event.values())[0]
            res_type = list(event.keys())[0]
            status = (resource['attributes'].get(STATUS_FIELD) or '').lower()
            raw_dn = resource['attributes'].get('dn')
            if self.is_child_object(res_type) and res_type != FAULT_KEY:
                # We need to make sure to retrieve the parent object as well
                try:
                    decomposed = (
                        apic_client.DNManager().aci_decompose_dn_guess(
                            raw_dn, res_type))
                    parent_dn = apic_client.DNManager().build(
                        decomposed[1][:-1])
                    if parent_dn not in result:
                        events.append({
                            decomposed[1][-2][0]: {
                                'attributes': {
                                    'dn': parent_dn,
                                    'status': converter.MODIFIED_STATUS,
                                    '_avoid_print_not_found': True
                                }
                            }
                        })
                except (apic_client.DNManager.InvalidNameFormat, KeyError):
                    LOG.debug("Object with DN %s is not supported." % raw_dn)
                    continue
            if res_type == FAULT_KEY:
                # Make sure we support the parent object
                try:
                    apic_client.DNManager().aci_decompose_dn_guess(
                        raw_dn, res_type)
                    utils.retrieve_fault_parent(raw_dn, converter.resource_map)
                except (apic_client.DNManager.InvalidNameFormat, KeyError):
                    LOG.debug("Fault with DN %s is not supported." % raw_dn)
                    continue
            if res_type == TAG_KEY:
                # Add to the result and go ahead to the next object
                result[raw_dn] = event
                continue
            if status == converter.DELETED_STATUS:
                # Add to the result but keep evaluating
                result[raw_dn] = event
            if status == converter.MODIFIED_STATUS:
                event_attrs = copy.deepcopy(
                    list(event.values())[0]['attributes'])
                event_attrs.pop(STATUS_FIELD)
                apnf = event_attrs.pop('_avoid_print_not_found', False)
                if raw_dn in result:
                    # Update with changes
                    list(result[raw_dn].values())[0]['attributes'].update(
                        event_attrs)
                key = tree_manager.AimHashTreeMaker._dn_to_key(
                    res_type, raw_dn)
                data = []
                if key:
                    # Search within the TenantManager state, which is the most
                    # up to date.
                    data = self.get_resources(
                        [key], desired_state=self._get_full_state())
                if not data and not apnf:
                    LOG.debug("Resource %s not found or not supported", raw_dn)
                for item in data:
                    dn = list(item.values())[0]['attributes']['dn']
                    if dn not in result:
                        result[dn] = item
                        if dn == raw_dn:
                            list(result[raw_dn].values()
                                 )[0]['attributes'].update(event_attrs)
            if not status or status == converter.CREATED_STATUS:
                result[raw_dn] = event
        LOG.debug("Result for retrieving ACI resources: %s\n %s" %
                  (events, result))
        return list(result.values())