Beispiel #1
0
class L3OutInterface(AciResourceBase):
    """Resource representing a logical interface.

    Identity attributes: name of ACI tenant, name of L3Out, name of node
    profile, name of interface profile, interface_path.
    """
    identity_attributes = t.identity(
        ('tenant_name', t.name),
        ('l3out_name', t.name),
        ('node_profile_name', t.name),
        ('interface_profile_name', t.name),
        ('interface_path', t.string()))
    other_attributes = t.other(
        ('primary_addr_a', t.ip_cidr),
        ('secondary_addr_a_list', t.list_of_ip_cidr_obj),
        ('primary_addr_b', t.ip_cidr),
        ('secondary_addr_b_list', t.list_of_ip_cidr_obj),
        ('encap', t.string()),
        ('mode', t.enum(*t.spmodes.values())),
        ('host', t.string()),
        ('type', t.enum("ext-svi")),
        ('monitored', t.bool))

    _aci_mo_name = 'l3extRsPathL3OutAtt'
    _tree_parent = L3OutInterfaceProfile

    def __init__(self, **kwargs):
        super(L3OutInterface, self).__init__(
            {'primary_addr_a': '', 'secondary_addr_a_list': [],
             'primary_addr_b': '', 'secondary_addr_b_list': [],
             'encap': '', 'type': 'ext-svi', 'mode': 'regular',
             'monitored': False, 'host': ''}, **kwargs)
class ServiceGraphConnection(resource.AciResourceBase):
    """Resource representing connections among function-nodes in service graph.

    """

    identity_attributes = t.identity(('tenant_name', t.name),
                                     ('service_graph_name', t.name),
                                     ('name', t.name))
    other_attributes = t.other(
        ('display_name', t.name), ('adjacency_type', t.enum('L2', 'L3')),
        ('connector_direction', t.enum('consumer', 'provider')),
        ('connector_type', t.enum('internal', 'external')),
        ('direct_connect', t.bool), ('unicast_route', t.bool),
        ('connector_dns', t.list_of_strings), ('monitored', t.bool))

    _aci_mo_name = 'vnsAbsConnection'
    _tree_parent = ServiceGraph

    def __init__(self, **kwargs):
        super(ServiceGraphConnection, self).__init__(
            {
                'display_name': '',
                'adjacency_type': 'L2',
                'connector_direction': 'provider',
                'connector_type': 'external',
                'direct_connect': False,
                'unicast_route': False,
                'connector_dns': [],
                'monitored': False
            }, **kwargs)
class ServiceGraphNode(resource.AciResourceBase):
    """Resource representing a function-node in service graph.

    """

    identity_attributes = t.identity(('tenant_name', t.name),
                                     ('service_graph_name', t.name),
                                     ('name', t.name))
    other_attributes = t.other(
        ('display_name', t.name),
        ('function_type', t.enum('GoTo', 'GoThrough')), ('managed', t.bool),
        ('routing_mode', t.enum('unspecified', 'Redirect')),
        ('connectors', t.list_of_names), ('device_cluster_name', t.name),
        ('device_cluster_tenant_name', t.name), ('monitored', t.bool))

    _aci_mo_name = 'vnsAbsNode'
    _tree_parent = ServiceGraph

    def __init__(self, **kwargs):
        super(ServiceGraphNode, self).__init__(
            {
                'display_name': '',
                'function_type': 'GoTo',
                'managed': True,
                'routing_mode': 'unspecified',
                'connectors': [],
                'device_cluster_name': '',
                'device_cluster_tenant_name': '',
                'monitored': False
            }, **kwargs)
class DeviceCluster(resource.AciResourceBase):
    """Represents a device-cluster and associated ACI objects.

    """

    identity_attributes = t.identity(('tenant_name', t.name), ('name', t.name))
    other_attributes = t.other(
        ('display_name', t.name),
        ('device_type', t.enum("PHYSICAL", "VIRTUAL")),
        ('service_type', t.enum("ADC", "FW", "OTHERS", "IDSIPS", "COPY")),
        ('context_aware', t.enum("single-Context", "multi-Context")),
        ('managed', t.bool), ('physical_domain_name', t.name),
        ('encap', t.string(24)),
        ('devices', t.list_of_dicts(
            ('name', t.name), ('path', t.string(512)))), ('monitored', t.bool))

    _aci_mo_name = 'vnsLDevVip'
    _tree_parent = resource.Tenant

    def __init__(self, **kwargs):
        super(DeviceCluster, self).__init__(
            {
                'display_name': '',
                'device_type': 'PHYSICAL',
                'service_type': 'OTHERS',
                'context_aware': 'single-Context',
                'managed': True,
                'physical_domain_name': '',
                'encap': '',
                'devices': [],
                'monitored': False
            }, **kwargs)
