kiranchavala opened a new issue, #5:
URL: https://github.com/apache/cloudstack-extensions/issues/5

   # Multiple bugs in `Network-Namespace/network-namespace-wrapper.sh` prevent 
it from working out of the box
   
   ## Summary
   
   Following the setup instructions in the CloudStack `NetworkExtension` 
protocol doc
   (`framework/extensions/.../network/README.md` in apache/cloudstack) to 
register this
   reference implementation as a `NetworkOrchestrator` extension (CloudStack 
4.23,
   KVM, physical network registered with 
`guest.network.device`/`public.network.device`),
   I hit six distinct issues before a VM could successfully deploy onto a 
network backed
   by this script. Filing them together since they were found in one debugging 
pass and
   several are related.
   
   **Environment:** Apache CloudStack 4.23.0, KVM hosts on Ubuntu 24.04, 
`network-namespace`
   branch, script fetched fresh via the documented raw.githubusercontent.com 
URL.
   
   ---
   
   ## 1. `ensure_host_bridge()`'s return-via-stdout leaks into the extension's 
real stdout
   
   `ensure_host_bridge()` returns its result the usual bash way — `echo 
"${br}"` — meant to
   be captured with `br=$(ensure_host_bridge ...)`. But at **four call sites** 
it's invoked
   as a bare statement, with the actual bridge name recomputed separately on 
the next line
   via `host_bridge_name()`:
   
   - `cmd_implement_network()` (guest bridge): `ensure_host_bridge 
"${GUEST_ETH}" "${VLAN}"`
   - `cmd_assign_ip()` (public bridge): `ensure_host_bridge "${PUB_ETH}" 
"${PUBLIC_VLAN}"`
   - two more identical public-bridge call sites in the VPC source-NAT / 
source-NAT-IP-update paths
   
   Since CloudStack's `NetworkExtensionElement` treats the command's stdout as 
the payload
   to parse, this leaked bridge name (e.g. `breth0-600`, or later `cloudbr0` 
once VLAN was
   `untagged`) corrupts the real output and gets logged as `Ignoring non-object 
script output: ...`
   or worse, treated as the entire (invalid) response.
   
   **Fix:** redirect all four calls to `/dev/null`:
   ```bash
   ensure_host_bridge "${GUEST_ETH}" "${VLAN}" >/dev/null
   ...
   ensure_host_bridge "${PUB_ETH}" "${PUBLIC_VLAN}" >/dev/null
   ```
   
   ---
   
   ## 2. `implement-network` never emits the required `network.broadcast_uri` / 
`network.broadcast_domain_type` JSON
   
   Per the protocol doc, whenever the extension has the detail
   `network.isolation.method=NetworkExtension` set (which selects
   `NetworkExtensionGuestNetworkGuru` in CloudStack core), 
`implement-network`'s stdout
   **must** be a JSON object containing `network.broadcast_domain_type` and
   `network.broadcast_uri` — enforced unconditionally by
   `NetworkExtensionElement.applyNetworkUpdateFromScriptOutput()` in CloudStack 
core.
   
   `cmd_implement_network()` never emits these keys anywhere in the script, so 
every
   `implement-network` call fails with:
   
   ```
   Script output is missing required network properties 'network.broadcast_uri' 
and
   'network.broadcast_domain_type' for network ...
   ```
   
   **Fix:** emit the JSON at the end of `cmd_implement_network()`, e.g.:
   ```bash
   if [ -n "${VLAN}" ]; then
       printf 
'{"network.broadcast_domain_type":"Vlan","network.broadcast_uri":"vlan://%s"}\n'
 "${VLAN}"
   fi
   ```
   
   ---
   
   ## 3. No handling for an `untagged` public VLAN
   
   When a zone's public IP range has no VLAN tag, CloudStack passes the literal 
string
   `"untagged"` as `payload.public_vlan`. 
`ensure_host_bridge()`/`host_bridge_name()` pass
   this straight through to:
   ```bash
   ip link add link "${eth}" name "${vif}" type vlan id "${vlan}"
   ```
   which fails immediately since VLAN IDs must be numeric:
   ```
   Error: argument "untagged" is wrong: id is invalid
   ```
   This is a completely normal, common CloudStack zone configuration (public 
network
   without 802.1q tagging), not an edge case.
   
   **Fix:** special-case `vlan == "untagged"` in both functions to reuse the 
