diff --git a/.asf.yaml b/.asf.yaml
index 43f0351bc7c..be818fda4d3 100644
--- a/.asf.yaml
+++ b/.asf.yaml
@@ -53,11 +53,12 @@ github:
- acs-robot
- gpordeus
- hsato03
- - bernardodemarco
- - abh1sar
- FelipeM525
- lucas-a-martins
- nicoschmdt
+ - abh1sar
+ - rosi-shapeblue
+ - sudo87
protected_branches: ~
diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml
index 5e8d65905eb..531c26ace44 100644
--- a/.github/linters/.markdown-lint.yml
+++ b/.github/linters/.markdown-lint.yml
@@ -86,3 +86,6 @@ MD046: false
# MD052/reference-links-images Reference links and images should use a label that is defined
MD052: false
+
+# MD059/descriptive-link-text Link text should be descriptive
+MD059: false
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index fd3c8f8ac67..06f9f424c7f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -32,13 +32,12 @@ jobs:
steps:
- uses: actions/checkout@v4
- - name: Set up JDK 11
+ - name: Set up JDK 17
uses: actions/setup-java@v4
with:
- java-version: '11'
- distribution: 'adopt'
- architecture: x64
- cache: maven
+ distribution: 'temurin'
+ java-version: '17'
+ cache: 'maven'
- name: Set up Python
uses: actions/setup-python@v5
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ceffb42c79b..471e56e3f07 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -89,7 +89,10 @@ jobs:
smoke/test_nested_virtualization
smoke/test_set_sourcenat
smoke/test_webhook_lifecycle
- smoke/test_purge_expunged_vms",
+ smoke/test_purge_expunged_vms
+ smoke/test_extension_lifecycle
+ smoke/test_extension_custom_action_lifecycle
+ smoke/test_extension_custom",
"smoke/test_network
smoke/test_network_acl
smoke/test_network_ipv6
@@ -137,6 +140,7 @@ jobs:
smoke/test_vm_deployment_planner
smoke/test_vm_strict_host_tags
smoke/test_vm_schedule
+ smoke/test_deploy_vgpu_enabled_vm
smoke/test_vm_life_cycle
smoke/test_vm_lifecycle_unmanage_import
smoke/test_vm_snapshot_kvm
@@ -164,7 +168,8 @@ jobs:
component/test_cpu_limits
component/test_cpu_max_limits
component/test_cpu_project_limits
- component/test_deploy_vm_userdata_multi_nic",
+ component/test_deploy_vm_userdata_multi_nic
+ component/test_deploy_vm_lease",
"component/test_egress_fw_rules
component/test_invalid_gw_nm
component/test_ip_reservation",
@@ -215,13 +220,12 @@ jobs:
with:
fetch-depth: 0
- - name: Set up JDK
+ - name: Set up JDK 17
uses: actions/setup-java@v4
with:
- java-version: '11'
- distribution: 'adopt'
- architecture: x64
- cache: maven
+ distribution: 'temurin'
+ java-version: '17'
+ cache: 'maven'
- name: Set up Python
uses: actions/setup-python@v5
@@ -236,7 +240,7 @@ jobs:
- name: Install Python dependencies
run: |
- python3 -m pip install --user --upgrade urllib3 lxml paramiko nose texttable ipmisim pyopenssl pycrypto mock flask netaddr pylint pycodestyle six astroid
+ python3 -m pip install --user --upgrade urllib3 lxml paramiko nose texttable ipmisim pyopenssl pycryptodome mock flask netaddr pylint pycodestyle six astroid pynose
- name: Install jacoco dependencies
run: |
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 00000000000..85f348b35bf
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,48 @@
+# 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.
+
+name: CodeQL Analysis
+on:
+ push:
+ branches: [main]
+ pull_request:
+ branches: [main]
+permissions:
+ actions: read
+ contents: read
+ security-events: write
+jobs:
+ codeql:
+ name: CodeQL
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ language: ["actions"]
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: ${{ matrix.language }}
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v3
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "Security"
diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml
index b6c814a36f4..0bc87c6cc13 100644
--- a/.github/workflows/linter.yml
+++ b/.github/workflows/linter.yml
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
-name: Lint
+name: pre-commit
on: [pull_request]
diff --git a/.github/workflows/main-sonar-check.yml b/.github/workflows/main-sonar-check.yml
index 8248e48022a..dccd7174e54 100644
--- a/.github/workflows/main-sonar-check.yml
+++ b/.github/workflows/main-sonar-check.yml
@@ -54,7 +54,7 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.m2/repository
- key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+ key: ${{ runner.os }}-m2-${{ hashFiles('pom.xml', '*/pom.xml', '*/*/pom.xml', '*/*/*/pom.xml') }}
restore-keys: |
${{ runner.os }}-m2
diff --git a/.github/workflows/sonar-check.yml b/.github/workflows/sonar-check.yml
index c36bceb2b90..d31f55980a8 100644
--- a/.github/workflows/sonar-check.yml
+++ b/.github/workflows/sonar-check.yml
@@ -56,7 +56,7 @@ jobs:
uses: actions/cache@v4
with:
path: ~/.m2/repository
- key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+ key: ${{ runner.os }}-m2-${{ hashFiles('pom.xml', '*/pom.xml', '*/*/pom.xml', '*/*/*/pom.xml') }}
restore-keys: |
${{ runner.os }}-m2
diff --git a/.github/workflows/ui.yml b/.github/workflows/ui.yml
index 56f757133b7..88d4a70e4c2 100644
--- a/.github/workflows/ui.yml
+++ b/.github/workflows/ui.yml
@@ -56,6 +56,7 @@ jobs:
npm run test:unit
- uses: codecov/codecov-action@v4
+ if: github.repository == 'apache/cloudstack'
with:
working-directory: ui
files: ./coverage/lcov.info
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index a9bc87454f1..46db709c3fe 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -15,23 +15,31 @@
# specific language governing permissions and limitations
# under the License.
---
-default_stages: [commit, push]
+default_stages: [pre-commit, pre-push]
default_language_version:
# force all unspecified Python hooks to run python3
python: python3
-minimum_pre_commit_version: "2.17.0"
+minimum_pre_commit_version: "3.2.0"
repos:
- repo: meta
hooks:
- id: identity
- id: check-hooks-apply
+ - repo: https://github.com/gitleaks/gitleaks
+ rev: v8.27.2
+ hooks:
+ - id: gitleaks
+ name: run gitleaks
+ description: detect hardcoded secrets
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.6.0
+ rev: v5.0.0
hooks:
#- id: check-added-large-files
- id: check-case-conflict
#- id: check-executables-have-shebangs
- id: check-merge-conflict
+ - id: check-shebang-scripts-are-executable
+ files: \.sh$
- id: check-symlinks
- id: check-vcs-permalinks
#- id: check-yaml
@@ -42,6 +50,7 @@ repos:
exclude: >
(?x)
^scripts/vm/systemvm/id_rsa\.cloud$|
+ ^server/src/test/java/org/apache/cloudstack/network/ssl/CertServiceTest.java$|
^server/src/test/java/com/cloud/keystore/KeystoreTest\.java$|
^server/src/test/resources/certs/dsa_self_signed\.key$|
^server/src/test/resources/certs/non_root\.key$|
@@ -51,7 +60,8 @@ repos:
^server/src/test/resources/certs/rsa_self_signed\.key$|
^services/console-proxy/rdpconsole/src/test/doc/rdp-key\.pem$|
^systemvm/agent/certs/localhost\.key$|
- ^systemvm/agent/certs/realhostip\.key$
+ ^systemvm/agent/certs/realhostip\.key$|
+ ^test/integration/smoke/test_ssl_offloading.py$
- id: end-of-file-fixer
exclude: \.vhd$
- id: fix-byte-order-marker
@@ -59,7 +69,7 @@ repos:
- id: mixed-line-ending
exclude: \.cs$
- id: trailing-whitespace
- files: \.(bat|cfg|cs|css|gitignore|header|in|install|java|md|properties|py|rb|sh|sql|txt|vue|xml|xsl|yaml|yml)$
+ files: \.(bat|cfg|cs|css|gitignore|header|in|install|java|md|properties|py|rb|rc|sh|sql|te|template|txt|ucls|vue|xml|xsl|yaml|yml)$|^cloud-cli/bindir/cloud-tool$|^debian/changelog$
args: [--markdown-linebreak-ext=md]
exclude: ^services/console-proxy/rdpconsole/src/test/doc/freerdp-debug-log\.txt$
- repo: https://github.com/codespell-project/codespell
@@ -69,25 +79,14 @@ repos:
name: run codespell
description: Check spelling with codespell
args: [--ignore-words=.github/linters/codespell.txt]
- exclude: ^ui/package\.json$|^ui/package-lock\.json$|^ui/public/js/less\.min\.js$|^ui/public/locales/.*[^n].*\.json$
+ exclude: ^systemvm/agent/noVNC/|^ui/package\.json$|^ui/package-lock\.json$|^ui/public/js/less\.min\.js$|^ui/public/locales/.*[^n].*\.json$|^server/src/test/java/org/apache/cloudstack/network/ssl/CertServiceTest.java$|^test/integration/smoke/test_ssl_offloading.py$
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
- id: flake8
args: [--config, .github/linters/.flake8]
- exclude: >
- (?x)
- ^agent/bindir/cloud-setup-agent\.in$|
- ^client/bindir/cloud-update-xenserver-licenses\.in$|
- ^cloud-cli/bindir/cloud-tool$|
- ^python/bindir/cloud-grab-dependent-library-versions$|
- ^python/bindir/cloud-setup-baremetal$|
- ^scripts/vm/hypervisor/xenserver/storagePlugin$|
- ^scripts/vm/hypervisor/xenserver/vmopspremium$|
- ^setup/bindir/cloud-setup-encryption\.in$|
- ^venv/.*$
- repo: https://github.com/igorshubovych/markdownlint-cli
- rev: v0.43.0
+ rev: v0.45.0
hooks:
- id: markdownlint
name: run markdownlint
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a6d006938f3..17ff4badc97 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,9 +4,9 @@ Contributing to Apache CloudStack (ACS)
Summary
-------
This document covers how to contribute to the ACS project. ACS uses GitHub PRs to manage code contributions.
-These instructions assume you have a GitHub.com account, so if you don't have one you will have to create one. Your proposed code changes will be published to your own fork of the ACS project and you will submit a Pull Request for your changes to be added.
+These instructions assume you have a GitHub.com account, so if you don't have one you will have to create one. Your proposed code changes will be published to your own fork of the ACS project, and you will submit a Pull Request for your changes to be added.
-_Lets get started!!!_
+_Let's get started!!!_
Bug fixes
---------
@@ -26,7 +26,7 @@ No back porting / cherry-picking features to existing branches!
PendingReleaseNotes file
------------------------
-When developing a new feature or making a (major) change to a existing feature you are encouraged to append this to the PendingReleaseNotes file so that the Release Manager can
+When developing a new feature or making a (major) change to an existing feature you are encouraged to append this to the PendingReleaseNotes file so that the Release Manager can
use this file as a source of information when compiling the Release Notes for a new release.
When adding information to the PendingReleaseNotes file make sure that you write a good and understandable description of the new feature or change which you have developed.
@@ -38,9 +38,9 @@ Fork the code
In your browser, navigate to: [https://github.com/apache/cloudstack](https://github.com/apache/cloudstack)
-Fork the repository by clicking on the 'Fork' button on the top right hand side. The fork will happen and you will be taken to your own fork of the repository. Copy the Git repository URL by clicking on the clipboard next to the URL on the right hand side of the page under '**HTTPS** clone URL'. You will paste this URL when doing the following `git clone` command.
+Fork the repository by clicking on the 'Fork' button on the top right hand side. The fork will happen, and you will be taken to your own fork of the repository. Copy the Git repository URL by clicking on the clipboard next to the URL on the right hand side of the page under '**HTTPS** clone URL'. You will paste this URL when doing the following `git clone` command.
-On your computer, follow these steps to setup a local repository for working on ACS:
+On your computer, follow these steps to set up a local repository for working on ACS:
```bash
$ git clone https://github.com/YOUR_ACCOUNT/cloudstack.git
@@ -92,9 +92,9 @@ $ git rebase main
Make a GitHub Pull Request to contribute your changes
-----------------------------------------------------
-When you are happy with your changes and you are ready to contribute them, you will create a Pull Request on GitHub to do so. This is done by pushing your local changes to your forked repository (default remote name is `origin`) and then initiating a pull request on GitHub.
+When you are happy with your changes, and you are ready to contribute them, you will create a Pull Request on GitHub to do so. This is done by pushing your local changes to your forked repository (default remote name is `origin`) and then initiating a pull request on GitHub.
-Please include JIRA id, detailed information about the bug/feature, what all tests are executed, how the reviewer can test this feature etc. Incase of UI PRs, a screenshot is preferred.
+Please include JIRA id, detailed information about the bug/feature, what all tests are executed, how the reviewer can test this feature etc. In case of UI PRs, a screenshot is preferred.
> **IMPORTANT:** Make sure you have rebased your `feature_x` branch to include the latest code from `upstream/main` _before_ you do this.
diff --git a/INSTALL.md b/INSTALL.md
index e133e7d7b91..efb42678b0a 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -18,25 +18,26 @@ Install tools and dependencies used for development:
# yum -y install git java-17-openjdk java-17-openjdk-devel \
mysql mysql-server mkisofs git gcc python MySQL-python openssh-clients wget
-Set up Maven (3.6.0):
+Set up Maven (3.9.10):
- # wget http://www.us.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
- # tar -zxvf apache-maven-3.6.3-bin.tar.gz -C /usr/local
+ # wget https://dlcdn.apache.org/maven/maven-3/3.9.10/binaries/apache-maven-3.9.10-bin.tar.gz
+ # sudo tar -zxvf apache-maven-3.9.10-bin.tar.gz -C /usr/local
# cd /usr/local
- # ln -s apache-maven-3.6.3 maven
+ # sudo ln -s apache-maven-3.9.10 maven
# echo export M2_HOME=/usr/local/maven >> ~/.bashrc # or .zshrc or .profile
# echo export PATH=/usr/local/maven/bin:${PATH} >> ~/.bashrc # or .zshrc or .profile
# source ~/.bashrc
-Setup up NodeJS (LTS):
+Setup up Node.js 16:
- # curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash -
+ # curl -sL https://rpm.nodesource.com/setup_16.x | sudo -E bash -
# sudo yum install nodejs
# sudo npm install -g @vue/cli npm-check-updates
Start the MySQL service:
$ service mysqld start
+ $ mysql_secure_installation
### Using jenv and/or pyenv for Version Management
@@ -86,13 +87,33 @@ Start the management server:
If this works, you've successfully setup a single server Apache CloudStack installation.
-Open the following URL on your browser to access the Management Server UI:
-
- http://localhost:8080/client/
+To access the Management Server UI, follow the following procedure:
The default credentials are; user: admin, password: password and the domain
field should be left blank which is defaulted to the ROOT domain.
+## To bring up CloudStack UI
+
+Move to UI Directory
+
+ $ cd /path/to/cloudstack/ui
+
+To install dependencies.
+
+ $ npm install
+
+To build the project.
+
+ $ npm run build
+
+For Development Mode.
+
+ $ npm start
+
+Make sure to set `CS_URL=http://localhost:8080` on the `.env.local` file on UI.
+
+You should be able to run the management server on http://localhost:5050
+
## Building with non-redistributable plugins
CloudStack supports several plugins that depend on libraries with distribution restrictions.
diff --git a/README.md b/README.md
index f66a4dc6f97..2403b20d652 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,14 @@
-# Apache CloudStack [](https://github.com/apache/cloudstack/actions/workflows/build.yml) [](https://github.com/apache/cloudstack/actions/workflows/ui.yml) [](https://github.com/apache/cloudstack/actions/workflows/rat.yml) [](https://github.com/apache/cloudstack/actions/workflows/ci.yml) [](https://sonarcloud.io/dashboard?id=apache_cloudstack) [](https://codecov.io/gh/apache/cloudstack)
+# Apache CloudStack
+
+[](https://github.com/apache/cloudstack/actions/workflows/build.yml)
+[](https://codecov.io/gh/apache/cloudstack)
+[](https://github.com/apache/cloudstack/actions/workflows/docker-cloudstack-simulator.yml)
+[](https://github.com/apache/cloudstack/actions/workflows/rat.yml)
+[](https://github.com/apache/cloudstack/actions/workflows/linter.yml)
+[](https://github.com/apache/cloudstack/actions/workflows/merge-conflict-checker.yml)
+[](https://sonarcloud.io/dashboard?id=apache_cloudstack)
+[](https://github.com/apache/cloudstack/actions/workflows/ci.yml)
+[](https://github.com/apache/cloudstack/actions/workflows/ui.yml)
[](https://cloudstack.apache.org/)
@@ -160,3 +170,11 @@ The following provides more details on the included cryptographic software:
* CloudStack makes use of the Bouncy Castle general-purpose encryption library.
* CloudStack can optionally interact with and control OpenSwan-based VPNs.
* CloudStack has a dependency on and makes use of JSch - a java SSH2 implementation.
+
+## Star History
+
+[](https://www.star-history.com/#apache/cloudstack&Date)
+
+## Contributors
+
+[](https://github.com/apache/cloudstack/graphs/contributors)
diff --git a/agent/bindir/cloud-setup-agent.in b/agent/bindir/cloud-setup-agent.in
index 18de64089ed..dc4582540df 100755
--- a/agent/bindir/cloud-setup-agent.in
+++ b/agent/bindir/cloud-setup-agent.in
@@ -20,9 +20,22 @@ import os
import logging
import sys
import socket
+
+# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
+# ---- We do this so cloud_utils can be looked up in the following order:
+# ---- 1) Sources directory
+# ---- 2) waf configured PYTHONDIR
+# ---- 3) System Python path
+for pythonpath in (
+ "@PYTHONDIR@",
+ os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
+ ):
+ if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
+# ---- End snippet of code ----
+
from cloudutils.cloudException import CloudRuntimeException, CloudInternalException
from cloudutils.utilities import initLoging, bash
-from cloudutils.configFileOps import configFileOps
+from cloudutils.configFileOps import configFileOps
from cloudutils.globalEnv import globalEnv
from cloudutils.networkConfig import networkConfig
from cloudutils.syscfg import sysConfigFactory
@@ -30,35 +43,41 @@ from cloudutils.serviceConfig import configureLibvirtConfig, configure_libvirt_t
from optparse import OptionParser
+
def getUserInputs():
print("Welcome to the CloudStack Agent Setup:")
cfo = configFileOps("@AGENTSYSCONFDIR@/agent.properties")
oldMgt = cfo.getEntry("host")
- mgtSvr = input("Please input the Management Server Hostname/IP-Address:[%s]"%oldMgt)
+ mgtSvr = input(
+ "Please input the Management Server Hostname/IP-Address:[%s]" % oldMgt
+ )
if mgtSvr == "":
mgtSvr = oldMgt
try:
socket.getaddrinfo(mgtSvr, 443)
except:
- print("Failed to resolve %s. Please input a valid hostname or IP-Address."%mgtSvr)
+ print(
+ "Failed to resolve %s. Please input a valid hostname or IP-Address."
+ % mgtSvr
+ )
exit(1)
oldToken = cfo.getEntry("zone")
- zoneToken = input("Please input the Zone Id:[%s]"%oldToken)
+ zoneToken = input("Please input the Zone Id:[%s]" % oldToken)
if zoneToken == "":
zoneToken = oldToken
oldPod = cfo.getEntry("pod")
- podId = input("Please input the Pod Id:[%s]"%oldPod)
+ podId = input("Please input the Pod Id:[%s]" % oldPod)
if podId == "":
- podId = oldToken
+ podId = oldToken
oldCluster = cfo.getEntry("cluster")
- clusterId = input("Please input the Cluster Id:[%s]"%oldCluster)
+ clusterId = input("Please input the Cluster Id:[%s]" % oldCluster)
if clusterId == "":
clusterId = oldCluster
@@ -66,18 +85,20 @@ def getUserInputs():
if oldHypervisor == "":
oldHypervisor = "kvm"
- hypervisor = input("Please input the Hypervisor type kvm/lxc:[%s]"%oldHypervisor)
+ hypervisor = input("Please input the Hypervisor type kvm/lxc:[%s]" % oldHypervisor)
if hypervisor == "":
hypervisor = oldHypervisor
try:
defaultNic = networkConfig.getDefaultNetwork()
except:
- print("Failed to get default route. Please configure your network to have a default route")
+ print(
+ "Failed to get default route. Please configure your network to have a default route"
+ )
exit(1)
defNic = defaultNic.name
- network = input("Please choose which network used to create VM:[%s]"%defNic)
+ network = input("Please choose which network used to create VM:[%s]" % defNic)
if network == "":
if defNic == "":
print("You need to specify one of Nic or bridge on your system")
@@ -87,7 +108,8 @@ def getUserInputs():
return [mgtSvr, zoneToken, network, podId, clusterId, hypervisor]
-if __name__ == '__main__':
+
+if __name__ == "__main__":
initLoging("@AGENTLOGDIR@/setup.log")
glbEnv = globalEnv()
@@ -95,13 +117,23 @@ if __name__ == '__main__':
glbEnv.agentMode = "Agent"
parser = OptionParser()
parser.add_option("-a", action="store_true", dest="auto", help="auto mode")
- parser.add_option("-m", "--host", dest="mgt", help="Management server hostname or IP-Address")
+ parser.add_option(
+ "-m", "--host", dest="mgt", help="Management server hostname or IP-Address"
+ )
parser.add_option("-z", "--zone", dest="zone", help="zone id")
parser.add_option("-p", "--pod", dest="pod", help="pod id")
parser.add_option("-c", "--cluster", dest="cluster", help="cluster id")
- parser.add_option("-t", "--hypervisor", default="kvm", dest="hypervisor", help="hypervisor type")
+ parser.add_option(
+ "-t", "--hypervisor", default="kvm", dest="hypervisor", help="hypervisor type"
+ )
parser.add_option("-g", "--guid", dest="guid", help="guid")
- parser.add_option("-s", action="store_true", default=False, dest="secure", help="Secure and enable TLS for libvirtd")
+ parser.add_option(
+ "-s",
+ action="store_true",
+ default=False,
+ dest="secure",
+ help="Secure and enable TLS for libvirtd",
+ )
parser.add_option("--pubNic", dest="pubNic", help="Public traffic interface")
parser.add_option("--prvNic", dest="prvNic", help="Private traffic interface")
parser.add_option("--guestNic", dest="guestNic", help="Guest traffic interface")
@@ -127,15 +159,15 @@ if __name__ == '__main__':
glbEnv.pod = userInputs[3]
glbEnv.cluster = userInputs[4]
glbEnv.hypervisor = userInputs[5]
- #generate UUID
+ # generate UUID
glbEnv.uuid = old_config.getEntry("guid")
if glbEnv.uuid == "":
glbEnv.uuid = bash("uuidgen").getStdout()
else:
for para, value in list(options.__dict__.items()):
if value is None:
- print("Missing operand:%s"%para)
- print("Try %s --help for more information"%sys.argv[0])
+ print("Missing operand:%s" % para)
+ print("Try %s --help for more information" % sys.argv[0])
sys.exit(1)
glbEnv.uuid = options.guid
@@ -155,7 +187,7 @@ if __name__ == '__main__':
try:
syscfg.config()
print("CloudStack Agent setup is done!")
- except (CloudRuntimeException,CloudInternalException) as e:
+ except (CloudRuntimeException, CloudInternalException) as e:
print(e)
print("Try to restore your system:")
try:
diff --git a/agent/bindir/libvirtqemuhook.in b/agent/bindir/libvirtqemuhook.in
index e17944d8353..4cc6ed7a1d2 100755
--- a/agent/bindir/libvirtqemuhook.in
+++ b/agent/bindir/libvirtqemuhook.in
@@ -20,6 +20,19 @@ import sys
import os
import subprocess
from threading import Timer
+
+# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
+# ---- We do this so cloud_utils can be looked up in the following order:
+# ---- 1) Sources directory
+# ---- 2) waf configured PYTHONDIR
+# ---- 3) System Python path
+for pythonpath in (
+ "@PYTHONDIR@",
+ os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
+ ):
+ if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
+# ---- End snippet of code ----
+
from xml.dom.minidom import parse
from cloudutils.configFileOps import configFileOps
from cloudutils.networkConfig import networkConfig
diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties
index bff7078fd9f..2a083de6fe5 100644
--- a/agent/conf/agent.properties
+++ b/agent/conf/agent.properties
@@ -213,8 +213,9 @@ hypervisor.type=kvm
# If null (default), defaults to the VM's OS architecture
#guest.cpu.arch=
-# This param will require CPU features on the CPU section.
-# The features listed in this property must be separated by a blank space (e.g.: vmx vme)
+# Specifies required CPU features for end-user and system VMs.
+# These features must be present on the host CPU for VM deployment.
+# Multiple features should be separated by whitespace (e.g.: vmx vme).
#guest.cpu.features=
# Disables memory ballooning on VM guests for overcommit.
@@ -441,3 +442,12 @@ iscsi.session.cleanup.enabled=false
# Wait(in seconds) during agent reconnections. When no value is set then default value of 5s will be used
#backoff.seconds=
+
+# Timeout (in seconds) to wait for the snapshot reversion to complete.
+# revert.snapshot.timeout=10800
+
+# Timeout (in seconds) to wait for the incremental snapshot to complete.
+# incremental.snapshot.timeout=10800
+
+# If set to true, creates VMs as full clones of their templates on KVM hypervisor. Creates as linked clones otherwise.
+# create.full.clone=false
diff --git a/agent/conf/developer.properties.template b/agent/conf/developer.properties.template
index a70a136f38c..02f51aa6bb8 100644
--- a/agent/conf/developer.properties.template
+++ b/agent/conf/developer.properties.template
@@ -5,9 +5,9 @@
# 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
diff --git a/agent/pom.xml b/agent/pom.xml
index 76c37cd87be..0fd7d35823e 100644
--- a/agent/pom.xml
+++ b/agent/pom.xml
@@ -24,7 +24,7 @@
org.apache.cloudstack
cloudstack
- 4.21.0.0-SNAPSHOT
+ 4.22.0.0-SNAPSHOT
diff --git a/agent/src/main/java/com/cloud/agent/Agent.java b/agent/src/main/java/com/cloud/agent/Agent.java
index 0a76bfbb4f8..e86557e9681 100644
--- a/agent/src/main/java/com/cloud/agent/Agent.java
+++ b/agent/src/main/java/com/cloud/agent/Agent.java
@@ -97,7 +97,6 @@ import com.cloud.utils.nio.Link;
import com.cloud.utils.nio.NioClient;
import com.cloud.utils.nio.NioConnection;
import com.cloud.utils.nio.Task;
-import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
/**
@@ -342,7 +341,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...", e);
}
}
- shell.updateConnectedHost();
+ shell.updateConnectedHost(((NioClient)connection).getHost());
scavengeOldAgentObjects();
}
@@ -453,22 +452,30 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
certExecutor.schedule(new PostCertificateRenewalTask(this), 5, TimeUnit.SECONDS);
}
- private void scheduleHostLBCheckerTask(final long checkInterval) {
+ private void scheduleHostLBCheckerTask(final String lbAlgorithm, final long checkInterval) {
String name = "HostLBCheckerTask";
if (hostLbCheckExecutor != null && !hostLbCheckExecutor.isShutdown()) {
+ logger.info("Shutting down the preferred host checker task {}", name);
hostLbCheckExecutor.shutdown();
try {
if (!hostLbCheckExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
hostLbCheckExecutor.shutdownNow();
}
} catch (InterruptedException e) {
- logger.debug("Forcing {} shutdown as it did not shutdown in the desired time due to: {}",
+ logger.debug("Forcing the preferred host checker task {} shutdown as it did not shutdown in the desired time due to: {}",
name, e.getMessage());
hostLbCheckExecutor.shutdownNow();
}
}
if (checkInterval > 0L) {
- logger.info("Scheduling preferred host task with host.lb.interval={}ms", checkInterval);
+ if ("shuffle".equalsIgnoreCase(lbAlgorithm)) {
+ logger.info("Scheduling the preferred host checker task to trigger once (to apply lb algorithm '{}') after host.lb.interval={} ms", lbAlgorithm, checkInterval);
+ hostLbCheckExecutor = Executors.newSingleThreadScheduledExecutor((new NamedThreadFactory(name)));
+ hostLbCheckExecutor.schedule(new PreferredHostCheckerTask(), checkInterval, TimeUnit.MILLISECONDS);
+ return;
+ }
+
+ logger.info("Scheduling a recurring preferred host checker task with host.lb.interval={} ms", checkInterval);
hostLbCheckExecutor = Executors.newSingleThreadScheduledExecutor((new NamedThreadFactory(name)));
hostLbCheckExecutor.scheduleAtFixedRate(new PreferredHostCheckerTask(), checkInterval, checkInterval,
TimeUnit.MILLISECONDS);
@@ -606,9 +613,9 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
protected String getAgentArch() {
- final Script command = new Script("/usr/bin/arch", 500, logger);
- final OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser();
- return command.execute(parser);
+ String arch = Script.runSimpleBashScript(Script.getExecutableAbsolutePath("arch"), 1000);
+ logger.debug("Arch for agent: {} found: {}", _name, arch);
+ return arch;
}
@Override
@@ -617,15 +624,11 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
protected void reconnect(final Link link) {
- reconnect(link, null, null, false);
+ reconnect(link, null, false);
}
- protected void reconnect(final Link link, String preferredHost, List avoidHostList, boolean forTransfer) {
+ protected void reconnect(final Link link, String preferredMSHost, boolean forTransfer) {
if (!(forTransfer || reconnectAllowed)) {
- return;
- }
-
- if (!reconnectAllowed) {
logger.debug("Reconnect requested but it is not allowed {}", () -> getLinkLog(link));
return;
}
@@ -637,19 +640,26 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
serverResource.disconnected();
logger.info("Lost connection to host: {}. Attempting reconnection while we still have {} commands in progress.", shell.getConnectedHost(), commandsInProgress.get());
stopAndCleanupConnection(true);
+ String host = preferredMSHost;
+ if (org.apache.commons.lang3.StringUtils.isBlank(host)) {
+ host = shell.getNextHost();
+ }
+ List avoidMSHostList = shell.getAvoidHosts();
do {
- final String host = shell.getNextHost();
- connection = new NioClient(getAgentName(), host, shell.getPort(), shell.getWorkers(), shell.getSslHandshakeTimeout(), this);
- logger.info("Reconnecting to host: {}", host);
- try {
- connection.start();
- } catch (final NioConnectionException e) {
- logger.info("Attempted to re-connect to the server, but received an unexpected exception, trying again...", e);
- stopAndCleanupConnection(false);
+ if (CollectionUtils.isEmpty(avoidMSHostList) || !avoidMSHostList.contains(host)) {
+ connection = new NioClient(getAgentName(), host, shell.getPort(), shell.getWorkers(), shell.getSslHandshakeTimeout(), this);
+ logger.info("Reconnecting to host: {}", host);
+ try {
+ connection.start();
+ } catch (final NioConnectionException e) {
+ logger.info("Attempted to re-connect to the server, but received an unexpected exception, trying again...", e);
+ stopAndCleanupConnection(false);
+ }
}
shell.getBackoffAlgorithm().waitBeforeRetry();
+ host = shell.getNextHost();
} while (!connection.isStartup());
- shell.updateConnectedHost();
+ shell.updateConnectedHost(((NioClient)connection).getHost());
logger.info("Connected to the host: {}", shell.getConnectedHost());
}
@@ -797,6 +807,9 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
commandsInProgress.incrementAndGet();
try {
+ if (cmd.isReconcile()) {
+ cmd.setRequestSequence(request.getSequence());
+ }
answer = serverResource.executeRequest(cmd);
} finally {
commandsInProgress.decrementAndGet();
@@ -922,7 +935,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
return new SetupCertificateAnswer(true);
}
- private void processManagementServerList(final List msList, final String lbAlgorithm, final Long lbCheckInterval) {
+ private void processManagementServerList(final List msList, final List avoidMsList, final String lbAlgorithm, final Long lbCheckInterval, final boolean triggerHostLB) {
if (CollectionUtils.isNotEmpty(msList) && StringUtils.isNotEmpty(lbAlgorithm)) {
try {
final String newMSHosts = String.format("%s%s%s", com.cloud.utils.StringUtils.toCSVList(msList), IAgentShell.hostLbAlgorithmSeparator, lbAlgorithm);
@@ -934,24 +947,31 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
throw new CloudRuntimeException("Could not persist received management servers list", e);
}
}
- if ("shuffle".equals(lbAlgorithm)) {
- scheduleHostLBCheckerTask(0);
- } else {
- scheduleHostLBCheckerTask(shell.getLbCheckerInterval(lbCheckInterval));
+ shell.setAvoidHosts(avoidMsList);
+ if (triggerHostLB) {
+ logger.info("Triggering the preferred host checker task now");
+ ScheduledExecutorService hostLbExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("HostLB-Executor"));
+ hostLbExecutor.schedule(new PreferredHostCheckerTask(), 0, TimeUnit.MILLISECONDS);
+ hostLbExecutor.shutdown();
}
+ scheduleHostLBCheckerTask(lbAlgorithm, shell.getLbCheckerInterval(lbCheckInterval));
}
private Answer setupManagementServerList(final SetupMSListCommand cmd) {
- processManagementServerList(cmd.getMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval());
+ processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval(), cmd.getTriggerHostLb());
return new SetupMSListAnswer(true);
}
private Answer migrateAgentToOtherMS(final MigrateAgentConnectionCommand cmd) {
try {
if (CollectionUtils.isNotEmpty(cmd.getMsList())) {
- processManagementServerList(cmd.getMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval());
+ processManagementServerList(cmd.getMsList(), cmd.getAvoidMsList(), cmd.getLbAlgorithm(), cmd.getLbCheckInterval(), false);
}
- migrateAgentConnection(cmd.getAvoidMsList());
+ ScheduledExecutorService migrateAgentConnectionService = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("MigrateAgentConnection-Job"));
+ migrateAgentConnectionService.schedule(() -> {
+ migrateAgentConnection(cmd.getAvoidMsList());
+ }, 3, TimeUnit.SECONDS);
+ migrateAgentConnectionService.shutdown();
} catch (Exception e) {
String errMsg = "Migrate agent connection failed, due to " + e.getMessage();
logger.debug(errMsg, e);
@@ -972,25 +992,26 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
throw new CloudRuntimeException("No other Management Server hosts to migrate");
}
- String preferredHost = null;
+ String preferredMSHost = null;
for (String msHost : msHostsList) {
try (final Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(msHost, shell.getPort()), 5000);
- preferredHost = msHost;
+ preferredMSHost = msHost;
break;
} catch (final IOException e) {
throw new CloudRuntimeException("Management server host: " + msHost + " is not reachable, to migrate connection");
}
}
- if (preferredHost == null) {
+ if (preferredMSHost == null) {
throw new CloudRuntimeException("Management server host(s) are not reachable, to migrate connection");
}
- logger.debug("Management server host " + preferredHost + " is found to be reachable, trying to reconnect");
+ logger.debug("Management server host " + preferredMSHost + " is found to be reachable, trying to reconnect");
shell.resetHostCounter();
+ shell.setAvoidHosts(avoidMsList);
shell.setConnectionTransfer(true);
- reconnect(link, preferredHost, avoidMsList, true);
+ reconnect(link, preferredMSHost, true);
}
public void processResponse(final Response response, final Link link) {
@@ -1003,14 +1024,23 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
for (final IAgentControlListener listener : controlListeners) {
listener.processControlResponse(response, (AgentControlAnswer)answer);
}
- } else if (answer instanceof PingAnswer && (((PingAnswer) answer).isSendStartup()) && reconnectAllowed) {
- logger.info("Management server requested startup command to reinitialize the agent");
- sendStartup(link);
+ } else if (answer instanceof PingAnswer) {
+ processPingAnswer((PingAnswer) answer);
} else {
updateLastPingResponseTime();
}
}
+ private void processPingAnswer(final PingAnswer answer) {
+ if ((answer.isSendStartup()) && reconnectAllowed) {
+ logger.info("Management server requested startup command to reinitialize the agent");
+ sendStartup(link);
+ } else {
+ serverResource.processPingAnswer((PingAnswer) answer);
+ }
+ shell.setAvoidHosts(answer.getAvoidMsList());
+ }
+
public void processReadyCommand(final Command cmd) {
final ReadyCommand ready = (ReadyCommand)cmd;
// Set human readable sizes;
@@ -1027,7 +1057,7 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
verifyAgentArch(ready.getArch());
- processManagementServerList(ready.getMsHostList(), ready.getLbAlgorithm(), ready.getLbCheckInterval());
+ processManagementServerList(ready.getMsHostList(), ready.getAvoidMsHostList(), ready.getLbAlgorithm(), ready.getLbCheckInterval(), false);
logger.info("Ready command is processed for agent [id: {}, uuid: {}, name: {}]", getId(), getUuid(), getName());
}
@@ -1073,6 +1103,9 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
Answer answer = null;
commandsInProgress.incrementAndGet();
try {
+ if (command.isReconcile()) {
+ command.setRequestSequence(req.getSequence());
+ }
answer = serverResource.executeRequest(command);
} finally {
commandsInProgress.decrementAndGet();
@@ -1374,26 +1407,26 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
if (msList == null || msList.length < 1) {
return;
}
- final String preferredHost = msList[0];
+ final String preferredMSHost = msList[0];
final String connectedHost = shell.getConnectedHost();
logger.debug("Running preferred host checker task, connected host={}, preferred host={}",
- connectedHost, preferredHost);
- if (preferredHost == null || preferredHost.equals(connectedHost) || link == null) {
+ connectedHost, preferredMSHost);
+ if (preferredMSHost == null || preferredMSHost.equals(connectedHost) || link == null) {
return;
}
boolean isHostUp = false;
try (final Socket socket = new Socket()) {
- socket.connect(new InetSocketAddress(preferredHost, shell.getPort()), 5000);
+ socket.connect(new InetSocketAddress(preferredMSHost, shell.getPort()), 5000);
isHostUp = true;
} catch (final IOException e) {
- logger.debug("Host: {} is not reachable", preferredHost);
+ logger.debug("Host: {} is not reachable", preferredMSHost);
}
if (isHostUp && link != null && commandsInProgress.get() == 0) {
if (logger.isDebugEnabled()) {
- logger.debug("Preferred host {} is found to be reachable, trying to reconnect", preferredHost);
+ logger.debug("Preferred host {} is found to be reachable, trying to reconnect", preferredMSHost);
}
shell.resetHostCounter();
- reconnect(link);
+ reconnect(link, preferredMSHost, false);
}
} catch (Throwable t) {
logger.error("Error caught while attempting to connect to preferred host", t);
diff --git a/agent/src/main/java/com/cloud/agent/AgentShell.java b/agent/src/main/java/com/cloud/agent/AgentShell.java
index aea7fd3a8de..4862e7e001e 100644
--- a/agent/src/main/java/com/cloud/agent/AgentShell.java
+++ b/agent/src/main/java/com/cloud/agent/AgentShell.java
@@ -66,6 +66,7 @@ public class AgentShell implements IAgentShell, Daemon {
private String _zone;
private String _pod;
private String _host;
+ private List _avoidHosts;
private String _privateIp;
private int _port;
private int _proxyPort;
@@ -76,7 +77,6 @@ public class AgentShell implements IAgentShell, Daemon {
private volatile boolean _exit = false;
private int _pingRetries;
private final List _agents = new ArrayList();
- private String hostToConnect;
private String connectedHost;
private Long preferredHostCheckInterval;
private boolean connectionTransfer = false;
@@ -121,7 +121,7 @@ public class AgentShell implements IAgentShell, Daemon {
if (_hostCounter >= hosts.length) {
_hostCounter = 0;
}
- hostToConnect = hosts[_hostCounter % hosts.length];
+ String hostToConnect = hosts[_hostCounter % hosts.length];
_hostCounter++;
return hostToConnect;
}
@@ -143,11 +143,10 @@ public class AgentShell implements IAgentShell, Daemon {
}
@Override
- public void updateConnectedHost() {
- connectedHost = hostToConnect;
+ public void updateConnectedHost(String connectedHost) {
+ this.connectedHost = connectedHost;
}
-
@Override
public void resetHostCounter() {
_hostCounter = 0;
@@ -166,6 +165,16 @@ public class AgentShell implements IAgentShell, Daemon {
}
}
+ @Override
+ public void setAvoidHosts(List avoidHosts) {
+ _avoidHosts = avoidHosts;
+ }
+
+ @Override
+ public List getAvoidHosts() {
+ return _avoidHosts;
+ }
+
@Override
public String getPrivateIp() {
return _privateIp;
diff --git a/agent/src/main/java/com/cloud/agent/IAgentShell.java b/agent/src/main/java/com/cloud/agent/IAgentShell.java
index c0ecd90ae69..9eefa6d2eee 100644
--- a/agent/src/main/java/com/cloud/agent/IAgentShell.java
+++ b/agent/src/main/java/com/cloud/agent/IAgentShell.java
@@ -16,6 +16,7 @@
// under the License.
package com.cloud.agent;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -63,9 +64,13 @@ public interface IAgentShell {
String[] getHosts();
+ void setAvoidHosts(List hosts);
+
+ List getAvoidHosts();
+
long getLbCheckerInterval(Long receivedLbInterval);
- void updateConnectedHost();
+ void updateConnectedHost(String connectedHost);
String getConnectedHost();
diff --git a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
index 61cd27fff77..57dc607b920 100644
--- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
+++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java
@@ -155,6 +155,14 @@ public class AgentProperties{
*/
public static final Property CMDS_TIMEOUT = new Property<>("cmds.timeout", 7200);
+ /**
+ * The timeout (in seconds) for the snapshot merge operation, mainly used for classic volume snapshots and disk-only VM snapshots on file-based storage.
+ * This configuration is only considered if libvirt.events.enabled is also true.
+ * Data type: Integer.
+ * Default value: 259200
+ */
+ public static final Property QCOW2_DELTA_MERGE_TIMEOUT = new Property<>("qcow2.delta.merge.timeout", 60 * 60 * 72);
+
/**
* This parameter sets the VM migration speed (in mbps). The default value is -1,
* which means that the agent will try to guess the speed of the guest network and consume all possible bandwidth.
@@ -213,6 +221,15 @@ public class AgentProperties{
*/
public static final Property AGENT_HOOKS_LIBVIRT_VM_XML_TRANSFORMER_SCRIPT = new Property<>("agent.hooks.libvirt_vm_xml_transformer.script", "libvirt-vm-xml-transformer.groovy");
+ /**
+ * This property is used with the agent.hooks.basedir property to define the Libvirt VM XML transformer shell script.
+ * The shell script is used to execute the Libvirt VM XML transformer script.
+ * For more information see the agent.properties file.
+ * Data type: String.
+ * Default value: libvirt-vm-xml-transformer.sh
+ */
+ public static final Property AGENT_HOOKS_LIBVIRT_VM_XML_TRANSFORMER_SHELL_SCRIPT = new Property<>("agent.hooks.libvirt_vm_xml_transformer.shell_script", "libvirt-vm-xml-transformer.sh");
+
/**
* This property is used with the agent.hooks.basedir and agent.hooks.libvirt_vm_xml_transformer.script properties to define the Libvirt VM XML transformer method.
* Libvirt XML transformer hook does XML-to-XML transformation.
@@ -233,6 +250,15 @@ public class AgentProperties{
*/
public static final Property AGENT_HOOKS_LIBVIRT_VM_ON_START_SCRIPT = new Property<>("agent.hooks.libvirt_vm_on_start.script", "libvirt-vm-state-change.groovy");
+ /**
+ * This property is used with the agent.hooks.basedir property to define the Libvirt VM on start shell script.
+ * The shell script is used to execute the Libvirt VM on start script.
+ * For more information see the agent.properties file.
+ * Data type: String.
+ * Default value: libvirt-vm-state-change.sh
+ */
+ public static final Property AGENT_HOOKS_LIBVIRT_VM_ON_START_SHELL_SCRIPT = new Property<>("agent.hooks.libvirt_vm_on_start.shell_script", "libvirt-vm-state-change.sh");
+
/**
* This property is used with the agent.hooks.basedir and agent.hooks.libvirt_vm_on_start.script properties to define the Libvirt VM on start method.
* The hook is called right after Libvirt successfully launched the VM.
@@ -252,6 +278,15 @@ public class AgentProperties{
*/
public static final Property AGENT_HOOKS_LIBVIRT_VM_ON_STOP_SCRIPT = new Property<>("agent.hooks.libvirt_vm_on_stop.script", "libvirt-vm-state-change.groovy");
+ /**
+ * This property is used with the agent.hooks.basedir property to define the Libvirt VM on stop shell script.
+ * The shell script is used to execute the Libvirt VM on stop script.
+ * For more information see the agent.properties file.
+ * Data type: String.
+ * Default value: libvirt-vm-state-change.sh
+ */
+ public static final Property AGENT_HOOKS_LIBVIRT_VM_ON_STOP_SHELL_SCRIPT = new Property<>("agent.hooks.libvirt_vm_on_stop.shell_script", "libvirt-vm-state-change.sh");
+
/**
* This property is used with the agent.hooks.basedir and agent.hooks.libvirt_vm_on_stop.script properties to define the Libvirt VM on stop method.
* The hook is called right after libvirt successfully stopped the VM.
@@ -390,8 +425,9 @@ public class AgentProperties{
public static final Property GUEST_CPU_ARCH = new Property<>("guest.cpu.arch", null, String.class);
/**
- * This param will require CPU features on the CPU section.
- * The features listed in this property must be separated by a blank space (see example below).
+ * Specifies required CPU features for end-user and system VMs.
+ * These features must be present on the host CPU for VM deployment.
+ * Multiple features should be separated by whitespace (see example below).
* Possible values: vmx vme
* Data type: String.
* Default value: null
@@ -816,14 +852,32 @@ public class AgentProperties{
* Data type: Integer.
* Default value: null
*/
- public static final Property SSL_HANDSHAKE_TIMEOUT = new Property<>("ssl.handshake.timeout", null, Integer.class);
+ public static final Property SSL_HANDSHAKE_TIMEOUT = new Property<>("ssl.handshake.timeout", 30, Integer.class);
+
+ /**
+ * Timeout (in seconds) to wait for the incremental snapshot to complete.
+ * */
+ public static final Property INCREMENTAL_SNAPSHOT_TIMEOUT = new Property<>("incremental.snapshot.timeout", 10800);
+
+ /**
+ * Timeout (in seconds) to wait for the snapshot reversion to complete.
+ * */
+ public static final Property REVERT_SNAPSHOT_TIMEOUT = new Property<>("revert.snapshot.timeout", 10800);
+
+ /**
+ * If set to true, creates VMs as full clones of their templates on KVM hypervisor. Creates as linked clones otherwise.
+ * Data type: Boolean.
+ * Default value: false
+ */
+ public static final Property CREATE_FULL_CLONE = new Property<>("create.full.clone", false);
+
public static class Property {
private String name;
private T defaultValue;
private Class typeClass;
- Property(String name, T value) {
+ public Property(String name, T value) {
init(name, value);
}
diff --git a/agent/src/main/java/com/cloud/agent/resource/DummyResource.java b/agent/src/main/java/com/cloud/agent/resource/DummyResource.java
index fe519ca9497..4002e53b585 100644
--- a/agent/src/main/java/com/cloud/agent/resource/DummyResource.java
+++ b/agent/src/main/java/com/cloud/agent/resource/DummyResource.java
@@ -20,7 +20,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.UUID;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
@@ -40,6 +39,7 @@ import com.cloud.resource.ServerResource;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.utils.StringUtils;
+import com.cloud.utils.UuidUtils;
public class DummyResource implements ServerResource {
String _name;
@@ -133,7 +133,7 @@ public class DummyResource implements ServerResource {
String hostIp = getConfiguredProperty("private.ip.address", "127.0.0.1");
String localStoragePath = getConfiguredProperty("local.storage.path", "/mnt");
String lh = hostIp + localStoragePath;
- String uuid = UUID.nameUUIDFromBytes(lh.getBytes(StringUtils.getPreferredCharset())).toString();
+ String uuid = UuidUtils.nameUUIDFromBytes(lh.getBytes(StringUtils.getPreferredCharset())).toString();
String capacity = getConfiguredProperty("local.storage.capacity", "1000000000");
String available = getConfiguredProperty("local.storage.avail", "10000000");
diff --git a/agent/src/test/java/com/cloud/agent/AgentShellTest.java b/agent/src/test/java/com/cloud/agent/AgentShellTest.java
index 6d9758cc3dc..d8def24a603 100644
--- a/agent/src/test/java/com/cloud/agent/AgentShellTest.java
+++ b/agent/src/test/java/com/cloud/agent/AgentShellTest.java
@@ -358,7 +358,7 @@ public class AgentShellTest {
AgentShell shell = new AgentShell();
shell.setHosts("test");
shell.getNextHost();
- shell.updateConnectedHost();
+ shell.updateConnectedHost("test");
Assert.assertEquals(expected, shell.getConnectedHost());
}
diff --git a/api/pom.xml b/api/pom.xml
index ec68e24c7e5..6270eb2dead 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -24,7 +24,7 @@
org.apache.cloudstack
cloudstack
- 4.21.0.0-SNAPSHOT
+ 4.22.0.0-SNAPSHOT
diff --git a/api/src/main/java/com/cloud/agent/api/Command.java b/api/src/main/java/com/cloud/agent/api/Command.java
index eb979c0060b..c4e99cb4170 100644
--- a/api/src/main/java/com/cloud/agent/api/Command.java
+++ b/api/src/main/java/com/cloud/agent/api/Command.java
@@ -19,9 +19,10 @@ package com.cloud.agent.api;
import java.util.HashMap;
import java.util.Map;
-import com.cloud.agent.api.LogLevel.Log4jLevel;
-import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import com.cloud.agent.api.LogLevel.Log4jLevel;
/**
* implemented by classes that extends the Command class. Command specifies
@@ -35,6 +36,23 @@ public abstract class Command {
Continue, Stop
}
+ public enum State {
+ CREATED, // Command is created by management server
+ STARTED, // Command is started by agent
+ PROCESSING, // Processing by agent
+ PROCESSING_IN_BACKEND, // Processing in backend by agent
+ COMPLETED, // Operation succeeds by agent or management server
+ FAILED, // Operation fails by agent
+ RECONCILE_RETRY, // Ready for retry of reconciliation
+ RECONCILING, // Being reconciled by management server
+ RECONCILED, // Reconciled by management server
+ RECONCILE_SKIPPED, // Skip the reconciliation as the resource state is inconsistent with the command
+ RECONCILE_FAILED, // Fail to reconcile by management server
+ TIMED_OUT, // Timed out on management server or agent
+ INTERRUPTED, // Interrupted by management server or agent (for example agent is restarted),
+ DANGLED_IN_BACKEND // Backend process which cannot be processed normally (for example agent is restarted)
+ }
+
public static final String HYPERVISOR_TYPE = "hypervisorType";
// allow command to carry over hypervisor or other environment related context info
@@ -42,6 +60,8 @@ public abstract class Command {
protected Map contextMap = new HashMap();
private int wait; //in second
private boolean bypassHostMaintenance = false;
+ private transient long requestSequence = 0L;
+ protected Map> externalDetails;
protected Command() {
this.wait = 0;
@@ -82,6 +102,10 @@ public abstract class Command {
return contextMap.get(name);
}
+ public Map getContextMap() {
+ return contextMap;
+ }
+
public boolean allowCaching() {
return true;
}
@@ -94,6 +118,26 @@ public abstract class Command {
this.bypassHostMaintenance = bypassHostMaintenance;
}
+ public boolean isReconcile() {
+ return false;
+ }
+
+ public long getRequestSequence() {
+ return requestSequence;
+ }
+
+ public void setRequestSequence(long requestSequence) {
+ this.requestSequence = requestSequence;
+ }
+
+ public void setExternalDetails(Map> externalDetails) {
+ this.externalDetails = externalDetails;
+ }
+
+ public Map> getExternalDetails() {
+ return externalDetails;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/api/src/main/java/com/cloud/agent/api/VgpuTypesInfo.java b/api/src/main/java/com/cloud/agent/api/VgpuTypesInfo.java
index 85ffc189820..5515a9c48bc 100644
--- a/api/src/main/java/com/cloud/agent/api/VgpuTypesInfo.java
+++ b/api/src/main/java/com/cloud/agent/api/VgpuTypesInfo.java
@@ -15,10 +15,24 @@
// specific language governing permissions and limitations
// under the License.
package com.cloud.agent.api;
+
+import org.apache.cloudstack.gpu.GpuDevice;
+
public class VgpuTypesInfo {
+ private boolean passthroughEnabled = true;
+ private GpuDevice.DeviceType deviceType;
+ private String parentBusAddress;
+ private String busAddress;
+ private String numaNode;
+ private String pciRoot;
+ private String deviceId;
+ private String deviceName;
+ private String vendorId;
+ private String vendorName;
private String modelName;
private String groupName;
+ private String vmName;
private Long maxHeads;
private Long videoRam;
private Long maxResolutionX;
@@ -26,6 +40,7 @@ public class VgpuTypesInfo {
private Long maxVgpuPerGpu;
private Long remainingCapacity;
private Long maxCapacity;
+ private boolean display = false;
public String getModelName() {
return modelName;
@@ -39,22 +54,42 @@ public class VgpuTypesInfo {
return videoRam;
}
+ public void setVideoRam(Long videoRam) {
+ this.videoRam = videoRam;
+ }
+
public Long getMaxHeads() {
return maxHeads;
}
+ public void setMaxHeads(Long maxHeads) {
+ this.maxHeads = maxHeads;
+ }
+
public Long getMaxResolutionX() {
return maxResolutionX;
}
+ public void setMaxResolutionX(Long maxResolutionX) {
+ this.maxResolutionX = maxResolutionX;
+ }
+
public Long getMaxResolutionY() {
return maxResolutionY;
}
+ public void setMaxResolutionY(Long maxResolutionY) {
+ this.maxResolutionY = maxResolutionY;
+ }
+
public Long getMaxVpuPerGpu() {
return maxVgpuPerGpu;
}
+ public void setMaxVgpuPerGpu(Long maxVgpuPerGpu) {
+ this.maxVgpuPerGpu = maxVgpuPerGpu;
+ }
+
public Long getRemainingCapacity() {
return remainingCapacity;
}
@@ -71,8 +106,133 @@ public class VgpuTypesInfo {
this.maxCapacity = maxCapacity;
}
- public VgpuTypesInfo(String groupName, String modelName, Long videoRam, Long maxHeads, Long maxResolutionX, Long maxResolutionY, Long maxVgpuPerGpu,
- Long remainingCapacity, Long maxCapacity) {
+ public boolean isPassthroughEnabled() {
+ return passthroughEnabled;
+ }
+
+ public void setPassthroughEnabled(boolean passthroughEnabled) {
+ this.passthroughEnabled = passthroughEnabled;
+ }
+
+ public GpuDevice.DeviceType getDeviceType() {
+ return deviceType;
+ }
+
+ public void setDeviceType(GpuDevice.DeviceType deviceType) {
+ this.deviceType = deviceType;
+ }
+
+ public String getParentBusAddress() {
+ return parentBusAddress;
+ }
+
+ public void setParentBusAddress(String parentBusAddress) {
+ this.parentBusAddress = parentBusAddress;
+ }
+
+ public String getBusAddress() {
+ return busAddress;
+ }
+
+ public void setBusAddress(String busAddress) {
+ this.busAddress = busAddress;
+ }
+
+ public String getNumaNode() {
+ return numaNode;
+ }
+
+ public void setNumaNode(String numaNode) {
+ this.numaNode = numaNode;
+ }
+
+ public String getPciRoot() {
+ return pciRoot;
+ }
+
+ public void setPciRoot(String pciRoot) {
+ this.pciRoot = pciRoot;
+ }
+
+ public String getDeviceId() {
+ return deviceId;
+ }
+
+ public void setDeviceId(String deviceId) {
+ this.deviceId = deviceId;
+ }
+
+ public String getDeviceName() {
+ return deviceName;
+ }
+
+ public void setDeviceName(String deviceName) {
+ this.deviceName = deviceName;
+ }
+
+ public String getVendorId() {
+ return vendorId;
+ }
+
+ public void setVendorId(String vendorId) {
+ this.vendorId = vendorId;
+ }
+
+ public String getVendorName() {
+ return vendorName;
+ }
+
+ public void setVendorName(String vendorName) {
+ this.vendorName = vendorName;
+ }
+
+ public String getVmName() {
+ return vmName;
+ }
+
+ public void setVmName(String vmName) {
+ this.vmName = vmName;
+ }
+
+ public boolean isDisplay() {
+ return display;
+ }
+
+ public void setDisplay(boolean display) {
+ this.display = display;
+ }
+
+ public VgpuTypesInfo(GpuDevice.DeviceType deviceType, String groupName, String modelName, String busAddress,
+ String vendorId, String vendorName, String deviceId, String deviceName, String numaNode, String pciRoot
+ ) {
+ this.deviceType = deviceType;
+ this.groupName = groupName;
+ this.modelName = modelName;
+ this.busAddress = busAddress;
+ this.deviceId = deviceId;
+ this.deviceName = deviceName;
+ this.vendorId = vendorId;
+ this.vendorName = vendorName;
+ this.numaNode = numaNode;
+ this.pciRoot = pciRoot;
+ }
+
+ public VgpuTypesInfo(GpuDevice.DeviceType deviceType, String groupName, String modelName, String busAddress,
+ String vendorId, String vendorName, String deviceId, String deviceName
+ ) {
+ this.deviceType = deviceType;
+ this.groupName = groupName;
+ this.modelName = modelName;
+ this.busAddress = busAddress;
+ this.deviceId = deviceId;
+ this.deviceName = deviceName;
+ this.vendorId = vendorId;
+ this.vendorName = vendorName;
+ }
+
+ public VgpuTypesInfo(String groupName, String modelName, Long videoRam, Long maxHeads, Long maxResolutionX,
+ Long maxResolutionY, Long maxVgpuPerGpu, Long remainingCapacity, Long maxCapacity
+ ) {
this.groupName = groupName;
this.modelName = modelName;
this.videoRam = videoRam;
diff --git a/api/src/main/java/com/cloud/agent/api/to/DiskTO.java b/api/src/main/java/com/cloud/agent/api/to/DiskTO.java
index d22df2df172..5664de79091 100644
--- a/api/src/main/java/com/cloud/agent/api/to/DiskTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/DiskTO.java
@@ -46,7 +46,7 @@ public class DiskTO {
private Long diskSeq;
private String path;
private Volume.Type type;
- private Map _details;
+ private Map details;
public DiskTO() {
@@ -92,10 +92,10 @@ public class DiskTO {
}
public void setDetails(Map details) {
- _details = details;
+ this.details = details;
}
public Map getDetails() {
- return _details;
+ return details;
}
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/FirewallRuleTO.java b/api/src/main/java/com/cloud/agent/api/to/FirewallRuleTO.java
index 25c75001a3c..69350815be3 100644
--- a/api/src/main/java/com/cloud/agent/api/to/FirewallRuleTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/FirewallRuleTO.java
@@ -47,7 +47,7 @@ public class FirewallRuleTO implements InternalIdentity {
int[] srcPortRange;
boolean revoked;
boolean alreadyAdded;
- private List sourceCidrList;
+ protected List sourceCidrList;
private List destCidrList;
FirewallRule.Purpose purpose;
private Integer icmpType;
diff --git a/api/src/main/java/com/cloud/agent/api/to/GPUDeviceTO.java b/api/src/main/java/com/cloud/agent/api/to/GPUDeviceTO.java
index 4afe080477b..6e9cee06dd3 100644
--- a/api/src/main/java/com/cloud/agent/api/to/GPUDeviceTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/GPUDeviceTO.java
@@ -16,7 +16,9 @@
// under the License.
package com.cloud.agent.api.to;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import com.cloud.agent.api.VgpuTypesInfo;
@@ -24,9 +26,23 @@ public class GPUDeviceTO {
private String gpuGroup;
private String vgpuType;
+ private int gpuCount;
private HashMap> groupDetails = new HashMap>();
+ private List gpuDevices = new ArrayList<>();
- public GPUDeviceTO( String gpuGroup, String vgpuType, HashMap> groupDetails) {
+ public GPUDeviceTO(String gpuGroup, String vgpuType, int gpuCount,
+ HashMap> groupDetails,
+ List gpuDevices) {
+ this.gpuGroup = gpuGroup;
+ this.vgpuType = vgpuType;
+ this.groupDetails = groupDetails;
+ this.gpuCount = gpuCount;
+ this.gpuDevices = gpuDevices;
+
+ }
+
+ public GPUDeviceTO(String gpuGroup, String vgpuType,
+ HashMap> groupDetails) {
this.gpuGroup = gpuGroup;
this.vgpuType = vgpuType;
this.groupDetails = groupDetails;
@@ -48,6 +64,14 @@ public class GPUDeviceTO {
this.vgpuType = vgpuType;
}
+ public int getGpuCount() {
+ return gpuCount;
+ }
+
+ public void setGpuCount(int gpuCount) {
+ this.gpuCount = gpuCount;
+ }
+
public HashMap> getGroupDetails() {
return groupDetails;
}
@@ -56,4 +80,11 @@ public class GPUDeviceTO {
this.groupDetails = groupDetails;
}
+ public List getGpuDevices() {
+ return gpuDevices;
+ }
+
+ public void setGpuDevices(List gpuDevices) {
+ this.gpuDevices = gpuDevices;
+ }
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java b/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java
index f395f26aeed..6c4b9e607c5 100644
--- a/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/LoadBalancerTO.java
@@ -71,7 +71,7 @@ public class LoadBalancerTO {
this.destinations = new DestinationTO[destinations.size()];
this.stickinessPolicies = null;
this.sslCert = null;
- this.lbProtocol = null;
+ this.lbProtocol = protocol;
int i = 0;
for (LbDestination destination : destinations) {
this.destinations[i++] = new DestinationTO(destination.getIpAddress(), destination.getDestinationPortStart(), destination.isRevoked(), false);
@@ -205,6 +205,10 @@ public class LoadBalancerTO {
return this.sslCert;
}
+ public void setLbSslCert(LbSslCert sslCert) {
+ this.sslCert = sslCert;
+ }
+
public String getSrcIpVlan() {
return srcIpVlan;
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/NetworkTO.java b/api/src/main/java/com/cloud/agent/api/to/NetworkTO.java
index bd08ce81101..d65ec0e3daa 100644
--- a/api/src/main/java/com/cloud/agent/api/to/NetworkTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/NetworkTO.java
@@ -36,7 +36,7 @@ public class NetworkTO {
protected TrafficType type;
protected URI broadcastUri;
protected URI isolationUri;
- protected boolean isSecurityGroupEnabled;
+ protected boolean securityGroupEnabled;
protected String name;
protected String ip6address;
protected String ip6gateway;
@@ -112,7 +112,7 @@ public class NetworkTO {
}
public void setSecurityGroupEnabled(boolean enabled) {
- this.isSecurityGroupEnabled = enabled;
+ this.securityGroupEnabled = enabled;
}
/**
@@ -221,7 +221,7 @@ public class NetworkTO {
}
public boolean isSecurityGroupEnabled() {
- return this.isSecurityGroupEnabled;
+ return this.securityGroupEnabled;
}
public void setIp6Dns1(String ip6Dns1) {
diff --git a/api/src/main/java/com/cloud/agent/api/to/NicTO.java b/api/src/main/java/com/cloud/agent/api/to/NicTO.java
index 573363c04fb..ca95fcfd679 100644
--- a/api/src/main/java/com/cloud/agent/api/to/NicTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/NicTO.java
@@ -86,6 +86,14 @@ public class NicTO extends NetworkTO {
this.nicUuid = uuid;
}
+ public String getNicUuid() {
+ return nicUuid;
+ }
+
+ public void setNicUuid(String nicUuid) {
+ this.nicUuid = nicUuid;
+ }
+
@Override
public String toString() {
return new StringBuilder("[Nic:").append(type).append("-").append(ip).append("-").append(broadcastUri).append("]").toString();
diff --git a/api/src/main/java/com/cloud/agent/api/to/PortForwardingRuleTO.java b/api/src/main/java/com/cloud/agent/api/to/PortForwardingRuleTO.java
index d43625c09a9..91f337c5f55 100644
--- a/api/src/main/java/com/cloud/agent/api/to/PortForwardingRuleTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/PortForwardingRuleTO.java
@@ -21,8 +21,6 @@ import com.cloud.network.rules.PortForwardingRule;
import com.cloud.utils.net.NetUtils;
import org.apache.commons.lang3.StringUtils;
-import java.util.List;
-
/**
* PortForwardingRuleTO specifies one port forwarding rule.
*
@@ -32,8 +30,6 @@ public class PortForwardingRuleTO extends FirewallRuleTO {
String dstIp;
int[] dstPortRange;
- List sourceCidrList;
-
protected PortForwardingRuleTO() {
super();
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java
index d86eb2a3a7f..18737c584b3 100644
--- a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java
@@ -27,6 +27,7 @@ public class RemoteInstanceTO implements Serializable {
private Hypervisor.HypervisorType hypervisorType;
private String instanceName;
+ private String instancePath;
// VMware Remote Instances parameters (required for exporting OVA through ovftool)
// TODO: cloud.agent.transport.Request#getCommands() cannot handle gsoc decode for polymorphic classes
@@ -44,9 +45,10 @@ public class RemoteInstanceTO implements Serializable {
this.instanceName = instanceName;
}
- public RemoteInstanceTO(String instanceName, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) {
+ public RemoteInstanceTO(String instanceName, String instancePath, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) {
this.hypervisorType = Hypervisor.HypervisorType.VMware;
this.instanceName = instanceName;
+ this.instancePath = instancePath;
this.vcenterHost = vcenterHost;
this.vcenterUsername = vcenterUsername;
this.vcenterPassword = vcenterPassword;
@@ -61,6 +63,10 @@ public class RemoteInstanceTO implements Serializable {
return this.instanceName;
}
+ public String getInstancePath() {
+ return this.instancePath;
+ }
+
public String getVcenterUsername() {
return vcenterUsername;
}
diff --git a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
index 6f24b1cd6ca..cffb9874080 100644
--- a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
+++ b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java
@@ -19,20 +19,22 @@ package com.cloud.agent.api.to;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
+import java.util.stream.Collectors;
import com.cloud.agent.api.LogLevel;
import com.cloud.network.element.NetworkElement;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
+import com.cloud.vm.VmDetailConstants;
public class VirtualMachineTO {
private long id;
private String name;
private BootloaderType bootloader;
private VirtualMachine.State state;
- Type type;
- int cpus;
+ private Type type;
+ private int cpus;
/**
'speed' is still here since 4.0.X/4.1.X management servers do not support
@@ -43,49 +45,50 @@ public class VirtualMachineTO {
So this is here for backwards compatibility with 4.0.X/4.1.X management servers
and newer agents.
*/
- Integer speed;
- Integer minSpeed;
- Integer maxSpeed;
+ private Integer speed;
+ private Integer minSpeed;
+ private Integer maxSpeed;
- long minRam;
- long maxRam;
- String hostName;
- String arch;
- String os;
- String platformEmulator;
- String bootArgs;
- String[] bootupScripts;
- boolean enableHA;
- boolean limitCpuUse;
- boolean enableDynamicallyScaleVm;
+ private long minRam;
+ private long maxRam;
+ private String hostName;
+ private String arch;
+ private String os;
+ private String platformEmulator;
+ private String bootArgs;
+ private String[] bootupScripts;
+ private boolean enableHA;
+ private boolean limitCpuUse;
+ private boolean enableDynamicallyScaleVm;
@LogLevel(LogLevel.Log4jLevel.Off)
- String vncPassword;
- String vncAddr;
- Map params;
- String uuid;
- String bootType;
- String bootMode;
- boolean enterHardwareSetup;
+ private String vncPassword;
+ private String vncAddr;
+ private Map details;
+ private Map params;
+ private String uuid;
+ private String bootType;
+ private String bootMode;
+ private boolean enterHardwareSetup;
- DiskTO[] disks;
- NicTO[] nics;
- GPUDeviceTO gpuDevice;
- Integer vcpuMaxLimit;
- List vmData = null;
+ private DiskTO[] disks;
+ private NicTO[] nics;
+ private GPUDeviceTO gpuDevice;
+ private Integer vcpuMaxLimit;
+ private List vmData = null;
- String configDriveLabel = null;
- String configDriveIsoRootFolder = null;
- String configDriveIsoFile = null;
- NetworkElement.Location configDriveLocation = NetworkElement.Location.SECONDARY;
+ private String configDriveLabel = null;
+ private String configDriveIsoRootFolder = null;
+ private String configDriveIsoFile = null;
+ private NetworkElement.Location configDriveLocation = NetworkElement.Location.SECONDARY;
- Double cpuQuotaPercentage = null;
+ private Double cpuQuotaPercentage = null;
- Map guestOsDetails = new HashMap();
- Map extraConfig = new HashMap<>();
- Map networkIdToNetworkNameMap = new HashMap<>();
- DeployAsIsInfoTO deployAsIsInfo;
- String metadataManufacturer;
- String metadataProductName;
+ private Map guestOsDetails = new HashMap();
+ private Map extraConfig = new HashMap<>();
+ private Map networkIdToNetworkNameMap = new HashMap<>();
+ private DeployAsIsInfoTO deployAsIsInfo;
+ private String metadataManufacturer;
+ private String metadataProductName;
public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader,
String os, boolean enableHA, boolean limitCpuUse, String vncPassword) {
@@ -191,7 +194,11 @@ public class VirtualMachineTO {
return maxSpeed;
}
- public boolean getLimitCpuUse() {
+ public boolean isEnableHA() {
+ return enableHA;
+ }
+
+ public boolean isLimitCpuUse() {
return limitCpuUse;
}
@@ -256,6 +263,10 @@ public class VirtualMachineTO {
this.bootupScripts = bootupScripts;
}
+ public void setEnableHA(boolean enableHA) {
+ this.enableHA = enableHA;
+ }
+
public DiskTO[] getDisks() {
return disks;
}
@@ -289,11 +300,11 @@ public class VirtualMachineTO {
}
public Map getDetails() {
- return params;
+ return details;
}
public void setDetails(Map params) {
- this.params = params;
+ this.details = params;
}
public String getUuid() {
@@ -431,6 +442,42 @@ public class VirtualMachineTO {
this.deployAsIsInfo = deployAsIsInfo;
}
+ public void setSpeed(Integer speed) {
+ this.speed = speed;
+ }
+
+ public void setMinSpeed(Integer minSpeed) {
+ this.minSpeed = minSpeed;
+ }
+
+ public void setMaxSpeed(Integer maxSpeed) {
+ this.maxSpeed = maxSpeed;
+ }
+
+ public void setMinRam(long minRam) {
+ this.minRam = minRam;
+ }
+
+ public void setMaxRam(long maxRam) {
+ this.maxRam = maxRam;
+ }
+
+ public void setLimitCpuUse(boolean limitCpuUse) {
+ this.limitCpuUse = limitCpuUse;
+ }
+
+ public Map getParams() {
+ return params;
+ }
+
+ public void setParams(Map params) {
+ this.params = params;
+ }
+
+ public void setExtraConfig(Map extraConfig) {
+ this.extraConfig = extraConfig;
+ }
+
public String getMetadataManufacturer() {
return metadataManufacturer;
}
@@ -451,4 +498,16 @@ public class VirtualMachineTO {
public String toString() {
return String.format("VM {id: \"%s\", name: \"%s\", uuid: \"%s\", type: \"%s\"}", id, name, uuid, type);
}
+
+ public Map getExternalDetails() {
+ if (details == null) {
+ return new HashMap<>();
+ }
+ return details.entrySet().stream()
+ .filter(entry -> entry.getKey().startsWith(VmDetailConstants.EXTERNAL_DETAIL_PREFIX))
+ .collect(Collectors.toMap(
+ entry -> entry.getKey().substring(VmDetailConstants.EXTERNAL_DETAIL_PREFIX.length()),
+ Map.Entry::getValue
+ ));
+ }
}
diff --git a/api/src/main/java/com/cloud/capacity/Capacity.java b/api/src/main/java/com/cloud/capacity/Capacity.java
index a4e2c2a7f05..4e584b18fee 100644
--- a/api/src/main/java/com/cloud/capacity/Capacity.java
+++ b/api/src/main/java/com/cloud/capacity/Capacity.java
@@ -34,13 +34,17 @@ public interface Capacity extends InternalIdentity, Identity {
public static final short CAPACITY_TYPE_LOCAL_STORAGE = 9;
public static final short CAPACITY_TYPE_VIRTUAL_NETWORK_IPV6_SUBNET = 10;
public static final short CAPACITY_TYPE_GPU = 19;
+ public static final short CAPACITY_TYPE_OBJECT_STORAGE = 20;
+ public static final short CAPACITY_TYPE_BACKUP_STORAGE = 21;
public static final short CAPACITY_TYPE_CPU_CORE = 90;
public static final List STORAGE_CAPACITY_TYPES = List.of(CAPACITY_TYPE_STORAGE,
CAPACITY_TYPE_STORAGE_ALLOCATED,
CAPACITY_TYPE_SECONDARY_STORAGE,
- CAPACITY_TYPE_LOCAL_STORAGE);
+ CAPACITY_TYPE_LOCAL_STORAGE,
+ CAPACITY_TYPE_BACKUP_STORAGE,
+ CAPACITY_TYPE_OBJECT_STORAGE);
public Long getHostOrPoolId();
diff --git a/api/src/main/java/com/cloud/configuration/ConfigurationService.java b/api/src/main/java/com/cloud/configuration/ConfigurationService.java
index 97d4b42974b..32e31519ea7 100644
--- a/api/src/main/java/com/cloud/configuration/ConfigurationService.java
+++ b/api/src/main/java/com/cloud/configuration/ConfigurationService.java
@@ -17,7 +17,11 @@
package com.cloud.configuration;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import com.cloud.network.Network;
+import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.config.ResetCfgCmd;
import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
import org.apache.cloudstack.api.command.admin.network.CreateGuestNetworkIpv6PrefixCmd;
@@ -201,11 +205,12 @@ public interface ConfigurationService {
* TODO
* @param allocationState
* TODO
+ * @param storageAccessGroups
* @return the new pod if successful, null otherwise
* @throws
* @throws
*/
- Pod createPod(long zoneId, String name, String startIp, String endIp, String gateway, String netmask, String allocationState);
+ Pod createPod(long zoneId, String name, String startIp, String endIp, String gateway, String netmask, String allocationState, List storageAccessGroups);
/**
* Creates a mutual exclusive IP range in the pod with same gateway, netmask.
@@ -372,4 +377,16 @@ public interface ConfigurationService {
List extends PortableIp> listPortableIps(long id);
Boolean isAccountAllowedToCreateOfferingsWithTags(IsAccountAllowedToCreateOfferingsWithTagsCmd cmd);
+
+ public static final Map ProviderDetailKeyMap = Map.of(
+ Network.Provider.Nsx.getName(), ApiConstants.NSX_DETAIL_KEY,
+ Network.Provider.Netris.getName(), ApiConstants.NETRIS_DETAIL_KEY
+ );
+
+ public static boolean IsIpRangeForProvider(Network.Provider provider) {
+ if (Objects.isNull(provider)) {
+ return false;
+ }
+ return ProviderDetailKeyMap.containsKey(provider.getName());
+ }
}
diff --git a/api/src/main/java/com/cloud/configuration/Resource.java b/api/src/main/java/com/cloud/configuration/Resource.java
index c7bf44de76c..97be7f9d64c 100644
--- a/api/src/main/java/com/cloud/configuration/Resource.java
+++ b/api/src/main/java/com/cloud/configuration/Resource.java
@@ -37,7 +37,8 @@ public interface Resource {
backup("backup", 12),
backup_storage("backup_storage", 13),
bucket("bucket", 14),
- object_storage("object_storage", 15);
+ object_storage("object_storage", 15),
+ gpu("gpu", 16);
private String name;
private int ordinal;
diff --git a/api/src/main/java/com/cloud/cpu/CPU.java b/api/src/main/java/com/cloud/cpu/CPU.java
index 4e1b9f5a501..3016e542db6 100644
--- a/api/src/main/java/com/cloud/cpu/CPU.java
+++ b/api/src/main/java/com/cloud/cpu/CPU.java
@@ -16,52 +16,55 @@
// under the License.
package com.cloud.cpu;
-import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.lang3.StringUtils;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
public class CPU {
+ public enum CPUArch {
+ x86("i686", 32),
+ amd64("x86_64", 64),
+ arm64("aarch64", 64);
- public static final String archX86Identifier = "i686";
- public static final String archX86_64Identifier = "x86_64";
- public static final String archARM64Identifier = "aarch64";
+ private final String type;
+ private final int bits;
- public static class CPUArch {
- private static final Map cpuArchMap = new LinkedHashMap<>();
-
- public static final CPUArch archX86 = new CPUArch(archX86Identifier, 32);
- public static final CPUArch amd64 = new CPUArch(archX86_64Identifier, 64);
- public static final CPUArch arm64 = new CPUArch(archARM64Identifier, 64);
-
- private String type;
- private int bits;
-
- public CPUArch(String type, int bits) {
+ CPUArch(String type, int bits) {
this.type = type;
this.bits = bits;
- cpuArchMap.put(type, this);
+ }
+
+ public static CPUArch getDefault() {
+ return amd64;
}
public String getType() {
- return this.type;
+ return type;
}
public int getBits() {
- return this.bits;
+ return bits;
}
public static CPUArch fromType(String type) {
if (StringUtils.isBlank(type)) {
- return amd64;
+ return getDefault();
}
- switch (type) {
- case archX86Identifier: return archX86;
- case archX86_64Identifier: return amd64;
- case archARM64Identifier: return arm64;
- default: throw new CloudRuntimeException(String.format("Unsupported arch type: %s", type));
+ for (CPUArch arch : values()) {
+ if (arch.type.equals(type)) {
+ return arch;
+ }
}
+ throw new IllegalArgumentException("Unsupported arch type: " + type);
+ }
+
+ public static String getTypesAsCSV() {
+ StringBuilder sb = new StringBuilder();
+ for (CPUArch arch : values()) {
+ sb.append(arch.getType()).append(",");
+ }
+ if (sb.length() > 0) {
+ sb.setLength(sb.length() - 1);
+ }
+ return sb.toString();
}
}
}
diff --git a/api/src/main/java/com/cloud/dc/Pod.java b/api/src/main/java/com/cloud/dc/Pod.java
index 1cbab36f3bd..17c5b615d4b 100644
--- a/api/src/main/java/com/cloud/dc/Pod.java
+++ b/api/src/main/java/com/cloud/dc/Pod.java
@@ -43,4 +43,6 @@ public interface Pod extends InfrastructureEntity, Grouping, Identity, InternalI
AllocationState getAllocationState();
boolean getExternalDhcp();
+
+ String getStorageAccessGroups();
}
diff --git a/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java b/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java
index 2697311d2b9..d127e4bdd66 100644
--- a/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java
+++ b/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java
@@ -62,7 +62,7 @@ public interface DeploymentClusterPlanner extends DeploymentPlanner {
"vm.allocation.algorithm",
"Advanced",
"random",
- "Order in which hosts within a cluster will be considered for VM/volume allocation. The value can be 'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit', or 'firstfitleastconsumed'.",
+ "Order in which hosts within a cluster will be considered for VM allocation. The value can be 'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit', or 'firstfitleastconsumed'.",
true,
ConfigKey.Scope.Global, null, null, null, null, null,
ConfigKey.Kind.Select,
diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java
index 862a6e21fa8..be21f13267b 100644
--- a/api/src/main/java/com/cloud/event/EventTypes.java
+++ b/api/src/main/java/com/cloud/event/EventTypes.java
@@ -29,13 +29,18 @@ import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.config.Configuration;
import org.apache.cloudstack.datacenter.DataCenterIpv4GuestSubnet;
+import org.apache.cloudstack.extension.Extension;
+import org.apache.cloudstack.extension.ExtensionCustomAction;
+import org.apache.cloudstack.gpu.GpuCard;
+import org.apache.cloudstack.gpu.GpuDevice;
+import org.apache.cloudstack.gpu.VgpuProfile;
import org.apache.cloudstack.ha.HAConfig;
import org.apache.cloudstack.network.BgpPeer;
import org.apache.cloudstack.network.Ipv4GuestSubnetNetworkMap;
import org.apache.cloudstack.quota.QuotaTariff;
-import org.apache.cloudstack.storage.sharedfs.SharedFS;
import org.apache.cloudstack.storage.object.Bucket;
import org.apache.cloudstack.storage.object.ObjectStore;
+import org.apache.cloudstack.storage.sharedfs.SharedFS;
import org.apache.cloudstack.usage.Usage;
import org.apache.cloudstack.vm.schedule.VMSchedule;
@@ -289,6 +294,8 @@ public class EventTypes {
//registering userdata events
public static final String EVENT_REGISTER_USER_DATA = "REGISTER.USER.DATA";
+ public static final String EVENT_REGISTER_CNI_CONFIG = "REGISTER.CNI.CONFIG";
+ public static final String EVENT_DELETE_CNI_CONFIG = "DELETE.CNI.CONFIG";
//register for user API and secret keys
public static final String EVENT_REGISTER_FOR_SECRET_API_KEY = "REGISTER.USER.KEY";
@@ -374,6 +381,21 @@ public class EventTypes {
public static final String EVENT_DISK_OFFERING_EDIT = "DISK.OFFERING.EDIT";
public static final String EVENT_DISK_OFFERING_DELETE = "DISK.OFFERING.DELETE";
+ // GPU Cards
+ public static final String EVENT_GPU_CARD_CREATE = "GPU.CARD.CREATE";
+ public static final String EVENT_GPU_CARD_EDIT = "GPU.CARD.EDIT";
+ public static final String EVENT_GPU_CARD_DELETE = "GPU.CARD.DELETE";
+
+ // vGPU Profile
+ public static final String EVENT_VGPU_PROFILE_CREATE = "VGPU.PROFILE.CREATE";
+ public static final String EVENT_VGPU_PROFILE_EDIT = "VGPU.PROFILE.EDIT";
+ public static final String EVENT_VGPU_PROFILE_DELETE = "VGPU.PROFILE.DELETE";
+
+ // GPU Devices
+ public static final String EVENT_GPU_DEVICE_CREATE = "GPU.DEVICE.CREATE";
+ public static final String EVENT_GPU_DEVICE_EDIT = "GPU.DEVICE.EDIT";
+ public static final String EVENT_GPU_DEVICE_DELETE = "GPU.DEVICE.DELETE";
+
// Network offerings
public static final String EVENT_NETWORK_OFFERING_CREATE = "NETWORK.OFFERING.CREATE";
public static final String EVENT_NETWORK_OFFERING_ASSIGN = "NETWORK.OFFERING.ASSIGN";
@@ -465,6 +487,7 @@ public class EventTypes {
public static final String EVENT_ENABLE_PRIMARY_STORAGE = "ENABLE.PS";
public static final String EVENT_DISABLE_PRIMARY_STORAGE = "DISABLE.PS";
public static final String EVENT_SYNC_STORAGE_POOL = "SYNC.STORAGE.POOL";
+ public static final String EVENT_CONFIGURE_STORAGE_ACCESS = "CONFIGURE.STORAGE.ACCESS";
public static final String EVENT_CHANGE_STORAGE_POOL_SCOPE = "CHANGE.STORAGE.POOL.SCOPE";
// VPN
@@ -496,6 +519,8 @@ public class EventTypes {
public static final String EVENT_ZONE_VLAN_ASSIGN = "ZONE.VLAN.ASSIGN";
public static final String EVENT_ZONE_VLAN_RELEASE = "ZONE.VLAN.RELEASE";
+ public static final String EVENT_ZONE_VXLAN_ASSIGN = "ZONE.VXLAN.ASSIGN";
+ public static final String EVENT_ZONE_VXLAN_RELEASE = "ZONE.VXLAN.RELEASE";
// Projects
public static final String EVENT_PROJECT_CREATE = "PROJECT.CREATE";
@@ -607,11 +632,13 @@ public class EventTypes {
public static final String EVENT_VM_BACKUP_CREATE = "BACKUP.CREATE";
public static final String EVENT_VM_BACKUP_RESTORE = "BACKUP.RESTORE";
public static final String EVENT_VM_BACKUP_DELETE = "BACKUP.DELETE";
+ public static final String EVENT_VM_BACKUP_OFFERING_REMOVED_AND_BACKUPS_DELETED = "BACKUP.OFFERING.BACKUPS.DEL";
public static final String EVENT_VM_BACKUP_RESTORE_VOLUME_TO_VM = "BACKUP.RESTORE.VOLUME.TO.VM";
public static final String EVENT_VM_BACKUP_SCHEDULE_CONFIGURE = "BACKUP.SCHEDULE.CONFIGURE";
public static final String EVENT_VM_BACKUP_SCHEDULE_DELETE = "BACKUP.SCHEDULE.DELETE";
public static final String EVENT_VM_BACKUP_USAGE_METRIC = "BACKUP.USAGE.METRIC";
public static final String EVENT_VM_BACKUP_EDIT = "BACKUP.OFFERING.EDIT";
+ public static final String EVENT_VM_CREATE_FROM_BACKUP = "VM.CREATE.FROM.BACKUP";
// external network device events
public static final String EVENT_EXTERNAL_NVP_CONTROLLER_ADD = "PHYSICAL.NVPCONTROLLER.ADD";
@@ -687,6 +714,9 @@ public class EventTypes {
public static final String EVENT_EXTERNAL_OPENDAYLIGHT_CONFIGURE_CONTROLLER = "PHYSICAL.ODLCONTROLLER.CONFIGURE";
//Guest OS related events
+ public static final String EVENT_GUEST_OS_CATEGORY_ADD = "GUEST.OS.CATEGORY.ADD";
+ public static final String EVENT_GUEST_OS_CATEGORY_DELETE = "GUEST.OS.CATEGORY.DELETE";
+ public static final String EVENT_GUEST_OS_CATEGORY_UPDATE = "GUEST.OS.CATEGORY.UPDATE";
public static final String EVENT_GUEST_OS_ADD = "GUEST.OS.ADD";
public static final String EVENT_GUEST_OS_REMOVE = "GUEST.OS.REMOVE";
public static final String EVENT_GUEST_OS_UPDATE = "GUEST.OS.UPDATE";
@@ -739,6 +769,13 @@ public class EventTypes {
//Purge resources
public static final String EVENT_PURGE_EXPUNGED_RESOURCES = "PURGE.EXPUNGED.RESOURCES";
+ // Management Server
+ public static final String EVENT_MS_MAINTENANCE_PREPARE = "MS.MAINTENANCE.PREPARE";
+ public static final String EVENT_MS_MAINTENANCE_CANCEL = "MS.MAINTENANCE.CANCEL";
+ public static final String EVENT_MS_SHUTDOWN_PREPARE = "MS.SHUTDOWN.PREPARE";
+ public static final String EVENT_MS_SHUTDOWN_CANCEL = "MS.SHUTDOWN.CANCEL";
+ public static final String EVENT_MS_SHUTDOWN = "MS.SHUTDOWN";
+
// OBJECT STORE
public static final String EVENT_OBJECT_STORE_CREATE = "OBJECT.STORE.CREATE";
public static final String EVENT_OBJECT_STORE_DELETE = "OBJECT.STORE.DELETE";
@@ -788,6 +825,33 @@ public class EventTypes {
// Resource Limit
public static final String EVENT_RESOURCE_LIMIT_UPDATE = "RESOURCE.LIMIT.UPDATE";
+ // Management Server
+ public static final String EVENT_MANAGEMENT_SERVER_REMOVE = "MANAGEMENT.SERVER.REMOVE";
+
+ // VM Lease
+ public static final String VM_LEASE_EXPIRED = "VM.LEASE.EXPIRED";
+ public static final String VM_LEASE_DISABLED = "VM.LEASE.DISABLED";
+ public static final String VM_LEASE_CANCELLED = "VM.LEASE.CANCELLED";
+ public static final String VM_LEASE_EXPIRING = "VM.LEASE.EXPIRING";
+
+ // GUI Theme
+ public static final String EVENT_GUI_THEME_CREATE = "GUI.THEME.CREATE";
+ public static final String EVENT_GUI_THEME_REMOVE = "GUI.THEME.REMOVE";
+ public static final String EVENT_GUI_THEME_UPDATE = "GUI.THEME.UPDATE";
+
+ // Extension
+ public static final String EVENT_EXTENSION_CREATE = "EXTENSION.CREATE";
+ public static final String EVENT_EXTENSION_UPDATE = "EXTENSION.UPDATE";
+ public static final String EVENT_EXTENSION_DELETE = "EXTENSION.DELETE";
+ public static final String EVENT_EXTENSION_RESOURCE_REGISTER = "EXTENSION.RESOURCE.REGISTER";
+ public static final String EVENT_EXTENSION_RESOURCE_UNREGISTER = "EXTENSION.RESOURCE.UNREGISTER";
+ public static final String EVENT_EXTENSION_CUSTOM_ACTION_ADD = "EXTENSION.CUSTOM.ACTION.ADD";
+ public static final String EVENT_EXTENSION_CUSTOM_ACTION_UPDATE = "EXTENSION.CUSTOM.ACTION.UPDATE";
+ public static final String EVENT_EXTENSION_CUSTOM_ACTION_DELETE = "EXTENSION.CUSTOM.ACTION.DELETE";
+
+ // Custom Action
+ public static final String EVENT_CUSTOM_ACTION = "CUSTOM.ACTION";
+
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
@@ -982,6 +1046,21 @@ public class EventTypes {
entityEventDetails.put(EVENT_DISK_OFFERING_EDIT, DiskOffering.class);
entityEventDetails.put(EVENT_DISK_OFFERING_DELETE, DiskOffering.class);
+ // GPU Cards
+ entityEventDetails.put(EVENT_GPU_CARD_CREATE, GpuCard.class);
+ entityEventDetails.put(EVENT_GPU_CARD_EDIT, GpuCard.class);
+ entityEventDetails.put(EVENT_GPU_CARD_DELETE, GpuCard.class);
+
+ // vGPU Profiles
+ entityEventDetails.put(EVENT_VGPU_PROFILE_CREATE, VgpuProfile.class);
+ entityEventDetails.put(EVENT_VGPU_PROFILE_EDIT, VgpuProfile.class);
+ entityEventDetails.put(EVENT_VGPU_PROFILE_DELETE, VgpuProfile.class);
+
+ // GPU Devices
+ entityEventDetails.put(EVENT_GPU_DEVICE_CREATE, GpuDevice.class);
+ entityEventDetails.put(EVENT_GPU_DEVICE_EDIT, GpuDevice.class);
+ entityEventDetails.put(EVENT_GPU_DEVICE_DELETE, GpuDevice.class);
+
// Network offerings
entityEventDetails.put(EVENT_NETWORK_OFFERING_CREATE, NetworkOffering.class);
entityEventDetails.put(EVENT_NETWORK_OFFERING_ASSIGN, NetworkOffering.class);
@@ -1233,6 +1312,12 @@ public class EventTypes {
entityEventDetails.put(EVENT_UPDATE_IMAGE_STORE_ACCESS_STATE, ImageStore.class);
entityEventDetails.put(EVENT_LIVE_PATCH_SYSTEMVM, "SystemVMs");
+ entityEventDetails.put(EVENT_MS_MAINTENANCE_PREPARE, "ManagementServer");
+ entityEventDetails.put(EVENT_MS_MAINTENANCE_CANCEL, "ManagementServer");
+ entityEventDetails.put(EVENT_MS_SHUTDOWN_PREPARE, "ManagementServer");
+ entityEventDetails.put(EVENT_MS_SHUTDOWN_CANCEL, "ManagementServer");
+ entityEventDetails.put(EVENT_MS_SHUTDOWN, "ManagementServer");
+
//Object Store
entityEventDetails.put(EVENT_OBJECT_STORE_CREATE, ObjectStore.class);
entityEventDetails.put(EVENT_OBJECT_STORE_UPDATE, ObjectStore.class);
@@ -1276,6 +1361,30 @@ public class EventTypes {
entityEventDetails.put(EVENT_SHAREDFS_DESTROY, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_EXPUNGE, SharedFS.class);
entityEventDetails.put(EVENT_SHAREDFS_RECOVER, SharedFS.class);
+
+ // Management Server
+ entityEventDetails.put(EVENT_MANAGEMENT_SERVER_REMOVE, "ManagementServer");
+
+ // VM Lease
+ entityEventDetails.put(VM_LEASE_EXPIRED, VirtualMachine.class);
+ entityEventDetails.put(VM_LEASE_EXPIRING, VirtualMachine.class);
+ entityEventDetails.put(VM_LEASE_DISABLED, VirtualMachine.class);
+ entityEventDetails.put(VM_LEASE_CANCELLED, VirtualMachine.class);
+
+ // GUI theme
+ entityEventDetails.put(EVENT_GUI_THEME_CREATE, "GuiTheme");
+ entityEventDetails.put(EVENT_GUI_THEME_REMOVE, "GuiTheme");
+ entityEventDetails.put(EVENT_GUI_THEME_UPDATE, "GuiTheme");
+
+ // Extension
+ entityEventDetails.put(EVENT_EXTENSION_CREATE, Extension.class);
+ entityEventDetails.put(EVENT_EXTENSION_UPDATE, Extension.class);
+ entityEventDetails.put(EVENT_EXTENSION_DELETE, Extension.class);
+ entityEventDetails.put(EVENT_EXTENSION_RESOURCE_REGISTER, Extension.class);
+ entityEventDetails.put(EVENT_EXTENSION_RESOURCE_UNREGISTER, Extension.class);
+ entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_ADD, ExtensionCustomAction.class);
+ entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_UPDATE, ExtensionCustomAction.class);
+ entityEventDetails.put(EVENT_EXTENSION_CUSTOM_ACTION_DELETE, ExtensionCustomAction.class);
}
public static boolean isNetworkEvent(String eventType) {
diff --git a/api/src/main/java/com/cloud/exception/OperationTimedoutException.java b/api/src/main/java/com/cloud/exception/OperationTimedoutException.java
index fe27408eb4e..66b607100d9 100644
--- a/api/src/main/java/com/cloud/exception/OperationTimedoutException.java
+++ b/api/src/main/java/com/cloud/exception/OperationTimedoutException.java
@@ -40,7 +40,7 @@ public class OperationTimedoutException extends CloudException {
boolean _isActive;
public OperationTimedoutException(Command[] cmds, long agentId, long seqId, int time, boolean isActive) {
- super("Commands " + seqId + " to Host " + agentId + " timed out after " + time);
+ super("Commands " + seqId + " to Host " + agentId + " timed out after " + time + " secs");
_agentId = agentId;
_seqId = seqId;
_time = time;
diff --git a/api/src/main/java/com/cloud/host/Host.java b/api/src/main/java/com/cloud/host/Host.java
index afac6df5631..07a0dfce041 100644
--- a/api/src/main/java/com/cloud/host/Host.java
+++ b/api/src/main/java/com/cloud/host/Host.java
@@ -53,9 +53,12 @@ public interface Host extends StateObject, Identity, Partition, HAResour
return strs;
}
}
- public static final String HOST_UEFI_ENABLE = "host.uefi.enable";
- public static final String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
- public static final String HOST_INSTANCE_CONVERSION = "host.instance.conversion";
+
+ String HOST_UEFI_ENABLE = "host.uefi.enable";
+ String HOST_VOLUME_ENCRYPTION = "host.volume.encryption";
+ String HOST_INSTANCE_CONVERSION = "host.instance.conversion";
+ String HOST_OVFTOOL_VERSION = "host.ovftool.version";
+ String HOST_VIRTV2V_VERSION = "host.virtv2v.version";
/**
* @return name of the machine.
@@ -213,4 +216,6 @@ public interface Host extends StateObject, Identity, Partition, HAResour
ResourceState getResourceState();
CPU.CPUArch getArch();
+
+ String getStorageAccessGroups();
}
diff --git a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
index 27ffef1c370..1f8741d3b7b 100644
--- a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
+++ b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
@@ -31,20 +31,22 @@ import java.util.stream.Collectors;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.DirectDownloadTemplate;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.RootDiskSizeOverride;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.VmStorageMigration;
+import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.VmStorageMigrationWithSnapshots;
public class Hypervisor {
public static class HypervisorType {
public enum Functionality {
DirectDownloadTemplate,
RootDiskSizeOverride,
- VmStorageMigration
+ VmStorageMigration,
+ VmStorageMigrationWithSnapshots
}
private static final Map hypervisorTypeMap = new LinkedHashMap<>();
public static final HypervisorType None = new HypervisorType("None"); //for storage hosts
public static final HypervisorType XenServer = new HypervisorType("XenServer", ImageFormat.VHD, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
public static final HypervisorType KVM = new HypervisorType("KVM", ImageFormat.QCOW2, EnumSet.of(DirectDownloadTemplate, RootDiskSizeOverride, VmStorageMigration));
- public static final HypervisorType VMware = new HypervisorType("VMware", ImageFormat.OVA, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
+ public static final HypervisorType VMware = new HypervisorType("VMware", ImageFormat.OVA, EnumSet.of(RootDiskSizeOverride, VmStorageMigration, VmStorageMigrationWithSnapshots));
public static final HypervisorType Hyperv = new HypervisorType("Hyperv");
public static final HypervisorType VirtualBox = new HypervisorType("VirtualBox");
public static final HypervisorType Parralels = new HypervisorType("Parralels");
@@ -54,6 +56,7 @@ public class Hypervisor {
public static final HypervisorType Ovm3 = new HypervisorType("Ovm3", ImageFormat.RAW);
public static final HypervisorType LXC = new HypervisorType("LXC");
public static final HypervisorType Custom = new HypervisorType("Custom", null, EnumSet.of(RootDiskSizeOverride));
+ public static final HypervisorType External = new HypervisorType("External", null, EnumSet.of(RootDiskSizeOverride));
public static final HypervisorType Any = new HypervisorType("Any"); /*If you don't care about the hypervisor type*/
private final String name;
private final ImageFormat imageFormat;
diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java
similarity index 78%
rename from plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java
rename to api/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java
index 591da077aec..571d993c7a1 100644
--- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java
+++ b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java
@@ -44,6 +44,8 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
AutoscaleRequested,
ScaleUpRequested,
ScaleDownRequested,
+ AddNodeRequested,
+ RemoveNodeRequested,
UpgradeRequested,
OperationSucceeded,
OperationFailed,
@@ -58,7 +60,10 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
Stopping("Resources for the Kubernetes cluster are being destroyed"),
Stopped("All resources for the Kubernetes cluster are destroyed, Kubernetes cluster may still have ephemeral resource like persistent volumes provisioned"),
Scaling("Transient state in which resources are either getting scaled up/down"),
+ ScalingStoppedCluster("Transient state in which the service offerings of stopped clusters are getting scaled"),
Upgrading("Transient state in which cluster is getting upgraded"),
+ Importing("Transient state in which additional nodes are added as worker nodes to a cluster"),
+ RemovingNodes("Transient state in which additional nodes are removed from a cluster"),
Alert("State to represent Kubernetes clusters which are not in expected desired state (operationally in active control place, stopped cluster VM's etc)."),
Recovering("State in which Kubernetes cluster is recovering from alert state"),
Destroyed("End state of Kubernetes cluster in which all resources are destroyed, cluster will not be usable further"),
@@ -89,13 +94,27 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
s_fsm.addTransition(State.Running, Event.AutoscaleRequested, State.Scaling);
s_fsm.addTransition(State.Running, Event.ScaleUpRequested, State.Scaling);
s_fsm.addTransition(State.Running, Event.ScaleDownRequested, State.Scaling);
+ s_fsm.addTransition(State.Stopped, Event.ScaleUpRequested, State.ScalingStoppedCluster);
s_fsm.addTransition(State.Scaling, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Scaling, Event.OperationFailed, State.Alert);
+ s_fsm.addTransition(State.ScalingStoppedCluster, Event.OperationSucceeded, State.Stopped);
+ s_fsm.addTransition(State.ScalingStoppedCluster, Event.OperationFailed, State.Alert);
s_fsm.addTransition(State.Running, Event.UpgradeRequested, State.Upgrading);
s_fsm.addTransition(State.Upgrading, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Upgrading, Event.OperationFailed, State.Alert);
+ s_fsm.addTransition(State.Running, Event.AddNodeRequested, State.Importing);
+ s_fsm.addTransition(State.Alert, Event.AddNodeRequested, State.Importing);
+ s_fsm.addTransition(State.Importing, Event.OperationSucceeded, State.Running);
+ s_fsm.addTransition(State.Importing, Event.OperationFailed, State.Running);
+ s_fsm.addTransition(State.Alert, Event.OperationSucceeded, State.Running);
+
+ s_fsm.addTransition(State.Running, Event.RemoveNodeRequested, State.RemovingNodes);
+ s_fsm.addTransition(State.Alert, Event.RemoveNodeRequested, State.RemovingNodes);
+ s_fsm.addTransition(State.RemovingNodes, Event.OperationSucceeded, State.Running);
+ s_fsm.addTransition(State.RemovingNodes, Event.OperationFailed, State.Running);
+
s_fsm.addTransition(State.Alert, Event.RecoveryRequested, State.Recovering);
s_fsm.addTransition(State.Recovering, Event.OperationSucceeded, State.Running);
s_fsm.addTransition(State.Recovering, Event.OperationFailed, State.Alert);
@@ -142,4 +161,13 @@ public interface KubernetesCluster extends ControlledEntity, com.cloud.utils.fsm
Long getMaxSize();
Long getSecurityGroupId();
ClusterType getClusterType();
+ Long getControlNodeServiceOfferingId();
+ Long getWorkerNodeServiceOfferingId();
+ Long getEtcdNodeServiceOfferingId();
+ Long getControlNodeTemplateId();
+ Long getWorkerNodeTemplateId();
+ Long getEtcdNodeTemplateId();
+ Long getEtcdNodeCount();
+ Long getCniConfigId();
+ String getCniConfigDetails();
}
diff --git a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java
index a13c1b3a6a8..37b8907b454 100644
--- a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java
+++ b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java
@@ -18,12 +18,23 @@ package com.cloud.kubernetes.cluster;
import org.apache.cloudstack.acl.ControlledEntity;
+import java.util.Map;
+
+import com.cloud.user.Account;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Adapter;
public interface KubernetesServiceHelper extends Adapter {
+ enum KubernetesClusterNodeType {
+ CONTROL, WORKER, ETCD, DEFAULT
+ }
+
ControlledEntity findByUuid(String uuid);
ControlledEntity findByVmId(long vmId);
void checkVmCanBeDestroyed(UserVm userVm);
+ boolean isValidNodeType(String nodeType);
+ Map getServiceOfferingNodeTypeMap(Map> serviceOfferingNodeTypeMap);
+ Map getTemplateNodeTypeMap(Map> templateNodeTypeMap);
+ void cleanupForAccount(Account account);
}
diff --git a/api/src/main/java/com/cloud/network/IpAddress.java b/api/src/main/java/com/cloud/network/IpAddress.java
index ae1af450577..70d652b54e9 100644
--- a/api/src/main/java/com/cloud/network/IpAddress.java
+++ b/api/src/main/java/com/cloud/network/IpAddress.java
@@ -99,4 +99,5 @@ public interface IpAddress extends ControlledEntity, Identity, InternalIdentity,
boolean isForSystemVms();
+ boolean isForRouter();
}
diff --git a/api/src/main/java/com/cloud/network/Network.java b/api/src/main/java/com/cloud/network/Network.java
index d3bc5005cb7..dc94932e31f 100644
--- a/api/src/main/java/com/cloud/network/Network.java
+++ b/api/src/main/java/com/cloud/network/Network.java
@@ -206,6 +206,7 @@ public interface Network extends ControlledEntity, StateObject, I
public static final Provider Tungsten = new Provider("Tungsten", false);
public static final Provider Nsx = new Provider("Nsx", false);
+ public static final Provider Netris = new Provider("Netris", false);
private final String name;
private final boolean isExternal;
diff --git a/api/src/main/java/com/cloud/network/NetworkModel.java b/api/src/main/java/com/cloud/network/NetworkModel.java
index a4cd87af008..eb496ac4e0b 100644
--- a/api/src/main/java/com/cloud/network/NetworkModel.java
+++ b/api/src/main/java/com/cloud/network/NetworkModel.java
@@ -305,6 +305,8 @@ public interface NetworkModel {
NicProfile getNicProfile(VirtualMachine vm, long networkId, String broadcastUri);
+ NicProfile getNicProfile(VirtualMachine vm, Nic nic, DataCenter dataCenter);
+
Set getAvailableIps(Network network, String requestedIp);
String getDomainNetworkDomain(long domainId, long zoneId);
diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java
index b8dd464b365..196e1f9aab8 100644
--- a/api/src/main/java/com/cloud/network/NetworkService.java
+++ b/api/src/main/java/com/cloud/network/NetworkService.java
@@ -19,7 +19,6 @@ package com.cloud.network;
import java.util.List;
import java.util.Map;
-import com.cloud.dc.DataCenter;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
@@ -39,13 +38,16 @@ import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
+import com.cloud.agent.api.to.NicTO;
+import com.cloud.dc.DataCenter;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
-import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
@@ -57,7 +59,6 @@ import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.Nic;
import com.cloud.vm.NicSecondaryIp;
-import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
/**
* The NetworkService interface is the "public" api to entities that make requests to the orchestration engine
@@ -268,4 +269,10 @@ public interface NetworkService {
InternalLoadBalancerElementService getInternalLoadBalancerElementByNetworkServiceProviderId(long networkProviderId);
InternalLoadBalancerElementService getInternalLoadBalancerElementById(long providerId);
List getInternalLoadBalancerElements();
+
+ boolean handleCksIsoOnNetworkVirtualRouter(Long virtualRouterId, boolean mount) throws ResourceUnavailableException;
+
+ IpAddresses getIpAddressesFromIps(String ipAddress, String ip6Address, String macAddress);
+
+ String getNicVlanValueForExternalVm(NicTO nic);
}
diff --git a/api/src/main/java/com/cloud/network/Networks.java b/api/src/main/java/com/cloud/network/Networks.java
index dfa0ddb84ca..9f06a044111 100644
--- a/api/src/main/java/com/cloud/network/Networks.java
+++ b/api/src/main/java/com/cloud/network/Networks.java
@@ -129,7 +129,8 @@ public class Networks {
UnDecided(null, null),
OpenDaylight("opendaylight", String.class),
TUNGSTEN("tf", String.class),
- NSX("nsx", String.class);
+ NSX("nsx", String.class),
+ Netris("netris", String.class);
private final String scheme;
private final Class> type;
diff --git a/api/src/main/java/com/cloud/network/SDNProviderNetworkRule.java b/api/src/main/java/com/cloud/network/SDNProviderNetworkRule.java
new file mode 100644
index 00000000000..a22db4287dc
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/SDNProviderNetworkRule.java
@@ -0,0 +1,358 @@
+// 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.
+package com.cloud.network;
+
+import java.util.List;
+
+public class SDNProviderNetworkRule {
+
+ protected long domainId;
+ protected long accountId;
+ protected long zoneId;
+ protected Long networkResourceId;
+ protected String networkResourceName;
+ protected boolean isVpcResource;
+ protected long vmId;
+ protected long ruleId;
+ protected String publicIp;
+ protected String vmIp;
+ protected String publicPort;
+ protected String privatePort;
+ protected String protocol;
+ protected String algorithm;
+ protected List sourceCidrList;
+ protected List destinationCidrList;
+ protected Integer icmpCode;
+
+ protected Integer icmpType;
+ protected String trafficType;
+ protected Network.Service service;
+
+ public long getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(long domainId) {
+ this.domainId = domainId;
+ }
+
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(long accountId) {
+ this.accountId = accountId;
+ }
+
+ public long getZoneId() {
+ return zoneId;
+ }
+
+ public void setZoneId(long zoneId) {
+ this.zoneId = zoneId;
+ }
+
+ public Long getNetworkResourceId() {
+ return networkResourceId;
+ }
+
+ public void setNetworkResourceId(Long networkResourceId) {
+ this.networkResourceId = networkResourceId;
+ }
+
+ public String getNetworkResourceName() {
+ return networkResourceName;
+ }
+
+ public void setNetworkResourceName(String networkResourceName) {
+ this.networkResourceName = networkResourceName;
+ }
+
+ public boolean isVpcResource() {
+ return isVpcResource;
+ }
+
+ public void setVpcResource(boolean vpcResource) {
+ isVpcResource = vpcResource;
+ }
+
+ public long getVmId() {
+ return vmId;
+ }
+
+ public void setVmId(long vmId) {
+ this.vmId = vmId;
+ }
+
+ public long getRuleId() {
+ return ruleId;
+ }
+
+ public void setRuleId(long ruleId) {
+ this.ruleId = ruleId;
+ }
+
+ public String getPublicIp() {
+ return publicIp;
+ }
+
+ public void setPublicIp(String publicIp) {
+ this.publicIp = publicIp;
+ }
+
+ public String getVmIp() {
+ return vmIp;
+ }
+
+ public void setVmIp(String vmIp) {
+ this.vmIp = vmIp;
+ }
+
+ public String getPublicPort() {
+ return publicPort;
+ }
+
+ public void setPublicPort(String publicPort) {
+ this.publicPort = publicPort;
+ }
+
+ public String getPrivatePort() {
+ return privatePort;
+ }
+
+ public void setPrivatePort(String privatePort) {
+ this.privatePort = privatePort;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public void setAlgorithm(String algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ public Network.Service getService() {
+ return service;
+ }
+
+ public void setService(Network.Service service) {
+ this.service = service;
+ }
+
+ public Integer getIcmpCode() {
+ return icmpCode;
+ }
+
+ public void setIcmpCode(Integer icmpCode) {
+ this.icmpCode = icmpCode;
+ }
+
+ public Integer getIcmpType() {
+ return icmpType;
+ }
+
+ public void setIcmpType(Integer icmpType) {
+ this.icmpType = icmpType;
+ }
+
+ public List getSourceCidrList() {
+ return sourceCidrList;
+ }
+
+ public void setSourceCidrList(List sourceCidrList) {
+ this.sourceCidrList = sourceCidrList;
+ }
+
+ public List getDestinationCidrList() {
+ return destinationCidrList;
+ }
+
+ public void setDestinationCidrList(List destinationCidrList) {
+ this.destinationCidrList = destinationCidrList;
+ }
+
+ public String getTrafficType() {
+ return trafficType;
+ }
+
+ public void setTrafficType(String trafficType) {
+ this.trafficType = trafficType;
+ }
+
+ public static class Builder {
+ public long domainId;
+ public long accountId;
+ public long zoneId;
+ public Long networkResourceId;
+ public String networkResourceName;
+ public boolean isVpcResource;
+ public long vmId;
+
+ public long ruleId;
+ public String publicIp;
+ public String vmIp;
+ public String publicPort;
+ public String privatePort;
+ public String protocol;
+ public String algorithm;
+ public List sourceCidrList;
+ public List destinationCidrList;
+ public String trafficType;
+ public Integer icmpType;
+ public Integer icmpCode;
+ public Network.Service service;
+
+ public Builder() {
+ // Default constructor
+ }
+
+ public Builder setDomainId(long domainId) {
+ this.domainId = domainId;
+ return this;
+ }
+
+ public Builder setAccountId(long accountId) {
+ this.accountId = accountId;
+ return this;
+ }
+
+ public Builder setZoneId(long zoneId) {
+ this.zoneId = zoneId;
+ return this;
+ }
+
+ public Builder setNetworkResourceId(Long networkResourceId) {
+ this.networkResourceId = networkResourceId;
+ return this;
+ }
+
+ public Builder setNetworkResourceName(String networkResourceName) {
+ this.networkResourceName = networkResourceName;
+ return this;
+ }
+
+ public Builder setVpcResource(boolean isVpcResource) {
+ this.isVpcResource = isVpcResource;
+ return this;
+ }
+
+
+ public Builder setVmId(long vmId) {
+ this.vmId = vmId;
+ return this;
+ }
+
+ public Builder setRuleId(long ruleId) {
+ this.ruleId = ruleId;
+ return this;
+ }
+
+ public Builder setPublicIp(String publicIp) {
+ this.publicIp = publicIp;
+ return this;
+ }
+
+ public Builder setVmIp(String vmIp) {
+ this.vmIp = vmIp;
+ return this;
+ }
+
+ public Builder setPublicPort(String publicPort) {
+ this.publicPort = publicPort;
+ return this;
+ }
+
+ public Builder setPrivatePort(String privatePort) {
+ this.privatePort = privatePort;
+ return this;
+ }
+
+ public Builder setProtocol(String protocol) {
+ this.protocol = protocol;
+ return this;
+ }
+
+ public Builder setAlgorithm(String algorithm) {
+ this.algorithm = algorithm;
+ return this;
+ }
+
+ public Builder setTrafficType(String trafficType) {
+ this.trafficType = trafficType;
+ return this;
+ }
+
+ public Builder setIcmpType(Integer icmpType) {
+ this.icmpType = icmpType;
+ return this;
+ }
+
+ public Builder setIcmpCode(Integer icmpCode) {
+ this.icmpCode = icmpCode;
+ return this;
+ }
+
+ public Builder setSourceCidrList(List sourceCidrList) {
+ this.sourceCidrList = sourceCidrList;
+ return this;
+ }
+
+ public Builder setDestinationCidrList(List destinationCidrList) {
+ this.destinationCidrList = destinationCidrList;
+ return this;
+ }
+
+ public Builder setService(Network.Service service) {
+ this.service = service;
+ return this;
+ }
+
+ public SDNProviderNetworkRule build() {
+ SDNProviderNetworkRule rule = new SDNProviderNetworkRule();
+ rule.setDomainId(this.domainId);
+ rule.setAccountId(this.accountId);
+ rule.setZoneId(this.zoneId);
+ rule.setNetworkResourceId(this.networkResourceId);
+ rule.setNetworkResourceName(this.networkResourceName);
+ rule.setVpcResource(this.isVpcResource);
+ rule.setVmId(this.vmId);
+ rule.setVmIp(this.vmIp);
+ rule.setPublicIp(this.publicIp);
+ rule.setPublicPort(this.publicPort);
+ rule.setPrivatePort(this.privatePort);
+ rule.setProtocol(this.protocol);
+ rule.setRuleId(this.ruleId);
+ rule.setAlgorithm(this.algorithm);
+ rule.setIcmpType(this.icmpType);
+ rule.setIcmpCode(this.icmpCode);
+ rule.setSourceCidrList(this.sourceCidrList);
+ rule.setDestinationCidrList(this.destinationCidrList);
+ rule.setTrafficType(this.trafficType);
+ rule.setService(service);
+ return rule;
+ }
+ }
+}
diff --git a/api/src/main/java/com/cloud/network/Site2SiteVpnConnection.java b/api/src/main/java/com/cloud/network/Site2SiteVpnConnection.java
index 994df875f7d..51036abe060 100644
--- a/api/src/main/java/com/cloud/network/Site2SiteVpnConnection.java
+++ b/api/src/main/java/com/cloud/network/Site2SiteVpnConnection.java
@@ -24,7 +24,7 @@ import org.apache.cloudstack.api.InternalIdentity;
public interface Site2SiteVpnConnection extends ControlledEntity, InternalIdentity, Displayable {
enum State {
- Pending, Connecting, Connected, Disconnected, Error,
+ Pending, Connecting, Connected, Disconnected, Error, Removed
}
@Override
diff --git a/api/src/main/java/com/cloud/network/element/NetworkElement.java b/api/src/main/java/com/cloud/network/element/NetworkElement.java
index fa67575edd3..cb0fc2fca98 100644
--- a/api/src/main/java/com/cloud/network/element/NetworkElement.java
+++ b/api/src/main/java/com/cloud/network/element/NetworkElement.java
@@ -23,6 +23,7 @@ import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
@@ -87,6 +88,14 @@ public interface NetworkElement extends Adapter {
boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException;
+ /**
+ * Release IP from the network provider if reserved
+ * @param ipAddress
+ */
+ default boolean releaseIp(IpAddress ipAddress) {
+ return true;
+ }
+
/**
* The network is being shutdown.
* @param network
diff --git a/api/src/main/java/com/cloud/network/element/PortForwardingServiceProvider.java b/api/src/main/java/com/cloud/network/element/PortForwardingServiceProvider.java
index e99bc2fd416..8dcc8b6d0a4 100644
--- a/api/src/main/java/com/cloud/network/element/PortForwardingServiceProvider.java
+++ b/api/src/main/java/com/cloud/network/element/PortForwardingServiceProvider.java
@@ -17,12 +17,40 @@
package com.cloud.network.element;
import java.util.List;
+import java.util.Objects;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
+import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.PortForwardingRule;
+import com.cloud.network.vpc.NetworkACLItem;
public interface PortForwardingServiceProvider extends NetworkElement, IpDeployingRequester {
+
+ static String getPublicPortRange(PortForwardingRule rule) {
+ return Objects.equals(rule.getSourcePortStart(), rule.getSourcePortEnd()) ?
+ String.valueOf(rule.getSourcePortStart()) :
+ String.valueOf(rule.getSourcePortStart()).concat("-").concat(String.valueOf(rule.getSourcePortEnd()));
+ }
+
+ static String getPrivatePFPortRange(PortForwardingRule rule) {
+ return rule.getDestinationPortStart() == rule.getDestinationPortEnd() ?
+ String.valueOf(rule.getDestinationPortStart()) :
+ String.valueOf(rule.getDestinationPortStart()).concat("-").concat(String.valueOf(rule.getDestinationPortEnd()));
+ }
+
+ static String getPrivatePortRange(FirewallRule rule) {
+ return Objects.equals(rule.getSourcePortStart(), rule.getSourcePortEnd()) ?
+ String.valueOf(rule.getSourcePortStart()) :
+ String.valueOf(rule.getSourcePortStart()).concat("-").concat(String.valueOf(rule.getSourcePortEnd()));
+ }
+
+ static String getPrivatePortRangeForACLRule(NetworkACLItem rule) {
+ return Objects.equals(rule.getSourcePortStart(), rule.getSourcePortEnd()) ?
+ String.valueOf(rule.getSourcePortStart()) :
+ String.valueOf(rule.getSourcePortStart()).concat("-").concat(String.valueOf(rule.getSourcePortEnd()));
+ }
+
/**
* Apply rules
* @param network
diff --git a/api/src/main/java/com/cloud/network/element/VpcProvider.java b/api/src/main/java/com/cloud/network/element/VpcProvider.java
index 6debd1fbc2d..fe8c8f8612f 100644
--- a/api/src/main/java/com/cloud/network/element/VpcProvider.java
+++ b/api/src/main/java/com/cloud/network/element/VpcProvider.java
@@ -55,4 +55,8 @@ public interface VpcProvider extends NetworkElement {
boolean applyACLItemsToPrivateGw(PrivateGateway gateway, List extends NetworkACLItem> rules) throws ResourceUnavailableException;
boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address);
+
+ default boolean updateVpc(Vpc vpc, String previousVpcName) {
+ return true;
+ }
}
diff --git a/api/src/main/java/com/cloud/network/guru/NetworkGuru.java b/api/src/main/java/com/cloud/network/guru/NetworkGuru.java
index 7b81c75ed84..ced664e54a9 100644
--- a/api/src/main/java/com/cloud/network/guru/NetworkGuru.java
+++ b/api/src/main/java/com/cloud/network/guru/NetworkGuru.java
@@ -215,4 +215,8 @@ public interface NetworkGuru extends Adapter {
default boolean isSlaacV6Only() {
return true;
}
+
+ default boolean update(Network network, String prevNetworkName) {
+ return true;
+ }
}
diff --git a/api/src/main/java/com/cloud/network/lb/LoadBalancingRulesService.java b/api/src/main/java/com/cloud/network/lb/LoadBalancingRulesService.java
index 46f17237e02..3fc6028b977 100644
--- a/api/src/main/java/com/cloud/network/lb/LoadBalancingRulesService.java
+++ b/api/src/main/java/com/cloud/network/lb/LoadBalancingRulesService.java
@@ -106,7 +106,7 @@ public interface LoadBalancingRulesService {
boolean applyLoadBalancerConfig(long lbRuleId) throws ResourceUnavailableException;
- boolean assignCertToLoadBalancer(long lbRuleId, Long certId);
+ boolean assignCertToLoadBalancer(long lbRuleId, Long certId, boolean isForced);
boolean removeCertFromLoadBalancer(long lbRuleId);
diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClientException.java b/api/src/main/java/com/cloud/network/netris/NetrisLbBackend.java
similarity index 63%
rename from vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClientException.java
rename to api/src/main/java/com/cloud/network/netris/NetrisLbBackend.java
index 828eed4622d..afc21f7f511 100644
--- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareClientException.java
+++ b/api/src/main/java/com/cloud/network/netris/NetrisLbBackend.java
@@ -14,20 +14,28 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.hypervisor.vmware.util;
+package com.cloud.network.netris;
-import com.cloud.exception.CloudException;
+public class NetrisLbBackend {
+ private long vmId;
+ private String vmIp;
+ private int port;
-public class VmwareClientException extends CloudException {
- public VmwareClientException(String message, Throwable cause) {
- super(message, cause);
+ public NetrisLbBackend(long vmId, String vmIp, int port) {
+ this.vmId = vmId;
+ this.vmIp = vmIp;
+ this.port = port;
}
- public VmwareClientException(String msg) {
- super(msg);
+ public long getVmId() {
+ return vmId;
}
- // TODO embed vmware classes in this one for use downstream
- public VmwareClientException(String msg, Exception embedded) {
- super(msg, embedded);
+
+ public String getVmIp() {
+ return vmIp;
+ }
+
+ public int getPort() {
+ return port;
}
}
diff --git a/api/src/main/java/com/cloud/network/netris/NetrisNetworkRule.java b/api/src/main/java/com/cloud/network/netris/NetrisNetworkRule.java
new file mode 100644
index 00000000000..211517ead49
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/netris/NetrisNetworkRule.java
@@ -0,0 +1,108 @@
+// 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.
+package com.cloud.network.netris;
+
+import com.cloud.network.SDNProviderNetworkRule;
+
+
+import java.util.List;
+
+public class NetrisNetworkRule {
+ public enum NetrisRuleAction {
+ PERMIT, DENY
+ }
+
+ private SDNProviderNetworkRule baseRule;
+ private NetrisRuleAction aclAction;
+ private List lbBackends;
+ private String lbRuleName;
+ private String lbCidrList;
+ private String reason;
+
+ public NetrisNetworkRule(Builder builder) {
+ this.baseRule = builder.baseRule;
+ this.aclAction = builder.aclAction;
+ this.lbBackends = builder.lbBackends;
+ this.reason = builder.reason;
+ this.lbCidrList = builder.lbCidrList;
+ this.lbRuleName = builder.lbRuleName;
+ }
+
+ public NetrisRuleAction getAclAction() {
+ return aclAction;
+ }
+
+ public List getLbBackends() {
+ return lbBackends;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public String getLbCidrList() {return lbCidrList; }
+
+ public String getLbRuleName() { return lbRuleName; }
+
+ public SDNProviderNetworkRule getBaseRule() {
+ return baseRule;
+ }
+
+ // Builder class extending the parent builder
+ public static class Builder {
+ private SDNProviderNetworkRule baseRule;
+ private NetrisRuleAction aclAction;
+ private List lbBackends;
+ private String reason;
+ private String lbCidrList;
+ private String lbRuleName;
+
+ public Builder baseRule(SDNProviderNetworkRule baseRule) {
+ this.baseRule = baseRule;
+ return this;
+ }
+
+ public Builder aclAction(NetrisRuleAction aclAction) {
+ this.aclAction = aclAction;
+ return this;
+ }
+
+ public Builder lbBackends(List lbBackends) {
+ this.lbBackends = lbBackends;
+ return this;
+ }
+
+ public Builder reason(String reason) {
+ this.reason = reason;
+ return this;
+ }
+
+ public Builder lbCidrList(String lbCidrList) {
+ this.lbCidrList = lbCidrList;
+ return this;
+ }
+
+ public Builder lbRuleName(String lbRuleName) {
+ this.lbRuleName = lbRuleName;
+ return this;
+ }
+
+ public NetrisNetworkRule build() {
+ return new NetrisNetworkRule(this);
+ }
+ }
+}
diff --git a/api/src/main/java/com/cloud/network/netris/NetrisProvider.java b/api/src/main/java/com/cloud/network/netris/NetrisProvider.java
new file mode 100644
index 00000000000..fccf2930e97
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/netris/NetrisProvider.java
@@ -0,0 +1,30 @@
+// 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.
+package com.cloud.network.netris;
+
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface NetrisProvider extends InternalIdentity, Identity {
+ long getZoneId();
+ String getName();
+ String getUrl();
+ String getUsername();
+ String getSiteName();
+ String getTenantName();
+ String getNetrisTag();
+}
diff --git a/api/src/main/java/com/cloud/network/netris/NetrisService.java b/api/src/main/java/com/cloud/network/netris/NetrisService.java
new file mode 100644
index 00000000000..110e9f07105
--- /dev/null
+++ b/api/src/main/java/com/cloud/network/netris/NetrisService.java
@@ -0,0 +1,310 @@
+// 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.
+package com.cloud.network.netris;
+
+import com.cloud.network.IpAddress;
+import com.cloud.network.Network;
+import com.cloud.network.SDNProviderNetworkRule;
+import com.cloud.network.vpc.StaticRoute;
+import com.cloud.network.vpc.Vpc;
+
+import java.util.List;
+
+/**
+ * Interface for Netris Services that provides methods to manage VPCs, networks,
+ * NAT rules, network rules, and static routes in an SDN (Software Defined Networking) environment.
+ */
+
+public interface NetrisService {
+
+ /**
+ * Creates IPAM (IP Address Management) allocations for zone-level public ranges.
+ *
+ * @param zoneId the ID of the zone
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createIPAMAllocationsForZoneLevelPublicRanges(long zoneId);
+
+ /**
+ * Creates a VPC (Virtual Private Cloud) resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcId the ID of the VPC
+ * @param vpcName the name of the VPC
+ * @param sourceNatEnabled true if source NAT is enabled
+ * @param cidr the CIDR of the VPC
+ * @param isVpcNetwork true if it is a VPC network
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createVpcResource(long zoneId, long accountId, long domainId, Long vpcId, String vpcName, boolean sourceNatEnabled, String cidr, boolean isVpcNetwork);
+
+ /**
+ * Updates an existing VPC resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcId the ID of the VPC
+ * @param vpcName the new name of the VPC
+ * @param previousVpcName the previous name of the VPC
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean updateVpcResource(long zoneId, long accountId, long domainId, Long vpcId, String vpcName, String previousVpcName);
+
+ /**
+ * Deletes a VPC resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpc the VPC to delete
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteVpcResource(long zoneId, long accountId, long domainId, Vpc vpc);
+
+ /**
+ * Creates a virtual network (vNet) resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the name of the network
+ * @param networkId the ID of the network
+ * @param cidr the CIDR of the network
+ * @param globalRouting true if global routing is enabled
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr, Boolean globalRouting);
+
+ /**
+ * Updates an existing vNet resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the new name of the network
+ * @param networkId the ID of the network
+ * @param prevNetworkName the previous name of the network
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean updateVnetResource(Long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String prevNetworkName);
+
+ /**
+ * Deletes an existing vNet resource.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the name of the network
+ * @param networkId the ID of the network
+ * @param cidr the CIDR of the network
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteVnetResource(long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, String cidr);
+
+ /**
+ * Creates a source NAT rule for a VPC or network.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the name of the network
+ * @param networkId the ID of the network
+ * @param isForVpc true if the rule applies to a VPC
+ * @param vpcCidr the VPC CIDR
+ * @param sourceNatIp the source NAT IP
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createSnatRule(long zoneId, long accountId, long domainId, String vpcName, long vpcId, String networkName, long networkId, boolean isForVpc, String vpcCidr, String sourceNatIp);
+
+ /**
+ * Creates a port forwarding rule for a VPC or network.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the name of the network
+ * @param networkId the ID of the network
+ * @param isForVpc true if the rule applies to a VPC
+ * @param vpcCidr the VPC CIDR
+ * @param networkRule the network rule to forward
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createPortForwardingRule(long zoneId, long accountId, long domainId, String vpcName, long vpcId, String networkName, Long networkId, boolean isForVpc, String vpcCidr, SDNProviderNetworkRule networkRule);
+
+ /**
+ * Deletes a port forwarding rule for a VPC or network.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param vpcName the name of the VPC
+ * @param vpcId the ID of the VPC
+ * @param networkName the name of the network
+ * @param networkId the ID of the network
+ * @param isForVpc true if the rule applies to a VPC
+ * @param vpcCidr the VPC CIDR
+ * @param networkRule the network rule to remove
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deletePortForwardingRule(long zoneId, long accountId, long domainId, String vpcName, Long vpcId, String networkName, Long networkId, boolean isForVpc, String vpcCidr, SDNProviderNetworkRule networkRule);
+
+ /**
+ * Updates the source NAT IP for a specified VPC.
+ *
+ * @param vpc the VPC to updates
+ * @param address the new source NAT IP address
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address);
+
+ /**
+ * Creates a static NAT rule for a specific VM.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param networkResourceName the name of the network resource
+ * @param networkResourceId the ID of the network resource
+ * @param isForVpc true if the rule applies to a VPC
+ * @param vpcCidr the VPC CIDR
+ * @param staticNatIp the static NAT IP
+ * @param vmIp the VM's IP address
+ * @param vmId the ID of the VM
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createStaticNatRule(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String vpcCidr, String staticNatIp, String vmIp, long vmId);
+
+ /**
+ * Deletes a static NAT rule for a specific VM.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param networkResourceName the name of the network resource
+ * @param networkResourceId the ID of the network resource
+ * @param isForVpc true if the rule applies to a VPC
+ * @param staticNatIp the static NAT IP
+ * @param vmId the ID of the VM
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteStaticNatRule(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String staticNatIp, long vmId);
+
+ /**
+ * Adds firewall rules to a specific network.
+ *
+ * @param network the target network
+ * @param firewallRules the list of firewall rules to add
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean addFirewallRules(Network network, List firewallRules);
+
+ /**
+ * Deletes firewall rules from a specific network.
+ *
+ * @param network the target network
+ * @param firewallRules the list of firewall rules to delete
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteFirewallRules(Network network, List firewallRules);
+
+ /**
+ * Adds or updates a static route for a specific network or VPC.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param networkResourceName the name of the network resource
+ * @param networkResourceId the ID of the network resource
+ * @param isForVpc true if it is for a VPC
+ * @param prefix the IP prefix of the route
+ * @param nextHop the next hop address
+ * @param routeId the ID of the route
+ * @param updateRoute true if the route should be updated
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean addOrUpdateStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId, boolean updateRoute);
+
+ /**
+ * Deletes a specific static route for a network or VPC.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param networkResourceName the name of the network resource
+ * @param networkResourceId the ID of the network resource
+ * @param isForVpc true if it is for a VPC
+ * @param prefix the IP prefix of the route
+ * @param nextHop the next hop address
+ * @param routeId the ID of the route
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteStaticRoute(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId);
+
+ /**
+ * Lists static routes for a specific network or VPC.
+ *
+ * @param zoneId the ID of the zone
+ * @param accountId the ID of the account
+ * @param domainId the ID of the domain
+ * @param networkResourceName the name of the network resource
+ * @param networkResourceId the ID of the network resource
+ * @param isForVpc true if it is for a VPC
+ * @param prefix the IP prefix of the route
+ * @param nextHop the next hop address
+ * @param routeId the ID of the route
+ * @return a list of static routes
+ */
+ List listStaticRoutes(long zoneId, long accountId, long domainId, String networkResourceName, Long networkResourceId, boolean isForVpc, String prefix, String nextHop, Long routeId);
+
+ /**
+ * Releases a NAT IP address.
+ *
+ * @param zoneId the ID of the zone
+ * @param publicIp the public NAT IP to release
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean releaseNatIp(long zoneId, String publicIp);
+
+ /**
+ * Creates or updates a load balancer (LB) rule.
+ *
+ * @param rule the network rule for the load balancer
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean createOrUpdateLbRule(NetrisNetworkRule rule);
+
+ /**
+ * Deletes a load balancer (LB) rule.
+ *
+ * @param rule the network rule to delete
+ * @return true if the operation is successful, false otherwise
+ */
+ boolean deleteLbRule(NetrisNetworkRule rule);
+}
diff --git a/api/src/main/java/com/cloud/network/nsx/NsxService.java b/api/src/main/java/com/cloud/network/nsx/NsxService.java
index bc4e6aafbfe..1adb7461cc0 100644
--- a/api/src/main/java/com/cloud/network/nsx/NsxService.java
+++ b/api/src/main/java/com/cloud/network/nsx/NsxService.java
@@ -16,9 +16,10 @@
// under the License.
package com.cloud.network.nsx;
+import org.apache.cloudstack.framework.config.ConfigKey;
+
import com.cloud.network.IpAddress;
import com.cloud.network.vpc.Vpc;
-import org.apache.cloudstack.framework.config.ConfigKey;
public interface NsxService {
@@ -33,4 +34,5 @@ public interface NsxService {
boolean createVpcNetwork(Long zoneId, long accountId, long domainId, Long vpcId, String vpcName, boolean sourceNatEnabled);
boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address);
+ String getSegmentId(long domainId, long accountId, long zoneId, Long vpcId, long networkId);
}
diff --git a/api/src/main/java/com/cloud/network/vpc/StaticRoute.java b/api/src/main/java/com/cloud/network/vpc/StaticRoute.java
index 5707ca14024..739fca328b8 100644
--- a/api/src/main/java/com/cloud/network/vpc/StaticRoute.java
+++ b/api/src/main/java/com/cloud/network/vpc/StaticRoute.java
@@ -25,6 +25,7 @@ public interface StaticRoute extends ControlledEntity, Identity, InternalIdentit
Staged, // route been created but has never got through network rule conflict detection. Routes in this state can not be sent to VPC virtual router.
Add, // Add means the route has been created and has gone through network rule conflict detection.
Active, // Route has been sent to the VPC router and reported to be active.
+ Update,
Revoke, // Revoke means this route has been revoked. If this route has been sent to the VPC router, the route will be deleted from database.
Deleting // rule has been revoked and is scheduled for deletion
}
@@ -32,7 +33,9 @@ public interface StaticRoute extends ControlledEntity, Identity, InternalIdentit
/**
* @return
*/
- long getVpcGatewayId();
+ Long getVpcGatewayId();
+
+ String getNextHop();
/**
* @return
diff --git a/api/src/main/java/com/cloud/network/vpc/StaticRouteProfile.java b/api/src/main/java/com/cloud/network/vpc/StaticRouteProfile.java
index cb4849f1f7b..c8fc073911f 100644
--- a/api/src/main/java/com/cloud/network/vpc/StaticRouteProfile.java
+++ b/api/src/main/java/com/cloud/network/vpc/StaticRouteProfile.java
@@ -23,7 +23,8 @@ public class StaticRouteProfile implements StaticRoute {
private String targetCidr;
private long accountId;
private long domainId;
- private long gatewayId;
+ private Long gatewayId;
+ private String nextHop;
private StaticRoute.State state;
private long vpcId;
String vlanTag;
@@ -46,6 +47,18 @@ public class StaticRouteProfile implements StaticRoute {
ipAddress = gateway.getIp4Address();
}
+ public StaticRouteProfile(StaticRoute staticRoute) {
+ id = staticRoute.getId();
+ uuid = staticRoute.getUuid();
+ targetCidr = staticRoute.getCidr();
+ accountId = staticRoute.getAccountId();
+ domainId = staticRoute.getDomainId();
+ gatewayId = staticRoute.getVpcGatewayId();
+ state = staticRoute.getState();
+ vpcId = staticRoute.getVpcId();
+ gateway = staticRoute.getNextHop();
+ }
+
@Override
public long getAccountId() {
return accountId;
@@ -57,10 +70,15 @@ public class StaticRouteProfile implements StaticRoute {
}
@Override
- public long getVpcGatewayId() {
+ public Long getVpcGatewayId() {
return gatewayId;
}
+ @Override
+ public String getNextHop() {
+ return nextHop;
+ }
+
@Override
public String getCidr() {
return targetCidr;
diff --git a/api/src/main/java/com/cloud/network/vpc/Vpc.java b/api/src/main/java/com/cloud/network/vpc/Vpc.java
index e9a831c9d83..b94089d2d43 100644
--- a/api/src/main/java/com/cloud/network/vpc/Vpc.java
+++ b/api/src/main/java/com/cloud/network/vpc/Vpc.java
@@ -105,4 +105,6 @@ public interface Vpc extends ControlledEntity, Identity, InternalIdentity {
String getIp6Dns1();
String getIp6Dns2();
+
+ boolean useRouterIpAsResolver();
}
diff --git a/api/src/main/java/com/cloud/network/vpc/VpcOffering.java b/api/src/main/java/com/cloud/network/vpc/VpcOffering.java
index 38263f59667..17f49bb3652 100644
--- a/api/src/main/java/com/cloud/network/vpc/VpcOffering.java
+++ b/api/src/main/java/com/cloud/network/vpc/VpcOffering.java
@@ -32,6 +32,8 @@ public interface VpcOffering extends InternalIdentity, Identity {
public static final String redundantVPCOfferingName = "Redundant VPC offering";
public static final String DEFAULT_VPC_NAT_NSX_OFFERING_NAME = "VPC offering with NSX - NAT Mode";
public static final String DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME = "VPC offering with NSX - Route Mode";
+ public static final String DEFAULT_VPC_ROUTE_NETRIS_OFFERING_NAME = "VPC offering with Netris - Route Mode";
+ public static final String DEFAULT_VPC_NAT_NETRIS_OFFERING_NAME = "VPC offering with Netris - NAT Mode";
/**
*
@@ -56,8 +58,6 @@ public interface VpcOffering extends InternalIdentity, Identity {
*/
boolean isDefault();
- boolean isForNsx();
-
NetworkOffering.NetworkMode getNetworkMode();
/**
diff --git a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
index 10f1ddcc12d..97b95339ecf 100644
--- a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
+++ b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java
@@ -37,7 +37,7 @@ public interface VpcProvisioningService {
VpcOffering createVpcOffering(String name, String displayText, List supportedServices,
Map> serviceProviders,
Map serviceCapabilitystList, NetUtils.InternetProtocol internetProtocol,
- Long serviceOfferingId, Boolean forNsx, NetworkOffering.NetworkMode networkMode,
+ Long serviceOfferingId, String externalProvider, NetworkOffering.NetworkMode networkMode,
List domainIds, List zoneIds, VpcOffering.State state,
NetworkOffering.RoutingMode routingMode, boolean specifyAsNumber);
diff --git a/api/src/main/java/com/cloud/network/vpc/VpcService.java b/api/src/main/java/com/cloud/network/vpc/VpcService.java
index af2a9847a62..c1546609d2b 100644
--- a/api/src/main/java/com/cloud/network/vpc/VpcService.java
+++ b/api/src/main/java/com/cloud/network/vpc/VpcService.java
@@ -48,17 +48,17 @@ public interface VpcService {
* @param vpcName
* @param displayText
* @param cidr
- * @param networkDomain TODO
+ * @param networkDomain TODO
* @param ip4Dns1
* @param ip4Dns2
- * @param displayVpc TODO
+ * @param displayVpc TODO
+ * @param useVrIpResolver
* @return
* @throws ResourceAllocationException TODO
*/
Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName, String displayText, String cidr, String networkDomain,
String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Boolean displayVpc, Integer publicMtu, Integer cidrSize,
- Long asNumber, List bgpPeerIds)
- throws ResourceAllocationException;
+ Long asNumber, List bgpPeerIds, Boolean useVrIpResolver) throws ResourceAllocationException;
/**
* Persists VPC record in the database
@@ -238,7 +238,7 @@ public interface VpcService {
* @param cidr
* @return
*/
- StaticRoute createStaticRoute(long gatewayId, String cidr) throws NetworkRuleConflictException;
+ StaticRoute createStaticRoute(Long gatewayId, Long vpcId, String nextHop, String cidr) throws NetworkRuleConflictException;
/**
* Lists static routes based on parameters passed to the call
diff --git a/api/src/main/java/com/cloud/offering/DiskOfferingInfo.java b/api/src/main/java/com/cloud/offering/DiskOfferingInfo.java
index d83039e15c2..12dcf423e34 100644
--- a/api/src/main/java/com/cloud/offering/DiskOfferingInfo.java
+++ b/api/src/main/java/com/cloud/offering/DiskOfferingInfo.java
@@ -31,6 +31,13 @@ public class DiskOfferingInfo {
_diskOffering = diskOffering;
}
+ public DiskOfferingInfo(DiskOffering diskOffering, Long size, Long minIops, Long maxIops) {
+ _diskOffering = diskOffering;
+ _size = size;
+ _minIops = minIops;
+ _maxIops = maxIops;
+ }
+
public void setDiskOffering(DiskOffering diskOffering) {
_diskOffering = diskOffering;
}
diff --git a/api/src/main/java/com/cloud/offering/NetworkOffering.java b/api/src/main/java/com/cloud/offering/NetworkOffering.java
index 7011aea679e..5000a4f8c62 100644
--- a/api/src/main/java/com/cloud/offering/NetworkOffering.java
+++ b/api/src/main/java/com/cloud/offering/NetworkOffering.java
@@ -64,6 +64,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
public static final String DEFAULT_NAT_NSX_OFFERING_FOR_VPC = "DefaultNATNSXNetworkOfferingForVpc";
public static final String DEFAULT_NAT_NSX_OFFERING_FOR_VPC_WITH_ILB = "DefaultNATNSXNetworkOfferingForVpcWithInternalLB";
public static final String DEFAULT_ROUTED_NSX_OFFERING_FOR_VPC = "DefaultRoutedNSXNetworkOfferingForVpc";
+ public static final String DEFAULT_ROUTED_NETRIS_OFFERING_FOR_VPC = "DefaultRoutedNetrisNetworkOfferingForVpc";
+ public static final String DEFAULT_NAT_NETRIS_OFFERING_FOR_VPC = "DefaultNATNetrisNetworkOfferingForVpc";
public static final String DEFAULT_NAT_NSX_OFFERING = "DefaultNATNSXNetworkOffering";
public static final String DEFAULT_ROUTED_NSX_OFFERING = "DefaultRoutedNSXNetworkOffering";
public final static String QuickCloudNoServices = "QuickCloudNoServices";
@@ -102,10 +104,6 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
boolean isForVpc();
- boolean isForTungsten();
-
- boolean isForNsx();
-
NetworkMode getNetworkMode();
TrafficType getTrafficType();
diff --git a/api/src/main/java/com/cloud/offering/ServiceOffering.java b/api/src/main/java/com/cloud/offering/ServiceOffering.java
index acb7a9f1cf9..532123e4373 100644
--- a/api/src/main/java/com/cloud/offering/ServiceOffering.java
+++ b/api/src/main/java/com/cloud/offering/ServiceOffering.java
@@ -142,4 +142,8 @@ public interface ServiceOffering extends InfrastructureEntity, InternalIdentity,
Boolean getDiskOfferingStrictness();
void setDiskOfferingStrictness(boolean diskOfferingStrictness);
+
+ Long getVgpuProfileId();
+
+ Integer getGpuCount();
}
diff --git a/api/src/main/java/com/cloud/org/Cluster.java b/api/src/main/java/com/cloud/org/Cluster.java
index 5124168084c..b0aa6bb04cf 100644
--- a/api/src/main/java/com/cloud/org/Cluster.java
+++ b/api/src/main/java/com/cloud/org/Cluster.java
@@ -41,4 +41,6 @@ public interface Cluster extends Grouping, Partition {
ManagedState getManagedState();
CPU.CPUArch getArch();
+
+ String getStorageAccessGroups();
}
diff --git a/api/src/main/java/com/cloud/resource/ResourceService.java b/api/src/main/java/com/cloud/resource/ResourceService.java
index 562c3c418df..3cdf8fc64e9 100644
--- a/api/src/main/java/com/cloud/resource/ResourceService.java
+++ b/api/src/main/java/com/cloud/resource/ResourceService.java
@@ -95,4 +95,11 @@ public interface ResourceService {
boolean releaseHostReservation(Long hostId);
+ void updatePodStorageAccessGroups(long podId, List newStorageAccessGroups);
+
+ void updateZoneStorageAccessGroups(long zoneId, List newStorageAccessGroups);
+
+ void updateClusterStorageAccessGroups(Long clusterId, List newStorageAccessGroups);
+
+ void updateHostStorageAccessGroups(Long hostId, List newStorageAccessGroups);
}
diff --git a/api/src/main/java/com/cloud/resource/ResourceState.java b/api/src/main/java/com/cloud/resource/ResourceState.java
index 70738c7921b..e91cf820b08 100644
--- a/api/src/main/java/com/cloud/resource/ResourceState.java
+++ b/api/src/main/java/com/cloud/resource/ResourceState.java
@@ -76,6 +76,10 @@ public enum ResourceState {
}
}
+ public static List s_maintenanceStates = List.of(ResourceState.Maintenance,
+ ResourceState.ErrorInMaintenance, ResourceState.PrepareForMaintenance,
+ ResourceState.ErrorInPrepareForMaintenance);
+
public ResourceState getNextState(Event a) {
return s_fsm.getNextState(this, a);
}
@@ -98,8 +102,7 @@ public enum ResourceState {
}
public static boolean isMaintenanceState(ResourceState state) {
- return Arrays.asList(ResourceState.Maintenance, ResourceState.ErrorInMaintenance,
- ResourceState.PrepareForMaintenance, ResourceState.ErrorInPrepareForMaintenance).contains(state);
+ return s_maintenanceStates.contains(state);
}
public static boolean canAttemptMaintenance(ResourceState state) {
diff --git a/api/src/main/java/com/cloud/server/ManagementService.java b/api/src/main/java/com/cloud/server/ManagementService.java
index 18f3e901cd9..f7b2456ce5c 100644
--- a/api/src/main/java/com/cloud/server/ManagementService.java
+++ b/api/src/main/java/com/cloud/server/ManagementService.java
@@ -25,16 +25,20 @@ import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
import org.apache.cloudstack.api.command.admin.config.ListCfgGroupsByCmd;
import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd;
+import org.apache.cloudstack.api.command.admin.guest.AddGuestOsCategoryCmd;
import org.apache.cloudstack.api.command.admin.guest.AddGuestOsCmd;
import org.apache.cloudstack.api.command.admin.guest.AddGuestOsMappingCmd;
+import org.apache.cloudstack.api.command.admin.guest.DeleteGuestOsCategoryCmd;
import org.apache.cloudstack.api.command.admin.guest.GetHypervisorGuestOsNamesCmd;
import org.apache.cloudstack.api.command.admin.guest.ListGuestOsMappingCmd;
import org.apache.cloudstack.api.command.admin.guest.RemoveGuestOsCmd;
import org.apache.cloudstack.api.command.admin.guest.RemoveGuestOsMappingCmd;
+import org.apache.cloudstack.api.command.admin.guest.UpdateGuestOsCategoryCmd;
import org.apache.cloudstack.api.command.admin.guest.UpdateGuestOsCmd;
import org.apache.cloudstack.api.command.admin.guest.UpdateGuestOsMappingCmd;
import org.apache.cloudstack.api.command.admin.host.ListHostsCmd;
import org.apache.cloudstack.api.command.admin.host.UpdateHostPasswordCmd;
+import org.apache.cloudstack.api.command.admin.management.RemoveManagementServerCmd;
import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd;
import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd;
import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd;
@@ -59,8 +63,10 @@ import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd;
import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd;
+import org.apache.cloudstack.api.command.user.userdata.DeleteCniConfigurationCmd;
import org.apache.cloudstack.api.command.user.userdata.DeleteUserDataCmd;
import org.apache.cloudstack.api.command.user.userdata.ListUserDataCmd;
+import org.apache.cloudstack.api.command.user.userdata.RegisterCniConfigurationCmd;
import org.apache.cloudstack.api.command.user.userdata.RegisterUserDataCmd;
import org.apache.cloudstack.api.command.user.vm.GetVMPasswordCmd;
import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
@@ -168,6 +174,12 @@ public interface ManagementService {
*/
Pair, Integer> listGuestOSCategoriesByCriteria(ListGuestOsCategoriesCmd cmd);
+ GuestOsCategory addGuestOsCategory(AddGuestOsCategoryCmd cmd);
+
+ GuestOsCategory updateGuestOsCategory(UpdateGuestOsCategoryCmd cmd);
+
+ boolean deleteGuestOsCategory(DeleteGuestOsCategoryCmd cmd);
+
/**
* Obtains a list of all guest OS mappings
*
@@ -360,17 +372,23 @@ public interface ManagementService {
* The api command class.
* @return The list of userdatas found.
*/
- Pair, Integer> listUserDatas(ListUserDataCmd cmd);
+ Pair, Integer> listUserDatas(ListUserDataCmd cmd, boolean forCks);
+
+ /**
+ * Registers a cni configuration.
+ *
+ * @param cmd The api command class.
+ * @return A VO with the registered user data.
+ */
+ UserData registerCniConfiguration(RegisterCniConfigurationCmd cmd);
/**
* Registers a userdata.
*
- * @param cmd
- * The api command class.
+ * @param cmd The api command class.
* @return A VO with the registered userdata.
*/
UserData registerUserData(RegisterUserDataCmd cmd);
-
/**
* Deletes a userdata.
*
@@ -380,6 +398,14 @@ public interface ManagementService {
*/
boolean deleteUserData(DeleteUserDataCmd cmd);
+ /**
+ * Deletes user data.
+ *
+ * @param cmd
+ * The api command class.
+ * @return True on success. False otherwise.
+ */
+ boolean deleteCniConfiguration(DeleteCniConfigurationCmd cmd);
/**
* Search registered key pairs for the logged in user.
*
@@ -481,4 +507,6 @@ public interface ManagementService {
Pair patchSystemVM(PatchSystemVMCmd cmd);
+ boolean removeManagementServer(RemoveManagementServerCmd cmd);
+
}
diff --git a/api/src/main/java/com/cloud/server/ResourceIconManager.java b/api/src/main/java/com/cloud/server/ResourceIconManager.java
index e5111d9160b..d10b3eb0cd5 100644
--- a/api/src/main/java/com/cloud/server/ResourceIconManager.java
+++ b/api/src/main/java/com/cloud/server/ResourceIconManager.java
@@ -16,7 +16,9 @@
// under the License.
package com.cloud.server;
+import java.util.Collection;
import java.util.List;
+import java.util.Map;
public interface ResourceIconManager {
@@ -25,4 +27,8 @@ public interface ResourceIconManager {
boolean deleteResourceIcon(List resourceIds, ResourceTag.ResourceObjectType resourceType);
ResourceIcon getByResourceTypeAndUuid(ResourceTag.ResourceObjectType type, String resourceId);
+
+ Map getByResourceTypeAndIds(ResourceTag.ResourceObjectType type, Collection resourceIds);
+
+ Map getByResourceTypeAndUuids(ResourceTag.ResourceObjectType type, Collection resourceUuids);
}
diff --git a/api/src/main/java/com/cloud/server/ResourceTag.java b/api/src/main/java/com/cloud/server/ResourceTag.java
index 9bbb5d43eae..b3026deceff 100644
--- a/api/src/main/java/com/cloud/server/ResourceTag.java
+++ b/api/src/main/java/com/cloud/server/ResourceTag.java
@@ -66,6 +66,7 @@ public interface ResourceTag extends ControlledEntity, Identity, InternalIdentit
LBStickinessPolicy(false, true),
LBHealthCheckPolicy(false, true),
SnapshotPolicy(true, true),
+ GuestOsCategory(false, false, true),
GuestOs(false, true),
NetworkOffering(false, true),
VpcOffering(true, false),
diff --git a/api/src/main/java/com/cloud/storage/GuestOsCategory.java b/api/src/main/java/com/cloud/storage/GuestOsCategory.java
index b46418d5c8f..e1ee4489158 100644
--- a/api/src/main/java/com/cloud/storage/GuestOsCategory.java
+++ b/api/src/main/java/com/cloud/storage/GuestOsCategory.java
@@ -16,6 +16,8 @@
// under the License.
package com.cloud.storage;
+import java.util.Date;
+
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
@@ -27,4 +29,7 @@ public interface GuestOsCategory extends Identity, InternalIdentity {
void setName(String name);
+ boolean isFeatured();
+
+ Date getCreated();
}
diff --git a/api/src/main/java/com/cloud/storage/MigrationOptions.java b/api/src/main/java/com/cloud/storage/MigrationOptions.java
index a39a2a7c827..8b642d09e29 100644
--- a/api/src/main/java/com/cloud/storage/MigrationOptions.java
+++ b/api/src/main/java/com/cloud/storage/MigrationOptions.java
@@ -24,6 +24,7 @@ public class MigrationOptions implements Serializable {
private String srcPoolUuid;
private Storage.StoragePoolType srcPoolType;
+ private Long srcPoolClusterId;
private Type type;
private ScopeType scopeType;
private String srcBackingFilePath;
@@ -38,21 +39,23 @@ public class MigrationOptions implements Serializable {
public MigrationOptions() {
}
- public MigrationOptions(String srcPoolUuid, Storage.StoragePoolType srcPoolType, String srcBackingFilePath, boolean copySrcTemplate, ScopeType scopeType) {
+ public MigrationOptions(String srcPoolUuid, Storage.StoragePoolType srcPoolType, String srcBackingFilePath, boolean copySrcTemplate, ScopeType scopeType, Long srcPoolClusterId) {
this.srcPoolUuid = srcPoolUuid;
this.srcPoolType = srcPoolType;
this.type = Type.LinkedClone;
this.scopeType = scopeType;
this.srcBackingFilePath = srcBackingFilePath;
this.copySrcTemplate = copySrcTemplate;
+ this.srcPoolClusterId = srcPoolClusterId;
}
- public MigrationOptions(String srcPoolUuid, Storage.StoragePoolType srcPoolType, String srcVolumeUuid, ScopeType scopeType) {
+ public MigrationOptions(String srcPoolUuid, Storage.StoragePoolType srcPoolType, String srcVolumeUuid, ScopeType scopeType, Long srcPoolClusterId) {
this.srcPoolUuid = srcPoolUuid;
this.srcPoolType = srcPoolType;
this.type = Type.FullClone;
this.scopeType = scopeType;
this.srcVolumeUuid = srcVolumeUuid;
+ this.srcPoolClusterId = srcPoolClusterId;
}
public String getSrcPoolUuid() {
@@ -63,6 +66,10 @@ public class MigrationOptions implements Serializable {
return srcPoolType;
}
+ public Long getSrcPoolClusterId() {
+ return srcPoolClusterId;
+ }
+
public ScopeType getScopeType() { return scopeType; }
public String getSrcBackingFilePath() {
diff --git a/api/src/main/java/com/cloud/storage/Snapshot.java b/api/src/main/java/com/cloud/storage/Snapshot.java
index fc919e442b2..c0a7b812ed9 100644
--- a/api/src/main/java/com/cloud/storage/Snapshot.java
+++ b/api/src/main/java/com/cloud/storage/Snapshot.java
@@ -48,7 +48,7 @@ public interface Snapshot extends ControlledEntity, Identity, InternalIdentity,
}
public enum State {
- Allocated, Creating, CreatedOnPrimary, BackingUp, BackedUp, Copying, Destroying, Destroyed,
+ Allocated, Creating, CreatedOnPrimary, BackingUp, BackedUp, Copying, Destroying, Destroyed, Hidden,
//it's a state, user can't see the snapshot from ui, while the snapshot may still exist on the storage
Error;
diff --git a/api/src/main/java/com/cloud/storage/Storage.java b/api/src/main/java/com/cloud/storage/Storage.java
index 05b8b3ab7a8..1ad3731b9ea 100644
--- a/api/src/main/java/com/cloud/storage/Storage.java
+++ b/api/src/main/java/com/cloud/storage/Storage.java
@@ -30,6 +30,7 @@ public class Storage {
OVA(true, true, true, "ova"),
VHDX(true, true, true, "vhdx"),
BAREMETAL(false, false, false, "BAREMETAL"),
+ EXTERNAL(false, false, false, "EXTERNAL"),
VMDK(true, true, false, "vmdk"),
VDI(true, true, false, "vdi"),
TAR(false, false, false, "tar"),
diff --git a/api/src/main/java/com/cloud/storage/StorageService.java b/api/src/main/java/com/cloud/storage/StorageService.java
index b8df75cd3e4..a29c8f6aece 100644
--- a/api/src/main/java/com/cloud/storage/StorageService.java
+++ b/api/src/main/java/com/cloud/storage/StorageService.java
@@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd;
import org.apache.cloudstack.api.command.admin.storage.ChangeStoragePoolScopeCmd;
+import org.apache.cloudstack.api.command.admin.storage.ConfigureStorageAccessCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd;
import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd;
@@ -99,6 +100,8 @@ public interface StorageService {
StoragePool disablePrimaryStoragePool(Long id);
+ boolean configureStorageAccess(ConfigureStorageAccessCmd cmd);
+
StoragePool getStoragePool(long id);
boolean deleteImageStore(DeleteImageStoreCmd cmd);
@@ -131,7 +134,7 @@ public interface StorageService {
void removeSecondaryStorageHeuristic(RemoveSecondaryStorageSelectorCmd cmd);
- ObjectStore discoverObjectStore(String name, String url, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
+ ObjectStore discoverObjectStore(String name, String url, Long size, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException;
boolean deleteObjectStore(DeleteObjectStoragePoolCmd cmd);
diff --git a/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java b/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java
index f43d5331222..db702a61f2b 100644
--- a/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java
+++ b/api/src/main/java/com/cloud/storage/VMTemplateStorageResourceAssoc.java
@@ -17,6 +17,7 @@
package com.cloud.storage;
import java.util.Date;
+import java.util.List;
import org.apache.cloudstack.api.InternalIdentity;
@@ -25,6 +26,8 @@ public interface VMTemplateStorageResourceAssoc extends InternalIdentity {
UNKNOWN, DOWNLOAD_ERROR, NOT_DOWNLOADED, DOWNLOAD_IN_PROGRESS, DOWNLOADED, ABANDONED, UPLOADED, NOT_UPLOADED, UPLOAD_ERROR, UPLOAD_IN_PROGRESS, CREATING, CREATED, BYPASSED
}
+ List PENDING_DOWNLOAD_STATES = List.of(Status.NOT_DOWNLOADED, Status.DOWNLOAD_IN_PROGRESS);
+
String getInstallPath();
long getTemplateId();
diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java
index 3a72f8bddc4..4140d51a800 100644
--- a/api/src/main/java/com/cloud/storage/VolumeApiService.java
+++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java
@@ -22,7 +22,12 @@ import java.net.MalformedURLException;
import java.util.List;
import java.util.Map;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.offering.DiskOffering;
+import com.cloud.user.Account;
import com.cloud.utils.Pair;
+import com.cloud.utils.fsm.NoTransitionException;
+
import org.apache.cloudstack.api.command.user.volume.AssignVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.ChangeOfferingForVolumeCmd;
@@ -37,13 +42,9 @@ import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
import org.apache.cloudstack.api.response.GetUploadParamsResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
-import com.cloud.exception.ResourceAllocationException;
-import com.cloud.user.Account;
-import com.cloud.utils.fsm.NoTransitionException;
-
public interface VolumeApiService {
- ConfigKey ConcurrentMigrationsThresholdPerDatastore = new ConfigKey("Advanced"
+ ConfigKey ConcurrentMigrationsThresholdPerDatastore = new ConfigKey<>("Advanced"
, Long.class
, "concurrent.migrations.per.target.datastore"
, "0"
@@ -51,7 +52,7 @@ public interface VolumeApiService {
, true // not sure if this is to be dynamic
, ConfigKey.Scope.Global);
- ConfigKey UseHttpsToUpload = new ConfigKey("Advanced",
+ ConfigKey UseHttpsToUpload = new ConfigKey<>("Advanced",
Boolean.class,
"use.https.to.upload",
"true",
@@ -85,7 +86,7 @@ public interface VolumeApiService {
* @param cmd
* the API command wrapping the criteria
* @return the volume object
- * @throws ResourceAllocationException
+ * @throws ResourceAllocationException no capacity to allocate the new volume size
*/
Volume resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationException;
@@ -112,10 +113,10 @@ public interface VolumeApiService {
Volume detachVolumeFromVM(DetachVolumeCmd cmd);
- Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup, Map tags, List zoneIds)
+ Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup, Map tags, List zoneIds, List poolIds, Boolean useStorageReplication)
throws ResourceAllocationException;
- Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, List zoneIds) throws ResourceAllocationException;
+ Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, List zoneIds, List storagePoolIds, Boolean useStorageReplication) throws ResourceAllocationException;
Volume updateVolume(long volumeId, String path, String state, Long storageId,
Boolean displayVolume, Boolean deleteProtection,
@@ -136,16 +137,16 @@ public interface VolumeApiService {
void updateDisplay(Volume volume, Boolean displayVolume);
- Snapshot allocSnapshotForVm(Long vmId, Long volumeId, String snapshotName) throws ResourceAllocationException;
+ Snapshot allocSnapshotForVm(Long vmId, Long volumeId, String snapshotName, Long vmSnapshotId) throws ResourceAllocationException;
/**
- * Checks if the target storage supports the disk offering.
+ * Checks if the storage pool supports the disk offering tags.
* This validation is consistent with the mechanism used to select a storage pool to deploy a volume when a virtual machine is deployed or when a data disk is allocated.
*
* The scenarios when this method returns true or false is presented in the following table.
*
*
- * | # | Disk offering tags | Storage tags | Does the storage support the disk offering? |
+ * # | Disk offering diskOfferingTags | Storage diskOfferingTags | Does the storage support the disk offering? |
*
*
*
@@ -169,7 +170,15 @@ public interface VolumeApiService {
*
*
*/
- boolean doesTargetStorageSupportDiskOffering(StoragePool destPool, String diskOfferingTags);
+ boolean doesStoragePoolSupportDiskOffering(StoragePool destPool, DiskOffering diskOffering);
+
+ /**
+ * Checks if the storage pool supports the required disk offering tags
+ * destPool the storage pool to check the disk offering tags
+ * diskOfferingTags the tags that should be supported
+ * return whether the tags are supported in the storage pool
+ */
+ boolean doesStoragePoolSupportDiskOfferingTags(StoragePool destPool, String diskOfferingTags);
Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge);
diff --git a/api/src/main/java/com/cloud/template/TemplateApiService.java b/api/src/main/java/com/cloud/template/TemplateApiService.java
index 5b494c308c3..6138f24c92b 100644
--- a/api/src/main/java/com/cloud/template/TemplateApiService.java
+++ b/api/src/main/java/com/cloud/template/TemplateApiService.java
@@ -58,10 +58,23 @@ public interface TemplateApiService {
VirtualMachineTemplate prepareTemplate(long templateId, long zoneId, Long storageId);
+ /**
+ * Detach ISO from VM
+ * @param vmId id of the VM
+ * @param isoId id of the ISO (when passed). If it is not passed, it will get it from user_vm table
+ * @param extraParams forced, isVirtualRouter
+ * @return true when operation succeeds, false if not
+ */
+ boolean detachIso(long vmId, Long isoId, Boolean... extraParams);
- boolean detachIso(long vmId, boolean forced);
-
- boolean attachIso(long isoId, long vmId, boolean forced);
+ /**
+ * Attach ISO to a VM
+ * @param isoId id of the ISO to attach
+ * @param vmId id of the VM to attach the ISO to
+ * @param extraParams: forced, isVirtualRouter
+ * @return true when operation succeeds, false if not
+ */
+ boolean attachIso(long isoId, long vmId, Boolean... extraParams);
/**
* Deletes a template
diff --git a/api/src/main/java/com/cloud/template/VirtualMachineTemplate.java b/api/src/main/java/com/cloud/template/VirtualMachineTemplate.java
index d8872d5fe72..b8c646048b9 100644
--- a/api/src/main/java/com/cloud/template/VirtualMachineTemplate.java
+++ b/api/src/main/java/com/cloud/template/VirtualMachineTemplate.java
@@ -145,10 +145,14 @@ public interface VirtualMachineTemplate extends ControlledEntity, Identity, Inte
boolean isDeployAsIs();
+ boolean isForCks();
+
Long getUserDataId();
UserData.UserDataOverridePolicy getUserDataOverridePolicy();
CPU.CPUArch getArch();
+ Long getExtensionId();
+
}
diff --git a/api/src/main/java/com/cloud/user/Account.java b/api/src/main/java/com/cloud/user/Account.java
index 6be4d0a48f6..1cc5eae64a6 100644
--- a/api/src/main/java/com/cloud/user/Account.java
+++ b/api/src/main/java/com/cloud/user/Account.java
@@ -71,6 +71,7 @@ public interface Account extends ControlledEntity, InternalIdentity, Identity {
}
public static final long ACCOUNT_ID_SYSTEM = 1;
+ public static final long ACCOUNT_ID_ADMIN = 2;
public String getAccountName();
diff --git a/api/src/main/java/com/cloud/user/AccountService.java b/api/src/main/java/com/cloud/user/AccountService.java
index e2c3bed0c29..c0ebcf09f59 100644
--- a/api/src/main/java/com/cloud/user/AccountService.java
+++ b/api/src/main/java/com/cloud/user/AccountService.java
@@ -87,6 +87,8 @@ public interface AccountService {
boolean isDomainAdmin(Long accountId);
+ boolean isResourceDomainAdmin(Long accountId);
+
boolean isNormalUser(long accountId);
User getActiveUserByRegistrationToken(String registrationToken);
diff --git a/api/src/main/java/com/cloud/user/ResourceLimitService.java b/api/src/main/java/com/cloud/user/ResourceLimitService.java
index 2f4ad1347be..49b20fe2fef 100644
--- a/api/src/main/java/com/cloud/user/ResourceLimitService.java
+++ b/api/src/main/java/com/cloud/user/ResourceLimitService.java
@@ -50,8 +50,14 @@ public interface ResourceLimitService {
"The default maximum number of projects that can be created for an account",false);
static final ConfigKey DefaultMaxDomainProjects = new ConfigKey<>("Domain Defaults",Long.class,"max.domain.projects","50",
"The default maximum number of projects that can be created for a domain",false);
+ static final ConfigKey DefaultMaxAccountGpus = new ConfigKey<>("Account Defaults",Long.class,"max.account.gpus","20",
+ "The default maximum number of GPU devices that can be used for an account", false);
+ static final ConfigKey DefaultMaxDomainGpus = new ConfigKey<>("Domain Defaults",Long.class,"max.domain.gpus","20",
+ "The default maximum number of GPU devices that can be used for a domain", false);
+ static final ConfigKey DefaultMaxProjectGpus = new ConfigKey<>("Project Defaults",Long.class,"max.project.gpus","20",
+ "The default maximum number of GPU devices that can be used for a project", false);
- static final List HostTagsSupportingTypes = List.of(ResourceType.user_vm, ResourceType.cpu, ResourceType.memory);
+ static final List HostTagsSupportingTypes = List.of(ResourceType.user_vm, ResourceType.cpu, ResourceType.memory, ResourceType.gpu);
static final List StorageTagsSupportingTypes = List.of(ResourceType.volume, ResourceType.primary_storage);
/**
@@ -284,4 +290,8 @@ public interface ResourceLimitService {
void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
void decrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory);
+ void checkVmGpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu) throws ResourceAllocationException;
+ void incrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu);
+ void decrementVmGpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long gpu);
+
}
diff --git a/api/src/main/java/com/cloud/user/UserData.java b/api/src/main/java/com/cloud/user/UserData.java
index fa0c50473c0..13a3c74f367 100644
--- a/api/src/main/java/com/cloud/user/UserData.java
+++ b/api/src/main/java/com/cloud/user/UserData.java
@@ -29,4 +29,5 @@ public interface UserData extends ControlledEntity, InternalIdentity, Identity {
String getUserData();
String getParams();
+ boolean isForCks();
}
diff --git a/api/src/main/java/com/cloud/vm/UserVmService.java b/api/src/main/java/com/cloud/vm/UserVmService.java
index 72b18b70e18..6f1aba4613d 100644
--- a/api/src/main/java/com/cloud/vm/UserVmService.java
+++ b/api/src/main/java/com/cloud/vm/UserVmService.java
@@ -16,14 +16,18 @@
// under the License.
package com.cloud.vm;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.Volume;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import com.cloud.deploy.DeploymentPlan;
import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd;
import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd;
import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd;
+import org.apache.cloudstack.api.command.user.vm.CreateVMFromBackupCmd;
import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd;
import org.apache.cloudstack.api.command.user.vm.RebootVMCmd;
@@ -111,7 +115,7 @@ public interface UserVmService {
UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ResourceAllocationException;
- void startVirtualMachine(UserVm vm) throws OperationTimedoutException, ResourceUnavailableException, InsufficientCapacityException;
+ void startVirtualMachine(UserVm vm, DeploymentPlan plan) throws OperationTimedoutException, ResourceUnavailableException, InsufficientCapacityException;
void startVirtualMachineForHA(VirtualMachine vm, Map params,
DeploymentPlanner planner) throws InsufficientCapacityException, ResourceUnavailableException,
@@ -217,11 +221,11 @@ public interface UserVmService {
* available.
*/
UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List securityGroupIdList,
- Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
+ Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, List dataDiskInfoList, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
String userData, Long userDataId, String userDataDetails, List sshKeyPairs, Map requestedIps, IpAddresses defaultIp, Boolean displayVm, String keyboard,
List affinityGroupIdList, Map customParameter, String customId, Map> dhcpOptionMap,
Map dataDiskTemplateToDiskOfferingMap,
- Map userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId) throws InsufficientCapacityException,
+ Map userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId, Volume volume, Snapshot snapshot) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
/**
@@ -294,10 +298,10 @@ public interface UserVmService {
* available.
*/
UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList,
- List securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
+ List securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, List dataDiskInfoList, String group, HypervisorType hypervisor,
HTTPMethod httpmethod, String userData, Long userDataId, String userDataDetails, List sshKeyPairs, Map requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard,
List affinityGroupIdList, Map customParameters, String customId, Map> dhcpOptionMap,
- Map dataDiskTemplateToDiskOfferingMap, Map userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId, String vmType) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
+ Map dataDiskTemplateToDiskOfferingMap, Map userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId, String vmType, Volume volume, Snapshot snapshot) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
/**
* Creates a User VM in Advanced Zone (Security Group feature is disabled)
@@ -366,10 +370,10 @@ public interface UserVmService {
* available.
*/
UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, Account owner,
- String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData,
+ String hostName, String displayName, Long diskOfferingId, Long diskSize, List dataDiskInfoList, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData,
Long userDataId, String userDataDetails, List sshKeyPairs, Map requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, List affinityGroupIdList,
Map customParameters, String customId, Map> dhcpOptionMap, Map dataDiskTemplateToDiskOfferingMap,
- Map templateOvfPropertiesMap, boolean dynamicScalingEnabled, String vmType, Long overrideDiskOfferingId)
+ Map templateOvfPropertiesMap, boolean dynamicScalingEnabled, String vmType, Long overrideDiskOfferingId, Volume volume, Snapshot snapshot)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
@@ -513,4 +517,8 @@ public interface UserVmService {
* @return true if the VM is successfully unmanaged, false if not.
*/
boolean unmanageUserVM(Long vmId);
+
+ UserVm allocateVMFromBackup(CreateVMFromBackupCmd cmd) throws InsufficientCapacityException, ResourceAllocationException, ResourceUnavailableException;
+
+ UserVm restoreVMFromBackup(CreateVMFromBackupCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException;
}
diff --git a/api/src/main/java/com/cloud/vm/VirtualMachine.java b/api/src/main/java/com/cloud/vm/VirtualMachine.java
index e2ea408e7b8..d244de7115e 100644
--- a/api/src/main/java/com/cloud/vm/VirtualMachine.java
+++ b/api/src/main/java/com/cloud/vm/VirtualMachine.java
@@ -128,7 +128,6 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Partition,
s_fsm.addTransition(new Transition(State.Error, VirtualMachine.Event.DestroyRequested, State.Expunging, null));
s_fsm.addTransition(new Transition(State.Error, VirtualMachine.Event.ExpungeOperation, State.Expunging, null));
s_fsm.addTransition(new Transition(State.Stopped, Event.RestoringRequested, State.Restoring, null));
- s_fsm.addTransition(new Transition(State.Expunging, Event.RestoringRequested, State.Restoring, null));
s_fsm.addTransition(new Transition(State.Destroyed, Event.RestoringRequested, State.Restoring, null));
s_fsm.addTransition(new Transition(State.Restoring, Event.RestoringSuccess, State.Stopped, null));
s_fsm.addTransition(new Transition(State.Restoring, Event.RestoringFailed, State.Stopped, null));
diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java
index 29803d5271b..596c861218f 100644
--- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java
+++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java
@@ -41,6 +41,7 @@ public interface VmDetailConstants {
String KVM_VNC_PORT = "kvm.vnc.port";
String KVM_VNC_ADDRESS = "kvm.vnc.address";
String KVM_VNC_PASSWORD = "kvm.vnc.password";
+ String KVM_GUEST_OS_MACHINE_TYPE = "kvm.guest.os.machine.type";
// KVM specific, custom virtual GPU hardware
String VIDEO_HARDWARE = "video.hardware";
@@ -89,6 +90,9 @@ public interface VmDetailConstants {
String DEPLOY_AS_IS_CONFIGURATION = "configurationId";
String KEY_PAIR_NAMES = "keypairnames";
String CKS_CONTROL_NODE_LOGIN_USER = "controlNodeLoginUser";
+ String CKS_NODE_TYPE = "node";
+ String OFFERING = "offering";
+ String TEMPLATE = "template";
// VMware to KVM VM migrations specific
String VMWARE_TO_KVM_PREFIX = "vmware-to-kvm";
@@ -101,4 +105,25 @@ public interface VmDetailConstants {
String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX);
String VMWARE_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX);
String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", VMWARE_TO_KVM_PREFIX);
+
+ // TPM
+ String VIRTUAL_TPM_ENABLED = "virtual.tpm.enabled";
+ String VIRTUAL_TPM_MODEL = "virtual.tpm.model";
+ String VIRTUAL_TPM_VERSION = "virtual.tpm.version";
+
+ // CPU mode and model, ADMIN only
+ String GUEST_CPU_MODE = "guest.cpu.mode";
+ String GUEST_CPU_MODEL = "guest.cpu.model";
+
+ // Lease related
+ String INSTANCE_LEASE_EXPIRY_DATE = "leaseexpirydate";
+ String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction";
+ String INSTANCE_LEASE_EXECUTION = "leaseactionexecution";
+
+ // External orchestrator related
+ String MAC_ADDRESS = "mac_address";
+ String EXPUNGE_EXTERNAL_VM = "expunge.external.vm";
+ String EXTERNAL_DETAIL_PREFIX = "External:";
+ String CLOUDSTACK_VM_DETAILS = "cloudstack.vm.details";
+ String CLOUDSTACK_VLAN = "cloudstack.vlan";
}
diff --git a/api/src/main/java/com/cloud/vm/VmDiskInfo.java b/api/src/main/java/com/cloud/vm/VmDiskInfo.java
new file mode 100644
index 00000000000..b8779a8d77c
--- /dev/null
+++ b/api/src/main/java/com/cloud/vm/VmDiskInfo.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+package com.cloud.vm;
+
+import com.cloud.offering.DiskOffering;
+import com.cloud.offering.DiskOfferingInfo;
+
+public class VmDiskInfo extends DiskOfferingInfo {
+ private Long _deviceId;
+
+ public VmDiskInfo(DiskOffering diskOffering, Long size, Long minIops, Long maxIops) {
+ super(diskOffering, size, minIops, maxIops);
+ }
+
+ public VmDiskInfo(DiskOffering diskOffering, Long size, Long minIops, Long maxIops, Long deviceId) {
+ super(diskOffering, size, minIops, maxIops);
+ _deviceId = deviceId;
+ }
+
+ public Long getDeviceId() {
+ return _deviceId;
+ }
+}
diff --git a/api/src/main/java/com/cloud/vm/snapshot/VMSnapshot.java b/api/src/main/java/com/cloud/vm/snapshot/VMSnapshot.java
index 3897df2d5e6..24e93af1562 100644
--- a/api/src/main/java/com/cloud/vm/snapshot/VMSnapshot.java
+++ b/api/src/main/java/com/cloud/vm/snapshot/VMSnapshot.java
@@ -31,7 +31,8 @@ public interface VMSnapshot extends ControlledEntity, Identity, InternalIdentity
enum State {
Allocated("The VM snapshot is allocated but has not been created yet."), Creating("The VM snapshot is being created."), Ready(
"The VM snapshot is ready to be used."), Reverting("The VM snapshot is being used to revert"), Expunging("The volume is being expunging"), Removed(
- "The volume is destroyed, and can't be recovered."), Error("The volume is in error state, and can't be recovered");
+ "The volume is destroyed, and can't be recovered."), Error("The volume is in error state, and can't be recovered"),
+ Hidden("The VM snapshot is hidden from the user and cannot be recovered.");
String _description;
@@ -60,6 +61,8 @@ public interface VMSnapshot extends ControlledEntity, Identity, InternalIdentity
s_fsm.addTransition(Expunging, Event.ExpungeRequested, Expunging);
s_fsm.addTransition(Expunging, Event.OperationSucceeded, Removed);
s_fsm.addTransition(Expunging, Event.OperationFailed, Error);
+ s_fsm.addTransition(Expunging, Event.Hide, Hidden);
+ s_fsm.addTransition(Hidden, Event.ExpungeRequested, Expunging);
}
}
@@ -68,7 +71,7 @@ public interface VMSnapshot extends ControlledEntity, Identity, InternalIdentity
}
enum Event {
- CreateRequested, OperationFailed, OperationSucceeded, RevertRequested, ExpungeRequested,
+ CreateRequested, OperationFailed, OperationSucceeded, RevertRequested, ExpungeRequested, Hide,
}
@Override
diff --git a/api/src/main/java/org/apache/cloudstack/acl/RoleType.java b/api/src/main/java/org/apache/cloudstack/acl/RoleType.java
index 005d47c85bc..46e4f1bc510 100644
--- a/api/src/main/java/org/apache/cloudstack/acl/RoleType.java
+++ b/api/src/main/java/org/apache/cloudstack/acl/RoleType.java
@@ -23,8 +23,11 @@ import com.google.common.base.Enums;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
+import java.util.Collection;
+import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
// Enum for default roles in CloudStack
public enum RoleType {
@@ -100,6 +103,30 @@ public enum RoleType {
return roleId;
}
+ public static int toCombinedMask(Collection roles) {
+ int combinedMask = 0;
+ if (roles != null) {
+ for (RoleType role : roles) {
+ combinedMask |= role.getMask();
+ }
+ }
+ return combinedMask;
+ }
+
+ public static Set fromCombinedMask(int combinedMask) {
+ Set roles = EnumSet.noneOf(RoleType.class);
+ for (RoleType roleType : RoleType.values()) {
+ if ((combinedMask & roleType.getMask()) != 0) {
+ roles.add(roleType);
+ }
+ }
+ if (roles.isEmpty()) {
+ roles.add(Unknown);
+ }
+ return roles;
+ }
+
+
/**
* This method returns the role account type if the role isn't null, else it returns the default account type.
* */
diff --git a/api/src/main/java/org/apache/cloudstack/alert/AlertService.java b/api/src/main/java/org/apache/cloudstack/alert/AlertService.java
index 1250284b5c2..d8e471756a0 100644
--- a/api/src/main/java/org/apache/cloudstack/alert/AlertService.java
+++ b/api/src/main/java/org/apache/cloudstack/alert/AlertService.java
@@ -73,6 +73,9 @@ public interface AlertService {
public static final AlertType ALERT_TYPE_VM_SNAPSHOT = new AlertType((short)32, "ALERT.VM.SNAPSHOT", true);
public static final AlertType ALERT_TYPE_VR_PUBLIC_IFACE_MTU = new AlertType((short)32, "ALERT.VR.PUBLIC.IFACE.MTU", true);
public static final AlertType ALERT_TYPE_VR_PRIVATE_IFACE_MTU = new AlertType((short)32, "ALERT.VR.PRIVATE.IFACE.MTU", true);
+ public static final AlertType ALERT_TYPE_EXTENSION_PATH_NOT_READY = new AlertType((short)33, "ALERT.TYPE.EXTENSION.PATH.NOT.READY", true);
+ public static final AlertType ALERT_TYPE_BACKUP_STORAGE = new AlertType(Capacity.CAPACITY_TYPE_BACKUP_STORAGE, "ALERT.STORAGE.BACKUP", true);
+ public static final AlertType ALERT_TYPE_OBJECT_STORAGE = new AlertType(Capacity.CAPACITY_TYPE_OBJECT_STORAGE, "ALERT.STORAGE.OBJECT", true);
public short getType() {
return type;
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java b/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java
index f2f52cec969..4d33ba859a5 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java
@@ -61,6 +61,7 @@ public enum ApiCommandResourceType {
AffinityGroup(org.apache.cloudstack.affinity.AffinityGroup.class),
InternalLbVm(com.cloud.network.router.VirtualRouter.class),
DedicatedGuestVlanRange(com.cloud.network.GuestVlan.class),
+ GuestOsCategory(com.cloud.storage.GuestOsCategory.class),
GuestOs(com.cloud.storage.GuestOS.class),
GuestOsMapping(com.cloud.storage.GuestOSHypervisor.class),
Network(com.cloud.network.Network.class),
@@ -84,9 +85,11 @@ public enum ApiCommandResourceType {
ObjectStore(org.apache.cloudstack.storage.object.ObjectStore.class),
Bucket(org.apache.cloudstack.storage.object.Bucket.class),
QuotaTariff(org.apache.cloudstack.quota.QuotaTariff.class),
- KubernetesCluster(null),
+ KubernetesCluster(com.cloud.kubernetes.cluster.KubernetesCluster.class),
KubernetesSupportedVersion(null),
- SharedFS(org.apache.cloudstack.storage.sharedfs.SharedFS.class);
+ SharedFS(org.apache.cloudstack.storage.sharedfs.SharedFS.class),
+ Extension(org.apache.cloudstack.extension.Extension.class),
+ ExtensionCustomAction(org.apache.cloudstack.extension.ExtensionCustomAction.class);
private final Class> clazz;
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 3e8b329cac7..489d737b5bb 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -23,15 +23,18 @@ public class ApiConstants {
public static final String ACCOUNT_ID = "accountid";
public static final String ACCOUNT_IDS = "accountids";
public static final String ACCUMULATE = "accumulate";
+ public static final String ACQUIRED = "acquired";
public static final String ACTIVATION_RULE = "activationrule";
public static final String ACTIVITY = "activity";
public static final String ADAPTER_TYPE = "adaptertype";
public static final String ADDRESS = "address";
public static final String ALGORITHM = "algorithm";
public static final String ALIAS = "alias";
+ public static final String ALLOCATED = "allocated";
public static final String ALLOCATED_DATE = "allocateddate";
public static final String ALLOCATED_ONLY = "allocatedonly";
public static final String ALLOCATED_TIME = "allocated";
+ public static final String ALLOWED_ROLE_TYPES = "allowedroletypes";
public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm";
public static final String ANNOTATION = "annotation";
public static final String API_KEY = "apikey";
@@ -59,6 +62,7 @@ public class ApiConstants {
public static final String BACKUP_STORAGE_AVAILABLE = "backupstorageavailable";
public static final String BACKUP_STORAGE_LIMIT = "backupstoragelimit";
public static final String BACKUP_STORAGE_TOTAL = "backupstoragetotal";
+ public static final String BACKUP_VM_OFFERING_REMOVED = "vmbackupofferingremoved";
public static final String BACKUP_TOTAL = "backuptotal";
public static final String BASE64_IMAGE = "base64image";
public static final String BGP_PEERS = "bgppeers";
@@ -68,6 +72,7 @@ public class ApiConstants {
public static final String BOOTABLE = "bootable";
public static final String BIND_DN = "binddn";
public static final String BIND_PASSWORD = "bindpass";
+ public static final String BUS_ADDRESS = "busaddress";
public static final String BYTES_READ_RATE = "bytesreadrate";
public static final String BYTES_READ_RATE_MAX = "bytesreadratemax";
public static final String BYTES_READ_RATE_MAX_LENGTH = "bytesreadratemaxlength";
@@ -90,9 +95,13 @@ public class ApiConstants {
public static final String CONVERT_INSTANCE_HOST_ID = "convertinstancehostid";
public static final String CONVERT_INSTANCE_STORAGE_POOL_ID = "convertinstancepoolid";
public static final String ENABLED_REVOCATION_CHECK = "enabledrevocationcheck";
+ public static final String CLIENT_ADDRESS = "clientaddress";
+ public static final String COMBINED_CAPACITY_ORDERING = "COMBINED";
public static final String CONTROLLER = "controller";
public static final String CONTROLLER_UNIT = "controllerunit";
+ public static final String CONSOLE_ENDPOINT_CREATOR_ADDRESS = "consoleendpointcreatoraddress";
public static final String COPY_IMAGE_TAGS = "copyimagetags";
+ public static final String CPU_OVERCOMMIT_RATIO = "cpuOvercommitRatio";
public static final String CSR = "csr";
public static final String PRIVATE_KEY = "privatekey";
public static final String DATASTORE_HOST = "datastorehost";
@@ -119,7 +128,12 @@ public class ApiConstants {
public static final String CN = "cn";
public static final String COMMAND = "command";
public static final String CMD_EVENT_TYPE = "cmdeventtype";
+ public static final String CNI_CONFIG = "cniconfig";
+ public static final String CNI_CONFIG_ID = "cniconfigurationid";
+ public static final String CNI_CONFIG_DETAILS = "cniconfigdetails";
+ public static final String CNI_CONFIG_NAME = "cniconfigname";
public static final String COMPONENT = "component";
+ public static final String CPU = "CPU";
public static final String CPU_CORE_PER_SOCKET = "cpucorepersocket";
public static final String CPU_NUMBER = "cpunumber";
public static final String CPU_SPEED = "cpuspeed";
@@ -133,6 +147,7 @@ public class ApiConstants {
public static final String CUSTOMIZED = "customized";
public static final String CUSTOMIZED_IOPS = "customizediops";
public static final String CUSTOM_ID = "customid";
+ public static final String CUSTOM_ACTION_ID = "customactionid";
public static final String CUSTOM_JOB_ID = "customjobid";
public static final String CURRENT_START_IP = "currentstartip";
public static final String CURRENT_END_IP = "currentendip";
@@ -140,10 +155,12 @@ public class ApiConstants {
public static final String ENCRYPT_FORMAT = "encryptformat";
public static final String ENCRYPT_ROOT = "encryptroot";
public static final String ENCRYPTION_SUPPORTED = "encryptionsupported";
+ public static final String ETCD_IPS = "etcdips";
public static final String MIN_IOPS = "miniops";
public static final String MAX_IOPS = "maxiops";
public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve";
public static final String DATACENTER_NAME = "datacentername";
+ public static final String DATADISKS_DETAILS = "datadisksdetails";
public static final String DATADISK_OFFERING_LIST = "datadiskofferinglist";
public static final String DEFAULT_VALUE = "defaultvalue";
public static final String DELETE_PROTECTION = "deleteprotection";
@@ -152,10 +169,13 @@ public class ApiConstants {
public static final String DESTINATION_ZONE_ID = "destzoneid";
public static final String DETAILS = "details";
public static final String DEVICE_ID = "deviceid";
+ public static final String DEVICE_IDS = "deviceids";
+ public static final String DEVICE_NAME = "devicename";
public static final String DIRECT_DOWNLOAD = "directdownload";
public static final String DISK = "disk";
public static final String DISK_OFFERING_ID = "diskofferingid";
public static final String NEW_DISK_OFFERING_ID = "newdiskofferingid";
+ public static final String ORCHESTRATOR_REQUIRES_PREPARE_VM = "orchestratorrequirespreparevm";
public static final String OVERRIDE_DISK_OFFERING_ID = "overridediskofferingid";
public static final String DISK_KBS_READ = "diskkbsread";
public static final String DISK_KBS_WRITE = "diskkbswrite";
@@ -197,6 +217,7 @@ public class ApiConstants {
public static final String END_IPV6 = "endipv6";
public static final String END_PORT = "endport";
public static final String ENTRY_TIME = "entrytime";
+ public static final String ERROR_MESSAGE = "errormessage";
public static final String EVENT_ID = "eventid";
public static final String EVENT_TYPE = "eventtype";
public static final String EXPIRES = "expires";
@@ -207,6 +228,12 @@ public class ApiConstants {
public static final String EXTRA_DHCP_OPTION_VALUE = "extradhcpvalue";
public static final String EXTERNAL = "external";
public static final String EXTERNAL_UUID = "externaluuid";
+ public static final String EXTERNAL_DETAILS = "externaldetails";
+ public static final String PARAMETERS = "parameters";
+ public static final String EXTENSION = "extension";
+ public static final String EXTENSION_ID = "extensionid";
+ public static final String EXTENSION_NAME = "extensionname";
+ public static final String EXTENSIONS_PATH = "extensionspath";
public static final String FENCE = "fence";
public static final String FETCH_LATEST = "fetchlatest";
public static final String FILESYSTEM = "filesystem";
@@ -215,9 +242,11 @@ public class ApiConstants {
public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage";
public static final String FORCE_DELETE_HOST = "forcedeletehost";
public static final String FORCE_MS_TO_IMPORT_VM_FILES = "forcemstoimportvmfiles";
+ public static final String FORCE_UPDATE_OS_TYPE = "forceupdateostype";
public static final String FORMAT = "format";
public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork";
public static final String FOR_SYSTEM_VMS = "forsystemvms";
+ public static final String FOR_PROVIDER = "forprovider";
public static final String FULL_PATH = "fullpath";
public static final String GATEWAY = "gateway";
public static final String IP6_GATEWAY = "ip6gateway";
@@ -262,6 +291,7 @@ public class ApiConstants {
public static final String PREVIOUS_OWNER_ID = "previousownerid";
public static final String PREVIOUS_OWNER_NAME = "previousownername";
public static final String NEXT_ACL_RULE_ID = "nextaclruleid";
+ public static final String NEXT_HOP = "nexthop";
public static final String MOVE_ACL_CONSISTENCY_HASH = "aclconsistencyhash";
public static final String IMAGE_PATH = "imagepath";
public static final String INSTANCE_CONVERSION_SUPPORTED = "instanceconversionsupported";
@@ -269,7 +299,10 @@ public class ApiConstants {
public static final String INTERNAL_DNS2 = "internaldns2";
public static final String INTERNET_PROTOCOL = "internetprotocol";
public static final String INTERVAL_TYPE = "intervaltype";
- public static final String LOCATION_TYPE = "locationtype";
+ public static final String INSTANCE_LEASE_DURATION = "leaseduration";
+ public static final String INSTANCE_LEASE_ENABLED = "instanceleaseenabled";
+ public static final String INSTANCE_LEASE_EXPIRY_ACTION = "leaseexpiryaction";
+ public static final String INSTANCE_LEASE_EXPIRY_DATE= "leaseexpirydate";
public static final String IOPS_READ_RATE = "iopsreadrate";
public static final String IOPS_READ_RATE_MAX = "iopsreadratemax";
public static final String IOPS_READ_RATE_MAX_LENGTH = "iopsreadratemaxlength";
@@ -279,6 +312,7 @@ public class ApiConstants {
public static final String IP_ADDRESS = "ipaddress";
public static final String IP_ADDRESSES = "ipaddresses";
public static final String IP6_ADDRESS = "ip6address";
+ public static final String IP6_ADDRESSES = "ip6addresses";
public static final String IP_ADDRESS_ID = "ipaddressid";
public static final String IS_2FA_ENABLED = "is2faenabled";
public static final String IS_2FA_VERIFIED = "is2faverified";
@@ -296,6 +330,7 @@ public class ApiConstants {
public static final String IS_EXTRACTABLE = "isextractable";
public static final String IS_FEATURED = "isfeatured";
public static final String IS_IMPLICIT = "isimplicit";
+ public static final String IS_ISO = "isiso";
public static final String IS_PORTABLE = "isportable";
public static final String IS_PUBLIC = "ispublic";
public static final String IS_PERSISTENT = "ispersistent";
@@ -317,27 +352,36 @@ public class ApiConstants {
public static final String LAST_BOOT = "lastboottime";
public static final String LAST_SERVER_START = "lastserverstart";
public static final String LAST_SERVER_STOP = "lastserverstop";
+ public static final String LEASED = "leased";
public static final String LEVEL = "level";
public static final String LENGTH = "length";
public static final String LIMIT = "limit";
public static final String LIMIT_CPU_USE = "limitcpuuse";
public static final String LIST_HOSTS = "listhosts";
+ public static final String LOCATION_TYPE = "locationtype";
public static final String LOCK = "lock";
public static final String LUN = "lun";
public static final String LBID = "lbruleid";
public static final String LB_PROVIDER = "lbprovider";
public static final String MAC_ADDRESS = "macaddress";
+ public static final String MAC_ADDRESSES = "macaddresses";
+ public static final String MANUAL_UPGRADE = "manualupgrade";
public static final String MAX = "max";
public static final String MAX_SNAPS = "maxsnaps";
public static final String MAX_BACKUPS = "maxbackups";
public static final String MAX_CPU_NUMBER = "maxcpunumber";
public static final String MAX_MEMORY = "maxmemory";
+ public static final String MEMORY_OVERCOMMIT_RATIO = "memoryOvercommitRatio";
+ public static final String MESSAGE = "message";
public static final String MIN_CPU_NUMBER = "mincpunumber";
public static final String MIN_MEMORY = "minmemory";
public static final String MIGRATION_TYPE = "migrationtype";
+ public static final String MIGRATION_JOB_ID = "migrationjobid";
+ public static final String MIGRATION_JOB_STATUS = "migrationjobstatus";
public static final String MIGRATIONS = "migrations";
public static final String MEMORY = "memory";
public static final String MODE = "mode";
+ public static final String MOUNT_CKS_ISO_ON_VR = "mountcksisoonvr";
public static final String MULTI_ARCH = "ismultiarch";
public static final String NSX_MODE = "nsxmode";
public static final String NETWORK_MODE = "networkmode";
@@ -348,12 +392,15 @@ public class ApiConstants {
public static final String NETMASK = "netmask";
public static final String NEW_NAME = "newname";
public static final String NIC = "nic";
+ public static final String NICS = "nics";
public static final String NIC_NETWORK_LIST = "nicnetworklist";
public static final String NIC_IP_ADDRESS_LIST = "nicipaddresslist";
public static final String NIC_MULTIQUEUE_NUMBER = "nicmultiqueuenumber";
public static final String NIC_PACKED_VIRTQUEUES_ENABLED = "nicpackedvirtqueuesenabled";
public static final String NEW_START_IP = "newstartip";
public static final String NEW_END_IP = "newendip";
+ public static final String KUBERNETES_NODE_VERSION = "kubernetesnodeversion";
+ public static final String NUMA_NODE = "numanode";
public static final String NUM_RETRIES = "numretries";
public static final String OFFER_HA = "offerha";
public static final String OS_DISTRIBUTION = "osdistribution";
@@ -370,6 +417,13 @@ public class ApiConstants {
public static final String OS_TYPE_ID = "ostypeid";
public static final String OS_DISPLAY_NAME = "osdisplayname";
public static final String OS_NAME_FOR_HYPERVISOR = "osnameforhypervisor";
+ public static final String GPU_CARD_ID = "gpucardid";
+ public static final String GPU_CARD_NAME = "gpucardname";
+ public static final String GPU_COUNT = "gpucount";
+ public static final String GPU_DISPLAY = "gpudisplay";
+ public static final String GPU_DEVICE_TYPE = "gpudevicetype";
+ public static final String GPU_ENABLED = "gpuenabled";
+ public static final String MAX_VGPU_PER_PHYSICAL_GPU = "maxvgpuperphysicalgpu";
public static final String GUEST_OS_LIST = "guestoslist";
public static final String GUEST_OS_COUNT = "guestoscount";
public static final String OS_MAPPING_CHECK_ENABLED = "osmappingcheckenabled";
@@ -381,14 +435,17 @@ public class ApiConstants {
public static final String PARENT = "parent";
public static final String PARENT_ID = "parentid";
public static final String PARENT_DOMAIN_ID = "parentdomainid";
+ public static final String PARENT_GPU_DEVICE_ID = "parentgpudeviceid";
public static final String PARENT_SUBNET = "parentsubnet";
public static final String PARENT_TEMPLATE_ID = "parenttemplateid";
public static final String PASSWORD = "password";
+ public static final String PCI_ROOT = "pciroot";
public static final String CURRENT_PASSWORD = "currentpassword";
public static final String SHOULD_UPDATE_PASSWORD = "update_passwd_on_host";
public static final String PASSWORD_ENABLED = "passwordenabled";
public static final String SSHKEY_ENABLED = "sshkeyenabled";
public static final String PATH = "path";
+ public static final String PATH_READY = "pathready";
public static final String PAYLOAD = "payload";
public static final String PAYLOAD_URL = "payloadurl";
public static final String PEERS = "peers";
@@ -411,6 +468,8 @@ public class ApiConstants {
public static final String POST_URL = "postURL";
public static final String POWER_STATE = "powerstate";
public static final String PRECEDENCE = "precedence";
+ public static final String PREPARE_VM = "preparevm";
+ public static final String PRESERVE_IP = "preserveip";
public static final String PRIVATE_INTERFACE = "privateinterface";
public static final String PRIVATE_IP = "privateip";
public static final String PRIVATE_PORT = "privateport";
@@ -427,11 +486,14 @@ public class ApiConstants {
public static final String PUBLIC_END_PORT = "publicendport";
public static final String PUBLIC_ZONE = "publiczone";
public static final String PURGE_RESOURCES = "purgeresources";
+ public static final String RAM = "RAM";
+ public static final String REBALANCE = "rebalance";
public static final String RECEIVED_BYTES = "receivedbytes";
public static final String RECONNECT = "reconnect";
public static final String RECOVER = "recover";
public static final String REPAIR = "repair";
public static final String REQUIRES_HVM = "requireshvm";
+ public static final String RESOURCES = "resources";
public static final String RESOURCE_COUNT = "resourcecount";
public static final String RESOURCE_NAME = "resourcename";
public static final String RESOURCE_TYPE = "resourcetype";
@@ -443,6 +505,7 @@ public class ApiConstants {
public static final String REGISTERED = "registered";
public static final String QUALIFIERS = "qualifiers";
public static final String QUERY_FILTER = "queryfilter";
+ public static final String QUIESCE_VM = "quiescevm";
public static final String SCHEDULE = "schedule";
public static final String SCHEDULE_ID = "scheduleid";
public static final String SCOPE = "scope";
@@ -456,7 +519,9 @@ public class ApiConstants {
public static final String SENT = "sent";
public static final String SENT_BYTES = "sentbytes";
public static final String SERIAL = "serial";
+ public static final String SERVICE_IP = "serviceip";
public static final String SERVICE_OFFERING_ID = "serviceofferingid";
+ public static final String SERVICE_OFFERING_NAME = "serviceofferingname";
public static final String SESSIONKEY = "sessionkey";
public static final String SHOW_CAPACITIES = "showcapacities";
public static final String SHOW_REMOVED = "showremoved";
@@ -466,6 +531,7 @@ public class ApiConstants {
public static final String SIGNATURE = "signature";
public static final String SIGNATURE_VERSION = "signatureversion";
public static final String SINCE = "since";
+ public static final String SITE_NAME = "sitename";
public static final String SIZE = "size";
public static final String SIZEGB = "sizegb";
public static final String SNAPSHOT = "snapshot";
@@ -473,6 +539,9 @@ public class ApiConstants {
public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid";
public static final String SNAPSHOT_TYPE = "snapshottype";
public static final String SNAPSHOT_QUIESCEVM = "quiescevm";
+
+ public static final String USE_STORAGE_REPLICATION = "usestoragereplication";
+
public static final String SOURCE_CIDR_LIST = "sourcecidrlist";
public static final String SOURCE_ZONE_ID = "sourcezoneid";
public static final String SSL_VERIFICATION = "sslverification";
@@ -485,19 +554,24 @@ public class ApiConstants {
public static final String STATE = "state";
public static final String STATS = "stats";
public static final String STATUS = "status";
+ public static final String STORAGE_TYPE = "storagetype";
+ public static final String STORAGE_POLICY = "storagepolicy";
+ public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled";
public static final String STORAGE_CAPABILITIES = "storagecapabilities";
public static final String STORAGE_CUSTOM_STATS = "storagecustomstats";
- public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled";
- public static final String STORAGE_POLICY = "storagepolicy";
- public static final String STORAGE_POOL = "storagepool";
- public static final String STORAGE_TYPE = "storagetype";
public static final String SUBNET = "subnet";
public static final String OWNER = "owner";
public static final String SWAP_OWNER = "swapowner";
public static final String SYSTEM_VM_TYPE = "systemvmtype";
public static final String TAGS = "tags";
public static final String STORAGE_TAGS = "storagetags";
+ public static final String STORAGE_ACCESS_GROUPS = "storageaccessgroups";
+ public static final String STORAGE_ACCESS_GROUP = "storageaccessgroup";
+ public static final String CLUSTER_STORAGE_ACCESS_GROUPS = "clusterstorageaccessgroups";
+ public static final String POD_STORAGE_ACCESS_GROUPS = "podstorageaccessgroups";
+ public static final String ZONE_STORAGE_ACCESS_GROUPS = "zonestorageaccessgroups";
public static final String SUCCESS = "success";
+ public static final String SUCCESS_MESSAGE = "successmessage";
public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine";
public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot";
public static final String TARGET_IQN = "targetiqn";
@@ -510,6 +584,7 @@ public class ApiConstants {
public static final String TIMEOUT = "timeout";
public static final String TIMEZONE = "timezone";
public static final String TIMEZONEOFFSET = "timezoneoffset";
+ public static final String TENANT_NAME = "tenantname";
public static final String TOTAL = "total";
public static final String TOTAL_SUBNETS = "totalsubnets";
public static final String TYPE = "type";
@@ -517,6 +592,7 @@ public class ApiConstants {
public static final String TRUST_STORE_PASSWORD = "truststorepass";
public static final String URL = "url";
public static final String USAGE_INTERFACE = "usageinterface";
+ public static final String USED = "used";
public static final String USED_SUBNETS = "usedsubnets";
public static final String USED_IOPS = "usediops";
public static final String USER_DATA = "userdata";
@@ -536,8 +612,16 @@ public class ApiConstants {
public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist";
public static final String USER_SECRET_KEY = "usersecretkey";
public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork";
+ public static final String USE_VIRTUAL_ROUTER_IP_RESOLVER = "userouteripresolver";
public static final String UPDATE_IN_SEQUENCE = "updateinsequence";
+ public static final String VALIDATION_FORMAT = "validationformat";
public static final String VALUE = "value";
+ public static final String VALUE_OPTIONS = "valueoptions";
+ public static final String VENDOR_ID = "vendorid";
+ public static final String VENDOR_NAME = "vendorname";
+ public static final String VGPU_PROFILE_ID = "vgpuprofileid";
+ public static final String VGPU_PROFILE_NAME = "vgpuprofilename";
+ public static final String VIRTUAL_MACHINE = "virtualmachine";
public static final String VIRTUAL_MACHINE_ID = "virtualmachineid";
public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids";
public static final String VIRTUAL_MACHINE_NAME = "virtualmachinename";
@@ -552,6 +636,12 @@ public class ApiConstants {
public static final String VLAN = "vlan";
public static final String VLAN_RANGE = "vlanrange";
+ public static final String WORKER_SERVICE_OFFERING_ID = "workerofferingid";
+ public static final String WORKER_SERVICE_OFFERING_NAME = "workerofferingname";
+ public static final String CONTROL_SERVICE_OFFERING_ID = "controlofferingid";
+ public static final String CONTROL_SERVICE_OFFERING_NAME = "controlofferingname";
+ public static final String ETCD_SERVICE_OFFERING_ID = "etcdofferingid";
+ public static final String ETCD_SERVICE_OFFERING_NAME = "etcdofferingname";
public static final String REMOVE_VLAN = "removevlan";
public static final String VLAN_ID = "vlanid";
public static final String ISOLATED_PVLAN = "isolatedpvlan";
@@ -561,8 +651,10 @@ public class ApiConstants {
public static final String IS_DEDICATED = "isdedicated";
public static final String TAKEN = "taken";
public static final String VM_AVAILABLE = "vmavailable";
+ public static final String VM_DETAILS = "vmdetails";
public static final String VM_LIMIT = "vmlimit";
public static final String VM_TOTAL = "vmtotal";
+ public static final String VM_SETTINGS = "vmsettings";
public static final String VM_TYPE = "vmtype";
public static final String VNET = "vnet";
public static final String IS_VOLATILE = "isvolatile";
@@ -630,7 +722,7 @@ public class ApiConstants {
public static final String NETWORK_DEVICE_PARAMETER_LIST = "networkdeviceparameterlist";
public static final String ZONE_TOKEN = "zonetoken";
public static final String DHCP_PROVIDER = "dhcpprovider";
- public static final String RESULT = "success";
+ public static final String RESULT = "result";
public static final String RESUME = "resume";
public static final String LUN_ID = "lunId";
public static final String IQN = "iqn";
@@ -744,6 +836,7 @@ public class ApiConstants {
public static final String LIST_ALL = "listall";
public static final String LIST_ONLY_REMOVED = "listonlyremoved";
public static final String LIST_SYSTEM_VMS = "listsystemvms";
+ public static final String LIST_VM_DETAILS = "listvmdetails";
public static final String IP_RANGES = "ipranges";
public static final String IPV4_ROUTING = "ip4routing";
public static final String IPV4_ROUTES = "ip4routes";
@@ -879,6 +972,8 @@ public class ApiConstants {
public static final String NETWORK = "network";
public static final String VPC_ID = "vpcid";
public static final String VPC_NAME = "vpcname";
+ public static final String VPC_GATEWAY_ID = "vpcgatewayid";
+ public static final String VPC_GATEWAY_IP = "vpcgatewayip";
public static final String GATEWAY_ID = "gatewayid";
public static final String CAN_USE_FOR_DEPLOY = "canusefordeploy";
public static final String RESOURCE_IDS = "resourceids";
@@ -902,6 +997,7 @@ public class ApiConstants {
public static final String SPLIT_CONNECTIONS = "splitconnections";
public static final String FOR_VPC = "forvpc";
public static final String FOR_NSX = "fornsx";
+ public static final String FOR_CKS = "forcks";
public static final String NSX_SUPPORT_LB = "nsxsupportlb";
public static final String NSX_SUPPORTS_INTERNAL_LB = "nsxsupportsinternallb";
public static final String FOR_TUNGSTEN = "fortungsten";
@@ -1021,6 +1117,7 @@ public class ApiConstants {
public static final String RESOURCE_DETAILS = "resourcedetails";
public static final String RESOURCE_ICON = "icon";
+ public static final String RESOURCE_MAP = "resourcemap";
public static final String EXPUNGE = "expunge";
public static final String FOR_DISPLAY = "fordisplay";
public static final String PASSIVE = "passive";
@@ -1052,10 +1149,12 @@ public class ApiConstants {
public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans";
public static final String METADATA = "metadata";
public static final String PHYSICAL_SIZE = "physicalsize";
+ public static final String CHAIN_SIZE = "chainsize";
public static final String OVM3_POOL = "ovm3pool";
public static final String OVM3_CLUSTER = "ovm3cluster";
public static final String OVM3_VIP = "ovm3vip";
public static final String CLEAN_UP_DETAILS = "cleanupdetails";
+ public static final String CLEAN_UP_PARAMETERS = "cleanupparameters";
public static final String VIRTUAL_SIZE = "virtualsize";
public static final String NETSCALER_CONTROLCENTER_ID = "netscalercontrolcenterid";
public static final String NETSCALER_SERVICEPACKAGE_ID = "netscalerservicepackageid";
@@ -1063,6 +1162,7 @@ public class ApiConstants {
public static final String ZONE_ID_LIST = "zoneids";
public static final String DESTINATION_ZONE_ID_LIST = "destzoneids";
+ public static final String STORAGE_ID_LIST = "storageids";
public static final String ADMIN = "admin";
public static final String CHECKSUM_PARAMETER_PREFIX_DESCRIPTION = "The parameter containing the checksum will be considered a MD5sum if it is not prefixed\n"
+ " and just a plain ascii/utf8 representation of a hexadecimal string. If it is required to\n"
@@ -1110,6 +1210,10 @@ public class ApiConstants {
public static final String MASTER_NODES = "masternodes";
public static final String NODE_IDS = "nodeids";
public static final String CONTROL_NODES = "controlnodes";
+ public static final String ETCD_NODES = "etcdnodes";
+ public static final String EXTERNAL_NODES = "externalnodes";
+ public static final String IS_EXTERNAL_NODE = "isexternalnode";
+ public static final String IS_ETCD_NODE = "isetcdnode";
public static final String MIN_SEMANTIC_VERSION = "minimumsemanticversion";
public static final String MIN_KUBERNETES_VERSION_ID = "minimumkubernetesversionid";
public static final String NODE_ROOT_DISK_SIZE = "noderootdisksize";
@@ -1118,6 +1222,8 @@ public class ApiConstants {
public static final String AUTOSCALING_ENABLED = "autoscalingenabled";
public static final String MIN_SIZE = "minsize";
public static final String MAX_SIZE = "maxsize";
+ public static final String NODE_TYPE_OFFERING_MAP = "nodeofferings";
+ public static final String NODE_TYPE_TEMPLATE_MAP = "nodetemplates";
public static final String BOOT_TYPE = "boottype";
public static final String BOOT_MODE = "bootmode";
@@ -1150,6 +1256,7 @@ public class ApiConstants {
public static final String PENDING_JOBS_COUNT = "pendingjobscount";
public static final String AGENTS_COUNT = "agentscount";
public static final String AGENTS = "agents";
+ public static final String LAST_AGENTS = "lastagents";
public static final String PUBLIC_MTU = "publicmtu";
public static final String PRIVATE_MTU = "privatemtu";
@@ -1166,6 +1273,10 @@ public class ApiConstants {
public static final String SOURCE_NAT_IP_ID = "sourcenatipaddressid";
public static final String HAS_RULES = "hasrules";
public static final String NSX_DETAIL_KEY = "forNsx";
+ public static final String NETRIS_DETAIL_KEY = "forNetris";
+ public static final String NETRIS_TAG = "netristag";
+ public static final String NETRIS_VXLAN_ID = "netrisvxlanid";
+ public static final String NETRIS_URL = "netrisurl";
public static final String DISK_PATH = "diskpath";
public static final String IMPORT_SOURCE = "importsource";
public static final String TEMP_PATH = "temppath";
@@ -1219,8 +1330,28 @@ public class ApiConstants {
"however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " +
"added, it will be interpreted as \"23:59:59\"). If the recommended format is not used, the date will be considered in the server timezone.";
+ public static final String PARAMETER_DESCRIPTION_MAX_BACKUPS = "The maximum number of backups to keep for a VM. " +
+ "If \"0\", no retention policy will be applied and, thus, no backups from the schedule will be automatically deleted. " +
+ "This parameter is only supported for the Dummy, NAS and EMC Networker backup provider.";
+
public static final String VMWARE_DC = "vmwaredc";
+ public static final String CSS = "css";
+
+ public static final String JSON_CONFIGURATION = "jsonconfiguration";
+
+ public static final String COMMON_NAMES = "commonnames";
+
+ public static final String COMMON_NAME = "commonname";
+
+ public static final String DOMAIN_IDS = "domainids";
+
+ public static final String SHOW_PUBLIC = "showpublic";
+
+ public static final String LIST_ONLY_DEFAULT_THEME = "listonlydefaulttheme";
+
+ public static final String RECURSIVE_DOMAINS = "recursivedomains";
+
/**
* This enum specifies IO Drivers, each option controls specific policies on I/O.
* Qemu guests support "threads" and "native" options Since 0.8.8 ; "io_uring" is supported Since 6.3.0 (QEMU 5.0).
@@ -1273,6 +1404,10 @@ public class ApiConstants {
all, resource, min;
}
+ public enum ExtensionDetails {
+ all, resource, external, min;
+ }
+
public enum ApiKeyAccess {
DISABLED(false),
ENABLED(true),
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiErrorCode.java b/api/src/main/java/org/apache/cloudstack/api/ApiErrorCode.java
index d4fdeddc9a9..616c37484d8 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiErrorCode.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiErrorCode.java
@@ -22,6 +22,7 @@ package org.apache.cloudstack.api;
*/
public enum ApiErrorCode {
+ BAD_REQUEST(400),
UNAUTHORIZED(401),
UNAUTHORIZED2FA(511),
METHOD_NOT_ALLOWED(405),
@@ -30,6 +31,7 @@ public enum ApiErrorCode {
UNSUPPORTED_ACTION_ERROR(432),
API_LIMIT_EXCEED(429),
+ SERVICE_UNAVAILABLE(503),
INTERNAL_ERROR(530),
ACCOUNT_ERROR(531),
ACCOUNT_RESOURCE_LIMIT_ERROR(532),
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiServerService.java b/api/src/main/java/org/apache/cloudstack/api/ApiServerService.java
index cbbcdc3bda4..cb75939d6bc 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiServerService.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiServerService.java
@@ -48,4 +48,6 @@ public interface ApiServerService {
boolean forgotPassword(UserAccount userAccount, Domain domain);
boolean resetPassword(UserAccount userAccount, String token, String password);
+
+ boolean isPostRequestsAndTimestampsEnforced();
}
diff --git a/api/src/main/java/org/apache/cloudstack/api/BaseCmd.java b/api/src/main/java/org/apache/cloudstack/api/BaseCmd.java
index 457afdc8847..8f47d51b19d 100644
--- a/api/src/main/java/org/apache/cloudstack/api/BaseCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/BaseCmd.java
@@ -39,6 +39,7 @@ import org.apache.cloudstack.affinity.AffinityGroupService;
import org.apache.cloudstack.alert.AlertService;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.gpu.GpuService;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.network.lb.ApplicationLoadBalancerService;
import org.apache.cloudstack.network.lb.InternalLoadBalancerVMService;
@@ -94,6 +95,7 @@ import com.cloud.utils.ReflectUtil;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.UUIDManager;
import com.cloud.vm.UserVmService;
+import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.snapshot.VMSnapshotService;
public abstract class BaseCmd {
@@ -130,6 +132,8 @@ public abstract class BaseCmd {
@Inject
public UserVmService _userVmService;
@Inject
+ public GpuService gpuService;
+ @Inject
public ManagementService _mgr;
@Inject
public StorageService _storageService;
@@ -484,4 +488,14 @@ public abstract class BaseCmd {
}
return detailsMap;
}
+
+ public Map convertExternalDetailsToMap(Map externalDetails) {
+ Map customparameterMap = convertDetailsToMap(externalDetails);
+ Map details = new HashMap<>();
+ for (String key : customparameterMap.keySet()) {
+ String value = customparameterMap.get(key);
+ details.put(VmDetailConstants.EXTERNAL_DETAIL_PREFIX + key, value);
+ }
+ return details;
+ }
}
diff --git a/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java
index 9a8282df112..8489bf05ec7 100644
--- a/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java
@@ -51,6 +51,10 @@ public abstract class BaseUpdateTemplateOrIsoCmd extends BaseCmd {
description = "the ID of the OS type that best represents the OS of this image.")
private Long osTypeId;
+ @Parameter(name = ApiConstants.FORCE_UPDATE_OS_TYPE, type = CommandType.BOOLEAN, since = "4.21", description = "Force OS type update. Warning: Updating OS type will " +
+ "update the guest OS configuration for all the existing Instances deployed with this template/iso, which may affect their behavior.")
+ private Boolean forceUpdateOsType;
+
@Parameter(name = ApiConstants.FORMAT, type = CommandType.STRING, description = "the format for the image")
private String format;
@@ -112,6 +116,10 @@ public abstract class BaseUpdateTemplateOrIsoCmd extends BaseCmd {
return osTypeId;
}
+ public Boolean getForceUpdateOsType() {
+ return forceUpdateOsType;
+ }
+
public Boolean getPasswordEnabled() {
return passwordEnabled;
}
diff --git a/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java
index ea0d946ee41..8e92e877f5c 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java
@@ -22,27 +22,24 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import com.cloud.bgp.ASNumber;
-import com.cloud.bgp.ASNumberRange;
-
-import org.apache.cloudstack.storage.object.Bucket;
+import org.apache.cloudstack.api.response.ConsoleSessionResponse;
+import org.apache.cloudstack.consoleproxy.ConsoleSession;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
-import org.apache.cloudstack.api.response.AccountResponse;
-import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse;
import org.apache.cloudstack.api.response.ASNRangeResponse;
import org.apache.cloudstack.api.response.ASNumberResponse;
+import org.apache.cloudstack.api.response.AccountResponse;
+import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse;
import org.apache.cloudstack.api.response.AsyncJobResponse;
import org.apache.cloudstack.api.response.AutoScalePolicyResponse;
import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse;
import org.apache.cloudstack.api.response.AutoScaleVmProfileResponse;
import org.apache.cloudstack.api.response.BackupOfferingResponse;
import org.apache.cloudstack.api.response.BackupRepositoryResponse;
-import org.apache.cloudstack.api.response.BackupResponse;
import org.apache.cloudstack.api.response.BackupScheduleResponse;
import org.apache.cloudstack.api.response.BucketResponse;
import org.apache.cloudstack.api.response.CapacityResponse;
@@ -60,24 +57,25 @@ import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.DomainRouterResponse;
import org.apache.cloudstack.api.response.EventResponse;
import org.apache.cloudstack.api.response.ExtractResponse;
-import org.apache.cloudstack.api.response.SharedFSResponse;
import org.apache.cloudstack.api.response.FirewallResponse;
import org.apache.cloudstack.api.response.FirewallRuleResponse;
import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse;
+import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import org.apache.cloudstack.api.response.GuestOSResponse;
import org.apache.cloudstack.api.response.GuestOsMappingResponse;
import org.apache.cloudstack.api.response.GuestVlanRangeResponse;
import org.apache.cloudstack.api.response.GuestVlanResponse;
+import org.apache.cloudstack.api.response.GuiThemeResponse;
import org.apache.cloudstack.api.response.HostForMigrationResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse;
import org.apache.cloudstack.api.response.HypervisorGuestOsNamesResponse;
import org.apache.cloudstack.api.response.IPAddressResponse;
-import org.apache.cloudstack.api.response.IpQuarantineResponse;
import org.apache.cloudstack.api.response.ImageStoreResponse;
import org.apache.cloudstack.api.response.InstanceGroupResponse;
import org.apache.cloudstack.api.response.InternalLoadBalancerElementResponse;
import org.apache.cloudstack.api.response.IpForwardingRuleResponse;
+import org.apache.cloudstack.api.response.IpQuarantineResponse;
import org.apache.cloudstack.api.response.IsolationMethodResponse;
import org.apache.cloudstack.api.response.LBHealthCheckResponse;
import org.apache.cloudstack.api.response.LBStickinessResponse;
@@ -115,6 +113,7 @@ import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse;
import org.apache.cloudstack.api.response.SecurityGroupResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.ServiceResponse;
+import org.apache.cloudstack.api.response.SharedFSResponse;
import org.apache.cloudstack.api.response.Site2SiteCustomerGatewayResponse;
import org.apache.cloudstack.api.response.Site2SiteVpnConnectionResponse;
import org.apache.cloudstack.api.response.Site2SiteVpnGatewayResponse;
@@ -144,7 +143,6 @@ import org.apache.cloudstack.api.response.VpcOfferingResponse;
import org.apache.cloudstack.api.response.VpcResponse;
import org.apache.cloudstack.api.response.VpnUsersResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
-import org.apache.cloudstack.backup.Backup;
import org.apache.cloudstack.backup.BackupOffering;
import org.apache.cloudstack.backup.BackupRepository;
import org.apache.cloudstack.backup.BackupSchedule;
@@ -153,16 +151,21 @@ import org.apache.cloudstack.config.ConfigurationGroup;
import org.apache.cloudstack.direct.download.DirectDownloadCertificate;
import org.apache.cloudstack.direct.download.DirectDownloadCertificateHostMap;
import org.apache.cloudstack.direct.download.DirectDownloadManager;
+import org.apache.cloudstack.gui.theme.GuiThemeJoin;
import org.apache.cloudstack.management.ManagementServerHost;
import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule;
import org.apache.cloudstack.region.PortableIp;
import org.apache.cloudstack.region.PortableIpRange;
import org.apache.cloudstack.region.Region;
import org.apache.cloudstack.secstorage.heuristics.Heuristic;
-import org.apache.cloudstack.storage.sharedfs.SharedFS;
+import org.apache.cloudstack.storage.object.Bucket;
import org.apache.cloudstack.storage.object.ObjectStore;
+import org.apache.cloudstack.storage.sharedfs.SharedFS;
import org.apache.cloudstack.usage.Usage;
+import org.apache.cloudstack.vm.UnmanagedInstanceTO;
+import com.cloud.bgp.ASNumber;
+import com.cloud.bgp.ASNumberRange;
import com.cloud.capacity.Capacity;
import com.cloud.configuration.ResourceCount;
import com.cloud.configuration.ResourceLimit;
@@ -223,10 +226,11 @@ import com.cloud.projects.ProjectAccount;
import com.cloud.projects.ProjectInvitation;
import com.cloud.region.ha.GlobalLoadBalancerRule;
import com.cloud.resource.RollingMaintenanceManager;
-import com.cloud.server.ResourceTag;
import com.cloud.server.ResourceIcon;
+import com.cloud.server.ResourceTag;
import com.cloud.storage.GuestOS;
import com.cloud.storage.GuestOSHypervisor;
+import com.cloud.storage.GuestOsCategory;
import com.cloud.storage.ImageStore;
import com.cloud.storage.Snapshot;
import com.cloud.storage.StoragePool;
@@ -240,14 +244,13 @@ import com.cloud.user.User;
import com.cloud.user.UserAccount;
import com.cloud.user.UserData;
import com.cloud.uservm.UserVm;
-import com.cloud.utils.net.Ip;
import com.cloud.utils.Pair;
+import com.cloud.utils.net.Ip;
import com.cloud.vm.InstanceGroup;
import com.cloud.vm.Nic;
import com.cloud.vm.NicSecondaryIp;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.snapshot.VMSnapshot;
-import org.apache.cloudstack.vm.UnmanagedInstanceTO;
public interface ResponseGenerator {
UserResponse createUserResponse(UserAccount user);
@@ -310,6 +313,8 @@ public interface ResponseGenerator {
PodResponse createPodResponse(Pod pod, Boolean showCapacities);
+ PodResponse createMinimalPodResponse(Pod pod);
+
ZoneResponse createZoneResponse(ResponseView view, DataCenter dataCenter, Boolean showCapacities, Boolean showResourceIcon);
DataCenterGuestIpv6PrefixResponse createDataCenterGuestIpv6PrefixResponse(DataCenterGuestIpv6Prefix prefix);
@@ -324,6 +329,8 @@ public interface ResponseGenerator {
ClusterResponse createClusterResponse(Cluster cluster, Boolean showCapacities);
+ ClusterResponse createMinimalClusterResponse(Cluster cluster);
+
FirewallRuleResponse createPortForwardingRuleResponse(PortForwardingRule fwRule);
IpForwardingRuleResponse createIpForwardingRuleResponse(StaticNatRule fwRule);
@@ -481,6 +488,10 @@ public interface ResponseGenerator {
AutoScaleVmGroupResponse createAutoScaleVmGroupResponse(AutoScaleVmGroup vmGroup);
+ GuestOSCategoryResponse createGuestOSCategoryResponse(GuestOsCategory guestOsCategory);
+
+ GuestOSCategoryResponse createGuestOSCategoryResponse(GuestOsCategory guestOsCategory, boolean showIcon);
+
GuestOSResponse createGuestOSResponse(GuestOS os);
GuestOsMappingResponse createGuestOSMappingResponse(GuestOSHypervisor osHypervisor);
@@ -523,8 +534,6 @@ public interface ResponseGenerator {
UserDataResponse createUserDataResponse(UserData userData);
- BackupResponse createBackupResponse(Backup backup);
-
BackupScheduleResponse createBackupScheduleResponse(BackupSchedule backup);
BackupOfferingResponse createBackupOfferingResponse(BackupOffering policy);
@@ -568,4 +577,10 @@ public interface ResponseGenerator {
BackupRepositoryResponse createBackupRepositoryResponse(BackupRepository repository);
SharedFSResponse createSharedFSResponse(ResponseView view, SharedFS sharedFS);
+
+ void updateTemplateIsoResponsesForIcons(List responses, ResourceTag.ResourceObjectType type);
+
+ GuiThemeResponse createGuiThemeResponse(GuiThemeJoin guiThemeJoin);
+
+ ConsoleSessionResponse createConsoleSessionResponse(ConsoleSession consoleSession, ResponseView responseView);
}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/ListProjectRolesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/ListProjectRolesCmd.java
index e876dbc9b58..dedbb410ea5 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/ListProjectRolesCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/ListProjectRolesCmd.java
@@ -72,7 +72,7 @@ public class ListProjectRolesCmd extends BaseListCmd {
@Override
public void execute() {
- List projectRoles;
+ List projectRoles = new ArrayList<>();
if (getProjectId() != null && getProjectRoleId() != null) {
projectRoles = Collections.singletonList(projRoleService.findProjectRole(getProjectRoleId(), getProjectId()));
} else if (StringUtils.isNotBlank(getRoleName())) {
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java
index 69cb43ce40e..3aef11b92e9 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java
@@ -19,21 +19,22 @@ package org.apache.cloudstack.api.command.admin.cluster;
import java.util.ArrayList;
import java.util.List;
-
-import com.cloud.cpu.CPU;
-import org.apache.cloudstack.api.ApiCommandResourceType;
+import java.util.Map;
import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ClusterResponse;
+import org.apache.cloudstack.api.response.ExtensionResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
+import com.cloud.cpu.CPU;
import com.cloud.exception.DiscoveryException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.org.Cluster;
@@ -43,7 +44,6 @@ import com.cloud.user.Account;
requestHasSensitiveInfo = true, responseHasSensitiveInfo = false)
public class AddClusterCmd extends BaseCmd {
-
@Parameter(name = ApiConstants.CLUSTER_NAME, type = CommandType.STRING, required = true, description = "the cluster name")
private String clusterName;
@@ -65,7 +65,7 @@ public class AddClusterCmd extends BaseCmd {
@Parameter(name = ApiConstants.HYPERVISOR,
type = CommandType.STRING,
required = true,
- description = "hypervisor type of the cluster: XenServer,KVM,VMware,Hyperv,BareMetal,Simulator,Ovm3")
+ description = "hypervisor type of the cluster: XenServer,KVM,VMware,Hyperv,BareMetal,Simulator,Ovm3,External")
private String hypervisor;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
@@ -118,6 +118,26 @@ public class AddClusterCmd extends BaseCmd {
private String ovm3cluster;
@Parameter(name = ApiConstants.OVM3_VIP, type = CommandType.STRING, required = false, description = "Ovm3 vip to use for pool (and cluster)")
private String ovm3vip;
+
+ @Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS,
+ type = CommandType.LIST, collectionType = CommandType.STRING,
+ description = "comma separated list of storage access groups for the hosts in the cluster",
+ since = "4.21.0")
+ private List storageAccessGroups;
+
+
+ @Parameter(name = ApiConstants.EXTENSION_ID,
+ type = CommandType.UUID, entityType = ExtensionResponse.class,
+ description = "UUID of the extension",
+ since = "4.21.0")
+ private Long extensionId;
+
+ @Parameter(name = ApiConstants.EXTERNAL_DETAILS,
+ type = CommandType.MAP,
+ description = "Details in key/value pairs to be added to the extension-resource mapping. Use the format externaldetails[i].=. Example: externaldetails[0].endpoint.url=https://example.com",
+ since = "4.21.0")
+ protected Map externalDetails;
+
public String getOvm3Pool() {
return ovm3pool;
}
@@ -184,6 +204,10 @@ public class AddClusterCmd extends BaseCmd {
return hypervisor;
}
+ public Long getExtensionId() {
+ return extensionId;
+ }
+
public String getClusterType() {
return clusterType;
}
@@ -192,6 +216,10 @@ public class AddClusterCmd extends BaseCmd {
this.clusterType = type;
}
+ public List getStorageAccessGroups() {
+ return storageAccessGroups;
+ }
+
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
@@ -214,6 +242,10 @@ public class AddClusterCmd extends BaseCmd {
return CPU.CPUArch.fromType(arch);
}
+ public Map getExternalDetails() {
+ return convertDetailsToMap(externalDetails);
+ }
+
@Override
public void execute() {
try {
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java
index 67d0678410c..b38278e3946 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java
@@ -17,8 +17,11 @@
package org.apache.cloudstack.api.command.admin.cluster;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import javax.inject.Inject;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
@@ -28,7 +31,13 @@ import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.extension.Extension;
+import org.apache.cloudstack.extension.ExtensionHelper;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import com.cloud.cpu.CPU;
+import com.cloud.hypervisor.Hypervisor;
import com.cloud.org.Cluster;
import com.cloud.utils.Pair;
@@ -36,6 +45,8 @@ import com.cloud.utils.Pair;
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListClustersCmd extends BaseListCmd {
+ @Inject
+ ExtensionHelper extensionHelper;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
@@ -68,6 +79,16 @@ public class ListClustersCmd extends BaseListCmd {
@Parameter(name = ApiConstants.SHOW_CAPACITIES, type = CommandType.BOOLEAN, description = "flag to display the capacity of the clusters")
private Boolean showCapacities;
+ @Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
+ description = "CPU arch of the clusters",
+ since = "4.20.1")
+ private String arch;
+
+ @Parameter(name = ApiConstants.STORAGE_ACCESS_GROUP, type = CommandType.STRING,
+ description = "the name of the storage access group",
+ since = "4.21.0")
+ private String storageAccessGroup;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -112,25 +133,64 @@ public class ListClustersCmd extends BaseListCmd {
return showCapacities;
}
+ public CPU.CPUArch getArch() {
+ return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
+ }
+
+ public String getStorageAccessGroup() {
+ return storageAccessGroup;
+ }
+
+ public ListClustersCmd() {
+
+ }
+
+ public ListClustersCmd(String storageAccessGroup) {
+ this.storageAccessGroup = storageAccessGroup;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
+ protected void updateClustersExtensions(final List clusterResponses) {
+ if (CollectionUtils.isEmpty(clusterResponses)) {
+ return;
+ }
+ Map idExtensionMap = new HashMap<>();
+ for (ClusterResponse response : clusterResponses) {
+ if (!Hypervisor.HypervisorType.External.getHypervisorDisplayName().equals(response.getHypervisorType())) {
+ continue;
+ }
+ Long extensionId = extensionHelper.getExtensionIdForCluster(response.getInternalId());
+ if (extensionId == null) {
+ continue;
+ }
+ Extension extension = idExtensionMap.computeIfAbsent(extensionId, id -> extensionHelper.getExtension(id));
+ if (extension == null) {
+ continue;
+ }
+ response.setExtensionId(extension.getUuid());
+ response.setExtensionName(extension.getName());
+ }
+ }
+
protected Pair, Integer> getClusterResponses() {
Pair, Integer> result = _mgr.searchForClusters(this);
- List clusterResponses = new ArrayList();
+ List clusterResponses = new ArrayList<>();
for (Cluster cluster : result.first()) {
ClusterResponse clusterResponse = _responseGenerator.createClusterResponse(cluster, showCapacities);
clusterResponse.setObjectName("cluster");
clusterResponses.add(clusterResponse);
}
- return new Pair, Integer>(clusterResponses, result.second());
+ updateClustersExtensions(clusterResponses);
+ return new Pair<>(clusterResponses, result.second());
}
@Override
public void execute() {
Pair, Integer> clusterResponses = getClusterResponses();
- ListResponse response = new ListResponse();
+ ListResponse response = new ListResponse<>();
response.setResponses(clusterResponses.first(), clusterResponses.second());
response.setResponseName(getCommandName());
this.setResponseObject(response);
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java
index c4ee87380ed..c160cfd2e03 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java
@@ -16,6 +16,8 @@
// under the License.
package org.apache.cloudstack.api.command.admin.cluster;
+import java.util.Map;
+
import com.cloud.cpu.CPU;
import org.apache.cloudstack.api.ApiCommandResourceType;
@@ -60,6 +62,12 @@ public class UpdateClusterCmd extends BaseCmd {
since = "4.20")
private String arch;
+ @Parameter(name = ApiConstants.EXTERNAL_DETAILS,
+ type = CommandType.MAP,
+ description = "Details in key/value pairs to be added to the extension-resource mapping. Use the format externaldetails[i].=. Example: externaldetails[0].endpoint.url=https://example.com",
+ since = "4.21.0")
+ protected Map externalDetails;
+
public String getClusterName() {
return clusterName;
}
@@ -122,6 +130,10 @@ public class UpdateClusterCmd extends BaseCmd {
return CPU.CPUArch.fromType(arch);
}
+ public Map getExternalDetails() {
+ return convertDetailsToMap(externalDetails);
+ }
+
@Override
public void execute() {
Cluster cluster = _resourceService.getCluster(getId());
@@ -130,7 +142,7 @@ public class UpdateClusterCmd extends BaseCmd {
}
Cluster result = _resourceService.updateCluster(this);
if (result != null) {
- ClusterResponse clusterResponse = _responseGenerator.createClusterResponse(cluster, false);
+ ClusterResponse clusterResponse = _responseGenerator.createClusterResponse(result, false);
clusterResponse.setResponseName(getCommandName());
this.setResponseObject(clusterResponse);
} else {
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/CreateGpuCardCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/CreateGpuCardCmd.java
new file mode 100644
index 00000000000..2faad89bf67
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/CreateGpuCardCmd.java
@@ -0,0 +1,122 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.user.Account;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GpuCardResponse;
+import org.apache.cloudstack.gpu.GpuCard;
+
+
+@APICommand(name = "createGpuCard", description = "Creates a GPU card definition in the system",
+ responseObject = GpuCardResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.21.0")
+public class CreateGpuCardCmd extends BaseCmd {
+
+ /// //////////////////////////////////////////////////
+ /// ///////////// API parameters /////////////////////
+ /// //////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.DEVICE_ID, type = CommandType.STRING, required = true,
+ description = "the device ID of the GPU card")
+ private String deviceId;
+
+ @Parameter(name = ApiConstants.DEVICE_NAME, type = CommandType.STRING, required = true,
+ description = "the device name of the GPU card")
+ private String deviceName;
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true,
+ description = "the display name of the GPU card")
+ private String name;
+
+ @Parameter(name = ApiConstants.VENDOR_NAME, type = CommandType.STRING, required = true,
+ description = "the vendor name of the GPU card")
+ private String vendorName;
+
+ @Parameter(name = ApiConstants.VENDOR_ID, type = CommandType.STRING, required = true,
+ description = "the vendor ID of the GPU card")
+ private String vendorId;
+
+ // Optional parameters for the passthrough vGPU profile display properties
+ @Parameter(name = ApiConstants.VIDEORAM, type = CommandType.LONG,
+ description = "the video RAM size in MB for the passthrough vGPU profile")
+ private Long videoRam;
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public String getDeviceId() {
+ return deviceId;
+ }
+
+ public String getDeviceName() {
+ return deviceName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVendorName() {
+ return vendorName;
+ }
+
+ public String getVendorId() {
+ return vendorId;
+ }
+
+ public Long getVideoRam() {
+ return videoRam;
+ }
+
+ @Override
+ public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException,
+ ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
+ try {
+ GpuCard gpuCard = gpuService.createGpuCard(this);
+ if (gpuCard != null) {
+ GpuCardResponse response = new GpuCardResponse(gpuCard);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create GPU card");
+ }
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create GPU card: " + e.getMessage());
+ }
+ }
+
+ /// //////////////////////////////////////////////////
+ /// //////////// API Implementation///////////////////
+ /// //////////////////////////////////////////////////
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/CreateGpuDeviceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/CreateGpuDeviceCmd.java
new file mode 100644
index 00000000000..e6386082a44
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/CreateGpuDeviceCmd.java
@@ -0,0 +1,123 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GpuCardResponse;
+import org.apache.cloudstack.api.response.GpuDeviceResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.VgpuProfileResponse;
+import org.apache.cloudstack.gpu.GpuDevice;
+import org.apache.commons.lang3.EnumUtils;
+import org.apache.commons.lang3.StringUtils;
+
+
+@APICommand(name = "createGpuDevice", description = "Creates a GPU device manually on a host",
+ responseObject = GpuDeviceResponse.class, since = "4.21.0", requestHasSensitiveInfo = false,
+ responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
+public class CreateGpuDeviceCmd extends BaseCmd {
+
+ @Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, required = true,
+ description = "ID of the host where the GPU device is located")
+ private Long hostId;
+
+ @Parameter(name = ApiConstants.BUS_ADDRESS, type = CommandType.STRING, required = true,
+ description = "PCI bus address of the GPU device (e.g., 0000:01:00.0) or UUID for MDEV devices.")
+ private String busAddress;
+
+ @Parameter(name = ApiConstants.GPU_CARD_ID, type = CommandType.UUID, entityType = GpuCardResponse.class,
+ required = true, description = "ID of the GPU card type")
+ private Long gpuCardId;
+
+ @Parameter(name = ApiConstants.VGPU_PROFILE_ID, type = CommandType.UUID, entityType = VgpuProfileResponse.class,
+ required = true, description = "ID of the vGPU profile")
+ private Long vgpuProfileId;
+
+ @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING,
+ description = "Type of GPU device (PCI, MDEV, VGPUOnly). Defaults to PCI.")
+ private String type;
+
+ @Parameter(name = ApiConstants.PARENT_GPU_DEVICE_ID, type = CommandType.UUID, entityType = GpuDeviceResponse.class,
+ description = "ID of the parent GPU device (for virtual GPU devices)")
+ private Long parentGpuDeviceId;
+
+ @Parameter(name = ApiConstants.NUMA_NODE, type = CommandType.STRING,
+ description = "NUMA node of the GPU device (e.g., 0, 1, etc.). This is optional and can be used to "
+ + "specify the NUMA node for the GPU device which is used during allocation. Defaults to -1")
+ private String numaNode;
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ public String getBusAddress() {
+ return busAddress;
+ }
+
+ public Long getGpuCardId() {
+ return gpuCardId;
+ }
+
+ public Long getVgpuProfileId() {
+ return vgpuProfileId;
+ }
+
+ public GpuDevice.DeviceType getType() {
+ GpuDevice.DeviceType deviceType = GpuDevice.DeviceType.PCI;
+ if (StringUtils.isNotBlank(type)) {
+ deviceType = EnumUtils.getEnumIgnoreCase(GpuDevice.DeviceType.class, type);
+ if (deviceType == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid GPU device type: " + type);
+ }
+ }
+ return deviceType;
+ }
+
+ public Long getParentGpuDeviceId() {
+ return parentGpuDeviceId;
+ }
+
+ public String getNumaNode() {
+ if (StringUtils.isBlank(numaNode)) {
+ return "-1"; // Default value for NUMA node
+ }
+ return numaNode;
+ }
+
+ @Override
+ public void execute() {
+ try {
+ GpuDeviceResponse response = gpuService.createGpuDevice(this);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
+ }
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/CreateVgpuProfileCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/CreateVgpuProfileCmd.java
new file mode 100644
index 00000000000..3210773b6f4
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/CreateVgpuProfileCmd.java
@@ -0,0 +1,131 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GpuCardResponse;
+import org.apache.cloudstack.api.response.VgpuProfileResponse;
+
+
+@APICommand(name = "createVgpuProfile", description = "Creates a vGPU profile in the system",
+ responseObject = VgpuProfileResponse.class, requestHasSensitiveInfo = false,
+ responseHasSensitiveInfo = false, since = "4.21.0", authorized = {RoleType.Admin})
+public class CreateVgpuProfileCmd extends BaseCmd {
+
+ /// //////////////////////////////////////////////////
+ /// ///////////// API parameters /////////////////////
+ /// //////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true,
+ description = "the name of the vGPU profile")
+ private String name;
+
+ @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING,
+ description = "the description of the vGPU profile")
+ private String description;
+
+ @Parameter(name = ApiConstants.GPU_CARD_ID, type = CommandType.UUID, entityType = GpuCardResponse.class,
+ required = true, description = "the GPU card ID associated with this GPU device")
+ private Long cardId;
+
+ @Parameter(name = ApiConstants.MAX_VGPU_PER_PHYSICAL_GPU, type = CommandType.LONG,
+ description = "Max vGPU per physical GPU. This is used to calculate capacity.")
+ private Long maxVgpuPerPgpu;
+
+ @Parameter(name = ApiConstants.VIDEORAM, type = CommandType.LONG,
+ description = "the video RAM size in MB")
+ private Long videoRam;
+
+ @Parameter(name = ApiConstants.MAXHEADS, type = CommandType.LONG,
+ description = "the maximum number of display heads")
+ private Long maxHeads;
+
+ @Parameter(name = ApiConstants.MAXRESOLUTIONX, type = CommandType.LONG,
+ description = "the maximum X resolution")
+ private Long maxResolutionX;
+
+ @Parameter(name = ApiConstants.MAXRESOLUTIONY, type = CommandType.LONG,
+ description = "the maximum Y resolution")
+ private Long maxResolutionY;
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public Long getCardId() {
+ return cardId;
+ }
+
+ public Long getMaxVgpuPerPgpu() {
+ return maxVgpuPerPgpu;
+ }
+
+ public Long getVideoRam() {
+ return videoRam;
+ }
+
+ public Long getMaxHeads() {
+ return maxHeads;
+ }
+
+ public Long getMaxResolutionX() {
+ return maxResolutionX;
+ }
+
+ public Long getMaxResolutionY() {
+ return maxResolutionY;
+ }
+
+ @Override
+ public void execute() {
+ try {
+ VgpuProfileResponse response = gpuService.createVgpuProfile(this);
+ if (response != null) {
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create vGPU profile");
+ }
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
+ "Failed to create vGPU profile: " + e.getMessage());
+ }
+ }
+
+ /// //////////////////////////////////////////////////
+ /// //////////// API Implementation///////////////////
+ /// //////////////////////////////////////////////////
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DeleteGpuCardCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DeleteGpuCardCmd.java
new file mode 100644
index 00000000000..9a510ecdead
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DeleteGpuCardCmd.java
@@ -0,0 +1,75 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GpuCardResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+
+@APICommand(name = "deleteGpuCard", description = "Deletes a GPU card definition from the system",
+ responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.21.0", authorized = {RoleType.Admin})
+public class DeleteGpuCardCmd extends BaseCmd {
+
+ /// //////////////////////////////////////////////////
+ /// ///////////// API parameters /////////////////////
+ /// //////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GpuCardResponse.class, required = true,
+ description = "the ID of the GPU card")
+ private Long id;
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void execute() {
+ try {
+ boolean success = gpuService.deleteGpuCard(this);
+ if (success) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete GPU card");
+ }
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete GPU card: " + e.getMessage());
+ }
+ }
+
+ /// //////////////////////////////////////////////////
+ /// //////////// API Implementation///////////////////
+ /// //////////////////////////////////////////////////
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DeleteGpuDeviceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DeleteGpuDeviceCmd.java
new file mode 100644
index 00000000000..9224afc66ec
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DeleteGpuDeviceCmd.java
@@ -0,0 +1,78 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GpuDeviceResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+import java.util.List;
+
+@APICommand(name = "deleteGpuDevice", description = "Deletes a vGPU profile from the system",
+ responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.21.0", authorized = {RoleType.Admin})
+public class DeleteGpuDeviceCmd extends BaseCmd {
+
+ /// //////////////////////////////////////////////////
+ /// ///////////// API parameters /////////////////////
+ /// //////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.IDS, type = CommandType.LIST, collectionType = CommandType.UUID,
+ entityType = GpuDeviceResponse.class, required = true,
+ description = "comma separated list of IDs of the GPU device")
+ private List ids;
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public List getIds() {
+ return ids;
+ }
+
+ @Override
+ public void execute() {
+ try {
+ boolean success = gpuService.deleteGpuDevices(this);
+ if (success) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete vGPU profile");
+ }
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
+ "Failed to delete vGPU profile: " + e.getMessage());
+ }
+ }
+
+ /// //////////////////////////////////////////////////
+ /// //////////// API Implementation///////////////////
+ /// //////////////////////////////////////////////////
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DeleteVgpuProfileCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DeleteVgpuProfileCmd.java
new file mode 100644
index 00000000000..a09a04199f5
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DeleteVgpuProfileCmd.java
@@ -0,0 +1,76 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.api.response.VgpuProfileResponse;
+
+
+@APICommand(name = "deleteVgpuProfile", description = "Deletes a vGPU profile from the system",
+ responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.21.0", authorized = {RoleType.Admin})
+public class DeleteVgpuProfileCmd extends BaseCmd {
+
+ /// //////////////////////////////////////////////////
+ /// ///////////// API parameters /////////////////////
+ /// //////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VgpuProfileResponse.class, required = true,
+ description = "the ID of the vGPU profile")
+ private Long id;
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void execute() {
+ try {
+ boolean success = gpuService.deleteVgpuProfile(this);
+ if (success) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete vGPU profile");
+ }
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
+ "Failed to delete vGPU profile: " + e.getMessage());
+ }
+ }
+
+ /// //////////////////////////////////////////////////
+ /// //////////// API Implementation///////////////////
+ /// //////////////////////////////////////////////////
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DiscoverGpuDevicesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DiscoverGpuDevicesCmd.java
new file mode 100644
index 00000000000..2ac07a9fb3a
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/DiscoverGpuDevicesCmd.java
@@ -0,0 +1,63 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.GpuDeviceResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.context.CallContext;
+
+
+@APICommand(name = "discoverGpuDevices", description = "Discovers available GPU devices on a host",
+ responseObject = GpuDeviceResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.21.0", authorized = {RoleType.Admin})
+public class DiscoverGpuDevicesCmd extends BaseListCmd {
+
+ /// //////////////////////////////////////////////////
+ /// ///////////// API parameters /////////////////////
+ /// //////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = HostResponse.class, required = true,
+ description = "ID of the host")
+ private Long id;
+
+ /// //////////////////////////////////////////////////
+ /// //////////// API Implementation //////////////////
+ /// //////////////////////////////////////////////////
+
+ @Override
+ public void execute() {
+ CallContext.current().setEventDetails("Discovering GPU Devices on host id: " + getId());
+ ListResponse response = gpuService.discoverGpuDevices(this);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/ListGpuDevicesCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/ListGpuDevicesCmdByAdmin.java
new file mode 100644
index 00000000000..b3c57713fcd
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/ListGpuDevicesCmdByAdmin.java
@@ -0,0 +1,74 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ResponseObject;
+import org.apache.cloudstack.api.command.admin.AdminCmd;
+import org.apache.cloudstack.api.command.user.gpu.ListGpuDevicesCmd;
+import org.apache.cloudstack.api.response.GpuCardResponse;
+import org.apache.cloudstack.api.response.GpuDeviceResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.VgpuProfileResponse;
+
+
+@APICommand(name = "listGpuDevices", description = "Lists all available GPU devices",
+ responseView = ResponseObject.ResponseView.Full,
+ responseObject = GpuDeviceResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.21.0")
+public class ListGpuDevicesCmdByAdmin extends ListGpuDevicesCmd implements AdminCmd {
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GpuDeviceResponse.class,
+ description = "ID of the GPU device")
+ private Long id;
+
+ @Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class,
+ description = "the host ID where the GPU device is attached")
+ private Long hostId;
+
+ @Parameter(name = ApiConstants.GPU_CARD_ID, type = CommandType.UUID, entityType = GpuCardResponse.class,
+ description = "the GPU card ID associated with the GPU device")
+ private Long gpuCardId;
+
+ @Parameter(name = ApiConstants.VGPU_PROFILE_ID, type = CommandType.UUID, entityType = VgpuProfileResponse.class,
+ description = "the vGPU profile ID assigned to the GPU device")
+ private Long vgpuProfileId;
+
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ public Long getGpuCardId() {
+ return gpuCardId;
+ }
+
+ public Long getVgpuProfileId() {
+ return vgpuProfileId;
+ }
+
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/ManageGpuDeviceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/ManageGpuDeviceCmd.java
new file mode 100644
index 00000000000..5dfe6c3deee
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/ManageGpuDeviceCmd.java
@@ -0,0 +1,78 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GpuDeviceResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+import java.util.List;
+
+@APICommand(name = "manageGpuDevice", description = "Manages a GPU device", responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.21.0",
+ authorized = {RoleType.Admin})
+public class ManageGpuDeviceCmd extends BaseCmd {
+
+ /// //////////////////////////////////////////////////
+ /// ///////////// API parameters /////////////////////
+ /// //////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.IDS, type = CommandType.LIST, collectionType = CommandType.UUID,
+ entityType = GpuDeviceResponse.class, required = true,
+ description = "comma separated list of IDs of the GPU device")
+ private List ids;
+
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public List getIds() {
+ return ids;
+ }
+
+ @Override
+ public void execute() {
+ try {
+ if (gpuService.enableGpuDevice(this)) {
+ SuccessResponse response = new SuccessResponse();
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to enable GPU device");
+ }
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to enable GPU device: " + e.getMessage());
+ }
+ }
+
+ /// //////////////////////////////////////////////////
+ /// //////////// API Implementation///////////////////
+ /// //////////////////////////////////////////////////
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UnmanageGpuDeviceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UnmanageGpuDeviceCmd.java
new file mode 100644
index 00000000000..46de23ec44b
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UnmanageGpuDeviceCmd.java
@@ -0,0 +1,79 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GpuDeviceResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+import java.util.List;
+
+@APICommand(name = "unmanageGpuDevice", description = "Unmanage a GPU device", responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.21.0",
+ authorized = {RoleType.Admin})
+public class UnmanageGpuDeviceCmd extends BaseCmd {
+
+ /// //////////////////////////////////////////////////
+ /// ///////////// API parameters /////////////////////
+ /// //////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.IDS, type = CommandType.LIST, collectionType = CommandType.UUID,
+ entityType = GpuDeviceResponse.class, required = true,
+ description = "comma separated list of IDs of the GPU device")
+ private List ids;
+
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public List getIds() {
+ return ids;
+ }
+
+ @Override
+ public void execute() {
+ try {
+ if (gpuService.disableGpuDevice(this)) {
+ SuccessResponse response = new SuccessResponse();
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to disable GPU device");
+ }
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
+ "Failed to disable GPU device: " + e.getMessage());
+ }
+ }
+
+ /// //////////////////////////////////////////////////
+ /// //////////// API Implementation///////////////////
+ /// //////////////////////////////////////////////////
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UpdateGpuCardCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UpdateGpuCardCmd.java
new file mode 100644
index 00000000000..0061149a985
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UpdateGpuCardCmd.java
@@ -0,0 +1,99 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GpuCardResponse;
+import org.apache.cloudstack.gpu.GpuCard;
+
+
+@APICommand(name = "updateGpuCard", description = "Updates a GPU card definition in the system",
+ responseObject = GpuCardResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ since = "4.21.0", authorized = {RoleType.Admin})
+public class UpdateGpuCardCmd extends BaseCmd {
+
+ /// //////////////////////////////////////////////////
+ /// ///////////// API parameters /////////////////////
+ /// //////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GpuCardResponse.class, required = true,
+ description = "the ID of the GPU card")
+ private Long id;
+
+ @Parameter(name = ApiConstants.DEVICE_NAME, type = CommandType.STRING,
+ description = "the device name of the GPU card")
+ private String deviceName;
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the display name of the GPU card")
+ private String name;
+
+ @Parameter(name = ApiConstants.VENDOR_NAME, type = CommandType.STRING,
+ description = "the vendor name of the GPU card")
+ private String vendorName;
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getDeviceName() {
+ return deviceName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVendorName() {
+ return vendorName;
+ }
+
+ @Override
+ public void execute() {
+ try {
+ GpuCard gpuCard = gpuService.updateGpuCard(this);
+ if (gpuCard != null) {
+ GpuCardResponse response = new GpuCardResponse(gpuCard);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update GPU card");
+ }
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update GPU card: " + e.getMessage());
+ }
+ }
+
+ /// //////////////////////////////////////////////////
+ /// //////////// API Implementation///////////////////
+ /// //////////////////////////////////////////////////
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UpdateGpuDeviceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UpdateGpuDeviceCmd.java
new file mode 100644
index 00000000000..5ad6e6e1a6f
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UpdateGpuDeviceCmd.java
@@ -0,0 +1,109 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GpuCardResponse;
+import org.apache.cloudstack.api.response.GpuDeviceResponse;
+import org.apache.cloudstack.api.response.VgpuProfileResponse;
+import org.apache.cloudstack.gpu.GpuDevice;
+import org.apache.commons.lang3.EnumUtils;
+import org.apache.commons.lang3.StringUtils;
+
+
+@APICommand(name = "updateGpuDevice", description = "Updates an existing GPU device",
+ responseObject = GpuDeviceResponse.class, since = "4.21.0", requestHasSensitiveInfo = false,
+ responseHasSensitiveInfo = false, authorized = {RoleType.Admin})
+public class UpdateGpuDeviceCmd extends BaseCmd {
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GpuDeviceResponse.class, required = true,
+ description = "ID of the GPU device to update")
+ private Long id;
+
+ @Parameter(name = ApiConstants.GPU_CARD_ID, type = CommandType.UUID, entityType = GpuCardResponse.class,
+ description = "New GPU card ID")
+ private Long gpuCardId;
+
+ @Parameter(name = ApiConstants.VGPU_PROFILE_ID, type = CommandType.UUID, entityType = VgpuProfileResponse.class,
+ description = "New vGPU profile ID")
+ private Long vgpuProfileId;
+
+ @Parameter(name = "type", type = CommandType.STRING, description = "New type of GPU device (PCI, MDEV, VGPUOnly)")
+ private String type;
+
+ @Parameter(name = "parentgpudeviceid", type = CommandType.UUID, entityType = GpuDeviceResponse.class,
+ description = "New parent GPU device ID (for virtual GPU devices)")
+ private Long parentGpuDeviceId;
+
+ @Parameter(name = ApiConstants.NUMA_NODE, type = CommandType.STRING,
+ description = "New NUMA node of the GPU device")
+ private String numaNode;
+
+ public Long getId() {
+ return id;
+ }
+
+ public Long getGpuCardId() {
+ return gpuCardId;
+ }
+
+ public Long getVgpuProfileId() {
+ return vgpuProfileId;
+ }
+
+ public GpuDevice.DeviceType getType() {
+ GpuDevice.DeviceType deviceType = null;
+ if (StringUtils.isNotBlank(type)) {
+ deviceType = EnumUtils.getEnumIgnoreCase(GpuDevice.DeviceType.class, type);
+ if (deviceType == null) {
+ throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid GPU device type: " + type);
+ }
+ }
+ return deviceType;
+ }
+
+ public Long getParentGpuDeviceId() {
+ return parentGpuDeviceId;
+ }
+
+ public String getNumaNode() {
+ return numaNode;
+ }
+
+ @Override
+ public void execute() {
+ try {
+ GpuDeviceResponse response = gpuService.updateGpuDevice(this);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage());
+ }
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UpdateVgpuProfileCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UpdateVgpuProfileCmd.java
new file mode 100644
index 00000000000..c8d60739bd4
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/gpu/UpdateVgpuProfileCmd.java
@@ -0,0 +1,129 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.gpu;
+
+import com.cloud.user.Account;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.VgpuProfileResponse;
+
+
+@APICommand(name = "updateVgpuProfile", description = "Updates a vGPU profile in the system",
+ responseObject = VgpuProfileResponse.class, requestHasSensitiveInfo = false,
+ responseHasSensitiveInfo = false, since = "4.21.0", authorized = {RoleType.Admin})
+public class UpdateVgpuProfileCmd extends BaseCmd {
+
+ /// //////////////////////////////////////////////////
+ /// ///////////// API parameters /////////////////////
+ /// //////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VgpuProfileResponse.class, required = true,
+ description = "the ID of the vGPU profile")
+ private Long id;
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the vGPU profile")
+ private String profileName;
+
+ @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING,
+ description = "the description of the vGPU profile")
+ private String description;
+
+ @Parameter(name = ApiConstants.MAX_VGPU_PER_PHYSICAL_GPU, type = CommandType.LONG,
+ description = "the maximum number of vGPUs per physical GPU")
+ private Long maxVgpuPerPgpu;
+
+ @Parameter(name = ApiConstants.VIDEORAM, type = CommandType.LONG,
+ description = "the video RAM size in MB")
+ private Long videoRam;
+
+ @Parameter(name = ApiConstants.MAXHEADS, type = CommandType.LONG,
+ description = "the maximum number of display heads")
+ private Long maxHeads;
+
+ @Parameter(name = ApiConstants.MAXRESOLUTIONX, type = CommandType.LONG,
+ description = "the maximum X resolution")
+ private Long maxResolutionX;
+
+ @Parameter(name = ApiConstants.MAXRESOLUTIONY, type = CommandType.LONG,
+ description = "the maximum Y resolution")
+ private Long maxResolutionY;
+
+ /// //////////////////////////////////////////////////
+ /// //////////////// Accessors ///////////////////////
+ /// //////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getProfileName() {
+ return profileName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public Long getMaxVgpuPerPgpu() {
+ return maxVgpuPerPgpu;
+ }
+
+ public Long getVideoRam() {
+ return videoRam;
+ }
+
+ public Long getMaxHeads() {
+ return maxHeads;
+ }
+
+ public Long getMaxResolutionX() {
+ return maxResolutionX;
+ }
+
+ public Long getMaxResolutionY() {
+ return maxResolutionY;
+ }
+
+ @Override
+ public void execute() {
+ try {
+ VgpuProfileResponse response = gpuService.updateVgpuProfile(this);
+ if (response != null) {
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update vGPU profile");
+ }
+ } catch (Exception e) {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR,
+ "Failed to update vGPU profile: " + e.getMessage());
+ }
+ }
+
+ /// //////////////////////////////////////////////////
+ /// //////////// API Implementation///////////////////
+ /// //////////////////////////////////////////////////
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCategoryCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCategoryCmd.java
new file mode 100644
index 00000000000..f099de43f5d
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCategoryCmd.java
@@ -0,0 +1,93 @@
+// 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.
+
+package org.apache.cloudstack.api.command.admin.guest;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandResourceType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
+
+import com.cloud.storage.GuestOsCategory;
+import com.cloud.user.Account;
+
+@APICommand(name = "addOsCategory",
+ description = "Adds a new OS category",
+ responseObject = GuestOSCategoryResponse.class,
+ requestHasSensitiveInfo = false,
+ responseHasSensitiveInfo = false,
+ since = "4.21.0",
+ authorized = {RoleType.Admin})
+public class AddGuestOsCategoryCmd extends BaseCmd {
+
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "Name of the OS category",
+ required = true)
+ private String name;
+
+ @Parameter(name = ApiConstants.IS_FEATURED, type = CommandType.BOOLEAN,
+ description = "Whether the category is featured or not")
+ private Boolean featured;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isFeatured() {
+ return Boolean.TRUE.equals(featured);
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() {
+ GuestOsCategory guestOs = _mgr.addGuestOsCategory(this);
+ if (guestOs != null) {
+ GuestOSCategoryResponse response = _responseGenerator.createGuestOSCategoryResponse(guestOs);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add new OS category");
+ }
+
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public ApiCommandResourceType getApiResourceType() {
+ return ApiCommandResourceType.GuestOsCategory;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/DeleteGuestOsCategoryCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/DeleteGuestOsCategoryCmd.java
new file mode 100644
index 00000000000..8cf62ee2aab
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/DeleteGuestOsCategoryCmd.java
@@ -0,0 +1,89 @@
+// 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.
+
+package org.apache.cloudstack.api.command.admin.guest;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandResourceType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+
+import com.cloud.user.Account;
+
+
+@APICommand(name = "deleteOsCategory",
+ description = "Deletes an OS category",
+ responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = false,
+ responseHasSensitiveInfo = false,
+ since = "4.21.0",
+ authorized = {RoleType.Admin})
+public class DeleteGuestOsCategoryCmd extends BaseCmd {
+
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GuestOSCategoryResponse.class,
+ required = true, description = "ID of the OS category")
+ private Long id;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() {
+ boolean result = _mgr.deleteGuestOsCategory(this);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove OS category");
+ }
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public ApiCommandResourceType getApiResourceType() {
+ return ApiCommandResourceType.GuestOsCategory;
+ }
+
+ @Override
+ public Long getApiResourceId() {
+ return getId();
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCategoryCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCategoryCmd.java
new file mode 100644
index 00000000000..4041967abe8
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCategoryCmd.java
@@ -0,0 +1,113 @@
+// 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.
+
+package org.apache.cloudstack.api.command.admin.guest;
+
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiCommandResourceType;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
+
+import com.cloud.storage.GuestOsCategory;
+import com.cloud.user.Account;
+
+@APICommand(name = "updateOsCategory",
+ description = "Updates an OS category",
+ responseObject = GuestOSCategoryResponse.class,
+ requestHasSensitiveInfo = false,
+ responseHasSensitiveInfo = false,
+ since = "4.21.0",
+ authorized = {RoleType.Admin})
+public class UpdateGuestOsCategoryCmd extends BaseCmd {
+
+
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GuestOSCategoryResponse.class,
+ required = true, description = "ID of the OS category")
+ private Long id;
+
+ @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "Name for the OS category")
+ private String name;
+
+ @Parameter(name = ApiConstants.IS_FEATURED, type = CommandType.BOOLEAN,
+ description = "Whether the category is featured or not")
+ private Boolean featured;
+
+ @Parameter(name = ApiConstants.SORT_KEY, type = CommandType.INTEGER,
+ description = "sort key of the OS category for listing")
+ private Integer sortKey;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Boolean isFeatured() {
+ return featured;
+ }
+
+ public Integer getSortKey() {
+ return sortKey;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute() {
+ GuestOsCategory guestOs = _mgr.updateGuestOsCategory(this);
+ if (guestOs != null) {
+ GuestOSCategoryResponse response = _responseGenerator.createGuestOSCategoryResponse(guestOs);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update OS category");
+ }
+ }
+
+ @Override
+ public ApiCommandResourceType getApiResourceType() {
+ return ApiCommandResourceType.GuestOsCategory;
+ }
+
+ @Override
+ public Long getApiResourceId() {
+ return getId();
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java
index c98cd149ef3..59909e09854 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java
@@ -16,8 +16,12 @@
// under the License.
package org.apache.cloudstack.api.command.admin.guest;
-import org.apache.commons.collections.MapUtils;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@@ -25,18 +29,14 @@ import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import org.apache.cloudstack.api.response.GuestOSResponse;
-import org.apache.cloudstack.acl.RoleType;
+import org.apache.commons.collections.MapUtils;
import com.cloud.event.EventTypes;
import com.cloud.storage.GuestOS;
import com.cloud.user.Account;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
@APICommand(name = "updateGuestOs", description = "Updates the information about Guest OS", responseObject = GuestOSResponse.class,
since = "4.4.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class UpdateGuestOsCmd extends BaseAsyncCmd {
@@ -50,7 +50,7 @@ public class UpdateGuestOsCmd extends BaseAsyncCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GuestOSResponse.class, required = true, description = "UUID of the Guest OS")
private Long id;
- @Parameter(name = ApiConstants.OS_DISPLAY_NAME, type = CommandType.STRING, required = true, description = "Unique display name for Guest OS")
+ @Parameter(name = ApiConstants.OS_DISPLAY_NAME, type = CommandType.STRING, description = "Unique display name for Guest OS")
private String osDisplayName;
@Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, required = false, description = "Map of (key/value pairs)")
@@ -59,6 +59,12 @@ public class UpdateGuestOsCmd extends BaseAsyncCmd {
@Parameter(name="forDisplay", type=CommandType.BOOLEAN, description="whether this guest OS is available for end users", authorized = {RoleType.Admin})
private Boolean display;
+ @Parameter(name = ApiConstants.OS_CATEGORY_ID, type = CommandType.UUID, entityType = GuestOSCategoryResponse.class,
+ description = "the ID of the OS category", since = "4.21.0")
+ private Long osCategoryId;
+
+
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -71,9 +77,9 @@ public class UpdateGuestOsCmd extends BaseAsyncCmd {
return osDisplayName;
}
- public Map getDetails() {
- Map detailsMap = new HashMap<>();;
- if (MapUtils.isNotEmpty(detailsMap)) {
+ public Map getDetails() {
+ Map detailsMap = new HashMap<>();
+ if (MapUtils.isNotEmpty(details)) {
Collection> servicesCollection = details.values();
Iterator> iter = servicesCollection.iterator();
while (iter.hasNext()) {
@@ -90,6 +96,10 @@ public class UpdateGuestOsCmd extends BaseAsyncCmd {
return display;
}
+ public Long getOsCategoryId() {
+ return osCategoryId;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddHostCmd.java
index ca27837aa88..cc124ab8106 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddHostCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddHostCmd.java
@@ -18,7 +18,7 @@ package org.apache.cloudstack.api.command.admin.host;
import java.util.ArrayList;
import java.util.List;
-
+import java.util.Map;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
@@ -75,6 +75,18 @@ public class AddHostCmd extends BaseCmd {
@Parameter(name = ApiConstants.HOST_TAGS, type = CommandType.LIST, collectionType = CommandType.STRING, description = "list of tags to be added to the host")
private List hostTags;
+ @Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS,
+ type = CommandType.LIST, collectionType = CommandType.STRING,
+ description = "comma separated list of storage access groups for the host",
+ since = "4.21.0")
+ private List storageAccessGroups;
+
+ @Parameter(name = ApiConstants.EXTERNAL_DETAILS,
+ type = CommandType.MAP,
+ description = "Details in key/value pairs using format externaldetails[i].keyname=keyvalue. Example: externaldetails[0].endpoint.url=urlvalue",
+ since = "4.21.0")
+ protected Map externalDetails;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -115,10 +127,18 @@ public class AddHostCmd extends BaseCmd {
return hostTags;
}
+ public List getStorageAccessGroups() {
+ return storageAccessGroups;
+ }
+
public String getAllocationState() {
return allocationState;
}
+ public Map getExternalDetails() {
+ return convertExternalDetailsToMap(externalDetails);
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java
index 5e229521efe..a71150a69e2 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java
@@ -21,7 +21,6 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Map;
-
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@@ -35,7 +34,9 @@ import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.commons.lang3.StringUtils;
+import com.cloud.cpu.CPU;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -109,6 +110,14 @@ public class ListHostsCmd extends BaseListCmd {
@Parameter(name = ApiConstants.MANAGEMENT_SERVER_ID, type = CommandType.UUID, entityType = ManagementServerResponse.class, description = "the id of the management server", since="4.21.0")
private Long managementServerId;
+ @Parameter(name = ApiConstants.ARCH, type = CommandType.STRING, description = "CPU Arch of the host", since = "4.20.1")
+ private String arch;
+
+ @Parameter(name = ApiConstants.STORAGE_ACCESS_GROUP, type = CommandType.STRING,
+ description = "the name of the storage access group",
+ since = "4.21.0")
+ private String storageAccessGroup;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -197,6 +206,22 @@ public class ListHostsCmd extends BaseListCmd {
return managementServerId;
}
+ public CPU.CPUArch getArch() {
+ return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
+ }
+
+ public String getStorageAccessGroup() {
+ return storageAccessGroup;
+ }
+
+ public ListHostsCmd() {
+
+ }
+
+ public ListHostsCmd(String storageAccessGroup) {
+ this.storageAccessGroup = storageAccessGroup;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java
index 397f9c80735..9baea58b7b5 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java
@@ -16,8 +16,9 @@
// under the License.
package org.apache.cloudstack.api.command.admin.host;
-import com.cloud.host.Host;
-import com.cloud.user.Account;
+import java.util.List;
+import java.util.Map;
+
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
@@ -28,7 +29,8 @@ import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.GuestOSCategoryResponse;
import org.apache.cloudstack.api.response.HostResponse;
-import java.util.List;
+import com.cloud.host.Host;
+import com.cloud.user.Account;
@APICommand(name = "updateHost", description = "Updates a host.", responseObject = HostResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
@@ -67,6 +69,9 @@ public class UpdateHostCmd extends BaseCmd {
@Parameter(name = ApiConstants.ANNOTATION, type = CommandType.STRING, description = "Add an annotation to this host", since = "4.11", authorized = {RoleType.Admin})
private String annotation;
+ @Parameter(name = ApiConstants.EXTERNAL_DETAILS, type = CommandType.MAP, description = "Details in key/value pairs using format externaldetails[i].keyname=keyvalue. Example: externaldetails[0].endpoint.url=urlvalue", since = "4.21.0")
+ protected Map externalDetails;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -103,6 +108,10 @@ public class UpdateHostCmd extends BaseCmd {
return annotation;
}
+ public Map getExternalDetails() {
+ return convertExternalDetailsToMap(externalDetails);
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/management/RemoveManagementServerCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/management/RemoveManagementServerCmd.java
new file mode 100644
index 00000000000..803b95bfa9e
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/management/RemoveManagementServerCmd.java
@@ -0,0 +1,61 @@
+// 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.
+package org.apache.cloudstack.api.command.admin.management;
+
+import com.cloud.event.EventTypes;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.response.ManagementServerResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.context.CallContext;
+
+@APICommand(name = "removeManagementServer", description = "Removes a Management Server.", responseObject = SuccessResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = RoleType.Admin)
+public class RemoveManagementServerCmd extends BaseCmd {
+
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ManagementServerResponse.class, required = true, description = "the ID of the Management Server")
+ private Long id;
+
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void execute() {
+ boolean result = _mgr.removeManagementServer(this);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove Management Server.");
+ }
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccountId();
+ }
+
+ public String getEventType() {
+ return EventTypes.EVENT_MANAGEMENT_SERVER_REMOVE;
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
index af3db374a7c..56333f4081b 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java
@@ -17,6 +17,7 @@
package org.apache.cloudstack.api.command.admin.network;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -60,6 +61,10 @@ import static com.cloud.network.Network.Service.NetworkACL;
import static com.cloud.network.Network.Service.UserData;
import static com.cloud.network.Network.Service.Firewall;
+import static org.apache.cloudstack.api.command.utils.OfferingUtils.isNetrisNatted;
+import static org.apache.cloudstack.api.command.utils.OfferingUtils.isNetrisRouted;
+import static org.apache.cloudstack.api.command.utils.OfferingUtils.isNsxWithoutLb;
+
@APICommand(name = "createNetworkOffering", description = "Creates a network offering.", responseObject = NetworkOfferingResponse.class, since = "3.0.0",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class CreateNetworkOfferingCmd extends BaseCmd {
@@ -140,12 +145,19 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
description = "true if network offering is meant to be used for VPC, false otherwise.")
private Boolean forVpc;
+ @Deprecated
@Parameter(name = ApiConstants.FOR_NSX,
type = CommandType.BOOLEAN,
description = "true if network offering is meant to be used for NSX, false otherwise.",
since = "4.20.0")
private Boolean forNsx;
+ @Parameter(name = ApiConstants.PROVIDER,
+ type = CommandType.STRING,
+ description = "Name of the provider providing the service",
+ since = "4.21.0")
+ private String provider;
+
@Parameter(name = ApiConstants.NSX_SUPPORT_LB,
type = CommandType.BOOLEAN,
description = "true if network offering for NSX network offering supports Load balancer service.",
@@ -257,19 +269,39 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
return serviceOfferingId;
}
+ public boolean isExternalNetworkProvider() {
+ return Arrays.asList("NSX", "Netris").stream()
+ .anyMatch(s -> provider != null && s.equalsIgnoreCase(provider));
+ }
+
+ public boolean isForNsx() {
+ return provider != null && provider.equalsIgnoreCase("NSX");
+ }
+
+ public boolean isForNetris() {
+ return provider != null && provider.equalsIgnoreCase("Netris");
+ }
+
+ public String getProvider() {
+ return provider;
+ }
+
public List getSupportedServices() {
- if (!isForNsx()) {
+ if (!isExternalNetworkProvider()) {
return supportedServices == null ? new ArrayList() : supportedServices;
} else {
List services = new ArrayList<>(List.of(
Dhcp.getName(),
Dns.getName(),
- StaticNat.getName(),
- SourceNat.getName(),
- PortForwarding.getName(),
UserData.getName()
));
- if (getNsxSupportsLbService()) {
+ if (NetworkOffering.NetworkMode.NATTED.name().equalsIgnoreCase(getNetworkMode())) {
+ services.addAll(Arrays.asList(
+ StaticNat.getName(),
+ SourceNat.getName(),
+ PortForwarding.getName()));
+ }
+ if (getNsxSupportsLbService() || (provider != null && isNetrisNatted(getProvider(), getNetworkMode()))) {
services.add(Lb.getName());
}
if (Boolean.TRUE.equals(forVpc)) {
@@ -308,10 +340,6 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
return forVpc;
}
- public boolean isForNsx() {
- return BooleanUtils.isTrue(forNsx);
- }
-
public String getNetworkMode() {
return networkMode;
}
@@ -345,7 +373,7 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
public Map> getServiceProviders() {
Map> serviceProviderMap = new HashMap<>();
- if (serviceProviderList != null && !serviceProviderList.isEmpty() && !isForNsx()) {
+ if (serviceProviderList != null && !serviceProviderList.isEmpty() && !isExternalNetworkProvider()) {
Collection servicesCollection = serviceProviderList.values();
Iterator iter = servicesCollection.iterator();
while (iter.hasNext()) {
@@ -361,17 +389,16 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
providerList.add(provider);
serviceProviderMap.put(service, providerList);
}
- } else if (Boolean.TRUE.equals(forNsx)) {
- getServiceProviderMapForNsx(serviceProviderMap);
+ } else if (isExternalNetworkProvider()) {
+ getServiceProviderMapForExternalProvider(serviceProviderMap, Network.Provider.getProvider(provider).getName());
}
return serviceProviderMap;
}
- private void getServiceProviderMapForNsx(Map> serviceProviderMap) {
+ private void getServiceProviderMapForExternalProvider(Map> serviceProviderMap, String provider) {
String routerProvider = Boolean.TRUE.equals(getForVpc()) ? VirtualRouterProvider.Type.VPCVirtualRouter.name() :
VirtualRouterProvider.Type.VirtualRouter.name();
- List unsupportedServices = new ArrayList<>(List.of("Vpn", "SecurityGroup", "Connectivity",
- "Gateway", "BaremetalPxeService"));
+ List unsupportedServices = new ArrayList<>(List.of("Vpn", "Gateway", "SecurityGroup", "Connectivity", "BaremetalPxeService"));
List routerSupported = List.of("Dhcp", "Dns", "UserData");
List allServices = Service.listAllServices().stream().map(Service::getName).collect(Collectors.toList());
if (routerProvider.equals(VirtualRouterProvider.Type.VPCVirtualRouter.name())) {
@@ -384,9 +411,10 @@ public class CreateNetworkOfferingCmd extends BaseCmd {
continue;
if (routerSupported.contains(service))
serviceProviderMap.put(service, List.of(routerProvider));
- else
- serviceProviderMap.put(service, List.of(Network.Provider.Nsx.getName()));
- if (!getNsxSupportsLbService()) {
+ else if (NetworkOffering.NetworkMode.NATTED.name().equalsIgnoreCase(getNetworkMode()) || NetworkACL.getName().equalsIgnoreCase(service)) {
+ serviceProviderMap.put(service, List.of(provider));
+ }
+ if (isNsxWithoutLb(getProvider(), getNsxSupportsLbService()) || isNetrisRouted(getProvider(), getNetworkMode())) {
serviceProviderMap.remove(Lb.getName());
}
}
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java
index 8f6d5413d72..3d20ed50a5d 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java
@@ -29,14 +29,17 @@ import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
+import org.apache.cloudstack.api.response.VgpuProfileResponse;
import org.apache.cloudstack.api.response.VsphereStoragePoliciesResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
-import org.apache.cloudstack.api.response.DiskOfferingResponse;
-import org.apache.commons.collections.MapUtils;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.cloudstack.vm.lease.VMLeaseManager;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.EnumUtils;
+import org.apache.commons.lang3.StringUtils;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.offering.ServiceOffering;
@@ -251,7 +254,40 @@ public class CreateServiceOfferingCmd extends BaseCmd {
since="4.20")
private Boolean purgeResources;
+ @Parameter(name = ApiConstants.INSTANCE_LEASE_DURATION,
+ type = CommandType.INTEGER,
+ description = "Number of days instance is leased for.",
+ since = "4.21.0")
+ private Integer leaseDuration;
+ @Parameter(name = ApiConstants.INSTANCE_LEASE_EXPIRY_ACTION, type = CommandType.STRING, since = "4.21.0",
+ description = "Lease expiry action, valid values are STOP and DESTROY")
+ private String leaseExpiryAction;
+
+ @Parameter(name = ApiConstants.VGPU_PROFILE_ID,
+ type = CommandType.UUID,
+ entityType = VgpuProfileResponse.class,
+ description = "the ID of the vGPU profile to which service offering should be mapped",
+ since = "4.21")
+ private Long vgpuProfileId;
+
+ @Parameter(name = ApiConstants.GPU_COUNT,
+ type = CommandType.INTEGER,
+ description = "Count of GPUs to be used with this service offering. This is applicable only when passed with vGPU profile.",
+ since = "4.21")
+ private Integer gpuCount;
+
+ @Parameter(name = ApiConstants.GPU_DISPLAY,
+ type = CommandType.BOOLEAN,
+ description = "Whether to enable GPU display for this service offering. This is applicable only when passed with vGPU profile. Defaults to false.",
+ since = "4.21")
+ private Boolean gpuDisplay;
+
+ @Parameter(name = ApiConstants.EXTERNAL_DETAILS,
+ type = CommandType.MAP,
+ description = "Details in key/value pairs using format externaldetails[i].keyname=keyvalue. Example: externaldetails[0].endpoint.url=urlvalue",
+ since = "4.21.0")
+ private Map externalDetails;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@@ -359,9 +395,15 @@ public class CreateServiceOfferingCmd extends BaseCmd {
}
}
}
+
+ detailsMap.putAll(getExternalDetails());
return detailsMap;
}
+ public Map getExternalDetails() {
+ return convertExternalDetailsToMap(externalDetails);
+ }
+
public Long getRootDiskSize() {
return rootDiskSize;
}
@@ -487,10 +529,38 @@ public class CreateServiceOfferingCmd extends BaseCmd {
return false;
}
+ public VMLeaseManager.ExpiryAction getLeaseExpiryAction() {
+ if (StringUtils.isBlank(leaseExpiryAction)) {
+ return null;
+ }
+ VMLeaseManager.ExpiryAction action = EnumUtils.getEnumIgnoreCase(VMLeaseManager.ExpiryAction.class, leaseExpiryAction);
+ if (action == null) {
+ throw new InvalidParameterValueException("Invalid value configured for leaseexpiryaction, valid values are: " +
+ com.cloud.utils.EnumUtils.listValues(VMLeaseManager.ExpiryAction.values()));
+ }
+ return action;
+ }
+
+ public Integer getLeaseDuration() {
+ return leaseDuration;
+ }
+
public boolean isPurgeResources() {
return Boolean.TRUE.equals(purgeResources);
}
+ public Long getVgpuProfileId() {
+ return vgpuProfileId;
+ }
+
+ public Integer getGpuCount() {
+ return gpuCount;
+ }
+
+ public Boolean getGpuDisplay() {
+ return Boolean.TRUE.equals(gpuDisplay);
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java
index e94bff1fce8..fcd6b03d3e5 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java
@@ -29,7 +29,7 @@ import org.apache.cloudstack.api.response.IsAccountAllowedToCreateOfferingsWithT
responseObject = IsAccountAllowedToCreateOfferingsWithTagsResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class IsAccountAllowedToCreateOfferingsWithTagsCmd extends BaseCmd {
- @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "Account UUID")
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "Account UUID", required = true)
private Long id;
@Override
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmd.java
index e580f0d9f41..7f66ac7058a 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmd.java
@@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.admin.offering;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import com.cloud.offering.ServiceOffering.State;
import org.apache.cloudstack.api.APICommand;
@@ -94,6 +95,12 @@ public class UpdateServiceOfferingCmd extends BaseCmd {
since="4.20")
private Boolean purgeResources;
+ @Parameter(name = ApiConstants.EXTERNAL_DETAILS,
+ type = CommandType.MAP,
+ description = "Details in key/value pairs using format externaldetails[i].keyname=keyvalue. Example: externaldetails[0].endpoint.url=urlvalue",
+ since = "4.21.0")
+ private Map externalDetails;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -194,6 +201,10 @@ public class UpdateServiceOfferingCmd extends BaseCmd {
return Boolean.TRUE.equals(purgeResources);
}
+ public Map getExternalDetails() {
+ return convertExternalDetailsToMap(externalDetails);
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/CreatePodCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/CreatePodCmd.java
index c1d9a6db429..36ad00e6e4a 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/CreatePodCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/CreatePodCmd.java
@@ -30,6 +30,8 @@ import org.apache.cloudstack.api.response.ZoneResponse;
import com.cloud.dc.Pod;
import com.cloud.user.Account;
+import java.util.List;
+
@APICommand(name = "createPod", description = "Creates a new Pod.", responseObject = PodResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class CreatePodCmd extends BaseCmd {
@@ -63,6 +65,12 @@ public class CreatePodCmd extends BaseCmd {
@Parameter(name = ApiConstants.ALLOCATION_STATE, type = CommandType.STRING, description = "Allocation state of this Pod for allocation of new resources")
private String allocationState;
+ @Parameter(name = ApiConstants.STORAGE_ACCESS_GROUPS,
+ type = CommandType.LIST, collectionType = CommandType.STRING,
+ description = "comma separated list of storage access groups for the hosts in the pod",
+ since = "4.21.0")
+ private List storageAccessGroups;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -95,6 +103,10 @@ public class CreatePodCmd extends BaseCmd {
return allocationState;
}
+ public List getStorageAccessGroups() {
+ return storageAccessGroups;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@@ -111,7 +123,7 @@ public class CreatePodCmd extends BaseCmd {
@Override
public void execute() {
- Pod result = _configService.createPod(getZoneId(), getPodName(), getStartIp(), getEndIp(), getGateway(), getNetmask(), getAllocationState());
+ Pod result = _configService.createPod(getZoneId(), getPodName(), getStartIp(), getEndIp(), getGateway(), getNetmask(), getAllocationState(), getStorageAccessGroups());
if (result != null) {
PodResponse response = _responseGenerator.createPodResponse(result, false);
response.setResponseName(getCommandName());
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java
index 5ad0b457ced..264e5263c4d 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java
@@ -55,6 +55,11 @@ public class ListPodsByCmd extends BaseListCmd {
@Parameter(name = ApiConstants.SHOW_CAPACITIES, type = CommandType.BOOLEAN, description = "flag to display the capacity of the pods")
private Boolean showCapacities;
+ @Parameter(name = ApiConstants.STORAGE_ACCESS_GROUP, type = CommandType.STRING,
+ description = "the name of the storage access group",
+ since = "4.21.0")
+ private String storageAccessGroup;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -79,6 +84,18 @@ public class ListPodsByCmd extends BaseListCmd {
return showCapacities;
}
+ public String getStorageAccessGroup() {
+ return storageAccessGroup;
+ }
+
+ public ListPodsByCmd() {
+
+ }
+
+ public ListPodsByCmd(String storageAccessGroup) {
+ this.storageAccessGroup = storageAccessGroup;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@@ -86,8 +103,8 @@ public class ListPodsByCmd extends BaseListCmd {
@Override
public void execute() {
Pair, Integer> result = _mgr.searchForPods(this);
- ListResponse response = new ListResponse();
- List podResponses = new ArrayList();
+ ListResponse response = new ListResponse<>();
+ List