Beispiel #5
0
class BridgeDomain(AciResourceBase):
    """Resource representing a BridgeDomain in ACI.

    Identity attributes are RNs for ACI tenant and bridge-domain.
    """

    identity_attributes = t.identity(
        ('tenant_name', t.name),
        ('name', t.name))
    other_attributes = t.other(
        ('display_name', t.name),
        ('vrf_name', t.name),
        ('enable_arp_flood', t.bool),
        ('enable_routing', t.bool),
        ('limit_ip_learn_to_subnets', t.bool),
        ('ip_learning', t.bool),
        ('l2_unknown_unicast_mode', t.enum("", "flood", "proxy")),
        ('ep_move_detect_mode', t.enum("", "garp")),
        ('l3out_names', t.list_of_names),
        ('monitored', t.bool))

    _aci_mo_name = 'fvBD'
    _tree_parent = Tenant

    def __init__(self, **kwargs):
        super(BridgeDomain, self).__init__({'vrf_name': '',
                                            'enable_arp_flood': True,
                                            'enable_routing': True,
                                            'limit_ip_learn_to_subnets': False,
                                            'ip_learning': True,
                                            'l2_unknown_unicast_mode': 'proxy',
                                            'ep_move_detect_mode': 'garp',
                                            'l3out_names': [],
                                            'monitored': False},
                                           **kwargs)
Beispiel #6
0
class SecurityGroupRule(AciResourceBase):
    """Resource representing a SG subject's rule in ACI.

    Identity attributes: name of ACI tenant, name of security group, name of
    subject and name of rule
    """
    identity_attributes = t.identity(
        ('tenant_name', t.name),
        ('security_group_name', t.name),
        ('security_group_subject_name', t.name),
        ('name', t.name))
    other_attributes = t.other(
        ('display_name', t.name),
        ('direction', t.enum("", "ingress", "egress")),
        ('ethertype', t.enum("", "undefined", "ipv4", "ipv6")),
        ('remote_ips', t.list_of_strings),
        ('ip_protocol', t.string()),
        ('from_port', t.port),
        ('to_port', t.port),
        ('conn_track', t.enum('normal', 'reflexive')),
        ('monitored', t.bool))

    _aci_mo_name = 'hostprotRule'
    _tree_parent = SecurityGroupSubject

    def __init__(self, **kwargs):
        super(SecurityGroupRule, self).__init__(
            {'direction': 'ingress',
             'ethertype': "undefined",
             'remote_ips': [],
             'ip_protocol': self.UNSPECIFIED,
             'from_port': self.UNSPECIFIED,
             'to_port': self.UNSPECIFIED,
             'conn_track': 'reflexive',
             'monitored': False}, **kwargs)
Beispiel #7
0
class Subnet(AciResourceBase):
    """Resource representing a Subnet in ACI.

    Identity attributes: name of ACI tenant, name of bridge-domain and
    IP-address & mask of the default gateway in CIDR format (that is
    <gateway-address>/<prefix-len>). Helper function 'to_gw_ip_mask'
    may be used to construct the IP-address & mask value.
    """

    identity_attributes = t.identity(
        ('tenant_name', t.name),
        ('bd_name', t.name),
        ('gw_ip_mask', t.ip_cidr))
    other_attributes = t.other(
        ('scope', t.enum("", "public", "private", "shared")),
        ('display_name', t.name),
        ('monitored', t.bool))

    _aci_mo_name = 'fvSubnet'
    _tree_parent = BridgeDomain

    SCOPE_PRIVATE = 'private'
    SCOPE_PUBLIC = 'public'

    def __init__(self, **kwargs):
        super(Subnet, self).__init__({'scope': self.SCOPE_PUBLIC,
                                      'monitored': False}, **kwargs)

    @staticmethod
    def to_gw_ip_mask(gateway_ip_address, prefix_len):
        return '%s/%d' % (gateway_ip_address, prefix_len)
