GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — ui lb algorithm from capability by msinhore · Pull Request #134 · shapeblue/cloudstack

Conversation

@msinhore

@msinhore msinhore commented Apr 30, 2026

Copy link
Copy Markdown

Description

The LB algorithm dropdown in every Load Balancer form was hard-coded to
['source', 'roundrobin', 'leastconn'] regardless of what the network's Lb
provider actually supports. A user could pick leastconn against a provider
that does not implement it (e.g. a third-party or future provider that
declares only a subset), and the rule would only be rejected later by
validateLBRule on the backend.

The capability is already declared by every NetworkElement via
getCapabilities() -> Service.Lb -> Capability.SupportedLBAlgorithms
and surfaced by listNetworks (createNetworkResponse walks the live
provider's capabilities verbatim). The UI just was not reading it.

This PR makes every LB algorithm dropdown data-driven from that capability,
across the four places where the list was hard-coded:

  • ui/src/views/network/LoadBalancing.vue — public-IP LB (create modal
    • edit-rule modal).
  • ui/src/views/network/VpcTiersTab.vue — "Add Internal LB" modal on
    the VPC details page.
  • ui/src/views/compute/AutoScaleLoadBalancing.vue — edit-rule modal on
    VPC public AutoScale LB.
  • ui/src/config/section/network.js — Internal LB action (flagged with
    a TODO; converting it requires AutogenView to support async/function-
    valued mapping[field].options, which is a framework-level change out of
    scope here).

How it works

Each form gains a supportedAlgorithms data field (default
['roundrobin', 'leastconn', 'source'] — the legacy list) and a
fetchLbCapabilities*() helper that:

  1. Resolves the network id from resource.associatednetworkid /
    resource.networkid / the selected tier.
  2. Calls listNetworks for that id.
  3. Walks service[name=Lb].capability[name=SupportedLbAlgorithms] and
    splits the CSV into the dropdown list.
  4. Snaps the form's current selection to the first supported value if the
    previous default falls outside the new set.
  5. Swallows backend errors and falls back to the legacy three, so providers
    that do not declare the capability behave exactly as before.

listNetworks is used (not listNetworkOfferings) because the offering
response hard-codes only SupportedLBIsolation / ElasticLb / InlineMode / VmAutoScaling for the Lb service, whereas createNetworkResponse exposes
the full provider capability set including SupportedLbAlgorithms.

Backwards compatibility

Provider-agnostic and fully backwards-compatible:

  • VirtualRouter and any provider that declares the legacy three: dropdown is unchanged.
  • Providers that declare a narrower set (e.g. {roundrobin, source}): the dropdown now reflects what the backend actually accepts, removing a silent foot-gun.
  • Providers that do not declare SupportedLbAlgorithms at all: legacy three options are shown (no regression).

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Enhancement (improves an existing feature and functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • build/CI

How Has This Been Tested?

UI exercised against a 4.23-dev environment with two Lb providers declaring
different SupportedLBAlgorithms sets:

  • VirtualRouter (declares roundrobin,leastconn,source): dropdown shows three options in all four forms — unchanged behaviour.
  • Custom provider (declares roundrobin,source only): dropdown shows two options across LoadBalancing.vue (create + edit), VpcTiersTab.vue (Add Internal LB), and AutoScaleLoadBalancing.vue (edit rule). Selecting the previous default leastconn is no longer possible, so the rule is guaranteed to pass validateLBRule on submit.
  • Provider without the capability declared: legacy three options shown, confirming the fallback path.

Verified that backend errors on listNetworks (simulated by stopping the management server briefly) do not break the dropdown — it falls back to the legacy three and the form remains usable.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
msinhore and others added 2 commits April 30, 2026 12:10
@msinhore @claude
ui: derive LB algorithm dropdown from network's Lb provider capability
da709bb
Before this change, both the public LB form (LoadBalancing.vue) and the
internal LB form (network.js Internal LB action) hard-coded the algorithm
dropdown to ['source', 'roundrobin', 'leastconn']. Every Lb provider got the
same three options regardless of what the provider actually supported, so a
user could pick "leastconn" against, e.g., the OVN provider, only to get the
rule rejected later by validateLBRule. The capability is already declared
(NetworkElement.getCapabilities() -> Service.Lb -> Capability.SupportedLBAlgorithms)
and surfaced by listNetworks - we just weren't reading it.

LoadBalancing.vue (public LB - the create modal and the edit-rule modal):
  - Replaces the three static <a-select-option>s with a v-for over a new
    `supportedAlgorithms` data field defaulting to the legacy
    ['roundrobin', 'leastconn', 'source'] (so providers/networks that don't
    declare the capability behave exactly as before).
  - Adds fetchLbCapabilities() (called from fetchData) which:
      * resolves the network id from resource.associatednetworkid or
        resource.networkid,
      * looks up the network via listNetworks,
      * walks service[name=Lb].capability[name=SupportedLbAlgorithms] and
        splits the CSV into the dropdown list,
      * snaps newRule.algorithm to the first supported value if the previous
        default falls outside the new set,
      * swallows any error so we never break the page on a backend hiccup.

  listNetworks is the right endpoint here. listNetworkOfferings hard-codes
  only SupportedLBIsolation/ElasticLb/InlineMode/VmAutoScaling for the Lb
  service in createNetworkOfferingResponse, while createNetworkResponse
  walks the live provider's getCapabilities() and exposes everything we
  declared - including SupportedLbAlgorithms.

network.js (internal LB action):
  - Leaves the static option list in place but flags the spot with a TODO.
    Driving this declaratively requires AutogenView to support an async or
    function-valued `mapping[field].options`, which is a framework-level
    change and out of scope for this UI patch. A follow-up can convert the
    declarative mapping to a SFC and adopt the same approach as the public
    LB form.

The change is provider-agnostic: it benefits every Lb provider that
correctly declares SupportedLBAlgorithms. OVN gets {roundrobin, source};
VirtualRouter keeps {roundrobin, leastconn, source}; Netscaler/F5/etc.
will reflect whatever they declare, and providers without the capability
fall back to the legacy three.

This commit is intentionally self-contained on top of the OVN plugin work
so it can be cherry-picked into a dedicated upstream PR.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
@msinhore @claude
ui: derive LB algorithm dropdown from capability on every LB form
d756c1a
Extends the data-driven LB algorithm dropdown previously added in
LoadBalancing.vue (public-IP LB form) to the two remaining places
where the capability was still hard-coded as
['source', 'roundrobin', 'leastconn']:

- VpcTiersTab.vue: the "Add Internal LB" modal accessible from the
  VPC details page. The dropdown now follows the capability declared
  by the selected tier's Lb provider, looked up via listNetworks at
  the moment the modal opens (handleAddInternalLB ->
  fetchLbCapabilitiesForNetwork). Falls back to the legacy three when
  the lookup fails or the provider does not declare the capability,
  so providers without it behave exactly as before.

- AutoScaleLoadBalancing.vue: the "Edit rule" modal on a VPC public
  AutoScale LB. Same pattern - openEditRuleModal ->
  fetchLbCapabilitiesForRule reads the capability from the rule's
  tier network and narrows the dropdown to whatever the provider
  actually accepts.

LoadBalancing.vue: keeps its existing per-network lookup but adds a
fallback for the VPC case. When the public IP record exposes only
vpcid (the IP has not been associated to a specific tier yet because
no rule exists), the helper now picks any Lb-enabled tier of the VPC
via listNetworks(vpcid=..., supportedservices=Lb) and reads the
capability from that tier. Every tier of the same VPC uses the same
Lb provider, so the answer is provider-uniform.

The change is provider-agnostic - any Lb provider that correctly
declares Service.Lb -> Capability.SupportedLBAlgorithms benefits.
The OVN provider exposes {roundrobin, source}, VirtualRouter keeps
{roundrobin, leastconn, source}, NetScaler / F5 / etc. will reflect
whatever they declare, and providers without the capability fall
back to the legacy three. listNetworks remains the right endpoint
because the offering response only emits a fixed subset of Lb
capabilities while createNetworkResponse walks the live provider's
getCapabilities() and surfaces SupportedLbAlgorithms verbatim.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@msinhore
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.