Compare commits

...

84 Commits

Author SHA1 Message Date
John Bampton
53a39d3ff7
.github: Move dependabot.yml to the correct directory (#12243)
The `dependabot.yml` configuration file should be placed in the `.github` directory at the root of your repository.

Dependabot will not work if the file is placed in any other directory

Minor file extension rename for standardization
2025-12-16 14:11:04 +01:00
Daan Hoogland
f06ac512fa merge forward 4.22 to main 2025-12-16 11:50:58 +01:00
Daan Hoogland
7aba434dc4 merge forward 4.20 to 4.22 LTS 2025-12-16 11:19:04 +01:00
Abhishek Kumar
da1c7cebf9
server: trim autoscale Windows VM hostname (#11327)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Co-authored-by: Wei Zhou <weizhou@apache.org>
2025-12-15 15:52:32 +01:00
Abhishek Kumar
39d0d62fdd
api,server: normalize string empty value on config update (#11770)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2025-12-15 15:43:00 +01:00
dahn
f570e16836
.github: initial version of Code Owners (#12253)
* initial version of Code Owners

* Update .github/CODEOWNERS

---------

Co-authored-by: Daan Hoogland <dahn@apache.org>
Co-authored-by: John Bampton <jbampton@users.noreply.github.com>
2025-12-15 11:04:45 +01:00
John Bampton
1919dcfb7c
pre-commit trailing-whitespace cleanup LICENSE/NOTICE (#12242) 2025-12-15 10:09:11 +01:00
Suresh Kumar Anaparti
67217d4d2e
UI: Option to choose the isolation method when creating the public IP range (#12000) 2025-12-15 09:37:18 +01:00
dahn
494c56a499
check for active MSses before starting DB upgrade (#12140) 2025-12-12 15:09:35 +01:00
Pearl Dsilva
0a13fb27f5
Prevent scaling of cluster if count / resources exceed account resource limits (#12167) 2025-12-12 13:57:15 +01:00
Abhishek Kumar
e1c48c3adc
server,ui: prevent role change for default accounts (#11761)
* server,ui: prevent role change for default accounts

Fixes #10931

Role for default accounts shouldn't be changed. Appropriate error should be returned by the server and UI should not present option for them.

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>

* Update server/src/main/java/com/cloud/user/AccountManagerImpl.java

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-12 13:42:26 +01:00
John Bampton
f417c6b0a1
yamllint use extends: default (#12066) 2025-12-11 17:59:45 +01:00
John Bampton
78f9e6584b
UI(vue) + extras: fix bugs/spelling and standardize (#12073) 2025-12-11 16:41:50 +01:00
dahn
79ebf6959e
refactor storapool automation (#11789)
Co-authored-by: Daan Hoogland <dahn@apache.org>
2025-12-11 09:04:23 +01:00
John Bampton
cfe96026dc
Standardize and auto add license headers to all Vue files with pre-commit (#12081) 2025-12-10 16:21:41 +01:00
Vishesh
4348386970
Optimize drs plan generation (#12014) 2025-12-10 13:24:39 +01:00
Abhishek Kumar
ba52db9b3e
ui: allow macaddress input for add nic to vm (#12145)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2025-12-09 15:20:01 +01:00
Manoj Kumar
951649c420
Support iprange while creating remote access vpn (#12063) 2025-12-09 11:56:16 +01:00
Pearl Dsilva
3c6484792d
UI: Create Account form to set proper domain and role based on route (#12200) 2025-12-09 10:56:04 +01:00
dahn
223fc2512c
Enhance NFS mount option check for empty response (#11839) 2025-12-09 10:51:42 +01:00
dahn
51910cd260
Add license information to dependabot.yaml
Added Apache License information to dependabot.yaml
2025-12-08 16:48:18 +01:00
dahn
5151f8dc6a
java dependabot file (#11409)
Co-authored-by: Daan Hoogland <dahn@apache.org>
2025-12-08 16:33:10 +01:00
dahn
c81295439f
removed code in comments (#11145) 2025-12-08 16:31:48 +01:00
Lucas Martins
12f4321952
Changes error message when using invalid endpoint.url (#8603)
Co-authored-by: lucas.martins.scclouds <lucas.martins@scclouds.com.br>
Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>
Co-authored-by: erikbocks <erik.bock@outlook.com>
2025-12-08 09:41:56 +01:00
Suresh Kumar Anaparti
b0d74fe00c
Merge branch '4.22' 2025-12-05 18:59:03 +05:30
Suresh Kumar Anaparti
a0ba2aaf3f
Merge branch '4.20' into 4.22 2025-12-05 18:41:18 +05:30
Abhisar Sinha
4379666fb6
Proxmox Extension : Make settings such as storage, disk_size,... (#12174)
Make storage, disk-size and os-type configurable in the Proxmox extension

Doc PR: apache/cloudstack-documentation#601

---------

Co-authored-by: dahn <daan.hoogland@gmail.com>
2025-12-03 17:05:22 +05:30
Suresh Kumar Anaparti
e4414d1c44
Fix agent wait before reconnect (#12153) 2025-12-03 11:19:47 +05:30
Abhishek Kumar
26009659f9
Merge remote-tracking branch 'apache/4.22' 2025-12-01 13:07:45 +05:30
Abhishek Kumar
2941b518ba
Merge remote-tracking branch 'apache/4.20' into 4.22 2025-12-01 13:05:08 +05:30
dahn
f3a112fd9e
use upstream method for creating enums from strings (#12158)
Co-authored-by: Daan Hoogland <dahn@apache.org>
2025-12-01 08:33:14 +01:00
Abhishek Kumar
243f566a60
refactor: add null check for BroadcastDomainType retrievals (#11572)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2025-12-01 08:19:09 +01:00
Wei Zhou
516012a0b4
ceph: fix offline volume migration between ceph pools (#12103) 2025-11-28 15:44:00 +01:00
Abhishek Kumar
44119cf34f
ui: fix dsiple managementservermetricsresponse - agentcount (#12148)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2025-11-28 10:29:18 +01:00
John Bampton
db6147060b
Rename PRE-COMMIT.md to PRE_COMMIT.md and fix link (#12157) 2025-11-28 10:01:38 +01:00
Abhishek Kumar
f379d78963
ui: fix section search filter (#12146)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2025-11-28 09:29:10 +01:00
Harikrishna
5798fb43a3
Fix upgrade files (#12155) 2025-11-27 15:56:26 +01:00
Daan Hoogland
4e61ddd1bc import 2025-11-26 13:01:52 +01:00
Daan Hoogland
9032fe3fb5 merge LTS branch 4.22 into main 2025-11-26 11:55:50 +01:00
Daan Hoogland
e23c7ef701 Merge release branch 4.20 to 4.22
* 4.20:
  fixed Password Exposure in IPMI Tool Command Execution (#12028)
  server: fix volume offering not updated after offering change (#12003)
  fix API Request Parameters Logged Credential Masking in ApiServer (#12020)
2025-11-26 11:31:27 +01:00
Abhisar Sinha
e33f4754f5
Fix DB upgrade script for 4.22 (#12111) 2025-11-26 09:25:41 +01:00
Abhishek Kumar
9ec8cc4186
api,server,ui: improve listing public ip for associate (#11591)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2025-11-26 09:24:12 +01:00
João Jandre
8171d9568c
Block use of internal and external snapshots on KVM (#11039) 2025-11-24 11:39:19 +01:00
Wei Zhou
dba889ea3e
UI: fix list of zones if zone has icon (#12083) 2025-11-24 11:10:43 +01:00
John Bampton
6dc259c7da
Rename and standardize issue templates to .yml (#12082) 2025-11-14 21:22:12 +01:00
John Bampton
39126a4339
Standardize and auto add license headers for Shell files with pre-commit (#12070)
* Add shebang to shell scripts
2025-11-14 14:23:41 +01:00
John Bampton
aa18188d30
pre-commit: auto add license headers for all YAML files (#12069)
Fix and standardize one license header
2025-11-14 14:23:03 +01:00
John Bampton
4ed86a2627
pre-commit upgrade codespell; fix spelling; (#10144) 2025-11-14 14:17:10 +01:00
John Bampton
86ae1fee7f
Standardize and auto add license headers for SQL files with pre-commit (#12071) 2025-11-14 11:47:27 +01:00
Abhishek Kumar
21d844ba1c
ui: fix zone options for image instance deploy button (#12060)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2025-11-14 10:43:42 +01:00
John Bampton
ac3b18095a
pre-commit use colored text in the CI for pass / fail / skipped (#11977) 2025-11-13 15:59:07 +05:30
John Bampton
fff4cafdca
ui(locales): remove duplicates and fix typos (#11872) 2025-11-13 11:17:02 +01:00
John Bampton
a5b455ff3a
pre-commit: auto add table of contents with doctoc (#11679)
https://github.com/thlorenz/doctoc?tab=readme-ov-file#usage-as-a-git-hook
https://github.com/thlorenz/doctoc/releases/tag/v2.2.0

Generates table of contents for Markdown files inside local git repository.

Links are compatible with anchors generated by github or other sites.

Added TOC to 3 Markdown files.

Never have to create a TOC again just run: `pre-commit run doctoc --all-files`

- CONTRIBUTING.md
- INSTALL.md
- README.md

So both Apache Airflow and Apache Sedona use `doctoc`:

eb4a8bc03c/.pre-commit-config.yaml (L32)
b0d86fda01/.pre-commit-config.yaml (L34)
2025-11-13 11:13:19 +01:00
John Bampton
8b034dc439
chore: rename workflow linter.yml to pre-commit.yml (#11647) 2025-11-13 15:22:49 +05:30
YoulongChen
028dd86945
fixed Password Exposure in IPMI Tool Command Execution (#12028) 2025-11-13 13:40:36 +05:30
Abhishek Kumar
dc8f465527
engine-schema: upgrade path for 4.23.0 (#12048)
Adds a 4.22.0 to 4.23.0 upgrade path.

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2025-11-13 08:51:08 +01:00
dahn
e90e31d386
add isPerson check to query for AD (#11843) 2025-11-12 16:09:28 +01:00
Madhukar Mishra
f985a67f4d
Fixes:#7837: Add isolationMethods and vlan to TrafficTypeResponse (#8151)
Co-authored-by: dahn <daan.hoogland@gmail.com>
Co-authored-by: dahn <daan@onecht.net>
2025-11-12 15:49:52 +01:00
dahn
5f9e131198
Svgs (#12051) 2025-11-12 14:31:36 +05:30
Abhishek Kumar
f0a0936675
server: fix volume offering not updated after offering change (#12003)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2025-11-12 09:51:51 +01:00
Abhisar Sinha
671d8ad704
Track volume usage data at a vm granularity as well (#11531)
Co-authored-by: Vishesh <8760112+vishesh92@users.noreply.github.com>
2025-11-12 09:32:01 +01:00
YoulongChen
81787b310e
fix API Request Parameters Logged Credential Masking in ApiServer (#12020) 2025-11-12 13:06:19 +05:30
Erik Böck
23fb0e2ccb
Update GUI Kubernetes logo (#11895) 2025-11-11 18:13:00 +01:00
Davi Torres
40c8bc528d
Keeping consistency with other error messages. (#11649)
Co-authored-by: Davi Torres <dtorres@simnet.ca>
Co-authored-by: dahn <daan.hoogland@gmail.com>
2025-11-11 15:33:07 +01:00
Pearl Dsilva
15439ede7d
UI: Update and reset domain level configuration (#11571) 2025-11-11 09:29:54 +01:00
Wei Zhou
50fe265017
Merge remote-tracking branch 'apache/4.20' into 4.22 2025-11-07 17:19:53 +01:00
Wei Zhou
d26122bf22
Veeam: use pre-defined object mapper (#10715) 2025-11-07 16:13:10 +01:00
Suresh Kumar Anaparti
2dd1e6d786
Enable UEFI on KVM hosts (by default), and configure with some default settings (#11740) 2025-11-07 14:54:02 +01:00
Phsm Qwerty
8c86f24261
enhancement: add instance info as Libvirt metadata (#11061) 2025-11-07 14:31:34 +01:00
Wei Zhou
2954e96947
Veeam: get templateId from vm instance if vm is created from ISO (#10705) 2025-11-07 11:55:27 +01:00
Manoj Kumar
c5c3cc40c1
consider Instance in Starting state for listPodsByUserConcentration (#11845) 2025-11-07 10:43:46 +01:00
Suresh Kumar Anaparti
9c0efb7072
DB setup: support db schema creation (with --schema-only) without force recreate option (#12004) 2025-11-07 09:37:11 +01:00
Suresh Kumar Anaparti
b8ec941ec1
uefi property typo (#11929) 2025-11-07 09:31:11 +01:00
Wei Zhou
8230f04a79
CKS: update cloud.kubernetes.cluster.network.offering to dynamic (#11847) 2025-11-06 11:13:53 +01:00
Pearl Dsilva
a50de029bf
Add empty Provider value in Network/VPC Offering form (#11982) 2025-11-06 11:09:00 +01:00
Suresh Kumar Anaparti
81b2c38be9
Merge branch '4.22' 2025-11-06 14:41:59 +05:30
Suresh Kumar Anaparti
ac8c200790
merge fix 2025-11-06 14:41:27 +05:30
Suresh Kumar Anaparti
5504b053e4
Merge branch '4.20' into 4.22 2025-11-06 14:37:38 +05:30
Harikrishna Patnala
dbda673e1f Updating pom.xml version numbers for release 4.23.0.0-SNAPSHOT
Signed-off-by: Harikrishna Patnala <harikrishna.patnala@gmail.com>
2025-11-05 16:54:39 +05:30
Harikrishna Patnala
e66926e6a4 Merge branch '4.22' 2025-11-05 16:52:20 +05:30
Harikrishna Patnala
d160731b9f Updating pom.xml version numbers for release 4.22.1.0-SNAPSHOT
Signed-off-by: Harikrishna Patnala <harikrishna.patnala@gmail.com>
2025-11-05 16:07:07 +05:30
Wei Zhou
15c2e50338
UI: fix typo Upload SSL certificate (#11869) 2025-11-03 15:36:52 +01:00
Wei Zhou
d53b6dbda4
api/test: fix storage pool update with only id (#11897) 2025-11-03 15:25:09 +01:00
Suresh Kumar Anaparti
e90e436ef8
UI: Enable listall (for Affinity Groups, SSH Keypairs, User Data) in deploy instance wizard for admin, and lists SSH Keypairs, User Data by domain/account (#11906) 2025-10-29 11:18:32 +01:00
504 changed files with 5192 additions and 3021 deletions

22
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,22 @@
# 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.
/plugins/storage/volume/linstor @rp-
/plugins/storage/volume/storpool @slavkap
.pre-commit-config.yaml @jbampton
/.github/linters/ @jbampton

28
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,28 @@
# 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.
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "maven" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"

View File

@ -15,13 +15,14 @@
# specific language governing permissions and limitations
# under the License.
---
extends: relaxed
extends: default
rules:
line-length:
max: 400 # Very forgiving for GitHub Actions and infrastructure files
indentation: disable # Disable indentation checking for existing files
comments: disable # Disable comment formatting checks
braces: disable
brackets: disable # Disable bracket spacing checks
colons:
max-spaces-after: -1 # Allow any number of spaces after colon

View File

@ -4,6 +4,7 @@ acount
actuall
acuiring
acumulate
addin
addreess
addtion
adminstrator
@ -12,10 +13,8 @@ afrer
afterall
againt
ags
aktive
algoritm
allo
alloacate
allocted
alocation
alogrithm
@ -65,6 +64,7 @@ bject
boardcast
bootstraper
bu
callin
cant
capabilites
capablity
@ -73,6 +73,7 @@ carrefully
cavaet
chaing
checkd
checkin
childs
choosen
chould
@ -93,7 +94,6 @@ confg
configruation
configuable
conneciton
connexion
constrait
constraits
containg
@ -101,9 +101,7 @@ contex
continuesly
contro
controler
controles
controll
convienient
convinience
coputer
correcponding
@ -158,13 +156,13 @@ differnet
differnt
direcotry
directroy
disale
disbale
discrepency
disover
dissapper
dissassociated
divice
dockin
doesn'
doesnot
doesnt
@ -175,7 +173,6 @@ eanbled
earch
ect
elemnt
eles
elments
emmited
enble
@ -187,22 +184,19 @@ environmnet
equivalant
erro
erronous
everthing
everytime
excute
execept
execption
exects
execut
executeable
exeeded
exisitng
exisits
existin
existsing
exitting
expcted
expection
explaination
explicitely
faield
faild
@ -215,7 +209,6 @@ fillled
findout
fisrt
fo
folowing
fowarding
frist
fro
@ -234,6 +227,7 @@ hanling
happend
hasing
hasnt
havin
hda
hostanme
hould
@ -253,20 +247,14 @@ implmeneted
implmentation
incase
includeing
incosistency
indecates
indien
infor
informations
informaton
infrastrcuture
ingore
inital
initalize
initator
initilization
inspite
instace
instal
instnace
intefaces
@ -284,12 +272,8 @@ ist
klunky
lable
leve
lief
limite
linke
listner
lokal
lokales
maintainence
maintenace
maintenence
@ -298,7 +282,6 @@ mambers
manaully
manuel
maxium
mehtod
mergable
mesage
messge
@ -308,7 +291,6 @@ minumum
mis
modifers
mor
mot
mulitply
multipl
multple
@ -322,7 +304,7 @@ nin
nodel
nome
noone
nowe
notin
numbe
numer
occured
@ -390,12 +372,9 @@ remaning
remore
remvoing
renabling
repeatly
reponse
reqest
reqiured
requieres
requried
reserv
reserverd
reseted
@ -414,14 +393,13 @@ retuned
returing
rever
rocessor
roperty
runing
runnign
sate
scalled
scipt
scirpt
scrip
seconadry
seconday
seesion
sepcified
@ -434,12 +412,10 @@ settig
sevices
shoul
shoule
sie
signle
simplier
singature
skiping
snaphsot
snpashot
specied
specifed
@ -450,7 +426,6 @@ standy
statics
stickyness
stil
stip
storeage
strat
streched
@ -459,7 +434,6 @@ succesfull
successfull
suceessful
suces
sucessfully
suiteable
suppots
suppport
@ -492,7 +466,6 @@ uncompressible
uneccessarily
unexepected
unexpect
unknow
unkonw
unkown
unneccessary
@ -500,14 +473,12 @@ unparseable
unrecoginized
unsupport
unxpected
updat
uptodate
usera
usign
usin
utlization
vaidate
valiate
valule
valus
varibles
@ -516,8 +487,6 @@ verfying
verifing
virutal
visable
wakup
wil
wit
wll
wth

View File

@ -44,6 +44,6 @@ jobs:
path: ~/.cache/pre-commit
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
- name: Run pre-commit
run: pre-commit run --all-files
run: pre-commit run --color=always --all-files
- name: Run manual pre-commit hooks
run: pre-commit run --all-files --hook-stage manual
run: pre-commit run --color=always --all-files --hook-stage manual

View File

@ -25,6 +25,12 @@ repos:
hooks:
- id: identity
- id: check-hooks-apply
- repo: https://github.com/thlorenz/doctoc.git
rev: v2.2.0
hooks:
- id: doctoc
name: Add TOC for Markdown files
files: ^CONTRIBUTING\.md$|^INSTALL\.md$|^README\.md$
- repo: https://github.com/oxipng/oxipng
rev: v9.1.5
hooks:
@ -41,6 +47,11 @@ repos:
- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.5.5
hooks:
- id: chmod
name: set file permissions
args: ['644']
files: \.md$
stages: [manual]
- id: insert-license
name: add license for all Markdown files
files: \.md$
@ -51,6 +62,44 @@ repos:
- .github/workflows/license-templates/LICENSE.txt
- --fuzzy-match-generates-todo
exclude: ^(CHANGES|ISSUE_TEMPLATE|PULL_REQUEST_TEMPLATE)\.md$|^ui/docs/(full|smoke)-test-plan\.template\.md$
- id: insert-license
name: add license for all Shell files
description: automatically adds a licence header to all Shell files that don't have a license header
files: \.sh$
args:
- --comment-style
- '|#|'
- --license-filepath
- .github/workflows/license-templates/LICENSE.txt
- --fuzzy-match-generates-todo
- id: insert-license
name: add license for all SQL files
files: \.sql$
args:
- --comment-style
- '|--|'
- --license-filepath
- .github/workflows/license-templates/LICENSE.txt
- --fuzzy-match-generates-todo
- id: insert-license
name: add license for all Vue files
files: \.vue$
args:
- --comment-style
- '|//|'
- --license-filepath
- .github/workflows/license-templates/LICENSE.txt
- --fuzzy-match-generates-todo
- id: insert-license
name: add license for all YAML files
description: automatically adds a licence header to all YAML files that don't have a license header
files: \.ya?ml$
args:
- --comment-style
- '|#|'
- --license-filepath
- .github/workflows/license-templates/LICENSE.txt
- --fuzzy-match-generates-todo
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
@ -84,7 +133,7 @@ repos:
^systemvm/agent/certs/realhostip\.key$|
^test/integration/smoke/test_ssl_offloading\.py$
- id: end-of-file-fixer
exclude: \.vhd$
exclude: \.vhd$|\.svg$
- id: file-contents-sorter
args: [--unique]
files: ^\.github/linters/codespell\.txt$
@ -92,11 +141,11 @@ repos:
- id: forbid-submodules
- id: mixed-line-ending
- id: trailing-whitespace
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$
files: ^(LICENSE|NOTICE)$|\.(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
rev: v2.2.6
rev: v2.4.1
hooks:
- id: codespell
name: run codespell
@ -117,14 +166,6 @@ repos:
args: [--config=.github/linters/.markdown-lint.yml]
types: [markdown]
files: \.(md|mdown|markdown)$
- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.5.5
hooks:
- id: chmod
name: set file permissions
args: ['644']
files: \.md$
stages: [manual]
- repo: https://github.com/adrienverge/yamllint
rev: v1.37.1
hooks:

View File

@ -21,6 +21,24 @@
## Summary
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Summary](#summary)
- [Bug fixes](#bug-fixes)
- [Developing new features](#developing-new-features)
- [PendingReleaseNotes file](#pendingreleasenotes-file)
- [Fork the code](#fork-the-code)
- [Making changes](#making-changes)
- [Rebase `feature_x` to include updates from `upstream/main`](#rebase-feature_x-to-include-updates-from-upstreammain)
- [Make a GitHub Pull Request to contribute your changes](#make-a-github-pull-request-to-contribute-your-changes)
- [Cleaning up after a successful pull request](#cleaning-up-after-a-successful-pull-request)
- [Release Principles](#release-principles)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## 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.

View File

@ -26,9 +26,21 @@ or the developer [wiki](https://cwiki.apache.org/confluence/display/CLOUDSTACK/H
Apache CloudStack developers use various platforms for development, this guide
was tested against a CentOS 7 x86_64 setup.
* [Setting up development environment](https://cwiki.apache.org/confluence/display/CLOUDSTACK/Setting+up+CloudStack+Development+Environment) for Apache CloudStack.
* [Building](https://cwiki.apache.org/confluence/display/CLOUDSTACK/How+to+build+CloudStack) Apache CloudStack.
* [Appliance based development](https://github.com/rhtyd/monkeybox)
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Setting up Development Environment](#setting-up-development-environment)
- [Using jenv and/or pyenv for Version Management](#using-jenv-andor-pyenv-for-version-management)
- [Getting the Source Code](#getting-the-source-code)
- [Building](#building)
- [To bring up CloudStack UI](#to-bring-up-cloudstack-ui)
- [Building with non-redistributable plugins](#building-with-non-redistributable-plugins)
- [Packaging and Installation](#packaging-and-installation)
- [Debian/Ubuntu](#debianubuntu)
- [RHEL/CentOS](#rhelcentos)
- [Notes](#notes)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Setting up Development Environment

View File

@ -20,7 +20,7 @@
# pre-commit
We run [pre-commit](https://pre-commit.com/) with
[GitHub Actions](https://github.com/apache/cloudstack/blob/main/.github/workflows/linter.yml) so installation on your
[GitHub Actions](https://github.com/apache/cloudstack/blob/main/.github/workflows/pre-commit.yml) so installation on your
local machine is currently optional.
The `pre-commit` [configuration file](https://github.com/apache/cloudstack/blob/main/.pre-commit-config.yaml)

View File

@ -31,6 +31,24 @@
[![Apache CloudStack](tools/logo/apache_cloudstack.png)](https://cloudstack.apache.org/)
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Who Uses CloudStack?](#who-uses-cloudstack)
- [Demo](#demo)
- [Getting Started](#getting-started)
- [Getting Source Repository](#getting-source-repository)
- [Documentation](#documentation)
- [News and Events](#news-and-events)
- [Getting Involved and Contributing](#getting-involved-and-contributing)
- [Reporting Security Vulnerabilities](#reporting-security-vulnerabilities)
- [License](#license)
- [Notice of Cryptographic Software](#notice-of-cryptographic-software)
- [Star History](#star-history)
- [Contributors](#contributors)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
Apache CloudStack is open source software designed to deploy and manage large
networks of virtual machines, as a highly available, highly scalable
Infrastructure as a Service (IaaS) cloud computing platform. CloudStack is used

View File

@ -0,0 +1,24 @@
# 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.
# Configuration file for UEFI
guest.nvram.template.legacy=@GUESTNVRAMTEMPLATELEGACY@
guest.loader.legacy=@GUESTLOADERLEGACY@
guest.nvram.template.secure=@GUESTNVRAMTEMPLATESECURE@
guest.loader.secure=@GUESTLOADERSECURE@
guest.nvram.path=@GUESTNVRAMPATH@

View File

@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>

View File

@ -1322,7 +1322,6 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
processResponse((Response)request, task.getLink());
} else {
//put the requests from mgt server into another thread pool, as the request may take a longer time to finish. Don't block the NIO main thread pool
//processRequest(request, task.getLink());
requestHandler.submit(new AgentRequestHandler(getType(), getLink(), request));
}
} catch (final ClassNotFoundException e) {
@ -1332,13 +1331,14 @@ public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater
}
} else if (task.getType() == Task.Type.DISCONNECT) {
try {
// an issue has been found if reconnect immediately after disconnecting. please refer to https://github.com/apache/cloudstack/issues/8517
// an issue has been found if reconnect immediately after disconnecting.
// wait 5 seconds before reconnecting
logger.debug("Wait for 5 secs before reconnecting, disconnect task - {}", () -> getLinkLog(task.getLink()));
Thread.sleep(5000);
} catch (InterruptedException e) {
}
shell.setConnectionTransfer(false);
logger.debug("Executing disconnect task - {}", () -> getLinkLog(task.getLink()));
logger.debug("Executing disconnect task - {} and reconnecting", () -> getLinkLog(task.getLink()));
reconnect(task.getLink());
} else if (task.getType() == Task.Type.OTHER) {
processOtherTask(task);

View File

@ -117,7 +117,7 @@ public class AgentProperties{
/**
* Local storage path.<br>
* This property allows multiple values to be entered in a single String. The differente values must be separated by commas.<br>
* This property allows multiple values to be entered in a single String. The different values must be separated by commas.<br>
* Data type: String.<br>
* Default value: <code>/var/lib/libvirt/images/</code>
*/
@ -134,7 +134,7 @@ public class AgentProperties{
/**
* MANDATORY: The UUID for the local storage pool.<br>
* This property allows multiple values to be entered in a single String. The differente values must be separated by commas.<br>
* This property allows multiple values to be entered in a single String. The different values must be separated by commas.<br>
* Data type: String.<br>
* Default value: <code>null</code>
*/

View File

@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>

View File

@ -0,0 +1,182 @@
// 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.agent.api.to;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class VirtualMachineMetadataTO {
// VM details
private final String name;
private final String internalName;
private final String displayName;
private final String instanceUuid;
private final Integer cpuCores;
private final Integer memory;
private final Long created;
private final Long started;
// Owner details
private final String ownerDomainUuid;
private final String ownerDomainName;
private final String ownerAccountUuid;
private final String ownerAccountName;
private final String ownerProjectUuid;
private final String ownerProjectName;
// Host and service offering
private final String serviceOfferingName;
private final List<String> serviceOfferingHostTags;
// zone, pod, and cluster details
private final String zoneName;
private final String zoneUuid;
private final String podName;
private final String podUuid;
private final String clusterName;
private final String clusterUuid;
// resource tags
private final Map<String, String> resourceTags;
public VirtualMachineMetadataTO(
String name, String internalName, String displayName, String instanceUuid, Integer cpuCores, Integer memory, Long created, Long started,
String ownerDomainUuid, String ownerDomainName, String ownerAccountUuid, String ownerAccountName, String ownerProjectUuid, String ownerProjectName,
String serviceOfferingName, List<String> serviceOfferingHostTags,
String zoneName, String zoneUuid, String podName, String podUuid, String clusterName, String clusterUuid, Map<String, String> resourceTags) {
/*
* Something failed in the metadata shall not be a fatal error, the VM can still be started
* Thus, the unknown fields just get an explicit "unknown" value so it can be fixed in case
* there are bugs on some execution paths.
* */
this.name = (name != null) ? name : "unknown";
this.internalName = (internalName != null) ? internalName : "unknown";
this.displayName = (displayName != null) ? displayName : "unknown";
this.instanceUuid = (instanceUuid != null) ? instanceUuid : "unknown";
this.cpuCores = (cpuCores != null) ? cpuCores : -1;
this.memory = (memory != null) ? memory : -1;
this.created = (created != null) ? created : 0;
this.started = (started != null) ? started : 0;
this.ownerDomainUuid = (ownerDomainUuid != null) ? ownerDomainUuid : "unknown";
this.ownerDomainName = (ownerDomainName != null) ? ownerDomainName : "unknown";
this.ownerAccountUuid = (ownerAccountUuid != null) ? ownerAccountUuid : "unknown";
this.ownerAccountName = (ownerAccountName != null) ? ownerAccountName : "unknown";
this.ownerProjectUuid = (ownerProjectUuid != null) ? ownerProjectUuid : "unknown";
this.ownerProjectName = (ownerProjectName != null) ? ownerProjectName : "unknown";
this.serviceOfferingName = (serviceOfferingName != null) ? serviceOfferingName : "unknown";
this.serviceOfferingHostTags = (serviceOfferingHostTags != null) ? serviceOfferingHostTags : new ArrayList<>();
this.zoneName = (zoneName != null) ? zoneName : "unknown";
this.zoneUuid = (zoneUuid != null) ? zoneUuid : "unknown";
this.podName = (podName != null) ? podName : "unknown";
this.podUuid = (podUuid != null) ? podUuid : "unknown";
this.clusterName = (clusterName != null) ? clusterName : "unknown";
this.clusterUuid = (clusterUuid != null) ? clusterUuid : "unknown";
this.resourceTags = (resourceTags != null) ? resourceTags : new HashMap<>();
}
public String getName() {
return name;
}
public String getInternalName() {
return internalName;
}
public String getDisplayName() {
return displayName;
}
public String getInstanceUuid() {
return instanceUuid;
}
public Integer getCpuCores() {
return cpuCores;
}
public Integer getMemory() {
return memory;
}
public Long getCreated() { return created; }
public Long getStarted() {
return started;
}
public String getOwnerDomainUuid() {
return ownerDomainUuid;
}
public String getOwnerDomainName() {
return ownerDomainName;
}
public String getOwnerAccountUuid() {
return ownerAccountUuid;
}
public String getOwnerAccountName() {
return ownerAccountName;
}
public String getOwnerProjectUuid() {
return ownerProjectUuid;
}
public String getOwnerProjectName() {
return ownerProjectName;
}
public String getserviceOfferingName() {
return serviceOfferingName;
}
public List<String> getserviceOfferingHostTags() {
return serviceOfferingHostTags;
}
public String getZoneName() {
return zoneName;
}
public String getZoneUuid() {
return zoneUuid;
}
public String getPodName() {
return podName;
}
public String getPodUuid() {
return podUuid;
}
public String getClusterName() {
return clusterName;
}
public String getClusterUuid() {
return clusterUuid;
}
public Map<String, String> getResourceTags() { return resourceTags; }
}

View File

@ -89,6 +89,7 @@ public class VirtualMachineTO {
private DeployAsIsInfoTO deployAsIsInfo;
private String metadataManufacturer;
private String metadataProductName;
private VirtualMachineMetadataTO metadata;
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) {
@ -494,6 +495,14 @@ public class VirtualMachineTO {
this.metadataProductName = metadataProductName;
}
public VirtualMachineMetadataTO getMetadata() {
return metadata;
}
public void setMetadata(VirtualMachineMetadataTO metadata) {
this.metadata = metadata;
}
@Override
public String toString() {
return String.format("VM {id: \"%s\", name: \"%s\", uuid: \"%s\", type: \"%s\"}", id, name, uuid, type);

View File

@ -36,5 +36,4 @@ public interface HostStats {
public HostStats getHostStats();
public double getLoadAverage();
// public double getXapiMemoryUsageKBs();
}

View File

@ -78,7 +78,7 @@ public class Networks {
}
@Override
public String getValueFrom(URI uri) {
return uri.getAuthority();
return uri == null ? null : uri.getAuthority();
}
},
Vswitch("vs", String.class), LinkLocal(null, null), Vnet("vnet", Long.class), Storage("storage", Integer.class), Lswitch("lswitch", String.class) {
@ -96,7 +96,7 @@ public class Networks {
*/
@Override
public String getValueFrom(URI uri) {
return uri.getSchemeSpecificPart();
return uri == null ? null : uri.getSchemeSpecificPart();
}
},
Mido("mido", String.class), Pvlan("pvlan", String.class),
@ -177,7 +177,7 @@ public class Networks {
* @return the scheme as BroadcastDomainType
*/
public static BroadcastDomainType getSchemeValue(URI uri) {
return toEnumValue(uri.getScheme());
return toEnumValue(uri == null ? null : uri.getScheme());
}
/**
@ -191,7 +191,7 @@ public class Networks {
if (com.cloud.dc.Vlan.UNTAGGED.equalsIgnoreCase(str)) {
return Native;
}
return getSchemeValue(new URI(str));
return getSchemeValue(str == null ? null : new URI(str));
}
/**
@ -220,7 +220,7 @@ public class Networks {
* @return the host part as String
*/
public String getValueFrom(URI uri) {
return uri.getHost();
return uri == null ? null : uri.getHost();
}
/**
@ -243,7 +243,7 @@ public class Networks {
* @throws URISyntaxException the string is not even an uri
*/
public static String getValue(String uriString) throws URISyntaxException {
return getValue(new URI(uriString));
return getValue(uriString == null ? null : new URI(uriString));
}
/**

View File

@ -41,4 +41,6 @@ public interface PhysicalNetworkTrafficType extends InternalIdentity, Identity {
String getHypervNetworkLabel();
String getOvm3NetworkLabel();
String getVlan();
}

View File

@ -108,8 +108,7 @@ public class LbStickinessMethod {
}
public void addParam(String name, Boolean required, String description, Boolean isFlag) {
/* FIXME : UI is breaking if the capability string length is larger , temporarily description is commented out */
// LbStickinessMethodParam param = new LbStickinessMethodParam(name, required, description);
/* is this still a valid comment: FIXME : UI is breaking if the capability string length is larger , temporarily description is commented out */
LbStickinessMethodParam param = new LbStickinessMethodParam(name, required, " ", isFlag);
_paramList.add(param);
return;
@ -133,7 +132,6 @@ public class LbStickinessMethod {
public void setDescription(String description) {
/* FIXME : UI is breaking if the capability string length is larger , temporarily description is commented out */
//this.description = description;
this._description = " ";
}
}

View File

@ -77,6 +77,8 @@ import com.cloud.alert.Alert;
import com.cloud.capacity.Capacity;
import com.cloud.dc.Pod;
import com.cloud.dc.Vlan;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.ManagementServerException;
import com.cloud.exception.ResourceUnavailableException;
@ -97,6 +99,7 @@ import com.cloud.utils.Ternary;
import com.cloud.vm.InstanceGroup;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
/**
* Hopefully this is temporary.
@ -478,6 +481,19 @@ public interface ManagementService {
Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Host, Boolean>> listHostsForMigrationOfVM(VirtualMachine vm, Long startIndex, Long pageSize, String keyword, List<VirtualMachine> vmList);
/**
* Apply affinity group constraints and other exclusion rules for VM migration.
* This is a helper method that can be used independently for per-iteration affinity checks in DRS.
*
* @param vm The virtual machine to migrate
* @param vmProfile The VM profile
* @param plan The deployment plan
* @param vmList List of VMs with current/simulated placements for affinity processing
* @return ExcludeList containing hosts to avoid
*/
ExcludeList applyAffinityConstraints(VirtualMachine vm, VirtualMachineProfile vmProfile,
DeploymentPlan plan, List<VirtualMachine> vmList);
/**
* List storage pools for live migrating of a volume. The API returns list of all pools in the cluster to which the
* volume can be migrated. Current pool is not included in the list. In case of vSphere datastore cluster storage pools,

View File

@ -128,7 +128,7 @@ public class Storage {
public static enum TemplateType {
ROUTING, // Router template
SYSTEM, /* routing, system vm template */
BUILTIN, /* buildin template */
BUILTIN, /* builtin template */
PERHOST, /* every host has this template, don't need to install it in secondary storage */
USER, /* User supplied template/iso */
VNF, /* VNFs (virtual network functions) template */

View File

@ -150,7 +150,7 @@ public class UpdateCfgCmd extends BaseCmd {
ConfigurationResponse response = _responseGenerator.createConfigurationResponse(cfg);
response.setResponseName(getCommandName());
response = setResponseScopes(response);
response = setResponseValue(response, cfg);
setResponseValue(response, cfg);
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update config");
@ -161,15 +161,13 @@ public class UpdateCfgCmd extends BaseCmd {
* Sets the configuration value in the response. If the configuration is in the `Hidden` or `Secure` categories, the value is encrypted before being set in the response.
* @param response to be set with the configuration `cfg` value
* @param cfg to be used in setting the response value
* @return the response with the configuration's value
*/
public ConfigurationResponse setResponseValue(ConfigurationResponse response, Configuration cfg) {
public void setResponseValue(ConfigurationResponse response, Configuration cfg) {
String value = cfg.getValue();
if (cfg.isEncrypted()) {
response.setValue(DBEncryptionUtil.encrypt(getValue()));
} else {
response.setValue(getValue());
value = DBEncryptionUtil.encrypt(value);
}
return response;
response.setValue(value);
}
/**

View File

@ -1,4 +1,4 @@
// Licensedname = "listIsoPermissions", to the Apache Software Foundation (ASF) under one
// 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

View File

@ -34,6 +34,7 @@ import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.utils.StringUtils;
@APICommand(name = "createManagementNetworkIpRange",
description = "Creates a Management network IP range.",
@ -118,7 +119,7 @@ public class CreateManagementNetworkIpRangeCmd extends BaseAsyncCmd {
}
public String getVlan() {
if (vlan == null || vlan.isEmpty()) {
if (StringUtils.isBlank(vlan)) {
vlan = "untagged";
}
return vlan;

View File

@ -153,6 +153,8 @@ public class UpdateStoragePoolCmd extends BaseCmd {
if (ObjectUtils.anyNotNull(name, capacityIops, capacityBytes, url, isTagARule, tags) ||
MapUtils.isNotEmpty(details)) {
result = _storageService.updateStoragePool(this);
} else {
result = _storageService.getStoragePool(getId());
}
if (enabled != null) {

View File

@ -1,4 +1,4 @@
// Licensedname = "listTemplatePermissions", to the Apache Software Foundation (ASF) under one
// 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

View File

@ -26,14 +26,13 @@ import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
import org.apache.cloudstack.api.response.ProviderResponse;
import org.apache.cloudstack.api.response.TrafficTypeResponse;
import com.cloud.network.PhysicalNetworkTrafficType;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
@APICommand(name = "listTrafficTypes", description = "Lists traffic types of a given physical network.", responseObject = ProviderResponse.class, since = "3.0.0",
@APICommand(name = "listTrafficTypes", description = "Lists traffic types of a given physical network.", responseObject = TrafficTypeResponse.class, since = "3.0.0",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListTrafficTypesCmd extends BaseListCmd {

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command.admin.vlan;
import com.cloud.configuration.ConfigurationService;
import com.cloud.network.Network;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.StringUtils;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
@ -163,7 +164,7 @@ public class CreateVlanIpRangeCmd extends BaseCmd {
}
public String getVlan() {
if ((vlan == null || vlan.isEmpty()) && !ConfigurationService.IsIpRangeForProvider(getProvider())) {
if (StringUtils.isBlank(vlan) && !ConfigurationService.IsIpRangeForProvider(getProvider())) {
vlan = "untagged";
}
return vlan;

View File

@ -53,7 +53,7 @@ public class ListPublicIpAddressesCmd extends BaseListRetrieveOnlyResourceCountC
@Parameter(name = ApiConstants.ALLOCATED_ONLY, type = CommandType.BOOLEAN, description = "limits search results to allocated public IP addresses")
private Boolean allocatedOnly;
@Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "lists all public IP addresses by state")
@Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "lists all public IP addresses by state. A comma-separated list of states can be passed")
private String state;
@Parameter(name = ApiConstants.FOR_VIRTUAL_NETWORK, type = CommandType.BOOLEAN, description = "the virtual network for the IP address")

View File

@ -1,4 +1,4 @@
// Licensedname = "listIsoPermissions", to the Apache Software Foundation (ASF) under one
// 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

View File

@ -63,7 +63,7 @@ public class UpdateLBHealthCheckPolicyCmd extends BaseAsyncCustomIdCmd{
@Override
public String getEventDescription() {
return "Update load balancer health check policy ID= " + id;
return "Update load balancer health check policy ID = " + id;
}
@Override

View File

@ -62,7 +62,7 @@ public class UpdateLBStickinessPolicyCmd extends BaseAsyncCustomIdCmd{
@Override
public String getEventDescription() {
return "Update load balancer stickiness policy ID= " + id;
return "Update load balancer stickiness policy ID = " + id;
}
@Override

View File

@ -1,4 +1,4 @@
// Licensedname = "listTemplatePermissions", to the Apache Software Foundation (ASF) under one
// 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

View File

@ -66,7 +66,7 @@ public class UpdateVpnConnectionCmd extends BaseAsyncCustomIdCmd {
@Override
public String getEventDescription() {
return "Updating site-to-site VPN connection id= " + id;
return "Updating site-to-site VPN connection ID = " + id;
}
@Override

View File

@ -63,7 +63,7 @@ public class UpdateVpnGatewayCmd extends BaseAsyncCustomIdCmd {
@Override
public String getEventDescription() {
return "Update site-to-site VPN gateway id= " + id;
return "Update site-to-site VPN gateway ID = " + id;
}
@Override

View File

@ -27,8 +27,6 @@ import org.apache.cloudstack.api.EntityReference;
import org.apache.cloudstack.network.tls.SslCert;
import com.cloud.serializer.Param;
//import org.apache.cloudstack.api.EntityReference;
@EntityReference(value = SslCert.class)
public class SslCertResponse extends BaseResponse {

View File

@ -56,6 +56,14 @@ public class TrafficTypeResponse extends BaseResponse {
@Param(description = "The network name label of the physical device dedicated to this traffic on a HyperV host")
private String hypervNetworkLabel;
@SerializedName(ApiConstants.VLAN)
@Param(description = "The VLAN id to be used for Management traffic by VMware host")
private String vlan;
@SerializedName(ApiConstants.ISOLATION_METHODS)
@Param(description = "isolation methods for the physical network traffic")
private String isolationMethods;
@SerializedName(ApiConstants.OVM3_NETWORK_LABEL)
@Param(description = "The network name of the physical device dedicated to this traffic on an OVM3 host")
private String ovm3NetworkLabel;
@ -128,4 +136,20 @@ public class TrafficTypeResponse extends BaseResponse {
public void setOvm3Label(String ovm3Label) {
this.ovm3NetworkLabel = ovm3Label;
}
public String getIsolationMethods() {
return isolationMethods;
}
public void setIsolationMethods(String isolationMethods) {
this.isolationMethods = isolationMethods;
}
public String getVlan() {
return vlan;
}
public void setVlan(String vlan) {
this.vlan = vlan;
}
}

View File

@ -124,6 +124,10 @@ public interface BackupProvider {
*/
boolean supportsInstanceFromBackup();
default boolean supportsMemoryVmSnapshot() {
return true;
}
/**
* Returns the backup storage usage (Used, Total) for a backup provider
* @param zoneId the zone for which to return metrics

View File

@ -34,4 +34,11 @@ public interface BackupService {
* @return backup provider
*/
BackupProvider getBackupProvider(final Long zoneId);
/**
* Find backup provider by name
* @param name backup provider name
* @return backup provider
*/
BackupProvider getBackupProvider(final String name);
}

View File

@ -22,10 +22,10 @@ package org.apache.cloudstack.cluster;
import com.cloud.host.Host;
import com.cloud.offering.ServiceOffering;
import com.cloud.org.Cluster;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.Adapter;
import com.cloud.vm.VirtualMachine;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.math3.stat.descriptive.moment.Mean;
import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation;
@ -40,6 +40,9 @@ import static org.apache.cloudstack.cluster.ClusterDrsService.ClusterDrsMetricUs
public interface ClusterDrsAlgorithm extends Adapter {
Mean MEAN_CALCULATOR = new Mean();
StandardDeviation STDDEV_CALCULATOR = new StandardDeviation(false);
/**
* Determines whether a DRS operation is needed for a given cluster and host-VM
* mapping.
@ -59,79 +62,121 @@ public interface ClusterDrsAlgorithm extends Adapter {
boolean needsDrs(Cluster cluster, List<Ternary<Long, Long, Long>> cpuList,
List<Ternary<Long, Long, Long>> memoryList) throws ConfigurationException;
/**
* Determines the metrics for a given virtual machine and destination host in a DRS cluster.
*
* @param clusterId
* the ID of the cluster to check
* @param vm
* the virtual machine to check
* @param serviceOffering
* the service offering for the virtual machine
* @param destHost
* the destination host for the virtual machine
* @param hostCpuMap
* a map of host IDs to the Ternary of used, reserved and total CPU on each host
* @param hostMemoryMap
* a map of host IDs to the Ternary of used, reserved and total memory on each host
* @param requiresStorageMotion
* whether storage motion is required for the virtual machine
* Calculates the metrics (improvement, cost, benefit) for migrating a VM to a destination host. Improvement is
* calculated based on the change in cluster imbalance before and after the migration.
*
* @param cluster the cluster to check
* @param vm the virtual machine to check
* @param serviceOffering the service offering for the virtual machine
* @param destHost the destination host for the virtual machine
* @param hostCpuMap a map of host IDs to the Ternary of used, reserved and total CPU on each host
* @param hostMemoryMap a map of host IDs to the Ternary of used, reserved and total memory on each host
* @param requiresStorageMotion whether storage motion is required for the virtual machine
* @param preImbalance the pre-calculated cluster imbalance before migration (null to calculate it)
* @param baseMetricsArray pre-calculated array of all host metrics before migration
* @param hostIdToIndexMap mapping from host ID to index in the metrics array
* @return a ternary containing improvement, cost, benefit
*/
Ternary<Double, Double, Double> getMetrics(Cluster cluster, VirtualMachine vm, ServiceOffering serviceOffering,
Host destHost, Map<Long, Ternary<Long, Long, Long>> hostCpuMap,
Map<Long, Ternary<Long, Long, Long>> hostMemoryMap,
Boolean requiresStorageMotion) throws ConfigurationException;
Boolean requiresStorageMotion, Double preImbalance,
double[] baseMetricsArray, Map<Long, Integer> hostIdToIndexMap) throws ConfigurationException;
/**
* Calculates the imbalance of the cluster after a virtual machine migration.
* Calculates the cluster imbalance after migrating a VM to a destination host.
*
* @param serviceOffering
* the service offering for the virtual machine
* @param vm
* the virtual machine being migrated
* @param destHost
* the destination host for the virtual machine
* @param hostCpuMap
* a map of host IDs to the Ternary of used, reserved and total CPU on each host
* @param hostMemoryMap
* a map of host IDs to the Ternary of used, reserved and total memory on each host
*
* @return a pair containing the CPU and memory imbalance of the cluster after the migration
* @param vm the virtual machine being migrated
* @param destHost the destination host for the virtual machine
* @param clusterId the cluster ID
* @param vmMetric the VM's resource consumption metric
* @param baseMetricsArray pre-calculated array of all host metrics before migration
* @param hostIdToIndexMap mapping from host ID to index in the metrics array
* @return the cluster imbalance after migration
*/
default Double getImbalancePostMigration(ServiceOffering serviceOffering, VirtualMachine vm,
Host destHost, Map<Long, Ternary<Long, Long, Long>> hostCpuMap,
Map<Long, Ternary<Long, Long, Long>> hostMemoryMap) throws ConfigurationException {
Pair<Long, Map<Long, Ternary<Long, Long, Long>>> pair = getHostMetricsMapAndType(destHost.getClusterId(), serviceOffering, hostCpuMap, hostMemoryMap);
long vmMetric = pair.first();
Map<Long, Ternary<Long, Long, Long>> hostMetricsMap = pair.second();
default Double getImbalancePostMigration(VirtualMachine vm,
Host destHost, Long clusterId, long vmMetric, double[] baseMetricsArray,
Map<Long, Integer> hostIdToIndexMap, Map<Long, Ternary<Long, Long, Long>> hostCpuMap,
Map<Long, Ternary<Long, Long, Long>> hostMemoryMap) {
// Create a copy of the base array and adjust only the two affected hosts
double[] adjustedMetrics = new double[baseMetricsArray.length];
System.arraycopy(baseMetricsArray, 0, adjustedMetrics, 0, baseMetricsArray.length);
List<Double> list = new ArrayList<>();
for (Long hostId : hostMetricsMap.keySet()) {
list.add(getMetricValuePostMigration(destHost.getClusterId(), hostMetricsMap.get(hostId), vmMetric, hostId, destHost.getId(), vm.getHostId()));
long destHostId = destHost.getId();
long vmHostId = vm.getHostId();
// Adjust source host (remove VM resources)
Integer sourceIndex = hostIdToIndexMap.get(vmHostId);
if (sourceIndex != null && sourceIndex < adjustedMetrics.length) {
Map<Long, Ternary<Long, Long, Long>> sourceMetricsMap = getClusterDrsMetric(clusterId).equals("cpu") ? hostCpuMap : hostMemoryMap;
Ternary<Long, Long, Long> sourceMetrics = sourceMetricsMap.get(vmHostId);
if (sourceMetrics != null) {
adjustedMetrics[sourceIndex] = getMetricValuePostMigration(clusterId, sourceMetrics, vmMetric, vmHostId, destHostId, vmHostId);
}
return getImbalance(list);
}
private Pair<Long, Map<Long, Ternary<Long, Long, Long>>> getHostMetricsMapAndType(Long clusterId,
ServiceOffering serviceOffering, Map<Long, Ternary<Long, Long, Long>> hostCpuMap,
Map<Long, Ternary<Long, Long, Long>> hostMemoryMap) throws ConfigurationException {
// Adjust destination host (add VM resources)
Integer destIndex = hostIdToIndexMap.get(destHostId);
if (destIndex != null && destIndex < adjustedMetrics.length) {
Map<Long, Ternary<Long, Long, Long>> destMetricsMap = getClusterDrsMetric(clusterId).equals("cpu") ? hostCpuMap : hostMemoryMap;
Ternary<Long, Long, Long> destMetrics = destMetricsMap.get(destHostId);
if (destMetrics != null) {
adjustedMetrics[destIndex] = getMetricValuePostMigration(clusterId, destMetrics, vmMetric, destHostId, destHostId, vmHostId);
}
}
return calculateImbalance(adjustedMetrics);
}
/**
* Calculate imbalance from an array of metric values.
* Imbalance is defined as standard deviation divided by mean.
*
* Uses reusable stateless calculator objects to avoid object creation overhead.
* @param values array of metric values
* @return calculated imbalance
*/
private static double calculateImbalance(double[] values) {
if (values == null || values.length == 0) {
return 0.0;
}
double mean = MEAN_CALCULATOR.evaluate(values);
if (mean == 0.0) {
return 0.0; // Avoid division by zero
}
double stdDev = STDDEV_CALCULATOR.evaluate(values, mean);
return stdDev / mean;
}
/**
* Helper method to get VM metric based on cluster configuration.
*/
static long getVmMetric(ServiceOffering serviceOffering, Long clusterId) throws ConfigurationException {
String metric = getClusterDrsMetric(clusterId);
Pair<Long, Map<Long, Ternary<Long, Long, Long>>> pair;
switch (metric) {
case "cpu":
pair = new Pair<>((long) serviceOffering.getCpu() * serviceOffering.getSpeed(), hostCpuMap);
break;
return (long) serviceOffering.getCpu() * serviceOffering.getSpeed();
case "memory":
pair = new Pair<>(serviceOffering.getRamSize() * 1024L * 1024L, hostMemoryMap);
break;
return serviceOffering.getRamSize() * 1024L * 1024L;
default:
throw new ConfigurationException(
String.format("Invalid metric: %s for cluster: %d", metric, clusterId));
}
return pair;
}
/**
* Helper method to calculate metrics from pre and post imbalance values.
*/
default Ternary<Double, Double, Double> calculateMetricsFromImbalances(Double preImbalance, Double postImbalance) {
// This needs more research to determine the cost and benefit of a migration
// TODO: Cost should be a factor of the VM size and the host capacity
// TODO: Benefit should be a factor of the VM size and the host capacity and the number of VMs on the host
final double improvement = preImbalance - postImbalance;
final double cost = 0.0;
final double benefit = 1.0;
return new Ternary<>(improvement, cost, benefit);
}
private Double getMetricValuePostMigration(Long clusterId, Ternary<Long, Long, Long> metrics, long vmMetric,
@ -151,9 +196,26 @@ public interface ClusterDrsAlgorithm extends Adapter {
}
private static Double getImbalance(List<Double> metricList) {
Double clusterMeanMetric = getClusterMeanMetric(metricList);
Double clusterStandardDeviation = getClusterStandardDeviation(metricList, clusterMeanMetric);
return clusterStandardDeviation / clusterMeanMetric;
if (CollectionUtils.isEmpty(metricList)) {
return 0.0;
}
// Convert List<Double> to double[] once, avoiding repeated conversions
double[] values = new double[metricList.size()];
int index = 0;
for (Double value : metricList) {
if (value != null) {
values[index++] = value;
}
}
// Trim array if some values were null
if (index < values.length) {
double[] trimmed = new double[index];
System.arraycopy(values, 0, trimmed, 0, index);
values = trimmed;
}
return calculateImbalance(values);
}
static String getClusterDrsMetric(long clusterId) {
@ -181,36 +243,6 @@ public interface ClusterDrsAlgorithm extends Adapter {
return null;
}
/**
* Mean is the average of a collection or set of metrics. In context of a DRS
* cluster, the cluster metrics defined as the average metrics value for some
* metric (such as CPU, memory etc.) for every resource such as host.
* Cluster Mean Metric, mavg = (mi) / N, where mi is a measurable metric for a
* resource i in a cluster with total N number of resources.
*/
static Double getClusterMeanMetric(List<Double> metricList) {
return new Mean().evaluate(metricList.stream().mapToDouble(i -> i).toArray());
}
/**
* Standard deviation is defined as the square root of the absolute squared sum
* of difference of a metric from its mean for every resource divided by the
* total number of resources. In context of the DRS, the cluster standard
* deviation is the standard deviation based on a metric of resources in a
* cluster such as for the allocation or utilisation CPU/memory metric of hosts
* in a cluster.
* Cluster Standard Deviation, σc = sqrt((mimavg^2) / N), where mavg is the
* mean metric value and mi is a measurable metric for some resource i in the
* cluster with total N number of resources.
*/
static Double getClusterStandardDeviation(List<Double> metricList, Double mean) {
if (mean != null) {
return new StandardDeviation(false).evaluate(metricList.stream().mapToDouble(i -> i).toArray(), mean);
} else {
return new StandardDeviation(false).evaluate(metricList.stream().mapToDouble(i -> i).toArray());
}
}
static boolean getDrsMetricUseRatio(long clusterId) {
return ClusterDrsMetricUseRatio.valueIn(clusterId);
}

View File

@ -16,10 +16,15 @@
// under the License.
package org.apache.cloudstack.config;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ApiServiceConfiguration implements Configurable {
protected static Logger LOGGER = LogManager.getLogger(ApiServiceConfiguration.class);
public static final ConfigKey<String> ManagementServerAddresses = new ConfigKey<>(String.class, "host", "Advanced", "localhost", "The ip address of management server. This can also accept comma separated addresses.", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
public static final ConfigKey<String> ApiServletPath = new ConfigKey<String>("Advanced", String.class, "endpoint.url", "http://localhost:8080/client/api",
"API end point. Can be used by CS components/services deployed remotely, for sending CS API requests", true);
@ -29,6 +34,20 @@ public class ApiServiceConfiguration implements Configurable {
"true", "Are the source checks on API calls enabled (true) or not (false)? See api.allowed.source.cidr.list", true, ConfigKey.Scope.Global);
public static final ConfigKey<String> ApiAllowedSourceCidrList = new ConfigKey<>(String.class, "api.allowed.source.cidr.list", "Advanced",
"0.0.0.0/0,::/0", "Comma separated list of IPv4/IPv6 CIDRs from which API calls can be performed. Can be set on Global and Account levels.", true, ConfigKey.Scope.Account, null, null, null, null, null, ConfigKey.Kind.CSV, null);
public static void validateEndpointUrl() {
String csUrl = getApiServletPathValue();
if (StringUtils.isBlank(csUrl) || StringUtils.containsAny(csUrl, "localhost", "127.0.0.1", "[::1]")) {
LOGGER.error("Global setting [{}] cannot contain localhost or be blank. Current value: {}", ApiServletPath.key(), csUrl);
throw new InvalidParameterValueException("Unable to complete this operation. Contact your cloud admin.");
}
}
public static String getApiServletPathValue() {
return ApiServletPath.value();
}
@Override
public String getConfigComponentName() {
return ApiServiceConfiguration.class.getSimpleName();

View File

@ -37,6 +37,24 @@ public class NetworksTest {
public void setUp() {
}
@Test
public void nullBroadcastDomainTypeTest() throws URISyntaxException {
BroadcastDomainType type = BroadcastDomainType.getTypeOf(null);
Assert.assertEquals("a null uri should mean a broadcasttype of undecided", BroadcastDomainType.UnDecided, type);
}
@Test
public void nullBroadcastDomainTypeValueTest() {
URI uri = null;
Assert.assertNull(BroadcastDomainType.getValue(uri));
}
@Test
public void nullBroadcastDomainTypeStringValueTest() throws URISyntaxException {
String uriString = null;
Assert.assertNull(BroadcastDomainType.getValue(uriString));
}
@Test
public void emptyBroadcastDomainTypeTest() throws URISyntaxException {
BroadcastDomainType type = BroadcastDomainType.getTypeOf("");

View File

@ -0,0 +1,81 @@
// 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.config;
import org.apache.cloudstack.api.response.ConfigurationResponse;
import org.apache.cloudstack.config.Configuration;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.utils.crypt.DBEncryptionUtil;
@RunWith(MockitoJUnitRunner.class)
public class UpdateCfgCmdTest {
private UpdateCfgCmd updateCfgCmd;
private MockedStatic<DBEncryptionUtil> mockedStatic;
@Before
public void setUp() {
updateCfgCmd = new UpdateCfgCmd();
mockedStatic = Mockito.mockStatic(DBEncryptionUtil.class);
}
@After
public void tearDown() {
mockedStatic.close();
}
@Test
public void setResponseValueSetsEncryptedValueWhenConfigurationIsEncrypted() {
ConfigurationResponse response = new ConfigurationResponse();
Configuration cfg = Mockito.mock(Configuration.class);
Mockito.when(cfg.isEncrypted()).thenReturn(true);
Mockito.when(cfg.getValue()).thenReturn("testValue");
Mockito.when(DBEncryptionUtil.encrypt("testValue")).thenReturn("encryptedValue");
updateCfgCmd.setResponseValue(response, cfg);
Assert.assertEquals("encryptedValue", response.getValue());
}
@Test
public void setResponseValueSetsPlainValueWhenConfigurationIsNotEncrypted() {
ConfigurationResponse response = new ConfigurationResponse();
Configuration cfg = Mockito.mock(Configuration.class);
Mockito.when(cfg.isEncrypted()).thenReturn(false);
Mockito.when(cfg.getValue()).thenReturn("testValue");
updateCfgCmd.setResponseValue(response, cfg);
Assert.assertEquals("testValue", response.getValue());
}
@Test
public void setResponseValueHandlesNullConfigurationValueGracefully() {
ConfigurationResponse response = new ConfigurationResponse();
Configuration cfg = Mockito.mock(Configuration.class);
Mockito.when(cfg.isEncrypted()).thenReturn(false);
Mockito.when(cfg.getValue()).thenReturn(null);
updateCfgCmd.setResponseValue(response, cfg);
Assert.assertNull(response.getValue());
}
}

View File

@ -78,10 +78,6 @@ public class ScaleVMCmdTest extends TestCase {
scaleVMCmd._responseGenerator = responseGenerator;
UserVmResponse userVmResponse = Mockito.mock(UserVmResponse.class);
//List<UserVmResponse> list = Mockito.mock(UserVmResponse.class);
//list.add(userVmResponse);
//LinkedList<UserVmResponse> mockedList = Mockito.mock(LinkedList.class);
//Mockito.when(mockedList.get(0)).thenReturn(userVmResponse);
List<UserVmResponse> list = new LinkedList<UserVmResponse>();
list.add(userVmResponse);

View File

@ -0,0 +1,95 @@
// 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.config;
import com.cloud.exception.InvalidParameterValueException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ApiServiceConfigurationTest {
private static final String LOCALHOST = "http://localhost";
private static final String ENDPOINT_URL = "https://acs.clouds.com/client/api";
private static final String WHITE_SPACE = " ";
private static final String BLANK_STRING = "";
private static final String NULL_STRING = null;
private static final String LOCALHOST_IP = "127.0.0.1";
@Test(expected = InvalidParameterValueException.class)
public void validateEndpointUrlTestIfEndpointUrlContainLocalhostShouldThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(LOCALHOST);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
@Test
public void validateEndpointUrlTestIfEndpointUrlContainLocalhostShouldNotThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(ENDPOINT_URL);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
@Test(expected = InvalidParameterValueException.class)
public void validateEndpointUrlTestIfEndpointUrlIsNullShouldThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(NULL_STRING);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
@Test(expected = InvalidParameterValueException.class)
public void validateEndpointUrlTestIfEndpointUrlIsBlankShouldThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(BLANK_STRING);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
@Test(expected = InvalidParameterValueException.class)
public void validateEndpointUrlTestIfEndpointUrlIsWhiteSpaceShouldThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(WHITE_SPACE);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
@Test(expected = InvalidParameterValueException.class)
public void validateEndpointUrlTestIfEndpointUrlContainLocalhostIpShouldThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(LOCALHOST_IP);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
}

View File

@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>

View File

@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>

View File

@ -629,9 +629,6 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator {
}
}
result.addAll(gSection);
// TODO decide under what circumstances these options are needed
// result.add("\tnokqueue");
// result.add("\tnopoll");
result.add(blankLine);
final List<String> dSection = Arrays.asList(defaultsSection);

View File

@ -417,8 +417,6 @@ public class VirtualRoutingResourceTest implements VirtualRouterDeployer {
// FIXME Check the json content
assertEquals(VRScripts.UPDATE_CONFIG, script);
assertEquals(VRScripts.NETWORK_ACL_CONFIG, args);
// assertEquals(args, " -d eth3 -M 01:23:45:67:89:AB -i 192.168.1.1 -m 24 -a Egress:ALL:0:0:192.168.0.1/24-192.168.0.2/24:ACCEPT:," +
// "Ingress:ICMP:0:0:192.168.0.1/24-192.168.0.2/24:DROP:,Ingress:TCP:20:80:192.168.0.1/24-192.168.0.2/24:ACCEPT:,");
break;
case 2:
assertEquals(VRScripts.UPDATE_CONFIG, script);
@ -464,8 +462,6 @@ public class VirtualRoutingResourceTest implements VirtualRouterDeployer {
private void verifyArgs(final SetupGuestNetworkCommand cmd, final String script, final String args) {
// TODO Check the contents of the json file
//assertEquals(script, VRScripts.VPC_GUEST_NETWORK);
//assertEquals(args, " -C -M 01:23:45:67:89:AB -d eth4 -i 10.1.1.2 -g 10.1.1.1 -m 24 -n 10.1.1.0 -s 8.8.8.8,8.8.4.4 -e cloud.test");
}
@Test

8
debian/changelog vendored
View File

@ -1,12 +1,12 @@
cloudstack (4.22.0.0) unstable; urgency=low
cloudstack (4.23.0.0-SNAPSHOT) unstable; urgency=low
* Update the version to 4.22.0.0
* Update the version to 4.23.0.0-SNAPSHOT
-- the Apache CloudStack project <dev@cloudstack.apache.org> Thu, 30 Oct 2025 19:23:55 +0530
cloudstack (4.22.0.0-SNAPSHOT) unstable; urgency=low
cloudstack (4.23.0.0-SNAPSHOT-SNAPSHOT) unstable; urgency=low
* Update the version to 4.22.0.0-SNAPSHOT
* Update the version to 4.23.0.0-SNAPSHOT-SNAPSHOT
-- the Apache CloudStack project <dev@cloudstack.apache.org> Thu, Aug 28 11:58:36 2025 +0530

View File

@ -16,6 +16,7 @@
# under the License.
/etc/cloudstack/agent/agent.properties
/etc/cloudstack/agent/uefi.properties
/etc/cloudstack/agent/environment.properties
/etc/cloudstack/agent/log4j-cloud.xml
/etc/default/cloudstack-agent

View File

@ -23,7 +23,7 @@ case "$1" in
configure)
OLDCONFDIR="/etc/cloud/agent"
NEWCONFDIR="/etc/cloudstack/agent"
CONFFILES="agent.properties log4j.xml log4j-cloud.xml"
CONFFILES="agent.properties uefi.properties log4j.xml log4j-cloud.xml"
mkdir -m 0755 -p /usr/share/cloudstack-agent/tmp

2
debian/control vendored
View File

@ -24,7 +24,7 @@ Description: CloudStack server library
Package: cloudstack-agent
Architecture: all
Depends: ${python:Depends}, ${python3:Depends}, openjdk-17-jre-headless | java17-runtime-headless | java17-runtime | zulu-17, cloudstack-common (= ${source:Version}), lsb-base (>= 9), openssh-client, qemu-kvm (>= 2.5) | qemu-system-x86 (>= 5.2), libvirt-bin (>= 1.3) | libvirt-daemon-system (>= 3.0), iproute2, ebtables, vlan, ipset, python3-libvirt, ethtool, iptables, cryptsetup, rng-tools, rsync, lsb-release, ufw, apparmor, cpu-checker, libvirt-daemon-driver-storage-rbd, sysstat
Depends: ${python:Depends}, ${python3:Depends}, openjdk-17-jre-headless | java17-runtime-headless | java17-runtime | zulu-17, cloudstack-common (= ${source:Version}), lsb-base (>= 9), openssh-client, qemu-kvm (>= 2.5) | qemu-system-x86 (>= 5.2), libvirt-bin (>= 1.3) | libvirt-daemon-system (>= 3.0), iproute2, ebtables, vlan, ipset, python3-libvirt, ethtool, iptables, cryptsetup, rng-tools, rsync, ovmf, swtpm, lsb-release, ufw, apparmor, cpu-checker, libvirt-daemon-driver-storage-rbd, sysstat
Recommends: init-system-helpers
Conflicts: cloud-agent, cloud-agent-libs, cloud-agent-deps, cloud-agent-scripts
Description: CloudStack agent

View File

@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>

View File

@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>

View File

@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>

View File

@ -94,6 +94,14 @@ public class UsageEventUtils {
}
public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId,
Long size, String entityType, String entityUUID, Long vmId, boolean displayResource) {
if (displayResource) {
saveUsageEvent(usageType, accountId, zoneId, resourceId, offeringId, templateId, size, vmId, resourceName);
}
publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID);
}
public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId,
Long size, Long virtualSize, String entityType, String entityUUID, Map<String, String> details) {
saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, size, virtualSize, details);
@ -202,6 +210,10 @@ public class UsageEventUtils {
s_usageEventDao.persist(new UsageEventVO(usageType, accountId, zoneId, vmId, securityGroupId));
}
public static void saveUsageEvent(String usageType, long accountId, long zoneId, long resourceId, Long offeringId, Long templateId, Long size, Long vmId, String resourceName) {
s_usageEventDao.persist(new UsageEventVO(usageType, accountId, zoneId, resourceId, offeringId, templateId, size, vmId, resourceName));
}
private static void publishUsageEvent(String usageEventType, Long accountId, Long zoneId, String resourceType, String resourceUUID) {
String configKey = "publish.usage.events";
String value = s_configDao.getValue(configKey);

View File

@ -230,7 +230,7 @@ public interface StorageManager extends StorageService {
/**
* should we execute in sequence not involving any storages?
* @return tru if commands should execute in sequence
* @return true if commands should execute in sequence
*/
static boolean shouldExecuteInSequenceOnVmware() {
return shouldExecuteInSequenceOnVmware(null, null);

View File

@ -61,7 +61,6 @@ public class VmWorkSerializer {
// use java binary serialization instead
//
return JobSerializerHelper.toObjectSerializedString(work);
// return s_gson.toJson(work);
}
public static <T extends VmWork> T deserialize(Class<?> clazz, String workInJsonText) {
@ -69,6 +68,5 @@ public class VmWorkSerializer {
// use java binary serialization instead
//
return (T)JobSerializerHelper.fromObjectSerializedString(workInJsonText);
// return (T)s_gson.fromJson(workInJsonText, clazz);
}
}

View File

@ -42,7 +42,7 @@ public interface VMSnapshotManager extends VMSnapshotService, Manager {
boolean deleteAllVMSnapshots(long id, VMSnapshot.Type type);
/**
* Sync VM snapshot state when VM snapshot in reverting or snapshoting or expunging state
* Sync VM snapshot state when VM snapshot in reverting or snapshotting or expunging state
* Used for fullsync after agent connects
*
* @param vm, the VM in question

View File

@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>

View File

@ -1652,7 +1652,6 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
final String reason = shutdown.getReason();
logger.info("Host {} has informed us that it is shutting down with reason {} and detail {}", attache, reason, shutdown.getDetail());
if (reason.equals(ShutdownCommand.Update)) {
// disconnectWithoutInvestigation(attache, Event.UpdateNeeded);
throw new CloudRuntimeException("Agent update not implemented");
} else if (reason.equals(ShutdownCommand.Requested)) {
disconnectWithoutInvestigation(attache, Event.ShutdownRequested);
@ -1753,7 +1752,6 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl
}
} catch (final UnsupportedVersionException e) {
logger.warn(e.getMessage());
// upgradeAgent(task.getLink(), data, e.getReason());
} catch (final ClassNotFoundException e) {
final String message = String.format("Exception occurred when executing tasks! Error '%s'", e.getMessage());
logger.error(message);

View File

@ -965,7 +965,6 @@ public class ClusteredAgentManagerImpl extends AgentManagerImpl implements Clust
synchronized (_agentToTransferIds) {
if (!_agentToTransferIds.isEmpty()) {
logger.debug("Found {} agents to transfer", _agentToTransferIds.size());
// for (Long hostId : _agentToTransferIds) {
for (final Iterator<Long> iterator = _agentToTransferIds.iterator(); iterator.hasNext(); ) {
final Long hostId = iterator.next();
final AgentAttache attache = findAttache(hostId);

View File

@ -213,7 +213,6 @@ public class EngineHostDaoImpl extends GenericDaoBase<EngineHostVO, Long> implem
SequenceSearch = createSearchBuilder();
SequenceSearch.and("id", SequenceSearch.entity().getId(), SearchCriteria.Op.EQ);
// SequenceSearch.addRetrieve("sequence", SequenceSearch.entity().getSequence());
SequenceSearch.done();
DirectlyConnectedSearch = createSearchBuilder();

View File

@ -903,7 +903,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
// Save usage event and update resource count for user vm volumes
if (vm.getType() == VirtualMachine.Type.User) {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size,
Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume());
Volume.class.getName(), vol.getUuid(), vol.getInstanceId(), vol.isDisplayVolume());
_resourceLimitMgr.incrementVolumeResourceCount(vm.getAccountId(), vol.isDisplayVolume(), vol.getSize(), offering);
}
DiskProfile diskProfile = toDiskProfile(vol, offering);
@ -981,7 +981,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
}
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offeringId, vol.getTemplateId(), size,
Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume());
Volume.class.getName(), vol.getUuid(), vol.getInstanceId(), vol.isDisplayVolume());
_resourceLimitMgr.incrementVolumeResourceCount(vm.getAccountId(), vol.isDisplayVolume(), vol.getSize(), offering);
}
@ -1583,12 +1583,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
vm.addDisk(disk);
}
//if (vm.getType() == VirtualMachine.Type.User && vm.getTemplate().getFormat() == ImageFormat.ISO) {
if (vm.getType() == VirtualMachine.Type.User) {
_tmpltMgr.prepareIsoForVmProfile(vm, dest);
//DataTO dataTO = tmplFactory.getTemplate(vm.getTemplate().getId(), DataStoreRole.Image, vm.getVirtualMachine().getDataCenterId()).getTO();
//DiskTO iso = new DiskTO(dataTO, 3L, null, Volume.Type.ISO);
//vm.addDisk(iso);
}
}

View File

@ -140,20 +140,12 @@ public class ProvisioningServiceImpl implements ProvisioningService {
@Override
public List<PodEntity> listPods() {
/*
* Not in use now, just commented out.
*/
//List<PodEntity> pods = new ArrayList<PodEntity>();
//pods.add(new PodEntityImpl("pod-uuid-1", "pod1"));
//pods.add(new PodEntityImpl("pod-uuid-2", "pod2"));
return null;
}
@Override
public List<ZoneEntity> listZones() {
List<ZoneEntity> zones = new ArrayList<ZoneEntity>();
//zones.add(new ZoneEntityImpl("zone-uuid-1"));
//zones.add(new ZoneEntityImpl("zone-uuid-2"));
return zones;
}

View File

@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<build>

View File

@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>

View File

@ -36,7 +36,6 @@ public class ClusterVSMMapDaoImpl extends GenericDaoBase<ClusterVSMMapVO, Long>
final SearchBuilder<ClusterVSMMapVO> VsmSearch;
public ClusterVSMMapDaoImpl() {
//super();
ClusterSearch = createSearchBuilder();
ClusterSearch.and("clusterId", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ);
@ -82,8 +81,6 @@ public class ClusterVSMMapDaoImpl extends GenericDaoBase<ClusterVSMMapVO, Long>
TransactionLegacy txn = TransactionLegacy.currentTxn();
txn.start();
ClusterVSMMapVO cluster = createForUpdate();
//cluster.setClusterId(null);
//cluster.setVsmId(null);
update(id, cluster);

View File

@ -75,6 +75,9 @@ public class UsageEventVO implements UsageEvent {
@Column(name = "virtual_size")
private Long virtualSize;
@Column(name = "vm_id")
private Long vmId;
public UsageEventVO() {
}
@ -143,6 +146,18 @@ public class UsageEventVO implements UsageEvent {
this.offeringId = securityGroupId;
}
public UsageEventVO(String usageType, long accountId, long zoneId, long resourceId, Long offeringId, Long templateId, Long size, Long vmId, String resourceName) {
this.type = usageType;
this.accountId = accountId;
this.zoneId = zoneId;
this.resourceId = resourceId;
this.offeringId = offeringId;
this.templateId = templateId;
this.size = size;
this.vmId = vmId;
this.resourceName = resourceName;
}
@Override
public long getId() {
return id;
@ -248,4 +263,11 @@ public class UsageEventVO implements UsageEvent {
this.virtualSize = virtualSize;
}
public Long getVmId() {
return vmId;
}
public void setVmId(Long vmId) {
this.vmId = vmId;
}
}

View File

@ -45,11 +45,11 @@ public class UsageEventDaoImpl extends GenericDaoBase<UsageEventVO, Long> implem
private final SearchBuilder<UsageEventVO> latestEventsSearch;
private final SearchBuilder<UsageEventVO> IpeventsSearch;
private static final String COPY_EVENTS =
"INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size) "
+ "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size FROM cloud.usage_event vmevt WHERE vmevt.id > ? and vmevt.id <= ? ";
"INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size, vm_id) "
+ "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size, vm_id FROM cloud.usage_event vmevt WHERE vmevt.id > ? and vmevt.id <= ? ";
private static final String COPY_ALL_EVENTS =
"INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size) "
+ "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size FROM cloud.usage_event vmevt WHERE vmevt.id <= ?";
"INSERT INTO cloud_usage.usage_event (id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size, vm_id) "
+ "SELECT id, type, account_id, created, zone_id, resource_id, resource_name, offering_id, template_id, size, resource_type, virtual_size, vm_id FROM cloud.usage_event vmevt WHERE vmevt.id <= ?";
private static final String COPY_EVENT_DETAILS = "INSERT INTO cloud_usage.usage_event_details (id, usage_event_id, name, value) "
+ "SELECT id, usage_event_id, name, value FROM cloud.usage_event_details vmevtDetails WHERE vmevtDetails.usage_event_id > ? and vmevtDetails.usage_event_id <= ? ";
private static final String COPY_ALL_EVENT_DETAILS = "INSERT INTO cloud_usage.usage_event_details (id, usage_event_id, name, value) "

View File

@ -76,7 +76,6 @@ public class VmRulesetLogDaoImpl extends GenericDaoBase<VmRulesetLogVO, Long> im
@Override
public int createOrUpdate(Set<Long> workItems) {
//return createOrUpdateUsingBatch(workItems);
return createOrUpdateUsingMultiInsert(workItems);
}

View File

@ -100,7 +100,6 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
private SearchBuilder<VMTemplateVO> PublicIsoSearch;
private SearchBuilder<VMTemplateVO> UserIsoSearch;
private GenericSearchBuilder<VMTemplateVO, Long> CountTemplatesByAccount;
// private SearchBuilder<VMTemplateVO> updateStateSearch;
private SearchBuilder<VMTemplateVO> AllFieldsSearch;
protected SearchBuilder<VMTemplateVO> ParentTemplateIdSearch;
private SearchBuilder<VMTemplateVO> InactiveUnremovedTmpltSearch;
@ -404,12 +403,6 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
CountTemplatesByAccount.and("state", CountTemplatesByAccount.entity().getState(), SearchCriteria.Op.EQ);
CountTemplatesByAccount.done();
// updateStateSearch = this.createSearchBuilder();
// updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ);
// updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ);
// updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ);
// updateStateSearch.done();
AllFieldsSearch = createSearchBuilder();
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);

View File

@ -33,11 +33,10 @@ import java.util.List;
import javax.inject.Inject;
import com.cloud.utils.FileUtil;
import org.apache.cloudstack.utils.CloudStackVersion;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.cloud.upgrade.dao.DbUpgrade;
import com.cloud.upgrade.dao.DbUpgradeSystemVmTemplate;
@ -91,8 +90,10 @@ import com.cloud.upgrade.dao.Upgrade41910to42000;
import com.cloud.upgrade.dao.Upgrade42000to42010;
import com.cloud.upgrade.dao.Upgrade42010to42100;
import com.cloud.upgrade.dao.Upgrade42100to42200;
import com.cloud.upgrade.dao.Upgrade42200to42210;
import com.cloud.upgrade.dao.Upgrade420to421;
import com.cloud.upgrade.dao.Upgrade421to430;
import com.cloud.upgrade.dao.Upgrade42210to42300;
import com.cloud.upgrade.dao.Upgrade430to440;
import com.cloud.upgrade.dao.Upgrade431to440;
import com.cloud.upgrade.dao.Upgrade432to440;
@ -121,12 +122,17 @@ import com.cloud.upgrade.dao.VersionDao;
import com.cloud.upgrade.dao.VersionDaoImpl;
import com.cloud.upgrade.dao.VersionVO;
import com.cloud.upgrade.dao.VersionVO.Step;
import com.cloud.utils.FileUtil;
import com.cloud.utils.component.SystemIntegrityChecker;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.ScriptRunner;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.google.common.annotations.VisibleForTesting;
public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
@ -236,6 +242,8 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
.next("4.20.0.0", new Upgrade42000to42010())
.next("4.20.1.0", new Upgrade42010to42100())
.next("4.21.0.0", new Upgrade42100to42200())
.next("4.22.0.0", new Upgrade42200to42210())
.next("4.22.1.0", new Upgrade42210to42300())
.build();
}
@ -251,7 +259,6 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
LOGGER.error("Unable to execute upgrade script", e);
throw new CloudRuntimeException("Unable to execute upgrade script", e);
}
}
@VisibleForTesting
@ -313,20 +320,20 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
}
protected void executeProcedureScripts() {
LOGGER.info(String.format("Executing Stored Procedure scripts that are under resource directory [%s].", PROCEDURES_DIRECTORY));
LOGGER.info("Executing Stored Procedure scripts that are under resource directory [{}].", PROCEDURES_DIRECTORY);
List<String> filesPathUnderViewsDirectory = FileUtil.getFilesPathsUnderResourceDirectory(PROCEDURES_DIRECTORY);
try (TransactionLegacy txn = TransactionLegacy.open("execute-procedure-scripts")) {
Connection conn = txn.getConnection();
for (String filePath : filesPathUnderViewsDirectory) {
LOGGER.debug(String.format("Executing PROCEDURE script [%s].", filePath));
LOGGER.debug("Executing PROCEDURE script [{}].", filePath);
InputStream viewScript = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);
runScript(conn, viewScript);
}
LOGGER.info(String.format("Finished execution of PROCEDURE scripts that are under resource directory [%s].", PROCEDURES_DIRECTORY));
LOGGER.info("Finished execution of PROCEDURE scripts that are under resource directory [{}].", PROCEDURES_DIRECTORY);
} catch (SQLException e) {
String message = String.format("Unable to execute PROCEDURE scripts due to [%s].", e.getMessage());
LOGGER.error(message, e);
@ -335,7 +342,7 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
}
private DbUpgrade[] executeUpgrades(CloudStackVersion dbVersion, CloudStackVersion currentVersion) {
LOGGER.info("Database upgrade must be performed from " + dbVersion + " to " + currentVersion);
LOGGER.info("Database upgrade must be performed from {} to {}", dbVersion, currentVersion);
final DbUpgrade[] upgrades = calculateUpgradePath(dbVersion, currentVersion);
@ -348,8 +355,8 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
private VersionVO executeUpgrade(DbUpgrade upgrade) {
VersionVO version;
LOGGER.debug("Running upgrade " + upgrade.getClass().getSimpleName() + " to upgrade from " + upgrade.getUpgradableVersionRange()[0] + "-" + upgrade
.getUpgradableVersionRange()[1] + " to " + upgrade.getUpgradedVersion());
LOGGER.debug("Running upgrade {} to upgrade from {}-{} to {}", upgrade.getClass().getSimpleName(), upgrade.getUpgradableVersionRange()[0], upgrade
.getUpgradableVersionRange()[1], upgrade.getUpgradedVersion());
TransactionLegacy txn = TransactionLegacy.open("Upgrade");
txn.start();
try {
@ -392,8 +399,8 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
// Run the corresponding '-cleanup.sql' script
txn = TransactionLegacy.open("Cleanup");
try {
LOGGER.info("Cleanup upgrade " + upgrade.getClass().getSimpleName() + " to upgrade from " + upgrade.getUpgradableVersionRange()[0] + "-" + upgrade
.getUpgradableVersionRange()[1] + " to " + upgrade.getUpgradedVersion());
LOGGER.info("Cleanup upgrade {} to upgrade from {}-{} to {}", upgrade.getClass().getSimpleName(), upgrade.getUpgradableVersionRange()[0], upgrade
.getUpgradableVersionRange()[1], upgrade.getUpgradedVersion());
txn.start();
Connection conn;
@ -408,7 +415,7 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
if (scripts != null) {
for (InputStream script : scripts) {
runScript(conn, script);
LOGGER.debug("Cleanup script " + upgrade.getClass().getSimpleName() + " is executed successfully");
LOGGER.debug("Cleanup script {} is executed successfully", upgrade.getClass().getSimpleName());
}
}
txn.commit();
@ -418,27 +425,27 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
version.setUpdated(new Date());
_dao.update(version.getId(), version);
txn.commit();
LOGGER.debug("Upgrade completed for version " + version.getVersion());
LOGGER.debug("Upgrade completed for version {}", version.getVersion());
} finally {
txn.close();
}
}
protected void executeViewScripts() {
LOGGER.info(String.format("Executing VIEW scripts that are under resource directory [%s].", VIEWS_DIRECTORY));
LOGGER.info("Executing VIEW scripts that are under resource directory [{}].", VIEWS_DIRECTORY);
List<String> filesPathUnderViewsDirectory = FileUtil.getFilesPathsUnderResourceDirectory(VIEWS_DIRECTORY);
try (TransactionLegacy txn = TransactionLegacy.open("execute-view-scripts")) {
Connection conn = txn.getConnection();
for (String filePath : filesPathUnderViewsDirectory) {
LOGGER.debug(String.format("Executing VIEW script [%s].", filePath));
LOGGER.debug("Executing VIEW script [{}].", filePath);
InputStream viewScript = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);
runScript(conn, viewScript);
}
LOGGER.info(String.format("Finished execution of VIEW scripts that are under resource directory [%s].", VIEWS_DIRECTORY));
LOGGER.info("Finished execution of VIEW scripts that are under resource directory [{}].", VIEWS_DIRECTORY);
} catch (SQLException e) {
String message = String.format("Unable to execute VIEW scripts due to [%s].", e.getMessage());
LOGGER.error(message, e);
@ -455,23 +462,57 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
throw new CloudRuntimeException("Unable to acquire lock to check for database integrity.");
}
doUpgrades(lock);
} finally {
lock.releaseRef();
}
}
boolean isStandalone() throws CloudRuntimeException {
return Transaction.execute(new TransactionCallback<>() {
@Override
public Boolean doInTransaction(TransactionStatus status) {
String sql = "SELECT COUNT(*) FROM `cloud`.`mshost` WHERE `state` = 'UP'";
try (Connection conn = TransactionLegacy.getStandaloneConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
int count = rs.getInt(1);
return count == 0;
}
} catch (SQLException e) {
String errorMessage = "Unable to check if the management server is running in standalone mode.";
LOGGER.error(errorMessage, e);
return false;
} catch (NullPointerException npe) {
String errorMessage = "Unable to check if the management server is running in standalone mode. Not able to get a Database connection.";
LOGGER.error(errorMessage, npe);
return false;
}
return true;
}
});
}
@VisibleForTesting
protected void doUpgrades(GlobalLock lock) {
try {
initializeDatabaseEncryptors();
final CloudStackVersion dbVersion = CloudStackVersion.parse(_dao.getCurrentVersion());
final String currentVersionValue = this.getClass().getPackage().getImplementationVersion();
final String currentVersionValue = getImplementationVersion();
if (StringUtils.isBlank(currentVersionValue)) {
return;
}
String csVersion = SystemVmTemplateRegistration.parseMetadataFile();
String csVersion = parseSystemVmMetadata();
final CloudStackVersion sysVmVersion = CloudStackVersion.parse(csVersion);
final CloudStackVersion currentVersion = CloudStackVersion.parse(currentVersionValue);
SystemVmTemplateRegistration.CS_MAJOR_VERSION = String.valueOf(sysVmVersion.getMajorRelease()) + "." + String.valueOf(sysVmVersion.getMinorRelease());
SystemVmTemplateRegistration.CS_MAJOR_VERSION = sysVmVersion.getMajorRelease() + "." + sysVmVersion.getMinorRelease();
SystemVmTemplateRegistration.CS_TINY_VERSION = String.valueOf(sysVmVersion.getPatchRelease());
LOGGER.info("DB version = " + dbVersion + " Code Version = " + currentVersion);
LOGGER.info("DB version = {} Code Version = {}", dbVersion, currentVersion);
if (dbVersion.compareTo(currentVersion) > 0) {
throw new CloudRuntimeException("Database version " + dbVersion + " is higher than management software version " + currentVersionValue);
@ -482,16 +523,40 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
return;
}
if (isStandalone()) {
upgrade(dbVersion, currentVersion);
} else {
String errorMessage = "Database upgrade is required but the management server is running in a clustered environment. " +
"Please perform the database upgrade when the management server is not running in a clustered environment.";
LOGGER.error(errorMessage);
handleClusteredUpgradeRequired(); // allow tests to override behavior
}
} finally {
lock.unlock();
}
} finally {
lock.releaseRef();
}
}
private void initializeDatabaseEncryptors() {
/**
* Hook that is called when an upgrade is required but the management server is clustered.
* Default behavior is to exit the JVM, tests can override to throw instead.
*/
@VisibleForTesting
protected void handleClusteredUpgradeRequired() {
System.exit(5); // I would prefer ServerDaemon.abort(errorMessage) but that would create a dependency hell
}
@VisibleForTesting
protected String getImplementationVersion() {
return this.getClass().getPackage().getImplementationVersion();
}
@VisibleForTesting
protected String parseSystemVmMetadata() {
return SystemVmTemplateRegistration.parseMetadataFile();
}
// Make this protected so tests can noop it out
protected void initializeDatabaseEncryptors() {
TransactionLegacy txn = TransactionLegacy.open("initializeDatabaseEncryptors");
txn.start();
String errorMessage = "Unable to get the database connections";
@ -520,7 +585,7 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
ResultSet result = pstmt.executeQuery()) {
if (result.next()) {
String init = result.getString(1);
LOGGER.info("init = " + DBEncryptionUtil.decrypt(init));
LOGGER.info("init = {}", DBEncryptionUtil.decrypt(init));
}
}
}
@ -551,21 +616,11 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker {
return upgradedVersion;
}
@Override
public boolean supportsRollingUpgrade() {
return false;
}
@Override
public InputStream[] getPrepareScripts() {
return new InputStream[0];
}
@Override
public void performDataMigration(Connection conn) {
}
@Override
public InputStream[] getCleanupScripts() {
return new InputStream[0];

View File

@ -77,8 +77,6 @@ public class Upgrade2214to30 extends Upgrade30xBase {
encryptData(conn);
// drop keys
dropKeysIfExist(conn);
//update template ID for system Vms
//updateSystemVms(conn); This is not required as system template update is handled during 4.2 upgrade
// update domain network ref
updateDomainNetworkRef(conn);
// update networks that use redundant routers to the new network offering

View File

@ -62,7 +62,6 @@ public class Upgrade302to40 extends Upgrade30xBase {
@Override
public void performDataMigration(Connection conn) {
//updateVmWareSystemVms(conn); This is not required as system template update is handled during 4.2 upgrade
correctVRProviders(conn);
correctMultiplePhysicaNetworkSetups(conn);
addHostDetailsUniqueKey(conn);

View File

@ -65,7 +65,6 @@ public class Upgrade304to305 extends Upgrade30xBase {
addVpcProvider(conn);
updateRouterNetworkRef(conn);
fixZoneUsingExternalDevices(conn);
// updateSystemVms(conn);
fixForeignKeys(conn);
encryptClusterDetails(conn);
}
@ -81,54 +80,6 @@ public class Upgrade304to305 extends Upgrade30xBase {
return new InputStream[] {script};
}
private void updateSystemVms(Connection conn) {
PreparedStatement pstmt = null;
ResultSet rs = null;
boolean VMware = false;
try {
pstmt = conn.prepareStatement("select distinct(hypervisor_type) from `cloud`.`cluster` where removed is null");
rs = pstmt.executeQuery();
while (rs.next()) {
if ("VMware".equals(rs.getString(1))) {
VMware = true;
}
}
} catch (SQLException e) {
throw new CloudRuntimeException("Error while iterating through list of hypervisors in use", e);
}
// Just update the VMware system template. Other hypervisor templates are unchanged from previous 3.0.x versions.
logger.debug("Updating VMware System Vms");
try {
//Get 3.0.5 VMware system Vm template Id
pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name = 'systemvm-vmware-3.0.5' and removed is null");
rs = pstmt.executeQuery();
if (rs.next()) {
long templateId = rs.getLong(1);
rs.close();
pstmt.close();
// change template type to SYSTEM
pstmt = conn.prepareStatement("update `cloud`.`vm_template` set type='SYSTEM' where id = ?");
pstmt.setLong(1, templateId);
pstmt.executeUpdate();
pstmt.close();
// update template ID of system Vms
pstmt = conn.prepareStatement("update `cloud`.`vm_instance` set vm_template_id = ? where type <> 'User' and hypervisor_type = 'VMware'");
pstmt.setLong(1, templateId);
pstmt.executeUpdate();
pstmt.close();
} else {
if (VMware) {
throw new CloudRuntimeException("3.0.5 VMware SystemVm template not found. Cannot upgrade system Vms");
} else {
logger.warn("3.0.5 VMware SystemVm template not found. VMware hypervisor is not used, so not failing upgrade");
}
}
} catch (SQLException e) {
throw new CloudRuntimeException("Error while updating VMware systemVm template", e);
}
logger.debug("Updating System Vm Template IDs Complete");
}
private void addVpcProvider(Connection conn) {
//Encrypt config params and change category to Hidden
logger.debug("Adding vpc provider to all physical networks in the system");

View File

@ -159,7 +159,7 @@ public class Upgrade41810to41900 extends DbUpgradeAbstractImpl implements DbUpgr
try (PreparedStatement pstmt = conn.prepareStatement(createNewColumn)) {
pstmt.execute();
} catch (SQLException e) {
String message = String.format("Unable to crate new backups' column date due to [%s].", e.getMessage());
String message = String.format("Unable to create new backups' column date due to [%s].", e.getMessage());
logger.error(message, e);
throw new CloudRuntimeException(message, e);
}

View File

@ -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.upgrade.dao;
public class Upgrade42200to42210 extends DbUpgradeAbstractImpl implements DbUpgrade, DbUpgradeSystemVmTemplate {
@Override
public String[] getUpgradableVersionRange() {
return new String[] {"4.22.0.0", "4.22.1.0"};
}
@Override
public String getUpgradedVersion() {
return "4.22.1.0";
}
}

View File

@ -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.upgrade.dao;
public class Upgrade42210to42300 extends DbUpgradeAbstractImpl implements DbUpgrade, DbUpgradeSystemVmTemplate {
@Override
public String[] getUpgradableVersionRange() {
return new String[]{"4.22.1.0", "4.23.0.0"};
}
@Override
public String getUpgradedVersion() {
return "4.23.0.0";
}
}

View File

@ -59,6 +59,9 @@ public class UsageVolumeVO implements InternalIdentity {
@Column(name = "size")
private long size;
@Column(name = "vm_id")
private Long vmId;
@Column(name = "created")
@Temporal(value = TemporalType.TIMESTAMP)
private Date created = null;
@ -70,13 +73,14 @@ public class UsageVolumeVO implements InternalIdentity {
protected UsageVolumeVO() {
}
public UsageVolumeVO(long id, long zoneId, long accountId, long domainId, Long diskOfferingId, Long templateId, long size, Date created, Date deleted) {
public UsageVolumeVO(long id, long zoneId, long accountId, long domainId, Long diskOfferingId, Long templateId, Long vmId, long size, Date created, Date deleted) {
this.volumeId = id;
this.zoneId = zoneId;
this.accountId = accountId;
this.domainId = domainId;
this.diskOfferingId = diskOfferingId;
this.templateId = templateId;
this.vmId = vmId;
this.size = size;
this.created = created;
this.deleted = deleted;
@ -126,4 +130,12 @@ public class UsageVolumeVO implements InternalIdentity {
public long getVolumeId() {
return volumeId;
}
public Long getVmId() {
return vmId;
}
public void setVmId(Long vmId) {
this.vmId = vmId;
}
}

View File

@ -57,6 +57,7 @@ public class UsageStorageDaoImpl extends GenericDaoBase<UsageStorageVO, Long> im
IdSearch.and("accountId", IdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
IdSearch.and("id", IdSearch.entity().getEntityId(), SearchCriteria.Op.EQ);
IdSearch.and("type", IdSearch.entity().getStorageType(), SearchCriteria.Op.EQ);
IdSearch.and("deleted", IdSearch.entity().getDeleted(), SearchCriteria.Op.NULL);
IdSearch.done();
IdZoneSearch = createSearchBuilder();
@ -74,6 +75,7 @@ public class UsageStorageDaoImpl extends GenericDaoBase<UsageStorageVO, Long> im
sc.setParameters("accountId", accountId);
sc.setParameters("id", id);
sc.setParameters("type", type);
sc.setParameters("deleted", null);
return listBy(sc, null);
}

View File

@ -23,9 +23,7 @@ import com.cloud.usage.UsageVolumeVO;
import com.cloud.utils.db.GenericDao;
public interface UsageVolumeDao extends GenericDao<UsageVolumeVO, Long> {
public void removeBy(long userId, long id);
public void update(UsageVolumeVO usage);
public List<UsageVolumeVO> getUsageRecords(Long accountId, Long domainId, Date startDate, Date endDate, boolean limit, int page);
List<UsageVolumeVO> listByVolumeId(long volumeId, long accountId);
}

View File

@ -18,81 +18,46 @@ package com.cloud.usage.dao;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import com.cloud.exception.CloudException;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
import com.cloud.usage.UsageVolumeVO;
import com.cloud.utils.DateUtil;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.TransactionLegacy;
@Component
public class UsageVolumeDaoImpl extends GenericDaoBase<UsageVolumeVO, Long> implements UsageVolumeDao {
protected static final String REMOVE_BY_USERID_VOLID = "DELETE FROM usage_volume WHERE account_id = ? AND volume_id = ?";
protected static final String UPDATE_DELETED = "UPDATE usage_volume SET deleted = ? WHERE account_id = ? AND volume_id = ? and deleted IS NULL";
protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, size, created, deleted "
protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, vm_id, size, created, deleted "
+ "FROM usage_volume " + "WHERE account_id = ? AND ((deleted IS NULL) OR (created BETWEEN ? AND ?) OR "
+ " (deleted BETWEEN ? AND ?) OR ((created <= ?) AND (deleted >= ?)))";
protected static final String GET_USAGE_RECORDS_BY_DOMAIN = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, size, created, deleted "
protected static final String GET_USAGE_RECORDS_BY_DOMAIN = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, vm_id, size, created, deleted "
+ "FROM usage_volume " + "WHERE domain_id = ? AND ((deleted IS NULL) OR (created BETWEEN ? AND ?) OR "
+ " (deleted BETWEEN ? AND ?) OR ((created <= ?) AND (deleted >= ?)))";
protected static final String GET_ALL_USAGE_RECORDS = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, size, created, deleted "
protected static final String GET_ALL_USAGE_RECORDS = "SELECT volume_id, zone_id, account_id, domain_id, disk_offering_id, template_id, vm_id, size, created, deleted "
+ "FROM usage_volume " + "WHERE (deleted IS NULL) OR (created BETWEEN ? AND ?) OR " + " (deleted BETWEEN ? AND ?) OR ((created <= ?) AND (deleted >= ?))";
private SearchBuilder<UsageVolumeVO> volumeSearch;
public UsageVolumeDaoImpl() {
}
@Override
public void removeBy(long accountId, long volId) {
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
try {
txn.start();
try(PreparedStatement pstmt = txn.prepareStatement(REMOVE_BY_USERID_VOLID);) {
if (pstmt != null) {
pstmt.setLong(1, accountId);
pstmt.setLong(2, volId);
pstmt.executeUpdate();
}
}catch (SQLException e) {
throw new CloudException("Error removing usageVolumeVO:"+e.getMessage(), e);
}
txn.commit();
} catch (Exception e) {
txn.rollback();
logger.warn("Error removing usageVolumeVO:"+e.getMessage(), e);
} finally {
txn.close();
}
}
@Override
public void update(UsageVolumeVO usage) {
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
PreparedStatement pstmt = null;
try {
txn.start();
if (usage.getDeleted() != null) {
pstmt = txn.prepareAutoCloseStatement(UPDATE_DELETED);
pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), usage.getDeleted()));
pstmt.setLong(2, usage.getAccountId());
pstmt.setLong(3, usage.getVolumeId());
pstmt.executeUpdate();
}
txn.commit();
} catch (Exception e) {
txn.rollback();
logger.warn("Error updating UsageVolumeVO", e);
} finally {
txn.close();
}
@PostConstruct
protected void init() {
volumeSearch = createSearchBuilder();
volumeSearch.and("accountId", volumeSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
volumeSearch.and("volumeId", volumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
volumeSearch.and("deleted", volumeSearch.entity().getDeleted(), SearchCriteria.Op.NULL);
volumeSearch.done();
}
@Override
@ -150,11 +115,15 @@ public class UsageVolumeDaoImpl extends GenericDaoBase<UsageVolumeVO, Long> impl
if (tId == 0) {
tId = null;
}
long size = Long.valueOf(rs.getLong(7));
Long vmId = Long.valueOf(rs.getLong(7));
if (vmId == 0) {
vmId = null;
}
long size = Long.valueOf(rs.getLong(8));
Date createdDate = null;
Date deletedDate = null;
String createdTS = rs.getString(8);
String deletedTS = rs.getString(9);
String createdTS = rs.getString(9);
String deletedTS = rs.getString(10);
if (createdTS != null) {
createdDate = DateUtil.parseDateString(s_gmtTimeZone, createdTS);
@ -163,7 +132,7 @@ public class UsageVolumeDaoImpl extends GenericDaoBase<UsageVolumeVO, Long> impl
deletedDate = DateUtil.parseDateString(s_gmtTimeZone, deletedTS);
}
usageRecords.add(new UsageVolumeVO(vId, zoneId, acctId, dId, doId, tId, size, createdDate, deletedDate));
usageRecords.add(new UsageVolumeVO(vId, zoneId, acctId, dId, doId, tId, vmId, size, createdDate, deletedDate));
}
} catch (Exception e) {
txn.rollback();
@ -174,4 +143,13 @@ public class UsageVolumeDaoImpl extends GenericDaoBase<UsageVolumeVO, Long> impl
return usageRecords;
}
@Override
public List<UsageVolumeVO> listByVolumeId(long volumeId, long accountId) {
SearchCriteria<UsageVolumeVO> sc = volumeSearch.create();
sc.setParameters("accountId", accountId);
sc.setParameters("volumeId", volumeId);
sc.setParameters("deleted", null);
return listBy(sc);
}
}

View File

@ -226,10 +226,6 @@ public class UserAccountVO implements UserAccount, InternalIdentity {
return created;
}
// public void setCreated(Date created) {
// this.created = created;
// }
@Override
public Date getRemoved() {
return removed;

View File

@ -101,7 +101,7 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
ReservationDao reservationDao;
private static final String LIST_PODS_HAVING_VMS_FOR_ACCOUNT =
"SELECT pod_id FROM cloud.vm_instance WHERE data_center_id = ? AND account_id = ? AND pod_id IS NOT NULL AND (state = 'Running' OR state = 'Stopped') "
"SELECT pod_id FROM cloud.vm_instance WHERE data_center_id = ? AND account_id = ? AND pod_id IS NOT NULL AND state IN ('Starting', 'Running', 'Stopped') "
+ "GROUP BY pod_id HAVING count(id) > 0 ORDER BY count(id) DESC";
private static final String VM_DETAILS = "select vm_instance.id, "
@ -782,7 +782,7 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
result.add(new Ternary<Integer, Integer, Integer>(rs.getInt(1), rs.getInt(2), rs.getInt(3)));
}
} catch (Exception e) {
logger.warn("Error counting vms by size for dcId= " + dcId, e);
logger.warn("Error counting vms by size for Data Center ID = " + dcId, e);
}
return result;
}

View File

@ -886,7 +886,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
return rs.getLong(1);
}
} catch (Exception e) {
logger.warn(String.format("Error counting vms by host tag for dcId= %s, hostTag= %s", dcId, hostTag), e);
logger.warn(String.format("Error counting vms by host tag for dcId = %s, hostTag = %s", dcId, hostTag), e);
}
return 0L;
}

View File

@ -209,10 +209,8 @@ public class VolumeDataStoreVO implements StateObject<ObjectInDataStoreStateMach
public VolumeDataStoreVO(long hostId, long volumeId, Date lastUpdated, int downloadPercent, Status downloadState, String localDownloadPath, String errorString,
String jobId, String installPath, String downloadUrl, String checksum) {
// super();
dataStoreId = hostId;
this.volumeId = volumeId;
// this.zoneId = zoneId;
this.lastUpdated = lastUpdated;
this.downloadPercent = downloadPercent;
this.downloadState = downloadState;

View File

@ -3,7 +3,7 @@
-- 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 compliances
-- "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

View File

@ -0,0 +1,20 @@
-- 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.
--;
-- Schema upgrade cleanup from 4.22.0.0 to 4.22.1.0
--;

View File

@ -0,0 +1,27 @@
-- 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.
--;
-- Schema upgrade from 4.22.0.0 to 4.22.1.0
--;
-- Add vm_id column to usage_event table for volume usage events
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.usage_event','vm_id', 'bigint UNSIGNED NULL COMMENT "VM ID associated with volume usage events"');
CALL `cloud_usage`.`IDEMPOTENT_ADD_COLUMN`('cloud_usage.usage_event','vm_id', 'bigint UNSIGNED NULL COMMENT "VM ID associated with volume usage events"');
-- Add vm_id column to cloud_usage.usage_volume table
CALL `cloud_usage`.`IDEMPOTENT_ADD_COLUMN`('cloud_usage.usage_volume','vm_id', 'bigint UNSIGNED NULL COMMENT "VM ID associated with the volume usage"');

View File

@ -0,0 +1,20 @@
-- 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.
--;
-- Schema upgrade cleanup from 4.22.1.0 to 4.23.0.0
--;

View File

@ -0,0 +1,20 @@
-- 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.
--;
-- Schema upgrade from 4.22.1.0 to 4.23.0.0
--;

View File

@ -0,0 +1,173 @@
// 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.upgrade;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import com.cloud.upgrade.dao.VersionDao;
import com.cloud.upgrade.dao.VersionDaoImpl;
import com.cloud.upgrade.dao.VersionVO;
import com.cloud.utils.db.GlobalLock;
import org.junit.Test;
public class DatabaseUpgradeCheckerDoUpgradesTest {
static class StubVersionDao extends VersionDaoImpl implements VersionDao {
private final String currentVersion;
StubVersionDao(String currentVersion) {
this.currentVersion = currentVersion;
}
@Override
public VersionVO findByVersion(String version, VersionVO.Step step) {
return null;
}
@Override
public String getCurrentVersion() {
return currentVersion;
}
}
private static class TestableChecker extends DatabaseUpgradeChecker {
boolean initializeCalled = false;
boolean upgradeCalled = false;
boolean clusterHandlerCalled = false;
String implVersionOverride = null;
String sysVmMetadataOverride = "4.8.0";
boolean standaloneOverride = true;
TestableChecker(String daoVersion) {
// set a stub DAO
this._dao = new StubVersionDao(daoVersion);
}
@Override
protected void initializeDatabaseEncryptors() {
initializeCalled = true;
// noop instead of doing DB work
}
@Override
protected String getImplementationVersion() {
return implVersionOverride;
}
@Override
protected String parseSystemVmMetadata() {
return sysVmMetadataOverride;
}
@Override
boolean isStandalone() {
return standaloneOverride;
}
@Override
protected void upgrade(org.apache.cloudstack.utils.CloudStackVersion dbVersion, org.apache.cloudstack.utils.CloudStackVersion currentVersion) {
upgradeCalled = true;
}
@Override
protected void handleClusteredUpgradeRequired() {
clusterHandlerCalled = true;
}
}
@Test
public void testDoUpgrades_noImplementationVersion_returnsEarly() {
TestableChecker checker = new TestableChecker("4.8.0");
checker.implVersionOverride = ""; // blank -> should return early
GlobalLock lock = GlobalLock.getInternLock("test-noimpl");
try {
// acquire lock so doUpgrades can safely call unlock in finally
lock.lock(1);
checker.doUpgrades(lock);
} finally {
// ensure lock released if still held
lock.releaseRef();
}
assertTrue("initializeDatabaseEncryptors should be called before returning", checker.initializeCalled);
assertFalse("upgrade should not be called when implementation version is blank", checker.upgradeCalled);
assertFalse("cluster handler should not be called", checker.clusterHandlerCalled);
}
@Test
public void testDoUpgrades_dbUpToDate_noUpgrade() {
// DB version = code version -> no upgrade
TestableChecker checker = new TestableChecker("4.8.1");
checker.implVersionOverride = "4.8.1";
checker.sysVmMetadataOverride = "4.8.1";
GlobalLock lock = GlobalLock.getInternLock("test-uptodate");
try {
lock.lock(1);
checker.doUpgrades(lock);
} finally {
lock.releaseRef();
}
assertTrue(checker.initializeCalled);
assertFalse(checker.upgradeCalled);
assertFalse(checker.clusterHandlerCalled);
}
@Test
public void testDoUpgrades_requiresUpgrade_standalone_invokesUpgrade() {
TestableChecker checker = new TestableChecker("4.8.0");
checker.implVersionOverride = "4.8.2"; // code is newer than DB
checker.sysVmMetadataOverride = "4.8.2";
checker.standaloneOverride = true;
GlobalLock lock = GlobalLock.getInternLock("test-upgrade-standalone");
try {
lock.lock(1);
checker.doUpgrades(lock);
} finally {
lock.releaseRef();
}
assertTrue(checker.initializeCalled);
assertTrue("upgrade should be invoked in standalone mode", checker.upgradeCalled);
assertFalse(checker.clusterHandlerCalled);
}
@Test
public void testDoUpgrades_requiresUpgrade_clustered_invokesHandler() {
TestableChecker checker = new TestableChecker("4.8.0");
checker.implVersionOverride = "4.8.2"; // code is newer than DB
checker.sysVmMetadataOverride = "4.8.2";
checker.standaloneOverride = false;
GlobalLock lock = GlobalLock.getInternLock("test-upgrade-clustered");
try {
lock.lock(1);
checker.doUpgrades(lock);
} finally {
lock.releaseRef();
}
assertTrue(checker.initializeCalled);
assertFalse("upgrade should not be invoked in clustered mode", checker.upgradeCalled);
assertTrue("cluster handler should be invoked in clustered mode", checker.clusterHandlerCalled);
}
}

View File

@ -16,14 +16,24 @@
// under the License.
package com.cloud.upgrade;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.sql.SQLException;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Arrays;
import javax.sql.DataSource;
import org.apache.cloudstack.utils.CloudStackVersion;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.upgrade.DatabaseUpgradeChecker.NoopDbUpgrade;
import com.cloud.upgrade.dao.DbUpgrade;
@ -43,8 +53,51 @@ import com.cloud.upgrade.dao.Upgrade471to480;
import com.cloud.upgrade.dao.Upgrade480to481;
import com.cloud.upgrade.dao.Upgrade490to4910;
import com.cloud.utils.db.TransactionLegacy;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertArrayEquals;
@RunWith(MockitoJUnitRunner.class)
public class DatabaseUpgradeCheckerTest {
@Mock
DataSource dataSource;
@Mock
Connection connection;
@Mock
PreparedStatement preparedStatement;
@Mock
ResultSet resultSet;
private DataSource backupDataSource;
@Before
public void setup() throws Exception {
Field dsField = TransactionLegacy.class.getDeclaredField("s_ds");
dsField.setAccessible(true);
backupDataSource = (DataSource) dsField.get(null);
dsField.set(null, dataSource);
Mockito.when(dataSource.getConnection()).thenReturn(connection);
Mockito.when(connection.prepareStatement(ArgumentMatchers.anyString())).thenReturn(preparedStatement);
Mockito.when(preparedStatement.executeQuery()).thenReturn(resultSet);
}
@After
public void cleanup() throws Exception {
Field dsField = TransactionLegacy.class.getDeclaredField("s_ds");
dsField.setAccessible(true);
dsField.set(null, backupDataSource);
}
@Test
public void testCalculateUpgradePath480to481() {
@ -79,7 +132,7 @@ public class DatabaseUpgradeCheckerTest {
assertTrue(upgrades.length >= 1);
assertTrue(upgrades[0] instanceof Upgrade490to4910);
assertTrue(Arrays.equals(new String[] {"4.9.0", currentVersion.toString()}, upgrades[0].getUpgradableVersionRange()));
assertArrayEquals(new String[]{"4.9.0", currentVersion.toString()}, upgrades[0].getUpgradableVersionRange());
assertEquals(currentVersion.toString(), upgrades[0].getUpgradedVersion());
}
@ -104,7 +157,7 @@ public class DatabaseUpgradeCheckerTest {
assertTrue(upgrades[3] instanceof Upgrade41120to41130);
assertTrue(upgrades[4] instanceof Upgrade41120to41200);
assertTrue(Arrays.equals(new String[] {"4.11.0.0", "4.11.1.0"}, upgrades[1].getUpgradableVersionRange()));
assertArrayEquals(new String[]{"4.11.0.0", "4.11.1.0"}, upgrades[1].getUpgradableVersionRange());
assertEquals(currentVersion.toString(), upgrades[4].getUpgradedVersion());
}
@ -151,12 +204,12 @@ public class DatabaseUpgradeCheckerTest {
assertTrue(upgrades[5] instanceof Upgrade471to480);
assertTrue(upgrades[6] instanceof Upgrade480to481);
assertTrue(Arrays.equals(new String[] {"4.8.1", currentVersion.toString()}, upgrades[upgrades.length - 1].getUpgradableVersionRange()));
assertArrayEquals(new String[]{"4.8.1", currentVersion.toString()}, upgrades[upgrades.length - 1].getUpgradableVersionRange());
assertEquals(currentVersion.toString(), upgrades[upgrades.length - 1].getUpgradedVersion());
}
@Test
public void testCalculateUpgradePathUnkownDbVersion() {
public void testCalculateUpgradePathUnknownDbVersion() {
final CloudStackVersion dbVersion = CloudStackVersion.parse("4.99.0.0");
assertNotNull(dbVersion);
@ -173,7 +226,7 @@ public class DatabaseUpgradeCheckerTest {
}
@Test
public void testCalculateUpgradePathFromKownDbVersion() {
public void testCalculateUpgradePathFromKnownDbVersion() {
final CloudStackVersion dbVersion = CloudStackVersion.parse("4.17.0.0");
assertNotNull(dbVersion);
@ -306,4 +359,25 @@ public class DatabaseUpgradeCheckerTest {
assertEquals(upgrades.length + 1, upgradesFromSecurityReleaseToNext.length);
assertTrue(upgradesFromSecurityReleaseToNext[upgradesFromSecurityReleaseToNext.length - 1] instanceof NoopDbUpgrade);
}
@Test
public void isStandalone() throws SQLException {
// simulate zero 'UP' hosts -> standalone
Mockito.when(resultSet.next()).thenReturn(true);
Mockito.when(resultSet.getInt(1)).thenReturn(0);
final DatabaseUpgradeChecker checker = new DatabaseUpgradeChecker();
assertTrue("DatabaseUpgradeChecker should be a standalone component", checker.isStandalone());
}
@Test
public void isNotStandalone() throws SQLException {
// simulate at least one 'UP' host -> not standalone
Mockito.when(resultSet.next()).thenReturn(true);
Mockito.when(resultSet.getInt(1)).thenReturn(1);
final DatabaseUpgradeChecker checker = new DatabaseUpgradeChecker();
assertFalse("DatabaseUpgradeChecker should not be a standalone component", checker.isStandalone());
}
}

View File

@ -22,7 +22,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
</parent>
<artifactId>cloud-engine-service</artifactId>
<packaging>war</packaging>

View File

@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-engine</artifactId>
<version>4.22.0.0</version>
<version>4.23.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>

Some files were not shown because too many files have changed in this diff Show More