Beispiel #8
0
class Contract(AciResourceBase):
    """Resource representing a contract in ACI.

    Identity attributes: name of ACI tenant and name of contract.
    """

    identity_attributes = t.identity(
        ('tenant_name', t.name),
        ('name', t.name))
    other_attributes = t.other(
        ('scope', t.enum("", "tenant", "context", "global",
                         "application-profile")),
        ('display_name', t.name),
        ('monitored', t.bool))

    _aci_mo_name = 'vzBrCP'
    _tree_parent = Tenant

    SCOPE_APP_PROFILE = 'application-profile'
    SCOPE_TENANT = 'tenant'
    SCOPE_CONTEXT = 'context'
    SCOPE_GLOBAL = 'global'

    def __init__(self, **kwargs):
        super(Contract, self).__init__({'scope': self.SCOPE_CONTEXT,
                                        'monitored': False}, **kwargs)
Beispiel #9
0
class VRF(AciResourceBase):
    """Resource representing a VRF (Layer3 network context) in ACI.

    Identity attributes: name of ACI tenant, name of VRF.
    """

    identity_attributes = t.identity(
        ('tenant_name', t.name),
        ('name', t.name))
    other_attributes = t.other(
        ('display_name', t.name),
        ('policy_enforcement_pref', t.enum("", "enforced", "unenforced")),
        ('monitored', t.bool))

    _aci_mo_name = 'fvCtx'
    _tree_parent = Tenant

    POLICY_ENFORCED = 'enforced'
    POLICY_UNENFORCED = 'unenforced'

    def __init__(self, **kwargs):
        super(VRF, self).__init__(
            {'policy_enforcement_pref': self.POLICY_ENFORCED,
             'monitored': False},
            **kwargs)
class AciFault(resource.ResourceBase, OperationalResource):
    """Fault information reported by ACI."""

    LC_UNKNOWN = 0x0
    LC_SOAKING = 0x1
    LC_RETAINING = 0x10
    LC_RAISED = 0x2
    LC_SOAKING_CLEARING = 0x4
    LC_RAISED_CLEARING = 0x8

    SEV_CLEARED = 'cleared'
    SEV_INFO = 'info'
    SEV_WARNING = 'warning'
    SEV_MINOR = 'minor'
    SEV_MAJOR = 'major'
    SEV_CRITICAL = 'critical'

    _aci_mo_name = 'faultInst'
    identity_attributes = t.identity(('fault_code', t.string()),
                                     ('external_identifier', t.string()))
    other_attributes = t.other(('severity',
                                t.enum(SEV_CLEARED, SEV_CRITICAL, SEV_INFO,
                                       SEV_WARNING, SEV_MAJOR, SEV_MINOR)),
                               ('status_id', t.id), ('cause', t.string()),
                               ('description', t.string(255)))

    db_attributes = t.db(('last_update_timestamp', t.string()))

    def __eq__(self, other):
        try:
            return self.identity == other.identity
        except AttributeError:
            return False

    def __init__(self, **kwargs):
        super(AciFault, self).__init__(
            {
                'severity': self.SEV_INFO,
                'lifecycle_status': self.LC_UNKNOWN,
                'cause': '',
                'description': ""
            }, **kwargs)

    def is_error(self):
        return self.severity in [self.SEV_MAJOR, self.SEV_CRITICAL]

    @property
    def dn(self):
        return self.external_identifier

    @property
    def root(self):
        mos_and_types = utils.decompose_dn(self._aci_mo_name, self.dn)
        if mos_and_types:
            # Faults associated with unrecognized MOs will not decompose
            mo = apic_client.ManagedObjectClass(mos_and_types[0][0])
            return (mo.rn(mos_and_types[0][1])
                    if mo.rn_param_count else mo.rn())
Beispiel #11
0
class HostDomainMappingV2(resource.ResourceBase):
    """host to VMM and phys-dom mapping, version 2"""

    identity_attributes = t.identity(
        ('host_name', t.string(128)), ('domain_name', t.string(64)),
        ('domain_type', t.enum('PhysDom', 'OpenStack', 'Kubernetes',
                               'VMware')))
    other_attributes = t.other()

    def __init__(self, **kwargs):
        super(HostDomainMappingV2, self).__init__({}, **kwargs)
Beispiel #12
0
class VMMPolicy(AciRoot):

    identity_attributes = t.identity(
        ('type', t.enum("VMWare", "OpenStack", "Kubernetes")))
    other_attributes = t.other(('monitored', t.bool), ('display_name', t.name))

    _aci_mo_name = 'vmmProvP'
    _tree_parent = None

    def __init__(self, **kwargs):
        super(VMMPolicy, self).__init__({'monitored': False}, **kwargs)
