weizhouapache commented on code in PR #13032: URL: https://github.com/apache/cloudstack/pull/13032#discussion_r3459607148
########## framework/extensions/src/main/java/org/apache/cloudstack/framework/extensions/network/README.md: ########## @@ -0,0 +1,1479 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + --> + +# Network Extension Script Protocol + +This document describes the complete interface between Apache CloudStack's +`NetworkExtensionElement` and the external script (Bash, Python, or any +executable) that implements network services for a custom device. + +Any executable that handles the commands listed below can be registered as a +**NetworkOrchestrator extension** and used as the provider for one or more +CloudStack network services (DHCP, DNS, UserData, SourceNat, StaticNat, +PortForwarding, Firewall, Lb, NetworkACL, Gateway). + +The reference implementation is the `network-namespace` extension at +`extensions/network-namespace/`, which uses Linux network namespaces on KVM +hosts. Use it as a working example. + +--- + +## Table of Contents + +1. [Architecture Overview](#architecture-overview) +2. [Script Placement Convention](#script-placement-convention) +3. [CloudStack Setup Steps](#cloudstack-setup-steps) +4. [Always-present payload fields](#always-present-payload-fields) +5. [Shared payload fields](#shared-payload-fields) +6. [Command Reference](#command-reference) + - [ensure-network-device](#ensure-network-device) + - [implement-network](#implement-network) + - [shutdown-network](#shutdown-network) + - [destroy-network](#destroy-network) + - [implement-vpc](#implement-vpc) + - [shutdown-vpc](#shutdown-vpc) + - [update-vpc-source-nat-ip](#update-vpc-source-nat-ip) + - [assign-ip / release-ip](#assign-ip--release-ip) + - [add-static-nat / delete-static-nat](#add-static-nat--delete-static-nat) + - [add-port-forward / delete-port-forward](#add-port-forward--delete-port-forward) + - [apply-fw-rules](#apply-fw-rules) + - [apply-network-acl](#apply-network-acl) + - [prepare-nic / release-nic](#prepare-nic--release-nic) + - [add-dhcp-entry / remove-dhcp-entry](#add-dhcp-entry--remove-dhcp-entry) + - [config-dhcp-subnet / remove-dhcp-subnet](#config-dhcp-subnet--remove-dhcp-subnet) + - [set-dhcp-options](#set-dhcp-options) + - [add-dns-entry](#add-dns-entry) + - [config-dns-subnet / remove-dns-subnet](#config-dns-subnet--remove-dns-subnet) + - [save-vm-data](#save-vm-data) + - [save-password](#save-password) + - [save-userdata](#save-userdata) + - [save-sshkey](#save-sshkey) + - [save-hypervisor-hostname](#save-hypervisor-hostname) + - [apply-lb-rules](#apply-lb-rules) + - [restore-network](#restore-network) + - [custom-action](#custom-action) +7. [Service-to-Command Mapping](#service-to-command-mapping) +8. [Capabilities Configuration](#capabilities-configuration) +9. [VPC Networks](#vpc-networks) +10. [Extension IP](#extension-ip) +11. [Exit Codes](#exit-codes) +12. [Minimal Script Skeleton](#minimal-script-skeleton) + +--- + +## Architecture Overview + +``` +CloudStack Management Server + │ + │ exec <extension-path>/<ext-name>.sh <command> <payload-file> <timeout-seconds> + │ payload-file contains JSON for the command invocation + ▼ + Your Script (Bash / Python / Go / …) + │ + │ configures / queries your device: + │ • KVM host over SSH + │ • SDN controller REST API + │ • Hardware appliance CLI + │ • Cloud provider API + ▼ + External Network Device +``` + +CloudStack calls the script synchronously (blocking process execution) on the +**management server** for every network event. The script is responsible for +translating those events into configuration changes on the actual device. + +The script must: + +- **Exit 0** on success. +- **Exit non-zero** on failure (CloudStack will log the error and may retry). +- For `ensure-network-device` only, **print a single-line JSON object** to + stdout (see [ensure-network-device](#ensure-network-device)). + +All other commands must produce no output on stdout (any output is logged at +DEBUG level and ignored). + +--- + +## Script Placement Convention + +CloudStack resolves the executable in this order (first match wins): + +1. **`<extensionPath>/<extensionName>.sh`** — preferred convention. + Example: extension named `my-sdn` → script at + `.../my-sdn/my-sdn.sh`. +2. **`<extensionPath>` itself**, if it is a regular file and is executable. + +The `<extensionPath>` is the `path` field returned by `listExtensions` after +the extension is created. CloudStack sets it to: + +``` +/usr/share/cloudstack-management/extensions/<extensionName>/ +``` + +> **Tip:** Your script does not have to live on the management server — it can +> be a thin proxy that SSHes into a remote appliance. The +> `network-namespace.sh` entry-point is exactly that: it SSHes into the target +> KVM host and calls the wrapper script there. + +--- + +## CloudStack Setup Steps + +### Step 1 – Create the Extension + +```bash +cmk createExtension \ + name=my-sdn \ + type=NetworkOrchestrator \ + "details[0].network.services=SourceNat,StaticNat,PortForwarding,Firewall,Lb,Dhcp,Dns,UserData,CustomAction" \ + "details[1].network.service.capabilities=$(cat my-sdn-capabilities.json)" \ + "details[2].network.isolation.method=NetworkExtension" +``` + +`network.service.capabilities` is a JSON object — see +[Capabilities Configuration](#capabilities-configuration). + +### Step 2 – Deploy the Script + +Copy your executable to the path reported by `listExtensions`: + +```bash +SCRIPT_PATH=$(cmk listExtensions name=my-sdn | jq -r '.[0].path') +# e.g. /usr/share/cloudstack-management/extensions/my-sdn/ +mkdir -p "${SCRIPT_PATH}" +cp my-sdn.sh "${SCRIPT_PATH}/my-sdn.sh" +chmod 755 "${SCRIPT_PATH}/my-sdn.sh" +``` + +If you have multiple management servers, deploy the script to **every** one. + +### Step 3 – Register the Extension to a Physical Network + +```bash +PHYS_ID=$(cmk listPhysicalNetworks | jq -r '.[0].id') +EXT_ID=$(cmk listExtensions name=my-sdn | jq -r '.[0].id') + +cmk registerExtension \ + id=${EXT_ID} \ + resourcetype=PhysicalNetwork \ + resourceid=${PHYS_ID} \ + "details[0].hosts=192.168.1.10,192.168.1.11" \ + "details[1].username=root" \ + "details[2].password=s3cr3t" +``` + +Any key/value pairs you pass here are stored with the physical-network +registration as extension metadata. The `custom-action` path embeds them +directly into the payload file under `physical-network-extension-details`. +The schema is entirely yours — CloudStack treats it as opaque. + +> **`network.isolation.method=NetworkExtension`** must be set as an Extension +> detail (via `createExtension` or `updateExtension`). +> This is required whenever your `implement-network` handler outputs JSON that +> updates the network's broadcast domain type. +> Without it the script output is accepted but silently ignored — the network +> record in the CloudStack database is not updated. + +### Step 4 – Enable the Network Service Provider + +```bash +NSP_ID=$(cmk listNetworkServiceProviders physicalnetworkid=${PHYS_ID} \ + name=my-sdn | jq -r '.[0].id') +cmk updateNetworkServiceProvider id=${NSP_ID} state=Enabled +``` + +### Step 5 – Create a Network Offering + +```bash +cmk createNetworkOffering \ + name="My-SDN-Offering" \ + displaytext="My SDN network offering" \ + guestiptype=Isolated \ + traffictype=GUEST \ + supportedservices=Dhcp,Dns,UserData,SourceNat,StaticNat,PortForwarding,Firewall,Lb \ + "serviceProviderList[Dhcp]=my-sdn" \ + "serviceProviderList[Dns]=my-sdn" \ + "serviceProviderList[UserData]=my-sdn" \ + "serviceProviderList[SourceNat]=my-sdn" \ + "serviceProviderList[StaticNat]=my-sdn" \ + "serviceProviderList[PortForwarding]=my-sdn" \ + "serviceProviderList[Firewall]=my-sdn" \ + "serviceProviderList[Lb]=my-sdn" \ + "serviceCapabilityList[SourceNat][SupportedSourceNatTypes]=peraccount" Review Comment: fixed -- 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]