NIC's
   *existing* bridge (e.g. `cloudbr0`, detected via `ip -o link show <eth> | 
grep -o 'master [^ ]*'`)
   instead of trying to create a fresh VLAN sub-interface + bridge.
   
   ---
   
   ## 4. Related to #3 — `teardown_host_bridge_if_unused()` would delete the 
host's shared bridge
   
   Once #3 is fixed so that `host_bridge_name()` can return an *existing*, 
host-critical
   bridge like `cloudbr0` for the untagged case, 
`teardown_host_bridge_if_unused()` — which
   runs `ip link del "${br}"` whenever it thinks the bridge has no other 
members — becomes
   dangerous: it did not create `cloudbr0` and has no business deleting it, but 
nothing
   in the current code prevents it from trying once that bridge is "unused" by 
this
   script's own veth accounting.
   
   **Fix:** short-circuit `teardown_host_bridge_if_unused()` to a no-op whenever
   `vlan == "untagged"`.
   
   ---
   
   ## 5. `pub_veth_host_name()` / `pub_veth_ns_name()` don't apply the existing 
15-char shortening logic
   
   The **guest**-side equivalents (`veth_host_name()`, `veth_ns_name()`) 
already shorten
   the generated interface name via `shorten_id()` when `vh-<vlan>-<id>` /
   `vn-<vlan>-<id>` would exceed the Linux `IFNAMSIZ` limit (15 chars). The 
**public**-side
   functions never got the same treatment — they just do `echo 
"vph-${pvlan}-${id}"` /
   `echo "vpn-${pvlan}-${id}"` unconditionally.
   
   This is latent for short numeric VLANs but fails as soon as `pvlan` is 
`"untagged"`
   (8 chars) combined with even a short numeric id, e.g. network id `222`:
   `vpn-untagged-222` = 17 characters →
   ```
   Error: argument "vpn-untagged-222" is wrong: "name" not a valid ifname
   ```
   
   **Fix:** apply the same three-tier shortening (`shorten_id()`, then 
hard-truncate to 15)
   already used in `veth_host_name()`/`veth_ns_name()`.
   
   ---
   
   ## 6. Design gap: the script requires the caller to pre-supply a VLAN; it 
never self-allocates one
   
   `NetworkExtensionGuestNetworkGuru` deliberately skips CloudStack's normal 
auto-VLAN
   pool — the protocol is designed for the extension's `implement-network` 
handler to
   generate **its own** segment identifier and report it back (the doc's own 
example uses
   
`{"network.broadcast_domain_type":"Lswitch","network.broadcast_uri":"ovn://cs-net-42"}`,
   no VLAN involved at all).
   
   This script instead just echoes back whatever `payload.vlan` it was given 
and never
   allocates anything itself, so a plain auto-VLAN Isolated network offering (no
   `specifyvlan`) always reaches `implement-network` with an empty VLAN, and 
the script's
   device-naming logic (`vn-<vlan>-<id>`) then fails outright (`Cannot find 
device "vn--<id>"`).
   In practice this forces every offering built on this extension to use
   `specifyvlan=true` plus an explicit `vlan=` on every `createNetwork` call, 
which isn't
   mentioned anywhere in the README's "CloudStack Setup Steps".
   
   **Suggested fix:** either (a) have `implement-network` fall back to 
self-generating a
   stable identifier (e.g. derived from the network/VPC id) when `payload.vlan` 
is empty,
   consistent with the protocol's intent, or (b) at minimum, document the
   `specifyvlan=true` + explicit `vlan=` requirement explicitly in the README's 
setup
   steps.
   
   ---
   
   ## 7. (Minor / docs) Missing host packages fail silently as far as 
CloudStack is concerned
   
   `cmd_restore_network()` hard-requires `dnsmasq`, `apache2`/`httpd`, and 
`haproxy` on the
   KVM host via `_require_binary`, but `die()` in this script only logs to the 
wrapper's
   own local log file (`/tmp/cloudstack-extensions/<name>.log` on the KVM host) 
— nothing
   reaches stdout, so CloudStack (and the mgmt-server SSH proxy's exit-code-3 
convention
   for "remote script returned non-zero") only ever sees an **empty** error 
message. This
   makes a missing-package issue on a KVM host very hard to diagnose from the 
CloudStack
   side alone.
   
   **Suggested fix:** either have `_require_binary`'s `die()` path also print 
to stdout
   (so it surfaces in the CloudStack-side log), or list `dnsmasq`, `apache2`, 
`haproxy` as
   explicit prerequisites in the README's KVM host setup section.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to