Beispiel #13
0
class EndpointGroup(AciResourceBase):
    """Resource representing an endpoint-group in ACI.

    Identity attributes: name of ACI tenant, name of application-profile
    and name of endpoint-group.

    Attribute 'static_paths' is a list of dicts with the following keys:
    * path: (Required) path-name of the switch-port which is bound to
            EndpointGroup
    * encap: (Required) encapsulation mode and identifier for
            this EndpointGroup on the specified switch-port. Must be specified
            in the format 'vlan-<vlan-id>' for VLAN encapsulation
    """
    identity_attributes = t.identity(
        ('tenant_name', t.name),
        ('app_profile_name', t.name),
        ('name', t.name))
    other_attributes = t.other(
        ('display_name', t.name),
        ('bd_name', t.name),
        ('policy_enforcement_pref', t.enum("", "enfFAorced", "unenforced")),
        ('provided_contract_names', t.list_of_names),
        ('consumed_contract_names', t.list_of_names),
        ('openstack_vmm_domain_names', t.list_of_names),
        ('physical_domain_names', t.list_of_names),
        ('vmm_domains', t.list_of_dicts(('type', t.name), ('name', t.name))),
        ('physical_domains', t.list_of_dicts(('name', t.name))),
        ('static_paths', t.list_of_static_paths),
        ('epg_contract_masters', t.list_of_dicts(('app_profile_name', t.name),
                                                 ('name', t.name))),
        ('monitored', t.bool),
        ('sync', t.bool))

    _aci_mo_name = 'fvAEPg'
    _tree_parent = ApplicationProfile

    POLICY_UNENFORCED = 'unenforced'
    POLICY_ENFORCED = 'enforced'

    def __init__(self, **kwargs):
        super(EndpointGroup, self).__init__({'bd_name': '',
                                             'provided_contract_names': [],
                                             'consumed_contract_names': [],
                                             'openstack_vmm_domain_names': [],
                                             'physical_domain_names': [],
                                             'vmm_domains': [],
                                             'physical_domains': [],
                                             'policy_enforcement_pref':
                                             self.POLICY_UNENFORCED,
                                             'static_paths': [],
                                             'epg_contract_masters': [],
                                             'monitored': False,
                                             'sync': True},
                                            **kwargs)
Beispiel #14
0
class VMMController(AciResourceBase):
    """Resource representing a VMM controller profile in ACI.

    Identity attributes: VMM domain type, VMM domain name, controller name.
    """
    identity_attributes = t.identity(
        ('domain_type', t.name),
        ('domain_name', t.name),
        ('name', t.name))
    other_attributes = t.other(
        ('display_name', t.name),
        ('scope', t.enum('unmanaged', 'vm', 'iaas', 'network',
                         'MicrosoftSCVMM', 'openstack', 'kubernetes')),
        ('root_cont_name', t.name),
        ('host_or_ip', t.name),
        ('mode', t.enum('default', 'n1kv', 'unknown', 'ovs', 'k8s')),
        ('monitored', t.bool))

    _aci_mo_name = 'vmmCtrlrP'
    _tree_parent = VMMDomain

    def __init__(self, **kwargs):
        defaults = {'monitored': False,
                    'scope': 'vm',
                    'root_cont_name': '',
                    'host_or_ip': '',
                    'mode': 'default'}
        vmm_type = kwargs.get('domain_type')
        if vmm_type == 'Kubernetes':
            defaults['scope'] = 'kubernetes'
            defaults['mode'] = 'k8s'
        elif vmm_type == 'OpenStack':
            defaults['scope'] = 'openstack'
            defaults['mode'] = 'ovs'
        name = kwargs.get('name')
        if name:
            defaults['root_cont_name'] = name
            defaults['host_or_ip'] = name
        super(VMMController, self).__init__(defaults, **kwargs)
Beispiel #15
0
class ActionLog(api_res.ResourceBase):
    CREATE = 'create'
    DELETE = 'delete'
    RESET = 'reset'

    identity_attributes = t.identity(('uuid', t.string(64)))
    other_attributes = t.other(
        ('action', t.enum(CREATE, DELETE, RESET)),
        ('object_type', t.string(50)),
        ('object_dict', t.string()),
        ('root_rn', t.string(64)),
    )
    db_attributes = t.db(('timestamp', t.string()), ('id', t.integer))

    def __init__(self, **kwargs):
        super(ActionLog, self).__init__({'uuid': utils.generate_uuid()},
                                        **kwargs)
