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)
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)
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)
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)
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)
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())
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)
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)
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)
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)
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)
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)
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()])
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())