> For the complete documentation index, see [llms.txt](https://docs.platform9.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.platform9.com/private-cloud-director/virtualized-networking/layer-2-networking.md).

# Layer 2 Networking

{% hint style="info" %}
Layer 2 Network is a beta feature in the 2026.4 release. Please contact the support team for further details.
{% endhint %}

A Layer 2 Network (L2 Network) is an L2-only physical network that provides basic Layer 2 connectivity between virtual machines, without managed IP addressing, routing, or security services. Layer 2 Networks are available only when creating Physical Networks. Virtual Networks are always Managed Networks and do not have an L2 option.

Use a Layer 2 Network when your infrastructure already handles IP management externally, or when you are migrating workloads from VMware and want equivalent L2 behaviour without adopting managed networking. If you need subnets, DHCP, routers, or security groups, use a managed [Virtual Network](/private-cloud-director/virtualized-networking/networks-and-ports.md) or [Physical Network](/private-cloud-director/virtualized-networking/physical-network.md) instead.

### How Layer 2 Networks Work

Layer 2 Networks provide pure Layer 2 connectivity between VMs. This means:

* **No managed IP addressing.** You configure IP addresses directly inside the guest OS using static assignment or an external DHCP server.
* **No routing.** VMs on the same Layer 2 Network communicate at Layer 2. Cross-network traffic requires external routing infrastructure.
* **No security groups.** Port-level security is managed outside of <code class="expression">space.vars.product\_name</code>.
* **No subnet configuration.** Layer 2 Networks operate only at the data link layerCreate a Layer 2 Network

### **Prerequisites**

* A physical network must be configured in your cluster blueprint. See [Cluster Blueprint](/private-cloud-director/virtualized-clusters/virtualized-cluster-blueprint.md)
* The VLAN ID you specify must exist on your physical network infrastructure.

Perform the following steps.

1. On the <code class="expression">space.vars.product\_name</code> UI , navigate to **Networks and Security > Networks**.
2. Select **Create Network** and then select **Physical Network**.
3. Under **Basic Information**, enter the following details.

<table><thead><tr><th width="196.56640625">Field</th><th>Description</th></tr></thead><tbody><tr><td>Name</td><td>Enter a name for the network.</td></tr><tr><td>Description</td><td>Optionally, enter a description.</td></tr><tr><td>Admin State</td><td>Select <strong>Up</strong> to make the network available for VM provisioning immediately, or <strong>Down</strong> to defer availability.</td></tr><tr><td>MTU</td><td>Optionally, set the maximum transmission unit. Minimum value is <code>68</code> for IPv4 and <code>1280</code> for IPv6.</td></tr></tbody></table>

4. Under **Network Type**, select **Layer 2 Network**.

{% hint style="info" %}
**NOTE**\
Selecting **Layer 2 Network** hides all subnets, DHCP, router, security groups, and public IP fields. These are not applicable to Layer 2 Networks. If you choose to configure these instances, configure the **Network Type** to **Managed Network**.
{% endhint %}

5. Enter the following details.

<table><thead><tr><th width="226.96484375">Field</th><th>Description</th></tr></thead><tbody><tr><td>Network Label</td><td>Select the network label that maps this network to the corresponding physical network on your hypervisors.</td></tr><tr><td>Network Type</td><td>Select <strong>Flat (Untagged)</strong> for a network with no VLAN tags, or <strong>VLAN (Tagged)</strong> for a network that uses VLAN tagging.</td></tr></tbody></table>

6. Optionally, select **Make Shared (Across All Tenants)** to make the network type available to every tenant. Only the tenant that creates the network can change this setting later.
7. Select **Create Physical Network**.

The network appears in **Networks and Security > Networks** with a **Layer 2 Network** tag corresponding to the network name.

#### **Using pcdctl CLI**

```bash
pcdctl network create \
    --provider-physical-network PHYSICAL_NETWORK_LABEL  \
    --provider-network-type NETWORK_TYPE \
    --provider-segment VLAN_TAG \
    --tag simple_network \
    --disable-port-security \
    NETWORK_NAME
```

<table><thead><tr><th width="275.3828125">Parameter</th><th>Description</th></tr></thead><tbody><tr><td><code>PHYSICAL_NETWORK_LABEL</code></td><td>The label configured in the blueprint.</td></tr><tr><td><code>NETWORK_TYPE</code></td><td>Either <code>vlan</code> or <code>flat</code>.</td></tr><tr><td><code>VLAN_TAG</code></td><td>The VLAN tag. Only required if <code>NETWORK_TYPE</code> is <code>vlan</code>.</td></tr><tr><td><code>NETWORK_NAME</code></td><td>The name you want to assign to the network.</td></tr></tbody></table>

The `--disable-port-security` option is required for L2-only networks because port security is a Layer 3 feature and does not apply to L2-only networks.

On a successful network creation, you should see a similar output.

<pre class="language-bash"><code class="lang-bash"><strong>$ pcdctl network create \
</strong>    --provider-network-type vlan \
    --provider-segment 1234 \
    --provider-physical-network physnet \
    --tag simple_network \
    --disable-port-security \
    my-net
<strong>+---------------------------+--------------------------------------+
</strong>| Field                     | Value                                |
+---------------------------+--------------------------------------+
| admin_state_up            | UP                                   |
| availability_zone_hints   |                                      |
| availability_zones        |                                      |
| created_at                | 2026-03-05T18:58:02Z                 |
| description               |                                      |
| dns_domain                |                                      |
| id                        | c2d9b7a4-88e0-480b-99a3-576ce202adf2 |
| ipv4_address_scope        | None                                 |
| ipv6_address_scope        | None                                 |
| is_default                | False                                |
| is_vlan_qinq              | None                                 |
| is_vlan_transparent       | None                                 |
| mtu                       | 9000                                 |
| name                      | my-net                         |
| port_security_enabled     | false                                 |
| project_id                | 635d175b6dec4b44899acd475a837cfc     |
| provider:network_type     | vlan                                 |
| provider:physical_network | physnet                              |
| provider:segmentation_id  | 1234                                 |
| qos_policy_id             | None                                 |
| revision_number           | 1                                    |
| router:external           | Internal                             |
| segments                  | None                                 |
| shared                    | False                                |
| status                    | ACTIVE                               |
| subnets                   |                                      |
| tags                      | simple_network                              |
| tenant_id                 | 034e5250cf6f48baaf59ffba6bea08b3     |
| updated_at                | 2026-03-05T18:58:02Z                 |
+---------------------------+--------------------------------------+
</code></pre>

### Deploy a VM on a Layer 2 Network

You can configure a VM for a Layer 2 Network when deploying a new VM from the Virtual Machines section.

1. Navigate to **Virtual Machines > Virtual Machines**.
2. Select **Deploy New VM** and proceed through the VM creation wizard.
3. On **Select Network Type**, choose **Layer 2 Network**.
4. Select the Layer 2 Network you want to use from the list.\
   Managed Network options show IP configuration fields. Layer 2 Network selection hides all IP configuration fields.
5. Select **Next Step** to continue creating the VM.

{% hint style="info" %}
**NOTE**

When deploying a VM on a Layer 2 Network:

* The security group field is disabled and cannot be changed.
* You can only create one VM at a time. To create multiple VMs on the same Layer 2 Network, repeat the deployment process for each VM.
  {% endhint %}

6. Complete the remaining VM configuration and select **Deploy**.

After deployment, the VM instance details the following for the network attachment:

* **Network**: `[Network Name] (Layer 2)`
* **IP Address**: `N/A — Configure in guest OS`

{% hint style="info" %}
**NOTE**

* **External DHCP configuration:** If using an external DHCP server for IP assignment, ensure the DHCP server is reachable in the L2 network's broadcast domain.
* **Cloud-init workaround for network configuration**: There is a known issue with [setting network configurations in cloud-init](https://docs.cloud-init.io/en/latest/reference/network-config.html). As a workaround, use the `runcmd` [section of cloud-init](https://docs.cloud-init.io/en/latest/reference/yaml_examples/boot_cmds.html) to configure static IP or DHCP.
  {% endhint %}

Here is an example for an Ubuntu VM.

{% hint style="info" %}
**NOTE**

You may need to make changes to make this work for other operating systems.
{% endhint %}

<pre class="language-yaml"><code class="lang-yaml"><strong>runcmd:
</strong>  - |
    cat &#x3C;/etc/netplan/99-static.yaml
    network:
      version: 2
      ethernets:
        ens3:
          dhcp4: false
          addresses:
            - 10.10.10.50/24
          gateway4: 10.10.10.1
          nameservers:
            addresses: [8.8.8.8, 8.8.4.4]
    EOF
  - netplan apply
</code></pre>

#### **Using pcdctl CLI**

Create the L2-only port that will be associated with the VM:

```bash
pcdctl port create \
    --network NETWORK_NAME_OR_ID \
    --disable-port-security \
    --no-fixed-ip \
    --binding-profile '{"l2-port": true}' \
    PORT_NAME
```

This command returns the port ID upon successful creation.

Here is an example of the output.

```bash
pcdctl port create \
    --network my-net \   
    --disable-port-security \
    --no-fixed-ip \
    --binding-profile '{"l2-port": true}' \
    my-l2-port
+-------------------------+--------------------------------------+
| Field                   | Value                                |
+-------------------------+--------------------------------------+
| admin_state_up          | UP                                   |
| allowed_address_pairs   |                                      |
| binding_host_id         |                                      |
| binding_profile         | l2-port=true                       |
| binding_vif_details     |                                      |
| binding_vif_type        | unbound                              |
| binding_vnic_type       | normal                               |
| created_at              | 2026-03-05T22:11:58Z                 |
| data_plane_status       | None                                 |
| description             |                                      |
| device_id               |                                      |
| device_owner            |                                      |
| device_profile          | None                                 |
| dns_assignment          |                                      |
| dns_domain              |                                      |
| dns_name                |                                      |
| extra_dhcp_opts         |                                      |
| fixed_ips               |                                      |
| hardware_offload_type   | None                                 |
| hints                   |                                      |
| id                      | f86dd5d6-fd59-4a84-a0e9-1c2b9722a582 |
| ip_allocation           | None                                 |
| mac_address             | fa:16:3e:dd:12:a6                    |
| name                    | my-l2-port                           |
| network_id              | c2d9b7a4-88e0-480b-99a3-576ce202adf2 |
| numa_affinity_policy    | None                                 |
| port_security_enabled   | False                                |
| project_id              | 635d175b6dec4b44899acd475a837cfc     |
| propagate_uplink_status | None                                 |
| resource_request        | None                                 |
| revision_number         | 1                                    |
| qos_network_policy_id   | None                                 |
| qos_policy_id           | None                                 |
| security_group_ids      |                                      |
| status                  | DOWN                                 |
| tags                    |                                      |
| trunk_details           | None                                 |
| updated_at              | 2026-03-05T22:11:58Z                 |
+-------------------------+--------------------------------------+
```

Attach the port created and create a VM:

```bash
pcdctl server create \
    --flavor  \
    --image  \
    --nic port-id=PORT_ID_FROM_ABOVE \
    VM_NAME
```

Here is an example.

```bash
pcdctl server create \
    --flavor m1.tiny \
    --image 889fb5f1-f1cf-44d7-a12a-6fb42d4d1e60 \
    --nic port-id=f86dd5d6-fd59-4a84-a0e9-1c2b9722a582 \
    my-vm
+--------------------------------------+---------------------------------------------------------------------+
| Field                                | Value                                                               |
+--------------------------------------+---------------------------------------------------------------------+
| OS-DCF:diskConfig                    | MANUAL                                                              |
| OS-EXT-AZ:availability_zone          |                                                                     |
| OS-EXT-SRV-ATTR:host                 | None                                                                |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | None                                                                |
| OS-EXT-SRV-ATTR:instance_name        |                                                                     |
| OS-EXT-STS:power_state               | NOSTATE                                                             |
| OS-EXT-STS:task_state                | scheduling                                                          |
| OS-EXT-STS:vm_state                  | building                                                            |
| OS-SRV-USG:launched_at               | None                                                                |
| OS-SRV-USG:terminated_at             | None                                                                |
| accessIPv4                           |                                                                     |
| accessIPv6                           |                                                                     |
| addresses                            |                                                                     |
| adminPass                            | dLC4vKgnNgEF                                                        |
| config_drive                         |                                                                     |
| created                              | 2026-03-05T22:22:09Z                                                |
| flavor                               | m1.tiny (6f3d4b95-fa8e-49c1-a494-4f338f72871d)                      |
| hostId                               |                                                                     |
| id                                   | 99b3addc-0fcb-44e3-a54c-14edfa915375                                |
| image                                | cirros-0.6.2-x86_64-disk.img (889fb5f1-f1cf-44d7-a12a-6fb42d4d1e60) |
| key_name                             | None                                                                |
| name                                 | my-vm                                                               |
| os-extended-volumes:volumes_attached | []                                                                  |
| progress                             | 0                                                                   |
| project_id                           | 635d175b6dec4b44899acd475a837cfc                                    |
| properties                           |                                                                     |
| security_groups                      | name='default'                                                      |
| status                               | BUILD                                                               |
| updated                              | 2026-03-05T22:22:09Z                                                |
| user_id                              | a2dc5954fe2540a8b1825beb76834e12                                    |
+--------------------------------------+---------------------------------------------------------------------+
```

### Integrate with an external IPAM or DHCP provider

Because Layer 2 Networks do not provide managed IP addressing, you can plug in any external IP Address Management (IPAM) or DHCP system to assign addresses to VMs. <code class="expression">space.vars.product\_name</code> does not communicate with the IPAM or DHCP server directly — the integration happens entirely at Layer 2. VMs broadcast standard DHCP discovery on the L2 segment, and your existing IPAM/DHCP infrastructure responds.

#### Requirements

* **Reachability.** The DHCP server, or a DHCP relay configured to forward to it, must be reachable in the same Layer 2 broadcast domain as the Layer 2 Network. If the server lives on a different subnet, configure a DHCP relay (`ip helper-address` or equivalent) on the upstream switch or router so `DISCOVER` and `REQUEST` packets reach it.
* **VLAN alignment.** The VLAN ID configured on the Layer 2 Network must match the VLAN that your DHCP server or relay listens on.
* **MAC addresses (reservations only).** Dynamic leases work without any prior coordination — the DHCP server learns each VM's MAC address from the `DISCOVER` packet. You only need to share MAC addresses with your IPAM in advance if you are pre-creating MAC-to-IP reservations. Retrieve a port's MAC address from the **Ports** view in the UI, or via `pcdctl port show PORT_ID`.
* **Guest support.** The guest OS must request a DHCP lease on its primary interface. Most cloud images do this by default, but an image with a static-IP configuration or an overridden cloud-init network config will not.

#### Provider setup

Refer to your IPAM/DHCP vendor's own documentation for the configuration steps. The following providers are commonly used with Layer 2 Networks:

* **Infoblox NIOS** — create a DHCP range or fixed-address objects scoped to the VLAN backing the Layer 2 Network. See [Configuring DHCP Overview](https://docs.infoblox.com/space/nios90/280404503) and [Configuring Infoblox DHCP Services](https://docs.infoblox.com/space/nios85/35417345/Configuring+Infoblox+DHCP+Services) in the Infoblox NIOS documentation.
* **Microsoft Windows Server DHCP** — create a DHCP scope on the matching VLAN. Reservations can be keyed to the VM port MAC address. See [Install and configure DHCP Server on Windows Server](https://learn.microsoft.com/en-us/windows-server/networking/technologies/dhcp/quickstart-install-configure-dhcp-server) and [Deploy DHCP Using Windows PowerShell](https://learn.microsoft.com/en-us/windows-server/networking/technologies/dhcp/dhcp-deploy-wps).

If the DHCP server is on a different subnet from the Layer 2 Network's broadcast domain, you will also need a relay agent — for example, see [Install DHCP relay agent for Windows Server](https://learn.microsoft.com/en-us/windows-server/networking/technologies/dhcp/dhcp-deploy-relay-agent).

If your guest OS cannot use DHCP, or you need an address assigned before the first network packet leaves the VM, use the static-IP cloud-init workflow described next instead.

### Using API:

## Create network

> Creates a network.

```json
{"openapi":"3.0.3","info":{"title":"Networking API","version":"2.0"},"tags":[{"name":"Networks","description":"Virtual network management operations"}],"servers":[{"url":"https://{host}/neutron","description":"PCD Network API v2.0","variables":{"host":{"default":"example.platform9.com","description":"The PCD controlplane hostname"}}}],"security":[{"pcdAuth":[]}],"components":{"securitySchemes":{"pcdAuth":{"name":"X-Auth-Token","type":"apiKey","in":"header","description":"PCD Identity Service token authentication"}},"schemas":{"NetworkCreateRequest":{"type":"object","properties":{"network":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"admin_state_up":{"default":true,"type":"boolean"},"shared":{"default":false,"type":"boolean"},"project_id":{"format":"uuid","type":"string"},"tenant_id":{"format":"uuid","type":"string"},"provider:network_type":{"type":"string"},"provider:physical_network":{"type":"string"},"provider:segmentation_id":{"type":"integer"},"mtu":{"type":"integer"},"port_security_enabled":{"type":"boolean"},"dns_domain":{"type":"string"},"qos_policy_id":{"format":"uuid","type":"string"},"router:external":{"type":"boolean"},"vlan_transparent":{"type":"boolean"},"is_default":{"type":"boolean"},"availability_zone_hints":{"type":"array","items":{"type":"string"}},"segments":{"type":"array","items":{"$ref":"#/components/schemas/NetworkSegment"}}}}}},"NetworkSegment":{"type":"object","properties":{"provider:network_type":{"type":"string"},"provider:physical_network":{"type":"string"},"provider:segmentation_id":{"type":"integer"}}},"NetworkResponse":{"type":"object","properties":{"network":{"$ref":"#/components/schemas/Network"}}},"Network":{"type":"object","properties":{"id":{"format":"uuid","type":"string","readOnly":true},"name":{"type":"string"},"description":{"type":"string"},"admin_state_up":{"type":"boolean"},"status":{"enum":["ACTIVE","BUILD","DOWN","ERROR"],"type":"string","readOnly":true},"shared":{"type":"boolean"},"project_id":{"format":"uuid","type":"string"},"tenant_id":{"format":"uuid","type":"string"},"subnets":{"type":"array","items":{"format":"uuid","type":"string"},"readOnly":true},"router:external":{"type":"boolean"},"provider:network_type":{"enum":["flat","vlan","vxlan","gre","local"],"type":"string"},"provider:physical_network":{"type":"string"},"provider:segmentation_id":{"type":"integer"},"mtu":{"minimum":68,"type":"integer"},"port_security_enabled":{"type":"boolean"},"dns_domain":{"type":"string"},"qos_policy_id":{"format":"uuid","type":"string"},"availability_zone_hints":{"type":"array","items":{"type":"string"}},"availability_zones":{"type":"array","items":{"type":"string"},"readOnly":true},"ipv4_address_scope":{"format":"uuid","type":"string"},"ipv6_address_scope":{"format":"uuid","type":"string"},"l2_adjacency":{"type":"boolean","readOnly":true},"vlan_transparent":{"type":"boolean"},"qinq":{"type":"boolean"},"is_default":{"type":"boolean"},"segments":{"type":"array","items":{"$ref":"#/components/schemas/NetworkSegment"}},"tags":{"type":"array","items":{"type":"string"}},"revision_number":{"type":"integer","readOnly":true},"created_at":{"format":"date-time","type":"string","readOnly":true},"updated_at":{"format":"date-time","type":"string","readOnly":true}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"detail":{"type":"string"}}}}}},"responses":{"BadRequest":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad Request"},"Unauthorized":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}}},"paths":{"/v2.0/networks":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkCreateRequest"}}},"required":true},"tags":["Networks"],"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkResponse"}}},"description":"Network created successfully"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}},"operationId":"createNetwork","summary":"Create network","description":"Creates a network."}}}}
```

We need to add a tag to the network for the UI to appropriately display it:

## Update network

> Updates a network.

```json
{"openapi":"3.0.3","info":{"title":"Networking API","version":"2.0"},"tags":[{"name":"Networks","description":"Virtual network management operations"}],"servers":[{"url":"https://{host}/neutron","description":"PCD Network API v2.0","variables":{"host":{"default":"example.platform9.com","description":"The PCD controlplane hostname"}}}],"security":[{"pcdAuth":[]}],"components":{"securitySchemes":{"pcdAuth":{"name":"X-Auth-Token","type":"apiKey","in":"header","description":"PCD Identity Service token authentication"}},"schemas":{"NetworkUpdateRequest":{"type":"object","properties":{"network":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"admin_state_up":{"type":"boolean"},"shared":{"type":"boolean"},"provider:network_type":{"type":"string"},"provider:physical_network":{"type":"string"},"provider:segmentation_id":{"type":"integer"},"mtu":{"type":"integer"},"port_security_enabled":{"type":"boolean"},"dns_domain":{"type":"string"},"qos_policy_id":{"format":"uuid","type":"string"},"router:external":{"type":"boolean"},"tags":{"type":"array","items":{"type":"string"}},"segments":{"type":"array","items":{"$ref":"#/components/schemas/NetworkSegment"}}}}}},"NetworkSegment":{"type":"object","properties":{"provider:network_type":{"type":"string"},"provider:physical_network":{"type":"string"},"provider:segmentation_id":{"type":"integer"}}},"NetworkResponse":{"type":"object","properties":{"network":{"$ref":"#/components/schemas/Network"}}},"Network":{"type":"object","properties":{"id":{"format":"uuid","type":"string","readOnly":true},"name":{"type":"string"},"description":{"type":"string"},"admin_state_up":{"type":"boolean"},"status":{"enum":["ACTIVE","BUILD","DOWN","ERROR"],"type":"string","readOnly":true},"shared":{"type":"boolean"},"project_id":{"format":"uuid","type":"string"},"tenant_id":{"format":"uuid","type":"string"},"subnets":{"type":"array","items":{"format":"uuid","type":"string"},"readOnly":true},"router:external":{"type":"boolean"},"provider:network_type":{"enum":["flat","vlan","vxlan","gre","local"],"type":"string"},"provider:physical_network":{"type":"string"},"provider:segmentation_id":{"type":"integer"},"mtu":{"minimum":68,"type":"integer"},"port_security_enabled":{"type":"boolean"},"dns_domain":{"type":"string"},"qos_policy_id":{"format":"uuid","type":"string"},"availability_zone_hints":{"type":"array","items":{"type":"string"}},"availability_zones":{"type":"array","items":{"type":"string"},"readOnly":true},"ipv4_address_scope":{"format":"uuid","type":"string"},"ipv6_address_scope":{"format":"uuid","type":"string"},"l2_adjacency":{"type":"boolean","readOnly":true},"vlan_transparent":{"type":"boolean"},"qinq":{"type":"boolean"},"is_default":{"type":"boolean"},"segments":{"type":"array","items":{"$ref":"#/components/schemas/NetworkSegment"}},"tags":{"type":"array","items":{"type":"string"}},"revision_number":{"type":"integer","readOnly":true},"created_at":{"format":"date-time","type":"string","readOnly":true},"updated_at":{"format":"date-time","type":"string","readOnly":true}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"detail":{"type":"string"}}}}}},"parameters":{"NetworkId":{"name":"network_id","description":"The ID of the network.","schema":{"format":"uuid","type":"string"},"in":"path","required":true}},"responses":{"BadRequest":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad Request"},"Unauthorized":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"Forbidden":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Forbidden"},"NotFound":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not Found"},"PreconditionFailed":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Precondition Failed"}}},"paths":{"/v2.0/networks/{network_id}":{"put":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkUpdateRequest"}}},"required":true},"tags":["Networks"],"parameters":[{"$ref":"#/components/parameters/NetworkId"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkResponse"}}},"description":"Network updated successfully"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"412":{"$ref":"#/components/responses/PreconditionFailed"}},"operationId":"updateNetwork","summary":"Update network","description":"Updates a network."}}}}
```

## Create port

> Creates a port.

```json
{"openapi":"3.0.3","info":{"title":"Networking API","version":"2.0"},"tags":[{"name":"Ports","description":"Network port management operations"}],"servers":[{"url":"https://{host}/neutron","description":"PCD Network API v2.0","variables":{"host":{"default":"example.platform9.com","description":"The PCD controlplane hostname"}}}],"security":[{"pcdAuth":[]}],"components":{"securitySchemes":{"pcdAuth":{"name":"X-Auth-Token","type":"apiKey","in":"header","description":"PCD Identity Service token authentication"}},"schemas":{"PortCreateRequest":{"required":["port"],"type":"object","properties":{"port":{"required":["network_id"],"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"network_id":{"format":"uuid","type":"string"},"admin_state_up":{"default":true,"type":"boolean"},"mac_address":{"type":"string"},"fixed_ips":{"type":"array","items":{"$ref":"#/components/schemas/FixedIP"}},"project_id":{"format":"uuid","type":"string"},"tenant_id":{"format":"uuid","type":"string"},"device_id":{"type":"string"},"device_owner":{"type":"string"},"security_groups":{"type":"array","items":{"format":"uuid","type":"string"}},"allowed_address_pairs":{"type":"array","items":{"$ref":"#/components/schemas/AllowedAddressPair"}},"extra_dhcp_opts":{"type":"array","items":{"$ref":"#/components/schemas/ExtraDhcpOpt"}},"port_security_enabled":{"type":"boolean"},"dns_name":{"type":"string"},"dns_domain":{"type":"string"},"qos_policy_id":{"format":"uuid","type":"string"},"binding:vnic_type":{"type":"string"},"binding:profile":{"type":"object","additionalProperties":true}}}}},"FixedIP":{"type":"object","properties":{"subnet_id":{"format":"uuid","type":"string"},"ip_address":{"format":"ipv4","type":"string"}}},"AllowedAddressPair":{"type":"object","properties":{"ip_address":{"type":"string"},"mac_address":{"pattern":"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$","type":"string"}}},"ExtraDhcpOpt":{"type":"object","properties":{"opt_name":{"type":"string"},"opt_value":{"type":"string"},"ip_version":{"enum":[4,6],"type":"integer"}}},"PortResponse":{"type":"object","properties":{"port":{"$ref":"#/components/schemas/Port"}}},"Port":{"type":"object","properties":{"id":{"format":"uuid","type":"string","readOnly":true},"name":{"type":"string"},"description":{"type":"string"},"network_id":{"format":"uuid","type":"string"},"admin_state_up":{"type":"boolean"},"status":{"enum":["ACTIVE","BUILD","DOWN","ERROR"],"type":"string","readOnly":true},"mac_address":{"pattern":"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$","type":"string"},"fixed_ips":{"type":"array","items":{"$ref":"#/components/schemas/FixedIP"}},"project_id":{"format":"uuid","type":"string"},"tenant_id":{"format":"uuid","type":"string"},"device_id":{"type":"string"},"device_owner":{"type":"string"},"security_groups":{"type":"array","items":{"format":"uuid","type":"string"}},"allowed_address_pairs":{"type":"array","items":{"$ref":"#/components/schemas/AllowedAddressPair"}},"extra_dhcp_opts":{"type":"array","items":{"$ref":"#/components/schemas/ExtraDhcpOpt"}},"port_security_enabled":{"type":"boolean"},"dns_name":{"type":"string"},"dns_assignment":{"type":"array","items":{"$ref":"#/components/schemas/DnsAssignment"},"readOnly":true},"dns_domain":{"type":"string"},"data_plane_status":{"enum":[null,"ACTIVE","DOWN"],"type":"string"},"qos_policy_id":{"format":"uuid","type":"string"},"qos_network_policy_id":{"format":"uuid","type":"string"},"binding:vnic_type":{"type":"string"},"binding:profile":{"type":"object","additionalProperties":true},"binding:host_id":{"type":"string"},"binding:vif_type":{"type":"string","readOnly":true},"binding:vif_details":{"type":"object","additionalProperties":true,"readOnly":true},"resource_request":{"type":"object","nullable":true,"readOnly":true},"tags":{"type":"array","items":{"type":"string"}},"revision_number":{"type":"integer","readOnly":true},"created_at":{"format":"date-time","type":"string","readOnly":true},"updated_at":{"format":"date-time","type":"string","readOnly":true}}},"DnsAssignment":{"type":"object","properties":{"hostname":{"type":"string"},"ip_address":{"type":"string"},"fqdn":{"type":"string"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"detail":{"type":"string"}}}}}},"responses":{"BadRequest":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad Request"},"Unauthorized":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}}},"paths":{"/v2.0/ports":{"post":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortCreateRequest"}}},"required":true},"tags":["Ports"],"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortResponse"}}},"description":"Port created successfully"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}},"operationId":"createPort","summary":"Create port","description":"Creates a port."}}}}
```

## Create Server

> Creates a server. The progress of this operation depends on various factors\
> including image location, network I/O, host load, and selected flavor.<br>

```json
{"openapi":"3.0.3","info":{"title":"Compute API","version":"2.96"},"servers":[{"url":"https://{host}/nova/v2.1","description":"Nova Compute API v2.1","variables":{"host":{"default":"pcd.example.com","description":"The PCD controlplane hostname"}}}],"security":[{"keystoneAuth":[]}],"components":{"securitySchemes":{"keystoneAuth":{"scheme":"bearer","type":"http","description":"OpenStack Keystone token authentication"}},"schemas":{"CreateServerRequest":{"required":["name","flavorRef"],"type":"object","properties":{"name":{"description":"The server name","type":"string"},"imageRef":{"format":"uuid","description":"The UUID of the image (not required for boot from volume)","type":"string"},"flavorRef":{"description":"The flavor reference (UUID or full URL)","type":"string"},"adminPass":{"description":"The administrative password of the server","type":"string"},"networks":{"oneOf":[{"description":"Special network allocation values","enum":["auto","none"],"type":"string"},{"description":"A list of networks","type":"array","items":{"$ref":"#/components/schemas/ServerNetwork"}}]},"block_device_mapping_v2":{"description":"Block device mapping for boot from volume","type":"array","items":{"$ref":"#/components/schemas/BlockDeviceMappingV2"}},"availability_zone":{"description":"The availability zone from which to launch the server","type":"string"},"user_data":{"format":"byte","description":"Configuration information or scripts (Base64 encoded)","type":"string"},"metadata":{"description":"Metadata key and value pairs","type":"object","additionalProperties":{"type":"string"}},"personality":{"description":"File path and contents to inject (deprecated in 2.57)","type":"array","items":{"$ref":"#/components/schemas/PersonalityFile"}},"security_groups":{"description":"One or more security groups","type":"array","items":{"type":"object","properties":{"name":{"type":"string"}}}},"key_name":{"description":"Key pair name","type":"string"},"config_drive":{"description":"Indicates whether a config drive enables metadata injection","type":"boolean"},"OS-DCF:diskConfig":{"description":"Controls how the API partitions the disk","enum":["AUTO","MANUAL"],"type":"string"},"accessIPv4":{"format":"ipv4","description":"IPv4 address that should be used to access this server","type":"string"},"accessIPv6":{"format":"ipv6","description":"IPv6 address that should be used to access this server","type":"string"},"description":{"description":"A free form description of the server","type":"string"},"hostname":{"description":"The hostname to configure for the instance","type":"string"},"tags":{"description":"A list of tags","maxItems":50,"type":"array","items":{"type":"string"}},"trusted_image_certificates":{"description":"A list of trusted certificate IDs","maxItems":50,"type":"array","items":{"format":"uuid","type":"string"}},"host":{"description":"The name of the compute service host (admin only)","type":"string"},"hypervisor_hostname":{"description":"The hostname of the hypervisor (admin only)","type":"string"}}},"ServerNetwork":{"type":"object","properties":{"uuid":{"format":"uuid","description":"The UUID of the network","type":"string"},"port":{"format":"uuid","description":"The UUID of an existing port","type":"string"},"fixed_ip":{"format":"ipv4","description":"A fixed IPv4 address for the NIC","type":"string"},"tag":{"description":"A device role tag for the network interface","type":"string"}}},"BlockDeviceMappingV2":{"required":["boot_index"],"type":"object","properties":{"boot_index":{"description":"The boot order of the device","minimum":0,"type":"integer"},"uuid":{"format":"uuid","description":"The UUID of the source resource","type":"string"},"source_type":{"description":"The source type of the block device","enum":["volume","image","snapshot","blank"],"type":"string"},"destination_type":{"description":"Where the block device mapping will reside","enum":["volume","local"],"type":"string"},"delete_on_termination":{"description":"Whether to delete the volume when the server is destroyed","default":false,"type":"boolean"},"device_name":{"description":"A path to the device for the volume","type":"string"},"device_type":{"description":"The device type","enum":["disk","cdrom","floppy","lun"],"type":"string"},"disk_bus":{"description":"Disk bus type","enum":["ide","usb","virtio","scsi","sata","uml","xen","lxc"],"type":"string"},"guest_format":{"description":"Guest server disk file system format","type":"string"},"no_device":{"description":"Whether this is a no device mapping","type":"boolean"},"volume_size":{"description":"The size of the volume in GiB","maximum":2147483647,"minimum":1,"type":"integer"},"tag":{"description":"A device role tag for the block device","type":"string"},"volume_type":{"description":"The volume type","type":"string"}}},"PersonalityFile":{"required":["path","contents"],"type":"object","properties":{"path":{"description":"The file path","maxLength":255,"type":"string"},"contents":{"format":"byte","description":"The file contents (Base64 encoded)","type":"string"}}},"SchedulerHints":{"description":"The dictionary of data to send to the scheduler","type":"object","properties":{"build_near_host_ip":{"format":"ipv4","description":"Schedule the server on a host in the network","type":"string"},"cidr":{"description":"Schedule the server on a host in the network specified with an IP address","type":"string"},"different_cell":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Schedule the server in a cell that is not specified"},"different_host":{"oneOf":[{"format":"uuid","type":"string"},{"type":"array","items":{"format":"uuid","type":"string"}}],"description":"Schedule the server on a different host from a set of servers"},"group":{"format":"uuid","description":"The server group UUID","type":"string"},"query":{"description":"Schedule the server by using a custom filter in JSON format","type":"string"},"same_host":{"oneOf":[{"format":"uuid","type":"string"},{"type":"array","items":{"format":"uuid","type":"string"}}],"description":"Schedule the server on the same host as another server"},"target_cell":{"description":"A target cell name","type":"string"}}},"ServerResponse":{"type":"object","properties":{"id":{"format":"uuid","description":"The UUID of the server","type":"string"},"links":{"type":"array","items":{"$ref":"#/components/schemas/Link"}},"OS-DCF:diskConfig":{"description":"Disk configuration","enum":["AUTO","MANUAL"],"type":"string"},"adminPass":{"description":"The administrative password for the server","type":"string"},"security_groups":{"type":"array","items":{"$ref":"#/components/schemas/SecurityGroup"}}}},"Link":{"type":"object","properties":{"href":{"format":"uri","type":"string"},"rel":{"enum":["self","bookmark","next","prev"],"type":"string"},"type":{"type":"string"}}},"SecurityGroup":{"type":"object","properties":{"name":{"description":"The security group name","type":"string"}}},"ErrorResponse":{"type":"object","properties":{"computeFault":{"type":"object","properties":{"code":{"type":"integer"},"message":{"type":"string"},"details":{"type":"string"}}}}}},"parameters":{"OpenStackAPIVersion":{"name":"OpenStack-API-Version","description":"Specifies the API microversion. Format: \"compute X.Y\" where X.Y is the microversion.\nIf not specified, the minimum supported version (2.1) is used.\n","schema":{"pattern":"^compute \\d+\\.\\d+","type":"string"},"in":"header"}},"responses":{"BadRequest":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Request"},"Unauthorized":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"Forbidden":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"NotFound":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"Conflict":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"}}},"paths":{"/servers":{"post":{"requestBody":{"content":{"application/json":{"schema":{"required":["server"],"type":"object","properties":{"server":{"$ref":"#/components/schemas/CreateServerRequest"},"OS-SCH-HNT:scheduler_hints":{"$ref":"#/components/schemas/SchedulerHints"}}}}},"required":true},"parameters":[{"$ref":"#/components/parameters/OpenStackAPIVersion"}],"responses":{"202":{"headers":{"Location":{"schema":{"format":"uri","type":"string"},"description":"The location URL of the server"}},"content":{"application/json":{"schema":{"type":"object","properties":{"server":{"$ref":"#/components/schemas/ServerResponse"}}}}},"description":"Server creation accepted"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}},"operationId":"createServer","summary":"Create Server","description":"Creates a server. The progress of this operation depends on various factors\nincluding image location, network I/O, host load, and selected flavor.\n"}}}}
```

### Configure a static IP with cloud-init

The `network:` block in a cloud-init `user_data` payload is not applied to VMs on a Layer 2 Network. To assign a static IP, default gateway, and DNS servers, use the `write_files` and `runcmd` cloud-init modules instead. This is a known platform behavior and cannot be changed by configuration.

Ports on a Layer 2 Network are created without a fixed IP. As a result, Nova builds the VM's Config Drive with an empty network configuration. On first boot, cloud-init reads the Config Drive as its network data source and applies that empty configuration. When cloud-init then processes your `user_data`, it treats network configuration as already handled and ignores the `network:`

Before you begin, confirm the following:

* You have a Layer 2 Network in your project. See
* You have the static IP address (in CIDR notation), default gateway, and DNS server addresses for your environment.
* Your VM image includes `cloud-init` and the network configuration tool referenced in your `write_files` target. The example in this section targets an Ubuntu image, where Netplan is the default.
* You know the primary network interface name inside the guest. On Ubuntu cloud images, this is typically `ens3`. To confirm your image, run `ip link` on a booted VM from the same image.

#### Apply the configuration

Supply the following cloud-init payload as the user data when you deploy the VM. The example uses sample values. Replace the IP address, subnet, gateway, and DNS server values with the ones for your environment.

```yaml
#cloud-config
password: <YOUR_PASSWORD>
chpasswd: { expire: False }
ssh_pwauth: True
manage_etc_hosts: true

write_files:
  - path: /etc/netplan/99-custom-static.yaml
    content: |
      network:
        version: 2
        ethernets:
          ens3:
            dhcp4: no
            addresses: [10.10.1.35/18]
            routes:
              - to: 10.10.0.0/18
                via: 10.10.0.1
                metric: 100
              - to: default
                metric: 100
                via: 10.10.0.1
            nameservers:
              addresses: [8.8.8.8, 8.8.4.4]

runcmd:
  - netplan apply
```

The `write_files` module creates `/etc/netplan/99-custom-static.yaml` on the VM during the cloud-init `final` stage. The `runcmd` module then runs `netplan apply` to load the configuration. The static IP, routes, and DNS servers persist across reboots.

{% hint style="info" %}
**NOTE**

The `password` and `ssh_pwauth` lines in this example are inherited from the underlying test payload and are not required for the static IP workaround. Avoid placing plaintext passwords in `user_data` for production VMs. Use SSH keys or your standard credential delivery mechanism instead.
{% endhint %}

#### Verify the configuration

After the VM boots, connect to it and run the following commands to confirm that cloud-init applied the configuration:

```bash
ip addr show ens3
cloud-init status --long
```

The `ip addr show` output should list the static IP you configured. The `cloud-init status` output should show `status: done`. If `cloud-init status` reports an error, inspect `/var/log/cloud-init.log` and `/var/log/cloud-init-output.log` for details.

#### Adapt the example for other operating systems

The example targets Ubuntu and Netplan. For other guest operating systems, change the `write_files` path and the `runcmd` command to match the distribution's network configuration tool. For example, on a RHEL-based image, write a NetworkManager keyfile or `ifcfg` file and reload it with `nmcli connection reload` followed by `nmcli connection up <CONNECTION_NAME>`.

### Clone a VM on a Layer 2 Network

When cloning a VM, you can select a Layer 2 Network during the clone workflow.

The network selection page that appears during cloning follows the same workflow as the VM deployment process.

1. Navigate to **Virtual Machines > Virtual Machines**.
2. Select the VM you want to clone.
3. Select **Clone**.
4. On the network selection page, choose **Layer 2 Network** as the network type.
5. Select the Layer 2 Network from the list and complete the clone process.

The same limitations apply: security groups are disabled, and only one VM can be cloned at a time.

### View Layer 2 Network details

To view details and connected VMs for a Layer 2 Network:

1. Navigate to **Networks and Security > Networks**.
2. Identify Layer 2 Networks by the **Layer 2 Network** tag displayed next to each network name. Select the specific Layer 2 Network you want to inspect.

The network details page displays the network type as **Physical**. You will not be able to view details on **Subnets**, **Router Attachments**, and **DHCP Configuration**.

### Edit a Layer 2 Network

You can update the name and description of a Layer 2 Network after it is created. The VLAN ID and physical network cannot be changed.

1. Navigate to **Networks and Security > Networks**.
2. Select the Layer 2 Network you want to edit.
3. Select **Edit**.
4. Update the **Name** or **Description** as needed.
5. Select **Save**.

### Delete a Layer 2 Network

Deleting a Layer 2 Network detaches all VMs connected to it. Ensure no active workloads depend on the network before proceeding.

1. Navigate to **Networks and Security > Networks**.
2. Select the Layer 2 Network you want to delete.
3. Select **Delete**.
4. Confirm the deletion when prompted.

### Next steps

After creating a Layer 2 Network and configuring IP addresses in your guest OS, you can continue managing your VMs:

* [Virtual Machines](/private-cloud-director/virtualized-clusters/virtualmachine.md)
* [Cluster Blueprint](/private-cloud-director/virtualized-clusters/virtualized-cluster-blueprint.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.platform9.com/private-cloud-director/virtualized-networking/layer-2-networking.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