Beispiel #16
0
class VmmInjectedService(AciResourceBase):
    """Resource representing a VMM injected service in ACI.

    Identity attributes: VMM domain type, VMM domain name, controller name,
    namespace name and service name.
    """
    identity_attributes = t.identity(
        ('domain_type', t.name),
        ('domain_name', t.name),
        ('controller_name', t.name),
        ('namespace_name', t.name),
        ('name', t.name))
    other_attributes = t.other(
        ('display_name', t.name),
        ('service_type', t.enum('clusterIp', 'externalName', 'nodePort',
                                'loadBalancer')),
        ('cluster_ip', t.string()),
        ('load_balancer_ip', t.string()),
        ('service_ports', t.list_of_dicts(('port', t.ports),
                                          ('protocol', t.string(32)),
                                          ('target_port', t.string(32)),
                                          ('node_port', t.ports))),
        ('endpoints', t.list_of_dicts(('ip', t.string()),
                                      ('pod_name', t.name))))
    db_attributes = t.db(('guid', t.string()))

    _aci_mo_name = 'vmmInjectedSvc'
    _tree_parent = VmmInjectedNamespace

    def __init__(self, **kwargs):
        super(VmmInjectedService, self).__init__(
            {'service_type': 'clusterIp',
             'cluster_ip': '0.0.0.0',
             'load_balancer_ip': '0.0.0.0',
             'service_ports': [],
             'endpoints': [],
             'guid': ''},
            **kwargs)
Beispiel #17
0
class VMMDomain(AciResourceBase):
    """Resource representing a VMM domain.

    Identity attributes: VMM type (eg. Openstack) and name
    """

    identity_attributes = t.identity(
        ('type', t.enum("VMWare", "OpenStack", "Kubernetes")),
        ('name', t.name))
    other_attributes = t.other(
        ('monitored', t.bool), ('display_name', t.name),
        ('enforcement_pref', t.enum('sw', 'hw', 'unknown')),
        ('mode', t.enum('default', 'n1kv', 'unknown', 'ovs', 'k8s')),
        ('mcast_address', t.string()),
        ('encap_mode', t.enum('unknown', 'vlan', 'vxlan')),
        ('pref_encap_mode', t.enum('unspecified', 'vlan', 'vxlan')),
        ('vlan_pool_name', t.name),
        ('vlan_pool_type', t.enum('static', 'dynamic')),
        ('mcast_addr_pool_name', t.name))

    _aci_mo_name = 'vmmDomP'
    _tree_parent = VMMPolicy

    def __init__(self, **kwargs):
        defaults = {
            'monitored': False,
            'enforcement_pref': 'hw',
            'mode': 'default',
            'mcast_address': '0.0.0.0',
            'encap_mode': 'unknown',
            'pref_encap_mode': 'unspecified',
            'vlan_pool_name': '',
            'vlan_pool_type': 'dynamic',
            'mcast_addr_pool_name': ''
        }
        vmm_type = kwargs.get('type')
        if vmm_type == 'Kubernetes':
            defaults['enforcement_pref'] = 'sw'
            defaults['mode'] = 'k8s'
        elif vmm_type == 'OpenStack':
            defaults['enforcement_pref'] = 'sw'
            defaults['mode'] = 'ovs'
        if kwargs.get('encap_mode') and kwargs['encap_mode'] != 'unknown':
            defaults['pref_encap_mode'] = kwargs['encap_mode']
        super(VMMDomain, self).__init__(defaults, **kwargs)
