def create(cls, name, cluster_virtual, network_value, macaddress,
               interface_id, nodes, vlan_id=None, cluster_mode='balancing',
               backup_mgt=None, primary_heartbeat=None, log_server_ref=None,
               domain_server_address=None, location_ref=None, zone_ref=None,
               default_nat=False, enable_antivirus=False, enable_gti=False,
               comment=None, snmp=None, **kw):
        """
        Create a layer 3 firewall cluster with management interface and any number
        of nodes. If providing keyword arguments to create additional interfaces,
        use the same constructor arguments and pass an `interfaces` keyword argument.
        The constructor defined interface will be assigned as the primary
        management interface by default. Otherwise the engine will be created with a
        single interface and interfaces can be added after.
        
        .. versionchanged:: 0.6.1
            Chgnged `cluster_nic` to `interface_id`, and `cluster_mask` to `network_value`
        
        :param str name: name of firewall engine
        :param str cluster_virtual: ip of cluster CVI
        :param str network_value: ip netmask of cluster CVI
        :param str macaddress: macaddress for packet dispatch clustering
        :param str interface_id: nic id to use for primary interface
        :param list nodes: address/network_value/nodeid combination for cluster nodes
        :param str vlan_id: optional VLAN id for the management interface, i.e. '15'.
        :param str cluster_mode: 'balancing' or 'standby' mode (default: balancing)
        :param str,int primary_heartbeat: optionally set the primary_heartbeat. This is
            automatically set to the management interface but can be overridden to use
            another interface if defining additional interfaces using `interfaces`.
        :param str,int backup_mgt: optionally set the backup management interface. This
            is unset unless you define additional interfaces using `interfaces`.
        :param str log_server_ref: (optional) href to log_server instance 
        :param list domain_server_address: (optional) DNS server addresses
        :param str location_ref: location href or not for engine if needed to contact SMC
            behind NAT (created if not found)
        :param str zone_ref: zone name, str href or Zone for management interface
            (created if not found)
        :param bool enable_antivirus: (optional) Enable antivirus (required DNS)
        :param bool enable_gti: (optional) Enable GTI
        :param list interfaces: optional keyword to supply additional interfaces
        :param dict snmp: SNMP dict should have keys `snmp_agent` str defining name of SNMPAgent,
            `snmp_interface` which is a list of interface IDs, and optionally `snmp_location` which
            is a string with the SNMP location name.
        :raises CreateEngineFailed: Failure to create with reason
        :return: :py:class:`smc.core.engine.Engine`

        Example nodes parameter input::

            [{'address':'5.5.5.2', 'network_value':'5.5.5.0/24', 'nodeid':1},
             {'address':'5.5.5.3', 'network_value':'5.5.5.0/24', 'nodeid':2},
             {'address':'5.5.5.4', 'network_value':'5.5.5.0/24', 'nodeid':3}]
        
        You can also create additional CVI+NDI, or NDI only interfaces by providing
        the keyword argument interfaces using the same keyword values from the
        constructor::
        
            interfaces=[
               {'interface_id': 1,
                'macaddress': '02:02:02:02:02:03',
                'interfaces': [{'cluster_virtual': '2.2.2.1',
                                'network_value': '2.2.2.0/24',
                                'nodes':[{'address': '2.2.2.2', 'network_value': '2.2.2.0/24', 'nodeid': 1},
                                         {'address': '2.2.2.3', 'network_value': '2.2.2.0/24', 'nodeid': 2}]
                              }]
                },
               {'interface_id': 2,
                'interfaces': [{'nodes':[{'address': '3.3.3.2', 'network_value': '3.3.3.0/24', 'nodeid': 1},
                                         {'address': '3.3.3.3', 'network_value': '3.3.3.0/24', 'nodeid': 2}]
                              }]
                }]
        
        It is also possible to define VLAN interfaces by providing the `vlan_id` keyword.
        Example VLAN with NDI only interfaces. If nesting the zone_ref within the interfaces
        list, the zone will be applied to the VLAN versus the top level interface::
        
            interfaces=[
               {'interface_id': 2,
                'interfaces': [{'nodes':[{'address': '3.3.3.2', 'network_value': '3.3.3.0/24', 'nodeid': 1},
                                         {'address': '3.3.3.3', 'network_value': '3.3.3.0/24', 'nodeid': 2}],
                                'vlan_id': 22,
                                'zone_ref': 'private-network'
                              },
                              {'nodes': [{'address': '4.4.4.1', 'network_value': '4.4.4.0/24', 'nodeid': 1},
                                         {'address': '4.4.4.2', 'network_value': '4.4.4.0/24', 'nodeid': 2}],
                               'vlan_id': 23,
                               'zone_ref': 'other_vlan'
                            }]
            }]
        
        Tunnel interfaces can also be created. As all interfaces defined are assumed to be
        a physical interface type, you must specify the `type` parameter to indicate the
        interface is a tunnel interface. Tunnel interfaces do not have a macaddress or VLANs.
        They be configured with NDI interfaces by omitting the `cluster_virtual` and
        `network_value` top level attributes::
        
            interfaces=[
                {'interface_id': 1000,
                 'interfaces': [{'cluster_virtual': '100.100.100.1',
                                 'network_value': '100.100.100.0/24',
                                 'nodes':[{'address': '100.100.100.2', 'network_value': '100.100.100.0/24', 'nodeid': 1},
                                          {'address': '100.100.100.3', 'network_value': '100.100.100.0/24', 'nodeid': 2}]
                               }],
                 'zone_ref': 'AWStunnel',
                 'type': 'tunnel_interface'
                }]
        
        If setting primary_heartbeat or backup_mgt to a specific interface (the primary
        interface configured in the constructor will have these roles by default), you
        must define the interfaces in the `interfaces` keyword argument list.
           
        .. note:: If creating additional interfaces, you must at minimum provide the
            `interface_id` and `nodes` to create an NDI only interface.
                                
        """
        interfaces = kw.pop('interfaces', [])
        # Add the primary interface to the interface list
        interface = {'cluster_virtual': cluster_virtual,
                     'network_value': network_value,
                     'nodes': nodes}
        if vlan_id:
            interface.update(vlan_id=vlan_id)
        
        interfaces.append(dict(
            interface_id=interface_id,
            macaddress=macaddress,
            zone_ref=zone_ref,
            interfaces=[interface]))
        
        primary_mgt = interface_id if not vlan_id else '{}.{}'.format(interface_id, vlan_id)
        
        return FirewallCluster.create_bulk(
            name, interfaces=interfaces, nodes=len(nodes),
            cluster_mode=cluster_mode, primary_mgt=primary_mgt,
            backup_mgt=backup_mgt, primary_heartbeat=primary_heartbeat, 
            log_server_ref=log_server_ref,
            domain_server_address=domain_server_address,
            location_ref=location_ref, default_nat=default_nat,
            enable_antivirus=enable_antivirus, enable_gti=enable_gti,
            comment=comment, snmp=snmp, **kw)