class AciStatus(resource.ResourceBase, OperationalResource):
    """Status of an AIM resource that is mapped to ACI object.

    Following attributes are available:
    * sync_status - Indicates whether ACI object was created/updated
    * sync_message - Informational or error message related to ACI
                     object creation/update
    * health_score - Health score of ACI object as reported by APIC
    * health_level - Level-wise classification of health-score
    * faults - List of AciFault objects as reported by APIC
    """

    # ACI object create/update is pending
    SYNC_PENDING = 'sync_pending'
    # ACI object was created/updated. It may or may not be in healthy state
    SYNCED = 'synced'
    # Create/update of ACI object failed
    SYNC_FAILED = 'sync_failed'
    SYNC_NA = 'N/A'

    identity_attributes = t.identity(('resource_type', t.string()),
                                     ('resource_id', t.id),
                                     ('resource_root', t.name))
    other_attributes = t.other(
        ('sync_status', t.enum(SYNCED, SYNC_PENDING, SYNC_FAILED)),
        ('sync_message', t.string()), ('health_score', t.number),
        ('faults', t.list_of_strings))
    db_attributes = t.db(('id', t.string(36)))

    HEALTH_POOR = "Poor Health Score"
    HEALTH_FAIR = "Fair Health Score"
    HEALTH_GOOD = "Good Health Score"
    HEALTH_EXCELLENT = "Excellent Health Score"

    def __init__(self, **kwargs):
        super(AciStatus, self).__init__(
            {
                'resource_type': None,
                'resource_id': None,
                'sync_status': self.SYNC_NA,
                'sync_message': '',
                'health_score': 100,
                'faults': []
            }, **kwargs)
        self._parent_class = None

    @property
    def health_level(self):
        if self.health_score > 90:
            return self.HEALTH_EXCELLENT
        elif self.health_score > 75:
            return self.HEALTH_GOOD
        elif self.health_score > 50:
            return self.HEALTH_FAIR
        else:
            return self.HEALTH_POOR

    @property
    def parent_class(self):
        if not self._parent_class:
            for path in resource_paths:
                try:
                    self._parent_class = importutils.import_class(
                        path + '.%s' % self.resource_type)
                except ImportError:
                    continue
        return self._parent_class

    @property
    def root(self):
        return self.resource_root

    def is_build(self):
        return self.sync_status in [self.SYNC_PENDING, self.SYNC_NA]

    def is_error(self):
        return (self.sync_status == self.SYNC_FAILED
                or self.health_level == self.HEALTH_POOR
                or [f for f in self.faults if f.is_error()])
Beispiel #19
0
class AciFault(resource.ResourceBase, OperationalResource):
    """Fault information reported by ACI."""

    LC_UNKNOWN = 0x0
    LC_SOAKING = 0x1
    LC_RETAINING = 0x10
    LC_RAISED = 0x2
    LC_SOAKING_CLEARING = 0x4
    LC_RAISED_CLEARING = 0x8

    SEV_CLEARED = 'cleared'
    SEV_INFO = 'info'
    SEV_WARNING = 'warning'
    SEV_MINOR = 'minor'
    SEV_MAJOR = 'major'
    SEV_CRITICAL = 'critical'

    _aci_mo_name = 'faultInst'
    identity_attributes = t.identity(('fault_code', t.string()),
                                     ('external_identifier', t.string()))
    other_attributes = t.other(('severity',
                                t.enum(SEV_CLEARED, SEV_CRITICAL, SEV_INFO,
                                       SEV_WARNING, SEV_MAJOR, SEV_MINOR)),
                               ('status_id', t.id), ('cause', t.string()),
                               ('description', t.string(255)))

    db_attributes = t.db(('last_update_timestamp', t.string()))

    def __eq__(self, other):
        try:
            return self.identity == other.identity
        except AttributeError:
            return False

    # An object is hashable if it has a hash value which never changes during
    # its lifetime (it needs a __hash__() method), and can be compared to
    # other objects (it needs an __eq__() or __cmp__() method).
    # Hashable objects which compare equal must have the same hash value.
    #
    # If you define __eq__() , the default __hash__() (namely, hashing the
    # address of the object in memory) goes away.
    # So for each class defining __eq__() we must also
    # define __hash__() even though parent class has __hash__().
    def __hash__(self):
        return super(AciFault, self).__hash__()

    def __init__(self, **kwargs):
        super(AciFault, self).__init__(
            {
                'severity': self.SEV_INFO,
                'lifecycle_status': self.LC_UNKNOWN,
                'cause': '',
                'description': ""
            }, **kwargs)

    def is_error(self):
        return self.severity in [self.SEV_MAJOR, self.SEV_CRITICAL]

    @property
    def dn(self):
        return self.external_identifier

    @property
    def root(self):
        mos_and_types = utils.decompose_dn(self._aci_mo_name, self.dn)
        if mos_and_types:
            # Faults associated with unrecognized MOs will not decompose
            mo = apic_client.ManagedObjectClass(mos_and_types[0][0])
            return (mo.rn(mos_and_types[0][1])
                    if mo.rn_param_count else mo.rn())