diff --git a/.asf.yaml b/.asf.yaml index e16eb20788e..8c1a5d51fdf 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -41,6 +41,7 @@ github: features: wiki: true issues: true + discussions: true projects: true enabled_merge_buttons: @@ -49,11 +50,20 @@ github: rebase: false collaborators: - - kiranchavala - - rajujith - - alexandremattioli - - vishesh92 - - soreana - acs-robot + - rajujith + - GaOrtiga + - SadiJr + - winterhazel + - gpordeus + - hsato03 + - bernardodemarco + - abh1sar protected_branches: ~ + +notifications: + commits: commits@cloudstack.apache.org + issues: commits@cloudstack.apache.org + pullrequests: commits@cloudstack.apache.org + discussions: users@cloudstack.apache.org diff --git a/.github/linters/.flake8 b/.github/linters/.flake8 index 1c239ac6985..3364ad14f29 100644 --- a/.github/linters/.flake8 +++ b/.github/linters/.flake8 @@ -15,11 +15,18 @@ # specific language governing permissions and limitations # under the License. +# E112 Expected an indented block +# E113 Unexpected indentation +# E133 Closing bracket is missing indentation # E223 Tab before operator # E224 Tab after operator +# E227 Missing whitespace around bitwise or shift operator # E242 Tab after ',' +# E271 Multiple spaces after keyword +# E272 Multiple spaces before keyword # E273 Tab after keyword # E274 Tab before keyword +# E713 Test for membership should be 'not in' # E742 Do not define classes named 'I', 'O', or 'l' # E743 Do not define functions named 'I', 'O', or 'l' # E901 SyntaxError or IndentationError @@ -30,4 +37,7 @@ # W391 Blank line at end of file [flake8] -select = E223,E224,E242,E273,E274,E742,E743,E901,E902,W291,W292,W293,W391 +exclude = + .git, + venv +select = E112,E113,E133,E223,E224,E227,E242,E271,E272,E273,E274,E713,E742,E743,E901,E902,W291,W292,W293,W391 diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml new file mode 100644 index 00000000000..df1b1a2825e --- /dev/null +++ b/.github/linters/.markdown-lint.yml @@ -0,0 +1,100 @@ +# 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. + +# MD001/heading-increment Heading levels should only increment by one level at a time +MD001: false + +# MD003/heading-style Heading style +MD003: false + +# MD004/ul-style Unordered list style +MD004: false + +# MD007/ul-indent Unordered list indentation +MD007: false + +# MD009/no-trailing-spaces Trailing spaces +MD009: false + +# MD010/no-hard-tabs Hard tabs +MD010: false + +# MD012/no-multiple-blanks Multiple consecutive blank lines +MD012: false + +# MD013/line-length Line length +MD013: false + +# MD014/commands-show-output Dollar signs used before commands without showing output +MD014: false + +# MD018/no-missing-space-atx No space after hash on atx style heading +MD018: false + +# MD019/no-multiple-space-atx Multiple spaces after hash on atx style heading +MD019: false + +# MD022/blanks-around-headings Headings should be surrounded by blank lines +MD022: false + +# MD023/heading-start-left Headings must start at the beginning of the line +MD023: false + +# MD024/no-duplicate-heading Multiple headings with the same content +MD024: false + +# MD025/single-title/single-h1 Multiple top-level headings in the same document +MD025: false + +# MD026/no-trailing-punctuation Trailing punctuation in heading +MD026: false + +# MD028/no-blanks-blockquote Blank line inside blockquote +MD028: false + +# MD029/ol-prefix Ordered list item prefix +MD029: false + +# MD031/blanks-around-fences Fenced code blocks should be surrounded by blank lines +MD031: false + +# MD032/blanks-around-lists Lists should be surrounded by blank lines +MD032: false + +# MD033/no-inline-html Inline HTML +MD033: false + +# MD034/no-bare-urls Bare URL used +MD034: false + +# MD036/no-emphasis-as-heading Emphasis used instead of a heading +MD036: false + +# MD037/no-space-in-emphasis Spaces inside emphasis markers +MD037: false + +# MD040/fenced-code-language Fenced code blocks should have a language specified +MD040: false + +# MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading +MD041: false + +# MD046/code-block-style Code block style +MD046: false + +# MD052/reference-links-images Reference links and images should use a label that is defined +MD052: false diff --git a/.github/linters/codespell.txt b/.github/linters/codespell.txt new file mode 100644 index 00000000000..37b3e6de1cb --- /dev/null +++ b/.github/linters/codespell.txt @@ -0,0 +1,526 @@ +accouns +acheived +acount +actuall +acuiring +acumulate +addreess +addtion +adminstrator +afer +afrer +afterall +againt +ags +aktive +algoritm +allo +alloacate +allocted +alocation +alogrithm +alpha-numeric +alue +ammended +ammount +ans +anull +apche +aplication +apllication +applicatio +apporpriate +appropritate +aqcuire +aqcuired +aquire +aquiring +assiciate +assigne +assoication +assosiate +asssert +astroid +asynchroniously +asyncronous +atleast +atomation +attache +attch +attches +authenciation +authenitcation +authenitication +availiability +avialable +bais +beacause +beacuse +becase +becasue +becaues +behviour +birdge +bject +boardcast +bootstraper +bu +cant +capabilites +capablity +capcity +carrefully +cavaet +chaing +checkd +childs +choosen +chould +clenup +cliente +clinet +cluser +cna +collison +comman +commited +comparision +comparisions +complient +concious +conectix +confg +configruation +configuable +conneciton +connexion +constrait +constraits +containg +contex +continuesly +contro +controler +controles +controll +convienient +convinience +coputer +correcponding +correspoding +correspoonds +cosole +coudl +couldnt +craete +craeted +crate +crated +createa +createing +credentail +cros +crresponding +curren +currentl +datas +decalared +declatory +decocdes +decypher +defalut +defaut +defered +definiton +deleteable +dependancy +dependant +dependend +deployement +deply +deplying +dervied +descktop +descrption +deserialzed +desination +detination +detroy +detroying +dettach +dettached +dettaching +diabling +diasbled +dictonary +didnt +differnet +differnt +direcotry +directroy +disale +disbale +discrepency +disover +dissapper +dissassociated +divice +doesn' +doesnot +doesnt +dont' +doubleclick +dows +eanbled +earch +ect +elemnt +eles +elments +emmited +enble +encryted +enebled +enmpty +entires +enviornment +environmnet +equivalant +erro +erronous +everthing +everytime +excetion +excption +excute +execept +execption +execut +executeable +exeeded +exisitng +exisits +existin +existsing +exitting +expcted +expection +explaination +explicitely +faield +faild +failes +falied +fasion +feild +filenname +fillled +findout +fisrt +fo +folowing +fowarding +frist +fro +frontent +fuctionality +genarate +generallly +gernerate +get's +gloabal +gorry +gracefull +gradiant +handeling +hanling +happend +hasing +hasnt +hda +hostanme +hould +hsould +hte +identifers +identifyer +identifyers +igoring +immediatley +implememented +implementor +implementors +implemnt +implict +implmeneted +implmentation +incase +includeing +incosistency +indecates +indien +infor +informations +informaton +infrastrcuture +ingore +inital +initalize +initator +initilization +inspite +instace +instal +instnace +intefaces +intepret +intereface +interfer +interpretted +intialize +intializes +intializing +invlaid +invokation +isnt +ist +klunky +lable +leve +lief +limite +linke +listner +lokal +lokales +maintainence +maintenace +maintenence +mamagement +mambers +manaully +manuel +maxium +mehtod +mergable +mesage +messge +metatdata +milisecond +minumum +mis +modifers +mor +mot +mulitply +multipl +multple +mutliple +nast +nd +neccessary +necesary +netowrk +nin +nodel +nome +noone +nowe +numbe +numer +occured +occurence +occuring +offfering +ofthe +omited +onother +opeation +optin +orginal +otherwse +outter +overriden +overwritting +paramater +paramemeter +paramenter +paramete +parametrs +pararmeter +parms +parralels +particualr +passowrd +perfromed +permissble +physcial +plugable +pluging +polcies +policys +poluting +possiblity +potenial +prefered +preffered +pressenter +previleges +primay +priviledged +procuct +programatically +progres +properites +propertie +propertys +propogate +provison +psudo +pyhsical +readabilty +readd +reccuring +recevied +recieved +recursivelly +redunant +refference +releease +relese +remaning +remore +remvoing +renabling +repeatly +reponse +reqest +reqiured +requieres +requried +reserv +reserverd +reseted +reseting +resorce +responser +resposne +resturns +retreive +retreiving +retrive +retrived +retriving +retrun +retuned +returing +re-use +rever +rocessor +runing +runnign +sate +scalled +scipt +scirpt +scrip +seconadry +seconday +seesion +sepcified +sepcify +seprated +ser +servies +seting +settig +sevices +shoul +shoule +sie +signle +simplier +singature +skiping +snaphsot +snpashot +specied +specifed +specifiy +splitted +spped +standy +statics +stickyness +stil +stip +storeage +strat +streched +strutural +succesfull +successfull +suceessful +suces +sucessfully +suiteable +suppots +suppport +syncronous +syste +tage +te +tempdate +testng +tha +thats +ther +therefor +theres +theses +thi +thorugh +throught +ths +tipically +transction +tring +trough +tyoe +ue +ues +unavailibility +uncommited +uncompressible +uneccessarily +unexepected +unexpect +unknow +unkonw +unkown +unneccessary +unparseable +unrecoginized +unsupport +unxpected +updat +uptodate +usera +usign +usin +utlization +vaidate +valiate +valule +valus +varibles +verfy +verfying +verifing +virutal +visable +wakup +wil +wit +wll +wth diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2ae08f7ba84..1c6c90a6183 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,14 +23,17 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'adopt' @@ -38,7 +41,7 @@ jobs: cache: maven - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.8' architecture: 'x64' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5b17ab33185..133e2c35b4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: build: if: github.repository == 'apache/cloudstack' @@ -51,6 +54,7 @@ jobs: smoke/test_deploy_vm_with_userdata smoke/test_deploy_vms_in_parallel smoke/test_deploy_vms_with_varied_deploymentplanners + smoke/test_restore_vm smoke/test_diagnostics smoke/test_direct_download smoke/test_disk_offerings @@ -59,7 +63,8 @@ jobs: smoke/test_domain_network_offerings smoke/test_domain_service_offerings smoke/test_domain_vpc_offerings", - "smoke/test_dynamicroles + "smoke/test_cluster_drs + smoke/test_dynamicroles smoke/test_enable_account_settings_for_domain smoke/test_enable_role_based_users_in_projects smoke/test_events_resource @@ -81,7 +86,9 @@ jobs: smoke/test_migration smoke/test_multipleips_per_nic smoke/test_nested_virtualization - smoke/test_set_sourcenat", + smoke/test_set_sourcenat + smoke/test_webhook_lifecycle + smoke/test_purge_expunged_vms", "smoke/test_network smoke/test_network_acl smoke/test_network_ipv6 @@ -89,6 +96,7 @@ jobs: smoke/test_nic smoke/test_nic_adapter_type smoke/test_non_contigiousvlan + smoke/test_object_stores smoke/test_outofbandmanagement smoke/test_outofbandmanagement_nestedplugin smoke/test_over_provisioning @@ -107,7 +115,8 @@ jobs: smoke/test_reset_configuration_settings smoke/test_reset_vm_on_reboot smoke/test_resource_accounting - smoke/test_resource_detail", + smoke/test_resource_detail + smoke/test_global_acls", "smoke/test_router_dhcphosts smoke/test_router_dns smoke/test_router_dnsservice @@ -125,6 +134,7 @@ jobs: smoke/test_usage smoke/test_usage_events smoke/test_vm_deployment_planner + smoke/test_vm_strict_host_tags smoke/test_vm_schedule smoke/test_vm_life_cycle smoke/test_vm_lifecycle_unmanage_import @@ -173,7 +183,8 @@ jobs: "component/test_project_usage component/test_protocol_number_security_group component/test_public_ip - component/test_resource_limits", + component/test_resource_limits + component/test_resource_limit_tags", "component/test_regions_accounts component/test_routers component/test_snapshots @@ -188,16 +199,23 @@ jobs: component/test_vpc_network component/test_vpc_offerings component/test_vpc_routers - component/test_vpn_users", - "component/test_vpc_network_lbrules" ] + component/test_vpn_users + component/test_vpc_network_lbrules", + "smoke/test_list_accounts + smoke/test_list_disk_offerings + smoke/test_list_domains + smoke/test_list_hosts + smoke/test_list_service_offerings + smoke/test_list_storage_pools + smoke/test_list_volumes"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'adopt' @@ -205,7 +223,7 @@ jobs: cache: maven - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.8' architecture: 'x64' @@ -272,7 +290,7 @@ jobs: while ! nc -vzw 5 localhost 8096 2>&1 > /dev/null; do grep Exception /tmp/jetty-log; sleep 10; done set -e echo -e "\nStarting Advanced Zone DataCenter deployment" - python3 tools/marvin/marvin/deployDataCenter.py -i setup/dev/advanced.cfg 2>&1 || true + python3 tools/marvin/marvin/deployDataCenter.py -i setup/dev/advdualzone.cfg 2>&1 || true - name: Run Integration Tests with Simulator run: | @@ -285,7 +303,7 @@ jobs: TESTS=($(echo $TESTS | tr -d '\n' | tr -s ' ')) for suite in "${TESTS[@]}" ; do echo -e "Currently running test: $suite\n" - time nosetests-3.4 --with-xunit --xunit-file=integration-test-results/$suite.xml --with-marvin --marvin-config=setup/dev/advanced.cfg test/integration/$suite.py -s -a tags=advanced,required_hardware=false --zone=Sandbox-simulator --hypervisor=simulator || true ; + time nosetests-3.4 --with-xunit --xunit-file=integration-test-results/$suite.xml --with-marvin --marvin-config=setup/dev/advdualzone.cfg test/integration/$suite.py -s -a tags=advanced,required_hardware=false --zone=zim1 --hypervisor=simulator || true ; done echo -e "Stopping Simulator, integration tests run completed\n" @@ -299,10 +317,11 @@ jobs: echo -e "Simulator CI Test Results: (only failures listed)\n" python3 ./tools/marvin/xunit-reader.py integration-test-results/ - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4 with: files: jacoco-coverage.xml fail_ci_if_error: true flags: simulator-marvin-tests verbose: true name: codecov + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 87a4feaf73a..a8f923d708d 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -32,12 +32,12 @@ jobs: name: codecov runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up JDK11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '11' @@ -49,10 +49,11 @@ jobs: cd nonoss && bash -x install-non-oss.sh && cd .. mvn -P quality -Dsimulator -Dnoredist clean install -T$(nproc) - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4 with: files: ./client/target/site/jacoco-aggregate/jacoco.xml fail_ci_if_error: true - flags: unit-tests + flags: unittests verbose: true name: codecov + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/docker-cloudstack-simulator.yml b/.github/workflows/docker-cloudstack-simulator.yml index ac6a6bfb2dc..21a09d04e0b 100644 --- a/.github/workflows/docker-cloudstack-simulator.yml +++ b/.github/workflows/docker-cloudstack-simulator.yml @@ -47,7 +47,7 @@ jobs: - name: Set Docker repository name run: echo "DOCKER_REPOSITORY=apache" >> $GITHUB_ENV - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set ACS version run: echo "ACS_VERSION=$(grep '' pom.xml | head -2 | tail -1 | cut -d'>' -f2 |cut -d'<' -f1)" >> $GITHUB_ENV diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index e3b6f34c3be..b6c814a36f4 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -32,14 +32,14 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Check Out - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install run: | python -m pip install --upgrade pip pip install pre-commit - name: Set PY run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cache/pre-commit key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} diff --git a/.github/workflows/main-sonar-check.yml b/.github/workflows/main-sonar-check.yml index f82819a2d2e..07d15583c82 100644 --- a/.github/workflows/main-sonar-check.yml +++ b/.github/workflows/main-sonar-check.yml @@ -32,26 +32,26 @@ jobs: name: Main Sonar JaCoCo Build runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up JDK11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '11' cache: 'maven' - name: Cache SonarCloud packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache local Maven repository - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/rat.yml b/.github/workflows/rat.yml index 81a9573eb70..b8f83de8194 100644 --- a/.github/workflows/rat.yml +++ b/.github/workflows/rat.yml @@ -23,13 +23,16 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'adopt' diff --git a/.github/workflows/sonar-check.yml b/.github/workflows/sonar-check.yml index 53c78021f10..5d1bcc5dc22 100644 --- a/.github/workflows/sonar-check.yml +++ b/.github/workflows/sonar-check.yml @@ -29,31 +29,31 @@ concurrency: jobs: build: - if: github.repository == 'apache/cloudstack' + if: github.repository == 'apache/cloudstack' && github.event.pull_request.head.repo.full_name == github.repository name: Sonar JaCoCo Coverage runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "refs/pull/${{ github.event.number }}/merge" fetch-depth: 0 - name: Set up JDK11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '11' cache: 'maven' - name: Cache SonarCloud packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache local Maven repository - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/ui.yml b/.github/workflows/ui.yml index badcebc9019..476526aff32 100644 --- a/.github/workflows/ui.yml +++ b/.github/workflows/ui.yml @@ -23,12 +23,15 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: build: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Node uses: actions/setup-node@v3 @@ -52,7 +55,7 @@ jobs: npm run lint npm run test:unit - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4 with: working-directory: ui files: ./coverage/lcov.info @@ -60,3 +63,4 @@ jobs: flags: uitests verbose: true name: codecov + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index 87b56ab5868..7dc318e67d6 100644 --- a/.gitignore +++ b/.gitignore @@ -15,93 +15,92 @@ # specific language governing permissions and limitations # under the License. -build/build.number -.lock-wscript -.waf-* -waf-* -target/ -override/ -.metadata -dist/ *~ +*_flymake.js *.bak -cloud-*.tar.bz2 -*.log -*.pyc -*.patch +*.css.map *.egginfo/ *.egg-info/ -*.prefs -build.number -*.log.* -cloud.log.*.* -unittest -deps/cloud.userlibraries -.DS_Store -.idea *.iml -git-remote-https.exe.stackdump -*.swp -tools/devcloud/devcloudbox/.vagrant -tools/cli/cloudmonkey/marvin/ -tools/cli/cloudmonkey/precache.py -tools/marvin/marvin/cloudstackAPI/ -tools/marvin/build/ -tools/cli/build/ -tools/appliance/systemvmtemplate/packer_cache/ -*.jar -*.war -*.mar *.iso +*.jar +*.log +*.log.* +*.mar +*.orig +*.patch +*.prefs +*.pyc +*.qcow2 +*.raw +*.swp *.tar.gz *.tgz *.vscode -*.css.map +*.war +.DS_Store +.checkstyle +.classpath +.idea +.lock-wscript +.metadata +.pmd +.pmdruleset.xml +.project +.pydevproject +.reviewboardrc +.settings.xml +.settings/ +.vscode +.waf-* +Gemfile.lock +build/build.number +build.number +build-indep-stamp +cloud.log.*.* +cloud-*.tar.bz2 +configure-stamp +db.properties.override +debian/*.debhelper +debian/*.substvars +debian/cloudstack-*/* +debian/files +debian/tmp +deps/cloud.userlibraries +dist/ +docs/publish +docs/runbook/publish +docs/runbook/tmp +docs/tmp +engine/storage/integration-test/test-output +git-remote-https.exe.stackdump +node_modules +override/ +plugins/hypervisors/kvm/.pydevproject +plugins/network-elements/juniper-contrail/logs/ +replace.properties.override +replace.properties.tmp +scripts/.pydevproject +scripts/vm/hypervisor/xenserver/vhd-util +systemvm/.pydevproject +target/ +target-eclipse +test/.pydevprojec +tools/apidoc/log/ +tools/appliance/box/ +tools/appliance/systemvmtemplate/packer_cache/ +tools/cli/build/ +tools/cli/cloudmonkey/marvin/ +tools/cli/cloudmonkey/precache.py +tools/devcloud/devcloudbox/.vagrant +tools/marvin/build/ +tools/marvin/marvin/cloudstackAPI/ +tools/marvin/marvin/cloudstackAPI/* +unittest +venv +waf-* # this ignores _all files starting with '.'. Don't do that! #.* -target-eclipse -!.gitignore -.classpath -.settings.xml -.settings/ -db.properties.override -replace.properties.override -tools/marvin/marvin/cloudstackAPI/* -docs/tmp -docs/publish -docs/runbook/tmp -docs/runbook/publish -.project -Gemfile.lock -debian/tmp -debian/files -debian/cloudstack-*/* -debian/*.substvars -debian/*.debhelper -replace.properties.tmp -build-indep-stamp -configure-stamp -*_flymake.js -engine/storage/integration-test/test-output -tools/apidoc/log/ -plugins/network-elements/juniper-contrail/logs/ -scripts/vm/hypervisor/xenserver/vhd-util -*.orig -tools/appliance/box/ -.reviewboardrc -.checkstyle -.pmd -.pmdruleset.xml -.pydevproject -systemvm/.pydevproject -test/.pydevprojec -plugins/hypervisors/kvm/.pydevproject -scripts/.pydevproject -*.qcow2 -*.raw -venv -node_modules -.vscode -*.bz2 +!.gitignore \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f7c3c0f90e1..e8f3c6093a9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,21 +19,25 @@ default_stages: [commit, push] default_language_version: # force all unspecified Python hooks to run python3 python: python3 -minimum_pre_commit_version: "2.18.0" +minimum_pre_commit_version: "2.17.0" repos: - repo: meta hooks: - id: identity - id: check-hooks-apply - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: #- id: check-added-large-files - id: check-case-conflict #- id: check-executables-have-shebangs - #- id: check-merge-conflict + - id: check-merge-conflict + - id: check-symlinks - id: check-vcs-permalinks #- id: check-yaml + - id: destroyed-symlinks + - id: detect-aws-credentials + args: [--allow-missing-credentials] - id: detect-private-key exclude: > (?x) @@ -51,11 +55,23 @@ repos: - id: end-of-file-fixer exclude: \.vhd$ #- id: fix-byte-order-marker + - id: forbid-submodules - id: mixed-line-ending - files: \.(java|md|py|txt|yaml|yml)$ - # - id: trailing-whitespace + exclude: \.(cs|xml)$ + - id: trailing-whitespace + files: \.(header|in|java|md|properties|py|rb|sh|sql|txt|vue|xml|yaml|yml)$ + 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 + hooks: + - id: codespell + name: run codespell + description: Check spelling with codespell + args: [--ignore-words=.github/linters/codespell.txt] + exclude: ^ui/package\.json$|^ui/package-lock\.json$|^ui/public/js/less\.min\.js$|^ui/public/locales/.*[^n].*\.json$ - repo: https://github.com/pycqa/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 args: [--config, .github/linters/.flake8] @@ -70,3 +86,12 @@ repos: ^scripts/vm/hypervisor/xenserver/vmopspremium$| ^setup/bindir/cloud-setup-encryption\.in$| ^venv/.*$ + - repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.40.0 + hooks: + - id: markdownlint + name: run markdownlint + description: check Markdown files with markdownlint + args: [--config=.github/linters/.markdown-lint.yml] + types: [markdown] + files: \.(md|mdown|markdown)$ diff --git a/CHANGES.md b/CHANGES.md index ef498f8edf0..9544fc014c7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -430,11 +430,11 @@ Bug ID | Description [CLOUDSTACK-6099](https://issues.apache.org/jira/browse/CLOUDSTACK-6099) | live migration is failing for vm deployed using dynamic compute offerings with NPE [CLOUDSTACK-7528](https://issues.apache.org/jira/browse/CLOUDSTACK-7528) | More verbose logging when sending alert fails [CLOUDSTACK-6624](https://issues.apache.org/jira/browse/CLOUDSTACK-6624) | set specifyIpRanges to true if specifyVlan is set to true -[CLOUDSTACK-7404](https://issues.apache.org/jira/browse/CLOUDSTACK-7404) | Failed to start an instance when originating template has been deleted +[CLOUDSTACK-7404](https://issues.apache.org/jira/browse/CLOUDSTACK-7404) | Failed to start an instance when originating template has been deleted [CLOUDSTACK-6531](https://issues.apache.org/jira/browse/CLOUDSTACK-6531) | Stopping the router in case of command failures [CLOUDSTACK-6115](https://issues.apache.org/jira/browse/CLOUDSTACK-6115) | TravisCI configuration [CLOUDSTACK-7405](https://issues.apache.org/jira/browse/CLOUDSTACK-7405) | allowing VR meta-data to be accessed without trailing slash -[CLOUDSTACK-7260](https://issues.apache.org/jira/browse/CLOUDSTACK-7260) | Management server not responding after some time for Vmware due to Oom +[CLOUDSTACK-7260](https://issues.apache.org/jira/browse/CLOUDSTACK-7260) | Management server not responding after some time for Vmware due to Oom [CLOUDSTACK-7038](https://issues.apache.org/jira/browse/CLOUDSTACK-7038) | Add mysql client dependency for mgmt server pkg for debian [CLOUDSTACK-6892](https://issues.apache.org/jira/browse/CLOUDSTACK-6892) | Create separate package for the mysql HA component [CLOUDSTACK-7038](https://issues.apache.org/jira/browse/CLOUDSTACK-7038) | Add mysql client dependency for mgmt server/rpms @@ -449,12 +449,12 @@ Bug ID | Description [CLOUDSTACK-7006](https://issues.apache.org/jira/browse/CLOUDSTACK-7006) | Restore template ID in ROOT volume usages [CLOUDSTACK-6747](https://issues.apache.org/jira/browse/CLOUDSTACK-6747) | test to allow all cidrs on other end of vpc [CLOUDSTACK-6272](https://issues.apache.org/jira/browse/CLOUDSTACK-6272) | Fix recover/restore VM actions -[CLOUDSTACK-6927](https://issues.apache.org/jira/browse/CLOUDSTACK-6927) | store virsh list in list instead of querying libvirt +[CLOUDSTACK-6927](https://issues.apache.org/jira/browse/CLOUDSTACK-6927) | store virsh list in list instead of querying libvirt [CLOUDSTACK-6317](https://issues.apache.org/jira/browse/CLOUDSTACK-6317) | [VMware] Tagged VLAN support broken for Management/Control/Storage traffic [CLOUDSTACK-5891](https://issues.apache.org/jira/browse/CLOUDSTACK-5891) | [VMware] If a template has been registered and "cpu.corespersocket=X" , [CLOUDSTACK-6478](https://issues.apache.org/jira/browse/CLOUDSTACK-6478) | Failed to download Template when having 3 SSVM's in one [CLOUDSTACK-6464](https://issues.apache.org/jira/browse/CLOUDSTACK-6464) | if guest network type is vlan://untagged, and traffic label is used -[CLOUDSTACK-6816](https://issues.apache.org/jira/browse/CLOUDSTACK-6816) | bugfix: cloudstack-setup-management make /root directory's permission 0777 +[CLOUDSTACK-6816](https://issues.apache.org/jira/browse/CLOUDSTACK-6816) | bugfix: cloudstack-setup-management make /root directory's permission 0777 [CLOUDSTACK-6204](https://issues.apache.org/jira/browse/CLOUDSTACK-6204) | applying missed patch [CLOUDSTACK-6472](https://issues.apache.org/jira/browse/CLOUDSTACK-6472) | (4.3 specific) listUsageRecords: Pull information from removed items as well [CLOUDSTACK-5976](https://issues.apache.org/jira/browse/CLOUDSTACK-5976) | Typo in "ssh_keypairs" table's foreign key constraints on the Upgraded Setup @@ -657,11 +657,11 @@ Version 4.1.0 ------------- This is the second major release of CloudStack from within the Apache Software Foundation, and the -first major release as a Top-Level Project (TLP). +first major release as a Top-Level Project (TLP). Build Tool Changes: - * The project now uses Maven 3 exclusively to build. + * The project now uses Maven 3 exclusively to build. New Features: * CLOUDSTACK-101: OVS support in KVM @@ -976,14 +976,14 @@ Issues fixed in this release: * CLOUDSTACK-1845: KVM - storage migration often fails * CLOUDSTACK-1846: KVM - storage pools can silently fail to be unregistered, leading to failure to register later * CLOUDSTACK-2003: Deleting domain while deleted account is cleaning up leaves VMs expunging forever due to 'Failed to update resource count' -* CLOUDSTACK-2090: Upgrade from version 4.0.1 to version 4.0.2 triggers the 4.0.0 to 4.0.1. +* CLOUDSTACK-2090: Upgrade from version 4.0.1 to version 4.0.2 triggers the 4.0.0 to 4.0.1. * CLOUDSTACK-2091: Error in API documentation for 4.0.x. Version 4.0.1-incubating ------------------------ -This is a bugfix release for Apache CloudStack 4.0.0-incubating, with no new features. +This is a bugfix release for Apache CloudStack 4.0.0-incubating, with no new features. Security Fixes: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cdfbfe77b7e..bb84e4e91fb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,7 @@ Contributing to Apache CloudStack (ACS) Summary ------- -This document covers how to contribute to the ACS project. ACS uses GitHub PRs to manage code contributions. +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. _Lets get started!!!_ @@ -11,17 +11,17 @@ _Lets get started!!!_ Bug fixes --------- -It's very important that we can easily track bug fix commits, so their hashes should remain the same in all branches. -Therefore, a pull request (PR) that fixes a bug, should be sent against a release branch. -This can be either the "current release" or the "previous release", depending on which ones are maintained. +It's very important that we can easily track bug fix commits, so their hashes should remain the same in all branches. +Therefore, a pull request (PR) that fixes a bug, should be sent against a release branch. +This can be either the "current release" or the "previous release", depending on which ones are maintained. Since the goal is a stable main, bug fixes should be "merged forward" to the next branch in order: "previous release" -> "current release" -> main (in other words: old to new) Developing new features ----------------------- -Development should be done in a feature branch, branched off of main. -Send a PR(steps below) to get it into main (2x LGTM applies). -PR will only be merged when main is open, will be held otherwise until main is open again. +Development should be done in a feature branch, branched off of main. +Send a PR(steps below) to get it into main (2x LGTM applies). +PR will only be merged when main is open, will be held otherwise until main is open again. No back porting / cherry-picking features to existing branches! PendingReleaseNotes file @@ -33,7 +33,7 @@ When adding information to the PendingReleaseNotes file make sure that you write Updating the PendingReleaseNotes file is preferably a part of the original Pull Request, but that is up to the developers' discretion. -Fork the code +Fork the code ------------- In your browser, navigate to: [https://github.com/apache/cloudstack](https://github.com/apache/cloudstack) @@ -136,4 +136,4 @@ $ git push origin :feature_x Release Principles ------------------ -Detailed information about ACS release principles is available at https://cwiki.apache.org/confluence/display/CLOUDSTACK/Release+principles+for+Apache+CloudStack+4.6+and+up +Detailed information about ACS release principles is available at https://cwiki.apache.org/confluence/display/CLOUDSTACK/Release+principles+for+Apache+CloudStack+4.6+and+up diff --git a/INSTALL.md b/INSTALL.md index 620fc1833a8..6586e4e57fc 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -15,7 +15,7 @@ was tested against a CentOS 7 x86_64 setup. Install tools and dependencies used for development: - # yum -y install git java-11-openjdk java-11-openjdk-devel \ + # yum -y install git java-17-openjdk java-17-openjdk-devel \ mysql mysql-server mkisofs git gcc python MySQL-python openssh-clients wget Set up Maven (3.6.0): diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 16345c1d723..e02cc651853 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -10,10 +10,10 @@ This PR... - - + + - + ### Types of changes @@ -22,6 +22,8 @@ This PR... - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] Enhancement (improves an existing feature and functionality) - [ ] Cleanup (Code refactoring and cleanup, that may add test cases) +- [ ] build/CI +- [ ] test (unit or integration test code) ### Feature/Enhancement Scale or Bug Severity @@ -43,8 +45,12 @@ This PR... ### How Has This Been Tested? + + +#### How did you try to break this feature and the system with this change? + diff --git a/README.md b/README.md index 2519c6cd273..f66a4dc6f97 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,13 @@ contribution. Note that you do not have to be a developer in order to contribute to Apache CloudStack. We need folks to help with documentation, translation, promotion etc. See our contribution [page](http://cloudstack.apache.org/contribute.html). +If you are a frequent contributors, you can request to be added as collaborators +(see https://cwiki.apache.org/confluence/display/INFRA/Git+-+.asf.yaml+features#Git.asf.yamlfeatures-AssigningexternalcollaboratorswiththetriageroleonGitHub) +to our GitHub repos. This allows you to use project GitHub with ability to report +issue with tags, and be assigned to issues and PRs. This is done via the .asf.yaml +file in this repo. +You may do so by sharing your GitHub users ID or raise a GitHub issue. + If you're interested in learning more or participating in the Apache CloudStack project, the mailing lists are the best way to do that. While the project has several communications channels, the [mailing lists](http://cloudstack.apache.org/mailing-lists.html) are the most active and the @@ -135,7 +142,7 @@ This distribution includes cryptographic software. The country in which you curr reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and -re-export of encryption software, to see if this is permitted. See [The Wassenaar Arrangement](http://www.wassenaar.org/) +re-export of encryption software, to see if this is permitted. See [The Wassenaar Arrangement](http://www.wassenaar.org/) for more information. The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has diff --git a/agent/bindir/cloud-setup-agent.in b/agent/bindir/cloud-setup-agent.in index 53c6c2f56aa..18de64089ed 100755 --- a/agent/bindir/cloud-setup-agent.in +++ b/agent/bindir/cloud-setup-agent.in @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/agent/bindir/cloud-ssh.in b/agent/bindir/cloud-ssh.in index e4b3c141a97..a5ea975c2f3 100644 --- a/agent/bindir/cloud-ssh.in +++ b/agent/bindir/cloud-ssh.in @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties index 9174da7fd7b..3b6a7b7de29 100644 --- a/agent/conf/agent.properties +++ b/agent/conf/agent.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -279,6 +279,11 @@ hypervisor.type=kvm # If this parameter is used, property host.overcommit.mem.mb must be set to 0. #host.reserved.mem.mb=1024 +# Number of CPU cores to subtract from advertised available cores. +# These are reserved for system activity, or otherwise share host CPU resources with +# CloudStack VM allocation. +# host.reserved.cpu.count = 0 + # The model of Watchdog timer to present to the Guest. # For all models refer to the libvirt documentation. #vm.watchdog.model=i6300esb @@ -373,6 +378,10 @@ iscsi.session.cleanup.enabled=false # If the time is exceeded shutdown will be forced. #stop.script.timeout=120 +# Time (in seconds) to wait for scripts to complete. +# This is currently used only while checking if the host supports UEFI. +#agent.script.timeout=60 + # Definition of VMs video model type. #vm.video.hardware= @@ -402,3 +411,25 @@ iscsi.session.cleanup.enabled=false # The path of an executable file/script for host health check for CloudStack to Auto Disable/Enable the host # depending on the return value of the file/script # agent.health.check.script.path= + +# Time interval (in milliseconds) between KVM heartbeats. +# kvm.heartbeat.update.frequency=60000 + +# Number of maximum tries to KVM heartbeats. +# kvm.heartbeat.update.max.tries=5 + +# Time amount (in milliseconds) for the KVM heartbeat retry sleep. +# kvm.heartbeat.update.retry.sleep=10000 + +# Timeout (in milliseconds) of the KVM heartbeat checker. +# kvm.heartbeat.checker.timeout=360000 + +# Instance Conversion from Vmware to KVM through virt-v2v. Enable verbose mode +# virtv2v.verbose.enabled=false + +# If set to "true", the agent will register for libvirt domain events, allowing for immediate updates on crashed or +# unexpectedly stopped. Experimental, requires agent restart. +# libvirt.events.enabled=false + +# Implicit host tags managed by agent.properties +# host.tags= diff --git a/agent/conf/cloudstack-agent.logrotate.in b/agent/conf/cloudstack-agent.logrotate.in index 2b3dc87f253..9f22b4bab86 100644 --- a/agent/conf/cloudstack-agent.logrotate.in +++ b/agent/conf/cloudstack-agent.logrotate.in @@ -15,11 +15,13 @@ # specific language governing permissions and limitations # under the License. -/var/log/cloudstack/agent/security_group.log /var/log/cloudstack/agent/resizevolume.log /var/log/cloudstack/agent/rolling-maintenance.log { +/var/log/cloudstack/agent/security_group.log /var/log/cloudstack/agent/resizevolume.log /var/log/cloudstack/agent/rolling-maintenance.log /var/log/cloudstack/agent/agent.out /var/log/cloudstack/agent/agent.err { copytruncate daily rotate 5 compress missingok size 10M + dateext + dateformat -%Y-%m-%d } diff --git a/agent/conf/environment.properties.in b/agent/conf/environment.properties.in index 514161a13fc..b6cc5bbd987 100644 --- a/agent/conf/environment.properties.in +++ b/agent/conf/environment.properties.in @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/agent/conf/log4j-cloud.xml.in b/agent/conf/log4j-cloud.xml.in index 9ed43e083e0..29c1d5ee641 100644 --- a/agent/conf/log4j-cloud.xml.in +++ b/agent/conf/log4j-cloud.xml.in @@ -17,91 +17,60 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - + + - + + + - - - + + + + + + + + - - - - - - - - - - - - - - - - + + + - - - + + + + + - - - - + - - - + + + - - - - - - - - - - - + - - - - + - - - - - - - + - - - - + - - - - + - - - + - - - + - - - - - + + + - + + + + + + + diff --git a/agent/pom.xml b/agent/pom.xml index 5fe88c8bdb7..9caa6d992c8 100644 --- a/agent/pom.xml +++ b/agent/pom.xml @@ -24,7 +24,7 @@ org.apache.cloudstack cloudstack - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT diff --git a/agent/src/main/java/com/cloud/agent/Agent.java b/agent/src/main/java/com/cloud/agent/Agent.java index e9213ca9b8c..d2d4f165979 100644 --- a/agent/src/main/java/com/cloud/agent/Agent.java +++ b/agent/src/main/java/com/cloud/agent/Agent.java @@ -40,6 +40,9 @@ import java.util.concurrent.atomic.AtomicInteger; import javax.naming.ConfigurationException; +import com.cloud.resource.AgentStatusUpdater; +import com.cloud.resource.ResourceStatusUpdater; +import com.cloud.agent.api.PingAnswer; import com.cloud.utils.NumbersUtil; import org.apache.cloudstack.agent.lb.SetupMSListAnswer; import org.apache.cloudstack.agent.lb.SetupMSListCommand; @@ -52,9 +55,10 @@ import org.apache.cloudstack.managed.context.ManagedContextTimerTask; import org.apache.cloudstack.utils.security.KeyStoreUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; -import org.apache.log4j.MDC; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import com.cloud.agent.api.AgentControlAnswer; import com.cloud.agent.api.AgentControlCommand; @@ -86,6 +90,7 @@ import com.cloud.utils.nio.NioConnection; import com.cloud.utils.nio.Task; import com.cloud.utils.script.OutputInterpreter; import com.cloud.utils.script.Script; +import org.apache.logging.log4j.ThreadContext; /** * @config @@ -100,8 +105,8 @@ import com.cloud.utils.script.Script; * For more configuration options, see the individual types. * **/ -public class Agent implements HandlerFactory, IAgentControl { - protected static Logger s_logger = Logger.getLogger(Agent.class); +public class Agent implements HandlerFactory, IAgentControl, AgentStatusUpdater { + protected Logger logger = LogManager.getLogger(getClass()); public enum ExitStatus { Normal(0), // Normal status = 0. @@ -178,7 +183,7 @@ public class Agent implements HandlerFactory, IAgentControl { final String value = _shell.getPersistentProperty(getResourceName(), "id"); _id = value != null ? Long.parseLong(value) : null; - s_logger.info("id is " + (_id != null ? _id : "")); + logger.info("id is {}", ObjectUtils.defaultIfNull(_id, "")); final Map params = new HashMap<>(); @@ -196,7 +201,7 @@ public class Agent implements HandlerFactory, IAgentControl { // ((NioClient)_connection).setBindAddress(_shell.getPrivateIp()); - s_logger.debug("Adding shutdown hook"); + logger.debug("Adding shutdown hook"); Runtime.getRuntime().addShutdownHook(_shutdownThread); _ugentTaskPool = @@ -207,8 +212,8 @@ public class Agent implements HandlerFactory, IAgentControl { new ThreadPoolExecutor(_shell.getWorkers(), 5 * _shell.getWorkers(), 1, TimeUnit.DAYS, new LinkedBlockingQueue(), new NamedThreadFactory( "agentRequest-Handler")); - s_logger.info("Agent [id = " + (_id != null ? _id : "new") + " : type = " + getResourceName() + " : zone = " + _shell.getZone() + " : pod = " + _shell.getPod() + - " : workers = " + _shell.getWorkers() + " : host = " + host + " : port = " + _shell.getPort()); + logger.info("Agent [id = {} : type = {} : zone = {} : pod = {} : workers = {} : host = {} : port = {}", ObjectUtils.defaultIfNull(_id, "new"), getResourceName(), + _shell.getZone(), _shell.getPod(), _shell.getWorkers(), host, _shell.getPort()); } public String getVersion() { @@ -265,7 +270,7 @@ public class Agent implements HandlerFactory, IAgentControl { public void start() { if (!_resource.start()) { - s_logger.error("Unable to start the resource: " + _resource.getName()); + logger.error("Unable to start the resource: {}", _resource.getName()); throw new CloudRuntimeException("Unable to start the resource: " + _resource.getName()); } @@ -282,14 +287,13 @@ public class Agent implements HandlerFactory, IAgentControl { try { _connection.start(); } catch (final NioConnectionException e) { - s_logger.warn("NIO Connection Exception " + e); - s_logger.info("Attempted to connect to the server, but received an unexpected exception, trying again..."); + logger.warn("Attempt to connect to server generated NIO Connection Exception {}, trying again", e.getLocalizedMessage()); } while (!_connection.isStartup()) { final String host = _shell.getNextHost(); _shell.getBackoffAlgorithm().waitBeforeRetry(); _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this); - s_logger.info("Connecting to host:" + host); + logger.info("Connecting to host:{}", host); try { _connection.start(); } catch (final NioConnectionException e) { @@ -297,9 +301,9 @@ public class Agent implements HandlerFactory, IAgentControl { try { _connection.cleanUp(); } catch (final IOException ex) { - s_logger.warn("Fail to clean up old connection. " + ex); + logger.warn("Fail to clean up old connection. {}", ex); } - s_logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...", e); + logger.info("Attempted to connect to the server, but received an unexpected exception, trying again...", e); } } _shell.updateConnectedHost(); @@ -308,7 +312,7 @@ public class Agent implements HandlerFactory, IAgentControl { } public void stop(final String reason, final String detail) { - s_logger.info("Stopping the agent: Reason = " + reason + (detail != null ? ": Detail = " + detail : "")); + logger.info("Stopping the agent: Reason = {} {}", reason, ": Detail = " + ObjectUtils.defaultIfNull(detail, "")); _reconnectAllowed = false; if (_connection != null) { final ShutdownCommand cmd = new ShutdownCommand(reason, detail); @@ -318,15 +322,15 @@ public class Agent implements HandlerFactory, IAgentControl { _link.send(req.toBytes()); } } catch (final ClosedChannelException e) { - s_logger.warn("Unable to send: " + cmd.toString()); + logger.warn("Unable to send: {}", cmd.toString()); } catch (final Exception e) { - s_logger.warn("Unable to send: " + cmd.toString() + " due to exception: ", e); + logger.warn("Unable to send: {} due to exception: {}", cmd.toString(), e); } - s_logger.debug("Sending shutdown to management server"); + logger.debug("Sending shutdown to management server"); try { Thread.sleep(1000); } catch (final InterruptedException e) { - s_logger.debug("Who the heck interrupted me here?"); + logger.debug("Who the heck interrupted me here?"); } _connection.stop(); _connection = null; @@ -373,7 +377,7 @@ public class Agent implements HandlerFactory, IAgentControl { } public void setId(final Long id) { - s_logger.info("Set agent id " + id); + logger.debug("Set agent id {}", id); _id = id; _shell.setPersistentProperty(getResourceName(), "id", Long.toString(id)); } @@ -392,7 +396,7 @@ public class Agent implements HandlerFactory, IAgentControl { hostLBTimer.cancel(); } if (checkInterval > 0L) { - s_logger.info("Scheduling preferred host timer task with host.lb.interval=" + checkInterval + "ms"); + logger.info("Scheduling preferred host timer task with host.lb.interval={}ms", checkInterval); hostLBTimer = new Timer("Host LB Timer"); hostLBTimer.scheduleAtFixedRate(new PreferredHostCheckerTask(), checkInterval, checkInterval); } @@ -400,23 +404,34 @@ public class Agent implements HandlerFactory, IAgentControl { public void scheduleWatch(final Link link, final Request request, final long delay, final long period) { synchronized (_watchList) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Adding a watch list"); - } + logger.debug("Adding task with request: {} to watch list", request.toString()); + final WatchTask task = new WatchTask(link, request, this); _timer.schedule(task, 0, period); _watchList.add(task); } } + public void triggerUpdate() { + PingCommand command = _resource.getCurrentStatus(getId()); + command.setOutOfBand(true); + logger.debug("Sending out of band ping"); + + final Request request = new Request(_id, -1, command, false); + request.setSequence(getNextSequence()); + try { + _link.send(request.toBytes()); + } catch (final ClosedChannelException e) { + logger.warn("Unable to send ping update: {}", request.toString()); + } + } + protected void cancelTasks() { synchronized (_watchList) { for (final WatchTask task : _watchList) { task.cancel(); } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Clearing watch list: " + _watchList.size()); - } + logger.debug("Clearing {} tasks of watch list", _watchList.size()); _watchList.clear(); } } @@ -452,14 +467,16 @@ public class Agent implements HandlerFactory, IAgentControl { final Request request = new Request(_id != null ? _id : -1, -1, commands, false, false); request.setSequence(getNextSequence()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Sending Startup: " + request.toString()); - } + logger.debug("Sending Startup: {}", request.toString()); lockStartupTask(link); try { link.send(request.toBytes()); } catch (final ClosedChannelException e) { - s_logger.warn("Unable to send request: " + request.toString()); + logger.warn("Unable to send request: {}", request.toString()); + } + + if (_resource instanceof ResourceStatusUpdater) { + ((ResourceStatusUpdater) _resource).registerStatusUpdater(this); } } } @@ -469,11 +486,11 @@ public class Agent implements HandlerFactory, IAgentControl { try { addr = InetAddress.getLocalHost(); } catch (final UnknownHostException e) { - s_logger.warn("unknown host? ", e); + logger.warn("unknown host? ", e); throw new CloudRuntimeException("Cannot get local IP address"); } - final Script command = new Script("hostname", 500, s_logger); + final Script command = new Script("hostname", 500, logger); final OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser(); final String result = command.execute(parser); final String hostname = result == null ? parser.getLine() : addr.toString(); @@ -515,14 +532,14 @@ public class Agent implements HandlerFactory, IAgentControl { _resource.disconnected(); - s_logger.info("Lost connection to host: " + _shell.getConnectedHost() + ". Attempting reconnection while we still have " + _inProgress.get() + " commands in progress."); + logger.info("Lost connection to host: {}. Attempting reconnection while we still have {} commands in progress.", _shell.getConnectedHost(), _inProgress.get()); _connection.stop(); try { _connection.cleanUp(); } catch (final IOException e) { - s_logger.warn("Fail to clean up old connection. " + e); + logger.warn("Fail to clean up old connection. {}", e); } while (_connection.isStartup()) { @@ -532,22 +549,22 @@ public class Agent implements HandlerFactory, IAgentControl { do { final String host = _shell.getNextHost(); _connection = new NioClient("Agent", host, _shell.getPort(), _shell.getWorkers(), this); - s_logger.info("Reconnecting to host:" + host); + logger.info("Reconnecting to host:{}", host); try { _connection.start(); } catch (final NioConnectionException e) { - s_logger.info("Attempted to re-connect to the server, but received an unexpected exception, trying again...", e); + logger.info("Attempted to re-connect to the server, but received an unexpected exception, trying again...", e); _connection.stop(); try { _connection.cleanUp(); } catch (final IOException ex) { - s_logger.warn("Fail to clean up old connection. " + ex); + logger.warn("Fail to clean up old connection. {}", ex); } } _shell.getBackoffAlgorithm().waitBeforeRetry(); } while (!_connection.isStartup()); _shell.updateConnectedHost(); - s_logger.info("Connected to the host: " + _shell.getConnectedHost()); + logger.info("Connected to the host: {}", _shell.getConnectedHost()); } public void processStartupAnswer(final Answer answer, final Response response, final Link link) { @@ -562,15 +579,15 @@ public class Agent implements HandlerFactory, IAgentControl { } final StartupAnswer startup = (StartupAnswer)answer; if (!startup.getResult()) { - s_logger.error("Not allowed to connect to the server: " + answer.getDetails()); + logger.error("Not allowed to connect to the server: {}", answer.getDetails()); System.exit(1); } if (cancelled) { - s_logger.warn("Threw away a startup answer because we're reconnecting."); + logger.warn("Threw away a startup answer because we're reconnecting."); return; } - s_logger.info("Process agent startup answer, agent id = " + startup.getHostId()); + logger.info("Process agent startup answer, agent id = {}", startup.getHostId()); setId(startup.getHostId()); _pingInterval = (long)startup.getPingInterval() * 1000; // change to ms. @@ -580,7 +597,7 @@ public class Agent implements HandlerFactory, IAgentControl { _ugentTaskPool.setKeepAliveTime(2 * _pingInterval, TimeUnit.MILLISECONDS); - s_logger.info("Startup Response Received: agent id = " + getId()); + logger.info("Startup Response Received: agent id = {}", getId()); } protected void processRequest(final Request request, final Link link) { @@ -595,18 +612,18 @@ public class Agent implements HandlerFactory, IAgentControl { Answer answer; try { if (cmd.getContextParam("logid") != null) { - MDC.put("logcontextid", cmd.getContextParam("logid")); + ThreadContext.put("logcontextid", cmd.getContextParam("logid")); } - if (s_logger.isDebugEnabled()) { + if (logger.isDebugEnabled()) { if (!requestLogged) // ensures request is logged only once per method call { final String requestMsg = request.toString(); if (requestMsg != null) { - s_logger.debug("Request:" + requestMsg); + logger.debug("Request:{}",requestMsg); } requestLogged = true; } - s_logger.debug("Processing command: " + cmd.toString()); + logger.debug("Processing command: {}", cmd.toString()); } if (cmd instanceof CronCommand) { @@ -615,7 +632,7 @@ public class Agent implements HandlerFactory, IAgentControl { answer = new Answer(cmd, true, null); } else if (cmd instanceof ShutdownCommand) { final ShutdownCommand shutdown = (ShutdownCommand)cmd; - s_logger.debug("Received shutdownCommand, due to: " + shutdown.getReason()); + logger.debug("Received shutdownCommand, due to: {}", shutdown.getReason()); cancelTasks(); if (shutdown.isRemoveHost()) { cleanupAgentZoneProperties(); @@ -623,11 +640,11 @@ public class Agent implements HandlerFactory, IAgentControl { _reconnectAllowed = false; answer = new Answer(cmd, true, null); } else if (cmd instanceof ReadyCommand && ((ReadyCommand)cmd).getDetails() != null) { - s_logger.debug("Not ready to connect to mgt server: " + ((ReadyCommand)cmd).getDetails()); + logger.debug("Not ready to connect to mgt server: {}", ((ReadyCommand)cmd).getDetails()); System.exit(1); return; } else if (cmd instanceof MaintainCommand) { - s_logger.debug("Received maintainCommand, do not cancel current tasks"); + logger.debug("Received maintainCommand, do not cancel current tasks"); answer = new MaintainAnswer((MaintainCommand)cmd); } else if (cmd instanceof AgentControlCommand) { answer = null; @@ -641,7 +658,7 @@ public class Agent implements HandlerFactory, IAgentControl { } if (answer == null) { - s_logger.warn("No handler found to process cmd: " + cmd.toString()); + logger.warn("No handler found to process cmd: {}", cmd.toString()); answer = new AgentControlAnswer(cmd); } } else if (cmd instanceof SetupKeyStoreCommand && ((SetupKeyStoreCommand) cmd).isHandleByAgent()) { @@ -664,12 +681,12 @@ public class Agent implements HandlerFactory, IAgentControl { _inProgress.decrementAndGet(); } if (answer == null) { - s_logger.debug("Response: unsupported command" + cmd.toString()); + logger.debug("Response: unsupported command {}", cmd.toString()); answer = Answer.createUnsupportedCommandAnswer(cmd); } } } catch (final Throwable th) { - s_logger.warn("Caught: ", th); + logger.warn("Caught: ", th); final StringWriter writer = new StringWriter(); th.printStackTrace(new PrintWriter(writer)); answer = new Answer(cmd, false, writer.toString()); @@ -685,10 +702,10 @@ public class Agent implements HandlerFactory, IAgentControl { } response = new Response(request, answers); } finally { - if (s_logger.isDebugEnabled()) { + if (logger.isDebugEnabled()) { final String responseMsg = response.toString(); if (responseMsg != null) { - s_logger.debug(response.toString()); + logger.debug(response.toString()); } } @@ -696,7 +713,7 @@ public class Agent implements HandlerFactory, IAgentControl { try { link.send(response.toBytes()); } catch (final ClosedChannelException e) { - s_logger.warn("Unable to send response: " + response.toString()); + logger.warn("Unable to send response: {}", response.toString()); } } } @@ -706,7 +723,7 @@ public class Agent implements HandlerFactory, IAgentControl { final String keyStorePassword = cmd.getKeystorePassword(); final long validityDays = cmd.getValidityDays(); - s_logger.debug("Setting up agent keystore file and generating CSR"); + logger.debug("Setting up agent keystore file and generating CSR"); final File agentFile = PropertiesUtil.findConfigFile("agent.properties"); if (agentFile == null) { @@ -721,7 +738,7 @@ public class Agent implements HandlerFactory, IAgentControl { _shell.setPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY, storedPassword); } - Script script = new Script(_keystoreSetupPath, 300000, s_logger); + Script script = new Script(_keystoreSetupPath, 300000, logger); script.add(agentFile.getAbsolutePath()); script.add(keyStoreFile); script.add(storedPassword); @@ -746,7 +763,7 @@ public class Agent implements HandlerFactory, IAgentControl { final String privateKey = cmd.getPrivateKey(); final String caCertificates = cmd.getCaCertificates(); - s_logger.debug("Importing received certificate to agent's keystore"); + logger.debug("Importing received certificate to agent's keystore"); final File agentFile = PropertiesUtil.findConfigFile("agent.properties"); if (agentFile == null) { @@ -760,13 +777,13 @@ public class Agent implements HandlerFactory, IAgentControl { try { FileUtils.writeStringToFile(new File(certFile), certificate, Charset.defaultCharset()); FileUtils.writeStringToFile(new File(caCertFile), caCertificates, Charset.defaultCharset()); - s_logger.debug("Saved received client certificate to: " + certFile); + logger.debug("Saved received client certificate to: {}", certFile); } catch (IOException e) { throw new CloudRuntimeException("Unable to save received agent client and ca certificates", e); } String ksPassphrase = _shell.getPersistentProperty(null, KeyStoreUtils.KS_PASSPHRASE_PROPERTY); - Script script = new Script(_keystoreCertImportPath, 300000, s_logger); + Script script = new Script(_keystoreCertImportPath, 300000, logger); script.add(agentFile.getAbsolutePath()); script.add(ksPassphrase); script.add(keyStoreFile); @@ -791,7 +808,7 @@ public class Agent implements HandlerFactory, IAgentControl { _shell.setPersistentProperty(null, "host", newMSHosts); _shell.setHosts(newMSHosts); _shell.resetHostCounter(); - s_logger.info("Processed new management server list: " + newMSHosts); + logger.info("Processed new management server list: {}", newMSHosts); } catch (final Exception e) { throw new CloudRuntimeException("Could not persist received management servers list", e); } @@ -810,9 +827,7 @@ public class Agent implements HandlerFactory, IAgentControl { public void processResponse(final Response response, final Link link) { final Answer answer = response.getAnswer(); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Received response: " + response.toString()); - } + logger.debug("Received response: {}", response.toString()); if (answer instanceof StartupAnswer) { processStartupAnswer(answer, response, link); } else if (answer instanceof AgentControlAnswer) { @@ -822,6 +837,9 @@ public class Agent implements HandlerFactory, IAgentControl { listener.processControlResponse(response, (AgentControlAnswer)answer); } } + } else if (answer instanceof PingAnswer && (((PingAnswer) answer).isSendStartup()) && _reconnectAllowed) { + logger.info("Management server requested startup command to reinitialize the agent"); + sendStartup(link); } else { setLastPingResponseTime(); } @@ -835,44 +853,42 @@ public class Agent implements HandlerFactory, IAgentControl { NumbersUtil.enableHumanReadableSizes = humanReadable; } - s_logger.info("Processing agent ready command, agent id = " + ready.getHostId()); + logger.info("Processing agent ready command, agent id = {}", ready.getHostId()); if (ready.getHostId() != null) { setId(ready.getHostId()); } processManagementServerList(ready.getMsHostList(), ready.getLbAlgorithm(), ready.getLbCheckInterval()); - s_logger.info("Ready command is processed for agent id = " + getId()); + logger.info("Ready command is processed for agent id = {}", getId()); } public void processOtherTask(final Task task) { final Object obj = task.get(); if (obj instanceof Response) { if (System.currentTimeMillis() - _lastPingResponseTime > _pingInterval * _shell.getPingRetries()) { - s_logger.error("Ping Interval has gone past " + _pingInterval * _shell.getPingRetries() + ". Won't reconnect to mgt server, as connection is still alive"); + logger.error("Ping Interval has gone past {}. Won't reconnect to mgt server, as connection is still alive", _pingInterval * _shell.getPingRetries()); return; } final PingCommand ping = _resource.getCurrentStatus(getId()); final Request request = new Request(_id, -1, ping, false); request.setSequence(getNextSequence()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Sending ping: " + request.toString()); - } + logger.debug("Sending ping: {}", request.toString()); try { task.getLink().send(request.toBytes()); //if i can send pingcommand out, means the link is ok setLastPingResponseTime(); } catch (final ClosedChannelException e) { - s_logger.warn("Unable to send request: " + request.toString()); + logger.warn("Unable to send request: {}", request.toString()); } } else if (obj instanceof Request) { final Request req = (Request)obj; final Command command = req.getCommand(); if (command.getContextParam("logid") != null) { - MDC.put("logcontextid", command.getContextParam("logid")); + ThreadContext.put("logcontextid", command.getContextParam("logid")); } Answer answer = null; _inProgress.incrementAndGet(); @@ -884,17 +900,15 @@ public class Agent implements HandlerFactory, IAgentControl { if (answer != null) { final Response response = new Response(req, answer); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Watch Sent: " + response.toString()); - } + logger.debug("Watch Sent: {}", response.toString()); try { task.getLink().send(response.toBytes()); } catch (final ClosedChannelException e) { - s_logger.warn("Unable to send response: " + response.toString()); + logger.warn("Unable to send response: {}", response.toString()); } } } else { - s_logger.warn("Ignoring an unknown task"); + logger.warn("Ignoring an unknown task"); } } @@ -934,7 +948,7 @@ public class Agent implements HandlerFactory, IAgentControl { try { listener.wait(timeoutInMilliseconds); } catch (final InterruptedException e) { - s_logger.warn("sendRequest is interrupted, exit waiting"); + logger.warn("sendRequest is interrupted, exit waiting"); } } @@ -956,7 +970,7 @@ public class Agent implements HandlerFactory, IAgentControl { try { _link.send(request.toBytes()); } catch (final ClosedChannelException e) { - s_logger.warn("Unable to post agent control request: " + request.toString()); + logger.warn("Unable to post agent control request: {}", request.toString()); throw new AgentControlChannelException("Unable to post agent control request due to " + e.getMessage()); } } else { @@ -1020,9 +1034,7 @@ public class Agent implements HandlerFactory, IAgentControl { @Override protected void runInContext() { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Scheduling " + (_request instanceof Response ? "Ping" : "Watch Task")); - } + logger.trace("Scheduling {}", (_request instanceof Response ? "Ping" : "Watch Task")); try { if (_request instanceof Response) { _ugentTaskPool.submit(new ServerHandler(Task.Type.OTHER, _link, _request)); @@ -1030,7 +1042,7 @@ public class Agent implements HandlerFactory, IAgentControl { _link.schedule(new ServerHandler(Task.Type.OTHER, _link, _request)); } } catch (final ClosedChannelException e) { - s_logger.warn("Unable to schedule task because channel is closed"); + logger.warn("Unable to schedule task because channel is closed"); } } } @@ -1040,7 +1052,7 @@ public class Agent implements HandlerFactory, IAgentControl { protected volatile boolean cancelled = false; public StartupTask(final Link link) { - s_logger.debug("Startup task created"); + logger.debug("Startup task created"); _link = link; } @@ -1050,7 +1062,7 @@ public class Agent implements HandlerFactory, IAgentControl { if (!cancelled) { cancelled = true; _startupWait = _startupWaitDefault; - s_logger.debug("Startup task cancelled"); + logger.debug("Startup task cancelled"); return super.cancel(); } return true; @@ -1059,9 +1071,7 @@ public class Agent implements HandlerFactory, IAgentControl { @Override protected synchronized void runInContext() { if (!cancelled) { - if (s_logger.isInfoEnabled()) { - s_logger.info("The startup command is now cancelled"); - } + logger.info("The startup command is now cancelled"); cancelled = true; _startup = null; _startupWait = _startupWaitDefault * 2; @@ -1112,11 +1122,17 @@ public class Agent implements HandlerFactory, IAgentControl { _executor.submit(new AgentRequestHandler(getType(), getLink(), request)); } } catch (final ClassNotFoundException e) { - s_logger.error("Unable to find this request "); + logger.error("Unable to find this request "); } catch (final Exception e) { - s_logger.error("Error parsing task", e); + logger.error("Error parsing task", e); } } 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 + // wait 5 seconds before reconnecting + Thread.sleep(5000); + } catch (InterruptedException e) { + } reconnect(task.getLink()); return; } else if (task.getType() == Task.Type.OTHER) { @@ -1142,7 +1158,7 @@ public class Agent implements HandlerFactory, IAgentControl { while (true) { try { if (_inProgress.get() == 0) { - s_logger.debug("Running post certificate renewal task to restart services."); + logger.debug("Running post certificate renewal task to restart services."); // Let the resource perform any post certificate renewal cleanups _resource.executeRequest(new PostCertificateRenewalCommand()); @@ -1167,12 +1183,11 @@ public class Agent implements HandlerFactory, IAgentControl { shell.launchNewAgent(resource); return; } - if (s_logger.isTraceEnabled()) { - s_logger.debug("Other tasks are in progress, will retry post certificate renewal command after few seconds"); - } + logger.debug("Other tasks are in progress, will retry post certificate renewal command after few seconds"); + Thread.sleep(5000); } catch (final Exception e) { - s_logger.warn("Failed to execute post certificate renewal command:", e); + logger.warn("Failed to execute post certificate renewal command:", e); break; } } @@ -1190,29 +1205,26 @@ public class Agent implements HandlerFactory, IAgentControl { } final String preferredHost = msList[0]; final String connectedHost = _shell.getConnectedHost(); - if (s_logger.isTraceEnabled()) { - s_logger.trace("Running preferred host checker task, connected host=" + connectedHost + ", preferred host=" + preferredHost); - } + logger.trace("Running preferred host checker task, connected host={}, preferred host={}", connectedHost, preferredHost); + if (preferredHost != null && !preferredHost.equals(connectedHost) && _link != null) { boolean isHostUp = true; try (final Socket socket = new Socket()) { socket.connect(new InetSocketAddress(preferredHost, _shell.getPort()), 5000); } catch (final IOException e) { isHostUp = false; - if (s_logger.isTraceEnabled()) { - s_logger.trace("Host: " + preferredHost + " is not reachable"); - } + logger.trace("Host: {} is not reachable", preferredHost); + } if (isHostUp && _link != null && _inProgress.get() == 0) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Preferred host " + preferredHost + " is found to be reachable, trying to reconnect"); - } + logger.debug("Preferred host {} is found to be reachable, trying to reconnect", preferredHost); + _shell.resetHostCounter(); reconnect(_link); } } } catch (Throwable t) { - s_logger.error("Error caught while attempting to connect to preferred host", t); + logger.error("Error caught while attempting to connect to preferred host", t); } } diff --git a/agent/src/main/java/com/cloud/agent/AgentShell.java b/agent/src/main/java/com/cloud/agent/AgentShell.java index ef042496a37..0699e00250b 100644 --- a/agent/src/main/java/com/cloud/agent/AgentShell.java +++ b/agent/src/main/java/com/cloud/agent/AgentShell.java @@ -34,8 +34,9 @@ import org.apache.commons.daemon.DaemonInitException; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; -import org.apache.log4j.xml.DOMConfigurator; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.config.Configurator; import javax.naming.ConfigurationException; import java.io.File; @@ -53,7 +54,7 @@ import java.util.Properties; import java.util.UUID; public class AgentShell implements IAgentShell, Daemon { - private static final Logger s_logger = Logger.getLogger(AgentShell.class.getName()); + protected static Logger LOGGER = LogManager.getLogger(AgentShell.class); private final Properties _properties = new Properties(); private final Map _cmdLineProperties = new HashMap(); @@ -221,7 +222,7 @@ public class AgentShell implements IAgentShell, Daemon { throw new ConfigurationException("Unable to find agent.properties."); } - s_logger.info("agent.properties found at " + file.getAbsolutePath()); + LOGGER.info("agent.properties found at {}", file.getAbsolutePath()); try { PropertiesUtil.loadFromFile(_properties, file); @@ -349,7 +350,7 @@ public class AgentShell implements IAgentShell, Daemon { @Override public void init(DaemonContext dc) throws DaemonInitException { - s_logger.debug("Initializing AgentShell from JSVC"); + LOGGER.debug("Initializing AgentShell from JSVC"); try { init(dc.getArguments()); } catch (ConfigurationException ex) { @@ -369,11 +370,11 @@ public class AgentShell implements IAgentShell, Daemon { } if (null != file) { - DOMConfigurator.configureAndWatch(file.getAbsolutePath()); + Configurator.initialize(null, file.getAbsolutePath()); - s_logger.info("Agent started"); + LOGGER.info("Agent started"); } else { - s_logger.error("Could not start the Agent because the absolute path of the \"log4j-cloud.xml\" file cannot be determined."); + LOGGER.error("Could not start the Agent because the absolute path of the \"log4j-cloud.xml\" file cannot be determined."); } final Class c = this.getClass(); @@ -381,19 +382,19 @@ public class AgentShell implements IAgentShell, Daemon { if (_version == null) { throw new CloudRuntimeException("Unable to find the implementation version of this agent"); } - s_logger.info("Implementation Version is " + _version); + LOGGER.info("Implementation Version is {}", _version); loadProperties(); parseCommand(args); - if (s_logger.isDebugEnabled()) { + if (LOGGER.isDebugEnabled()) { List properties = Collections.list((Enumeration)_properties.propertyNames()); for (String property : properties) { - s_logger.debug("Found property: " + property); + LOGGER.debug("Found property: {}", property); } } - s_logger.info("Defaulting to using properties file for storage"); + LOGGER.info("Defaulting to using properties file for storage"); _storage = new PropertiesStorage(); _storage.configure("Storage", new HashMap()); @@ -403,14 +404,14 @@ public class AgentShell implements IAgentShell, Daemon { _properties.put(cmdLineProp.getKey(), cmdLineProp.getValue()); } - s_logger.info("Defaulting to the constant time backoff algorithm"); + LOGGER.info("Defaulting to the constant time backoff algorithm"); _backoff = new ConstantTimeBackoff(); _backoff.configure("ConstantTimeBackoff", new HashMap()); } private void launchAgent() throws ConfigurationException { String resourceClassNames = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.RESOURCE); - s_logger.trace("resource=" + resourceClassNames); + LOGGER.trace("resource={}", resourceClassNames); if (resourceClassNames != null) { launchAgentFromClassInfo(resourceClassNames); return; @@ -440,10 +441,10 @@ public class AgentShell implements IAgentShell, Daemon { private void launchAgentFromTypeInfo() throws ConfigurationException { String typeInfo = getProperty(null, "type"); if (typeInfo == null) { - s_logger.error("Unable to retrieve the type"); + LOGGER.error("Unable to retrieve the type"); throw new ConfigurationException("Unable to retrieve the type of this agent."); } - s_logger.trace("Launching agent based on type=" + typeInfo); + LOGGER.trace("Launching agent based on type={}", typeInfo); } public void launchNewAgent(ServerResource resource) throws ConfigurationException { @@ -477,17 +478,17 @@ public class AgentShell implements IAgentShell, Daemon { } if (ipv6disabled) { - s_logger.info("Preferring IPv4 address family for agent connection"); + LOGGER.info("Preferring IPv4 address family for agent connection"); System.setProperty("java.net.preferIPv4Stack", "true"); if (ipv6prefer) { - s_logger.info("ipv6prefer is set to true, but ipv6disabled is false. Not preferring IPv6 for agent connection"); + LOGGER.info("ipv6prefer is set to true, but ipv6disabled is false. Not preferring IPv6 for agent connection"); } } else { if (ipv6prefer) { - s_logger.info("Preferring IPv6 address family for agent connection"); + LOGGER.info("Preferring IPv6 address family for agent connection"); System.setProperty("java.net.preferIPv6Addresses", "true"); } else { - s_logger.info("Using default Java settings for IPv6 preference for agent connection"); + LOGGER.info("Using default Java settings for IPv6 preference for agent connection"); } } @@ -505,7 +506,7 @@ public class AgentShell implements IAgentShell, Daemon { String pidDir = getProperty(null, "piddir"); final String run = "agent." + instance + "pid"; - s_logger.debug("Checking to see if " + run + " exists."); + LOGGER.debug("Checking to see if {} exists.", run); ProcessUtil.pidCheck(pidDir, run); launchAgent(); @@ -514,11 +515,11 @@ public class AgentShell implements IAgentShell, Daemon { while (!_exit) Thread.sleep(1000); } catch (InterruptedException e) { - s_logger.debug("[ignored] AgentShell was interrupted."); + LOGGER.debug("[ignored] AgentShell was interrupted."); } } catch (final Exception e) { - s_logger.error("Unable to start agent: ", e); + LOGGER.error("Unable to start agent: ", e); System.exit(ExitStatus.Error.value()); } } @@ -535,7 +536,7 @@ public class AgentShell implements IAgentShell, Daemon { public static void main(String[] args) { try { - s_logger.debug("Initializing AgentShell from main"); + LOGGER.debug("Initializing AgentShell from main"); AgentShell shell = new AgentShell(); shell.init(args); shell.start(); diff --git a/agent/src/main/java/com/cloud/agent/dao/impl/PropertiesStorage.java b/agent/src/main/java/com/cloud/agent/dao/impl/PropertiesStorage.java index a1db88c86c4..17e0ceeeede 100644 --- a/agent/src/main/java/com/cloud/agent/dao/impl/PropertiesStorage.java +++ b/agent/src/main/java/com/cloud/agent/dao/impl/PropertiesStorage.java @@ -24,7 +24,8 @@ import java.util.Map; import java.util.Properties; import org.apache.commons.io.IOUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import com.cloud.agent.dao.StorageComponent; import com.cloud.utils.PropertiesUtil; @@ -36,7 +37,7 @@ import com.cloud.utils.PropertiesUtil; * path to the properties _file | String | db/db.properties || * } **/ public class PropertiesStorage implements StorageComponent { - private static final Logger s_logger = Logger.getLogger(PropertiesStorage.class); + protected Logger logger = LogManager.getLogger(getClass()); Properties _properties = new Properties(); File _file; String _name; @@ -49,7 +50,7 @@ public class PropertiesStorage implements StorageComponent { @Override public synchronized void persist(String key, String value) { if (!loadFromFile(_file)) { - s_logger.error("Failed to load changes and then write to them"); + logger.error("Failed to load changes and then write to them"); } _properties.setProperty(key, value); FileOutputStream output = null; @@ -59,7 +60,7 @@ public class PropertiesStorage implements StorageComponent { output.flush(); output.close(); } catch (IOException e) { - s_logger.error("Uh-oh: ", e); + logger.error("Uh-oh: ", e); } finally { IOUtils.closeQuietly(output); } @@ -70,10 +71,10 @@ public class PropertiesStorage implements StorageComponent { PropertiesUtil.loadFromFile(_properties, file); _file = file; } catch (FileNotFoundException e) { - s_logger.error("How did we get here? ", e); + logger.error("How did we get here? ", e); return false; } catch (IOException e) { - s_logger.error("IOException: ", e); + logger.error("IOException: ", e); return false; } return true; @@ -92,11 +93,12 @@ public class PropertiesStorage implements StorageComponent { file = new File(path); try { if (!file.createNewFile()) { - s_logger.error("Unable to create _file: " + file.getAbsolutePath()); + logger.error("Unable to create _file: {}", file.getAbsolutePath()); return false; } } catch (IOException e) { - s_logger.error("Unable to create _file: " + file.getAbsolutePath(), e); + logger.error("Unable to create file: {}", file.getAbsolutePath()); + logger.debug("IOException while trying to create file: {}", file.getAbsolutePath(), e); return false; } } diff --git a/agent/src/main/java/com/cloud/agent/dhcp/DhcpProtocolParserServer.java b/agent/src/main/java/com/cloud/agent/dhcp/DhcpProtocolParserServer.java index 0ee9fd6860d..00488f94382 100644 --- a/agent/src/main/java/com/cloud/agent/dhcp/DhcpProtocolParserServer.java +++ b/agent/src/main/java/com/cloud/agent/dhcp/DhcpProtocolParserServer.java @@ -25,12 +25,13 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import org.apache.log4j.Logger; import com.cloud.utils.concurrency.NamedThreadFactory; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; public class DhcpProtocolParserServer extends Thread { - private static final Logger s_logger = Logger.getLogger(DhcpProtocolParserServer.class);; + protected Logger logger = LogManager.getLogger(DhcpProtocolParserServer.class);; protected ExecutorService _executor; private int dhcpServerPort = 67; private int bufferSize = 300; @@ -54,7 +55,7 @@ public class DhcpProtocolParserServer extends Thread { dhcpSocket.receive(dgp); } } catch (IOException e) { - s_logger.debug(e.getMessage()); + logger.debug(e.getMessage()); } } } diff --git a/agent/src/main/java/com/cloud/agent/dhcp/FakeDhcpSnooper.java b/agent/src/main/java/com/cloud/agent/dhcp/FakeDhcpSnooper.java deleted file mode 100644 index c42a5af814d..00000000000 --- a/agent/src/main/java/com/cloud/agent/dhcp/FakeDhcpSnooper.java +++ /dev/null @@ -1,161 +0,0 @@ -// 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.dhcp; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; - -import javax.naming.ConfigurationException; - -import org.apache.log4j.Logger; - -import com.cloud.utils.Pair; -import com.cloud.utils.net.NetUtils; - -public class FakeDhcpSnooper implements DhcpSnooper { - private static final Logger s_logger = Logger.getLogger(FakeDhcpSnooper.class); - private Queue _ipAddresses = new ConcurrentLinkedQueue(); - private Map _macIpMap = new ConcurrentHashMap(); - private Map _vmIpMap = new ConcurrentHashMap(); - - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - String guestIpRange = (String)params.get("guest.ip.range"); - if (guestIpRange != null) { - String[] guestIps = guestIpRange.split("-"); - if (guestIps.length == 2) { - long start = NetUtils.ip2Long(guestIps[0]); - long end = NetUtils.ip2Long(guestIps[1]); - while (start <= end) { - _ipAddresses.offer(NetUtils.long2Ip(start++)); - } - } - } - return true; - } - - @Override - public boolean start() { - return true; - } - - @Override - public String getName() { - return "FakeDhcpSnooper"; - } - - @Override - public InetAddress getIPAddr(String macAddr, String vmName) { - String ipAddr = _ipAddresses.poll(); - if (ipAddr == null) { - s_logger.warn("No ip addresses left in queue"); - return null; - } - try { - InetAddress inetAddr = InetAddress.getByName(ipAddr); - _macIpMap.put(macAddr.toLowerCase(), ipAddr); - _vmIpMap.put(vmName, inetAddr); - s_logger.info("Got ip address " + ipAddr + " for vm " + vmName + " mac=" + macAddr.toLowerCase()); - return inetAddr; - } catch (UnknownHostException e) { - s_logger.warn("Failed to get InetAddress for " + ipAddr); - return null; - } - } - - @Override - public void cleanup(String macAddr, String vmName) { - try { - if (macAddr == null) { - return; - } - InetAddress inetAddr = _vmIpMap.remove(vmName); - String ipAddr = inetAddr.getHostName(); - for (Map.Entry entry : _macIpMap.entrySet()) { - if (entry.getValue().equalsIgnoreCase(ipAddr)) { - macAddr = entry.getKey(); - break; - } - } - ipAddr = _macIpMap.remove(macAddr); - - s_logger.info("Cleaning up for mac address: " + macAddr + " ip=" + ipAddr + " inetAddr=" + inetAddr); - if (ipAddr != null) { - _ipAddresses.offer(ipAddr); - } - } catch (Exception e) { - s_logger.debug("Failed to cleanup: " + e.toString()); - } - } - - @Override - public Map syncIpAddr() { - return _vmIpMap; - } - - @Override - public boolean stop() { - return false; - } - - @Override - public void initializeMacTable(List> macVmNameList) { - - } - - @Override - public InetAddress getDhcpServerIP() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setName(String name) { - // TODO Auto-generated method stub - - } - - @Override - public void setConfigParams(Map params) { - // TODO Auto-generated method stub - - } - - @Override - public Map getConfigParams() { - // TODO Auto-generated method stub - return null; - } - - @Override - public int getRunLevel() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public void setRunLevel(int level) { - // TODO Auto-generated method stub - - } - -} diff --git a/agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java b/agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java index b155cb725b1..54fdde3d3d2 100644 --- a/agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java +++ b/agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java @@ -22,14 +22,15 @@ import java.util.Map; import java.util.Random; import java.util.Set; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.VirtualMachine.State; public class MockVmMgr implements VmMgr { - private static final Logger s_logger = Logger.getLogger(MockVmMgr.class); + protected Logger logger = LogManager.getLogger(getClass()); private static final int DEFAULT_DOM0_MEM_MB = 128; private static final Random randSeed = new Random(); @@ -56,14 +57,14 @@ public class MockVmMgr implements VmMgr { public String startVM(String vmName, String vnetId, String gateway, String dns, String privateIP, String privateMac, String privateMask, String publicIP, String publicMac, String publicMask, int cpuCount, int cpuUtilization, long ramSize, String localPath, String vncPassword) { - if (s_logger.isInfoEnabled()) { + if (logger.isInfoEnabled()) { StringBuffer sb = new StringBuffer(); sb.append("Start VM. name: " + vmName + ", vnet: " + vnetId + ", dns: " + dns); sb.append(", privateIP: " + privateIP + ", privateMac: " + privateMac + ", privateMask: " + privateMask); sb.append(", publicIP: " + publicIP + ", publicMac: " + publicMac + ", publicMask: " + publicMask); sb.append(", cpu count: " + cpuCount + ", cpuUtilization: " + cpuUtilization + ", ram : " + ramSize); sb.append(", localPath: " + localPath); - s_logger.info(sb.toString()); + logger.info(sb.toString()); } synchronized (this) { @@ -86,8 +87,7 @@ public class MockVmMgr implements VmMgr { @Override public String stopVM(String vmName, boolean force) { - if (s_logger.isInfoEnabled()) - s_logger.info("Stop VM. name: " + vmName); + logger.info("Stop VM. name: {}", vmName); synchronized (this) { MockVm vm = vms.get(vmName); @@ -102,8 +102,7 @@ public class MockVmMgr implements VmMgr { @Override public String rebootVM(String vmName) { - if (s_logger.isInfoEnabled()) - s_logger.info("Reboot VM. name: " + vmName); + logger.info("Reboot VM. name: {}", vmName); synchronized (this) { MockVm vm = vms.get(vmName); @@ -115,8 +114,7 @@ public class MockVmMgr implements VmMgr { @Override public boolean migrate(String vmName, String params) { - if (s_logger.isInfoEnabled()) - s_logger.info("Migrate VM. name: " + vmName); + logger.info("Migrate VM. name: {}", vmName); synchronized (this) { MockVm vm = vms.get(vmName); @@ -258,13 +256,13 @@ public class MockVmMgr implements VmMgr { vm = vms.get(vmName); if (vm == null) { if (ramSize > getHostFreeMemory()) { - s_logger.debug("host is out of memory"); + logger.debug("host is out of memory"); throw new CloudRuntimeException("Host is out of Memory"); } int vncPort = allocVncPort(); if (vncPort < 0) { - s_logger.debug("Unable to allocate VNC port"); + logger.debug("Unable to allocate VNC port"); throw new CloudRuntimeException("Unable to allocate vnc port"); } diff --git a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java index 75248fb01bf..8f97edc3935 100644 --- a/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java +++ b/agent/src/main/java/com/cloud/agent/properties/AgentProperties.java @@ -14,6 +14,8 @@ */ package com.cloud.agent.properties; +import org.apache.cloudstack.utils.security.KeyStoreUtils; + /** * Class of constant agent's properties available to configure on * "agent.properties". @@ -502,6 +504,15 @@ public class AgentProperties{ */ public static final Property HOST_RESERVED_MEM_MB = new Property<>("host.reserved.mem.mb", 1024); + /** + * How many host CPUs to reserve for non-allocation.
+ * This can be used to set aside CPU cores on the host for other tasks, such as running hyperconverged storage
+ * processes, etc. + * Data type: Integer.
+ * Default value: 0 + */ + public static final Property HOST_RESERVED_CPU_CORE_COUNT = new Property<>("host.reserved.cpu.count", 0); + /** * The model of Watchdog timer to present to the Guest.
* For all models refer to the libvirt documentation.
@@ -530,10 +541,10 @@ public class AgentProperties{ /** * Heartbeat update timeout (in ms).
* Depending on the use case, this timeout might need increasing/decreasing.
- * Data type: Integer.
- * Default value: 60000 + * Data type: Long.
+ * Default value: 60000L */ - public static final Property HEARTBEAT_UPDATE_TIMEOUT = new Property<>("heartbeat.update.timeout", 60000); + public static final Property HEARTBEAT_UPDATE_TIMEOUT = new Property<>("heartbeat.update.timeout", 60000L); /** * The timeout (in seconds) to retrieve the target's domain ID when migrating a VM with KVM.
@@ -648,6 +659,14 @@ public class AgentProperties{ */ public static final Property STOP_SCRIPT_TIMEOUT = new Property<>("stop.script.timeout", 120); + /** + * Time (in seconds) to wait for scripts to complete.
+ * This is currently used only while checking if the host supports UEFI.
+ * Data type: Integer.
+ * Default value: 60 + */ + public static final Property AGENT_SCRIPT_TIMEOUT = new Property<>("agent.script.timeout", 60); + /** * Definition of VMs video model type.
* Data type: String.
@@ -676,6 +695,13 @@ public class AgentProperties{ */ public static final Property DEVELOPER = new Property<>("developer", false); + /** + * If set to "true", the agent will register for libvirt domain events, allowing for immediate updates on crashed or unexpectedly + * stopped VMs. Experimental, requires agent restart. + * Default value: false + */ + public static final Property LIBVIRT_EVENTS_ENABLED = new Property<>("libvirt.events.enabled", false); + /** * Can only be used if developer = true. This property is used to define the local bridge name and private network name.
* Data type: String.
@@ -724,6 +750,13 @@ public class AgentProperties{ */ public static final Property IOTHREADS = new Property<>("iothreads", 1); + /** + * Enable verbose mode for virt-v2v Instance Conversion from VMware to KVM + * Data type: Boolean.
+ * Default value: false + */ + public static final Property VIRTV2V_VERBOSE_ENABLED = new Property<>("virtv2v.verbose.enabled", false); + /** * BGP controll CIDR * Data type: String.
@@ -731,6 +764,52 @@ public class AgentProperties{ */ public static final Property CONTROL_CIDR = new Property<>("control.cidr", "169.254.0.0/16"); + /** + * Time interval (in milliseconds) between KVM heartbeats.
+ * This property is for KVM only. + * Data type: Long.
+ * Default value: 60000l + */ + public static final Property KVM_HEARTBEAT_UPDATE_FREQUENCY = new Property<>("kvm.heartbeat.update.frequency", 60000L); + + /** + * Number of maximum tries to KVM heartbeats.
+ * This property is for KVM only. + * Data type: Long.
+ * Default value: 5l + */ + public static final Property KVM_HEARTBEAT_UPDATE_MAX_TRIES = new Property<>("kvm.heartbeat.update.max.tries", 5L); + + /** + * Time amount (in milliseconds) for the KVM heartbeat retry sleep.
+ * This property is for KVM only. + * Data type: Long.
+ * Default value: 10000l + */ + public static final Property KVM_HEARTBEAT_UPDATE_RETRY_SLEEP = new Property<>("kvm.heartbeat.update.retry.sleep", 10000L); + + /** + * Timeout (in milliseconds) of the KVM heartbeat checker.
+ * This property is for KVM only. + * Data type: Long.
+ * Default value: 360000l + */ + public static final Property KVM_HEARTBEAT_CHECKER_TIMEOUT = new Property<>("kvm.heartbeat.checker.timeout", 360000L); + + /** + * Keystore passphrase + * Data type: String.
+ * Default value: null + */ + public static final Property KEYSTORE_PASSPHRASE = new Property<>(KeyStoreUtils.KS_PASSPHRASE_PROPERTY, null, String.class); + + /** + * Implicit host tags + * Data type: String.
+ * Default value: null + */ + public static final Property HOST_TAGS = new Property<>("host.tags", null, String.class); + public static class Property { private String name; private T defaultValue; diff --git a/agent/src/main/java/com/cloud/agent/properties/AgentPropertiesFileHandler.java b/agent/src/main/java/com/cloud/agent/properties/AgentPropertiesFileHandler.java index 602aa1efcb0..b28018fcd94 100644 --- a/agent/src/main/java/com/cloud/agent/properties/AgentPropertiesFileHandler.java +++ b/agent/src/main/java/com/cloud/agent/properties/AgentPropertiesFileHandler.java @@ -22,7 +22,8 @@ import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.beanutils.converters.IntegerConverter; import org.apache.commons.beanutils.converters.LongConverter; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; /** * This class provides a facility to read the agent's properties file and get @@ -31,7 +32,7 @@ import org.apache.log4j.Logger; */ public class AgentPropertiesFileHandler { - private static final Logger logger = Logger.getLogger(AgentPropertiesFileHandler.class); + protected static Logger LOGGER = LogManager.getLogger(AgentPropertiesFileHandler.class); /** * This method reads the property in the agent.properties file. @@ -47,7 +48,7 @@ public class AgentPropertiesFileHandler { File agentPropertiesFile = PropertiesUtil.findConfigFile(KeyStoreUtils.AGENT_PROPSFILE); if (agentPropertiesFile == null) { - logger.debug(String.format("File [%s] was not found, we will use default defined values. Property [%s]: [%s].", KeyStoreUtils.AGENT_PROPSFILE, name, defaultValue)); + LOGGER.debug("File [{}] was not found, we will use default defined values. Property [{}]: [{}].", KeyStoreUtils.AGENT_PROPSFILE, name, defaultValue); return defaultValue; } @@ -55,7 +56,7 @@ public class AgentPropertiesFileHandler { try { String configValue = PropertiesUtil.loadFromFile(agentPropertiesFile).getProperty(name); if (StringUtils.isBlank(configValue)) { - logger.debug(String.format("Property [%s] has empty or null value. Using default value [%s].", name, defaultValue)); + LOGGER.debug("Property [{}] has empty or null value. Using default value [{}].", name, defaultValue); return defaultValue; } @@ -67,11 +68,11 @@ public class AgentPropertiesFileHandler { ConvertUtils.register(new LongConverter(defaultValue), Long.class); } - logger.debug(String.format("Property [%s] was altered. Now using the value [%s].", name, configValue)); + LOGGER.debug("Property [{}] was altered. Now using the value [{}].", name, configValue); return (T)ConvertUtils.convert(configValue, property.getTypeClass()); } catch (IOException ex) { - logger.debug(String.format("Failed to get property [%s]. Using default value [%s].", name, defaultValue), ex); + LOGGER.debug("Failed to get property [{}]. Using default value [{}].", name, defaultValue, ex); } return defaultValue; diff --git a/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java b/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java index 5b04f5751e3..ccd0d976e58 100644 --- a/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java +++ b/agent/src/main/java/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java @@ -34,7 +34,6 @@ import javax.naming.ConfigurationException; import com.cloud.agent.api.proxy.AllowConsoleAccessCommand; import org.apache.cloudstack.managed.context.ManagedContextRunnable; -import org.apache.log4j.Logger; import com.cloud.agent.Agent.ExitStatus; import com.cloud.agent.api.AgentControlAnswer; @@ -81,18 +80,17 @@ import com.google.gson.Gson; * */ public class ConsoleProxyResource extends ServerResourceBase implements ServerResource { - static final Logger s_logger = Logger.getLogger(ConsoleProxyResource.class); - private final Properties _properties = new Properties(); - private Thread _consoleProxyMain = null; + private final Properties properties = new Properties(); + private Thread consoleProxyMain = null; - long _proxyVmId; - int _proxyPort; + long proxyVmId; + int proxyPort; - String _localgw; - String _eth1ip; - String _eth1mask; - String _pubIp; + String localGateway; + String eth1Ip; + String eth1Mask; + String publicIp; @Override public Answer executeRequest(final Command cmd) { @@ -101,7 +99,7 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe } else if (cmd instanceof WatchConsoleProxyLoadCommand) { return execute((WatchConsoleProxyLoadCommand)cmd); } else if (cmd instanceof ReadyCommand) { - s_logger.info("Receive ReadyCommand, response with ReadyAnswer"); + logger.info("Receive ReadyCommand, response with ReadyAnswer"); return new ReadyAnswer((ReadyCommand)cmd); } else if (cmd instanceof CheckHealthCommand) { return new CheckHealthAnswer((CheckHealthCommand)cmd, true); @@ -123,13 +121,13 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe return new Answer(cmd); } catch (SecurityException | NoSuchMethodException | ClassNotFoundException | InvocationTargetException | IllegalAccessException e) { String errorMsg = "Unable to add allowed session due to: " + e.getMessage(); - s_logger.error(errorMsg, e); + logger.error(errorMsg, e); return new Answer(cmd, false, errorMsg); } } private Answer execute(StartConsoleProxyAgentHttpHandlerCommand cmd) { - s_logger.info("Invoke launchConsoleProxy() in responding to StartConsoleProxyAgentHttpHandlerCommand"); + logger.info("Invoke launchConsoleProxy() in responding to StartConsoleProxyAgentHttpHandlerCommand"); launchConsoleProxy(cmd.getKeystoreBits(), cmd.getKeystorePassword(), cmd.getEncryptorPassword(), cmd.isSourceIpCheckEnabled()); return new Answer(cmd); } @@ -140,7 +138,7 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe { out.write("0"); } catch (IOException e) { - s_logger.warn("Unable to disable rp_filter"); + logger.warn("Unable to disable rp_filter"); } } @@ -177,12 +175,12 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe try { is.close(); } catch (final IOException e) { - s_logger.warn("Exception when closing , console proxy address : " + proxyManagementIp); + logger.warn("Exception when closing , console proxy address : {}", proxyManagementIp); success = false; } } } catch (final IOException e) { - s_logger.warn("Unable to open console proxy command port url, console proxy address : " + proxyManagementIp); + logger.warn("Unable to open console proxy command port url, console proxy address : {}", proxyManagementIp); success = false; } @@ -203,10 +201,10 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe public synchronized StartupCommand[] initialize() { final StartupProxyCommand cmd = new StartupProxyCommand(); fillNetworkInformation(cmd); - cmd.setProxyPort(_proxyPort); - cmd.setProxyVmId(_proxyVmId); - if (_pubIp != null) - cmd.setPublicIpAddress(_pubIp); + cmd.setProxyPort(proxyPort); + cmd.setProxyVmId(proxyVmId); + if (publicIp != null) + cmd.setPublicIpAddress(publicIp); return new StartupCommand[] {cmd}; } @@ -221,79 +219,78 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe @Override public boolean configure(String name, Map params) throws ConfigurationException { - _localgw = (String)params.get("localgw"); - _eth1mask = (String)params.get("eth1mask"); - _eth1ip = (String)params.get("eth1ip"); - if (_eth1ip != null) { + localGateway = (String)params.get("localgw"); + eth1Mask = (String)params.get("eth1mask"); + eth1Ip = (String)params.get("eth1ip"); + if (eth1Ip != null) { params.put("private.network.device", "eth1"); } else { - s_logger.info("eth1ip parameter has not been configured, assuming that we are not inside a system vm"); + logger.info("eth1ip parameter has not been configured, assuming that we are not inside a system vm"); } String eth2ip = (String)params.get("eth2ip"); if (eth2ip != null) { params.put("public.network.device", "eth2"); } else { - s_logger.info("eth2ip parameter is not found, assuming that we are not inside a system vm"); + logger.info("eth2ip parameter is not found, assuming that we are not inside a system vm"); } super.configure(name, params); for (Map.Entry entry : params.entrySet()) { - _properties.put(entry.getKey(), entry.getValue()); + properties.put(entry.getKey(), entry.getValue()); } String value = (String)params.get("premium"); if (value != null && value.equals("premium")) - _proxyPort = 443; + proxyPort = 443; else { value = (String)params.get("consoleproxy.httpListenPort"); - _proxyPort = NumbersUtil.parseInt(value, 80); + proxyPort = NumbersUtil.parseInt(value, 80); } value = (String)params.get("proxy_vm"); - _proxyVmId = NumbersUtil.parseLong(value, 0); + proxyVmId = NumbersUtil.parseLong(value, 0); - if (_localgw != null) { + if (localGateway != null) { String mgmtHosts = (String)params.get("host"); - if (_eth1ip != null) { + if (eth1Ip != null) { for (final String mgmtHost : mgmtHosts.split(",")) { - addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, mgmtHost); + addRouteToInternalIpOrCidr(localGateway, eth1Ip, eth1Mask, mgmtHost); } String internalDns1 = (String) params.get("internaldns1"); if (internalDns1 == null) { - s_logger.warn("No DNS entry found during configuration of ConsoleProxy"); + logger.warn("No DNS entry found during configuration of ConsoleProxy"); } else { - addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, internalDns1); + addRouteToInternalIpOrCidr(localGateway, eth1Ip, eth1Mask, internalDns1); } String internalDns2 = (String) params.get("internaldns2"); if (internalDns2 != null) { - addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, internalDns2); + addRouteToInternalIpOrCidr(localGateway, eth1Ip, eth1Mask, internalDns2); } } } - _pubIp = (String)params.get("public.ip"); + publicIp = (String)params.get("public.ip"); value = (String)params.get("disable_rp_filter"); if (value != null && value.equalsIgnoreCase("true")) { disableRpFilter(); } - if (s_logger.isInfoEnabled()) - s_logger.info("Receive proxyVmId in ConsoleProxyResource configuration as " + _proxyVmId); + logger.info("Receive proxyVmId in ConsoleProxyResource configuration as {}", proxyVmId); return true; } private void addRouteToInternalIpOrCidr(String localgw, String eth1ip, String eth1mask, String destIpOrCidr) { - s_logger.debug("addRouteToInternalIp: localgw=" + localgw + ", eth1ip=" + eth1ip + ", eth1mask=" + eth1mask + ",destIp=" + destIpOrCidr); + logger.debug("addRouteToInternalIp: localgw={}, eth1ip={}, eth1mask={}, destIp={}", localgw, eth1ip, eth1mask, destIpOrCidr); if (destIpOrCidr == null) { - s_logger.debug("addRouteToInternalIp: destIp is null"); + logger.debug("addRouteToInternalIp: destIp is null"); return; } if (!NetUtils.isValidIp4(destIpOrCidr) && !NetUtils.isValidIp4Cidr(destIpOrCidr)) { - s_logger.warn(" destIp is not a valid ip address or cidr destIp=" + destIpOrCidr); + logger.warn(" destIp is not a valid ip address or cidr destIp={}", destIpOrCidr); return; } boolean inSameSubnet = false; @@ -301,75 +298,75 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe if (eth1ip != null && eth1mask != null) { inSameSubnet = NetUtils.sameSubnet(eth1ip, destIpOrCidr, eth1mask); } else { - s_logger.warn("addRouteToInternalIp: unable to determine same subnet: _eth1ip=" + eth1ip + ", dest ip=" + destIpOrCidr + ", _eth1mask=" + eth1mask); + logger.warn("addRouteToInternalIp: unable to determine same subnet: eth1ip={}, dest ip={}, eth1mask={}", eth1ip, destIpOrCidr, eth1mask); } } else { inSameSubnet = NetUtils.isNetworkAWithinNetworkB(destIpOrCidr, NetUtils.ipAndNetMaskToCidr(eth1ip, eth1mask)); } if (inSameSubnet) { - s_logger.debug("addRouteToInternalIp: dest ip " + destIpOrCidr + " is in the same subnet as eth1 ip " + eth1ip); + logger.debug("addRouteToInternalIp: dest ip {} is in the same subnet as eth1 ip {}", destIpOrCidr, eth1ip); return; } - Script command = new Script("/bin/bash", s_logger); + Script command = new Script("/bin/bash", logger); command.add("-c"); command.add("ip route delete " + destIpOrCidr); command.execute(); - command = new Script("/bin/bash", s_logger); + command = new Script("/bin/bash", logger); command.add("-c"); command.add("ip route add " + destIpOrCidr + " via " + localgw); String result = command.execute(); if (result != null) { - s_logger.warn("Error in configuring route to internal ip err=" + result); + logger.warn("Error in configuring route to internal ip err={}", result); } else { - s_logger.debug("addRouteToInternalIp: added route to internal ip=" + destIpOrCidr + " via " + localgw); + logger.debug("addRouteToInternalIp: added route to internal ip={} via {}", destIpOrCidr, localgw); } } @Override public String getName() { - return _name; + return name; } private void launchConsoleProxy(final byte[] ksBits, final String ksPassword, final String encryptorPassword, final Boolean isSourceIpCheckEnabled) { final Object resource = this; - s_logger.info("Building class loader for com.cloud.consoleproxy.ConsoleProxy"); - if (_consoleProxyMain == null) { - s_logger.info("Running com.cloud.consoleproxy.ConsoleProxy with encryptor password=" + encryptorPassword); - _consoleProxyMain = new Thread(new ManagedContextRunnable() { + logger.info("Building class loader for com.cloud.consoleproxy.ConsoleProxy"); + if (consoleProxyMain == null) { + logger.info("Running com.cloud.consoleproxy.ConsoleProxy with encryptor password={}", encryptorPassword); + consoleProxyMain = new Thread(new ManagedContextRunnable() { @Override protected void runInContext() { try { Class consoleProxyClazz = Class.forName("com.cloud.consoleproxy.ConsoleProxy"); try { - s_logger.info("Invoke startWithContext()"); + logger.info("Invoke startWithContext()"); Method method = consoleProxyClazz.getMethod("startWithContext", Properties.class, Object.class, byte[].class, String.class, String.class, Boolean.class); - method.invoke(null, _properties, resource, ksBits, ksPassword, encryptorPassword, isSourceIpCheckEnabled); + method.invoke(null, properties, resource, ksBits, ksPassword, encryptorPassword, isSourceIpCheckEnabled); } catch (SecurityException e) { - s_logger.error("Unable to launch console proxy due to SecurityException", e); + logger.error("Unable to launch console proxy due to SecurityException", e); System.exit(ExitStatus.Error.value()); } catch (NoSuchMethodException e) { - s_logger.error("Unable to launch console proxy due to NoSuchMethodException", e); + logger.error("Unable to launch console proxy due to NoSuchMethodException", e); System.exit(ExitStatus.Error.value()); } catch (IllegalArgumentException e) { - s_logger.error("Unable to launch console proxy due to IllegalArgumentException", e); + logger.error("Unable to launch console proxy due to IllegalArgumentException", e); System.exit(ExitStatus.Error.value()); } catch (IllegalAccessException e) { - s_logger.error("Unable to launch console proxy due to IllegalAccessException", e); + logger.error("Unable to launch console proxy due to IllegalAccessException", e); System.exit(ExitStatus.Error.value()); } catch (InvocationTargetException e) { - s_logger.error("Unable to launch console proxy due to InvocationTargetException " + e.getTargetException().toString(), e); + logger.error("Unable to launch console proxy due to InvocationTargetException {}", e.getTargetException().toString(), e); System.exit(ExitStatus.Error.value()); } } catch (final ClassNotFoundException e) { - s_logger.error("Unable to launch console proxy due to ClassNotFoundException"); + logger.error("Unable to launch console proxy due to ClassNotFoundException"); System.exit(ExitStatus.Error.value()); } } }, "Console-Proxy-Main"); - _consoleProxyMain.setDaemon(true); - _consoleProxyMain.start(); + consoleProxyMain.setDaemon(true); + consoleProxyMain.start(); } else { - s_logger.info("com.cloud.consoleproxy.ConsoleProxy is already running"); + logger.info("com.cloud.consoleproxy.ConsoleProxy is already running"); try { Class consoleProxyClazz = Class.forName("com.cloud.consoleproxy.ConsoleProxy"); @@ -378,22 +375,22 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe methodSetup = consoleProxyClazz.getMethod("setIsSourceIpCheckEnabled", Boolean.class); methodSetup.invoke(null, isSourceIpCheckEnabled); } catch (SecurityException e) { - s_logger.error("Unable to launch console proxy due to SecurityException", e); + logger.error("Unable to launch console proxy due to SecurityException", e); System.exit(ExitStatus.Error.value()); } catch (NoSuchMethodException e) { - s_logger.error("Unable to launch console proxy due to NoSuchMethodException", e); + logger.error("Unable to launch console proxy due to NoSuchMethodException", e); System.exit(ExitStatus.Error.value()); } catch (IllegalArgumentException e) { - s_logger.error("Unable to launch console proxy due to IllegalArgumentException", e); + logger.error("Unable to launch console proxy due to IllegalArgumentException", e); System.exit(ExitStatus.Error.value()); } catch (IllegalAccessException e) { - s_logger.error("Unable to launch console proxy due to IllegalAccessException", e); + logger.error("Unable to launch console proxy due to IllegalAccessException", e); System.exit(ExitStatus.Error.value()); } catch (InvocationTargetException e) { - s_logger.error("Unable to launch console proxy due to InvocationTargetException " + e.getTargetException().toString(), e); + logger.error("Unable to launch console proxy due to InvocationTargetException " + e.getTargetException().toString(), e); System.exit(ExitStatus.Error.value()); } catch (final ClassNotFoundException e) { - s_logger.error("Unable to launch console proxy due to ClassNotFoundException", e); + logger.error("Unable to launch console proxy due to ClassNotFoundException", e); System.exit(ExitStatus.Error.value()); } } @@ -420,39 +417,36 @@ public class ConsoleProxyResource extends ServerResourceBase implements ServerRe result.setTunnelUrl(authAnswer.getTunnelUrl()); result.setTunnelSession(authAnswer.getTunnelSession()); } else { - s_logger.error("Authentication failed for vm: " + vmId + " with sid: " + sid); + logger.error("Authentication failed for vm: {} with sid: {}", vmId, sid); } } catch (AgentControlChannelException e) { - s_logger.error("Unable to send out console access authentication request due to " + e.getMessage(), e); + logger.error("Unable to send out console access authentication request due to {}", e.getMessage(), e); } return new Gson().toJson(result); } public void reportLoadInfo(String gsonLoadInfo) { - ConsoleProxyLoadReportCommand cmd = new ConsoleProxyLoadReportCommand(_proxyVmId, gsonLoadInfo); + ConsoleProxyLoadReportCommand cmd = new ConsoleProxyLoadReportCommand(proxyVmId, gsonLoadInfo); try { getAgentControl().postRequest(cmd); - - if (s_logger.isDebugEnabled()) - s_logger.debug("Report proxy load info, proxy : " + _proxyVmId + ", load: " + gsonLoadInfo); + logger.debug("Report proxy load info, proxy : {}, load: {}", proxyVmId, gsonLoadInfo); } catch (AgentControlChannelException e) { - s_logger.error("Unable to send out load info due to " + e.getMessage(), e); + logger.error("Unable to send out load info due to {}", e.getMessage(), e); } } public void ensureRoute(String address) { - if (_localgw != null) { - if (s_logger.isDebugEnabled()) - s_logger.debug("Ensure route for " + address + " via " + _localgw); + if (localGateway != null) { + logger.debug("Ensure route for {} via {}", address, localGateway); // this method won't be called in high frequency, serialize access // to script execution synchronized (this) { try { - addRouteToInternalIpOrCidr(_localgw, _eth1ip, _eth1mask, address); + addRouteToInternalIpOrCidr(localGateway, eth1Ip, eth1Mask, address); } catch (Throwable e) { - s_logger.warn("Unexpected exception while adding internal route to " + address, e); + logger.warn("Unexpected exception while adding internal route to {}", address, e); } } } diff --git a/agent/src/test/java/com/cloud/agent/AgentShellTest.java b/agent/src/test/java/com/cloud/agent/AgentShellTest.java index f7151779f58..4126692546f 100644 --- a/agent/src/test/java/com/cloud/agent/AgentShellTest.java +++ b/agent/src/test/java/com/cloud/agent/AgentShellTest.java @@ -350,4 +350,16 @@ public class AgentShellTest { Mockito.verify(agentShellSpy).setHosts(expected); } + + @Test + public void updateAndGetConnectedHost() { + String expected = "test"; + + AgentShell shell = new AgentShell(); + shell.setHosts("test"); + shell.getNextHost(); + shell.updateConnectedHost(); + + Assert.assertEquals(expected, shell.getConnectedHost()); + } } diff --git a/agent/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/agent/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker deleted file mode 100644 index 1f0955d450f..00000000000 --- a/agent/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker +++ /dev/null @@ -1 +0,0 @@ -mock-maker-inline diff --git a/api/pom.xml b/api/pom.xml index ff9083afa09..32897725e0c 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -24,7 +24,7 @@ org.apache.cloudstack cloudstack - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT @@ -36,6 +36,11 @@ com.google.code.gson gson + + org.apache.commons + commons-math3 + ${cs.commons-math3.version} + javax.servlet javax.servlet-api diff --git a/api/src/main/java/com/cloud/agent/api/Command.java b/api/src/main/java/com/cloud/agent/api/Command.java index b3c6120462a..eb979c0060b 100644 --- a/api/src/main/java/com/cloud/agent/api/Command.java +++ b/api/src/main/java/com/cloud/agent/api/Command.java @@ -20,6 +20,8 @@ import java.util.HashMap; import java.util.Map; import com.cloud.agent.api.LogLevel.Log4jLevel; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; /** * implemented by classes that extends the Command class. Command specifies @@ -27,6 +29,8 @@ import com.cloud.agent.api.LogLevel.Log4jLevel; */ public abstract class Command { + protected transient Logger logger = LogManager.getLogger(getClass()); + public static enum OnError { Continue, Stop } @@ -47,6 +51,13 @@ public abstract class Command { return wait; } + /** + * This is the time in seconds that the agent will wait before waiting for an answer from the endpoint. + * The actual wait time is twice the value of this variable. + * See {@link com.cloud.agent.manager.AgentAttache#send(com.cloud.agent.transport.Request, int) AgentAttache#send} implementation for more details. + * + * @param wait + **/ public void setWait(int wait) { this.wait = wait; } diff --git a/api/src/main/java/com/cloud/agent/api/LogLevel.java b/api/src/main/java/com/cloud/agent/api/LogLevel.java index a8da272f39f..136cb6d7228 100644 --- a/api/src/main/java/com/cloud/agent/api/LogLevel.java +++ b/api/src/main/java/com/cloud/agent/api/LogLevel.java @@ -23,8 +23,8 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; /** */ @@ -41,7 +41,7 @@ public @interface LogLevel { } public boolean enabled(Logger logger) { - return _level != Level.OFF && logger.isEnabledFor(_level); + return _level != Level.OFF && logger.isEnabled(_level); } } diff --git a/api/src/main/java/com/cloud/agent/api/StoragePoolInfo.java b/api/src/main/java/com/cloud/agent/api/StoragePoolInfo.java index d923694a854..eb7e8813ecd 100644 --- a/api/src/main/java/com/cloud/agent/api/StoragePoolInfo.java +++ b/api/src/main/java/com/cloud/agent/api/StoragePoolInfo.java @@ -52,6 +52,13 @@ public class StoragePoolInfo { this.details = details; } + public StoragePoolInfo(String uuid, String host, String hostPath, String localPath, StoragePoolType poolType, long capacityBytes, long availableBytes, + Map details, String name) { + this(uuid, host, hostPath, localPath, poolType, capacityBytes, availableBytes); + this.details = details; + this.name = name; + } + public long getCapacityBytes() { return capacityBytes; } diff --git a/api/src/main/java/com/cloud/agent/api/storage/OVFHelper.java b/api/src/main/java/com/cloud/agent/api/storage/OVFHelper.java index c8313ccd664..6396e3deb72 100644 --- a/api/src/main/java/com/cloud/agent/api/storage/OVFHelper.java +++ b/api/src/main/java/com/cloud/agent/api/storage/OVFHelper.java @@ -39,7 +39,8 @@ import org.apache.cloudstack.utils.security.ParserUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -63,7 +64,7 @@ import com.cloud.utils.compression.CompressionUtil; import com.cloud.utils.exception.CloudRuntimeException; public class OVFHelper { - private static final Logger s_logger = Logger.getLogger(OVFHelper.class); + protected Logger logger = LogManager.getLogger(getClass()); private final OVFParser ovfParser; @@ -118,7 +119,7 @@ public class OVFHelper { boolean password = StringUtils.isNotBlank(passStr) && passStr.equalsIgnoreCase("true"); String label = ovfParser.getChildNodeValue(node, "Label"); String description = ovfParser.getChildNodeValue(node, "Description"); - s_logger.debug("Creating OVF property index " + index + (category == null ? "" : " for category " + category) + logger.debug("Creating OVF property index " + index + (category == null ? "" : " for category " + category) + " with key = " + key); return new OVFPropertyTO(key, type, value, qualifiers, userConfigurable, label, description, password, index, category); @@ -151,7 +152,7 @@ public class OVFHelper { if (child.getNodeName().equalsIgnoreCase("Category") || child.getNodeName().endsWith(":Category")) { lastCategoryFound = child.getTextContent(); - s_logger.info("Category found " + lastCategoryFound); + logger.info("Category found " + lastCategoryFound); } else if (child.getNodeName().equalsIgnoreCase("Property") || child.getNodeName().endsWith(":Property")) { OVFPropertyTO prop = createOVFPropertyFromNode(child, propertyIndex, lastCategoryFound); @@ -249,13 +250,13 @@ public class OVFHelper { int diskNumber = 0; for (OVFVirtualHardwareItemTO diskItem : diskHardwareItems) { if (StringUtils.isBlank(diskItem.getHostResource())) { - s_logger.error("Missing disk information for hardware item " + diskItem.getElementName() + " " + diskItem.getInstanceId()); + logger.error("Missing disk information for hardware item " + diskItem.getElementName() + " " + diskItem.getInstanceId()); continue; } String diskId = extractDiskIdFromDiskHostResource(diskItem.getHostResource()); OVFDisk diskDefinition = getDiskDefinitionFromDiskId(diskId, disks); if (diskDefinition == null) { - s_logger.error("Missing disk definition for disk ID " + diskId); + logger.error("Missing disk definition for disk ID " + diskId); } OVFFile fileDefinition = getFileDefinitionFromDiskDefinition(diskDefinition._fileRef, files); DatadiskTO datadiskTO = generateDiskTO(fileDefinition, diskDefinition, ovfParentPath, diskNumber, diskItem); @@ -277,7 +278,7 @@ public class OVFHelper { if (StringUtils.isNotBlank(path)) { File f = new File(path); if (!f.exists() || f.isDirectory()) { - s_logger.error("One of the attached disk or iso does not exists " + path); + logger.error("One of the attached disk or iso does not exists " + path); throw new InternalErrorException("One of the attached disk or iso as stated on OVF does not exists " + path); } } @@ -333,8 +334,8 @@ public class OVFHelper { od._controller = getControllerType(items, od._diskId); vd.add(od); } - if (s_logger.isTraceEnabled()) { - s_logger.trace(String.format("found %d disk definitions",vd.size())); + if (logger.isTraceEnabled()) { + logger.trace(String.format("found %d disk definitions",vd.size())); } return vd; } @@ -365,8 +366,8 @@ public class OVFHelper { vf.add(of); } } - if (s_logger.isTraceEnabled()) { - s_logger.trace(String.format("found %d file definitions in %s",vf.size(), ovfFile.getPath())); + if (logger.isTraceEnabled()) { + logger.trace(String.format("found %d file definitions in %s",vf.size(), ovfFile.getPath())); } return vf; } @@ -461,7 +462,7 @@ public class OVFHelper { Element disk = (Element)disks.item(i); String fileRef = ovfParser.getNodeAttribute(disk, "fileRef"); if (keepfile == null) { - s_logger.info("FATAL: OVA format error"); + logger.info("FATAL: OVA format error"); } else if (keepfile.equals(fileRef)) { keepdisk = ovfParser.getNodeAttribute(disk, "diskId"); } else { @@ -505,7 +506,7 @@ public class OVFHelper { outfile.write(writer.toString()); outfile.close(); } catch (IOException | TransformerException e) { - s_logger.info("Unexpected exception caught while rewriting OVF:" + e.getMessage(), e); + logger.info("Unexpected exception caught while rewriting OVF:" + e.getMessage(), e); throw new CloudRuntimeException(e); } } @@ -521,8 +522,8 @@ public class OVFHelper { public List getNetPrerequisitesFromDocument(Document doc) throws InternalErrorException { if (doc == null) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("no document to parse; returning no prerequisite networks"); + if (logger.isTraceEnabled()) { + logger.trace("no document to parse; returning no prerequisite networks"); } return Collections.emptyList(); } @@ -539,8 +540,8 @@ public class OVFHelper { private void matchNicsToNets(Map nets, Node systemElement) { final DocumentTraversal traversal = (DocumentTraversal) systemElement; final NodeIterator iterator = traversal.createNodeIterator(systemElement, NodeFilter.SHOW_ELEMENT, null, true); - if (s_logger.isTraceEnabled()) { - s_logger.trace(String.format("starting out with %d network-prerequisites, parsing hardware",nets.size())); + if (logger.isTraceEnabled()) { + logger.trace(String.format("starting out with %d network-prerequisites, parsing hardware",nets.size())); } int nicCount = 0; for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) { @@ -549,8 +550,8 @@ public class OVFHelper { nicCount++; String name = e.getTextContent(); // should be in our nets if(nets.get(name) == null) { - if(s_logger.isInfoEnabled()) { - s_logger.info(String.format("found a nic definition without a network definition byname %s, adding it to the list.", name)); + if(logger.isInfoEnabled()) { + logger.info(String.format("found a nic definition without a network definition byname %s, adding it to the list.", name)); } nets.put(name, new OVFNetworkTO()); } @@ -560,8 +561,8 @@ public class OVFHelper { } } } - if (s_logger.isTraceEnabled()) { - s_logger.trace(String.format("ending up with %d network-prerequisites, parsed %d nics", nets.size(), nicCount)); + if (logger.isTraceEnabled()) { + logger.trace(String.format("ending up with %d network-prerequisites, parsed %d nics", nets.size(), nicCount)); } } @@ -584,7 +585,7 @@ public class OVFHelper { int addressOnParent = Integer.parseInt(addressOnParentStr); nic.setAddressOnParent(addressOnParent); } catch (NumberFormatException e) { - s_logger.warn("Encountered element of type \"AddressOnParent\", that could not be parse to an integer number: " + addressOnParentStr); + logger.warn("Encountered element of type \"AddressOnParent\", that could not be parse to an integer number: " + addressOnParentStr); } boolean automaticAllocation = StringUtils.isNotBlank(automaticAllocationStr) && Boolean.parseBoolean(automaticAllocationStr); @@ -596,7 +597,7 @@ public class OVFHelper { int instanceId = Integer.parseInt(instanceIdStr); nic.setInstanceID(instanceId); } catch (NumberFormatException e) { - s_logger.warn("Encountered element of type \"InstanceID\", that could not be parse to an integer number: " + instanceIdStr); + logger.warn("Encountered element of type \"InstanceID\", that could not be parse to an integer number: " + instanceIdStr); } nic.setResourceSubType(resourceSubType); @@ -608,7 +609,7 @@ public class OVFHelper { NodeList systemElements = ovfParser.getElementsFromOVFDocument(doc, "VirtualSystem"); if (systemElements.getLength() != 1) { String msg = "found " + systemElements.getLength() + " system definitions in OVA, can only handle exactly one."; - s_logger.warn(msg); + logger.warn(msg); throw new InternalErrorException(msg); } } @@ -629,8 +630,8 @@ public class OVFHelper { nets.put(networkName,network); } - if (s_logger.isTraceEnabled()) { - s_logger.trace(String.format("found %d networks in template", nets.size())); + if (logger.isTraceEnabled()) { + logger.trace(String.format("found %d networks in template", nets.size())); } return nets; } @@ -770,7 +771,7 @@ public class OVFHelper { try { return Long.parseLong(value); } catch (NumberFormatException e) { - s_logger.debug("Could not parse the value: " + value + ", ignoring it"); + logger.debug("Could not parse the value: " + value + ", ignoring it"); } } return null; @@ -781,7 +782,7 @@ public class OVFHelper { try { return Integer.parseInt(value); } catch (NumberFormatException e) { - s_logger.debug("Could not parse the value: " + value + ", ignoring it"); + logger.debug("Could not parse the value: " + value + ", ignoring it"); } } return null; @@ -807,9 +808,11 @@ public class OVFHelper { String eulaLicense = null; for (int i = 0; i < eulaChildNodes.getLength(); i++) { Node eulaItem = eulaChildNodes.item(i); - if (eulaItem.getNodeName().equalsIgnoreCase("Info")) { + if (eulaItem.getNodeName().equalsIgnoreCase("Info") + || eulaItem.getNodeName().endsWith(":Info")) { eulaInfo = eulaItem.getTextContent(); - } else if (eulaItem.getNodeName().equalsIgnoreCase("License")) { + } else if (eulaItem.getNodeName().equalsIgnoreCase("License") + || eulaItem.getNodeName().endsWith(":License")) { eulaLicense = eulaItem.getTextContent(); } } @@ -817,7 +820,7 @@ public class OVFHelper { try { compressedLicense = compressOVFEula(eulaLicense); } catch (IOException e) { - s_logger.error("Could not compress the license for info " + eulaInfo); + logger.error("Could not compress the license for info " + eulaInfo); continue; } OVFEulaSectionTO eula = new OVFEulaSectionTO(eulaInfo, compressedLicense, eulaIndex); diff --git a/api/src/main/java/com/cloud/agent/api/storage/OVFParser.java b/api/src/main/java/com/cloud/agent/api/storage/OVFParser.java index b66fbe418d7..38f478d63cf 100644 --- a/api/src/main/java/com/cloud/agent/api/storage/OVFParser.java +++ b/api/src/main/java/com/cloud/agent/api/storage/OVFParser.java @@ -27,7 +27,8 @@ import javax.xml.parsers.ParserConfigurationException; import org.apache.cloudstack.utils.security.ParserUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -36,7 +37,7 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; public class OVFParser { - private static final Logger s_logger = Logger.getLogger(OVFParser.class); + protected Logger logger = LogManager.getLogger(getClass()); private static final String DEFAULT_OVF_SCHEMA = "http://schemas.dmtf.org/ovf/envelope/1"; private static final String VMW_SCHEMA = "http://www.vmware.com/schema/ovf"; @@ -53,7 +54,7 @@ public class OVFParser { documentBuilderFactory.setNamespaceAware(true); documentBuilder = documentBuilderFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { - s_logger.error("Cannot start the OVF parser: " + e.getMessage(), e); + logger.error("Cannot start the OVF parser: " + e.getMessage(), e); } } @@ -69,7 +70,7 @@ public class OVFParser { try { return documentBuilder.parse(new File(ovfFilePath)); } catch (SAXException | IOException e) { - s_logger.error("Error parsing " + ovfFilePath + " " + e.getMessage(), e); + logger.error("Error parsing " + ovfFilePath + " " + e.getMessage(), e); return null; } } diff --git a/api/src/main/java/com/cloud/agent/api/to/HostTO.java b/api/src/main/java/com/cloud/agent/api/to/HostTO.java index 967a63d63b5..ee14e659718 100644 --- a/api/src/main/java/com/cloud/agent/api/to/HostTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/HostTO.java @@ -24,6 +24,7 @@ public class HostTO { private NetworkTO publicNetwork; private NetworkTO storageNetwork1; private NetworkTO storageNetwork2; + private String parent; protected HostTO() { } @@ -40,6 +41,9 @@ public class HostTO { if (vo.getStorageIpAddressDeux() != null) { storageNetwork2 = new NetworkTO(vo.getStorageIpAddressDeux(), vo.getStorageNetmaskDeux(), vo.getStorageMacAddressDeux()); } + if (vo.getParent() != null) { + parent = vo.getParent(); + } } public String getGuid() { @@ -81,4 +85,12 @@ public class HostTO { public void setStorageNetwork2(NetworkTO storageNetwork2) { this.storageNetwork2 = storageNetwork2; } + + public String getParent() { + return parent; + } + + public void setParent(String parent) { + this.parent = parent; + } } diff --git a/api/src/main/java/com/cloud/agent/api/to/NicTO.java b/api/src/main/java/com/cloud/agent/api/to/NicTO.java index 3a616170d7e..573363c04fb 100644 --- a/api/src/main/java/com/cloud/agent/api/to/NicTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/NicTO.java @@ -32,6 +32,9 @@ public class NicTO extends NetworkTO { Map details; boolean dpdkEnabled; Integer mtu; + Long networkId; + + String networkSegmentName; public NicTO() { super(); @@ -127,4 +130,20 @@ public class NicTO extends NetworkTO { public void setMtu(Integer mtu) { this.mtu = mtu; } + + public Long getNetworkId() { + return networkId; + } + + public void setNetworkId(Long networkId) { + this.networkId = networkId; + } + + public String getNetworkSegmentName() { + return networkSegmentName; + } + + public void setNetworkSegmentName(String networkSegmentName) { + this.networkSegmentName = networkSegmentName; + } } diff --git a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java new file mode 100644 index 00000000000..d86eb2a3a7f --- /dev/null +++ b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.cloud.agent.api.to; + +import java.io.Serializable; + +import com.cloud.agent.api.LogLevel; +import com.cloud.hypervisor.Hypervisor; + +public class RemoteInstanceTO implements Serializable { + + private Hypervisor.HypervisorType hypervisorType; + private String instanceName; + + // VMware Remote Instances parameters (required for exporting OVA through ovftool) + // TODO: cloud.agent.transport.Request#getCommands() cannot handle gsoc decode for polymorphic classes + private String vcenterUsername; + @LogLevel(LogLevel.Log4jLevel.Off) + private String vcenterPassword; + private String vcenterHost; + private String datacenterName; + + public RemoteInstanceTO() { + } + + public RemoteInstanceTO(String instanceName) { + this.hypervisorType = Hypervisor.HypervisorType.VMware; + this.instanceName = instanceName; + } + + public RemoteInstanceTO(String instanceName, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) { + this.hypervisorType = Hypervisor.HypervisorType.VMware; + this.instanceName = instanceName; + this.vcenterHost = vcenterHost; + this.vcenterUsername = vcenterUsername; + this.vcenterPassword = vcenterPassword; + this.datacenterName = datacenterName; + } + + public Hypervisor.HypervisorType getHypervisorType() { + return this.hypervisorType; + } + + public String getInstanceName() { + return this.instanceName; + } + + public String getVcenterUsername() { + return vcenterUsername; + } + + public String getVcenterPassword() { + return vcenterPassword; + } + + public String getVcenterHost() { + return vcenterHost; + } + + public String getDatacenterName() { + return datacenterName; + } +} diff --git a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java index db6cba77548..b4f4619be9a 100644 --- a/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/VirtualMachineTO.java @@ -82,6 +82,7 @@ public class VirtualMachineTO { Map guestOsDetails = new HashMap(); Map extraConfig = new HashMap<>(); + Map networkIdToNetworkNameMap = new HashMap<>(); DeployAsIsInfoTO deployAsIsInfo; public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader, @@ -392,6 +393,14 @@ public class VirtualMachineTO { return extraConfig; } + public Map getNetworkIdToNetworkNameMap() { + return networkIdToNetworkNameMap; + } + + public void setNetworkIdToNetworkNameMap(Map networkIdToNetworkNameMap) { + this.networkIdToNetworkNameMap = networkIdToNetworkNameMap; + } + public String getBootType() { return bootType; } diff --git a/api/src/main/java/com/cloud/capacity/Capacity.java b/api/src/main/java/com/cloud/capacity/Capacity.java index 684490a605c..a4e2c2a7f05 100644 --- a/api/src/main/java/com/cloud/capacity/Capacity.java +++ b/api/src/main/java/com/cloud/capacity/Capacity.java @@ -16,6 +16,8 @@ // under the License. package com.cloud.capacity; +import java.util.List; + import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -35,6 +37,11 @@ public interface Capacity extends InternalIdentity, Identity { public static final short CAPACITY_TYPE_CPU_CORE = 90; + public static final List STORAGE_CAPACITY_TYPES = List.of(CAPACITY_TYPE_STORAGE, + CAPACITY_TYPE_STORAGE_ALLOCATED, + CAPACITY_TYPE_SECONDARY_STORAGE, + CAPACITY_TYPE_LOCAL_STORAGE); + public Long getHostOrPoolId(); public Long getDataCenterId(); @@ -54,4 +61,6 @@ public interface Capacity extends InternalIdentity, Identity { public Float getUsedPercentage(); public Long getAllocatedCapacity(); + + public String getTag(); } diff --git a/api/src/main/java/com/cloud/configuration/Resource.java b/api/src/main/java/com/cloud/configuration/Resource.java index 32db2fcafea..bf8fca9d905 100644 --- a/api/src/main/java/com/cloud/configuration/Resource.java +++ b/api/src/main/java/com/cloud/configuration/Resource.java @@ -85,5 +85,6 @@ public interface Resource { long getOwnerId(); ResourceOwnerType getResourceOwnerType(); + String getTag(); } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/VmwareDatacenter.java b/api/src/main/java/com/cloud/dc/VmwareDatacenter.java similarity index 96% rename from plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/VmwareDatacenter.java rename to api/src/main/java/com/cloud/dc/VmwareDatacenter.java index b1f233c3606..859ff190b65 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/VmwareDatacenter.java +++ b/api/src/main/java/com/cloud/dc/VmwareDatacenter.java @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -package com.cloud.hypervisor.vmware; +package com.cloud.dc; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; diff --git a/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java b/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java index a668b79187d..2697311d2b9 100644 --- a/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java +++ b/api/src/main/java/com/cloud/deploy/DeploymentClusterPlanner.java @@ -57,6 +57,17 @@ public interface DeploymentClusterPlanner extends DeploymentPlanner { false, ConfigKey.Scope.Global); + static final ConfigKey VmAllocationAlgorithm = new ConfigKey<>( + String.class, + "vm.allocation.algorithm", + "Advanced", + "random", + "Order in which hosts within a cluster will be considered for VM/volume allocation. The value can be 'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit', or 'firstfitleastconsumed'.", + true, + ConfigKey.Scope.Global, null, null, null, null, null, + ConfigKey.Kind.Select, + "random,firstfit,userdispersing,userconcentratedpod_random,userconcentratedpod_firstfit,firstfitleastconsumed"); + /** * This is called to determine list of possible clusters where a virtual * machine can be deployed. diff --git a/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java b/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java index e9f706ac1ce..354f9cfaac5 100644 --- a/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java +++ b/api/src/main/java/com/cloud/deploy/DeploymentPlanner.java @@ -21,8 +21,12 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + import com.cloud.dc.DataCenter; import com.cloud.dc.Pod; +import com.cloud.exception.CloudException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.exception.ResourceUnavailableException; @@ -75,7 +79,7 @@ public interface DeploymentPlanner extends Adapter { public static class ExcludeList implements Serializable { private static final long serialVersionUID = -482175549460148301L; - + protected static Logger LOGGER = LogManager.getLogger(ExcludeList.class); private Set _dcIds; private Set _podIds; private Set _clusterIds; @@ -104,13 +108,26 @@ public interface DeploymentPlanner extends Adapter { } } + private void logAvoid(Class scope, CloudException e) { + Long id = null; + if (e instanceof InsufficientCapacityException) { + id = ((InsufficientCapacityException) e).getId(); + } else if (e instanceof ResourceUnavailableException) { + id = ((ResourceUnavailableException) e).getResourceId(); + } else { + LOGGER.debug("Failed to log avoided component due to unexpected exception type [{}].", e.getMessage()); + return; + } + LOGGER.debug("Adding {} [{}] to the avoid set due to [{}].", scope.getSimpleName(), id, e.getMessage()); + } + public boolean add(InsufficientCapacityException e) { Class scope = e.getScope(); if (scope == null) { return false; } - + logAvoid(scope, e); if (Host.class.isAssignableFrom(scope)) { addHost(e.getId()); } else if (Pod.class.isAssignableFrom(scope)) { @@ -128,13 +145,14 @@ public interface DeploymentPlanner extends Adapter { return true; } + public boolean add(ResourceUnavailableException e) { Class scope = e.getScope(); if (scope == null) { return false; } - + logAvoid(scope, e); if (Host.class.isAssignableFrom(scope)) { addHost(e.getResourceId()); } else if (Pod.class.isAssignableFrom(scope)) { diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java index 484dc9b001e..d4235cbc9bc 100644 --- a/api/src/main/java/com/cloud/event/EventTypes.java +++ b/api/src/main/java/com/cloud/event/EventTypes.java @@ -29,7 +29,11 @@ import org.apache.cloudstack.api.response.PodResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.config.Configuration; import org.apache.cloudstack.ha.HAConfig; +import org.apache.cloudstack.quota.QuotaTariff; +import org.apache.cloudstack.storage.object.Bucket; +import org.apache.cloudstack.storage.object.ObjectStore; import org.apache.cloudstack.usage.Usage; +import org.apache.cloudstack.vm.schedule.VMSchedule; import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenterGuestIpv6Prefix; @@ -84,7 +88,6 @@ import com.cloud.user.User; import com.cloud.vm.Nic; import com.cloud.vm.NicSecondaryIp; import com.cloud.vm.VirtualMachine; -import org.apache.cloudstack.vm.schedule.VMSchedule; public class EventTypes { @@ -301,6 +304,7 @@ public class EventTypes { public static final String EVENT_VOLUME_CREATE = "VOLUME.CREATE"; public static final String EVENT_VOLUME_DELETE = "VOLUME.DELETE"; public static final String EVENT_VOLUME_ATTACH = "VOLUME.ATTACH"; + public static final String EVENT_VOLUME_CHECK = "VOLUME.CHECK"; public static final String EVENT_VOLUME_DETACH = "VOLUME.DETACH"; public static final String EVENT_VOLUME_EXTRACT = "VOLUME.EXTRACT"; public static final String EVENT_VOLUME_UPLOAD = "VOLUME.UPLOAD"; @@ -312,14 +316,18 @@ public class EventTypes { public static final String EVENT_VOLUME_UPDATE = "VOLUME.UPDATE"; public static final String EVENT_VOLUME_DESTROY = "VOLUME.DESTROY"; public static final String EVENT_VOLUME_RECOVER = "VOLUME.RECOVER"; + public static final String EVENT_VOLUME_IMPORT = "VOLUME.IMPORT"; + public static final String EVENT_VOLUME_UNMANAGE = "VOLUME.UNMANAGE"; public static final String EVENT_VOLUME_CHANGE_DISK_OFFERING = "VOLUME.CHANGE.DISK.OFFERING"; // Domains public static final String EVENT_DOMAIN_CREATE = "DOMAIN.CREATE"; public static final String EVENT_DOMAIN_DELETE = "DOMAIN.DELETE"; public static final String EVENT_DOMAIN_UPDATE = "DOMAIN.UPDATE"; + public static final String EVENT_DOMAIN_MOVE = "DOMAIN.MOVE"; // Snapshots + public static final String EVENT_SNAPSHOT_COPY = "SNAPSHOT.COPY"; public static final String EVENT_SNAPSHOT_CREATE = "SNAPSHOT.CREATE"; public static final String EVENT_SNAPSHOT_ON_PRIMARY = "SNAPSHOT.ON_PRIMARY"; public static final String EVENT_SNAPSHOT_OFF_PRIMARY = "SNAPSHOT.OFF_PRIMARY"; @@ -394,6 +402,9 @@ public class EventTypes { public static final String EVENT_STORAGE_IP_RANGE_UPDATE = "STORAGE.IP.RANGE.UPDATE"; public static final String EVENT_IMAGE_STORE_DATA_MIGRATE = "IMAGE.STORE.MIGRATE.DATA"; + public static final String EVENT_IMAGE_STORE_RESOURCES_MIGRATE = "IMAGE.STORE.MIGRATE.RESOURCES"; + public static final String EVENT_IMAGE_STORE_OBJECT_DOWNLOAD = "IMAGE.STORE.OBJECT.DOWNLOAD"; + public static final String EVENT_UPDATE_IMAGE_STORE_ACCESS_STATE = "IMAGE.STORE.ACCESS.UPDATED"; // Configuration Table public static final String EVENT_CONFIGURATION_VALUE_EDIT = "CONFIGURATION.VALUE.EDIT"; @@ -440,6 +451,7 @@ public class EventTypes { public static final String EVENT_ENABLE_PRIMARY_STORAGE = "ENABLE.PS"; public static final String EVENT_DISABLE_PRIMARY_STORAGE = "DISABLE.PS"; public static final String EVENT_SYNC_STORAGE_POOL = "SYNC.STORAGE.POOL"; + public static final String EVENT_CHANGE_STORAGE_POOL_SCOPE = "CHANGE.STORAGE.POOL.SCOPE"; // VPN public static final String EVENT_REMOTE_ACCESS_VPN_CREATE = "VPN.REMOTE.ACCESS.CREATE"; @@ -677,6 +689,11 @@ public class EventTypes { //Usage related events public static final String EVENT_USAGE_REMOVE_USAGE_RECORDS = "USAGE.REMOVE.USAGE.RECORDS"; + // DRS Events + public static final String EVENT_CLUSTER_DRS = "CLUSTER.DRS"; + public static final String EVENT_CLUSTER_DRS_GENERATE = "CLUSTER.DRS.GENERATE"; + + // Netscaler Service Package events public static final String EVENT_NETSCALER_SERVICEPACKAGE_ADD = "NETSCALER.SERVICEPACKAGE.ADD"; public static final String EVENT_NETSCALER_SERVICEPACKAGE_DELETE = "NETSCALER.SERVICEPACKAGE.DELETE"; @@ -705,6 +722,23 @@ public class EventTypes { // SystemVM public static final String EVENT_LIVE_PATCH_SYSTEMVM = "LIVE.PATCH.SYSTEM.VM"; + //Purge resources + public static final String EVENT_PURGE_EXPUNGED_RESOURCES = "PURGE.EXPUNGED.RESOURCES"; + + // OBJECT STORE + public static final String EVENT_OBJECT_STORE_CREATE = "OBJECT.STORE.CREATE"; + public static final String EVENT_OBJECT_STORE_DELETE = "OBJECT.STORE.DELETE"; + public static final String EVENT_OBJECT_STORE_UPDATE = "OBJECT.STORE.UPDATE"; + + // BUCKETS + public static final String EVENT_BUCKET_CREATE = "BUCKET.CREATE"; + public static final String EVENT_BUCKET_DELETE = "BUCKET.DELETE"; + public static final String EVENT_BUCKET_UPDATE = "BUCKET.UPDATE"; + + // Quota + public static final String EVENT_QUOTA_TARIFF_CREATE = "QUOTA.TARIFF.CREATE"; + public static final String EVENT_QUOTA_TARIFF_DELETE = "QUOTA.TARIFF.DELETE"; + public static final String EVENT_QUOTA_TARIFF_UPDATE = "QUOTA.TARIFF.UPDATE"; static { @@ -858,6 +892,7 @@ public class EventTypes { entityEventDetails.put(EVENT_DOMAIN_CREATE, Domain.class); entityEventDetails.put(EVENT_DOMAIN_DELETE, Domain.class); entityEventDetails.put(EVENT_DOMAIN_UPDATE, Domain.class); + entityEventDetails.put(EVENT_DOMAIN_MOVE, Domain.class); // Snapshots entityEventDetails.put(EVENT_SNAPSHOT_CREATE, Snapshot.class); @@ -968,6 +1003,7 @@ public class EventTypes { // Primary storage pool entityEventDetails.put(EVENT_ENABLE_PRIMARY_STORAGE, StoragePool.class); entityEventDetails.put(EVENT_DISABLE_PRIMARY_STORAGE, StoragePool.class); + entityEventDetails.put(EVENT_CHANGE_STORAGE_POOL_SCOPE, StoragePool.class); // VPN entityEventDetails.put(EVENT_REMOTE_ACCESS_VPN_CREATE, RemoteAccessVpn.class); @@ -1141,9 +1177,30 @@ public class EventTypes { entityEventDetails.put(EVENT_IMPORT_VCENTER_STORAGE_POLICIES, "StoragePolicies"); entityEventDetails.put(EVENT_IMAGE_STORE_DATA_MIGRATE, ImageStore.class); + entityEventDetails.put(EVENT_IMAGE_STORE_OBJECT_DOWNLOAD, ImageStore.class); + entityEventDetails.put(EVENT_UPDATE_IMAGE_STORE_ACCESS_STATE, ImageStore.class); entityEventDetails.put(EVENT_LIVE_PATCH_SYSTEMVM, "SystemVMs"); + + //Object Store + entityEventDetails.put(EVENT_OBJECT_STORE_CREATE, ObjectStore.class); + entityEventDetails.put(EVENT_OBJECT_STORE_UPDATE, ObjectStore.class); + entityEventDetails.put(EVENT_OBJECT_STORE_DELETE, ObjectStore.class); + + //Buckets + entityEventDetails.put(EVENT_BUCKET_CREATE, Bucket.class); + entityEventDetails.put(EVENT_BUCKET_UPDATE, Bucket.class); + entityEventDetails.put(EVENT_BUCKET_DELETE, Bucket.class); + + // Quota + entityEventDetails.put(EVENT_QUOTA_TARIFF_CREATE, QuotaTariff.class); + entityEventDetails.put(EVENT_QUOTA_TARIFF_DELETE, QuotaTariff.class); + entityEventDetails.put(EVENT_QUOTA_TARIFF_UPDATE, QuotaTariff.class); } + public static boolean isNetworkEvent(String eventType) { + return EVENT_NETWORK_CREATE.equals(eventType) || EVENT_NETWORK_DELETE.equals(eventType) || + EVENT_NETWORK_UPDATE.equals(eventType); + } public static String getEntityForEvent(String eventName) { Object entityClass = entityEventDetails.get(eventName); if (entityClass == null) { @@ -1172,4 +1229,12 @@ public class EventTypes { return null; } + + public static boolean isVpcEvent(String eventType) { + return EventTypes.EVENT_VPC_CREATE.equals(eventType) || EventTypes.EVENT_VPC_DELETE.equals(eventType); + } + + public static void addEntityEventDetail(String event, Class clazz) { + entityEventDetails.put(event, clazz); + } } diff --git a/api/src/main/java/com/cloud/gpu/GPU.java b/api/src/main/java/com/cloud/gpu/GPU.java index 8aa54c0c0f8..64ff24a8279 100644 --- a/api/src/main/java/com/cloud/gpu/GPU.java +++ b/api/src/main/java/com/cloud/gpu/GPU.java @@ -25,13 +25,104 @@ public class GPU { } public enum GPUType { - GRID_K100("GRID K100"), - GRID_K120Q("GRID K120Q"), - GRID_K140Q("GRID K140Q"), - GRID_K200("GRID K200"), - GRID_K220Q("GRID K220Q"), - GRID_K240Q("GRID K240Q"), - GRID_K260("GRID K260Q"), + GRID_V100D_32A("GRID V100D-32A"), + GRID_V100D_8Q("GRID V100D-8Q"), + GRID_V100D_4A("GRID V100D-4A"), + GRID_V100D_1B("GRID V100D-1B"), + GRID_V100D_2Q("GRID V100D-2Q"), + GRID_V100D_4Q("GRID V100D-4Q"), + GRID_V100D_2A("GRID V100D-2A"), + GRID_V100D_2B("GRID V100D-2B"), + GRID_V100D_32Q("GRID V100D-32Q"), + GRID_V100D_16A("GRID V100D-16A"), + GRID_V100D_1Q("GRID V100D-1Q"), + GRID_V100D_2B4("GRID V100D-2B4"), + GRID_V100D_16Q("GRID V100D-16Q"), + GRID_V100D_8A("GRID V100D-8A"), + GRID_V100D_1A("GRID V100D-1A"), + GRID_T4_16A("GRID T4-16A"), + GRID_T4_2B4("GRID T4-2B4"), + GRID_T4_4Q("GRID T4-4Q"), + GRID_T4_16Q("GRID T4-16Q"), + GRID_T4_4A("GRID T4-4A"), + GRID_T4_1A("GRID T4-1A"), + GRID_T4_2Q("GRID T4-2Q"), + GRID_T4_2B("GRID T4-2B"), + GRID_T4_8Q("GRID T4-8Q"), + GRID_T4_2A("GRID T4-2A"), + GRID_T4_1B("GRID T4-1B"), + GRID_T4_1Q("GRID T4-1Q"), + GRID_T4_8A("GRID T4-8A"), + NVIDIA_RTX5500_1A("NVIDIA RTXA5500-1A"), + NVIDIA_RTX5500_1B("NVIDIA RTXA5500-1B"), + NVIDIA_RTX5500_1Q("NVIDIA RTXA5500-1Q"), + NVIDIA_RTX5500_2A("NVIDIA RTXA5500-2A"), + NVIDIA_RTX5500_2B("NVIDIA RTXA5500-2B"), + NVIDIA_RTX5500_2Q("NVIDIA RTXA5500-2Q"), + NVIDIA_RTX5500_3A("NVIDIA RTXA5500-3A"), + NVIDIA_RTX5500_3Q("NVIDIA RTXA5500-3Q"), + NVIDIA_RTX5500_4A("NVIDIA RTXA5500-4A"), + NVIDIA_RTX5500_4Q("NVIDIA RTXA5500-4Q"), + NVIDIA_RTX5500_6A("NVIDIA RTXA5500-6A"), + NVIDIA_RTX5500_6Q("NVIDIA RTXA5500-6Q"), + NVIDIA_RTX5500_8A("NVIDIA RTXA5500-8A"), + NVIDIA_RTX5500_8Q("NVIDIA RTXA5500-8Q"), + NVIDIA_RTX5500_12A("NVIDIA RTXA5500-12A"), + NVIDIA_RTX5500_12Q("NVIDIA RTXA5500-12Q"), + NVIDIA_RTX5500_24A("NVIDIA RTXA5500-24A"), + NVIDIA_RTX5500_24Q("NVIDIA RTXA5500-24Q"), + NVIDIA_A40_1A("NVIDIA A40-1A"), + NVIDIA_A40_1B("NVIDIA A40-1B"), + NVIDIA_A40_1Q("NVIDIA A40-1Q"), + NVIDIA_A40_2A("NVIDIA A40-2A"), + NVIDIA_A40_2B("NVIDIA A40-2B"), + NVIDIA_A40_2Q("NVIDIA A40-2Q"), + NVIDIA_A40_3A("NVIDIA A40-3A"), + NVIDIA_A40_3Q("NVIDIA A40-3Q"), + NVIDIA_A40_4A("NVIDIA A40-4A"), + NVIDIA_A40_4Q("NVIDIA A40-4Q"), + NVIDIA_A40_6A("NVIDIA A40-6A"), + NVIDIA_A40_6Q("NVIDIA A40-6Q"), + NVIDIA_A40_8A("NVIDIA A40-8A"), + NVIDIA_A40_8Q("NVIDIA A40-8Q"), + NVIDIA_A40_12A("NVIDIA A40-12A"), + NVIDIA_A40_12Q("NVIDIA A40-12Q"), + NVIDIA_A40_16A("NVIDIA A40-16A"), + NVIDIA_A40_16Q("NVIDIA A40-16Q"), + NVIDIA_A40_24A("NVIDIA A40-24A"), + NVIDIA_A40_24Q("NVIDIA A40-24Q"), + NVIDIA_A40_48A("NVIDIA A40-48A"), + NVIDIA_A40_48Q("NVIDIA A40-48Q"), + NVIDIA_A2_1A("NVIDIA A2-1A"), + NVIDIA_A2_1B("NVIDIA A2-1B"), + NVIDIA_A2_1Q("NVIDIA A2-1Q"), + NVIDIA_A2_2A("NVIDIA A2-2A"), + NVIDIA_A2_2B("NVIDIA A2-2B"), + NVIDIA_A2_2Q("NVIDIA A2-2Q"), + NVIDIA_A2_4A("NVIDIA A2-4A"), + NVIDIA_A2_4Q("NVIDIA A2-4Q"), + NVIDIA_A2_8A("NVIDIA A2-8A"), + NVIDIA_A2_8Q("NVIDIA A2-8Q"), + NVIDIA_A2_16A("NVIDIA A2-16A"), + NVIDIA_A2_16Q("NVIDIA A2-16Q"), + NVIDIA_A10_1A("NVIDIA A10-1A"), + NVIDIA_A10_1B("NVIDIA A10-1B"), + NVIDIA_A10_1Q("NVIDIA A10-1Q"), + NVIDIA_A10_2A("NVIDIA A10-2A"), + NVIDIA_A10_2B("NVIDIA A10-2B"), + NVIDIA_A10_2Q("NVIDIA A10-2Q"), + NVIDIA_A10_3A("NVIDIA A10-3A"), + NVIDIA_A10_3Q("NVIDIA A10-3Q"), + NVIDIA_A10_4A("NVIDIA A10-4A"), + NVIDIA_A10_4Q("NVIDIA A10-4Q"), + NVIDIA_A10_6A("NVIDIA A10-6A"), + NVIDIA_A10_6Q("NVIDIA A10-6Q"), + NVIDIA_A10_8A("NVIDIA A10-8A"), + NVIDIA_A10_8Q("NVIDIA A10-8Q"), + NVIDIA_A10_12A("NVIDIA A10-12A"), + NVIDIA_A10_12Q("NVIDIA A10-12Q"), + NVIDIA_A10_24A("NVIDIA A10-24A"), + NVIDIA_A10_24Q("NVIDIA A10-24Q"), passthrough("passthrough"); private String type; diff --git a/api/src/main/java/com/cloud/host/Host.java b/api/src/main/java/com/cloud/host/Host.java index 7563bc3b742..4a3b914364f 100644 --- a/api/src/main/java/com/cloud/host/Host.java +++ b/api/src/main/java/com/cloud/host/Host.java @@ -54,6 +54,7 @@ public interface Host extends StateObject, Identity, Partition, HAResour } public static final String HOST_UEFI_ENABLE = "host.uefi.enable"; public static final String HOST_VOLUME_ENCRYPTION = "host.volume.encryption"; + public static final String HOST_INSTANCE_CONVERSION = "host.instance.conversion"; /** * @return name of the machine. diff --git a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java index 2f0cc736af3..e1108b34a83 100644 --- a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java +++ b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java @@ -17,55 +17,45 @@ package com.cloud.hypervisor; import com.cloud.storage.Storage.ImageFormat; +import org.apache.commons.lang3.StringUtils; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; +import java.util.Objects; public class Hypervisor { + public static class HypervisorType { + private static final Map hypervisorTypeMap = new LinkedHashMap<>(); + public static final HypervisorType None = new HypervisorType("None"); //for storage hosts + public static final HypervisorType XenServer = new HypervisorType("XenServer", ImageFormat.VHD); + public static final HypervisorType KVM = new HypervisorType("KVM", ImageFormat.QCOW2); + public static final HypervisorType VMware = new HypervisorType("VMware", ImageFormat.OVA); + public static final HypervisorType Hyperv = new HypervisorType("Hyperv"); + public static final HypervisorType VirtualBox = new HypervisorType("VirtualBox"); + public static final HypervisorType Parralels = new HypervisorType("Parralels"); + public static final HypervisorType BareMetal = new HypervisorType("BareMetal"); + public static final HypervisorType Simulator = new HypervisorType("Simulator"); + public static final HypervisorType Ovm = new HypervisorType("Ovm", ImageFormat.RAW); + public static final HypervisorType Ovm3 = new HypervisorType("Ovm3", ImageFormat.RAW); + public static final HypervisorType LXC = new HypervisorType("LXC"); + public static final HypervisorType Custom = new HypervisorType("Custom"); + public static final HypervisorType Any = new HypervisorType("Any"); /*If you don't care about the hypervisor type*/ + private final String name; + private final ImageFormat imageFormat; - static Map hypervisorTypeMap; - static Map supportedImageFormatMap; + public HypervisorType(String name) { + this(name, null); + } - public enum HypervisorType { - None, //for storage hosts - XenServer, - KVM, - VMware, - Hyperv, - VirtualBox, - Parralels, - BareMetal, - Simulator, - Ovm, - Ovm3, - LXC, - Custom, - - Any; /*If you don't care about the hypervisor type*/ - - static { - hypervisorTypeMap = new HashMap<>(); - hypervisorTypeMap.put("xenserver", HypervisorType.XenServer); - hypervisorTypeMap.put("kvm", HypervisorType.KVM); - hypervisorTypeMap.put("vmware", HypervisorType.VMware); - hypervisorTypeMap.put("hyperv", HypervisorType.Hyperv); - hypervisorTypeMap.put("virtualbox", HypervisorType.VirtualBox); - hypervisorTypeMap.put("parallels", HypervisorType.Parralels); - hypervisorTypeMap.put("baremetal", HypervisorType.BareMetal); - hypervisorTypeMap.put("simulator", HypervisorType.Simulator); - hypervisorTypeMap.put("ovm", HypervisorType.Ovm); - hypervisorTypeMap.put("lxc", HypervisorType.LXC); - hypervisorTypeMap.put("any", HypervisorType.Any); - hypervisorTypeMap.put("ovm3", HypervisorType.Ovm3); - hypervisorTypeMap.put("custom", HypervisorType.Custom); - - supportedImageFormatMap = new HashMap<>(); - supportedImageFormatMap.put(HypervisorType.XenServer, ImageFormat.VHD); - supportedImageFormatMap.put(HypervisorType.KVM, ImageFormat.QCOW2); - supportedImageFormatMap.put(HypervisorType.VMware, ImageFormat.OVA); - supportedImageFormatMap.put(HypervisorType.Ovm, ImageFormat.RAW); - supportedImageFormatMap.put(HypervisorType.Ovm3, ImageFormat.RAW); + public HypervisorType(String name, ImageFormat imageFormat) { + this.name = name; + this.imageFormat = imageFormat; + if (name.equals("Parralels")){ // typo in the original code + hypervisorTypeMap.put("parallels", this); + } else { + hypervisorTypeMap.putIfAbsent(name.toLowerCase(Locale.ROOT), this); + } } public static HypervisorType getType(String hypervisor) { @@ -75,24 +65,62 @@ public class Hypervisor { hypervisorTypeMap.getOrDefault(hypervisor.toLowerCase(Locale.ROOT), HypervisorType.None)); } + public static HypervisorType[] values() { + return hypervisorTypeMap.values().toArray(HypervisorType[]::new).clone(); + } + + public static HypervisorType valueOf(String name) { + if (StringUtils.isBlank(name)) { + return null; + } + + HypervisorType hypervisorType = hypervisorTypeMap.get(name.toLowerCase(Locale.ROOT)); + if (hypervisorType == null) { + throw new IllegalArgumentException("HypervisorType '" + name + "' not found"); + } + return hypervisorType; + } + /** * Returns the display name of a hypervisor type in case the custom hypervisor is used, * using the 'hypervisor.custom.display.name' setting. Otherwise, returns hypervisor name */ public String getHypervisorDisplayName() { - return !Hypervisor.HypervisorType.Custom.equals(this) ? - this.toString() : - HypervisorGuru.HypervisorCustomDisplayName.value(); + return HypervisorType.Custom.equals(this) ? HypervisorGuru.HypervisorCustomDisplayName.value() : name; } /** * This method really needs to be part of the properties of the hypervisor type itself. * - * @param hyperType * @return */ - public static ImageFormat getSupportedImageFormat(HypervisorType hyperType) { - return supportedImageFormatMap.getOrDefault(hyperType, null); + public ImageFormat getSupportedImageFormat() { + return imageFormat; + } + + public String name() { + return name; + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } else if (o == null || getClass() != o.getClass()) { + return false; + } + HypervisorType that = (HypervisorType) o; + return Objects.equals(name, that.name); + } + + @Override + public String toString() { + return name; } } diff --git a/api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java b/api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java index 2dfa707b57b..0c821b4e36c 100644 --- a/api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java +++ b/api/src/main/java/com/cloud/hypervisor/HypervisorGuru.java @@ -23,6 +23,7 @@ import org.apache.cloudstack.backup.Backup; import org.apache.cloudstack.framework.config.ConfigKey; import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -33,6 +34,7 @@ import com.cloud.utils.component.Adapter; import com.cloud.vm.NicProfile; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; public interface HypervisorGuru extends Adapter { @@ -100,8 +102,45 @@ public interface HypervisorGuru extends Adapter { * Will generate commands to migrate a vm to a pool. For now this will only work for stopped VMs on Vmware. * * @param vm the stopped vm to migrate - * @param destination the primary storage pool to migrate to + * @param volumeToPool the primary storage pools to migrate to * @return a list of commands to perform for a successful migration */ List finalizeMigrate(VirtualMachine vm, Map volumeToPool); + + + /** + * Will return the hypervisor VM (clone VM for PowerOn VMs), performs a clone of a VM if required on an external host (if the guru can handle) + * @param hostIp VM's source host IP + * @param vmName name of the source VM (clone VM name if cloned) + * @param params hypervisor specific additional parameters + * @return a reference to the hypervisor or cloned VM, and cloned flag + */ + Pair getHypervisorVMOutOfBandAndCloneIfRequired(String hostIp, String vmName, Map params); + + /** + * Removes a VM created as a clone of a VM on an external host + * @param hostIp VM's source host IP + * @param vmName name of the VM to remove + * @param params hypervisor specific additional parameters + * @return true if the operation succeeds, false if not + */ + boolean removeClonedHypervisorVMOutOfBand(String hostIp, String vmName, Map params); + + /** + * Create an OVA/OVF template of a VM on an external host (if the guru can handle) + * @param hostIp VM's source host IP + * @param vmName name of the source VM to create template from + * @param params hypervisor specific additional parameters + * @param templateLocation datastore to create the template file + * @return the created template dir/name + */ + String createVMTemplateOutOfBand(String hostIp, String vmName, Map params, DataStoreTO templateLocation, int threadsCountToExportOvf); + + /** + * Removes the template on the location + * @param templateLocation datastore to remove the template file + * @param templateDir the template dir to remove from datastore + * @return true if the operation succeeds, false if not + */ + boolean removeVMTemplateOutOfBand(DataStoreTO templateLocation, String templateDir); } diff --git a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelper.java b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java similarity index 84% rename from api/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelper.java rename to api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java index e445e50f82c..a13c1b3a6a8 100644 --- a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelper.java +++ b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java @@ -16,10 +16,14 @@ // under the License. package com.cloud.kubernetes.cluster; -import com.cloud.utils.component.Adapter; import org.apache.cloudstack.acl.ControlledEntity; -public interface KubernetesClusterHelper extends Adapter { +import com.cloud.uservm.UserVm; +import com.cloud.utils.component.Adapter; + +public interface KubernetesServiceHelper extends Adapter { ControlledEntity findByUuid(String uuid); + ControlledEntity findByVmId(long vmId); + void checkVmCanBeDestroyed(UserVm userVm); } diff --git a/api/src/main/java/com/cloud/network/IpAddress.java b/api/src/main/java/com/cloud/network/IpAddress.java index cf2e2f82db9..ae1af450577 100644 --- a/api/src/main/java/com/cloud/network/IpAddress.java +++ b/api/src/main/java/com/cloud/network/IpAddress.java @@ -97,4 +97,6 @@ public interface IpAddress extends ControlledEntity, Identity, InternalIdentity, void setRuleState(State ruleState); + boolean isForSystemVms(); + } diff --git a/api/src/main/java/com/cloud/network/Network.java b/api/src/main/java/com/cloud/network/Network.java index 458169c80aa..3b13ef7bd9c 100644 --- a/api/src/main/java/com/cloud/network/Network.java +++ b/api/src/main/java/com/cloud/network/Network.java @@ -205,6 +205,8 @@ public interface Network extends ControlledEntity, StateObject, I //Add Tungsten Fabric provider public static final Provider Tungsten = new Provider("Tungsten", false); + public static final Provider Nsx = new Provider("Nsx", false); + private final String name; private final boolean isExternal; @@ -427,6 +429,8 @@ public interface Network extends ControlledEntity, StateObject, I long getDataCenterId(); + long getAccountId(); + long getNetworkOfferingId(); @Override diff --git a/api/src/main/java/com/cloud/network/NetworkModel.java b/api/src/main/java/com/cloud/network/NetworkModel.java index 96f38b64bcd..699dcbf6c50 100644 --- a/api/src/main/java/com/cloud/network/NetworkModel.java +++ b/api/src/main/java/com/cloud/network/NetworkModel.java @@ -73,6 +73,7 @@ public interface NetworkModel { String HYPERVISOR_HOST_NAME_FILE = "hypervisor-host-name"; String CLOUD_DOMAIN_FILE = "cloud-domain"; String CLOUD_DOMAIN_ID_FILE = "cloud-domain-id"; + String CLOUD_NAME_FILE = "cloud-name"; int CONFIGDATA_DIR = 0; int CONFIGDATA_FILE = 1; int CONFIGDATA_CONTENT = 2; @@ -83,11 +84,12 @@ public interface NetworkModel { .put(PUBLIC_HOSTNAME_FILE, "name") .put(CLOUD_DOMAIN_FILE, CLOUD_DOMAIN_FILE) .put(CLOUD_DOMAIN_ID_FILE, CLOUD_DOMAIN_ID_FILE) + .put(CLOUD_NAME_FILE, CLOUD_NAME_FILE) .put(HYPERVISOR_HOST_NAME_FILE, HYPERVISOR_HOST_NAME_FILE) .build(); List metadataFileNames = new ArrayList<>(Arrays.asList(SERVICE_OFFERING_FILE, AVAILABILITY_ZONE_FILE, LOCAL_HOSTNAME_FILE, LOCAL_IPV4_FILE, PUBLIC_HOSTNAME_FILE, PUBLIC_IPV4_FILE, - INSTANCE_ID_FILE, VM_ID_FILE, PUBLIC_KEYS_FILE, CLOUD_IDENTIFIER_FILE, HYPERVISOR_HOST_NAME_FILE)); + INSTANCE_ID_FILE, VM_ID_FILE, PUBLIC_KEYS_FILE, CLOUD_IDENTIFIER_FILE, CLOUD_NAME_FILE, HYPERVISOR_HOST_NAME_FILE)); static final ConfigKey MACIdentifier = new ConfigKey<>("Advanced",Integer.class, "mac.identifier", "0", "This value will be used while generating the mac addresses for isolated and shared networks. The hexadecimal equivalent value will be present at the 2nd octet of the mac address. Default value is zero (0) which means that the DB id of the zone will be used.", true, ConfigKey.Scope.Zone); @@ -315,6 +317,8 @@ public interface NetworkModel { void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gateway, String ip6Cidr) throws InvalidParameterValueException; + void checkIp6CidrSizeEqualTo64(String ip6Cidr) throws InvalidParameterValueException; + void checkRequestedIpAddresses(long networkId, IpAddresses ips) throws InvalidParameterValueException; String getStartIpv6Address(long id); diff --git a/api/src/main/java/com/cloud/network/NetworkProfile.java b/api/src/main/java/com/cloud/network/NetworkProfile.java index 44853069575..1a5c80ea871 100644 --- a/api/src/main/java/com/cloud/network/NetworkProfile.java +++ b/api/src/main/java/com/cloud/network/NetworkProfile.java @@ -22,10 +22,8 @@ import java.util.Date; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; -import org.apache.log4j.Logger; public class NetworkProfile implements Network { - static final Logger s_logger = Logger.getLogger(NetworkProfile.class); private final long id; private final String uuid; private final long dataCenterId; diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java index 099d73d5fcb..b8dd464b365 100644 --- a/api/src/main/java/com/cloud/network/NetworkService.java +++ b/api/src/main/java/com/cloud/network/NetworkService.java @@ -19,11 +19,15 @@ package com.cloud.network; import java.util.List; import java.util.Map; +import com.cloud.dc.DataCenter; +import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd; import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd; import org.apache.cloudstack.api.command.admin.network.ListGuestVlansCmd; import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; +import org.apache.cloudstack.api.command.user.address.RemoveQuarantinedIpCmd; +import org.apache.cloudstack.api.command.user.address.UpdateQuarantinedIpCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkPermissionsCmd; import org.apache.cloudstack.api.command.user.network.ListNetworkPermissionsCmd; @@ -53,6 +57,7 @@ import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.Nic; import com.cloud.vm.NicSecondaryIp; +import org.apache.cloudstack.network.element.InternalLoadBalancerElementService; /** * The NetworkService interface is the "public" api to entities that make requests to the orchestration engine @@ -85,6 +90,8 @@ public interface NetworkService { IpAddress reserveIpAddress(Account account, Boolean displayIp, Long ipAddressId) throws ResourceAllocationException; + IpAddress reserveIpAddressWithVlanDetail(Account account, DataCenter zone, Boolean displayIp, String vlanDetailKey) throws ResourceAllocationException; + boolean releaseReservedIpAddress(long ipAddressId) throws InsufficientAddressCapacityException; boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException; @@ -96,6 +103,10 @@ public interface NetworkService { Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException; + Network createGuestNetwork(long networkOfferingId, String name, String displayText, Account owner, + PhysicalNetwork physicalNetwork, long zoneId, ControlledEntity.ACLType aclType) throws + InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException; + Pair, Integer> searchForNetworks(ListNetworksCmd cmd); boolean deleteNetwork(long networkId, boolean forced); @@ -112,6 +123,8 @@ public interface NetworkService { IpAddress getIp(long id); + IpAddress getIp(String ipAddress); + Network updateGuestNetwork(final UpdateNetworkCmd cmd); /** @@ -246,4 +259,13 @@ public interface NetworkService { boolean resetNetworkPermissions(ResetNetworkPermissionsCmd resetNetworkPermissionsCmd); void validateIfServiceOfferingIsActiveAndSystemVmTypeIsDomainRouter(final Long serviceOfferingId) throws InvalidParameterValueException; + + PublicIpQuarantine updatePublicIpAddressInQuarantine(UpdateQuarantinedIpCmd cmd); + + void removePublicIpAddressFromQuarantine(RemoveQuarantinedIpCmd cmd); + + InternalLoadBalancerElementService getInternalLoadBalancerElementByType(VirtualRouterProvider.Type type); + InternalLoadBalancerElementService getInternalLoadBalancerElementByNetworkServiceProviderId(long networkProviderId); + InternalLoadBalancerElementService getInternalLoadBalancerElementById(long providerId); + List getInternalLoadBalancerElements(); } diff --git a/api/src/main/java/com/cloud/network/Networks.java b/api/src/main/java/com/cloud/network/Networks.java index aeed5d4aec6..dfa0ddb84ca 100644 --- a/api/src/main/java/com/cloud/network/Networks.java +++ b/api/src/main/java/com/cloud/network/Networks.java @@ -128,7 +128,8 @@ public class Networks { }, UnDecided(null, null), OpenDaylight("opendaylight", String.class), - TUNGSTEN("tf", String.class); + TUNGSTEN("tf", String.class), + NSX("nsx", String.class); private final String scheme; private final Class type; diff --git a/api/src/main/java/com/cloud/network/PublicIpQuarantine.java b/api/src/main/java/com/cloud/network/PublicIpQuarantine.java new file mode 100644 index 00000000000..625a1bbbe50 --- /dev/null +++ b/api/src/main/java/com/cloud/network/PublicIpQuarantine.java @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +import java.util.Date; + +public interface PublicIpQuarantine extends InternalIdentity, Identity { + Long getPublicIpAddressId(); + + Long getPreviousOwnerId(); + + Date getEndDate(); + + String getRemovalReason(); + + Long getRemoverAccountId(); + + Date getRemoved(); + + Date getCreated(); +} diff --git a/api/src/main/java/com/cloud/network/VNF.java b/api/src/main/java/com/cloud/network/VNF.java new file mode 100644 index 00000000000..e7a7fb01cb9 --- /dev/null +++ b/api/src/main/java/com/cloud/network/VNF.java @@ -0,0 +1,111 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network; + +import org.apache.commons.lang3.StringUtils; + +public class VNF { + + public enum AccessMethod { + SSH_WITH_PASSWORD("ssh-password"), + SSH_WITH_KEY("ssh-key"), + HTTP("http"), + HTTPS("https"), + CONSOLE("console"); + + String _method; + + AccessMethod(String method) { + _method = method; + } + + @Override + public String toString() { + return _method; + } + + public static AccessMethod fromValue(String method) { + if (StringUtils.isBlank(method)) { + return null; + } else { + for (AccessMethod accessMethod : AccessMethod.values()) { + if (accessMethod.toString().equalsIgnoreCase(method)) { + return accessMethod; + } + } + } + return null; + } + } + + public enum AccessDetail { + ACCESS_METHODS, + USERNAME, + PASSWORD, + SSH_USER, + SSH_PASSWORD, + SSH_PORT, + WEB_USER, + WEB_PASSWORD, + HTTP_PATH, + HTTP_PORT, + HTTPS_PATH, + HTTPS_PORT + } + + public enum VnfDetail { + VERSION, + VENDOR, + MAINTAINER + } + + public static class VnfNic { + long deviceId; + String name; + boolean required; + boolean management; + String description; + + public VnfNic(long deviceId, String nicName, boolean required, boolean management, String nicDescription) { + this.deviceId = deviceId; + this.name = nicName; + this.required = required; + this.management = management; + this.description = nicDescription; + } + + public long getDeviceId() { + return deviceId; + } + + public String getName() { + return name; + } + + public boolean isRequired() { + return required; + } + + public boolean isManagement() { + return management; + } + + public String getDescription() { + return description; + } + } +} diff --git a/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java b/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java index c47500c7849..cb92739d283 100644 --- a/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java +++ b/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java @@ -17,17 +17,22 @@ package com.cloud.network; import java.util.List; +import java.util.Map; import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd; import org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd; +import com.cloud.deploy.DeploymentPlanner; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.router.VirtualRouter; import com.cloud.user.Account; import com.cloud.utils.Pair; import com.cloud.vm.Nic; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; public interface VirtualNetworkApplianceService { /** @@ -62,6 +67,10 @@ public interface VirtualNetworkApplianceService { VirtualRouter startRouter(long id) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException; + void startRouterForHA(VirtualMachine vm, Map params, DeploymentPlanner planner) + throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, + OperationTimedoutException; + VirtualRouter destroyRouter(long routerId, Account caller, Long callerUserId) throws ResourceUnavailableException, ConcurrentOperationException; VirtualRouter findRouter(long routerId); diff --git a/api/src/main/java/com/cloud/network/VirtualRouterProvider.java b/api/src/main/java/com/cloud/network/VirtualRouterProvider.java index aca526b1832..98410ca09f8 100644 --- a/api/src/main/java/com/cloud/network/VirtualRouterProvider.java +++ b/api/src/main/java/com/cloud/network/VirtualRouterProvider.java @@ -21,7 +21,7 @@ import org.apache.cloudstack.api.InternalIdentity; public interface VirtualRouterProvider extends InternalIdentity, Identity { public enum Type { - VirtualRouter, ElasticLoadBalancerVm, VPCVirtualRouter, InternalLbVm, NetScalerVm + VirtualRouter, ElasticLoadBalancerVm, VPCVirtualRouter, InternalLbVm, NetScalerVm, Nsx } public Type getType(); diff --git a/api/src/main/java/com/cloud/network/VpcVirtualNetworkApplianceService.java b/api/src/main/java/com/cloud/network/VpcVirtualNetworkApplianceService.java index 5c3ee3f1032..cd04db802ca 100644 --- a/api/src/main/java/com/cloud/network/VpcVirtualNetworkApplianceService.java +++ b/api/src/main/java/com/cloud/network/VpcVirtualNetworkApplianceService.java @@ -29,7 +29,6 @@ public interface VpcVirtualNetworkApplianceService extends VirtualNetworkApplian /** * @param router * @param network - * @param isRedundant * @param params TODO * @return * @throws ConcurrentOperationException @@ -42,11 +41,30 @@ public interface VpcVirtualNetworkApplianceService extends VirtualNetworkApplian /** * @param router * @param network - * @param isRedundant * @return * @throws ConcurrentOperationException * @throws ResourceUnavailableException */ boolean removeVpcRouterFromGuestNetwork(VirtualRouter router, Network network) throws ConcurrentOperationException, ResourceUnavailableException; + + /** + * @param router + * @param network + * @return + * @throws ConcurrentOperationException + * @throws ResourceUnavailableException + */ + boolean stopKeepAlivedOnRouter(VirtualRouter router, Network network) throws ConcurrentOperationException, ResourceUnavailableException; + + + /** + * @param router + * @param network + * @return + * @throws ConcurrentOperationException + * @throws ResourceUnavailableException + */ + boolean startKeepAlivedOnRouter(VirtualRouter router, Network network) throws ConcurrentOperationException, ResourceUnavailableException; + } diff --git a/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java b/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java index 1bb37be970d..dc0f60f4519 100644 --- a/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java +++ b/api/src/main/java/com/cloud/network/element/LoadBalancingServiceProvider.java @@ -48,4 +48,7 @@ public interface LoadBalancingServiceProvider extends NetworkElement, IpDeployin List updateHealthChecks(Network network, List lbrules); boolean handlesOnlyRulesInTransitionState(); + + default void expungeLbVmRefs(List vmIds, Long batchSize) { + } } diff --git a/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java b/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java index 8c3243c99f4..852a650cfcd 100644 --- a/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java +++ b/api/src/main/java/com/cloud/network/element/NetworkACLServiceProvider.java @@ -21,6 +21,7 @@ import java.util.List; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.Vpc; public interface NetworkACLServiceProvider extends NetworkElement { @@ -32,4 +33,6 @@ public interface NetworkACLServiceProvider extends NetworkElement { */ boolean applyNetworkACLs(Network config, List rules) throws ResourceUnavailableException; + boolean reorderAclRules(Vpc vpc, List networks, List networkACLItems); + } diff --git a/api/src/main/java/com/cloud/network/element/VpcProvider.java b/api/src/main/java/com/cloud/network/element/VpcProvider.java index 14e86195a70..6debd1fbc2d 100644 --- a/api/src/main/java/com/cloud/network/element/VpcProvider.java +++ b/api/src/main/java/com/cloud/network/element/VpcProvider.java @@ -22,6 +22,7 @@ import com.cloud.deploy.DeployDestination; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.IpAddress; import com.cloud.network.vpc.NetworkACLItem; import com.cloud.network.vpc.PrivateGateway; import com.cloud.network.vpc.StaticRouteProfile; @@ -52,4 +53,6 @@ public interface VpcProvider extends NetworkElement { boolean applyStaticRoutes(Vpc vpc, List routes) throws ResourceUnavailableException; boolean applyACLItemsToPrivateGw(PrivateGateway gateway, List rules) throws ResourceUnavailableException; + + boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address); } diff --git a/api/src/main/java/com/cloud/network/guru/NetworkGuru.java b/api/src/main/java/com/cloud/network/guru/NetworkGuru.java index 52f654007f2..7b81c75ed84 100644 --- a/api/src/main/java/com/cloud/network/guru/NetworkGuru.java +++ b/api/src/main/java/com/cloud/network/guru/NetworkGuru.java @@ -79,20 +79,24 @@ public interface NetworkGuru extends Adapter { * be used to make determination can be isolation methods, services * provided on the guest network and the service provider that's on the * guest network. - * + *

* If a network is already fully substantiated with the necessary resources * during this design phase, then the state should be set to Setup. If * the resources are not allocated at this point, the state should be set * to Allocated. * - * @param offering network offering that contains the package of services - * the end user intends to use on that network. - * @param plan where is this network being deployed. + * @param offering network offering that contains the package of services + * the end user intends to use on that network. + * @param plan where is this network being deployed. * @param userSpecified user specified parameters for this network. - * @param owner owner of this network. + * @param name + * @param vpcId + * @param owner owner of this network. * @return Network */ - Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner); + Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, String name, Long vpcId, Account owner); + + void setup(Network network, long networkId); /** * For guest networks that are in Allocated state after the design stage, @@ -208,4 +212,7 @@ public interface NetworkGuru extends Adapter { boolean isMyTrafficType(TrafficType type); + default boolean isSlaacV6Only() { + return true; + } } diff --git a/api/src/main/java/com/cloud/network/nsx/NsxProvider.java b/api/src/main/java/com/cloud/network/nsx/NsxProvider.java new file mode 100644 index 00000000000..19cb3b4b939 --- /dev/null +++ b/api/src/main/java/com/cloud/network/nsx/NsxProvider.java @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.nsx; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface NsxProvider extends InternalIdentity, Identity { + String getHostname(); + + String getPort(); + String getProviderName(); + String getUsername(); + long getZoneId(); + + String getTier0Gateway(); + String getEdgeCluster(); + + String getTransportZone(); +} diff --git a/api/src/main/java/com/cloud/network/nsx/NsxService.java b/api/src/main/java/com/cloud/network/nsx/NsxService.java new file mode 100644 index 00000000000..79ad9547c73 --- /dev/null +++ b/api/src/main/java/com/cloud/network/nsx/NsxService.java @@ -0,0 +1,26 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.nsx; + +import com.cloud.network.IpAddress; +import com.cloud.network.vpc.Vpc; + +public interface NsxService { + + boolean createVpcNetwork(Long zoneId, long accountId, long domainId, Long vpcId, String vpcName, boolean sourceNatEnabled); + boolean updateVpcSourceNatIp(Vpc vpc, IpAddress address); +} diff --git a/api/src/main/java/com/cloud/network/vpc/VpcOffering.java b/api/src/main/java/com/cloud/network/vpc/VpcOffering.java index b4df8e38dba..3aab57d5d3d 100644 --- a/api/src/main/java/com/cloud/network/vpc/VpcOffering.java +++ b/api/src/main/java/com/cloud/network/vpc/VpcOffering.java @@ -29,6 +29,8 @@ public interface VpcOffering extends InternalIdentity, Identity { public static final String defaultVPCOfferingName = "Default VPC offering"; public static final String defaultVPCNSOfferingName = "Default VPC offering with Netscaler"; public static final String redundantVPCOfferingName = "Redundant VPC offering"; + public static final String DEFAULT_VPC_NAT_NSX_OFFERING_NAME = "VPC offering with NSX - NAT Mode"; + public static final String DEFAULT_VPC_ROUTE_NSX_OFFERING_NAME = "VPC offering with NSX - Route Mode"; /** * @@ -53,6 +55,10 @@ public interface VpcOffering extends InternalIdentity, Identity { */ boolean isDefault(); + boolean isForNsx(); + + String getNsxMode(); + /** * @return service offering id used by VPC virtual router */ diff --git a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java index 5cccd6c5a82..1ce3cf8ab0e 100644 --- a/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java +++ b/api/src/main/java/com/cloud/network/vpc/VpcProvisioningService.java @@ -36,7 +36,8 @@ public interface VpcProvisioningService { VpcOffering createVpcOffering(String name, String displayText, List supportedServices, Map> serviceProviders, Map serviceCapabilitystList, NetUtils.InternetProtocol internetProtocol, - Long serviceOfferingId, List domainIds, List zoneIds, VpcOffering.State state); + Long serviceOfferingId, Boolean forNsx, String mode, + List domainIds, List zoneIds, VpcOffering.State state); Pair,Integer> listVpcOfferings(ListVPCOfferingsCmd cmd); diff --git a/api/src/main/java/com/cloud/network/vpc/VpcService.java b/api/src/main/java/com/cloud/network/vpc/VpcService.java index 2cdc034a16e..0f0d29f4082 100644 --- a/api/src/main/java/com/cloud/network/vpc/VpcService.java +++ b/api/src/main/java/com/cloud/network/vpc/VpcService.java @@ -132,6 +132,8 @@ public interface VpcService { */ boolean startVpc(long vpcId, boolean destroyOnFailure) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + void startVpc(CreateVPCCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; + /** * Shuts down the VPC which includes shutting down all VPC provider and rules cleanup on the backend * diff --git a/api/src/main/java/com/cloud/offering/NetworkOffering.java b/api/src/main/java/com/cloud/offering/NetworkOffering.java index 207880ea28c..cf01fbf30e2 100644 --- a/api/src/main/java/com/cloud/offering/NetworkOffering.java +++ b/api/src/main/java/com/cloud/offering/NetworkOffering.java @@ -43,6 +43,11 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, InternalLbProvider, PublicLbProvider, servicepackageuuid, servicepackagedescription, PromiscuousMode, MacAddressChanges, ForgedTransmits, MacLearning, RelatedNetworkOffering, domainid, zoneid, pvlanType, internetProtocol } + public enum NsxMode { + NATTED, + ROUTED + } + public final static String SystemPublicNetwork = "System-Public-Network"; public final static String SystemControlNetwork = "System-Control-Network"; public final static String SystemManagementNetwork = "System-Management-Network"; @@ -52,6 +57,11 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, public final static String DefaultSharedNetworkOfferingWithSGService = "DefaultSharedNetworkOfferingWithSGService"; public static final String DEFAULT_TUNGSTEN_SHARED_NETWORK_OFFERING_WITH_SGSERVICE = "DefaultTungstenSharedNetworkOfferingWithSGService"; + public static final String DEFAULT_NAT_NSX_OFFERING_FOR_VPC = "DefaultNATNSXNetworkOfferingForVpc"; + public static final String DEFAULT_NAT_NSX_OFFERING_FOR_VPC_WITH_ILB = "DefaultNATNSXNetworkOfferingForVpcWithInternalLB"; + public static final String DEFAULT_ROUTED_NSX_OFFERING_FOR_VPC = "DefaultRoutedNSXNetworkOfferingForVpc"; + public static final String DEFAULT_NAT_NSX_OFFERING = "DefaultNATNSXNetworkOffering"; + public static final String DEFAULT_ROUTED_NSX_OFFERING = "DefaultRoutedNSXNetworkOffering"; public final static String QuickCloudNoServices = "QuickCloudNoServices"; public final static String DefaultIsolatedNetworkOfferingWithSourceNatService = "DefaultIsolatedNetworkOfferingWithSourceNatService"; public final static String OvsIsolatedNetworkOfferingWithSourceNatService = "OvsIsolatedNetworkOfferingWithSourceNatService"; @@ -90,6 +100,10 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, boolean isForTungsten(); + boolean isForNsx(); + + String getNsxMode(); + TrafficType getTrafficType(); boolean isSpecifyVlan(); diff --git a/api/src/main/java/com/cloud/offering/ServiceOffering.java b/api/src/main/java/com/cloud/offering/ServiceOffering.java index 278acbe231e..acb7a9f1cf9 100644 --- a/api/src/main/java/com/cloud/offering/ServiceOffering.java +++ b/api/src/main/java/com/cloud/offering/ServiceOffering.java @@ -33,6 +33,9 @@ public interface ServiceOffering extends InfrastructureEntity, InternalIdentity, static final String internalLbVmDefaultOffUniqueName = "Cloud.Com-InternalLBVm"; // leaving cloud.com references as these are identifyers and no real world addresses (check against DB) + + static final String PURGE_DB_ENTITIES_KEY = "purge.db.entities"; + enum State { Inactive, Active, } @@ -102,7 +105,7 @@ public interface ServiceOffering extends InfrastructureEntity, InternalIdentity, boolean getDefaultUse(); - String getSystemVmType(); + String getVmType(); String getDeploymentPlanner(); diff --git a/api/src/main/java/com/cloud/server/ManagementService.java b/api/src/main/java/com/cloud/server/ManagementService.java index 14d46e00ec6..18f3e901cd9 100644 --- a/api/src/main/java/com/cloud/server/ManagementService.java +++ b/api/src/main/java/com/cloud/server/ManagementService.java @@ -106,7 +106,7 @@ public interface ManagementService { Pair, Integer> searchForConfigurations(ListCfgsByCmd c); /** - * returns the the configuration groups + * returns the configuration groups * * @return list of configuration groups */ @@ -441,16 +441,19 @@ public interface ManagementService { */ Ternary, Integer>, List, Map> listHostsForMigrationOfVM(Long vmId, Long startIndex, Long pageSize, String keyword); + Ternary, Integer>, List, Map> listHostsForMigrationOfVM(VirtualMachine vm, Long startIndex, Long pageSize, String keyword, List 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, * this method removes the child storage pools and adds the corresponding parent datastore cluster for API response listing * * @param Long volumeId + * @param String keyword if passed, will only return storage pools that contain this keyword in the name * @return Pair, List> List of storage pools in cluster and list * of pools with enough capacity. */ - Pair, List> listStoragePoolsForMigrationOfVolume(Long volumeId); + Pair, List> listStoragePoolsForMigrationOfVolume(Long volumeId, String keyword); Pair, List> listStoragePoolsForSystemMigrationOfVolume(Long volumeId, Long newDiskOfferingId, Long newSize, Long newMinIops, Long newMaxIops, boolean keepSourceStoragePool, boolean bypassStorageTypeCheck); diff --git a/api/src/main/java/com/cloud/server/ResourceTag.java b/api/src/main/java/com/cloud/server/ResourceTag.java index 6288446cbdd..9bbb5d43eae 100644 --- a/api/src/main/java/com/cloud/server/ResourceTag.java +++ b/api/src/main/java/com/cloud/server/ResourceTag.java @@ -30,6 +30,7 @@ public interface ResourceTag extends ControlledEntity, Identity, InternalIdentit public enum ResourceObjectType { UserVm(true, true, true), Template(true, true, true), + VnfTemplate(false, false, true), ISO(true, false, true), Volume(true, true), Snapshot(true, false), @@ -68,7 +69,8 @@ public interface ResourceTag extends ControlledEntity, Identity, InternalIdentit GuestOs(false, true), NetworkOffering(false, true), VpcOffering(true, false), - Domain(false, false, true); + Domain(false, false, true), + ObjectStore(false, false, true); ResourceObjectType(boolean resourceTagsSupport, boolean resourceMetadataSupport) { diff --git a/api/src/main/java/com/cloud/storage/DataStoreRole.java b/api/src/main/java/com/cloud/storage/DataStoreRole.java index cc20cc0ce96..d9af495ab00 100644 --- a/api/src/main/java/com/cloud/storage/DataStoreRole.java +++ b/api/src/main/java/com/cloud/storage/DataStoreRole.java @@ -20,8 +20,9 @@ package com.cloud.storage; import com.cloud.utils.exception.CloudRuntimeException; + public enum DataStoreRole { - Primary("primary"), Image("image"), ImageCache("imagecache"), Backup("backup"); + Primary("primary"), Image("image"), ImageCache("imagecache"), Backup("backup"), Object("object"); public boolean isImageStore() { return (role.equalsIgnoreCase("image") || role.equalsIgnoreCase("imagecache")) ? true : false; @@ -45,6 +46,8 @@ public enum DataStoreRole { return ImageCache; } else if (role.equalsIgnoreCase("backup")) { return Backup; + } else if (role.equalsIgnoreCase("object")) { + return Object; } else { throw new CloudRuntimeException("can't identify the role"); } diff --git a/api/src/main/java/com/cloud/storage/Snapshot.java b/api/src/main/java/com/cloud/storage/Snapshot.java index 5b25843f48b..fc919e442b2 100644 --- a/api/src/main/java/com/cloud/storage/Snapshot.java +++ b/api/src/main/java/com/cloud/storage/Snapshot.java @@ -26,7 +26,7 @@ import java.util.Date; public interface Snapshot extends ControlledEntity, Identity, InternalIdentity, StateObject { public enum Type { - MANUAL, RECURRING, TEMPLATE, HOURLY, DAILY, WEEKLY, MONTHLY, GROUP; + MANUAL, RECURRING, TEMPLATE, HOURLY, DAILY, WEEKLY, MONTHLY, GROUP, FROM_GROUP; private int max = 8; public void setMax(int max) { diff --git a/api/src/main/java/com/cloud/storage/Storage.java b/api/src/main/java/com/cloud/storage/Storage.java index c6dee56fa22..c997f5e1dbf 100644 --- a/api/src/main/java/com/cloud/storage/Storage.java +++ b/api/src/main/java/com/cloud/storage/Storage.java @@ -16,10 +16,14 @@ // under the License. package com.cloud.storage; -import org.apache.commons.lang.NotImplementedException; - import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.Objects; + +import org.apache.commons.lang.NotImplementedException; +import org.apache.commons.lang3.StringUtils; public class Storage { public static enum ImageFormat { @@ -77,13 +81,18 @@ public class Storage { } public static enum Capability { - HARDWARE_ACCELERATION("HARDWARE_ACCELERATION"); + HARDWARE_ACCELERATION("HARDWARE_ACCELERATION"), + ALLOW_MIGRATE_OTHER_POOLS("ALLOW_MIGRATE_OTHER_POOLS"); private final String capability; private Capability(String capability) { this.capability = capability; } + + public String toString() { + return this.capability; + } } public static enum ProvisioningType { @@ -125,40 +134,77 @@ public class Storage { BUILTIN, /* buildin 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 */ DATADISK, /* Template corresponding to a datadisk(non root disk) present in an OVA */ ISODISK /* Template corresponding to a iso (non root disk) present in an OVA */ } - public static enum StoragePoolType { - Filesystem(false, true, true), // local directory - NetworkFilesystem(true, true, true), // NFS - IscsiLUN(true, false, false), // shared LUN, with a clusterfs overlay - Iscsi(true, false, false), // for e.g., ZFS Comstar - ISO(false, false, false), // for iso image - LVM(false, false, false), // XenServer local LVM SR - CLVM(true, false, false), - RBD(true, true, false), // http://libvirt.org/storage.html#StorageBackendRBD - SharedMountPoint(true, false, true), - VMFS(true, true, false), // VMware VMFS storage - PreSetup(true, true, false), // for XenServer, Storage Pool is set up by customers. - EXT(false, true, false), // XenServer local EXT SR - OCFS2(true, false, false), - SMB(true, false, false), - Gluster(true, false, false), - PowerFlex(true, true, true), // Dell EMC PowerFlex/ScaleIO (formerly VxFlexOS) - ManagedNFS(true, false, false), - Linstor(true, true, false), - DatastoreCluster(true, true, false), // for VMware, to abstract pool of clusters - StorPool(true, true, true); + /** + * StoragePoolTypes carry some details about the format and capabilities of a storage pool. While not necessarily a + * 1:1 with PrimaryDataStoreDriver (and for KVM agent, KVMStoragePool and StorageAdaptor) implementations, it is + * often used to decide which storage plugin or storage command to call, so it may be necessary for new storage + * plugins to add a StoragePoolType. This can be done by adding it below, or by creating a new public static final + * instance of StoragePoolType in the plugin itself, which registers it with the map. + * + * Note that if the StoragePoolType is for KVM and defined in plugin code rather than below, care must be taken to + * ensure this is available on the agent side as well. This is best done by defining the StoragePoolType in a common + * package available on both management server and agent plugin jars. + */ + public static class StoragePoolType { + private static final Map map = new LinkedHashMap<>(); + public static final StoragePoolType Filesystem = new StoragePoolType("Filesystem", false, true, true); + public static final StoragePoolType NetworkFilesystem = new StoragePoolType("NetworkFilesystem", true, true, true); + public static final StoragePoolType IscsiLUN = new StoragePoolType("IscsiLUN", true, false, false); + public static final StoragePoolType Iscsi = new StoragePoolType("Iscsi", true, false, false); + public static final StoragePoolType ISO = new StoragePoolType("ISO", false, false, false); + public static final StoragePoolType LVM = new StoragePoolType("LVM", false, false, false); + public static final StoragePoolType CLVM = new StoragePoolType("CLVM", true, false, false); + public static final StoragePoolType RBD = new StoragePoolType("RBD", true, true, false); + public static final StoragePoolType SharedMountPoint = new StoragePoolType("SharedMountPoint", true, true, true); + public static final StoragePoolType VMFS = new StoragePoolType("VMFS", true, true, false); + public static final StoragePoolType PreSetup = new StoragePoolType("PreSetup", true, true, false); + public static final StoragePoolType EXT = new StoragePoolType("EXT", false, true, false); + public static final StoragePoolType OCFS2 = new StoragePoolType("OCFS2", true, false, false); + public static final StoragePoolType SMB = new StoragePoolType("SMB", true, false, false); + public static final StoragePoolType Gluster = new StoragePoolType("Gluster", true, false, false); + public static final StoragePoolType PowerFlex = new StoragePoolType("PowerFlex", true, true, true); + public static final StoragePoolType ManagedNFS = new StoragePoolType("ManagedNFS", true, false, false); + public static final StoragePoolType Linstor = new StoragePoolType("Linstor", true, true, false); + public static final StoragePoolType DatastoreCluster = new StoragePoolType("DatastoreCluster", true, true, false); + public static final StoragePoolType StorPool = new StoragePoolType("StorPool", true,true,true); + public static final StoragePoolType FiberChannel = new StoragePoolType("FiberChannel", true,true,false); + + + private final String name; private final boolean shared; - private final boolean overprovisioning; + private final boolean overProvisioning; private final boolean encryption; - StoragePoolType(boolean shared, boolean overprovisioning, boolean encryption) { + /** + * New StoragePoolType, set the name to check with it in Dao (Note: Do not register it into the map of pool types). + * @param name name of the StoragePoolType. + */ + public StoragePoolType(String name) { + this.name = name; + this.shared = false; + this.overProvisioning = false; + this.encryption = false; + } + + /** + * Define a new StoragePoolType, and register it into the map of pool types known to the management server. + * @param name Simple unique name of the StoragePoolType. + * @param shared Storage pool is shared/accessible to multiple hypervisors + * @param overProvisioning Storage pool supports overProvisioning + * @param encryption Storage pool supports encrypted volumes + */ + public StoragePoolType(String name, boolean shared, boolean overProvisioning, boolean encryption) { + this.name = name; this.shared = shared; - this.overprovisioning = overprovisioning; + this.overProvisioning = overProvisioning; this.encryption = encryption; + addStoragePoolType(this); } public boolean isShared() { @@ -166,14 +212,58 @@ public class Storage { } public boolean supportsOverProvisioning() { - return overprovisioning; + return overProvisioning; } - public boolean supportsEncryption() { return encryption; } + public boolean supportsEncryption() { + return encryption; + } + + private static void addStoragePoolType(StoragePoolType storagePoolType) { + map.putIfAbsent(storagePoolType.name, storagePoolType); + } + + public static StoragePoolType[] values() { + return map.values().toArray(StoragePoolType[]::new).clone(); + } + + public static StoragePoolType valueOf(String name) { + if (StringUtils.isBlank(name)) { + return null; + } + + StoragePoolType storage = map.get(name); + if (storage == null) { + throw new IllegalArgumentException("StoragePoolType '" + name + "' not found"); + } + return storage; + } + + @Override + public String toString() { + return name; + } + + public String name() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + StoragePoolType that = (StoragePoolType) o; + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } } public static List getNonSharedStoragePoolTypes() { - List nonSharedStoragePoolTypes = new ArrayList(); + List nonSharedStoragePoolTypes = new ArrayList<>(); for (StoragePoolType storagePoolType : StoragePoolType.values()) { if (!storagePoolType.isShared()) { nonSharedStoragePoolTypes.add(storagePoolType); diff --git a/api/src/main/java/com/cloud/storage/StorageService.java b/api/src/main/java/com/cloud/storage/StorageService.java index bb086ad05cb..1ce335b0115 100644 --- a/api/src/main/java/com/cloud/storage/StorageService.java +++ b/api/src/main/java/com/cloud/storage/StorageService.java @@ -21,19 +21,29 @@ import java.net.UnknownHostException; import java.util.Map; import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd; +import org.apache.cloudstack.api.command.admin.storage.ChangeStoragePoolScopeCmd; import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd; import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd; import org.apache.cloudstack.api.command.admin.storage.DeleteImageStoreCmd; +import org.apache.cloudstack.api.command.admin.storage.DeleteObjectStoragePoolCmd; import org.apache.cloudstack.api.command.admin.storage.DeletePoolCmd; import org.apache.cloudstack.api.command.admin.storage.DeleteSecondaryStagingStoreCmd; import org.apache.cloudstack.api.command.admin.storage.SyncStoragePoolCmd; +import org.apache.cloudstack.api.command.admin.storage.UpdateObjectStoragePoolCmd; +import org.apache.cloudstack.api.command.admin.storage.UpdateImageStoreCmd; import org.apache.cloudstack.api.command.admin.storage.UpdateStoragePoolCmd; import com.cloud.exception.DiscoveryException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceInUseException; import com.cloud.exception.ResourceUnavailableException; +import org.apache.cloudstack.api.command.admin.storage.heuristics.CreateSecondaryStorageSelectorCmd; +import org.apache.cloudstack.api.command.admin.storage.heuristics.RemoveSecondaryStorageSelectorCmd; +import org.apache.cloudstack.api.command.admin.storage.heuristics.UpdateSecondaryStorageSelectorCmd; +import org.apache.cloudstack.secstorage.heuristics.Heuristic; +import org.apache.cloudstack.storage.object.ObjectStore; public interface StorageService { /** @@ -103,10 +113,25 @@ public interface StorageService { */ ImageStore migrateToObjectStore(String name, String url, String providerName, Map details) throws DiscoveryException; + ImageStore updateImageStore(UpdateImageStoreCmd cmd); + ImageStore updateImageStoreStatus(Long id, Boolean readonly); void updateStorageCapabilities(Long poolId, boolean failOnChecks); StoragePool syncStoragePool(SyncStoragePoolCmd cmd); + Heuristic createSecondaryStorageHeuristic(CreateSecondaryStorageSelectorCmd cmd); + + Heuristic updateSecondaryStorageHeuristic(UpdateSecondaryStorageSelectorCmd cmd); + + void removeSecondaryStorageHeuristic(RemoveSecondaryStorageSelectorCmd cmd); + + ObjectStore discoverObjectStore(String name, String url, String providerName, Map details) throws IllegalArgumentException, DiscoveryException, InvalidParameterValueException; + + boolean deleteObjectStore(DeleteObjectStoragePoolCmd cmd); + + ObjectStore updateObjectStore(Long id, UpdateObjectStoragePoolCmd cmd); + + void changeStoragePoolScope(ChangeStoragePoolScopeCmd cmd) throws IllegalArgumentException, InvalidParameterValueException, PermissionDeniedException; } diff --git a/api/src/main/java/com/cloud/storage/Volume.java b/api/src/main/java/com/cloud/storage/Volume.java index 4a14197bd30..40c5660b2df 100644 --- a/api/src/main/java/com/cloud/storage/Volume.java +++ b/api/src/main/java/com/cloud/storage/Volume.java @@ -30,6 +30,8 @@ import com.cloud.utils.fsm.StateObject; public interface Volume extends ControlledEntity, Identity, InternalIdentity, BasedOn, StateObject, Displayable { + static final long DISK_OFFERING_SUITABILITY_CHECK_VOLUME_ID = -1; + // Managed storage volume parameters (specified in the compute/disk offering for PowerFlex) String BANDWIDTH_LIMIT_IN_MBPS = "bandwidthLimitInMbps"; String IOPS_LIMIT = "iopsLimit"; @@ -39,30 +41,38 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba }; enum State { - Allocated("The volume is allocated but has not been created yet."), - Creating("The volume is being created. getPoolId() should reflect the pool where it is being created."), - Ready("The volume is ready to be used."), - Migrating("The volume is migrating to other storage pool"), - Snapshotting("There is a snapshot created on this volume, not backed up to secondary storage yet"), - RevertSnapshotting("There is a snapshot created on this volume, the volume is being reverting from snapshot"), - Resizing("The volume is being resized"), - Expunging("The volume is being expunging"), - Expunged("The volume has been expunged, and can no longer be recovered"), - Destroy("The volume is destroyed, and can be recovered."), - Destroying("The volume is destroying, and can't be recovered."), - UploadOp("The volume upload operation is in progress or in short the volume is on secondary storage"), - Copying("Volume is copying from image store to primary, in case it's an uploaded volume"), - Uploaded("Volume is uploaded"), - NotUploaded("The volume entry is just created in DB, not yet uploaded"), - UploadInProgress("Volume upload is in progress"), - UploadError("Volume upload encountered some error"), - UploadAbandoned("Volume upload is abandoned since the upload was never initiated within a specified time"), - Attaching("The volume is attaching to a VM from Ready state."), - Restoring("The volume is being restored from backup."); + Allocated(false, "The volume is allocated but has not been created yet."), + Creating(true, "The volume is being created. getPoolId() should reflect the pool where it is being created."), + Ready(false, "The volume is ready to be used."), + Migrating(true, "The volume is migrating to other storage pool"), + Snapshotting(true, "There is a snapshot created on this volume, not backed up to secondary storage yet"), + RevertSnapshotting(true, "There is a snapshot created on this volume, the volume is being reverting from snapshot"), + Resizing(true, "The volume is being resized"), + Expunging(true, "The volume is being expunging"), + Expunged(false, "The volume has been expunged, and can no longer be recovered"), + Destroy(false, "The volume is destroyed, and can be recovered."), + Destroying(false, "The volume is destroying, and can't be recovered."), + UploadOp(true, "The volume upload operation is in progress or in short the volume is on secondary storage"), + Copying(true, "Volume is copying from image store to primary, in case it's an uploaded volume"), + Uploaded(false, "Volume is uploaded"), + NotUploaded(true, "The volume entry is just created in DB, not yet uploaded"), + UploadInProgress(true, "Volume upload is in progress"), + UploadError(false, "Volume upload encountered some error"), + UploadAbandoned(false, "Volume upload is abandoned since the upload was never initiated within a specified time"), + Attaching(true, "The volume is attaching to a VM from Ready state."), + Restoring(true, "The volume is being restored from backup."); + + boolean _transitional; String _description; - private State(String description) { + /** + * Volume State + * @param transitional true for transition/non-final state, otherwise false + * @param description description of the state + */ + private State(boolean transitional, String description) { + _transitional = transitional; _description = description; } @@ -70,6 +80,10 @@ public interface Volume extends ControlledEntity, Identity, InternalIdentity, Ba return s_fsm; } + public boolean isTransitional() { + return _transitional; + } + public String getDescription() { return _description; } diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java index 09a3a33d915..4f09702b7db 100644 --- a/api/src/main/java/com/cloud/storage/VolumeApiService.java +++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java @@ -19,12 +19,14 @@ package com.cloud.storage; import java.net.MalformedURLException; +import java.util.List; import java.util.Map; -import com.cloud.utils.fsm.NoTransitionException; +import com.cloud.utils.Pair; import org.apache.cloudstack.api.command.user.volume.AssignVolumeCmd; import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; import org.apache.cloudstack.api.command.user.volume.ChangeOfferingForVolumeCmd; +import org.apache.cloudstack.api.command.user.volume.CheckAndRepairVolumeCmd; import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd; @@ -37,6 +39,7 @@ import org.apache.cloudstack.framework.config.ConfigKey; import com.cloud.exception.ResourceAllocationException; import com.cloud.user.Account; +import com.cloud.utils.fsm.NoTransitionException; public interface VolumeApiService { @@ -105,10 +108,10 @@ public interface VolumeApiService { Volume detachVolumeFromVM(DetachVolumeCmd cmd); - Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup, Map tags) + Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup, Map tags, List zoneIds) throws ResourceAllocationException; - Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType) throws ResourceAllocationException; + Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, List zoneIds) throws ResourceAllocationException; Volume updateVolume(long volumeId, String path, String state, Long storageId, Boolean displayVolume, String customId, long owner, String chainInfo, String name); @@ -172,9 +175,13 @@ public interface VolumeApiService { boolean validateVolumeSizeInBytes(long size); + void validateDestroyVolume(Volume volume, Account caller, boolean expunge, boolean forceExpunge); + Volume changeDiskOfferingForVolume(ChangeOfferingForVolumeCmd cmd) throws ResourceAllocationException; void publishVolumeCreationUsageEvent(Volume volume); boolean stateTransitTo(Volume vol, Volume.Event event) throws NoTransitionException; + + Pair checkAndRepairVolume(CheckAndRepairVolumeCmd cmd) throws ResourceAllocationException; } diff --git a/api/src/main/java/com/cloud/storage/snapshot/SnapshotApiService.java b/api/src/main/java/com/cloud/storage/snapshot/SnapshotApiService.java index 38e5e105a48..0893f337ce2 100644 --- a/api/src/main/java/com/cloud/storage/snapshot/SnapshotApiService.java +++ b/api/src/main/java/com/cloud/storage/snapshot/SnapshotApiService.java @@ -18,18 +18,20 @@ package com.cloud.storage.snapshot; import java.util.List; +import org.apache.cloudstack.api.command.user.snapshot.CopySnapshotCmd; import org.apache.cloudstack.api.command.user.snapshot.CreateSnapshotPolicyCmd; import org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotPoliciesCmd; import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotPoliciesCmd; import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd; +import org.apache.cloudstack.api.command.user.snapshot.UpdateSnapshotPolicyCmd; import com.cloud.api.commands.ListRecurringSnapshotScheduleCmd; import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.StorageUnavailableException; import com.cloud.storage.Snapshot; import com.cloud.storage.Volume; import com.cloud.user.Account; import com.cloud.utils.Pair; -import org.apache.cloudstack.api.command.user.snapshot.UpdateSnapshotPolicyCmd; public interface SnapshotApiService { @@ -50,7 +52,7 @@ public interface SnapshotApiService { * @param snapshotId * TODO */ - boolean deleteSnapshot(long snapshotId); + boolean deleteSnapshot(long snapshotId, Long zoneId); /** * Creates a policy with specified schedule. maxSnaps specifies the number of most recent snapshots that are to be @@ -88,7 +90,7 @@ public interface SnapshotApiService { Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType) throws ResourceAllocationException; - Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, Boolean isFromVmSnapshot) + Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType, Boolean isFromVmSnapshot, List zoneIds) throws ResourceAllocationException; @@ -124,4 +126,6 @@ public interface SnapshotApiService { SnapshotPolicy updateSnapshotPolicy(UpdateSnapshotPolicyCmd updateSnapshotPolicyCmd); void markVolumeSnapshotsAsDestroyed(Volume volume); + + Snapshot copySnapshot(CopySnapshotCmd cmd) throws StorageUnavailableException, ResourceAllocationException; } diff --git a/api/src/main/java/com/cloud/user/Account.java b/api/src/main/java/com/cloud/user/Account.java index b4cdb882c4b..bb9838f137a 100644 --- a/api/src/main/java/com/cloud/user/Account.java +++ b/api/src/main/java/com/cloud/user/Account.java @@ -30,7 +30,7 @@ public interface Account extends ControlledEntity, InternalIdentity, Identity { * Account states. * */ enum State { - DISABLED, ENABLED, LOCKED; + DISABLED, ENABLED, LOCKED, REMOVED; /** * The toString method was overridden to maintain consistency in the DB, as the GenericDaoBase uses toString in the enum value to make the sql statements diff --git a/api/src/main/java/com/cloud/user/AccountService.java b/api/src/main/java/com/cloud/user/AccountService.java index 77a5b442e86..63f5455cfd0 100644 --- a/api/src/main/java/com/cloud/user/AccountService.java +++ b/api/src/main/java/com/cloud/user/AccountService.java @@ -70,6 +70,8 @@ public interface AccountService { UserAccount getActiveUserAccount(String username, Long domainId); + List getActiveUserAccountByEmail(String email, Long domainId); + UserAccount updateUser(UpdateUserCmd updateUserCmd); Account getActiveAccountById(long accountId); diff --git a/api/src/main/java/com/cloud/user/DomainService.java b/api/src/main/java/com/cloud/user/DomainService.java index 3ccfcbcea4c..06109cf5ff7 100644 --- a/api/src/main/java/com/cloud/user/DomainService.java +++ b/api/src/main/java/com/cloud/user/DomainService.java @@ -20,9 +20,11 @@ import java.util.List; import org.apache.cloudstack.api.command.admin.domain.ListDomainChildrenCmd; import org.apache.cloudstack.api.command.admin.domain.ListDomainsCmd; +import org.apache.cloudstack.api.command.admin.domain.MoveDomainCmd; import com.cloud.domain.Domain; import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceAllocationException; import com.cloud.utils.Pair; public interface DomainService { @@ -66,4 +68,5 @@ public interface DomainService { */ Domain findDomainByIdOrPath(Long id, String domainPath); + Domain moveDomainAndChildrenToNewParentDomain(MoveDomainCmd cmd) throws ResourceAllocationException; } diff --git a/api/src/main/java/com/cloud/user/ResourceLimitService.java b/api/src/main/java/com/cloud/user/ResourceLimitService.java index f2d87a4390d..2f4ad1347be 100644 --- a/api/src/main/java/com/cloud/user/ResourceLimitService.java +++ b/api/src/main/java/com/cloud/user/ResourceLimitService.java @@ -18,13 +18,18 @@ package com.cloud.user; import java.util.List; +import org.apache.cloudstack.api.response.AccountResponse; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.framework.config.ConfigKey; + import com.cloud.configuration.Resource.ResourceType; import com.cloud.configuration.ResourceCount; import com.cloud.configuration.ResourceLimit; import com.cloud.domain.Domain; import com.cloud.exception.ResourceAllocationException; -import org.apache.cloudstack.framework.config.ConfigKey; -import org.apache.cloudstack.user.ResourceReservation; +import com.cloud.offering.DiskOffering; +import com.cloud.offering.ServiceOffering; +import com.cloud.template.VirtualMachineTemplate; public interface ResourceLimitService { @@ -33,7 +38,21 @@ public interface ResourceLimitService { static final ConfigKey MaxProjectSecondaryStorage = new ConfigKey<>("Project Defaults", Long.class, "max.project.secondary.storage", "400", "The default maximum secondary storage space (in GiB) that can be used for a project", false); static final ConfigKey ResourceCountCheckInterval = new ConfigKey<>("Advanced", Long.class, "resourcecount.check.interval", "300", - "Time (in seconds) to wait before running resource recalculation and fixing task. Default is 300 seconds, Setting this to 0 disables execution of the task", false); + "Time (in seconds) to wait before running resource recalculation and fixing tasks like stale resource reservation cleanup" + + ". Default is 300 seconds, Setting this to 0 disables execution of the task", true); + static final ConfigKey ResourceReservationCleanupDelay = new ConfigKey<>("Advanced", Long.class, "resource.reservation.cleanup.delay", "3600", + "Time (in seconds) after which a resource reservation gets deleted. Default is 3600 seconds, Setting this to 0 disables execution of the task", true); + static final ConfigKey ResourceLimitHostTags = new ConfigKey<>("Advanced", String.class, "resource.limit.host.tags", "", + "A comma-separated list of tags for host resource limits", true); + static final ConfigKey ResourceLimitStorageTags = new ConfigKey<>("Advanced", String.class, "resource.limit.storage.tags", "", + "A comma-separated list of tags for storage resource limits", true); + static final ConfigKey DefaultMaxAccountProjects = new ConfigKey<>("Account Defaults",Long.class,"max.account.projects","10", + "The default maximum number of projects that can be created for an account",false); + static final ConfigKey DefaultMaxDomainProjects = new ConfigKey<>("Domain Defaults",Long.class,"max.domain.projects","50", + "The default maximum number of projects that can be created for a domain",false); + + static final List HostTagsSupportingTypes = List.of(ResourceType.user_vm, ResourceType.cpu, ResourceType.memory); + static final List StorageTagsSupportingTypes = List.of(ResourceType.volume, ResourceType.primary_storage); /** * Updates an existing resource limit with the specified details. If a limit doesn't exist, will create one. @@ -46,22 +65,27 @@ public interface ResourceLimitService { * TODO * @param max * TODO + * @param tag + * tag for the resource type * * @return the updated/created resource limit */ - ResourceLimit updateResourceLimit(Long accountId, Long domainId, Integer resourceType, Long max); + ResourceLimit updateResourceLimit(Long accountId, Long domainId, Integer resourceType, Long max, String tag); /** * Updates an existing resource count details for the account/domain * * @param accountId - * TODO + * Id of the account for which resource recalculation to be done * @param domainId - * TODO + * Id of the domain for which resource recalculation to be doneDO * @param typeId - * TODO + * type of the resource for which recalculation to be done + * @param tag + * tag for the resource type for which recalculation to be done * @return the updated/created resource counts */ + List recalculateResourceCount(Long accountId, Long domainId, Integer typeId, String tag); List recalculateResourceCount(Long accountId, Long domainId, Integer typeId); /** @@ -77,7 +101,7 @@ public interface ResourceLimitService { * TODO * @return a list of limits that match the criteria */ - public List searchForLimits(Long id, Long accountId, Long domainId, ResourceType resourceType, Long startIndex, Long pageSizeVal); + public List searchForLimits(Long id, Long accountId, Long domainId, ResourceType resourceType, String tag, Long startIndex, Long pageSizeVal); /** * Finds the resource limit for a specified account and type. If the account has an infinite limit, will check @@ -85,9 +109,10 @@ public interface ResourceLimitService { * * @param account * @param type + * @param tag * @return resource limit */ - public long findCorrectResourceLimitForAccount(Account account, ResourceType type); + public long findCorrectResourceLimitForAccount(Account account, ResourceType type, String tag); /** * This call should be used when we have already queried resource limit for an account. This is to handle @@ -105,9 +130,10 @@ public interface ResourceLimitService { * * @param domain * @param type + * @param tag * @return resource limit */ - public long findCorrectResourceLimitForDomain(Domain domain, ResourceType type); + public long findCorrectResourceLimitForDomain(Domain domain, ResourceType type, String tag); /** * Finds the default resource limit for a specified type. @@ -122,9 +148,10 @@ public interface ResourceLimitService { * * @param domain * @param type + * @param tag * @return resource limit */ - public long findCorrectResourceLimitForAccountAndDomain(Account account, Domain domain, ResourceType type); + public long findCorrectResourceLimitForAccountAndDomain(Account account, Domain domain, ResourceType type, String tag); /** * Increments the resource count @@ -134,6 +161,7 @@ public interface ResourceLimitService { * @param delta */ public void incrementResourceCount(long accountId, ResourceType type, Long... delta); + public void incrementResourceCountWithTag(long accountId, ResourceType type, String tag, Long... delta); /** * Decrements the resource count @@ -143,6 +171,7 @@ public interface ResourceLimitService { * @param delta */ public void decrementResourceCount(long accountId, ResourceType type, Long... delta); + public void decrementResourceCountWithTag(long accountId, ResourceType type, String tag, Long... delta); /** * Checks if a limit has been exceeded for an account @@ -155,15 +184,17 @@ public interface ResourceLimitService { * @throws ResourceAllocationException */ public void checkResourceLimit(Account account, ResourceCount.ResourceType type, long... count) throws ResourceAllocationException; + public void checkResourceLimitWithTag(Account account, ResourceCount.ResourceType type, String tag, long... count) throws ResourceAllocationException; /** * Gets the count of resources for a resource type and account * * @param account * @param type + * @param tag * @return count of resources */ - public long getResourceCount(Account account, ResourceType type); + public long getResourceCount(Account account, ResourceType type, String tag); /** * Checks if a limit has been exceeded for an account if displayResource flag is on @@ -208,15 +239,49 @@ public interface ResourceLimitService { */ void decrementResourceCount(long accountId, ResourceType type, Boolean displayResource, Long... delta); - /** - * Adds a reservation that will be counted in subsequent calls to {count}getResourceCount{code} until {code}this[code} - * is closed. It will create a reservation record that will be counted when resource limits are checked. - * @param account The account for which the reservation is. - * @param displayResource whether this resource is shown to users at all (if not it is not counted to limits) - * @param type resource type - * @param delta amount to reserve (will not be <+ 0) - * @return a {code}AutoClosable{Code} object representing the resource the user needs - */ - ResourceReservation getReservation(Account account, Boolean displayResource, ResourceType type, Long delta) throws ResourceAllocationException; + List getResourceLimitHostTags(); + List getResourceLimitHostTags(ServiceOffering serviceOffering, VirtualMachineTemplate template); + List getResourceLimitStorageTags(); + List getResourceLimitStorageTags(DiskOffering diskOffering); + void updateTaggedResourceLimitsAndCountsForAccounts(List responses, String tag); + void updateTaggedResourceLimitsAndCountsForDomains(List responses, String tag); + void checkVolumeResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException; + + void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize, + DiskOffering currentOffering, DiskOffering newOffering) throws ResourceAllocationException; + + void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException; + + void incrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering); + void decrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering); + + void updateVmResourceCountForTemplateChange(long accountId, Boolean display, ServiceOffering offering, VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate); + + void updateVmResourceCountForServiceOfferingChange(long accountId, Boolean display, Long currentCpu, Long newCpu, Long currentMemory, + Long newMemory, + ServiceOffering currentOffering, ServiceOffering newOffering, + VirtualMachineTemplate template); + + void updateVolumeResourceCountForDiskOfferingChange(long accountId, Boolean display, Long currentSize, Long newSize, + DiskOffering currentDiskOffering, DiskOffering newDiskOffering); + + void incrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering); + void decrementVolumePrimaryStorageResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering); + void checkVmResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template) throws ResourceAllocationException; + void incrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template); + void decrementVmResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template); + + void checkVmResourceLimitsForServiceOfferingChange(Account owner, Boolean display, Long currentCpu, Long newCpu, + Long currentMemory, Long newMemory, ServiceOffering currentOffering, ServiceOffering newOffering, VirtualMachineTemplate template) throws ResourceAllocationException; + + void checkVmResourceLimitsForTemplateChange(Account owner, Boolean display, ServiceOffering offering, + VirtualMachineTemplate currentTemplate, VirtualMachineTemplate newTemplate) throws ResourceAllocationException; + + void checkVmCpuResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu) throws ResourceAllocationException; + void incrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu); + void decrementVmCpuResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long cpu); + void checkVmMemoryResourceLimit(Account owner, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory) throws ResourceAllocationException; + void incrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory); + void decrementVmMemoryResourceCount(long accountId, Boolean display, ServiceOffering serviceOffering, VirtualMachineTemplate template, Long memory); } diff --git a/api/src/main/java/com/cloud/user/User.java b/api/src/main/java/com/cloud/user/User.java index c50ed3f28af..422e264f10b 100644 --- a/api/src/main/java/com/cloud/user/User.java +++ b/api/src/main/java/com/cloud/user/User.java @@ -24,7 +24,7 @@ public interface User extends OwnedBy, InternalIdentity { // UNKNOWN and NATIVE can be used interchangeably public enum Source { - LDAP, SAML2, SAML2DISABLED, UNKNOWN, NATIVE + OAUTH2, LDAP, SAML2, SAML2DISABLED, UNKNOWN, NATIVE } public static final long UID_SYSTEM = 1; diff --git a/api/src/main/java/com/cloud/uservm/UserVm.java b/api/src/main/java/com/cloud/uservm/UserVm.java index e30f5e03054..9035d2903c9 100644 --- a/api/src/main/java/com/cloud/uservm/UserVm.java +++ b/api/src/main/java/com/cloud/uservm/UserVm.java @@ -48,4 +48,6 @@ public interface UserVm extends VirtualMachine, ControlledEntity { void setAccountId(long accountId); public boolean isDisplayVm(); + + String getUserVmType(); } diff --git a/api/src/main/java/com/cloud/vm/NicProfile.java b/api/src/main/java/com/cloud/vm/NicProfile.java index 3f37331b1e4..183c8dcb2d5 100644 --- a/api/src/main/java/com/cloud/vm/NicProfile.java +++ b/api/src/main/java/com/cloud/vm/NicProfile.java @@ -62,6 +62,7 @@ public class NicProfile implements InternalIdentity, Serializable { String iPv4Dns1; String iPv4Dns2; String requestedIPv4; + boolean ipv4AllocationRaceCheck; // IPv6 String iPv6Address; @@ -405,6 +406,13 @@ public class NicProfile implements InternalIdentity, Serializable { this.mtu = mtu; } + public boolean getIpv4AllocationRaceCheck() { + return this.ipv4AllocationRaceCheck; + } + + public void setIpv4AllocationRaceCheck(boolean ipv4AllocationRaceCheck) { + this.ipv4AllocationRaceCheck = ipv4AllocationRaceCheck; + } // // OTHER METHODS @@ -442,6 +450,6 @@ public class NicProfile implements InternalIdentity, Serializable { @Override public String toString() { - return String.format("NicProfile %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "vmId", "reservationId", "iPv4Address", "broadcastUri")); + return String.format("NicProfile %s", ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "id", "vmId", "deviceId", "broadcastUri", "reservationId", "iPv4Address")); } } diff --git a/api/src/main/java/com/cloud/vm/UserVmService.java b/api/src/main/java/com/cloud/vm/UserVmService.java index d58b75b0dca..5a9301eef7f 100644 --- a/api/src/main/java/com/cloud/vm/UserVmService.java +++ b/api/src/main/java/com/cloud/vm/UserVmService.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.vm; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -41,9 +42,11 @@ import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; import com.cloud.dc.DataCenter; +import com.cloud.deploy.DeploymentPlanner; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ManagementServerException; +import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; @@ -65,10 +68,7 @@ public interface UserVmService { /** * Destroys one virtual machine * - * @param userId - * the id of the user performing the action - * @param vmId - * the id of the virtual machine. + * @param cmd the API Command Object containg the parameters to use for this service action * @throws ConcurrentOperationException * @throws ResourceUnavailableException */ @@ -109,7 +109,13 @@ public interface UserVmService { UserVm startVirtualMachine(StartVMCmd cmd) throws StorageUnavailableException, ExecutionException, ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException; - UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException; + UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ResourceAllocationException; + + void startVirtualMachine(UserVm vm) throws OperationTimedoutException, ResourceUnavailableException, InsufficientCapacityException; + + void startVirtualMachineForHA(VirtualMachine vm, Map params, + DeploymentPlanner planner) throws InsufficientCapacityException, ResourceUnavailableException, + ConcurrentOperationException, OperationTimedoutException; UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException; @@ -147,14 +153,6 @@ public interface UserVmService { * Creates a Basic Zone User VM in the database and returns the VM to the * caller. * - * - * - * @param sshKeyPair - * - name of the ssh key pair used to login to the virtual - * machine - * @param cpuSpeed - * @param memory - * @param cpuNumber * @param zone * - availability zone for the virtual machine * @param serviceOffering @@ -230,9 +228,6 @@ public interface UserVmService { * Creates a User VM in Advanced Zone (Security Group feature is enabled) in * the database and returns the VM to the caller. * - * - * - * @param type * @param zone * - availability zone for the virtual machine * @param serviceOffering @@ -308,14 +303,6 @@ public interface UserVmService { * Creates a User VM in Advanced Zone (Security Group feature is disabled) * in the database and returns the VM to the caller. * - * - * - * @param sshKeyPair - * - name of the ssh key pair used to login to the virtual - * machine - * @param cpuSpeed - * @param memory - * @param cpuNumber * @param zone * - availability zone for the virtual machine * @param serviceOffering @@ -489,9 +476,9 @@ public interface UserVmService { VirtualMachine vmStorageMigration(Long vmId, Map volumeToPool); - UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException; + UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ResourceAllocationException; - UserVm restoreVirtualMachine(Account caller, long vmId, Long newTemplateId) throws InsufficientCapacityException, ResourceUnavailableException; + UserVm restoreVirtualMachine(Account caller, long vmId, Long newTemplateId, Long rootDiskOfferingId, boolean expunge, Map details) throws InsufficientCapacityException, ResourceUnavailableException; UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException; @@ -518,7 +505,8 @@ public interface UserVmService { UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemplate template, final String instanceName, final String displayName, final Account owner, final String userData, final Account caller, final Boolean isDisplayVm, final String keyboard, final long accountId, final long userId, final ServiceOffering serviceOffering, final String sshPublicKey, - final String hostName, final HypervisorType hypervisorType, final Map customParameters, final VirtualMachine.PowerState powerState) throws InsufficientCapacityException; + final String hostName, final HypervisorType hypervisorType, final Map customParameters, + final VirtualMachine.PowerState powerState, final LinkedHashMap> networkNicMap) throws InsufficientCapacityException; /** * Unmanage a guest VM from CloudStack diff --git a/api/src/main/java/com/cloud/vm/VirtualMachine.java b/api/src/main/java/com/cloud/vm/VirtualMachine.java index 34c7a42b9a2..e7c5efb773b 100644 --- a/api/src/main/java/com/cloud/vm/VirtualMachine.java +++ b/api/src/main/java/com/cloud/vm/VirtualMachine.java @@ -315,6 +315,9 @@ public interface VirtualMachine extends RunningOn, ControlledEntity, Partition, @Override Long getHostId(); + + void setHostId(Long hostId); + /** * @return should HA be enabled for this machine? */ diff --git a/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java b/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java index 62519412fdb..c67ee4eabc2 100644 --- a/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java +++ b/api/src/main/java/com/cloud/vm/VirtualMachineProfile.java @@ -60,6 +60,8 @@ public interface VirtualMachineProfile { void setConfigDriveLocation(NetworkElement.Location location); + void setServiceOffering(ServiceOffering offering); + public static class Param { public static final Param VmPassword = new Param("VmPassword"); @@ -190,6 +192,10 @@ public interface VirtualMachineProfile { Map getParameters(); + void setCpuOvercommitRatio(Float cpuOvercommitRatio); + + void setMemoryOvercommitRatio(Float memoryOvercommitRatio); + Float getCpuOvercommitRatio(); Float getMemoryOvercommitRatio(); diff --git a/api/src/main/java/com/cloud/vm/VmDetailConstants.java b/api/src/main/java/com/cloud/vm/VmDetailConstants.java index add2518321b..603948d76cf 100644 --- a/api/src/main/java/com/cloud/vm/VmDetailConstants.java +++ b/api/src/main/java/com/cloud/vm/VmDetailConstants.java @@ -19,6 +19,7 @@ package com.cloud.vm; public interface VmDetailConstants { String KEYBOARD = "keyboard"; String CPU_CORE_PER_SOCKET = "cpu.corespersocket"; + String CPU_THREAD_PER_CORE = "cpu.threadspercore"; String ROOT_DISK_SIZE = "rootdisksize"; String BOOT_MODE = "boot.mode"; String NAME_ON_HYPERVISOR= "nameonhypervisor"; @@ -39,6 +40,7 @@ public interface VmDetailConstants { // KVM specific (internal) String KVM_VNC_PORT = "kvm.vnc.port"; String KVM_VNC_ADDRESS = "kvm.vnc.address"; + String KVM_VNC_PASSWORD = "kvm.vnc.password"; // KVM specific, custom virtual GPU hardware String VIDEO_HARDWARE = "video.hardware"; @@ -73,6 +75,8 @@ public interface VmDetailConstants { String CONFIG_DRIVE_LOCATION = "configDriveLocation"; + String SKIP_DRS = "skipFromDRS"; + // VM import with nic, disk and custom params for custom compute offering String NIC = "nic"; String NETWORK = "network"; @@ -84,4 +88,16 @@ public interface VmDetailConstants { String DEPLOY_AS_IS_CONFIGURATION = "configurationId"; String KEY_PAIR_NAMES = "keypairnames"; String CKS_CONTROL_NODE_LOGIN_USER = "controlNodeLoginUser"; + + // VMware to KVM VM migrations specific + String VMWARE_TO_KVM_PREFIX = "vmware-to-kvm"; + String VMWARE_VCENTER_HOST = String.format("%s-vcenter", VMWARE_TO_KVM_PREFIX); + String VMWARE_DATACENTER_NAME = String.format("%s-datacenter", VMWARE_TO_KVM_PREFIX); + String VMWARE_CLUSTER_NAME = String.format("%s-cluster", VMWARE_TO_KVM_PREFIX); + String VMWARE_VCENTER_USERNAME = String.format("%s-username", VMWARE_TO_KVM_PREFIX); + String VMWARE_VCENTER_PASSWORD = String.format("%s-password", VMWARE_TO_KVM_PREFIX); + String VMWARE_VM_NAME = String.format("%s-vmname", VMWARE_TO_KVM_PREFIX); + String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX); + String VMWARE_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX); + String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", VMWARE_TO_KVM_PREFIX); } diff --git a/api/src/main/java/org/apache/cloudstack/acl/RoleService.java b/api/src/main/java/org/apache/cloudstack/acl/RoleService.java index 9becce643d4..07f62a7e7f8 100644 --- a/api/src/main/java/org/apache/cloudstack/acl/RoleService.java +++ b/api/src/main/java/org/apache/cloudstack/acl/RoleService.java @@ -38,7 +38,9 @@ public interface RoleService { * Moreover, we will check if the requested role is of 'Admin' type; roles with 'Admin' type should only be visible to 'root admins'. * Therefore, if a non-'root admin' user tries to search for an 'Admin' role, this method will return null. */ - Role findRole(Long id, boolean removePrivateRoles); + Role findRole(Long id, boolean ignorePrivateRoles); + + List findRoles(List ids, boolean ignorePrivateRoles); Role findRole(Long id); diff --git a/api/src/main/java/org/apache/cloudstack/acl/RoleType.java b/api/src/main/java/org/apache/cloudstack/acl/RoleType.java index ec82cd6605b..005d47c85bc 100644 --- a/api/src/main/java/org/apache/cloudstack/acl/RoleType.java +++ b/api/src/main/java/org/apache/cloudstack/acl/RoleType.java @@ -20,7 +20,8 @@ import org.apache.commons.lang3.StringUtils; import com.cloud.user.Account; import com.google.common.base.Enums; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import java.util.HashMap; import java.util.Map; @@ -37,7 +38,7 @@ public enum RoleType { private Account.Type accountType; private int mask; - private static Logger logger = Logger.getLogger(RoleType.class.getName()); + private static Logger LOGGER = LogManager.getLogger(RoleType.class.getName()); private static Map ACCOUNT_TYPE_MAP = new HashMap<>(); static { @@ -104,10 +105,10 @@ public enum RoleType { * */ public static Account.Type getAccountTypeByRole(final Role role, final Account.Type defautAccountType) { if (role != null) { - logger.debug(String.format("Role [%s] is not null; therefore, we use its account type [%s].", role, defautAccountType)); + LOGGER.debug(String.format("Role [%s] is not null; therefore, we use its account type [%s].", role, defautAccountType)); return role.getRoleType().getAccountType(); } - logger.debug(String.format("Role is null; therefore, we use the default account type [%s] value.", defautAccountType)); + LOGGER.debug(String.format("Role is null; therefore, we use the default account type [%s] value.", defautAccountType)); return defautAccountType; } } diff --git a/api/src/main/java/org/apache/cloudstack/affinity/AffinityGroupProcessor.java b/api/src/main/java/org/apache/cloudstack/affinity/AffinityGroupProcessor.java index f3ff1dd37f1..077953d0931 100644 --- a/api/src/main/java/org/apache/cloudstack/affinity/AffinityGroupProcessor.java +++ b/api/src/main/java/org/apache/cloudstack/affinity/AffinityGroupProcessor.java @@ -21,8 +21,11 @@ import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.exception.AffinityConflictException; import com.cloud.utils.component.Adapter; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; +import java.util.List; + public interface AffinityGroupProcessor extends Adapter { /** @@ -35,7 +38,12 @@ public interface AffinityGroupProcessor extends Adapter { * deployment plan that tells you where it's being deployed to. * @param avoid * avoid these data centers, pods, clusters, or hosts. + * @param vmList + * list of virtual machines objects according to which the affinity group should be processed. + * This can be used to process a theoretical state in some cases like generating DRS plans */ + void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid, List vmList) throws AffinityConflictException; + void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) throws AffinityConflictException; /** diff --git a/api/src/main/java/org/apache/cloudstack/affinity/AffinityProcessorBase.java b/api/src/main/java/org/apache/cloudstack/affinity/AffinityProcessorBase.java index d48b5fd7556..9995d8039e1 100644 --- a/api/src/main/java/org/apache/cloudstack/affinity/AffinityProcessorBase.java +++ b/api/src/main/java/org/apache/cloudstack/affinity/AffinityProcessorBase.java @@ -21,14 +21,23 @@ import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.exception.AffinityConflictException; import com.cloud.utils.component.AdapterBase; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; +import java.util.Collections; +import java.util.List; + public class AffinityProcessorBase extends AdapterBase implements AffinityGroupProcessor { protected String _type; @Override public void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) throws AffinityConflictException { + process(vm, plan, avoid, Collections.emptyList()); + } + + @Override + public void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid, List vmList) throws AffinityConflictException { } diff --git a/api/src/main/java/org/apache/cloudstack/alert/AlertService.java b/api/src/main/java/org/apache/cloudstack/alert/AlertService.java index 5b29426e6eb..1250284b5c2 100644 --- a/api/src/main/java/org/apache/cloudstack/alert/AlertService.java +++ b/api/src/main/java/org/apache/cloudstack/alert/AlertService.java @@ -52,7 +52,7 @@ public interface AlertService { public static final AlertType ALERT_TYPE_ROUTING = new AlertType((short)11, "ALERT.NETWORK.ROUTING", true); public static final AlertType ALERT_TYPE_STORAGE_MISC = new AlertType((short)12, "ALERT.STORAGE.MISC", true); public static final AlertType ALERT_TYPE_USAGE_SERVER = new AlertType((short)13, "ALERT.USAGE", true); - public static final AlertType ALERT_TYPE_MANAGMENT_NODE = new AlertType((short)14, "ALERT.MANAGEMENT", true); + public static final AlertType ALERT_TYPE_MANAGEMENT_NODE = new AlertType((short)14, "ALERT.MANAGEMENT", true); public static final AlertType ALERT_TYPE_DOMAIN_ROUTER_MIGRATE = new AlertType((short)15, "ALERT.NETWORK.DOMAINROUTERMIGRATE", true); public static final AlertType ALERT_TYPE_CONSOLE_PROXY_MIGRATE = new AlertType((short)16, "ALERT.SERVICE.CONSOLEPROXYMIGRATE", true); public static final AlertType ALERT_TYPE_USERVM_MIGRATE = new AlertType((short)17, "ALERT.USERVM.MIGRATE", true); @@ -91,6 +91,10 @@ public interface AlertService { return null; } + public static Set getAlertTypes() { + return defaultAlertTypes; + } + @Override public String toString() { return String.valueOf(this.getType()); diff --git a/api/src/main/java/org/apache/cloudstack/annotation/AnnotationService.java b/api/src/main/java/org/apache/cloudstack/annotation/AnnotationService.java index 51c6286a9d5..64bd96d9a9b 100644 --- a/api/src/main/java/org/apache/cloudstack/annotation/AnnotationService.java +++ b/api/src/main/java/org/apache/cloudstack/annotation/AnnotationService.java @@ -45,7 +45,7 @@ public interface AnnotationService { SERVICE_OFFERING(false), DISK_OFFERING(false), NETWORK_OFFERING(false), ZONE(false), POD(false), CLUSTER(false), HOST(false), DOMAIN(false), PRIMARY_STORAGE(false), SECONDARY_STORAGE(false), VR(false), SYSTEM_VM(false), - AUTOSCALE_VM_GROUP(true), MANAGEMENT_SERVER(false),; + AUTOSCALE_VM_GROUP(true), MANAGEMENT_SERVER(false), OBJECT_STORAGE(false); private final boolean usersAllowed; @@ -78,6 +78,7 @@ public interface AnnotationService { list.add(EntityType.VR); list.add(EntityType.SYSTEM_VM); list.add(EntityType.MANAGEMENT_SERVER); + list.add(EntityType.OBJECT_STORAGE); if (roleType != RoleType.DomainAdmin) { list.add(EntityType.DOMAIN); list.add(EntityType.SERVICE_OFFERING); diff --git a/api/src/main/java/org/apache/cloudstack/api/AbstractGetUploadParamsCmd.java b/api/src/main/java/org/apache/cloudstack/api/AbstractGetUploadParamsCmd.java index ed3381ae97c..083a1be00f5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/AbstractGetUploadParamsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/AbstractGetUploadParamsCmd.java @@ -25,11 +25,9 @@ import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.GetUploadParamsResponse; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; public abstract class AbstractGetUploadParamsCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AbstractGetUploadParamsCmd.class.getName()); @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name of the volume/template/iso") private String name; diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java b/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java index 9267ca6fa96..93893676516 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java @@ -17,7 +17,9 @@ package org.apache.cloudstack.api; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.cloudstack.region.PortableIp; import org.apache.commons.collections.CollectionUtils; @@ -78,15 +80,25 @@ public enum ApiCommandResourceType { VmSnapshot(com.cloud.vm.snapshot.VMSnapshot.class), Role(org.apache.cloudstack.acl.Role.class), VpnCustomerGateway(com.cloud.network.Site2SiteCustomerGateway.class), - ManagementServer(org.apache.cloudstack.management.ManagementServerHost.class); + ManagementServer(org.apache.cloudstack.management.ManagementServerHost.class), + ObjectStore(org.apache.cloudstack.storage.object.ObjectStore.class), + Bucket(org.apache.cloudstack.storage.object.Bucket.class), + QuotaTariff(org.apache.cloudstack.quota.QuotaTariff.class), + KubernetesCluster(null), + KubernetesSupportedVersion(null); private final Class clazz; + static final Map> additionalClassMappings = new HashMap<>(); + private ApiCommandResourceType(Class clazz) { this.clazz = clazz; } public Class getAssociatedClass() { + if (this.clazz == null && additionalClassMappings.containsKey(this)) { + return additionalClassMappings.get(this); + } return this.clazz; } @@ -116,4 +128,8 @@ public enum ApiCommandResourceType { } return null; } + + public static void setClassMapping(ApiCommandResourceType type, Class clazz) { + additionalClassMappings.put(type, clazz); + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index 3e0e65220e1..7a167a7aeb6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -69,6 +69,8 @@ public class ApiConstants { public static final String CERTIFICATE_SERIALNUM = "serialnum"; public static final String CERTIFICATE_SUBJECT = "subject"; public static final String CERTIFICATE_VALIDITY = "validity"; + public static final String CONVERT_INSTANCE_HOST_ID = "convertinstancehostid"; + public static final String CONVERT_INSTANCE_STORAGE_POOL_ID = "convertinstancepoolid"; public static final String ENABLED_REVOCATION_CHECK = "enabledrevocationcheck"; public static final String CONTROLLER = "controller"; public static final String CONTROLLER_UNIT = "controllerunit"; @@ -76,8 +78,10 @@ public class ApiConstants { public static final String CSR = "csr"; public static final String PRIVATE_KEY = "privatekey"; public static final String DATASTORE_HOST = "datastorehost"; + public static final String DATASTORE_ID = "datastoreid"; public static final String DATASTORE_NAME = "datastorename"; public static final String DATASTORE_PATH = "datastorepath"; + public static final String DATASTORE_STATE = "datastorestate"; public static final String DATASTORE_TYPE = "datastoretype"; public static final String DOMAIN_SUFFIX = "domainsuffix"; public static final String DNS_SEARCH_ORDER = "dnssearchorder"; @@ -113,11 +117,13 @@ public class ApiConstants { public static final String CURRENT_START_IP = "currentstartip"; public static final String CURRENT_END_IP = "currentendip"; public static final String ENCRYPT = "encrypt"; + public static final String ENCRYPT_FORMAT = "encryptformat"; public static final String ENCRYPT_ROOT = "encryptroot"; public static final String ENCRYPTION_SUPPORTED = "encryptionsupported"; public static final String MIN_IOPS = "miniops"; public static final String MAX_IOPS = "maxiops"; public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve"; + public static final String DATACENTER_NAME = "datacentername"; public static final String DATADISK_OFFERING_LIST = "datadiskofferinglist"; public static final String DEFAULT_VALUE = "defaultvalue"; public static final String DESCRIPTION = "description"; @@ -169,6 +175,8 @@ public class ApiConstants { public static final String END_IPV6 = "endipv6"; public static final String END_PORT = "endport"; public static final String ENTRY_TIME = "entrytime"; + public static final String EVENT_ID = "eventid"; + public static final String EVENT_TYPE = "eventtype"; public static final String EXPIRES = "expires"; public static final String EXTRA_CONFIG = "extraconfig"; public static final String EXTRA_DHCP_OPTION = "extradhcpoption"; @@ -183,9 +191,11 @@ public class ApiConstants { public static final String FORCED = "forced"; public static final String FORCED_DESTROY_LOCAL_STORAGE = "forcedestroylocalstorage"; public static final String FORCE_DELETE_HOST = "forcedeletehost"; + public static final String FORCE_MS_TO_IMPORT_VM_FILES = "forcemstoimportvmfiles"; public static final String FORMAT = "format"; public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork"; public static final String FOR_SYSTEM_VMS = "forsystemvms"; + public static final String FULL_PATH = "fullpath"; public static final String GATEWAY = "gateway"; public static final String IP6_GATEWAY = "ip6gateway"; public static final String GROUP = "group"; @@ -202,10 +212,13 @@ public class ApiConstants { public static final String HA_PROVIDER = "haprovider"; public static final String HA_STATE = "hastate"; public static final String HEALTH = "health"; + public static final String HEADERS = "headers"; public static final String HIDE_IP_ADDRESS_USAGE = "hideipaddressusage"; public static final String HOST_ID = "hostid"; public static final String HOST_IDS = "hostids"; + public static final String HOST_IP = "hostip"; public static final String HOST_NAME = "hostname"; + public static final String HOST = "host"; public static final String HOST_CONTROL_STATE = "hostcontrolstate"; public static final String HOSTS_MAP = "hostsmap"; public static final String HYPERVISOR = "hypervisor"; @@ -222,9 +235,12 @@ public class ApiConstants { public static final String INSTANCES_STATS_USER_ONLY = "instancesstatsuseronly"; public static final String PREFIX = "prefix"; public static final String PREVIOUS_ACL_RULE_ID = "previousaclruleid"; + public static final String PREVIOUS_OWNER_ID = "previousownerid"; + public static final String PREVIOUS_OWNER_NAME = "previousownername"; public static final String NEXT_ACL_RULE_ID = "nextaclruleid"; public static final String MOVE_ACL_CONSISTENCY_HASH = "aclconsistencyhash"; public static final String IMAGE_PATH = "imagepath"; + public static final String INSTANCE_CONVERSION_SUPPORTED = "instanceconversionsupported"; public static final String INTERNAL_DNS1 = "internaldns1"; public static final String INTERNAL_DNS2 = "internaldns2"; public static final String INTERNET_PROTOCOL = "internetprotocol"; @@ -252,8 +268,10 @@ public class ApiConstants { public static final String IS_CLEANUP_REQUIRED = "iscleanuprequired"; public static final String IS_DYNAMIC = "isdynamic"; public static final String IS_EDGE = "isedge"; + public static final String IS_ENCRYPTED = "isencrypted"; public static final String IS_EXTRACTABLE = "isextractable"; public static final String IS_FEATURED = "isfeatured"; + public static final String IS_IMPLICIT = "isimplicit"; public static final String IS_PORTABLE = "isportable"; public static final String IS_PUBLIC = "ispublic"; public static final String IS_PERSISTENT = "ispersistent"; @@ -269,6 +287,7 @@ public class ApiConstants { public static final String JOB_STATUS = "jobstatus"; public static final String KEEPALIVE_ENABLED = "keepaliveenabled"; public static final String KERNEL_VERSION = "kernelversion"; + public static final String KEY = "key"; public static final String LABEL = "label"; public static final String LASTNAME = "lastname"; public static final String LAST_BOOT = "lastboottime"; @@ -276,6 +295,7 @@ public class ApiConstants { public static final String LAST_SERVER_STOP = "lastserverstop"; public static final String LEVEL = "level"; public static final String LENGTH = "length"; + public static final String LIMIT = "limit"; public static final String LIMIT_CPU_USE = "limitcpuuse"; public static final String LIST_HOSTS = "listhosts"; public static final String LOCK = "lock"; @@ -290,8 +310,11 @@ public class ApiConstants { public static final String MIN_CPU_NUMBER = "mincpunumber"; public static final String MIN_MEMORY = "minmemory"; public static final String MIGRATION_TYPE = "migrationtype"; + public static final String MIGRATIONS = "migrations"; public static final String MEMORY = "memory"; public static final String MODE = "mode"; + public static final String NSX_MODE = "nsxmode"; + public static final String NSX_ENABLED = "isnsxenabled"; public static final String NAME = "name"; public static final String METHOD_NAME = "methodname"; public static final String NETWORK_DOMAIN = "networkdomain"; @@ -311,6 +334,7 @@ public class ApiConstants { public static final String IS_DEFAULT_USE = "defaultuse"; public static final String OLD_FORMAT = "oldformat"; public static final String OP = "op"; + public static final String OPTION = "option"; public static final String OPTIONS = "options"; public static final String OS_CATEGORY_ID = "oscategoryid"; public static final String OS_CATEGORY_NAME = "oscategoryname"; @@ -338,6 +362,7 @@ public class ApiConstants { public static final String SSHKEY_ENABLED = "sshkeyenabled"; public static final String PATH = "path"; public static final String PAYLOAD = "payload"; + public static final String PAYLOAD_URL = "payloadurl"; public static final String POD_ID = "podid"; public static final String POD_NAME = "podname"; public static final String POD_IDS = "podids"; @@ -365,10 +390,13 @@ public class ApiConstants { public static final String PUBLIC_START_PORT = "publicport"; public static final String PUBLIC_END_PORT = "publicendport"; public static final String PUBLIC_ZONE = "publiczone"; + public static final String PURGE_RESOURCES = "purgeresources"; public static final String RECEIVED_BYTES = "receivedbytes"; public static final String RECONNECT = "reconnect"; public static final String RECOVER = "recover"; + public static final String REPAIR = "repair"; public static final String REQUIRES_HVM = "requireshvm"; + public static final String RESOURCE_COUNT = "resourcecount"; public static final String RESOURCE_NAME = "resourcename"; public static final String RESOURCE_TYPE = "resourcetype"; public static final String RESOURCE_TYPE_NAME = "resourcetypename"; @@ -381,11 +409,9 @@ public class ApiConstants { public static final String QUERY_FILTER = "queryfilter"; public static final String SCHEDULE = "schedule"; public static final String SCOPE = "scope"; - public static final String SECRET_KEY = "usersecretkey"; - public static final String SECONDARY_IP = "secondaryip"; - public static final String SINCE = "since"; - public static final String KEY = "key"; public static final String SEARCH_BASE = "searchbase"; + public static final String SECONDARY_IP = "secondaryip"; + public static final String SECRET_KEY = "secretkey"; public static final String SECURITY_GROUP_IDS = "securitygroupids"; public static final String SECURITY_GROUP_NAMES = "securitygroupnames"; public static final String SECURITY_GROUP_NAME = "securitygroupname"; @@ -399,17 +425,19 @@ public class ApiConstants { public static final String SHOW_CAPACITIES = "showcapacities"; public static final String SHOW_REMOVED = "showremoved"; public static final String SHOW_RESOURCE_ICON = "showicon"; + public static final String SHOW_INACTIVE = "showinactive"; public static final String SHOW_UNIQUE = "showunique"; public static final String SIGNATURE = "signature"; public static final String SIGNATURE_VERSION = "signatureversion"; + public static final String SINCE = "since"; public static final String SIZE = "size"; public static final String SNAPSHOT = "snapshot"; public static final String SNAPSHOT_ID = "snapshotid"; public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid"; public static final String SNAPSHOT_TYPE = "snapshottype"; public static final String SNAPSHOT_QUIESCEVM = "quiescevm"; - public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot"; public static final String SOURCE_ZONE_ID = "sourcezoneid"; + public static final String SSL_VERIFICATION = "sslverification"; public static final String START_DATE = "startdate"; public static final String START_ID = "startid"; public static final String START_IP = "startip"; @@ -422,20 +450,27 @@ public class ApiConstants { public static final String STORAGE_POLICY = "storagepolicy"; public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled"; public static final String STORAGE_CAPABILITIES = "storagecapabilities"; + public static final String STORAGE_CUSTOM_STATS = "storagecustomstats"; public static final String SUBNET = "subnet"; public static final String OWNER = "owner"; public static final String SWAP_OWNER = "swapowner"; public static final String SYSTEM_VM_TYPE = "systemvmtype"; public static final String TAGS = "tags"; public static final String STORAGE_TAGS = "storagetags"; + public static final String SUCCESS = "success"; + public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine"; + public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot"; public static final String TARGET_IQN = "targetiqn"; public static final String TEMPLATE_FILTER = "templatefilter"; public static final String TEMPLATE_ID = "templateid"; public static final String TEMPLATE_IDS = "templateids"; public static final String TEMPLATE_NAME = "templatename"; + public static final String TEMPLATE_TYPE = "templatetype"; + public static final String TEMPLATE_FORMAT = "templateformat"; public static final String TIMEOUT = "timeout"; public static final String TIMEZONE = "timezone"; public static final String TIMEZONEOFFSET = "timezoneoffset"; + public static final String TOTAL = "total"; public static final String TOTAL_SUBNETS = "totalsubnets"; public static final String TYPE = "type"; public static final String TRUST_STORE = "truststore"; @@ -458,6 +493,7 @@ public class ApiConstants { public static final String USERNAME = "username"; public static final String USER_CONFIGURABLE = "userconfigurable"; public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist"; + public static final String USER_SECRET_KEY = "usersecretkey"; public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork"; public static final String UPDATE_IN_SEQUENCE = "updateinsequence"; public static final String VALUE = "value"; @@ -489,9 +525,13 @@ public class ApiConstants { public static final String IS_VOLATILE = "isvolatile"; public static final String VOLUME_ID = "volumeid"; public static final String VOLUMES = "volumes"; + public static final String VOLUME_CHECK_RESULT = "volumecheckresult"; + public static final String VOLUME_REPAIR_RESULT = "volumerepairresult"; + public static final String ZONE = "zone"; public static final String ZONE_ID = "zoneid"; public static final String ZONE_NAME = "zonename"; + public static final String ZONE_WISE = "zonewise"; public static final String NETWORK_TYPE = "networktype"; public static final String PAGE = "page"; public static final String PAGE_SIZE = "pagesize"; @@ -533,6 +573,8 @@ public class ApiConstants { public static final String ALLOCATION_STATE = "allocationstate"; public static final String MANAGED_STATE = "managedstate"; public static final String MANAGEMENT_SERVER_ID = "managementserverid"; + public static final String MANAGEMENT_SERVER_NAME = "managementservername"; + public static final String STORAGE = "storage"; public static final String STORAGE_ID = "storageid"; public static final String PING_STORAGE_SERVER_IP = "pingstorageserverip"; public static final String PING_DIR = "pingdir"; @@ -551,6 +593,7 @@ public class ApiConstants { public static final String AGGREGATE_NAME = "aggregatename"; public static final String POOL_NAME = "poolname"; public static final String VOLUME_NAME = "volumename"; + public static final String VOLUME_STATE = "volumestate"; public static final String SNAPSHOT_POLICY = "snapshotpolicy"; public static final String SNAPSHOT_RESERVATION = "snapshotreservation"; public static final String IP_NETWORK_LIST = "iptonetworklist"; @@ -589,6 +632,8 @@ public class ApiConstants { public static final String SERVICE_CAPABILITY_LIST = "servicecapabilitylist"; public static final String CAN_CHOOSE_SERVICE_CAPABILITY = "canchooseservicecapability"; public static final String PROVIDER = "provider"; + public static final String OAUTH_PROVIDER = "oauthprovider"; + public static final String OAUTH_SECRET_KEY = "secretkey"; public static final String MANAGED = "managed"; public static final String CAPACITY_BYTES = "capacitybytes"; public static final String CAPACITY_IOPS = "capacityiops"; @@ -658,6 +703,7 @@ public class ApiConstants { public static final String SPECIFY_IP_RANGES = "specifyipranges"; public static final String IS_SOURCE_NAT = "issourcenat"; public static final String IS_STATIC_NAT = "isstaticnat"; + public static final String ITERATIONS = "iterations"; public static final String SORT_BY = "sortby"; public static final String CHANGE_CIDR = "changecidr"; public static final String PURPOSE = "purpose"; @@ -679,6 +725,12 @@ public class ApiConstants { public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC = "publicvswitchtype"; public static final String VSWITCH_NAME_GUEST_TRAFFIC = "guestvswitchname"; public static final String VSWITCH_NAME_PUBLIC_TRAFFIC = "publicvswitchname"; + + // NSX + public static final String EDGE_CLUSTER = "edgecluster"; + public static final String TIER0_GATEWAY = "tier0gateway"; + + public static final String TRANSPORT_ZONE = "transportzone"; // Tungsten-Fabric public static final String TUNGSTEN_VIRTUAL_ROUTER_UUID = "tungstenvirtualrouteruuid"; public static final String TUNGSTEN_PROVIDER_HOSTNAME = "tungstenproviderhostname"; @@ -702,6 +754,7 @@ public class ApiConstants { public static final String POLICY_UUID = "policyuuid"; public static final String RULE_UUID = "ruleuuid"; public static final String DIRECTION = "direction"; + public static final String TAGGED_RESOURCES = "taggedresources"; public static final String TAG_UUID = "taguuid"; public static final String TAG_TYPE = "tagtype"; public static final String TAG_VALUE = "tagvalue"; @@ -768,6 +821,7 @@ public class ApiConstants { public static final String VSM_CONFIG_STATE = "vsmconfigstate"; public static final String VSM_DEVICE_STATE = "vsmdevicestate"; public static final String VCENTER = "vcenter"; + public static final String EXISTING_VCENTER_ID = "existingvcenterid"; public static final String ADD_VSM_FLAG = "addvsmflag"; public static final String END_POINT = "endpoint"; public static final String REGION_ID = "regionid"; @@ -786,6 +840,8 @@ public class ApiConstants { public static final String IPSEC_PSK = "ipsecpsk"; public static final String GUEST_IP = "guestip"; public static final String REMOVED = "removed"; + public static final String REMOVER_ACCOUNT_ID = "removeraccountid"; + public static final String REMOVAL_REASON = "removalreason"; public static final String COMPLETED = "completed"; public static final String IKE_VERSION = "ikeversion"; public static final String IKE_POLICY = "ikepolicy"; @@ -796,6 +852,9 @@ public class ApiConstants { public static final String FORCE_ENCAP = "forceencap"; public static final String SPLIT_CONNECTIONS = "splitconnections"; public static final String FOR_VPC = "forvpc"; + public static final String FOR_NSX = "fornsx"; + public static final String NSX_SUPPORT_LB = "nsxsupportlb"; + public static final String NSX_SUPPORTS_INTERNAL_LB = "nsxsupportsinternallb"; public static final String FOR_TUNGSTEN = "fortungsten"; public static final String SHRINK_OK = "shrinkok"; public static final String NICIRA_NVP_DEVICE_ID = "nvpdeviceid"; @@ -805,6 +864,11 @@ public class ApiConstants { public static final String NICIRA_NVP_L2_GATEWAYSERVICE_UUID = "l2gatewayserviceuuid"; public static final String NSX_LOGICAL_SWITCH = "nsxlogicalswitch"; public static final String NSX_LOGICAL_SWITCH_PORT = "nsxlogicalswitchport"; + public static final String NSX_PROVIDER_UUID = "nsxprovideruuid"; + public static final String NSX_PROVIDER_HOSTNAME = "nsxproviderhostname"; + + public static final String NSX_PROVIDER_PORT = "nsxproviderport"; + public static final String NSX_CONTROLLER_ID = "nsxcontrollerid"; public static final String S3_ACCESS_KEY = "accesskey"; public static final String S3_SECRET_KEY = "secretkey"; public static final String S3_END_POINT = "endpoint"; @@ -850,6 +914,7 @@ public class ApiConstants { public static final String AUTOSCALE_VMGROUP_NAME = "autoscalevmgroupname"; public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername"; public static final String BAREMETAL_RCT_URL = "baremetalrcturl"; + public static final String BATCH_SIZE = "batchsize"; public static final String UCS_DN = "ucsdn"; public static final String GSLB_PROVIDER = "gslbprovider"; public static final String EXCLUSIVE_GSLB_PROVIDER = "isexclusivegslbprovider"; @@ -929,6 +994,7 @@ public class ApiConstants { public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc"; public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet"; public static final String SUPPORTS_PUBLIC_ACCESS = "supportspublicaccess"; + public static final String SUPPORTS_INTERNAL_LB = "supportsinternallb"; public static final String SUPPORTS_VM_AUTOSCALING = "supportsvmautoscaling"; public static final String REGION_LEVEL_VPC = "regionlevelvpc"; public static final String STRECHED_L2_SUBNET = "strechedl2subnet"; @@ -964,6 +1030,7 @@ public class ApiConstants { public static final String TARGET_ID = "targetid"; public static final String FILES = "files"; public static final String SRC_POOL = "srcpool"; + public static final String DEST_POOL = "destpool"; public static final String DEST_POOLS = "destpools"; public static final String VOLUME_IDS = "volumeids"; @@ -1008,7 +1075,6 @@ public class ApiConstants { public static final String DEPLOY_AS_IS = "deployasis"; public static final String DEPLOY_AS_IS_DETAILS = "deployasisdetails"; public static final String CROSS_ZONES = "crossZones"; - public static final String TEMPLATETYPE = "templatetype"; public static final String SOURCETEMPLATEID = "sourcetemplateid"; public static final String DYNAMIC_SCALING_ENABLED = "dynamicscalingenabled"; public static final String IOTHREADS_ENABLED = "iothreadsenabled"; @@ -1037,10 +1103,43 @@ public class ApiConstants { public static final String MTU = "mtu"; public static final String AUTO_ENABLE_KVM_HOST = "autoenablekvmhost"; public static final String LIST_APIS = "listApis"; + public static final String OBJECT_STORAGE_ID = "objectstorageid"; + public static final String VERSIONING = "versioning"; + public static final String OBJECT_LOCKING = "objectlocking"; + public static final String ENCRYPTION = "encryption"; + public static final String QUOTA = "quota"; + public static final String ACCESS_KEY = "accesskey"; public static final String SOURCE_NAT_IP = "sourcenatipaddress"; public static final String SOURCE_NAT_IP_ID = "sourcenatipaddressid"; public static final String HAS_RULES = "hasrules"; + public static final String NSX_DETAIL_KEY = "forNsx"; + public static final String DISK_PATH = "diskpath"; + public static final String IMPORT_SOURCE = "importsource"; + public static final String TEMP_PATH = "temppath"; + public static final String OBJECT_STORAGE = "objectstore"; + public static final String HEURISTIC_RULE = "heuristicrule"; + public static final String HEURISTIC_TYPE_VALID_OPTIONS = "Valid options are: ISO, SNAPSHOT, TEMPLATE and VOLUME."; + public static final String MANAGEMENT = "management"; + public static final String IS_VNF = "isvnf"; + public static final String VNF_NICS = "vnfnics"; + public static final String VNF_DETAILS = "vnfdetails"; + public static final String CLEAN_UP_VNF_DETAILS = "cleanupvnfdetails"; + public static final String CLEAN_UP_VNF_NICS = "cleanupvnfnics"; + public static final String VNF_CONFIGURE_MANAGEMENT = "vnfconfiguremanagement"; + public static final String VNF_CIDR_LIST = "vnfcidrlist"; + + public static final String CLIENT_ID = "clientid"; + public static final String REDIRECT_URI = "redirecturi"; + + public static final String IS_TAG_A_RULE = "istagarule"; + + public static final String PARAMETER_DESCRIPTION_IS_TAG_A_RULE = "Whether the informed tag is a JS interpretable rule or not."; + + public static final String WEBHOOK_ID = "webhookid"; + public static final String WEBHOOK_NAME = "webhookname"; + + public static final String NFS_MOUNT_OPTIONS = "nfsmountopts"; /** * This enum specifies IO Drivers, each option controls specific policies on I/O. @@ -1064,6 +1163,14 @@ public class ApiConstants { } } + public static final String PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + + "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + + "added, it will be interpreted as \"00:00:00\"). If the recommended format is not used, the date will be considered in the server timezone."; + + public static final String PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + + "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + + "added, it will be interpreted as \"23:59:59\"). If the recommended format is not used, the date will be considered in the server timezone."; + public enum BootType { UEFI, BIOS; @@ -1087,7 +1194,7 @@ public class ApiConstants { } public enum VMDetails { - all, group, nics, stats, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp; + all, group, nics, stats, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp, vnfnics; } public enum DomainDetails { diff --git a/api/src/main/java/org/apache/cloudstack/api/BaseAsyncCmd.java b/api/src/main/java/org/apache/cloudstack/api/BaseAsyncCmd.java index 865ec745640..6859b0a7f40 100644 --- a/api/src/main/java/org/apache/cloudstack/api/BaseAsyncCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/BaseAsyncCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api; -import org.apache.log4j.Logger; /** * queryAsyncJobResult API command. @@ -30,7 +29,6 @@ public abstract class BaseAsyncCmd extends BaseCmd { public static final String migrationSyncObject = "migration"; public static final String snapshotHostSyncObject = "snapshothost"; public static final String gslbSyncObject = "globalserverloadbalancer"; - private static final Logger s_logger = Logger.getLogger(BaseAsyncCmd.class.getName()); private Object job; diff --git a/api/src/main/java/org/apache/cloudstack/api/BaseCmd.java b/api/src/main/java/org/apache/cloudstack/api/BaseCmd.java index 79e103a291d..b206cd011c1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/BaseCmd.java @@ -38,14 +38,16 @@ import org.apache.cloudstack.affinity.AffinityGroupService; import org.apache.cloudstack.alert.AlertService; import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.network.element.InternalLoadBalancerElementService; import org.apache.cloudstack.network.lb.ApplicationLoadBalancerService; import org.apache.cloudstack.network.lb.InternalLoadBalancerVMService; import org.apache.cloudstack.query.QueryService; +import org.apache.cloudstack.storage.object.BucketApiService; import org.apache.cloudstack.storage.ImageStoreService; +import org.apache.cloudstack.storage.template.VnfTemplateManager; import org.apache.cloudstack.usage.UsageService; import org.apache.commons.collections.MapUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import com.cloud.configuration.ConfigurationService; import com.cloud.exception.ConcurrentOperationException; @@ -93,7 +95,7 @@ import com.cloud.vm.UserVmService; import com.cloud.vm.snapshot.VMSnapshotService; public abstract class BaseCmd { - private static final Logger s_logger = Logger.getLogger(BaseCmd.class.getName()); + protected transient Logger logger = LogManager.getLogger(getClass()); public static final String RESPONSE_SUFFIX = "response"; public static final String RESPONSE_TYPE_XML = HttpUtils.RESPONSE_TYPE_XML; public static final String RESPONSE_TYPE_JSON = HttpUtils.RESPONSE_TYPE_JSON; @@ -198,8 +200,6 @@ public abstract class BaseCmd { @Inject public AffinityGroupService _affinityGroupService; @Inject - public InternalLoadBalancerElementService _internalLbElementSvc; - @Inject public InternalLoadBalancerVMService _internalLbSvc; @Inject public NetworkModel _ntwkModel; @@ -213,6 +213,11 @@ public abstract class BaseCmd { public ResourceIconManager resourceIconManager; @Inject public Ipv6Service ipv6Service; + @Inject + public VnfTemplateManager vnfTemplateManager; + @Inject + public BucketApiService _bucketService; + public abstract void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException; @@ -367,7 +372,7 @@ public abstract class BaseCmd { if (roleIsAllowed) { validFields.add(field); } else { - s_logger.debug("Ignoring parameter " + parameterAnnotation.name() + " as the caller is not authorized to pass it in"); + logger.debug("Ignoring parameter " + parameterAnnotation.name() + " as the caller is not authorized to pass it in"); } } @@ -412,7 +417,7 @@ public abstract class BaseCmd { if(!isDisplay) break; } catch (Exception e){ - s_logger.trace("Caught exception while checking first class entities for display property, continuing on", e); + logger.trace("Caught exception while checking first class entities for display property, continuing on", e); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/BaseListTemplateOrIsoPermissionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/BaseListTemplateOrIsoPermissionsCmd.java index 052d7d1e8b7..be95547a8a7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/BaseListTemplateOrIsoPermissionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/BaseListTemplateOrIsoPermissionsCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.command.ResponseViewProvider; @@ -28,7 +27,6 @@ import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; public abstract class BaseListTemplateOrIsoPermissionsCmd extends BaseCmd implements ResponseViewProvider { - public Logger logger = getLogger(); protected static final String s_name = "listtemplatepermissionsresponse"; ///////////////////////////////////////////////////// @@ -59,9 +57,6 @@ public abstract class BaseListTemplateOrIsoPermissionsCmd extends BaseCmd implem return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked } - protected Logger getLogger() { - return Logger.getLogger(BaseListTemplateOrIsoPermissionsCmd.class); - } @Override public String getCommandName() { diff --git a/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java index 08f390f1972..e3aead6881b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.response.GuestOSResponse; import org.apache.cloudstack.api.response.TemplateResponse; @@ -24,7 +23,6 @@ import java.util.Collection; import java.util.Map; public abstract class BaseUpdateTemplateOrIsoCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(BaseUpdateTemplateOrIsoCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoPermissionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoPermissionsCmd.java index 410ffefb00d..e6ee0897db0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoPermissionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoPermissionsCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.SuccessResponse; @@ -27,16 +26,12 @@ import org.apache.cloudstack.api.response.TemplateResponse; import com.cloud.exception.InvalidParameterValueException; public abstract class BaseUpdateTemplateOrIsoPermissionsCmd extends BaseCmd { - public Logger _logger = getLogger(); protected String _name = getResponseName(); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// // /////////////////////////////////////////////////// - protected Logger getLogger() { - return Logger.getLogger(BaseUpdateTemplateOrIsoPermissionsCmd.class); - } protected String getResponseName() { return "updatetemplateorisopermissionsresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/InternalIdentity.java b/api/src/main/java/org/apache/cloudstack/api/InternalIdentity.java index 4149dd1c846..ce214e05b4f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/InternalIdentity.java +++ b/api/src/main/java/org/apache/cloudstack/api/InternalIdentity.java @@ -25,4 +25,18 @@ import java.io.Serializable; public interface InternalIdentity extends Serializable { long getId(); + + /* + Helper method to add conditions in joins where some column name is equal to a string value + */ + default Object setString(String str) { + return null; + } + + /* + Helper method to add conditions in joins where some column name is equal to a long value + */ + default Object setLong(Long l) { + return null; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java index 88b3571385a..ef759aaf9c3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/main/java/org/apache/cloudstack/api/ResponseGenerator.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.cloudstack.storage.object.Bucket; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ApiConstants.HostDetails; @@ -37,6 +38,7 @@ import org.apache.cloudstack.api.response.AutoScaleVmProfileResponse; import org.apache.cloudstack.api.response.BackupOfferingResponse; import org.apache.cloudstack.api.response.BackupResponse; import org.apache.cloudstack.api.response.BackupScheduleResponse; +import org.apache.cloudstack.api.response.BucketResponse; import org.apache.cloudstack.api.response.CapacityResponse; import org.apache.cloudstack.api.response.ClusterResponse; import org.apache.cloudstack.api.response.ConditionResponse; @@ -64,6 +66,7 @@ import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse; import org.apache.cloudstack.api.response.HypervisorGuestOsNamesResponse; import org.apache.cloudstack.api.response.IPAddressResponse; +import org.apache.cloudstack.api.response.IpQuarantineResponse; import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.InternalLoadBalancerElementResponse; @@ -81,6 +84,7 @@ import org.apache.cloudstack.api.response.NetworkPermissionsResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.NicResponse; import org.apache.cloudstack.api.response.NicSecondaryIpResponse; +import org.apache.cloudstack.api.response.ObjectStoreResponse; import org.apache.cloudstack.api.response.OvsProviderResponse; import org.apache.cloudstack.api.response.PhysicalNetworkResponse; import org.apache.cloudstack.api.response.PodResponse; @@ -100,6 +104,7 @@ import org.apache.cloudstack.api.response.ResourceTagResponse; import org.apache.cloudstack.api.response.RollingMaintenanceResponse; import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse; import org.apache.cloudstack.api.response.SSHKeyPairResponse; +import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.ServiceResponse; @@ -118,6 +123,7 @@ import org.apache.cloudstack.api.response.TemplatePermissionsResponse; import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.TrafficMonitorResponse; import org.apache.cloudstack.api.response.TrafficTypeResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; import org.apache.cloudstack.api.response.UpgradeRouterTemplateResponse; import org.apache.cloudstack.api.response.UsageRecordResponse; import org.apache.cloudstack.api.response.UserDataResponse; @@ -144,6 +150,8 @@ import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; import org.apache.cloudstack.region.PortableIp; import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.secstorage.heuristics.Heuristic; +import org.apache.cloudstack.storage.object.ObjectStore; import org.apache.cloudstack.usage.Usage; import com.cloud.capacity.Capacity; @@ -169,6 +177,7 @@ import com.cloud.network.OvsProvider; import com.cloud.network.PhysicalNetwork; import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PhysicalNetworkTrafficType; +import com.cloud.network.PublicIpQuarantine; import com.cloud.network.RemoteAccessVpn; import com.cloud.network.RouterHealthCheckResult; import com.cloud.network.Site2SiteCustomerGateway; @@ -229,6 +238,7 @@ import com.cloud.vm.Nic; import com.cloud.vm.NicSecondaryIp; import com.cloud.vm.VirtualMachine; import com.cloud.vm.snapshot.VMSnapshot; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; public interface ResponseGenerator { UserResponse createUserResponse(UserAccount user); @@ -438,7 +448,7 @@ public interface ResponseGenerator { * @param result * @return */ - PrivateGatewayResponse createPrivateGatewayResponse(PrivateGateway result); + PrivateGatewayResponse createPrivateGatewayResponse(ResponseView view, PrivateGateway result); /** * @param result @@ -529,4 +539,14 @@ public interface ResponseGenerator { DirectDownloadCertificateHostStatusResponse createDirectDownloadCertificateProvisionResponse(Long certificateId, Long hostId, Pair result); FirewallResponse createIpv6FirewallRuleResponse(FirewallRule acl); + + UnmanagedInstanceResponse createUnmanagedInstanceResponse(UnmanagedInstanceTO instance, Cluster cluster, Host host); + + SecondaryStorageHeuristicsResponse createSecondaryStorageSelectorResponse(Heuristic heuristic); + + IpQuarantineResponse createQuarantinedIpsResponse(PublicIpQuarantine publicIp); + + ObjectStoreResponse createObjectStoreResponse(ObjectStore os); + + BucketResponse createBucketResponse(Bucket bucket); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java index 945bb956c3e..6dbc6acc59a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java @@ -21,7 +21,6 @@ import java.util.Map; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -43,7 +42,6 @@ import com.cloud.user.UserAccount; @APICommand(name = "createAccount", description = "Creates an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = true, responseHasSensitiveInfo = true) public class CreateAccountCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateAccountCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java index 9a0ea4e9ec0..36e22acff91 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java @@ -31,7 +31,6 @@ import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.region.RegionService; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.user.Account; @@ -39,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteAccount", description = "Deletes a account, and all users associated with this account", responseObject = SuccessResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAccountCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteAccountCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java index 91b0673e186..55293eca619 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.account; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -43,7 +42,6 @@ import com.cloud.user.Account; @APICommand(name = "disableAccount", description = "Disables an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DisableAccountCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DisableAccountCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java index cc37dc23713..da96383f134 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.account; import javax.inject.Inject; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -39,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "enableAccount", description = "Enables an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class EnableAccountCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(EnableAccountCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java index a430914a25a..d7847373e92 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.account; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.utils.exception.CloudRuntimeException; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class LockAccountCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(LockAccountCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java index 36d299bcfc8..91cbb90e4da 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java @@ -23,7 +23,6 @@ import javax.inject.Inject; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.response.RoleResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -43,7 +42,6 @@ import com.cloud.user.Account; @APICommand(name = "updateAccount", description = "Updates account information for the authenticated user", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateAccountCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateAccountCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/CreateRoleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/CreateRoleCmd.java index 8a469df1f1f..e67a3e2c0a0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/CreateRoleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/CreateRoleCmd.java @@ -48,8 +48,7 @@ public class CreateRoleCmd extends RoleCmd { description = "ID of the role to be cloned from. Either roleid or type must be passed in") private Long roleId; - @Parameter(name = ApiConstants.IS_PUBLIC, type = CommandType.BOOLEAN, description = "Indicates whether the role will be visible to all users (public) or only to root admins (private)." + - " If this parameter is not specified during the creation of the role its value will be defaulted to true (public).") + @Parameter(name = ApiConstants.IS_PUBLIC, type = CommandType.BOOLEAN, description = "Indicates whether the role will be visible to all users (public) or only to root admins (private). Default is true.") private boolean publicRole = true; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/CreateProjectRoleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/CreateProjectRoleCmd.java index c03e6112ea7..ed17a876b24 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/CreateProjectRoleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/CreateProjectRoleCmd.java @@ -20,6 +20,7 @@ package org.apache.cloudstack.api.command.admin.acl.project; import org.apache.cloudstack.acl.ProjectRole; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -70,4 +71,13 @@ public class CreateProjectRoleCmd extends ProjectRoleCmd { return Account.ACCOUNT_ID_SYSTEM; } + @Override + public Long getApiResourceId() { + return getProjectId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Project; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/CreateProjectRolePermissionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/CreateProjectRolePermissionCmd.java index 9b6c2e633fc..d39c2312aa9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/CreateProjectRolePermissionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/CreateProjectRolePermissionCmd.java @@ -22,6 +22,7 @@ import org.apache.cloudstack.acl.ProjectRolePermission; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.Parameter; @@ -96,4 +97,14 @@ public class CreateProjectRolePermissionCmd extends BaseRolePermissionCmd { response.setObjectName("projectrolepermission"); setResponseObject(response); } + + @Override + public Long getApiResourceId() { + return getProjectId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Project; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/DeleteProjectRoleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/DeleteProjectRoleCmd.java index 4bb460c63f7..9f8d8248958 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/DeleteProjectRoleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/DeleteProjectRoleCmd.java @@ -21,6 +21,7 @@ import org.apache.cloudstack.acl.ProjectRole; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -79,4 +80,14 @@ public class DeleteProjectRoleCmd extends BaseCmd { public long getEntityOwnerId() { return CallContext.current().getCallingAccountId(); } + + @Override + public Long getApiResourceId() { + return getProjectId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Project; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/DeleteProjectRolePermissionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/DeleteProjectRolePermissionCmd.java index 8b83253c869..ac68278535e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/DeleteProjectRolePermissionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/DeleteProjectRolePermissionCmd.java @@ -21,6 +21,7 @@ import org.apache.cloudstack.acl.ProjectRolePermission; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -80,4 +81,14 @@ public class DeleteProjectRolePermissionCmd extends BaseCmd { public long getEntityOwnerId() { return CallContext.current().getCallingAccountId(); } + + @Override + public Long getApiResourceId() { + return getProjectId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Project; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/UpdateProjectRoleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/UpdateProjectRoleCmd.java index 202daa3d49c..3bc8b3d6186 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/UpdateProjectRoleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/UpdateProjectRoleCmd.java @@ -21,6 +21,7 @@ import org.apache.cloudstack.acl.ProjectRole; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -76,4 +77,14 @@ public class UpdateProjectRoleCmd extends ProjectRoleCmd { public long getEntityOwnerId() { return 0; } + + @Override + public Long getApiResourceId() { + return getProjectId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Project; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/UpdateProjectRolePermissionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/UpdateProjectRolePermissionCmd.java index d27235e5aae..dd59310c66a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/UpdateProjectRolePermissionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/acl/project/UpdateProjectRolePermissionCmd.java @@ -26,6 +26,7 @@ import org.apache.cloudstack.acl.ProjectRolePermission; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -154,4 +155,14 @@ public class UpdateProjectRolePermissionCmd extends BaseCmd { public long getEntityOwnerId() { return CallContext.current().getCallingAccountId(); } + + @Override + public Long getApiResourceId() { + return getProjectId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Project; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/address/AcquirePodIpCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/address/AcquirePodIpCmdByAdmin.java index a965624a2a9..7397697bd2c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/address/AcquirePodIpCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/address/AcquirePodIpCmdByAdmin.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.address; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.exception.ResourceUnavailableException; @APICommand(name = "acquirePodIpAddress", description = "Allocates IP addresses in respective Pod of a Zone", responseObject = AcquirePodIpCmdResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AcquirePodIpCmdByAdmin extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AcquirePodIpCmdByAdmin.class.getName()); private static final String s_name = "acquirepodipaddress"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java index 56f41b5f58e..672691ffbd8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.address; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ResponseObject.ResponseView; @@ -27,5 +26,4 @@ import org.apache.cloudstack.api.response.IPAddressResponse; @APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account.", responseObject = IPAddressResponse.class, responseView = ResponseView.Full, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AssociateIPAddrCmdByAdmin extends AssociateIPAddrCmd implements AdminCmd { - public static final Logger s_logger = Logger.getLogger(AssociateIPAddrCmdByAdmin.class.getName()); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/address/ReleasePodIpCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/address/ReleasePodIpCmdByAdmin.java index b6bfbcaa1e2..7d4cab6a0ac 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/address/ReleasePodIpCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/address/ReleasePodIpCmdByAdmin.java @@ -16,7 +16,6 @@ //under the License. package org.apache.cloudstack.api.command.admin.address; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -31,7 +30,6 @@ import com.cloud.user.Account; @APICommand(name = "releasePodIpAddress", description = "Releases a Pod IP back to the Pod", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ReleasePodIpCmdByAdmin extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ReleasePodIpCmdByAdmin.class.getName()); private static final String s_name = "releasepodipresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/affinitygroup/UpdateVMAffinityGroupCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/affinitygroup/UpdateVMAffinityGroupCmdByAdmin.java index 7bf9b64481b..43e70838e18 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/affinitygroup/UpdateVMAffinityGroupCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/affinitygroup/UpdateVMAffinityGroupCmdByAdmin.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.affinitygroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ResponseObject.ResponseView; @@ -33,5 +32,4 @@ import com.cloud.vm.VirtualMachine; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateVMAffinityGroupCmdByAdmin extends UpdateVMAffinityGroupCmd implements AdminCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVMAffinityGroupCmdByAdmin.class.getName()); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/alert/GenerateAlertCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/alert/GenerateAlertCmd.java index 9446272df6e..30f3bbbec1b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/alert/GenerateAlertCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/alert/GenerateAlertCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.PodResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; @@ -35,7 +34,6 @@ import com.cloud.event.EventTypes; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class GenerateAlertCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(GenerateAlertCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/autoscale/CreateCounterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/autoscale/CreateCounterCmd.java index 617d1104eda..7fa66ffff1f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/autoscale/CreateCounterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/autoscale/CreateCounterCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.autoscale; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "createCounter", description = "Adds metric counter for VM auto scaling", responseObject = CounterResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateCounterCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateCounterCmd.class.getName()); private static final String s_name = "counterresponse"; // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/autoscale/DeleteCounterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/autoscale/DeleteCounterCmd.java index e1f7859a56b..b7b2ce5cb70 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/autoscale/DeleteCounterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/autoscale/DeleteCounterCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.autoscale; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -36,7 +35,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteCounter", description = "Deletes a counter for VM auto scaling", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteCounterCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteCounterCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// @@ -55,7 +53,7 @@ public class DeleteCounterCmd extends BaseAsyncCmd { try { result = _autoScaleService.deleteCounter(getId()); } catch (ResourceInUseException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_IN_USE_ERROR, ex.getMessage()); } @@ -63,7 +61,7 @@ public class DeleteCounterCmd extends BaseAsyncCmd { SuccessResponse response = new SuccessResponse(getCommandName()); this.setResponseObject(response); } else { - s_logger.warn("Failed to delete counter with Id: " + getId()); + logger.warn("Failed to delete counter with Id: " + getId()); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete counter."); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/UpdateBackupOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/UpdateBackupOfferingCmd.java index 1cd6f4a8328..9de06715ee7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/UpdateBackupOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/UpdateBackupOfferingCmd.java @@ -30,7 +30,6 @@ import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.backup.BackupOffering; import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.Account; @@ -39,7 +38,6 @@ import com.cloud.utils.exception.CloudRuntimeException; @APICommand(name = "updateBackupOffering", description = "Updates a backup offering.", responseObject = BackupOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.16.0") public class UpdateBackupOfferingCmd extends BaseCmd { - private static final Logger LOGGER = Logger.getLogger(UpdateBackupOfferingCmd.class.getName()); @Inject private BackupManager backupManager; @@ -100,7 +98,7 @@ public class UpdateBackupOfferingCmd extends BaseCmd { this.setResponseObject(response); } catch (CloudRuntimeException e) { ApiErrorCode paramError = e instanceof InvalidParameterValueException ? ApiErrorCode.PARAM_ERROR : ApiErrorCode.INTERNAL_ERROR; - LOGGER.error(String.format("Failed to update Backup Offering [id: %s] due to: [%s].", id, e.getMessage()), e); + logger.error(String.format("Failed to update Backup Offering [id: %s] due to: [%s].", id, e.getMessage()), e); throw new ServerApiException(paramError, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/ca/IssueCertificateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/ca/IssueCertificateCmd.java index 4c543fdb6a8..463af000f58 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/ca/IssueCertificateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/ca/IssueCertificateCmd.java @@ -37,7 +37,6 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.ca.Certificate; import org.apache.cloudstack.utils.security.CertUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; @@ -49,7 +48,6 @@ import com.cloud.event.EventTypes; since = "4.11.0", authorized = {RoleType.Admin}) public class IssueCertificateCmd extends BaseAsyncCmd { - private static final Logger LOG = Logger.getLogger(IssueCertificateCmd.class); @Inject @@ -132,7 +130,7 @@ public class IssueCertificateCmd extends BaseAsyncCmd { certificateResponse.setCaCertificate(CertUtils.x509CertificatesToPem(certificate.getCaCertificates())); } } catch (final IOException e) { - LOG.error("Failed to generate and convert client certificate(s) to PEM due to error: ", e); + logger.error("Failed to generate and convert client certificate(s) to PEM due to error: ", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to process and return client certificate"); } certificateResponse.setResponseName(getCommandName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java index df48b2511b6..184a443d9db 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.List; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -42,7 +41,6 @@ import com.cloud.user.Account; @APICommand(name = "addCluster", description = "Adds a new cluster", responseObject = ClusterResponse.class, requestHasSensitiveInfo = true, responseHasSensitiveInfo = false) public class AddClusterCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddClusterCmd.class.getName()); @Parameter(name = ApiConstants.CLUSTER_NAME, type = CommandType.STRING, required = true, description = "the cluster name") @@ -226,10 +224,10 @@ public class AddClusterCmd extends BaseCmd { this.setResponseObject(response); } catch (DiscoveryException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (ResourceInUseException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); ServerApiException e = new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); for (String proxyObj : ex.getIdProxyList()) { e.addProxyObject(proxyObj); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/DeleteClusterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/DeleteClusterCmd.java index 497cef4c3ec..2b1cfe8bcb5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/DeleteClusterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/DeleteClusterCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.cluster; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -33,7 +32,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteCluster", description = "Deletes a cluster.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteClusterCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteClusterCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ExecuteClusterDrsPlanCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ExecuteClusterDrsPlanCmd.java new file mode 100644 index 00000000000..60f2c2b1dee --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ExecuteClusterDrsPlanCmd.java @@ -0,0 +1,147 @@ +/* + * 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.cluster; + +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.host.Host; +import com.cloud.user.Account; +import com.cloud.utils.UuidUtils; +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ClusterDrsPlanResponse; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.cluster.ClusterDrsService; +import org.apache.commons.collections.MapUtils; + +import javax.inject.Inject; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +@APICommand(name = "executeClusterDrsPlan", + description = "Execute DRS for a cluster. If there is another plan in progress for the same cluster, " + + "this command will fail.", + responseObject = ClusterDrsPlanResponse.class, since = "4.19.0", requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false) +public class ExecuteClusterDrsPlanCmd extends BaseAsyncCmd { + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ClusterResponse.class, required = true, + description = "ID of cluster") + private Long id; + + @Parameter( + name = ApiConstants.MIGRATE_TO, + type = CommandType.MAP, + description = "Virtual Machine to destination host mapping. This parameter specifies the mapping between " + + "a vm and a host to migrate that VM. clusterid is required if this parameter is set." + + "Format of this parameter: migrateto[vm-index].vm=&migrateto[vm-index].host= " + + "Where, [vm-index] indicates the index to identify the vm that you want to migrate, " + + "vm= indicates the UUID of the vm that you want to migrate, and " + + "host= indicates the UUID of the host where you want to migrate the vm. " + + "Example: migrateto[0].vm=<71f43cd6-69b0-4d3b-9fbc-67f50963d60b>" + + "&migrateto[0].host=" + + "&migrateto[1].vm=<88de0173-55c0-4c1c-a269-83d0279eeedf>" + + "&migrateto[1].host=<95d6e97c-6766-4d67-9a30-c449c15011d1>" + + "&migrateto[2].vm=<1b331390-59f2-4796-9993-bf11c6e76225>" + + "&migrateto[2].host=<41fdb564-9d3b-447d-88ed-7628f7640cbc>") + private Map migrateVmTo; + + @Inject + private ClusterDrsService clusterDrsService; + + public Map getVmToHostMap() { + Map vmToHostMap = new HashMap<>(); + if (MapUtils.isNotEmpty(migrateVmTo)) { + Collection allValues = migrateVmTo.values(); + Iterator iter = allValues.iterator(); + while (iter.hasNext()) { + HashMap vmToHost = (HashMap) iter.next(); + + String vmId = vmToHost.get("vm"); + String hostId = vmToHost.get("host"); + + VirtualMachine vm; + Host host; + if (UuidUtils.isUuid(vmId)) { + vm = _entityMgr.findByUuid(VirtualMachine.class, vmId); + } else { + vm = _entityMgr.findById(VirtualMachine.class, Long.parseLong(vmId)); + } + + if (UuidUtils.isUuid(hostId)) { + host = _entityMgr.findByUuid(Host.class, hostId); + } else { + host = _entityMgr.findById(Host.class, Long.parseLong(hostId)); + } + + if (vm == null || host == null) { + throw new InvalidParameterValueException( + String.format("Unable to find the vm/host for vmId=%s, destHostId=%s", vmId, hostId)); + } + + vmToHostMap.put(vm, host); + } + } + return vmToHostMap; + } + + @Override + public void execute() { + ClusterDrsPlanResponse response = clusterDrsService.executeDrsPlan(this); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public Long getApiResourceId() { + return getId(); + } + + public Long getId() { + return id; + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Cluster; + } + + + @Override + public String getEventType() { + return EventTypes.EVENT_CLUSTER_DRS; + } + + @Override + public String getEventDescription() { + return String.format("Executing DRS plan for cluster: %d", getId()); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/GenerateClusterDrsPlanCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/GenerateClusterDrsPlanCmd.java new file mode 100644 index 00000000000..69a6c113405 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/GenerateClusterDrsPlanCmd.java @@ -0,0 +1,85 @@ +/* + * 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.cluster; + +import com.cloud.user.Account; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ClusterDrsPlanResponse; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.cluster.ClusterDrsService; + +import javax.inject.Inject; + +import static org.apache.cloudstack.cluster.ClusterDrsService.ClusterDrsMaxMigrations; + +@APICommand(name = "generateClusterDrsPlan", description = "Generate DRS plan for a cluster", + responseObject = ClusterDrsPlanResponse.class, since = "4.19.0", requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false) +public class GenerateClusterDrsPlanCmd extends BaseCmd { + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ClusterResponse.class, required = true, + description = "the ID of the Cluster") + private Long id; + + @Parameter(name = ApiConstants.MIGRATIONS, type = CommandType.INTEGER, + description = "Maximum number of VMs to migrate for a DRS execution. Defaults to value of cluster's drs.vm.migrations setting") + private Integer migrations; + + @Inject + private ClusterDrsService clusterDrsService; + + public Integer getMaxMigrations() { + if (migrations == null) { + return ClusterDrsMaxMigrations.valueIn(getId()); + } + return migrations; + } + + public Long getId() { + return id; + } + + @Override + public void execute() { + final ClusterDrsPlanResponse response = clusterDrsService.generateDrsPlan(this); + response.setResponseName(getCommandName()); + response.setObjectName(getCommandName()); + this.setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public Long getApiResourceId() { + return getId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Cluster; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClusterDrsPlanCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClusterDrsPlanCmd.java new file mode 100644 index 00000000000..d34805ae2e3 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClusterDrsPlanCmd.java @@ -0,0 +1,62 @@ +/* + * 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.cluster; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ClusterDrsPlanResponse; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.cluster.ClusterDrsService; + +import javax.inject.Inject; + +@APICommand(name = "listClusterDrsPlan", description = "List DRS plans for a clusters", + responseObject = ClusterDrsPlanResponse.class, since = "4.19.0", requestHasSensitiveInfo = false) +public class ListClusterDrsPlanCmd extends BaseListCmd { + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ClusterDrsPlanResponse.class, + description = "ID of the drs plan") + private Long id; + + @Parameter(name = ApiConstants.CLUSTER_ID, type = CommandType.UUID, entityType = ClusterResponse.class, + description = "ID of the cluster") + private Long clusterId; + + @Inject + private ClusterDrsService clusterDrsService; + + public Long getId() { + return id; + } + + public Long getClusterId() { + return clusterId; + } + + @Override + public void execute() { + ListResponse response = clusterDrsService.listDrsPlan(this); + response.setResponseName(getCommandName()); + response.setObjectName(getCommandName()); + setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java index d83330c664a..67d0678410c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.cluster; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listClusters", description = "Lists clusters.", responseObject = ClusterResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListClustersCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListClustersCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java index dd527fb409a..77bb97fd39d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.cluster; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "updateCluster", description = "Updates an existing cluster", responseObject = ClusterResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateClusterCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddClusterCmd.class.getName()); @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ClusterResponse.class, required = true, description = "the ID of the Cluster") diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgGroupsByCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgGroupsByCmd.java index 46ab10cb2bc..d735218169d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgGroupsByCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgGroupsByCmd.java @@ -27,14 +27,12 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ConfigurationGroupResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.config.ConfigurationGroup; -import org.apache.log4j.Logger; import com.cloud.utils.Pair; @APICommand(name = ListCfgGroupsByCmd.APINAME, description = "Lists all configuration groups (primarily used for UI).", responseObject = ConfigurationGroupResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.18.0") public class ListCfgGroupsByCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListCfgGroupsByCmd.class.getName()); public static final String APINAME = "listConfigurationGroups"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java index 80abe5d3e8f..e365d8bc2dc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java @@ -23,7 +23,6 @@ import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -47,7 +46,6 @@ import com.cloud.utils.exception.CloudRuntimeException; public class ListCfgsByCmd extends BaseListCmd { public static final String APINAME = "listConfigurations"; - public static final Logger s_logger = Logger.getLogger(ListCfgsByCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListDeploymentPlannersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListDeploymentPlannersCmd.java index 4f5186a6df6..78fa31beeb4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListDeploymentPlannersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListDeploymentPlannersCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.config; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseListCmd; @@ -29,7 +28,6 @@ import org.apache.cloudstack.api.response.ListResponse; @APICommand(name = "listDeploymentPlanners", description = "Lists all DeploymentPlanners available.", responseObject = DeploymentPlannersResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListDeploymentPlannersCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListDeploymentPlannersCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListHypervisorCapabilitiesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListHypervisorCapabilitiesCmd.java index 64f1c19b70c..e7cc9e0234e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListHypervisorCapabilitiesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListHypervisorCapabilitiesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.config; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,7 +38,6 @@ import com.cloud.utils.Pair; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListHypervisorCapabilitiesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListHypervisorCapabilitiesCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java index ada389e0093..f114b263b63 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java @@ -25,7 +25,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.framework.config.ConfigKey; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.ClusterResponse; @@ -41,7 +40,6 @@ import com.cloud.utils.Pair; @APICommand(name = "resetConfiguration", description = "Resets a configuration. The configuration will be set to default value for global setting, and removed from account_details or domain_details for Account/Domain settings", responseObject = ConfigurationResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.16.0") public class ResetCfgCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ResetCfgCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java index abe7e31cfa2..dbf478df701 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java @@ -16,9 +16,9 @@ // under the License. package org.apache.cloudstack.api.command.admin.config; +import com.cloud.utils.crypt.DBEncryptionUtil; import org.apache.cloudstack.acl.RoleService; import org.apache.cloudstack.api.response.DomainResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +40,6 @@ import com.cloud.user.Account; @APICommand(name = "updateConfiguration", description = "Updates a configuration.", responseObject = ConfigurationResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateCfgCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateCfgCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -150,25 +149,50 @@ public class UpdateCfgCmd extends BaseCmd { if (cfg != null) { ConfigurationResponse response = _responseGenerator.createConfigurationResponse(cfg); response.setResponseName(getCommandName()); - if (getZoneId() != null) { - response.setScope("zone"); - } - if (getClusterId() != null) { - response.setScope("cluster"); - } - if (getStoragepoolId() != null) { - response.setScope("storagepool"); - } - if (getAccountId() != null) { - response.setScope("account"); - } - if (getDomainId() != null) { - response.setScope("domain"); - } - response.setValue(value); + response = setResponseScopes(response); + response = setResponseValue(response, cfg); this.setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update config"); } } + + /** + * 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) { + if (cfg.isEncrypted()) { + response.setValue(DBEncryptionUtil.encrypt(getValue())); + } else { + response.setValue(getValue()); + } + return response; + } + + /** + * Sets the scope for the Configuration response only if the field is not null. + * @param response to be updated + * @return the response updated with the scopes + */ + public ConfigurationResponse setResponseScopes(ConfigurationResponse response) { + if (getZoneId() != null) { + response.setScope("zone"); + } + if (getClusterId() != null) { + response.setScope("cluster"); + } + if (getStoragepoolId() != null) { + response.setScope("storagepool"); + } + if (getAccountId() != null) { + response.setScope("account"); + } + if (getDomainId() != null) { + response.setScope("domain"); + } + return response; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java index 02cdf1a0717..01f7af10841 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.config; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateHypervisorCapabilitiesCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateHypervisorCapabilitiesCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -45,6 +43,12 @@ public class UpdateHypervisorCapabilitiesCmd extends BaseCmd { @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = HypervisorCapabilitiesResponse.class, description = "ID of the hypervisor capability") private Long id; + @Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, description = "the hypervisor for which the hypervisor capabilities are to be updated", since = "4.19.1") + private String hypervisor; + + @Parameter(name = ApiConstants.HYPERVISOR_VERSION, type = CommandType.STRING, description = "the hypervisor version for which the hypervisor capabilities are to be updated", since = "4.19.1") + private String hypervisorVersion; + @Parameter(name = ApiConstants.SECURITY_GROUP_EANBLED, type = CommandType.BOOLEAN, description = "set true to enable security group for this hypervisor.") private Boolean securityGroupEnabled; @@ -75,6 +79,14 @@ public class UpdateHypervisorCapabilitiesCmd extends BaseCmd { return id; } + public String getHypervisor() { + return hypervisor; + } + + public String getHypervisorVersion() { + return hypervisorVersion; + } + public Long getMaxGuestsLimit() { return maxGuestsLimit; } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/diagnostics/RunDiagnosticsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/diagnostics/RunDiagnosticsCmd.java index 3d3c7410dc5..4537eb6f215 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/diagnostics/RunDiagnosticsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/diagnostics/RunDiagnosticsCmd.java @@ -38,7 +38,6 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.diagnostics.DiagnosticsService; import org.apache.cloudstack.diagnostics.DiagnosticsType; import org.apache.commons.collections.CollectionUtils; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InsufficientCapacityException; @@ -53,7 +52,6 @@ import com.cloud.vm.VirtualMachine; authorized = {RoleType.Admin}, since = "4.12.0.0") public class RunDiagnosticsCmd extends BaseAsyncCmd { - private static final Logger LOGGER = Logger.getLogger(RunDiagnosticsCmd.class); @Inject private DiagnosticsService diagnosticsService; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/ListTemplateDirectDownloadCertificatesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/ListTemplateDirectDownloadCertificatesCmd.java index 53b29a37f8f..145ff6ba782 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/ListTemplateDirectDownloadCertificatesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/ListTemplateDirectDownloadCertificatesCmd.java @@ -35,7 +35,6 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.direct.download.DirectDownloadCertificate; import org.apache.cloudstack.direct.download.DirectDownloadCertificateHostMap; import org.apache.cloudstack.direct.download.DirectDownloadManager; -import org.apache.log4j.Logger; import javax.inject.Inject; import java.util.ArrayList; @@ -63,7 +62,6 @@ public class ListTemplateDirectDownloadCertificatesCmd extends BaseListCmd { description = "if set to true: include the hosts where the certificate is uploaded to") private Boolean listHosts; - private static final Logger LOG = Logger.getLogger(ListTemplateDirectDownloadCertificatesCmd.class); public boolean isListHosts() { return listHosts != null && listHosts; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/RevokeTemplateDirectDownloadCertificateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/RevokeTemplateDirectDownloadCertificateCmd.java index e44ebd31274..eb9031cbc58 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/RevokeTemplateDirectDownloadCertificateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/RevokeTemplateDirectDownloadCertificateCmd.java @@ -41,7 +41,6 @@ import org.apache.cloudstack.direct.download.DirectDownloadManager; import org.apache.cloudstack.direct.download.DirectDownloadManager.HostCertificateStatus; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import javax.inject.Inject; import java.util.ArrayList; @@ -57,7 +56,6 @@ public class RevokeTemplateDirectDownloadCertificateCmd extends BaseCmd { @Inject DirectDownloadManager directDownloadManager; - private static final Logger LOG = Logger.getLogger(RevokeTemplateDirectDownloadCertificateCmd.class); @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = DirectDownloadCertificateResponse.class, diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/UploadTemplateDirectDownloadCertificateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/UploadTemplateDirectDownloadCertificateCmd.java index 0fa1797c7fe..c5c102be56d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/UploadTemplateDirectDownloadCertificateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/direct/download/UploadTemplateDirectDownloadCertificateCmd.java @@ -33,7 +33,6 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.direct.download.DirectDownloadCertificate; import org.apache.cloudstack.direct.download.DirectDownloadManager; import org.apache.cloudstack.direct.download.DirectDownloadManager.HostCertificateStatus; -import org.apache.log4j.Logger; import javax.inject.Inject; import java.util.ArrayList; @@ -49,7 +48,6 @@ public class UploadTemplateDirectDownloadCertificateCmd extends BaseCmd { @Inject DirectDownloadManager directDownloadManager; - private static final Logger LOG = Logger.getLogger(UploadTemplateDirectDownloadCertificateCmd.class); @Parameter(name = ApiConstants.CERTIFICATE, type = BaseCmd.CommandType.STRING, required = true, length = 65535, description = "SSL certificate") @@ -97,7 +95,7 @@ public class UploadTemplateDirectDownloadCertificateCmd extends BaseCmd { } try { - LOG.debug("Uploading certificate " + name + " to agents for Direct Download"); + logger.debug("Uploading certificate " + name + " to agents for Direct Download"); Pair> uploadStatus = directDownloadManager.uploadCertificateToHosts(certificate, name, hypervisor, zoneId, hostId); DirectDownloadCertificate certificate = uploadStatus.first(); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java index f6e09695f88..c7f06920bb8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/CreateDomainCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.domain; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = { RoleType.Admin, RoleType.DomainAdmin }) public class CreateDomainCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateDomainCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java index e0783b63098..db3bae25e39 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/DeleteDomainCmd.java @@ -30,7 +30,6 @@ import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.region.RegionService; -import org.apache.log4j.Logger; import com.cloud.domain.Domain; import com.cloud.event.EventTypes; @@ -40,7 +39,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = { RoleType.Admin, RoleType.DomainAdmin }) public class DeleteDomainCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteDomainCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainChildrenCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainChildrenCmd.java index 72614627f31..8514bb6dda5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainChildrenCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainChildrenCmd.java @@ -22,7 +22,6 @@ import java.util.List; import com.cloud.server.ResourceIcon; import com.cloud.server.ResourceTag; import org.apache.cloudstack.api.response.ResourceIconResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listDomainChildren", description = "Lists all children domains belonging to a specified domain", responseObject = DomainResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListDomainChildrenCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListDomainChildrenCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java index 8b6661f27ff..b91e56dcaef 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmd.java @@ -20,11 +20,6 @@ import java.util.ArrayList; import java.util.EnumSet; import java.util.List; -import com.cloud.server.ResourceIcon; -import com.cloud.server.ResourceTag; -import org.apache.cloudstack.api.response.ResourceIconResponse; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants.DomainDetails; @@ -34,14 +29,17 @@ import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.ResourceIconResponse; +import org.apache.commons.collections.CollectionUtils; import com.cloud.domain.Domain; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.server.ResourceIcon; +import com.cloud.server.ResourceTag; @APICommand(name = "listDomains", description = "Lists domains and provides detailed information for listed domains", responseObject = DomainResponse.class, responseView = ResponseView.Restricted, entityType = {Domain.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListDomainsCmd extends BaseListCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListDomainsCmd.class.getName()); private static final String s_name = "listdomainsresponse"; @@ -73,6 +71,9 @@ public class ListDomainsCmd extends BaseListCmd implements UserCmd { description = "flag to display the resource icon for domains") private Boolean showIcon; + @Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for resource type to return usage", since = "4.20.0") + private String tag; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -112,10 +113,14 @@ public class ListDomainsCmd extends BaseListCmd implements UserCmd { return dv; } - public Boolean getShowIcon() { + public boolean getShowIcon() { return showIcon != null ? showIcon : false; } + public String getTag() { + return tag; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -130,12 +135,17 @@ public class ListDomainsCmd extends BaseListCmd implements UserCmd { ListResponse response = _queryService.searchForDomains(this); response.setResponseName(getCommandName()); this.setResponseObject(response); - if (response != null && response.getCount() > 0 && getShowIcon()) { - updateDomainResponse(response.getResponses()); - } + updateDomainResponse(response.getResponses()); } - private void updateDomainResponse(List response) { + protected void updateDomainResponse(List response) { + if (CollectionUtils.isEmpty(response)) { + return; + } + _resourceLimitService.updateTaggedResourceLimitsAndCountsForDomains(response, getTag()); + if (!getShowIcon()) { + return; + } for (DomainResponse domainResponse : response) { ResourceIcon resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.Domain, domainResponse.getId()); if (resourceIcon == null) { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/MoveDomainCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/MoveDomainCmd.java new file mode 100644 index 00000000000..586345b2de7 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/MoveDomainCmd.java @@ -0,0 +1,73 @@ +// 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.domain; + +import com.cloud.domain.Domain; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.user.Account; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.DomainResponse; + +@APICommand(name = "moveDomain", description = "Moves a domain and its children to a new parent domain.", since = "4.19.0.0", responseObject = DomainResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin}) +public class MoveDomainCmd extends BaseCmd { + + private static final String APINAME = "moveDomain"; + @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "The ID of the domain to be moved.") + private Long domainId; + + @Parameter(name = ApiConstants.PARENT_DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, + description = "The ID of the new parent domain of the domain to be moved.") + private Long parentDomainId; + + public Long getDomainId() { + return domainId; + } + + public Long getParentDomainId() { + return parentDomainId; + } + + @Override + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() throws ResourceAllocationException { + Domain domain = _domainService.moveDomainAndChildrenToNewParentDomain(this); + + if (domain != null) { + DomainResponse response = _responseGenerator.createDomainResponse(domain); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to move the domain."); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/UpdateDomainCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/UpdateDomainCmd.java index db4030da772..353cb852bfd 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/UpdateDomainCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/domain/UpdateDomainCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.domain; import javax.inject.Inject; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "updateDomain", description = "Updates a domain with a new name", responseObject = DomainResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateDomainCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateDomainCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCmd.java index 0ad50071287..b854e8389c4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.guest; import org.apache.commons.collections.MapUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -43,7 +42,6 @@ import java.util.Map; @APICommand(name = "addGuestOs", description = "Add a new guest OS type", responseObject = GuestOSResponse.class, since = "4.4.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddGuestOsCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(AddGuestOsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsMappingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsMappingCmd.java index 0ddd21994e3..3fdfebb54bf 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsMappingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsMappingCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.guest; import org.apache.commons.lang3.BooleanUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -36,7 +35,6 @@ import com.cloud.user.Account; @APICommand(name = "addGuestOsMapping", description = "Adds a guest OS name to hypervisor OS name mapping", responseObject = GuestOsMappingResponse.class, since = "4.4.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddGuestOsMappingCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(AddGuestOsMappingCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/GetHypervisorGuestOsNamesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/GetHypervisorGuestOsNamesCmd.java index 79517708290..da920a2ec2d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/GetHypervisorGuestOsNamesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/GetHypervisorGuestOsNamesCmd.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.HypervisorGuestOsNamesResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.user.Account; @@ -35,8 +34,6 @@ import com.cloud.utils.Pair; @APICommand(name = GetHypervisorGuestOsNamesCmd.APINAME, description = "Gets the guest OS names in the hypervisor", responseObject = HypervisorGuestOsNamesResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.0", authorized = {RoleType.Admin}) public class GetHypervisorGuestOsNamesCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(GetHypervisorGuestOsNamesCmd.class.getName()); - public static final String APINAME = "getHypervisorGuestOsNames"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/ListGuestOsMappingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/ListGuestOsMappingCmd.java index 29ae0b4f188..23e62cdc781 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/ListGuestOsMappingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/ListGuestOsMappingCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.guest; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listGuestOsMapping", description = "Lists all available OS mappings for given hypervisor", responseObject = GuestOsMappingResponse.class, since = "4.4.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListGuestOsMappingCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListGuestOsMappingCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/RemoveGuestOsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/RemoveGuestOsCmd.java index 14beb83e073..d38682ce5bb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/RemoveGuestOsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/RemoveGuestOsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.guest; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -36,7 +35,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RemoveGuestOsCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RemoveGuestOsCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/RemoveGuestOsMappingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/RemoveGuestOsMappingCmd.java index 0a72b7e0451..a472ab672c5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/RemoveGuestOsMappingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/RemoveGuestOsMappingCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.guest; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -36,7 +35,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RemoveGuestOsMappingCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RemoveGuestOsMappingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java index 25f022b3b51..c98cd149ef3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.guest; import org.apache.commons.collections.MapUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -42,7 +41,6 @@ import java.util.Map; since = "4.4.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateGuestOsCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateGuestOsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsMappingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsMappingCmd.java index c83be131b4f..fc67ef0a7e7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsMappingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsMappingCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.guest; import org.apache.commons.lang3.BooleanUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "updateGuestOsMapping", description = "Updates the information about Guest OS to Hypervisor specific name mapping", responseObject = GuestOsMappingResponse.class, since = "4.4.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateGuestOsMappingCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateGuestOsMappingCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddHostCmd.java index 15955b9f0a8..ca27837aa88 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddHostCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddHostCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.host; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,6 @@ import com.cloud.user.Account; @APICommand(name = "addHost", description = "Adds a new host.", responseObject = HostResponse.class, requestHasSensitiveInfo = true, responseHasSensitiveInfo = false) public class AddHostCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddHostCmd.class.getName()); ///////////////////////////////////////////////////// @@ -150,7 +148,7 @@ public class AddHostCmd extends BaseCmd { this.setResponseObject(response); } catch (DiscoveryException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java index 225eb1dfecd..c965a39450b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/AddSecondaryStorageCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.host; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "addSecondaryStorage", description = "Adds secondary storage.", responseObject = ImageStoreResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddSecondaryStorageCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddSecondaryStorageCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -81,7 +79,7 @@ public class AddSecondaryStorageCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage"); } } catch (DiscoveryException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/CancelMaintenanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/CancelMaintenanceCmd.java index cca449f570b..a514a61b8a4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/CancelMaintenanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/CancelMaintenanceCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.host; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "cancelHostMaintenance", description = "Cancels host maintenance.", responseObject = HostResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CancelMaintenanceCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(CancelMaintenanceCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/DeleteHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/DeleteHostCmd.java index 609d189b0ca..38325c2f072 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/DeleteHostCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/DeleteHostCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.host; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,7 +31,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteHost", description = "Deletes a host.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteHostCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteHostCmd.class.getName()); // /////////////////////////////////////////////////// @@ -64,7 +62,7 @@ public class DeleteHostCmd extends BaseCmd { return (forced != null) ? forced : false; } - public boolean isForceDestoryLocalStorage() { + public boolean isForceDestroyLocalStorage() { return (forceDestroyLocalStorage != null) ? forceDestroyLocalStorage : true; } @@ -79,7 +77,7 @@ public class DeleteHostCmd extends BaseCmd { @Override public void execute() { - boolean result = _resourceService.deleteHost(getId(), isForced(), isForceDestoryLocalStorage()); + boolean result = _resourceService.deleteHost(getId(), isForced(), isForceDestroyLocalStorage()); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); this.setResponseObject(response); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java index 2b6ccb68eea..db30e4f4c02 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.utils.Ternary; @APICommand(name = "findHostsForMigration", description = "Find hosts suitable for migrating a virtual machine.", responseObject = HostForMigrationResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class FindHostsForMigrationCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(FindHostsForMigrationCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostTagsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostTagsCmd.java index ed4f9a09bc5..9ea2b2a7fbb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostTagsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostTagsCmd.java @@ -18,7 +18,6 @@ */ package org.apache.cloudstack.api.command.admin.host; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.BaseListCmd; @@ -27,7 +26,6 @@ import org.apache.cloudstack.api.response.HostTagResponse; @APICommand(name = "listHostTags", description = "Lists host tags", responseObject = HostTagResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListHostTagsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListHostTagsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java index 75fe339b710..af87bbf33bb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java @@ -21,7 +21,6 @@ import java.util.EnumSet; import java.util.List; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -45,7 +44,6 @@ import com.cloud.utils.Ternary; @APICommand(name = "listHosts", description = "Lists hosts.", responseObject = HostResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListHostsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListHostsCmd.class.getName()); ///////////////////////////////////////////////////// @@ -119,6 +117,10 @@ public class ListHostsCmd extends BaseListCmd { return id; } + public void setId(Long id) { + this.id = id; + } + public String getHostName() { return hostName; } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/PrepareForMaintenanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/PrepareForMaintenanceCmd.java index a89965e822e..2641c54364e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/PrepareForMaintenanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/PrepareForMaintenanceCmd.java @@ -25,7 +25,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.host.Host; @@ -35,7 +34,6 @@ import com.cloud.utils.exception.CloudRuntimeException; @APICommand(name = "prepareHostForMaintenance", description = "Prepares a host for maintenance.", responseObject = HostResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class PrepareForMaintenanceCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(PrepareForMaintenanceCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ReconnectHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ReconnectHostCmd.java index 7439d9da514..3550d61fdb9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ReconnectHostCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ReconnectHostCmd.java @@ -25,7 +25,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.AgentUnavailableException; @@ -36,7 +35,6 @@ import com.cloud.utils.exception.CloudRuntimeException; @APICommand(name = "reconnectHost", description = "Reconnects a host.", responseObject = HostResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ReconnectHostCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ReconnectHostCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ReleaseHostReservationCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ReleaseHostReservationCmd.java index 90c388bc7dc..7fee0684c78 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ReleaseHostReservationCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/ReleaseHostReservationCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.host; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "releaseHostReservation", description = "Releases host reservation.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ReleaseHostReservationCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ReleaseHostReservationCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java index e3ff130e2d4..88eeadb9b13 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostCmd.java @@ -27,14 +27,12 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.GuestOSCategoryResponse; import org.apache.cloudstack.api.response.HostResponse; -import org.apache.log4j.Logger; import java.util.List; @APICommand(name = "updateHost", description = "Updates a host.", responseObject = HostResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateHostCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateHostCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -60,6 +58,9 @@ public class UpdateHostCmd extends BaseCmd { @Parameter(name = ApiConstants.HOST_TAGS, type = CommandType.LIST, collectionType = CommandType.STRING, description = "list of tags to be added to the host") private List hostTags; + @Parameter(name = ApiConstants.IS_TAG_A_RULE, type = CommandType.BOOLEAN, description = ApiConstants.PARAMETER_DESCRIPTION_IS_TAG_A_RULE) + private Boolean isTagARule; + @Parameter(name = ApiConstants.URL, type = CommandType.STRING, description = "the new uri for the secondary storage: nfs://host/path") private String url; @@ -90,6 +91,10 @@ public class UpdateHostCmd extends BaseCmd { return hostTags; } + public Boolean getIsTagARule() { + return isTagARule; + } + public String getUrl() { return url; } @@ -120,7 +125,7 @@ public class UpdateHostCmd extends BaseCmd { hostResponse.setResponseName(getCommandName()); this.setResponseObject(hostResponse); } catch (Exception e) { - s_logger.debug("Failed to update host:" + getId(), e); + logger.debug("Failed to update host:" + getId(), e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update host:" + getId() + "," + e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostPasswordCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostPasswordCmd.java index 2e05ad14475..c94fe2c5865 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostPasswordCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/host/UpdateHostPasswordCmd.java @@ -24,14 +24,12 @@ import org.apache.cloudstack.api.response.ClusterResponse; import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.commons.lang3.BooleanUtils; -import org.apache.log4j.Logger; import com.cloud.user.Account; @APICommand(name = "updateHostPassword", description = "Update password of a host/pool on management server.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = true, responseHasSensitiveInfo = false) public class UpdateHostPasswordCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateHostPasswordCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ConfigureInternalLoadBalancerElementCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ConfigureInternalLoadBalancerElementCmd.java index 1c7e4a0ce21..c94d326ee62 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ConfigureInternalLoadBalancerElementCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ConfigureInternalLoadBalancerElementCmd.java @@ -17,12 +17,6 @@ package org.apache.cloudstack.api.command.admin.internallb; -import java.util.List; - -import javax.inject.Inject; - -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -47,10 +41,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ConfigureInternalLoadBalancerElementCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ConfigureInternalLoadBalancerElementCmd.class.getName()); - - @Inject - private List _service; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -100,7 +90,8 @@ public class ConfigureInternalLoadBalancerElementCmd extends BaseAsyncCmd { @Override public void execute() throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { CallContext.current().setEventDetails("Internal load balancer element: " + id); - VirtualRouterProvider result = _service.get(0).configureInternalLoadBalancerElement(getId(), getEnabled()); + InternalLoadBalancerElementService service = _networkService.getInternalLoadBalancerElementById(id); + VirtualRouterProvider result = service.configureInternalLoadBalancerElement(getId(), getEnabled()); if (result != null) { InternalLoadBalancerElementResponse routerResponse = _responseGenerator.createInternalLbElementResponse(result); routerResponse.setResponseName(getCommandName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/CreateInternalLoadBalancerElementCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/CreateInternalLoadBalancerElementCmd.java index f11f081031a..924287b673b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/CreateInternalLoadBalancerElementCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/CreateInternalLoadBalancerElementCmd.java @@ -16,12 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.internallb; -import java.util.List; - -import javax.inject.Inject; - -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -45,10 +39,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateInternalLoadBalancerElementCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateInternalLoadBalancerElementCmd.class.getName()); - - @Inject - private List _service; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -85,7 +75,8 @@ public class CreateInternalLoadBalancerElementCmd extends BaseAsyncCreateCmd { @Override public void execute() { CallContext.current().setEventDetails("Virtual router element Id: " + getEntityId()); - VirtualRouterProvider result = _service.get(0).getInternalLoadBalancerElement(getEntityId()); + InternalLoadBalancerElementService service = _networkService.getInternalLoadBalancerElementByNetworkServiceProviderId(getNspId()); + VirtualRouterProvider result = service.getInternalLoadBalancerElement(getEntityId()); if (result != null) { InternalLoadBalancerElementResponse response = _responseGenerator.createInternalLbElementResponse(result); response.setResponseName(getCommandName()); @@ -97,7 +88,8 @@ public class CreateInternalLoadBalancerElementCmd extends BaseAsyncCreateCmd { @Override public void create() throws ResourceAllocationException { - VirtualRouterProvider result = _service.get(0).addInternalLoadBalancerElement(getNspId()); + InternalLoadBalancerElementService service = _networkService.getInternalLoadBalancerElementByNetworkServiceProviderId(getNspId()); + VirtualRouterProvider result = service.addInternalLoadBalancerElement(getNspId()); if (result != null) { setEntityId(result.getId()); setEntityUuid(result.getUuid()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java index f5756909706..0eb00234382 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.internallb; import org.apache.commons.lang.BooleanUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -39,7 +38,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "listInternalLoadBalancerVMs", description = "List internal LB VMs.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListInternalLBVMsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListInternalLBVMsCmd.class.getName()); private static final String s_name = "listinternallbvmsresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java index 82d373e3119..b17cc22e746 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java @@ -17,12 +17,9 @@ package org.apache.cloudstack.api.command.admin.internallb; import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import javax.inject.Inject; - -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; @@ -46,10 +43,6 @@ import com.cloud.network.VirtualRouterProvider; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListInternalLoadBalancerElementsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListInternalLoadBalancerElementsCmd.class.getName()); - - @Inject - private InternalLoadBalancerElementService _service; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -88,12 +81,21 @@ public class ListInternalLoadBalancerElementsCmd extends BaseListCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { - List providers = _service.searchForInternalLoadBalancerElements(getId(), getNspId(), getEnabled()); + List services; + if (id == null && nspId == null) { + services = _networkService.getInternalLoadBalancerElements(); + } else { + InternalLoadBalancerElementService elementService = id != null ? _networkService.getInternalLoadBalancerElementById(id) : _networkService.getInternalLoadBalancerElementByNetworkServiceProviderId(nspId); + services = Collections.singletonList(elementService); + } ListResponse response = new ListResponse(); List providerResponses = new ArrayList(); - for (VirtualRouterProvider provider : providers) { - InternalLoadBalancerElementResponse providerResponse = _responseGenerator.createInternalLbElementResponse(provider); - providerResponses.add(providerResponse); + for (InternalLoadBalancerElementService service : services) { + List providers = service.searchForInternalLoadBalancerElements(getId(), getNspId(), getEnabled()); + for (VirtualRouterProvider provider : providers) { + InternalLoadBalancerElementResponse providerResponse = _responseGenerator.createInternalLbElementResponse(provider); + providerResponses.add(providerResponse); + } } response.setResponses(providerResponses); response.setResponseName(getCommandName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java index fdec7947853..3dd7d2adf37 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.internallb; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -42,7 +41,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "startInternalLoadBalancerVM", responseObject = DomainRouterResponse.class, description = "Starts an existing internal lb vm.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StartInternalLBVMCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(StartInternalLBVMCmd.class.getName()); private static final String s_name = "startinternallbvmresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java index 76ad4d438d2..a746e5d906d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.internallb; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -41,7 +40,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "stopInternalLoadBalancerVM", description = "Stops an Internal LB vm.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StopInternalLBVMCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(StopInternalLBVMCmd.class.getName()); private static final String s_name = "stopinternallbvmresponse"; // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/iso/ListIsosCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/iso/ListIsosCmdByAdmin.java index 4b6d4c0bd58..0719d2a7ce4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/iso/ListIsosCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/iso/ListIsosCmdByAdmin.java @@ -17,12 +17,33 @@ package org.apache.cloudstack.api.command.admin.iso; import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.command.admin.AdminCmd; import org.apache.cloudstack.api.command.user.iso.ListIsosCmd; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.TemplateResponse; @APICommand(name = "listIsos", description = "Lists all available ISO files.", responseObject = TemplateResponse.class, responseView = ResponseView.Full, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListIsosCmdByAdmin extends ListIsosCmd implements AdminCmd { + @Parameter(name = ApiConstants.IMAGE_STORE_ID, type = CommandType.UUID, entityType = ImageStoreResponse.class, + description = "ID of the image or image cache store", since = "4.19") + private Long imageStoreId; + + @Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, + description = "ID of the storage pool", since = "4.19") + private Long storagePoolId; + + @Override + public Long getImageStoreId() { + return imageStoreId; + } + + @Override + public Long getStoragePoolId() { + return storagePoolId; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/management/ListMgmtsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/management/ListMgmtsCmd.java index 3af772d332f..a68ed62857a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/management/ListMgmtsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/management/ListMgmtsCmd.java @@ -23,12 +23,10 @@ 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.ManagementServerResponse; -import org.apache.log4j.Logger; @APICommand(name = "listManagementServers", description = "Lists management servers.", responseObject = ManagementServerResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListMgmtsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListMgmtsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/AddNetworkDeviceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/AddNetworkDeviceCmd.java index be0cd9f2fa7..33477297043 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/AddNetworkDeviceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/AddNetworkDeviceCmd.java @@ -20,7 +20,6 @@ import java.util.Map; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -44,7 +43,6 @@ import com.cloud.utils.exception.CloudRuntimeException; responseObject = NetworkDeviceResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddNetworkDeviceCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddNetworkDeviceCmd.class); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/AddNetworkServiceProviderCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/AddNetworkServiceProviderCmd.java index 176375ce181..40a82239345 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/AddNetworkServiceProviderCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/AddNetworkServiceProviderCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.network; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -43,7 +42,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddNetworkServiceProviderCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(AddNetworkServiceProviderCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateGuestNetworkIpv6PrefixCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateGuestNetworkIpv6PrefixCmd.java index d7c7bec99f9..f6b035c5783 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateGuestNetworkIpv6PrefixCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateGuestNetworkIpv6PrefixCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.DataCenterGuestIpv6PrefixResponse; import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; import com.cloud.dc.DataCenterGuestIpv6Prefix; import com.cloud.event.EventTypes; @@ -45,7 +44,6 @@ import com.cloud.user.Account; responseHasSensitiveInfo = false, authorized = {RoleType.Admin}) public class CreateGuestNetworkIpv6PrefixCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(CreateGuestNetworkIpv6PrefixCmd.class); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateManagementNetworkIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateManagementNetworkIpRangeCmd.java index 2bab4f05352..85cfddfb714 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateManagementNetworkIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateManagementNetworkIpRangeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.ApiArgValidator; @@ -44,7 +43,6 @@ import com.cloud.user.Account; responseHasSensitiveInfo = false, authorized = {RoleType.Admin}) public class CreateManagementNetworkIpRangeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(CreateManagementNetworkIpRangeCmd.class); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java index 53b02718ea3..cd9770877ed 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.network; import org.apache.cloudstack.api.ApiArgValidator; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,7 +31,6 @@ import com.cloud.network.Network; @APICommand(name = "createNetwork", description = "Creates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Full, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateNetworkCmdByAdmin extends CreateNetworkCmd implements AdminCmd { - public static final Logger s_logger = Logger.getLogger(CreateNetworkCmdByAdmin.class.getName()); @Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, description="the ID or VID of the network") private String vlan; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java index 8bf6fce881c..9117bcfc193 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkOfferingCmd.java @@ -24,12 +24,15 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +import com.cloud.network.Network; +import com.cloud.network.VirtualRouterProvider; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -47,10 +50,19 @@ import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.Availability; import com.cloud.user.Account; +import static com.cloud.network.Network.Service.Dhcp; +import static com.cloud.network.Network.Service.Dns; +import static com.cloud.network.Network.Service.Lb; +import static com.cloud.network.Network.Service.StaticNat; +import static com.cloud.network.Network.Service.SourceNat; +import static com.cloud.network.Network.Service.PortForwarding; +import static com.cloud.network.Network.Service.NetworkACL; +import static com.cloud.network.Network.Service.UserData; +import static com.cloud.network.Network.Service.Firewall; + @APICommand(name = "createNetworkOffering", description = "Creates a network offering.", responseObject = NetworkOfferingResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateNetworkOfferingCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateNetworkOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -74,7 +86,8 @@ public class CreateNetworkOfferingCmd extends BaseCmd { @Parameter(name = ApiConstants.SPECIFY_VLAN, type = CommandType.BOOLEAN, description = "true if network offering supports vlans") private Boolean specifyVlan; - @Parameter(name = ApiConstants.AVAILABILITY, type = CommandType.STRING, description = "the availability of network offering. Default value is Optional") + @Parameter(name = ApiConstants.AVAILABILITY, type = CommandType.STRING, description = "the availability of network offering. The default value is Optional. " + + " Another value is Required, which will make it as the default network offering for new networks ") private String availability; @Parameter(name = ApiConstants.NETWORKRATE, type = CommandType.INTEGER, description = "data transfer rate in megabits per second allowed") @@ -127,6 +140,30 @@ public class CreateNetworkOfferingCmd extends BaseCmd { description = "true if network offering is meant to be used for VPC, false otherwise.") private Boolean forVpc; + @Parameter(name = ApiConstants.FOR_NSX, + type = CommandType.BOOLEAN, + description = "true if network offering is meant to be used for NSX, false otherwise.", + since = "4.20.0") + private Boolean forNsx; + + @Parameter(name = ApiConstants.NSX_MODE, + type = CommandType.STRING, + description = "Indicates the mode with which the network will operate. Valid option: NATTED or ROUTED", + since = "4.20.0") + private String nsxMode; + + @Parameter(name = ApiConstants.NSX_SUPPORT_LB, + type = CommandType.BOOLEAN, + description = "true if network offering for NSX network offering supports Load balancer service.", + since = "4.20.0") + private Boolean nsxSupportsLbService; + + @Parameter(name = ApiConstants.NSX_SUPPORTS_INTERNAL_LB, + type = CommandType.BOOLEAN, + description = "true if network offering for NSX network offering supports Internal Load balancer service.", + since = "4.20.0") + private Boolean nsxSupportsInternalLbService; + @Parameter(name = ApiConstants.FOR_TUNGSTEN, type = CommandType.BOOLEAN, description = "true if network offering is meant to be used for Tungsten-Fabric, false otherwise.") @@ -211,7 +248,27 @@ public class CreateNetworkOfferingCmd extends BaseCmd { } public List getSupportedServices() { - return supportedServices == null ? new ArrayList() : supportedServices; + if (!isForNsx()) { + return supportedServices == null ? new ArrayList() : supportedServices; + } else { + List services = new ArrayList<>(List.of( + Dhcp.getName(), + Dns.getName(), + StaticNat.getName(), + SourceNat.getName(), + PortForwarding.getName(), + UserData.getName() + )); + if (getNsxSupportsLbService()) { + services.add(Lb.getName()); + } + if (Boolean.TRUE.equals(forVpc)) { + services.add(NetworkACL.getName()); + } else { + services.add(Firewall.getName()); + } + return services; + } } public String getGuestIpType() { @@ -241,6 +298,22 @@ public class CreateNetworkOfferingCmd extends BaseCmd { return forVpc; } + public boolean isForNsx() { + return BooleanUtils.isTrue(forNsx); + } + + public String getNsxMode() { + return nsxMode; + } + + public boolean getNsxSupportsLbService() { + return BooleanUtils.isTrue(nsxSupportsLbService); + } + + public boolean getNsxSupportsInternalLbService() { + return BooleanUtils.isTrue(nsxSupportsInternalLbService); + } + public Boolean getForTungsten() { return forTungsten; } @@ -261,9 +334,8 @@ public class CreateNetworkOfferingCmd extends BaseCmd { } public Map> getServiceProviders() { - Map> serviceProviderMap = null; - if (serviceProviderList != null && !serviceProviderList.isEmpty()) { - serviceProviderMap = new HashMap>(); + Map> serviceProviderMap = new HashMap<>(); + if (serviceProviderList != null && !serviceProviderList.isEmpty() && !isForNsx()) { Collection servicesCollection = serviceProviderList.values(); Iterator iter = servicesCollection.iterator(); while (iter.hasNext()) { @@ -279,11 +351,37 @@ public class CreateNetworkOfferingCmd extends BaseCmd { providerList.add(provider); serviceProviderMap.put(service, providerList); } + } else if (Boolean.TRUE.equals(forNsx)) { + getServiceProviderMapForNsx(serviceProviderMap); } - return serviceProviderMap; } + private void getServiceProviderMapForNsx(Map> serviceProviderMap) { + String routerProvider = Boolean.TRUE.equals(getForVpc()) ? VirtualRouterProvider.Type.VPCVirtualRouter.name() : + VirtualRouterProvider.Type.VirtualRouter.name(); + List unsupportedServices = new ArrayList<>(List.of("Vpn", "SecurityGroup", "Connectivity", + "Gateway", "BaremetalPxeService")); + List routerSupported = List.of("Dhcp", "Dns", "UserData"); + List allServices = Service.listAllServices().stream().map(Service::getName).collect(Collectors.toList()); + if (routerProvider.equals(VirtualRouterProvider.Type.VPCVirtualRouter.name())) { + unsupportedServices.add("Firewall"); + } else { + unsupportedServices.add("NetworkACL"); + } + for (String service : allServices) { + if (unsupportedServices.contains(service)) + continue; + if (routerSupported.contains(service)) + serviceProviderMap.put(service, List.of(routerProvider)); + else + serviceProviderMap.put(service, List.of(Network.Provider.Nsx.getName())); + if (!getNsxSupportsLbService()) { + serviceProviderMap.remove(Lb.getName()); + } + } + } + public Map getServiceCapabilities(Service service) { Map capabilityMap = null; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreatePhysicalNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreatePhysicalNetworkCmd.java index 294ee047fe6..7eb52b92456 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreatePhysicalNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreatePhysicalNetworkCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.network; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -40,7 +39,6 @@ import com.cloud.user.Account; @APICommand(name = "createPhysicalNetwork", description = "Creates a physical network", responseObject = PhysicalNetworkResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreatePhysicalNetworkCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreatePhysicalNetworkCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateStorageNetworkIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateStorageNetworkIpRangeCmd.java index d2dc3d8688f..42262cc2bf1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateStorageNetworkIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateStorageNetworkIpRangeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -42,7 +41,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateStorageNetworkIpRangeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(CreateStorageNetworkIpRangeCmd.class); ///////////////////////////////////////////////////// @@ -119,7 +117,7 @@ public class CreateStorageNetworkIpRangeCmd extends BaseAsyncCmd { response.setResponseName(getCommandName()); this.setResponseObject(response); } catch (Exception e) { - s_logger.warn("Create storage network IP range failed", e); + logger.warn("Create storage network IP range failed", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DedicateGuestVlanRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DedicateGuestVlanRangeCmd.java index e6a289d096b..355f738679e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DedicateGuestVlanRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DedicateGuestVlanRangeCmd.java @@ -18,7 +18,6 @@ */ package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "dedicateGuestVlanRange", description = "Dedicates a guest vlan range to an account", responseObject = GuestVlanRangeResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DedicateGuestVlanRangeCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DedicateGuestVlanRangeCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteGuestNetworkIpv6PrefixCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteGuestNetworkIpv6PrefixCmd.java index 67d309456d6..e2ada4191a8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteGuestNetworkIpv6PrefixCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteGuestNetworkIpv6PrefixCmd.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.DataCenterGuestIpv6PrefixResponse; import org.apache.cloudstack.api.response.SuccessResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -45,7 +44,6 @@ import com.cloud.utils.exception.CloudRuntimeException; responseHasSensitiveInfo = false, authorized = {RoleType.Admin}) public class DeleteGuestNetworkIpv6PrefixCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteGuestNetworkIpv6PrefixCmd.class); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteManagementNetworkIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteManagementNetworkIpRangeCmd.java index abb72eb2724..41cf5e518b3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteManagementNetworkIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteManagementNetworkIpRangeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.ApiArgValidator; @@ -42,7 +41,6 @@ import com.cloud.user.Account; responseHasSensitiveInfo = false, authorized = {RoleType.Admin}) public class DeleteManagementNetworkIpRangeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteManagementNetworkIpRangeCmd.class); ///////////////////////////////////////////////////// @@ -112,13 +110,13 @@ public class DeleteManagementNetworkIpRangeCmd extends BaseAsyncCmd { SuccessResponse response = new SuccessResponse(getCommandName()); this.setResponseObject(response); } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (Exception e) { - s_logger.warn("Failed to delete management ip range from " + getStartIp() + " to " + getEndIp() + " of Pod: " + getPodId(), e); + logger.warn("Failed to delete management ip range from " + getStartIp() + " to " + getEndIp() + " of Pod: " + getPodId(), e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkDeviceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkDeviceCmd.java index d7e8744d6b7..89a36d0b94f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkDeviceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkDeviceCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.network; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,6 @@ import com.cloud.utils.exception.CloudRuntimeException; @APICommand(name = "deleteNetworkDevice", description = "Deletes network device.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteNetworkDeviceCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteNetworkDeviceCmd.class); @Inject ExternalNetworkDeviceManager nwDeviceMgr; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkOfferingCmd.java index 80ce48cc7d9..e0598b71ea1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkOfferingCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,7 +31,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteNetworkOffering", description = "Deletes a network offering.", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteNetworkOfferingCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteNetworkOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkServiceProviderCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkServiceProviderCmd.java index 1ccfff5d7ba..4b56612fdda 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkServiceProviderCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteNetworkServiceProviderCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -36,7 +35,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteNetworkServiceProvider", description = "Deletes a Network Service Provider.", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteNetworkServiceProviderCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteNetworkServiceProviderCmd.class.getName()); ///////////////////////////////////////////////////// @@ -78,10 +76,10 @@ public class DeleteNetworkServiceProviderCmd extends BaseAsyncCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete network service provider"); } } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeletePhysicalNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeletePhysicalNetworkCmd.java index 79f0685c6c6..3233130211c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeletePhysicalNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeletePhysicalNetworkCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "deletePhysicalNetwork", description = "Deletes a Physical Network.", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeletePhysicalNetworkCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeletePhysicalNetworkCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteStorageNetworkIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteStorageNetworkIpRangeCmd.java index b5de43dc5e2..454dfba92f2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteStorageNetworkIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/DeleteStorageNetworkIpRangeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteStorageNetworkIpRange", description = "Deletes a storage network IP Range.", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteStorageNetworkIpRangeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteStorageNetworkIpRangeCmd.class); ///////////////////////////////////////////////////// @@ -77,7 +75,7 @@ public class DeleteStorageNetworkIpRangeCmd extends BaseAsyncCmd { SuccessResponse response = new SuccessResponse(getCommandName()); this.setResponseObject(response); } catch (Exception e) { - s_logger.warn("Failed to delete storage network ip range " + getId(), e); + logger.warn("Failed to delete storage network ip range " + getId(), e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListDedicatedGuestVlanRangesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListDedicatedGuestVlanRangesCmd.java index 67324d81927..0247a306921 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListDedicatedGuestVlanRangesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListDedicatedGuestVlanRangesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.network; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,7 +38,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listDedicatedGuestVlanRanges", description = "Lists dedicated guest vlan ranges", responseObject = GuestVlanRangeResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListDedicatedGuestVlanRangesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListDedicatedGuestVlanRangesCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListGuestVlansCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListGuestVlansCmd.java index 1daeac9c53d..4b368f5e034 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListGuestVlansCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListGuestVlansCmd.java @@ -22,7 +22,6 @@ import java.util.List; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.response.PhysicalNetworkResponse; import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,7 +38,6 @@ import com.cloud.utils.Pair; since = "4.17.0", authorized = {RoleType.Admin}) public class ListGuestVlansCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListGuestVlansCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListNetworkDeviceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListNetworkDeviceCmd.java index 405c2654bdf..768bab64108 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListNetworkDeviceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListNetworkDeviceCmd.java @@ -22,7 +22,6 @@ import java.util.Map; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -45,7 +44,6 @@ import com.cloud.utils.exception.CloudRuntimeException; @APICommand(name = "listNetworkDevice", description = "List network devices", responseObject = NetworkDeviceResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNetworkDeviceCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListNetworkDeviceCmd.class); private static final String s_name = "listnetworkdevice"; @Inject diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListNetworkServiceProvidersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListNetworkServiceProvidersCmd.java index 67fc8292a93..68495a62215 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListNetworkServiceProvidersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListNetworkServiceProvidersCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.network; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,6 @@ import com.cloud.utils.Pair; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNetworkServiceProvidersCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListNetworkServiceProvidersCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListPhysicalNetworksCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListPhysicalNetworksCmd.java index b8f30d3f7a1..51a6ddabd9f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListPhysicalNetworksCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListPhysicalNetworksCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.network; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listPhysicalNetworks", description = "Lists physical networks", responseObject = PhysicalNetworkResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListPhysicalNetworksCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListPhysicalNetworksCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListStorageNetworkIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListStorageNetworkIpRangeCmd.java index c22ec8ee19b..556162ca360 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListStorageNetworkIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListStorageNetworkIpRangeCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.network; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -42,7 +41,6 @@ import com.cloud.user.Account; @APICommand(name = "listStorageNetworkIpRange", description = "List a storage network IP range.", responseObject = StorageNetworkIpRangeResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListStorageNetworkIpRangeCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListStorageNetworkIpRangeCmd.class); String _name = "liststoragenetworkiprangeresponse"; @@ -99,7 +97,7 @@ public class ListStorageNetworkIpRangeCmd extends BaseListCmd { response.setResponseName(getCommandName()); this.setResponseObject(response); } catch (Exception e) { - s_logger.warn("Failed to list storage network ip range for rangeId=" + getRangeId() + " podId=" + getPodId() + " zoneId=" + getZoneId()); + logger.warn("Failed to list storage network ip range for rangeId=" + getRangeId() + " podId=" + getPodId() + " zoneId=" + getZoneId()); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java index 361da2d0db4..120c6af41ad 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.network; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSupportedNetworkServicesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListSupportedNetworkServicesCmd.class.getName()); @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, description = "network service provider name") private String providerName; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/MigrateNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/MigrateNetworkCmd.java index b38e8f453b0..8ef853b99da 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/MigrateNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/MigrateNetworkCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -48,7 +47,6 @@ import com.cloud.user.User; since = "4.11.0", authorized = {RoleType.Admin}) public class MigrateNetworkCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(MigrateNetworkCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/MigrateVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/MigrateVPCCmd.java index cca367ce750..3e0801be40b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/MigrateVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/MigrateVPCCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.network; import java.util.HashMap; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker; @@ -50,7 +49,6 @@ import com.cloud.user.User; since = "4.11.0", authorized = {RoleType.Admin}) public class MigrateVPCCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(MigrateVPCCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ReleaseDedicatedGuestVlanRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ReleaseDedicatedGuestVlanRangeCmd.java index 916357920a1..b3125ec3668 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ReleaseDedicatedGuestVlanRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/ReleaseDedicatedGuestVlanRangeCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -36,7 +35,6 @@ import com.cloud.user.Account; @APICommand(name = "releaseDedicatedGuestVlanRange", description = "Releases a dedicated guest vlan range to the system", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ReleaseDedicatedGuestVlanRangeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ReleaseDedicatedGuestVlanRangeCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java index 57c34822759..75fb45e1f11 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.NetworkOfferingResponse; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.domain.Domain; @@ -39,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "updateNetworkOffering", description = "Updates a network offering.", responseObject = NetworkOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateNetworkOfferingCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateNetworkOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -55,7 +53,7 @@ public class UpdateNetworkOfferingCmd extends BaseCmd { private String displayText; @Parameter(name = ApiConstants.AVAILABILITY, type = CommandType.STRING, description = "the availability of network offering." - + " Default value is Required for Guest Virtual network offering; Optional for Guest Direct network offering") + + " The value is Required makes this network offering default for Guest Virtual Networks. Only one network offering can have the value Required ") private String availability; @Parameter(name = ApiConstants.SORT_KEY, type = CommandType.INTEGER, description = "sort key of the network offering, integer") diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkServiceProviderCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkServiceProviderCmd.java index 1bbf21b85ed..b4801d9368e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkServiceProviderCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkServiceProviderCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.network; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -40,7 +39,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateNetworkServiceProviderCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateNetworkServiceProviderCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java index 24fd93f49d1..162116470bd 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.network; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "updatePhysicalNetwork", description = "Updates a physical network", responseObject = PhysicalNetworkResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdatePhysicalNetworkCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdatePhysicalNetworkCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdatePodManagementNetworkIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdatePodManagementNetworkIpRangeCmd.java index 4e880f122d8..6f90a070f0d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdatePodManagementNetworkIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdatePodManagementNetworkIpRangeCmd.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.PodResponse; import org.apache.cloudstack.api.response.SuccessResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -42,7 +41,6 @@ import com.cloud.user.Account; authorized = {RoleType.Admin}) public class UpdatePodManagementNetworkIpRangeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdatePodManagementNetworkIpRangeCmd.class); ///////////////////////////////////////////////////// @@ -138,10 +136,10 @@ public class UpdatePodManagementNetworkIpRangeCmd extends BaseAsyncCmd { SuccessResponse response = new SuccessResponse(getCommandName()); this.setResponseObject(response); } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (Exception e) { - s_logger.warn("Failed to update pod management IP range " + getNewStartIP() + "-" + getNewEndIP() + " of Pod: " + getPodId(), e); + logger.warn("Failed to update pod management IP range " + getNewStartIP() + "-" + getNewEndIP() + " of Pod: " + getPodId(), e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateStorageNetworkIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateStorageNetworkIpRangeCmd.java index 459c89debc9..65e2437417d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateStorageNetworkIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateStorageNetworkIpRangeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -41,7 +40,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateStorageNetworkIpRangeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateStorageNetworkIpRangeCmd.class); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -107,7 +105,7 @@ public class UpdateStorageNetworkIpRangeCmd extends BaseAsyncCmd { response.setResponseName(getCommandName()); this.setResponseObject(response); } catch (Exception e) { - s_logger.warn("Update storage network IP range failed", e); + logger.warn("Update storage network IP range failed", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateDiskOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateDiskOfferingCmd.java index c2d8b3b6839..c46e4cd6b44 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateDiskOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateDiskOfferingCmd.java @@ -37,7 +37,6 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.offering.DiskOffering; import com.cloud.offering.ServiceOffering; @@ -47,7 +46,6 @@ import com.cloud.user.Account; @APICommand(name = "createDiskOffering", description = "Creates a disk offering.", responseObject = DiskOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateDiskOfferingCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateDiskOfferingCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java index d947f6f0659..8f6d5413d72 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java @@ -37,7 +37,6 @@ import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.collections.CollectionUtils; -import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; import com.cloud.offering.ServiceOffering; @@ -47,7 +46,6 @@ import com.cloud.user.Account; @APICommand(name = "createServiceOffering", description = "Creates a service offering.", responseObject = ServiceOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateServiceOfferingCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateServiceOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -56,7 +54,11 @@ public class CreateServiceOfferingCmd extends BaseCmd { @Parameter(name = ApiConstants.CPU_NUMBER, type = CommandType.INTEGER, required = false, description = "the CPU number of the service offering") private Integer cpuNumber; - @Parameter(name = ApiConstants.CPU_SPEED, type = CommandType.INTEGER, required = false, description = "the CPU speed of the service offering in MHz.") + @Parameter(name = ApiConstants.CPU_SPEED, type = CommandType.INTEGER, required = false, description = "For VMware and Xen based hypervisors this is the CPU speed of the service offering in MHz.\n" + + "For the KVM hypervisor," + + " the values of the parameters cpuSpeed and cpuNumber will be used to calculate the `shares` value. This value is used by the KVM hypervisor to calculate how much time" + + " the VM will have access to the host's CPU. The `shares` value does not have a unit, and its purpose is being a weight value for the host to compare between its guest" + + " VMs. For more information, see https://libvirt.org/formatdomain.html#cpu-tuning.") private Integer cpuSpeed; @Parameter(name = ApiConstants.DISPLAY_TEXT, type = CommandType.STRING, description = "The display text of the service offering, defaults to 'name'.") @@ -244,6 +246,12 @@ public class CreateServiceOfferingCmd extends BaseCmd { @Parameter(name = ApiConstants.ENCRYPT_ROOT, type = CommandType.BOOLEAN, description = "VMs using this offering require root volume encryption", since="4.18") private Boolean encryptRoot; + @Parameter(name = ApiConstants.PURGE_RESOURCES, type = CommandType.BOOLEAN, + description = "Whether to cleanup instance and its associated resource from database upon expunge of the instance", + since="4.20") + private Boolean purgeResources; + + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -271,7 +279,7 @@ public class CreateServiceOfferingCmd extends BaseCmd { public String getServiceOfferingName() { if (StringUtils.isEmpty(serviceOfferingName)) { - throw new InvalidParameterValueException("Failed to create service offering because offering name has not been spified."); + throw new InvalidParameterValueException("Failed to create service offering because offering name has not been specified."); } return serviceOfferingName; } @@ -479,6 +487,10 @@ public class CreateServiceOfferingCmd extends BaseCmd { return false; } + public boolean isPurgeResources() { + return Boolean.TRUE.equals(purgeResources); + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/DeleteDiskOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/DeleteDiskOfferingCmd.java index 0159cd297f9..591b09c60a5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/DeleteDiskOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/DeleteDiskOfferingCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.offering; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,7 +31,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteDiskOffering", description = "Updates a disk offering.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteDiskOfferingCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteDiskOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/DeleteServiceOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/DeleteServiceOfferingCmd.java index 9b7f9d48e30..19203289d10 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/DeleteServiceOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/DeleteServiceOfferingCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.offering; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,7 +31,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteServiceOffering", description = "Deletes a service offering.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteServiceOfferingCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteServiceOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateDiskOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateDiskOfferingCmd.java index 1d5898ea4a0..370453804cf 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateDiskOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateDiskOfferingCmd.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command.admin.offering; import java.util.ArrayList; import java.util.List; +import com.cloud.offering.DiskOffering.State; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; @@ -27,8 +28,8 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.DiskOfferingResponse; +import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.domain.Domain; @@ -39,7 +40,6 @@ import com.cloud.user.Account; @APICommand(name = "updateDiskOffering", description = "Updates a disk offering.", responseObject = DiskOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateDiskOfferingCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateDiskOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -123,6 +123,9 @@ public class UpdateDiskOfferingCmd extends BaseCmd { @Parameter(name = ApiConstants.CACHE_MODE, type = CommandType.STRING, description = "the cache mode to use for this disk offering", since = "4.15") private String cacheMode; + @Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "state of the disk offering") + private String diskOfferingState; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -262,6 +265,13 @@ public class UpdateDiskOfferingCmd extends BaseCmd { public Long getIopsWriteRateMaxLength() { return iopsWriteRateMaxLength; } + public State getState() { + State state = EnumUtils.getEnumIgnoreCase(State.class, diskOfferingState); + if (StringUtils.isNotBlank(diskOfferingState) && state == null) { + throw new InvalidParameterValueException("Invalid state value: " + diskOfferingState); + } + return state; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmd.java index d86564a60c6..e580f0d9f41 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmd.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command.admin.offering; import java.util.ArrayList; import java.util.List; +import com.cloud.offering.ServiceOffering.State; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; @@ -27,8 +28,8 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ServiceOfferingResponse; +import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.domain.Domain; @@ -39,7 +40,6 @@ import com.cloud.user.Account; @APICommand(name = "updateServiceOffering", description = "Updates a service offering.", responseObject = ServiceOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateServiceOfferingCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateServiceOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -84,6 +84,16 @@ public class UpdateServiceOfferingCmd extends BaseCmd { since = "4.16") private String hostTags; + @Parameter(name = ApiConstants.STATE, + type = CommandType.STRING, + description = "state of the service offering") + private String serviceOfferingState; + + @Parameter(name = ApiConstants.PURGE_RESOURCES, type = CommandType.BOOLEAN, + description = "Whether to cleanup VM and its associated resource upon expunge", + since="4.20") + private Boolean purgeResources; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -172,6 +182,18 @@ public class UpdateServiceOfferingCmd extends BaseCmd { return hostTags; } + public State getState() { + State state = EnumUtils.getEnumIgnoreCase(State.class, serviceOfferingState); + if (StringUtils.isNotBlank(serviceOfferingState) && state == null) { + throw new InvalidParameterValueException("Invalid state value: " + serviceOfferingState); + } + return state; + } + + public boolean isPurgeResources() { + return Boolean.TRUE.equals(purgeResources); + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/ChangeOutOfBandManagementPasswordCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/ChangeOutOfBandManagementPasswordCmd.java index dad6506729a..e2c31d6cf07 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/ChangeOutOfBandManagementPasswordCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/ChangeOutOfBandManagementPasswordCmd.java @@ -26,6 +26,7 @@ import com.cloud.host.Host; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -102,4 +103,14 @@ public class ChangeOutOfBandManagementPasswordCmd extends BaseAsyncCmd { public String getEventDescription() { return "change out-of-band management password for host: " + getHostId(); } + + @Override + public Long getApiResourceId() { + return getHostId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Host; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/ConfigureOutOfBandManagementCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/ConfigureOutOfBandManagementCmd.java index 699e2855185..157d3c627db 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/ConfigureOutOfBandManagementCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/ConfigureOutOfBandManagementCmd.java @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableMap; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -112,4 +113,14 @@ public class ConfigureOutOfBandManagementCmd extends BaseCmd { builder.put(option, value); } } + + @Override + public Long getApiResourceId() { + return getHostId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Host; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForClusterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForClusterCmd.java index 604aae66889..445e7b92665 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForClusterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForClusterCmd.java @@ -27,6 +27,7 @@ import com.cloud.org.Cluster; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -94,4 +95,14 @@ public class DisableOutOfBandManagementForClusterCmd extends BaseAsyncCmd { public String getEventDescription() { return "disable out-of-band management password for cluster: " + getClusterId(); } + + @Override + public Long getApiResourceId() { + return getClusterId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Cluster; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForHostCmd.java index 51c0fbcc3db..7e4444e93fb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForHostCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForHostCmd.java @@ -27,6 +27,7 @@ import com.cloud.host.Host; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -95,4 +96,14 @@ public class DisableOutOfBandManagementForHostCmd extends BaseAsyncCmd { public String getEventDescription() { return "disable out-of-band management password for host: " + getHostId(); } + + @Override + public Long getApiResourceId() { + return getHostId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Host; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForZoneCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForZoneCmd.java index 4c3e92cf05d..2028f8fc2a0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForZoneCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/DisableOutOfBandManagementForZoneCmd.java @@ -27,6 +27,7 @@ import com.cloud.exception.ResourceUnavailableException; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -94,4 +95,14 @@ public class DisableOutOfBandManagementForZoneCmd extends BaseAsyncCmd { public String getEventDescription() { return "disable out-of-band management password for zone: " + getZoneId(); } + + @Override + public Long getApiResourceId() { + return getZoneId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Zone; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForClusterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForClusterCmd.java index a69f27fb3ac..549743b3172 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForClusterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForClusterCmd.java @@ -27,6 +27,7 @@ import com.cloud.org.Cluster; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -94,4 +95,14 @@ public class EnableOutOfBandManagementForClusterCmd extends BaseAsyncCmd { public String getEventDescription() { return "enable out-of-band management password for cluster: " + getClusterId(); } + + @Override + public Long getApiResourceId() { + return getClusterId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Cluster; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForHostCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForHostCmd.java index 5e32c8943bf..834181a5e1c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForHostCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForHostCmd.java @@ -27,6 +27,7 @@ import com.cloud.host.Host; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -95,4 +96,14 @@ public class EnableOutOfBandManagementForHostCmd extends BaseAsyncCmd { public String getEventDescription() { return "enable out-of-band management password for host: " + getHostId(); } + + @Override + public Long getApiResourceId() { + return getHostId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Host; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForZoneCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForZoneCmd.java index 4eea4d50fe0..de4c4d801de 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForZoneCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/EnableOutOfBandManagementForZoneCmd.java @@ -27,6 +27,7 @@ import com.cloud.exception.ResourceUnavailableException; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiArgValidator; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -94,4 +95,14 @@ public class EnableOutOfBandManagementForZoneCmd extends BaseAsyncCmd { public String getEventDescription() { return "enable out-of-band management password for zone: " + getZoneId(); } + + @Override + public Long getApiResourceId() { + return getZoneId(); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Zone; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/IssueOutOfBandManagementPowerActionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/IssueOutOfBandManagementPowerActionCmd.java index d10664f0a25..97a813c9d47 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/IssueOutOfBandManagementPowerActionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/outofbandmanagement/IssueOutOfBandManagementPowerActionCmd.java @@ -114,4 +114,9 @@ public class IssueOutOfBandManagementPowerActionCmd extends BaseAsyncCmd { public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.Host; } + + @Override + public Long getApiResourceId() { + return getHostId(); + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/CreatePodCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/CreatePodCmd.java index b15854ca875..c1d9a6db429 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/CreatePodCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/CreatePodCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.pod; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "createPod", description = "Creates a new Pod.", responseObject = PodResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreatePodCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreatePodCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/DeletePodCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/DeletePodCmd.java index bdb9ef26694..c1de800d745 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/DeletePodCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/DeletePodCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.pod; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -33,7 +32,6 @@ import com.cloud.user.Account; @APICommand(name = "deletePod", description = "Deletes a Pod.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeletePodCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeletePodCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java index c0e26a32eee..5ad0b457ced 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.pod; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listPods", description = "Lists all Pods.", responseObject = PodResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListPodsByCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListPodsByCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/UpdatePodCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/UpdatePodCmd.java index 99ab5e1cee4..7dae6f4c7cf 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/UpdatePodCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/UpdatePodCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.pod; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -33,7 +32,6 @@ import com.cloud.user.Account; @APICommand(name = "updatePod", description = "Updates a Pod.", responseObject = PodResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdatePodCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdatePodCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/AddRegionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/AddRegionCmd.java index 61bf32ab822..3a93a275042 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/AddRegionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/AddRegionCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.region; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "addRegion", description = "Adds a Region", responseObject = RegionResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddRegionCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddRegionCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/CreatePortableIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/CreatePortableIpRangeCmd.java index 61deceb0691..fd103c83830 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/CreatePortableIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/CreatePortableIpRangeCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.region; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -43,7 +42,6 @@ import com.cloud.user.Account; responseHasSensitiveInfo = false) public class CreatePortableIpRangeCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreatePortableIpRangeCmd.class.getName()); ///////////////////////////////////////////////////// @@ -126,7 +124,7 @@ public class CreatePortableIpRangeCmd extends BaseAsyncCreateCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create portable public IP range"); } } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/DeletePortableIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/DeletePortableIpRangeCmd.java index 6cc884645e9..3ff46fcc94d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/DeletePortableIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/DeletePortableIpRangeCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.region; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "deletePortableIpRange", description = "deletes a range of portable public IP's associated with a region", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeletePortableIpRangeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeletePortableIpRangeCmd.class.getName()); private static final String s_name = "deleteportablepublicipresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/ListPortableIpRangesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/ListPortableIpRangesCmd.java index ed0ddd68aca..e654da6df44 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/ListPortableIpRangesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/ListPortableIpRangesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.region; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListPortableIpRangesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListPortableIpRangesCmd.class.getName()); private static final String s_name = "listportableipresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java index 180e34c7a8f..3ea323eebfb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/RemoveRegionCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.region; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "removeRegion", description = "Removes specified region", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RemoveRegionCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(RemoveRegionCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/UpdateRegionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/UpdateRegionCmd.java index c772efd5e1f..4267f6a2c28 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/region/UpdateRegionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/region/UpdateRegionCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.region; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "updateRegion", description = "Updates a region", responseObject = RegionResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateRegionCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateRegionCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ArchiveAlertsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ArchiveAlertsCmd.java index 003b823e106..dc8c15cf09d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ArchiveAlertsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ArchiveAlertsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.resource; import java.util.Date; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ArchiveAlertsCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ArchiveAlertsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/CleanVMReservationsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/CleanVMReservationsCmd.java index 9acc71ce693..1ae8c944123 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/CleanVMReservationsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/CleanVMReservationsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.resource; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiErrorCode; @@ -31,7 +30,6 @@ import com.cloud.user.Account; @APICommand(name = "cleanVMReservations", description = "Cleanups VM reservations in the database.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CleanVMReservationsCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(CleanVMReservationsCmd.class.getName()); private static final String s_name = "cleanvmreservationresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/DeleteAlertsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/DeleteAlertsCmd.java index eb384892758..9262a120f72 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/DeleteAlertsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/DeleteAlertsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.resource; import java.util.Date; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAlertsCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteAlertsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListAlertTypesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListAlertTypesCmd.java new file mode 100644 index 00000000000..e7bfbdbc625 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListAlertTypesCmd.java @@ -0,0 +1,54 @@ +// 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.resource; + +import com.cloud.user.Account; +import org.apache.cloudstack.alert.AlertService; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.response.AlertResponse; +import org.apache.cloudstack.api.response.AlertTypeResponse; +import org.apache.cloudstack.api.response.ListResponse; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +@APICommand(name = "listAlertTypes", description = "Lists all alerts types", responseObject = AlertResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class ListAlertTypesCmd extends BaseCmd { + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + Set result = AlertService.AlertType.getAlertTypes(); + ListResponse response = new ListResponse<>(); + List typeResponseList = new ArrayList<>(); + for (AlertService.AlertType alertType : result) { + AlertTypeResponse alertResponse = new AlertTypeResponse(alertType.getType(), alertType.getName()); + alertResponse.setObjectName("alerttype"); + typeResponseList.add(alertResponse); + } + response.setResponses(typeResponseList, result.size()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListAlertsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListAlertsCmd.java index 3471ab60837..64cf691e6a7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListAlertsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListAlertsCmd.java @@ -25,7 +25,6 @@ import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.AlertResponse; import org.apache.cloudstack.api.response.ListResponse; -import org.apache.log4j.Logger; import com.cloud.alert.Alert; import com.cloud.utils.Pair; @@ -34,7 +33,6 @@ import com.cloud.utils.Pair; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAlertsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListAlertsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmd.java index 253677616f0..6b31c4cc43c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmd.java @@ -21,7 +21,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,6 @@ import com.cloud.exception.InvalidParameterValueException; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListCapacityCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListCapacityCmd.class.getName()); private static final DecimalFormat s_percentFormat = new DecimalFormat("##.##"); @@ -73,6 +71,9 @@ public class ListCapacityCmd extends BaseListCmd { @Parameter(name = ApiConstants.SORT_BY, type = CommandType.STRING, since = "3.0.0", description = "Sort the results. Available values: Usage") private String sortBy; + @Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for the resource type", since = "4.20.0") + private String tag; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -109,6 +110,10 @@ public class ListCapacityCmd extends BaseListCmd { return null; } + public String getTag() { + return tag; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/PurgeExpungedResourcesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/PurgeExpungedResourcesCmd.java new file mode 100644 index 00000000000..b6833f09733 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/PurgeExpungedResourcesCmd.java @@ -0,0 +1,131 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.resource; + + +import java.util.Date; + +import javax.inject.Inject; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.PurgeExpungedResourcesResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.resource.ResourceCleanupService; + +import com.cloud.event.EventTypes; + +@APICommand(name = "purgeExpungedResources", + description = "Purge expunged resources", + responseObject = SuccessResponse.class, + responseView = ResponseObject.ResponseView.Full, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false, + authorized = {RoleType.Admin}, + since = "4.20") +public class PurgeExpungedResourcesCmd extends BaseAsyncCmd { + + @Inject + ResourceCleanupService resourceCleanupService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.RESOURCE_TYPE, type = BaseCmd.CommandType.STRING, + description = "The type of the resource which need to be purged. Supported types: " + + "VirtualMachine") + private String resourceType; + + @Parameter(name = ApiConstants.BATCH_SIZE, type = CommandType.LONG, + description = "The size of batch used during purging") + private Long batchSize; + + @Parameter(name = ApiConstants.START_DATE, + type = CommandType.DATE, + description = "The start date range of the expunged resources used for purging " + + "(use format \"yyyy-MM-dd\" or \"yyyy-MM-dd HH:mm:ss\")") + private Date startDate; + + @Parameter(name = ApiConstants.END_DATE, + type = CommandType.DATE, + description = "The end date range of the expunged resources used for purging " + + "(use format \"yyyy-MM-dd\" or \"yyyy-MM-dd HH:mm:ss\")") + private Date endDate; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public String getResourceType() { + return resourceType; + } + + public Long getBatchSize() { + return batchSize; + } + + public Date getStartDate() { + return startDate; + } + + public Date getEndDate() { + return endDate; + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccount().getId(); + } + + @Override + public String getEventType() { + return EventTypes.EVENT_PURGE_EXPUNGED_RESOURCES; + } + + @Override + public String getEventDescription() { + return "Purging expunged resources"; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() { + try { + long result = resourceCleanupService.purgeExpungedResources(this); + PurgeExpungedResourcesResponse response = new PurgeExpungedResourcesResponse(); + response.setResourceCount(result); + response.setObjectName(getCommandName().toLowerCase()); + setResponseObject(response); + } catch (Exception e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getLocalizedMessage()); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/StartRollingMaintenanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/StartRollingMaintenanceCmd.java index 7ee3e50e0cd..04fa1002611 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/StartRollingMaintenanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/StartRollingMaintenanceCmd.java @@ -34,7 +34,6 @@ import org.apache.cloudstack.api.response.PodResponse; import org.apache.cloudstack.api.response.RollingMaintenanceResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -55,7 +54,6 @@ public class StartRollingMaintenanceCmd extends BaseAsyncCmd { @Inject RollingMaintenanceManager manager; - public static final Logger s_logger = Logger.getLogger(StartRollingMaintenanceCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/UploadCustomCertificateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/UploadCustomCertificateCmd.java index 5dfada57216..c5ae6890c3e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/UploadCustomCertificateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/UploadCustomCertificateCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.resource; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; description = "Uploads a custom certificate for the console proxy VMs to use for SSL. Can be used to upload a single certificate signed by a known CA. Can also be used, through multiple calls, to upload a chain of certificates from CA to the custom certificate itself.", requestHasSensitiveInfo = true, responseHasSensitiveInfo = false) public class UploadCustomCertificateCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UploadCustomCertificateCmd.class.getName()); @Parameter(name = ApiConstants.CERTIFICATE, type = CommandType.STRING, required = true, description = "The certificate to be uploaded.", length = 65535) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/DeleteResourceIconCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/DeleteResourceIconCmd.java index 8fb02ea7054..e97a68bddcb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/DeleteResourceIconCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/DeleteResourceIconCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import java.util.List; @@ -37,7 +36,6 @@ import java.util.List; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.DomainAdmin, RoleType.ResourceAdmin, RoleType.User}) public class DeleteResourceIconCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteResourceIconCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/ListResourceIconCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/ListResourceIconCmd.java index 0af11ceec22..6cc3173cf15 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/ListResourceIconCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/ListResourceIconCmd.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ResourceIconResponse; -import org.apache.log4j.Logger; import java.util.List; @@ -35,7 +34,6 @@ import java.util.List; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.DomainAdmin, RoleType.ResourceAdmin, RoleType.User}) public class ListResourceIconCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ListResourceIconCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/UploadResourceIconCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/UploadResourceIconCmd.java index ea5d8995a2a..5a6acd961bf 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/UploadResourceIconCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/resource/icon/UploadResourceIconCmd.java @@ -31,7 +31,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import java.awt.image.BufferedImage; @@ -46,7 +45,6 @@ import java.util.List; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.DomainAdmin, RoleType.ResourceAdmin, RoleType.User}) public class UploadResourceIconCmd extends BaseCmd { - public static final Logger LOGGER = Logger.getLogger(UploadResourceIconCmd.class.getName()); ///////////////////////////////////////////////////// @@ -120,7 +118,7 @@ public class UploadResourceIconCmd extends BaseCmd { return false; } } catch (Exception e) { - LOGGER.warn("Data uploaded not a valid image"); + logger.warn("Data uploaded not a valid image"); return false; } return true; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ConfigureOvsElementCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ConfigureOvsElementCmd.java index a1b01a1c04f..4a8c0bc3a3b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ConfigureOvsElementCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ConfigureOvsElementCmd.java @@ -29,7 +29,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.OvsProviderResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -42,8 +41,6 @@ import com.cloud.user.Account; @APICommand(name = "configureOvsElement", responseObject = OvsProviderResponse.class, description = "Configures an ovs element.", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ConfigureOvsElementCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger - .getLogger(ConfigureOvsElementCmd.class.getName()); @Inject private List _service; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ConfigureVirtualRouterElementCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ConfigureVirtualRouterElementCmd.java index b7f7a050d07..aa119f3aca7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ConfigureVirtualRouterElementCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ConfigureVirtualRouterElementCmd.java @@ -20,7 +20,6 @@ import java.util.List; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -43,7 +42,6 @@ import com.cloud.user.Account; @APICommand(name = "configureVirtualRouterElement", responseObject = VirtualRouterProviderResponse.class, description = "Configures a virtual router element.", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ConfigureVirtualRouterElementCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ConfigureVirtualRouterElementCmd.class.getName()); @Inject private List _service; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/CreateVirtualRouterElementCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/CreateVirtualRouterElementCmd.java index f93ca35a06a..e85531c83c4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/CreateVirtualRouterElementCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/CreateVirtualRouterElementCmd.java @@ -20,7 +20,6 @@ import java.util.List; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -43,7 +42,6 @@ import com.cloud.user.Account; @APICommand(name = "createVirtualRouterElement", responseObject = VirtualRouterProviderResponse.class, description = "Create a virtual router element.", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVirtualRouterElementCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateVirtualRouterElementCmd.class.getName()); @Inject private List _service; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java index d2dce6b9ff3..39ccee47fbe 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.router; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -38,7 +37,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "destroyRouter", description = "Destroys a router.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DestroyRouterCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DestroyRouterCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/GetRouterHealthCheckResultsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/GetRouterHealthCheckResultsCmd.java index 93a48eba49c..4bef26e0555 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/GetRouterHealthCheckResultsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/GetRouterHealthCheckResultsCmd.java @@ -30,7 +30,6 @@ import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse; import org.apache.cloudstack.api.response.RouterHealthCheckResultsListResponse; import org.apache.cloudstack.context.CallContext; import org.apache.commons.lang.BooleanUtils; -import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceUnavailableException; @@ -47,7 +46,6 @@ import com.cloud.vm.VirtualMachine; responseHasSensitiveInfo = false, since = "4.14.0") public class GetRouterHealthCheckResultsCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(GetRouterHealthCheckResultsCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListOvsElementsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListOvsElementsCmd.java index 89b39f87e44..a267aa52669 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListOvsElementsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListOvsElementsCmd.java @@ -26,11 +26,9 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.OvsProviderResponse; import org.apache.cloudstack.api.response.ProviderResponse; -import org.apache.log4j.Logger; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -42,8 +40,7 @@ import com.cloud.network.element.VirtualRouterElementService; @APICommand(name = "listOvsElements", description = "Lists all available ovs elements.", responseObject = OvsProviderResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListOvsElementsCmd extends BaseListCmd { - public static final Logger s_logger = Logger - .getLogger(ListNetworkOfferingsCmd.class.getName()); + @Inject private List _service; // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java index 6e955e46212..e0cdc0dcf80 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.router; import org.apache.commons.lang.BooleanUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -40,7 +39,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "listRouters", description = "List routers.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListRoutersCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java index 6eb24dce074..424b8c29d04 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java @@ -21,7 +21,6 @@ import java.util.List; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -42,7 +41,6 @@ import com.cloud.network.element.VirtualRouterElementService; @APICommand(name = "listVirtualRouterElements", description = "Lists all available virtual router elements.", responseObject = VirtualRouterProviderResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVirtualRouterElementsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListVirtualRouterElementsCmd.class.getName()); // TODO, VirtualRouterElementServer is not singleton in system! @Inject diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java index 6e334d7e442..1d97dd80309 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.router; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -39,7 +38,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "rebootRouter", description = "Starts a router.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RebootRouterCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RebootRouterCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java index 121b2a1bd11..24ab7881037 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.router; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -41,7 +40,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "startRouter", responseObject = DomainRouterResponse.class, description = "Starts a router.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StartRouterCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(StartRouterCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java index 2da38d90426..971086a57cf 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.router; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -40,7 +39,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "stopRouter", description = "Stops a router.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StopRouterCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(StopRouterCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java index 2d5255614c6..3265a089d67 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.router; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "changeServiceForRouter", description = "Upgrades domain router to a new service offering", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpgradeRouterCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpgradeRouterCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/UpgradeRouterTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/UpgradeRouterTemplateCmd.java index fa0fe5800ee..74464cab315 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/UpgradeRouterTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/UpgradeRouterTemplateCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.router; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -43,7 +42,6 @@ import com.cloud.user.Account; @APICommand(name = "upgradeRouterTemplate", description = "Upgrades router to use newer template", responseObject = BaseResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpgradeRouterTemplateCmd extends org.apache.cloudstack.api.BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpgradeRouterTemplateCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/snapshot/ListSnapshotsCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/snapshot/ListSnapshotsCmdByAdmin.java new file mode 100644 index 00000000000..7070ba349e6 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/snapshot/ListSnapshotsCmdByAdmin.java @@ -0,0 +1,50 @@ +// 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.snapshot; + +import com.cloud.storage.Snapshot; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.command.admin.AdminCmd; +import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.SnapshotResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; + +@APICommand(name = "listSnapshots", description = "Lists all available snapshots for the account.", responseObject = SnapshotResponse.class, entityType = { + Snapshot.class }, responseView = ResponseObject.ResponseView.Full, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class ListSnapshotsCmdByAdmin extends ListSnapshotsCmd implements AdminCmd { + @Parameter(name = ApiConstants.IMAGE_STORE_ID, type = CommandType.UUID, entityType = ImageStoreResponse.class, + description = "ID of the image or image cache store", since = "4.19") + private Long imageStoreId; + + @Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, + description = "ID of the storage pool", since = "4.19") + private Long storagePoolId; + + @Override + public Long getImageStoreId() { + return imageStoreId; + } + + @Override + public Long getStoragePoolId() { + return storagePoolId; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java index b8ab1461a2b..7c8f0e21afb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreCmd.java @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "addImageStore", description = "Adds backup image store.", responseObject = ImageStoreResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddImageStoreCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddImageStoreCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -137,7 +135,7 @@ public class AddImageStoreCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage"); } } catch (DiscoveryException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreS3CMD.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreS3CMD.java index 34ff171b91f..2fe3c7cd106 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreS3CMD.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddImageStoreS3CMD.java @@ -38,7 +38,6 @@ import java.util.HashMap; import java.util.Map; import com.cloud.utils.storage.S3.ClientOptions; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -59,7 +58,6 @@ import com.cloud.storage.ImageStore; @APICommand(name = "addImageStoreS3", description = "Adds S3 Image Store", responseObject = ImageStoreResponse.class, since = "4.7.0", requestHasSensitiveInfo = true, responseHasSensitiveInfo = false) public final class AddImageStoreS3CMD extends BaseCmd implements ClientOptions { - public static final Logger s_logger = Logger.getLogger(AddImageStoreS3CMD.class.getName()); private static final String s_name = "addImageStoreS3Response"; @@ -141,7 +139,7 @@ public final class AddImageStoreS3CMD extends BaseCmd implements ClientOptions { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add S3 Image Store."); } } catch (DiscoveryException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddObjectStoragePoolCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddObjectStoragePoolCmd.java new file mode 100644 index 00000000000..b779ba2a2b4 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/AddObjectStoragePoolCmd.java @@ -0,0 +1,130 @@ +// 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.storage; + +import org.apache.cloudstack.storage.object.ObjectStore; +import com.cloud.user.Account; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ObjectStoreResponse; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +@APICommand(name = "addObjectStoragePool", description = "Adds a object storage pool", responseObject = ObjectStoreResponse.class, since = "4.19.0", + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class AddObjectStoragePoolCmd extends BaseCmd { + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name for the object store") + private String name; + + @Parameter(name = ApiConstants.URL, type = CommandType.STRING, length = 2048, required = true, description = "the URL for the object store") + private String url; + + @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, required = true, description = "the object store provider name") + private String providerName; + + @Parameter(name = ApiConstants.DETAILS, + type = CommandType.MAP, + description = "the details for the object store. Example: details[0].key=accesskey&details[0].value=s389ddssaa&details[1].key=secretkey&details[1].value=8dshfsss") + private Map details; + + @Parameter(name = ApiConstants.TAGS, type = CommandType.STRING, description = "the tags for the storage pool") + private String tags; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getUrl() { + return url; + } + + public String getName() { + return name; + } + + public Map getDetails() { + Map detailsMap = null; + if (details != null && !details.isEmpty()) { + detailsMap = new HashMap(); + Collection props = details.values(); + Iterator iter = props.iterator(); + while (iter.hasNext()) { + HashMap detail = (HashMap)iter.next(); + String key = detail.get(ApiConstants.KEY); + String value = detail.get(ApiConstants.VALUE); + detailsMap.put(key, value); + } + } + return detailsMap; + } + + public String getProviderName() { + return providerName; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public void setDetails(Map details) { + this.details = details; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute(){ + try{ + ObjectStore result = _storageService.discoverObjectStore(getName(), getUrl(), getProviderName(), getDetails()); + ObjectStoreResponse storeResponse = null; + if (result != null) { + storeResponse = _responseGenerator.createObjectStoreResponse(result); + storeResponse.setResponseName(getCommandName()); + storeResponse.setObjectName("objectstore"); + setResponseObject(storeResponse); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add object storage"); + } + } catch (Exception ex) { + logger.error("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CancelPrimaryStorageMaintenanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CancelPrimaryStorageMaintenanceCmd.java index a694aba30fb..7e925f286d0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CancelPrimaryStorageMaintenanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CancelPrimaryStorageMaintenanceCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.storage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -36,7 +35,6 @@ import com.cloud.user.Account; @APICommand(name = "cancelStorageMaintenance", description = "Cancels maintenance for primary storage", responseObject = StoragePoolResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CancelPrimaryStorageMaintenanceCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(CancelPrimaryStorageMaintenanceCmd.class.getName()); private static final String s_name = "cancelprimarystoragemaintenanceresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ChangeStoragePoolScopeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ChangeStoragePoolScopeCmd.java new file mode 100644 index 00000000000..d3b6a074610 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ChangeStoragePoolScopeCmd.java @@ -0,0 +1,98 @@ +// 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.storage; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; + +import com.cloud.event.EventTypes; +import com.cloud.storage.StoragePool; + +@APICommand(name = "changeStoragePoolScope", description = "Changes the scope of a storage pool when the pool is in Disabled state." + + "This feature is officially tested and supported for Hypervisors: KVM and VMware, Protocols: NFS and Ceph, and Storage Provider: DefaultPrimary. " + + "There might be extra steps involved to make this work for other hypervisors and storage options.", + responseObject = SuccessResponse.class, since= "4.19.1", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class ChangeStoragePoolScopeCmd extends BaseAsyncCmd { + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, required = true, description = "the Id of the storage pool") + private Long id; + + @Parameter(name = ApiConstants.SCOPE, type = CommandType.STRING, required = true, description = "the scope of the storage: cluster or zone") + private String scope; + + @Parameter(name = ApiConstants.CLUSTER_ID, type = CommandType.UUID, entityType = ClusterResponse.class, description = "the Id of the cluster to use if scope is being set to Cluster") + private Long clusterId; + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.StoragePool; + } + + @Override + public Long getApiResourceId() { + return getId(); + } + + public String getEventType() { + return EventTypes.EVENT_CHANGE_STORAGE_POOL_SCOPE; + } + + @Override + public String getEventDescription() { + String description = "Change storage pool scope. Storage pool Id: "; + StoragePool pool = _entityMgr.findById(StoragePool.class, getId()); + if (pool != null) { + description += pool.getUuid(); + } else { + description += getId(); + } + description += " to " + getScope(); + return description; + } + + @Override + public void execute() { + _storageService.changeStoragePoolScope(this); + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccountId(); + } + + public Long getId() { + return id; + } + + public String getScope() { + return scope; + } + + public Long getClusterId() { + return clusterId; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateSecondaryStagingStoreCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateSecondaryStagingStoreCmd.java index 08069446893..5776eb6464c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateSecondaryStagingStoreCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateSecondaryStagingStoreCmd.java @@ -21,7 +21,6 @@ package org.apache.cloudstack.api.command.admin.storage; import java.util.HashMap; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,6 @@ import com.cloud.user.Account; @APICommand(name = "createSecondaryStagingStore", description = "create secondary staging store.", responseObject = ImageStoreResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateSecondaryStagingStoreCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateSecondaryStagingStoreCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -113,7 +111,7 @@ public class CreateSecondaryStagingStoreCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage"); } } catch (Exception ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java index 0eacc5cda6b..75813a7aabf 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.storage; import java.net.UnknownHostException; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -41,7 +40,6 @@ import com.cloud.user.Account; @APICommand(name = "createStoragePool", description = "Creates a storage pool.", responseObject = StoragePoolResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateStoragePoolCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateStoragePoolCmd.class.getName()); ///////////////////////////////////////////////////// @@ -90,6 +88,9 @@ public class CreateStoragePoolCmd extends BaseCmd { description = "hypervisor type of the hosts in zone that will be attached to this storage pool. KVM, VMware supported as of now.") private String hypervisor; + @Parameter(name = ApiConstants.IS_TAG_A_RULE, type = CommandType.BOOLEAN, description = ApiConstants.PARAMETER_DESCRIPTION_IS_TAG_A_RULE) + private Boolean isTagARule; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -146,6 +147,10 @@ public class CreateStoragePoolCmd extends BaseCmd { return hypervisor; } + public Boolean isTagARule() { + return this.isTagARule; + } + @Override public long getEntityOwnerId() { return Account.ACCOUNT_ID_SYSTEM; @@ -163,13 +168,13 @@ public class CreateStoragePoolCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add storage pool"); } } catch (ResourceUnavailableException ex1) { - s_logger.warn("Exception: ", ex1); + logger.warn("Exception: ", ex1); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex1.getMessage()); } catch (ResourceInUseException ex2) { - s_logger.warn("Exception: ", ex2); + logger.warn("Exception: ", ex2); throw new ServerApiException(ApiErrorCode.RESOURCE_IN_USE_ERROR, ex2.getMessage()); } catch (UnknownHostException ex3) { - s_logger.warn("Exception: ", ex3); + logger.warn("Exception: ", ex3); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex3.getMessage()); } catch (Exception ex4) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex4.getMessage()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteImageStoreCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteImageStoreCmd.java index 194f0baf603..50a9d9a6f39 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteImageStoreCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteImageStoreCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.storage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,7 +31,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteImageStore", description = "Deletes an image store or Secondary Storage.", responseObject = SuccessResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteImageStoreCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteImageStoreCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteObjectStoragePoolCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteObjectStoragePoolCmd.java new file mode 100644 index 00000000000..6cb38d4c862 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteObjectStoragePoolCmd.java @@ -0,0 +1,67 @@ +// 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.storage; + +import com.cloud.user.Account; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ObjectStoreResponse; +import org.apache.cloudstack.api.response.SuccessResponse; + +@APICommand(name = "deleteObjectStoragePool", description = "Deletes an Object Storage Pool", responseObject = SuccessResponse.class, since = "4.19.0", + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class DeleteObjectStoragePoolCmd extends BaseCmd { + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ObjectStoreResponse.class, required = true, description = "The Object Storage ID.") + private Long id; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + boolean result = _storageService.deleteObjectStore(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete object store"); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeletePoolCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeletePoolCmd.java index d87768e7f39..28f71e0740f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeletePoolCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeletePoolCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.storage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteStoragePool", description = "Deletes a storage pool.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeletePoolCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeletePoolCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteSecondaryStagingStoreCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteSecondaryStagingStoreCmd.java index 34a26461fa8..a0c2731ccda 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteSecondaryStagingStoreCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DeleteSecondaryStagingStoreCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.storage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,7 +31,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteSecondaryStagingStore", description = "Deletes a secondary staging store .", responseObject = SuccessResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSecondaryStagingStoreCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteSecondaryStagingStoreCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DownloadImageStoreObjectCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DownloadImageStoreObjectCmd.java new file mode 100644 index 00000000000..92019e70eca --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/DownloadImageStoreObjectCmd.java @@ -0,0 +1,99 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.storage; + +import com.cloud.event.EventTypes; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ExtractResponse; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.storage.browser.StorageBrowser; + +import javax.inject.Inject; +import java.nio.file.Path; + +@APICommand(name = "downloadImageStoreObject", description = "Download object at a specified path on an image store.", + responseObject = ExtractResponse.class, since = "4.19.0", requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false) +public class DownloadImageStoreObjectCmd extends BaseAsyncCmd { + + @Inject + StorageBrowser storageBrowser; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ImageStoreResponse.class, required = true, + description = "id of the image store") + private Long storeId; + + @Parameter(name = ApiConstants.PATH, type = CommandType.STRING, description = "path to download on image store") + private String path; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getStoreId() { + return storeId; + } + + public String getPath() { + if (path == null) { + path = "/"; + } + // We prepend "/" to path and normalize to prevent path traversal attacks + return Path.of(String.format("/%s", path)).normalize().toString().substring(1); + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() { + ExtractResponse response = storageBrowser.downloadImageStoreObject(this); + response.setResponseName(getCommandName()); + response.setObjectName(getCommandName()); + this.setResponseObject(response); + } + + /** + * For commands the API framework needs to know the owner of the object being acted upon. This method is + * used to determine that information. + * + * @return the id of the account that owns the object being acted upon + */ + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccount().getId(); + } + + @Override + public String getEventType() { + return EventTypes.EVENT_IMAGE_STORE_OBJECT_DOWNLOAD; + } + + @Override + public String getEventDescription() { + return "Downloading object at path " + getPath() + " on image store " + getStoreId(); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java index 699f4831415..a45f72766dc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java @@ -30,7 +30,6 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.storage.StoragePool; import com.cloud.utils.Pair; @@ -38,7 +37,6 @@ import com.cloud.utils.Pair; @APICommand(name = "findStoragePoolsForMigration", description = "Lists storage pools available for migration of a volume.", responseObject = StoragePoolResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class FindStoragePoolsForMigrationCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(FindStoragePoolsForMigrationCmd.class.getName()); ///////////////////////////////////////////////////// @@ -67,7 +65,7 @@ public class FindStoragePoolsForMigrationCmd extends BaseListCmd { @Override public void execute() { - Pair, List> pools = _mgr.listStoragePoolsForMigrationOfVolume(getId()); + Pair, List> pools = _mgr.listStoragePoolsForMigrationOfVolume(getId(), getKeyword()); ListResponse response = new ListResponse(); List poolResponses = new ArrayList(); @@ -87,7 +85,8 @@ public class FindStoragePoolsForMigrationCmd extends BaseListCmd { poolResponses.add(poolResponse); } sortPoolsBySuitabilityAndName(poolResponses); - response.setResponses(poolResponses); + List pagingList = com.cloud.utils.StringUtils.applyPagination(poolResponses, this.getStartIndex(), this.getPageSizeVal()); + response.setResponses(pagingList, poolResponses.size()); response.setResponseName(getCommandName()); this.setResponseObject(response); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListImageStoreObjectsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListImageStoreObjectsCmd.java new file mode 100644 index 00000000000..48fd25c99c6 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListImageStoreObjectsCmd.java @@ -0,0 +1,77 @@ +// 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.storage; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.storage.browser.DataStoreObjectResponse; +import org.apache.cloudstack.storage.browser.StorageBrowser; + +import javax.inject.Inject; +import java.nio.file.Path; + +@APICommand(name = "listImageStoreObjects", description = "Lists objects at specified path on an image store.", + responseObject = DataStoreObjectResponse.class, since = "4.19.0", requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false) +public class ListImageStoreObjectsCmd extends BaseListCmd { + + @Inject + StorageBrowser storageBrowser; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ImageStoreResponse.class, required = true, + description = "id of the image store") + private Long storeId; + + @Parameter(name = ApiConstants.PATH, type = CommandType.STRING, description = "path to list on image store") + private String path; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getStoreId() { + return storeId; + } + + public String getPath() { + if (path == null) { + path = "/"; + } + // We prepend "/" to path and normalize to prevent path traversal attacks + return Path.of(String.format("/%s", path)).normalize().toString().substring(1); + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() { + ListResponse response = storageBrowser.listImageStoreObjects(this); + response.setResponseName(getCommandName()); + response.setObjectName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListImageStoresCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListImageStoresCmd.java index a9eac3ed76d..5270569de44 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListImageStoresCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListImageStoresCmd.java @@ -23,12 +23,10 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; @APICommand(name = "listImageStores", description = "Lists image stores.", responseObject = ImageStoreResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListImageStoresCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListImageStoresCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListObjectStoragePoolsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListObjectStoragePoolsCmd.java new file mode 100644 index 00000000000..005a1a54444 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListObjectStoragePoolsCmd.java @@ -0,0 +1,77 @@ +// 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.storage; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.ObjectStoreResponse; + +@APICommand(name = "listObjectStoragePools", description = "Lists object storage pools.", responseObject = ObjectStoreResponse.class, since = "4.19.0", + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class ListObjectStoragePoolsCmd extends BaseListCmd { + + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the object store") + private String storeName; + + @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, description = "the object store provider") + private String provider; + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ObjectStoreResponse.class, description = "the ID of the storage pool") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public String getStoreName() { + return storeName; + } + + public Long getId() { + return id; + } + + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() { + ListResponse response = _queryService.searchForObjectStores(this); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListSecondaryStagingStoresCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListSecondaryStagingStoresCmd.java index e315c8a6d47..0cad16a247f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListSecondaryStagingStoresCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListSecondaryStagingStoresCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.storage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -29,7 +28,6 @@ import org.apache.cloudstack.api.response.ZoneResponse; @APICommand(name = "listSecondaryStagingStores", description = "Lists secondary staging stores.", responseObject = ImageStoreResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSecondaryStagingStoresCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListSecondaryStagingStoresCmd.class.getName()); private static final String s_name = "listsecondarystagingstoreresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolObjectsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolObjectsCmd.java new file mode 100644 index 00000000000..4dac92a9572 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolObjectsCmd.java @@ -0,0 +1,78 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.storage; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.storage.browser.DataStoreObjectResponse; +import org.apache.cloudstack.storage.browser.StorageBrowser; + +import javax.inject.Inject; +import java.nio.file.Path; + + +@APICommand(name = "listStoragePoolObjects", description = "Lists objects at specified path on a storage pool.", + responseObject = DataStoreObjectResponse.class, since = "4.19.0", requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false) +public class ListStoragePoolObjectsCmd extends BaseListCmd { + + @Inject + StorageBrowser storageBrowser; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, required = true, + description = "id of the storage pool") + private Long storeId; + + @Parameter(name = ApiConstants.PATH, type = CommandType.STRING, description = "path to list on storage pool") + private String path; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getStoreId() { + return storeId; + } + + public String getPath() { + if (path == null) { + path = "/"; + } + // We prepend "/" to path and normalize to prevent path traversal attacks + return Path.of(String.format("/%s", path)).normalize().toString().substring(1); + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() { + ListResponse response = storageBrowser.listPrimaryStoreObjects(this); + response.setResponseName(getCommandName()); + response.setObjectName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolsCmd.java index 209aaac279c..57a87939b6b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.storage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -24,6 +23,7 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.PodResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; @@ -32,7 +32,6 @@ import org.apache.cloudstack.api.response.ZoneResponse; @APICommand(name = "listStoragePools", description = "Lists storage pools.", responseObject = StoragePoolResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListStoragePoolsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListStoragePoolsCmd.class.getName()); ///////////////////////////////////////////////////// @@ -63,16 +62,26 @@ public class ListStoragePoolsCmd extends BaseListCmd { @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, description = "the ID of the storage pool") private Long id; - @Parameter(name = ApiConstants.SCOPE, type = CommandType.STRING, entityType = StoragePoolResponse.class, description = "the ID of the storage pool") + @Parameter(name = ApiConstants.SCOPE, type = CommandType.STRING, entityType = StoragePoolResponse.class, description = "the scope of the storage pool") private String scope; + @Parameter(name = ApiConstants.STATUS, type = CommandType.STRING, description = "the status of the storage pool") private String status; + @Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, description = "host ID of the storage pools") + private Long hostId; + + @Parameter(name = ApiConstants.STORAGE_CUSTOM_STATS, type = CommandType.BOOLEAN, description = "If true, lists the custom stats of the storage pool", since = "4.18.1") + private Boolean customStats; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// + public Long getHostId() { + return hostId; + } + public Long getClusterId() { return clusterId; } @@ -81,6 +90,10 @@ public class ListStoragePoolsCmd extends BaseListCmd { return ipAddress; } + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + public String getStoragePoolName() { return storagePoolName; } @@ -108,6 +121,19 @@ public class ListStoragePoolsCmd extends BaseListCmd { public void setId(Long id) { this.id = id; } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + public Boolean getCustomStats() { + return customStats != null && customStats; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -123,8 +149,4 @@ public class ListStoragePoolsCmd extends BaseListCmd { response.setResponseName(getCommandName()); this.setResponseObject(response); } - - public String getScope() { - return scope; - } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStorageProvidersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStorageProvidersCmd.java index 347b66061f6..efe7a23b5cb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStorageProvidersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStorageProvidersCmd.java @@ -20,7 +20,6 @@ package org.apache.cloudstack.api.command.admin.storage; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,6 @@ import com.cloud.exception.ResourceUnavailableException; @APICommand(name = "listStorageProviders", description = "Lists storage providers.", responseObject = StorageProviderResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListStorageProvidersCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListStorageProvidersCmd.class.getName()); @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, description = "the type of storage provider: either primary or image", required = true) private String type; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStorageTagsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStorageTagsCmd.java index 43981ee1a3d..d9bb5d4cd93 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStorageTagsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/ListStorageTagsCmd.java @@ -18,7 +18,6 @@ */ package org.apache.cloudstack.api.command.admin.storage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.BaseListCmd; @@ -27,7 +26,6 @@ import org.apache.cloudstack.api.response.StorageTagResponse; @APICommand(name = "listStorageTags", description = "Lists storage tags", responseObject = StorageTagResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListStorageTagsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListStorageTagsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/MigrateResourcesToAnotherSecondaryStorageCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/MigrateResourcesToAnotherSecondaryStorageCmd.java new file mode 100644 index 00000000000..3bc4fd7a371 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/MigrateResourcesToAnotherSecondaryStorageCmd.java @@ -0,0 +1,140 @@ +// 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.storage; + +import com.cloud.event.EventTypes; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.MigrationResponse; +import org.apache.cloudstack.api.response.SnapshotResponse; +import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.commons.collections.CollectionUtils; + +import java.util.Collections; +import java.util.List; + +@APICommand(name = "migrateResourceToAnotherSecondaryStorage", + description = "migrates resources from one secondary storage to destination image store", + responseObject = MigrationResponse.class, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = false, + since = "4.19.0", + authorized = {RoleType.Admin}) +public class MigrateResourcesToAnotherSecondaryStorageCmd extends BaseAsyncCmd { + + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.SRC_POOL, + type = CommandType.UUID, + entityType = ImageStoreResponse.class, + description = "id of the image store from where the data is to be migrated", + required = true) + private Long id; + + + @Parameter(name = ApiConstants.DEST_POOL, + type = CommandType.UUID, + entityType = ImageStoreResponse.class, + description = "id of the destination secondary storage pool to which the resources are to be migrated", + required = true) + private Long destStoreId; + + @Parameter(name = "templates", + type = CommandType.LIST, + collectionType = CommandType.UUID, + entityType = TemplateResponse.class, + description = "id(s) of the templates to be migrated", + required = false) + private List templateIdList; + + @Parameter(name = "snapshots", + type = CommandType.LIST, + collectionType = CommandType.UUID, + entityType = SnapshotResponse.class, + description = "id(s) of the snapshots to be migrated", + required = false) + private List snapshotIdList; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getDestStoreId() { + return destStoreId; + } + + public List getTemplateIdList() { + if (CollectionUtils.isEmpty(templateIdList)) { + return Collections.emptyList(); + } + return templateIdList; + } + + public List getSnapshotIdList() { + if (CollectionUtils.isEmpty(snapshotIdList)) { + return Collections.emptyList(); + } + return snapshotIdList; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_IMAGE_STORE_RESOURCES_MIGRATE; + } + + @Override + public String getEventDescription() { + return "Attempting to migrate files/data objects to another image store"; + } + + @Override + public void execute() { + MigrationResponse response = _imageStoreService.migrateResources(this); + response.setObjectName("imagestore"); + this.setResponseObject(response); + CallContext.current().setEventDetails(response.getMessage()); + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccountId(); + } + + @Override + public Long getApiResourceId() { + return getId(); + } + + public Long getId() { + return id; + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.ImageStore; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/MigrateSecondaryStorageDataCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/MigrateSecondaryStorageDataCmd.java index de9b55a9ff1..8f5a7aced3f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/MigrateSecondaryStorageDataCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/MigrateSecondaryStorageDataCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.MigrationResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; @@ -41,7 +40,6 @@ import com.cloud.event.EventTypes; authorized = {RoleType.Admin}) public class MigrateSecondaryStorageDataCmd extends BaseAsyncCmd { - public static final Logger LOGGER = Logger.getLogger(MigrateSecondaryStorageDataCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/PreparePrimaryStorageForMaintenanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/PreparePrimaryStorageForMaintenanceCmd.java index ddabefb14c8..818b3a5bbea 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/PreparePrimaryStorageForMaintenanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/PreparePrimaryStorageForMaintenanceCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.storage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "enableStorageMaintenance", description = "Puts storage pool into maintenance state", responseObject = StoragePoolResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class PreparePrimaryStorageForMaintenanceCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(PreparePrimaryStorageForMaintenanceCmd.class.getName()); private static final String s_name = "prepareprimarystorageformaintenanceresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/SyncStoragePoolCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/SyncStoragePoolCmd.java index d7a783a4ff4..9f81f2f6c86 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/SyncStoragePoolCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/SyncStoragePoolCmd.java @@ -33,7 +33,6 @@ import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.context.CallContext; -import java.util.logging.Logger; @APICommand(name = "syncStoragePool", description = "Sync storage pool with management server (currently supported for Datastore Cluster in VMware and syncs the datastores in it)", @@ -45,7 +44,6 @@ import java.util.logging.Logger; ) public class SyncStoragePoolCmd extends BaseAsyncCmd { - public static final Logger LOGGER = Logger.getLogger(SyncStoragePoolCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateCloudToUseObjectStoreCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateCloudToUseObjectStoreCmd.java index 3351d389c6f..5ac34f27bad 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateCloudToUseObjectStoreCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateCloudToUseObjectStoreCmd.java @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,6 @@ import com.cloud.user.Account; @APICommand(name = "updateCloudToUseObjectStore", description = "Migrate current NFS secondary storages to use object store.", responseObject = ImageStoreResponse.class, since = "4.3.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateCloudToUseObjectStoreCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateCloudToUseObjectStoreCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -130,7 +128,7 @@ public class UpdateCloudToUseObjectStoreCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add secondary storage"); } } catch (DiscoveryException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateImageStoreCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateImageStoreCmd.java index d7dca93b485..0e1631a46ba 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateImageStoreCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateImageStoreCmd.java @@ -25,14 +25,12 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.storage.ImageStore; @APICommand(name = UpdateImageStoreCmd.APINAME, description = "Updates image store read-only status", responseObject = ImageStoreResponse.class, entityType = {ImageStore.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.15.0") public class UpdateImageStoreCmd extends BaseCmd { - private static final Logger LOG = Logger.getLogger(UpdateImageStoreCmd.class.getName()); public static final String APINAME = "updateImageStore"; ///////////////////////////////////////////////////// @@ -41,10 +39,17 @@ public class UpdateImageStoreCmd extends BaseCmd { @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ImageStoreResponse.class, required = true, description = "Image Store UUID") private Long id; - @Parameter(name = ApiConstants.READ_ONLY, type = CommandType.BOOLEAN, required = true, description = "If set to true, it designates the corresponding image store to read-only, " + - "hence not considering them during storage migration") + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = false, description = "The new name for the Image Store.") + private String name; + + @Parameter(name = ApiConstants.READ_ONLY, type = CommandType.BOOLEAN, required = false, + description = "If set to true, it designates the corresponding image store to read-only, hence not considering them during storage migration") private Boolean readonly; + @Parameter(name = ApiConstants.CAPACITY_BYTES, type = CommandType.LONG, required = false, + description = "The number of bytes CloudStack can use on this image storage.\n\tNOTE: this will be overwritten by the StatsCollector as soon as there is a SSVM to query the storage.") + private Long capacityBytes; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -53,17 +58,25 @@ public class UpdateImageStoreCmd extends BaseCmd { return id; } + public String getName() { + return name; + } + public Boolean getReadonly() { return readonly; } + public Long getCapacityBytes() { + return capacityBytes; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @Override public void execute() { - ImageStore result = _storageService.updateImageStoreStatus(getId(), getReadonly()); + ImageStore result = _storageService.updateImageStore(this); ImageStoreResponse storeResponse = null; if (result != null) { storeResponse = _responseGenerator.createImageStoreResponse(result); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateObjectStoragePoolCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateObjectStoragePoolCmd.java new file mode 100644 index 00000000000..497179d25ef --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateObjectStoragePoolCmd.java @@ -0,0 +1,93 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.storage; + +import org.apache.cloudstack.storage.object.ObjectStore; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ObjectStoreResponse; +import org.apache.cloudstack.context.CallContext; + +@APICommand(name = UpdateObjectStoragePoolCmd.APINAME, description = "Updates object storage pool", responseObject = ObjectStoreResponse.class, entityType = {ObjectStore.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.0") +public class UpdateObjectStoragePoolCmd extends BaseCmd { + public static final String APINAME = "updateObjectStoragePool"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ObjectStoreResponse.class, required = true, description = "Object Store ID") + private Long id; + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name for the object store") + private String name; + + @Parameter(name = ApiConstants.URL, type = CommandType.STRING, description = "the url for the object store") + private String url; + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getUrl() { + return url; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() { + ObjectStore result = _storageService.updateObjectStore(getId(), this); + + ObjectStoreResponse storeResponse = null; + if (result != null) { + storeResponse = _responseGenerator.createObjectStoreResponse(result); + storeResponse.setResponseName(getCommandName()); + storeResponse.setObjectName("objectstore"); + setResponseObject(storeResponse); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update object storage"); + } + } + + @Override + public String getCommandName() { + return APINAME; + } + + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccountId(); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStorageCapabilitiesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStorageCapabilitiesCmd.java index 8403d3c6241..716c95b45c3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStorageCapabilitiesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStorageCapabilitiesCmd.java @@ -29,14 +29,12 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; @APICommand(name = "updateStorageCapabilities", description = "Syncs capabilities of storage pools", responseObject = StoragePoolResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.16.0") public class UpdateStorageCapabilitiesCmd extends BaseCmd { - private static final Logger LOG = Logger.getLogger(UpdateStorageCapabilitiesCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStoragePoolCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStoragePoolCmd.java index 9e34684a09d..13f02ef83c2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStoragePoolCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/UpdateStoragePoolCmd.java @@ -17,9 +17,9 @@ package org.apache.cloudstack.api.command.admin.storage; import java.util.List; +import java.util.Map; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,10 +32,10 @@ import org.apache.cloudstack.api.response.StoragePoolResponse; import com.cloud.storage.StoragePool; import com.cloud.user.Account; +@SuppressWarnings("rawtypes") @APICommand(name = "updateStoragePool", description = "Updates a storage pool.", responseObject = StoragePoolResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateStoragePoolCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateStoragePoolCmd.class.getName()); ///////////////////////////////////////////////////// @@ -61,6 +61,23 @@ public class UpdateStoragePoolCmd extends BaseCmd { " enable it back.") private Boolean enabled; + @Parameter(name = ApiConstants.DETAILS, + type = CommandType.MAP, + required = false, + description = "the details for the storage pool", + since = "4.19.0") + private Map details; + + @Parameter(name = ApiConstants.URL, + type = CommandType.STRING, + required = false, + description = "the URL of the storage pool", + since = "4.19.0") + private String url; + + @Parameter(name = ApiConstants.IS_TAG_A_RULE, type = CommandType.BOOLEAN, description = ApiConstants.PARAMETER_DESCRIPTION_IS_TAG_A_RULE) + private Boolean isTagARule; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -89,6 +106,10 @@ public class UpdateStoragePoolCmd extends BaseCmd { return enabled; } + public Boolean isTagARule() { + return isTagARule; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -108,6 +129,22 @@ public class UpdateStoragePoolCmd extends BaseCmd { return ApiCommandResourceType.StoragePool; } + public Map getDetails() { + return details; + } + + public void setDetails(Map details) { + this.details = details; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + @Override public void execute() { StoragePool result = _storageService.updateStoragePool(this); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/CreateSecondaryStorageSelectorCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/CreateSecondaryStorageSelectorCmd.java new file mode 100644 index 00000000000..a0e99b55971 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/CreateSecondaryStorageSelectorCmd.java @@ -0,0 +1,93 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.storage.heuristics; + +import com.cloud.user.Account; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.secstorage.heuristics.Heuristic; + +import static org.apache.cloudstack.api.ApiConstants.HEURISTIC_TYPE_VALID_OPTIONS; + +@APICommand(name = "createSecondaryStorageSelector", description = "Creates a secondary storage selector, described by the heuristic rule.", since = "4.19.0", responseObject = + SecondaryStorageHeuristicsResponse.class, entityType = {Heuristic.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin}) +public class CreateSecondaryStorageSelectorCmd extends BaseCmd{ + + @Parameter(name = ApiConstants.NAME, required = true, type = CommandType.STRING, description = "The name identifying the heuristic rule.") + private String name; + + @Parameter(name = ApiConstants.DESCRIPTION, required = true, type = BaseCmd.CommandType.STRING, description = "The description of the heuristic rule.") + private String description; + + @Parameter(name = ApiConstants.ZONE_ID, required = true, entityType = ZoneResponse.class, type = BaseCmd.CommandType.UUID, description = "The zone in which the heuristic " + + "rule will be applied.") + private Long zoneId; + + @Parameter(name = ApiConstants.TYPE, required = true, type = BaseCmd.CommandType.STRING, description = + "The resource type directed to a specific secondary storage by the selector. " + HEURISTIC_TYPE_VALID_OPTIONS) + private String type; + + @Parameter(name = ApiConstants.HEURISTIC_RULE, required = true, type = BaseCmd.CommandType.STRING, description = "The heuristic rule, in JavaScript language. It is required " + + "that it returns the UUID of a secondary storage pool. An example of a rule is `if (snapshot.hypervisorType === 'KVM') { '7832f261-c602-4e8e-8580-2496ffbbc45d'; " + + "}` would allocate all snapshots with the KVM hypervisor to the specified secondary storage UUID.", length = 65535) + private String heuristicRule; + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Long getZoneId() { + return zoneId; + } + + public String getType() { + return type; + } + + public String getHeuristicRule() { + return heuristicRule; + } + + @Override + public void execute() { + Heuristic heuristic = _storageService.createSecondaryStorageHeuristic(this); + + if (heuristic == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create a secondary storage selector."); + } + + SecondaryStorageHeuristicsResponse response = _responseGenerator.createSecondaryStorageSelectorResponse(heuristic); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/ListSecondaryStorageSelectorsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/ListSecondaryStorageSelectorsCmd.java new file mode 100644 index 00000000000..c437cd660e7 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/ListSecondaryStorageSelectorsCmd.java @@ -0,0 +1,63 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.storage.heuristics; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.secstorage.heuristics.Heuristic; + +import static org.apache.cloudstack.api.ApiConstants.HEURISTIC_TYPE_VALID_OPTIONS; + +@APICommand(name = "listSecondaryStorageSelectors", description = "Lists the secondary storage selectors and their rules.", since = "4.19.0", responseObject = + SecondaryStorageHeuristicsResponse.class, requestHasSensitiveInfo = false, entityType = {Heuristic.class}, responseHasSensitiveInfo = false, authorized = {RoleType.Admin}) +public class ListSecondaryStorageSelectorsCmd extends BaseListCmd { + + @Parameter(name = ApiConstants.ZONE_ID, required = true, entityType = ZoneResponse.class, type = CommandType.UUID, description = "The zone ID to be used in the search filter.") + private Long zoneId; + + @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, description = + "Whether to filter the selectors by type and, if so, which one. " + HEURISTIC_TYPE_VALID_OPTIONS) + private String type; + + @Parameter(name = ApiConstants.SHOW_REMOVED, type = CommandType.BOOLEAN, description = "Show removed heuristics.") + private boolean showRemoved = false; + + public Long getZoneId() { + return zoneId; + } + + public String getType() { + return type; + } + + public boolean isShowRemoved() { + return showRemoved; + } + + @Override + public void execute() { + ListResponse response = _queryService.listSecondaryStorageSelectors(this); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/RemoveSecondaryStorageSelectorCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/RemoveSecondaryStorageSelectorCmd.java new file mode 100644 index 00000000000..79554f44782 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/RemoveSecondaryStorageSelectorCmd.java @@ -0,0 +1,54 @@ +// 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.storage.heuristics; + +import com.cloud.user.Account; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.secstorage.heuristics.Heuristic; + +@APICommand(name = "removeSecondaryStorageSelector", description = "Removes an existing secondary storage selector.", since = "4.19.0", responseObject = + SecondaryStorageHeuristicsResponse.class, requestHasSensitiveInfo = false, entityType = {Heuristic.class}, responseHasSensitiveInfo = false, authorized = {RoleType.Admin}) +public class RemoveSecondaryStorageSelectorCmd extends BaseCmd { + @Parameter(name = ApiConstants.ID, type = BaseCmd.CommandType.UUID, entityType = SecondaryStorageHeuristicsResponse.class, required = true, + description = "The unique identifier of the secondary storage selector to be removed.") + private Long id; + + public Long getId() { + return id; + } + + @Override + public void execute() { + _storageService.removeSecondaryStorageHeuristic(this); + final SuccessResponse response = new SuccessResponse(); + response.setResponseName(getCommandName()); + response.setSuccess(true); + setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/UpdateSecondaryStorageSelectorCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/UpdateSecondaryStorageSelectorCmd.java new file mode 100644 index 00000000000..e63d1cbfa27 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/storage/heuristics/UpdateSecondaryStorageSelectorCmd.java @@ -0,0 +1,67 @@ +// 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.storage.heuristics; + +import com.cloud.user.Account; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse; +import org.apache.cloudstack.secstorage.heuristics.Heuristic; + +@APICommand(name = "updateSecondaryStorageSelector", description = "Updates an existing secondary storage selector.", since = "4.19.0", responseObject = + SecondaryStorageHeuristicsResponse.class, requestHasSensitiveInfo = false, entityType = {Heuristic.class}, responseHasSensitiveInfo = false, authorized = {RoleType.Admin}) +public class UpdateSecondaryStorageSelectorCmd extends BaseCmd { + @Parameter(name = ApiConstants.ID, type = BaseCmd.CommandType.UUID, entityType = SecondaryStorageHeuristicsResponse.class, required = true, + description = "The unique identifier of the secondary storage selector.") + private Long id; + + @Parameter(name = ApiConstants.HEURISTIC_RULE, required = true, type = BaseCmd.CommandType.STRING, description = "The heuristic rule, in JavaScript language. It is required " + + "that it returns the UUID of a secondary storage pool. An example of a rule is `if (snapshot.hypervisorType === 'KVM') { '7832f261-c602-4e8e-8580-2496ffbbc45d'; " + + "}` would allocate all snapshots with the KVM hypervisor to the specified secondary storage UUID.", length = 65535) + private String heuristicRule; + + public Long getId() { + return id; + } + + public String getHeuristicRule() { + return heuristicRule; + } + + @Override + public void execute() { + Heuristic heuristic = _storageService.updateSecondaryStorageHeuristic(this); + + if (heuristic == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update the secondary storage selector."); + } + + SecondaryStorageHeuristicsResponse response = _responseGenerator.createSecondaryStorageSelectorResponse(heuristic); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java index 7eb87006d0d..bd72f3213de 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/AddSwiftCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.swift; import java.util.HashMap; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.user.Account; @APICommand(name = "addSwift", description = "Adds Swift.", responseObject = ImageStoreResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddSwiftCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddSwiftCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -102,7 +100,7 @@ public class AddSwiftCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Swift secondary storage"); } } catch (DiscoveryException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/ListSwiftsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/ListSwiftsCmd.java index 6d7bfbaf1b1..e21a23349bb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/ListSwiftsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/swift/ListSwiftsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.swift; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -31,7 +30,6 @@ import com.cloud.user.Account; @APICommand(name = "listSwifts", description = "List Swift.", responseObject = ImageStoreResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSwiftsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListSwiftsCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java index 7ed536f6d4c..7e0faab2fb5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.systemvm; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -37,7 +36,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "destroySystemVm", responseObject = SystemVmResponse.class, description = "Destroys a system virtual machine.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DestroySystemVmCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DestroySystemVmCmd.class.getName()); @ACL(accessType = AccessType.OperateEntry) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java index b6f8c92fa17..e8e5ee0ebad 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.systemvm; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -39,7 +38,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "listSystemVms", description = "List system virtual machines.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSystemVMsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListSystemVMsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java index f0f7aca16c8..ccc6093aa83 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java @@ -31,7 +31,6 @@ import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.SystemVmResponse; import org.apache.cloudstack.context.CallContext; import org.apache.commons.lang.BooleanUtils; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -47,7 +46,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "migrateSystemVm", description = "Attempts Migration of a system virtual machine to the host specified.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class MigrateSystemVMCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(MigrateSystemVMCmd.class.getName()); ///////////////////////////////////////////////////// @@ -171,16 +169,16 @@ public class MigrateSystemVMCmd extends BaseAsyncCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to migrate the system vm"); } } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ConcurrentOperationException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } catch (ManagementServerException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } catch (VirtualMachineMigrationException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java index ae3c36b4948..4f4b2631667 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmd.java @@ -30,13 +30,11 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.SystemVmResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; @APICommand(name = "patchSystemVm", description = "Attempts to live patch systemVMs - CPVM, SSVM ", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = { RoleType.Admin }, since = "4.17.0") public class PatchSystemVMCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(PatchSystemVMCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java index 0ba7e0c2edf..30bd51184ac 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.systemvm; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -37,7 +36,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "rebootSystemVm", description = "Reboots a system VM.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RebootSystemVmCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RebootSystemVmCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java index f694988efa0..06e57674c53 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.systemvm; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -46,7 +45,6 @@ import com.cloud.vm.VirtualMachine; + "The system vm must be in a \"Stopped\" state for " + "this command to take effect.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ScaleSystemVMCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ScaleSystemVMCmd.class.getName()); private static final String s_name = "changeserviceforsystemvmresponse"; ///////////////////////////////////////////////////// @@ -111,16 +109,16 @@ public class ScaleSystemVMCmd extends BaseAsyncCmd { try { result = _mgr.upgradeSystemVM(this); } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (ManagementServerException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (VirtualMachineMigrationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } if (result != null) { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java index 0cb517f4058..eac3d64ab59 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.systemvm; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -37,7 +36,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "startSystemVm", responseObject = SystemVmResponse.class, description = "Starts a system virtual machine.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StartSystemVMCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(StartSystemVMCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java index 4bb533ce5b6..1d84382f5d2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.systemvm; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -39,7 +38,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "stopSystemVm", description = "Stops a system VM.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StopSystemVmCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(StopSystemVmCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java index 12f80f32b06..5abe90e3f58 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.systemvm; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -41,7 +40,6 @@ import com.cloud.vm.VirtualMachine; + "The system vm must be in a \"Stopped\" state for " + "this command to take effect.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpgradeSystemVMCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpgradeSystemVMCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java index 2f57783e5ea..22eb0ff0659 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java @@ -17,15 +17,36 @@ package org.apache.cloudstack.api.command.admin.template; import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.command.admin.AdminCmd; import org.apache.cloudstack.api.command.user.template.ListTemplatesCmd; +import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.TemplateResponse; import com.cloud.template.VirtualMachineTemplate; -@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {VirtualMachineTemplate.class}, responseView = ResponseView.Full, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", + responseObject = TemplateResponse.class, entityType = {VirtualMachineTemplate.class}, + responseView = ResponseView.Full, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTemplatesCmdByAdmin extends ListTemplatesCmd implements AdminCmd { + @Parameter(name = ApiConstants.IMAGE_STORE_ID, type = CommandType.UUID, entityType = ImageStoreResponse.class, + description = "ID of the image or image cache store", since = "4.19") + private Long imageStoreId; + @Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, + description = "ID of the storage pool", since = "4.19") + private Long storagePoolId; + + @Override + public Long getImageStoreId() { + return imageStoreId; + } + + @Override + public Long getStoragePoolId() { + return storagePoolId; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/ListVnfTemplatesCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/ListVnfTemplatesCmdByAdmin.java new file mode 100644 index 00000000000..f231036bbc6 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/ListVnfTemplatesCmdByAdmin.java @@ -0,0 +1,32 @@ +// 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.template; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.admin.AdminCmd; +import org.apache.cloudstack.api.command.user.template.ListVnfTemplatesCmd; +import org.apache.cloudstack.api.response.TemplateResponse; + +import com.cloud.template.VirtualMachineTemplate; + +@APICommand(name = "listVnfTemplates", description = "List all public, private, and privileged VNF templates.", + responseObject = TemplateResponse.class, entityType = {VirtualMachineTemplate.class}, responseView = ResponseView.Full, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.19.0") +public class ListVnfTemplatesCmdByAdmin extends ListVnfTemplatesCmd implements AdminCmd { +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java index 9b8d402864a..9a59efb19f2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.template; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -38,7 +37,6 @@ import com.cloud.user.Account; @APICommand(name = "prepareTemplate", responseObject = TemplateResponse.class, description = "load template into primary storage", entityType = {VirtualMachineTemplate.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class PrepareTemplateCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(PrepareTemplateCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/RegisterTemplateCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/RegisterTemplateCmdByAdmin.java index 28593755c11..91c0dd50e8e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/RegisterTemplateCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/RegisterTemplateCmdByAdmin.java @@ -18,9 +18,11 @@ package org.apache.cloudstack.api.command.admin.template; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.admin.AdminCmd; import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd; import org.apache.cloudstack.api.response.TemplateResponse; @APICommand(name = "registerTemplate", description = "Registers an existing template into the CloudStack cloud.", responseObject = TemplateResponse.class, responseView = ResponseView.Full, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class RegisterTemplateCmdByAdmin extends RegisterTemplateCmd {} +public class RegisterTemplateCmdByAdmin extends RegisterTemplateCmd implements AdminCmd { +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/RegisterVnfTemplateCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/RegisterVnfTemplateCmdByAdmin.java new file mode 100644 index 00000000000..45b40bfebb1 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/RegisterVnfTemplateCmdByAdmin.java @@ -0,0 +1,31 @@ +// 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.template; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.admin.AdminCmd; +import org.apache.cloudstack.api.command.user.template.RegisterVnfTemplateCmd; +import org.apache.cloudstack.api.response.TemplateResponse; + +@APICommand(name = "registerVnfTemplate", + description = "Registers an existing VNF template into the CloudStack cloud. ", + responseObject = TemplateResponse.class, responseView = ResponseView.Full, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.19.0") +public class RegisterVnfTemplateCmdByAdmin extends RegisterVnfTemplateCmd implements AdminCmd { +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/UpdateTemplateCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/UpdateTemplateCmdByAdmin.java index 09591c809b1..b1dfae3ed83 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/UpdateTemplateCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/UpdateTemplateCmdByAdmin.java @@ -24,4 +24,5 @@ import org.apache.cloudstack.api.response.TemplateResponse; @APICommand(name = "updateTemplate", description = "Updates attributes of a template.", responseObject = TemplateResponse.class, responseView = ResponseView.Full, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class UpdateTemplateCmdByAdmin extends UpdateTemplateCmd implements AdminCmd {} +public class UpdateTemplateCmdByAdmin extends UpdateTemplateCmd implements AdminCmd { +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/template/UpdateVnfTemplateCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/UpdateVnfTemplateCmdByAdmin.java new file mode 100644 index 00000000000..102a4703d4c --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/template/UpdateVnfTemplateCmdByAdmin.java @@ -0,0 +1,31 @@ +// 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.template; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.admin.AdminCmd; +import org.apache.cloudstack.api.command.user.template.UpdateVnfTemplateCmd; +import org.apache.cloudstack.api.response.TemplateResponse; + +@APICommand(name = "updateVnfTemplate", + description = "Updates a template to VNF template or attributes of a VNF template.", + responseObject = TemplateResponse.class, responseView = ResponseView.Full, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + since = "4.19.0") +public class UpdateVnfTemplateCmdByAdmin extends UpdateVnfTemplateCmd implements AdminCmd { +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/AddTrafficMonitorCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/AddTrafficMonitorCmd.java index 95593714feb..5c0f1fc1cd2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/AddTrafficMonitorCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/AddTrafficMonitorCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.usage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.utils.exception.CloudRuntimeException; @APICommand(name = "addTrafficMonitor", description = "Adds Traffic Monitor Host for Direct Network Usage", responseObject = TrafficMonitorResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddTrafficMonitorCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AddTrafficMonitorCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/AddTrafficTypeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/AddTrafficTypeCmd.java index 809129402a8..b1810676b74 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/AddTrafficTypeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/AddTrafficTypeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.usage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "addTrafficType", description = "Adds traffic type to a physical network", responseObject = TrafficTypeResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddTrafficTypeCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(AddTrafficTypeCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficMonitorCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficMonitorCmd.java index ff371d6e83d..8fdb3af399c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficMonitorCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficMonitorCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.usage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -33,7 +32,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteTrafficMonitor", description = "Deletes an traffic monitor host.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteTrafficMonitorCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteTrafficMonitorCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficTypeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficTypeCmd.java index a728690a09d..a1e4ebda09a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficTypeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/DeleteTrafficTypeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.usage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteTrafficType", description = "Deletes traffic type of a physical network", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteTrafficTypeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteTrafficTypeCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/GenerateUsageRecordsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/GenerateUsageRecordsCmd.java index 65b864f2ab6..a0314586d92 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/GenerateUsageRecordsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/GenerateUsageRecordsCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.usage; import java.util.Date; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class GenerateUsageRecordsCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(GenerateUsageRecordsCmd.class.getName()); ///////////////////////////////////////////////////// @@ -49,13 +47,13 @@ public class GenerateUsageRecordsCmd extends BaseCmd { @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, - required = true, + required = false, description = "End date range for usage record query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.") private Date endDate; @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, - required = true, + required = false, description = "Start date range for usage record query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-01.") private Date startDate; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficMonitorsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficMonitorsCmd.java index f3a65bbfffd..ed42bc42dbd 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficMonitorsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficMonitorsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.usage; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.host.Host; @APICommand(name = "listTrafficMonitors", description = "List traffic monitor Hosts.", responseObject = TrafficMonitorResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTrafficMonitorsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListTrafficMonitorsCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java index 97f43155be6..1ad8872db96 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.usage; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -44,7 +43,6 @@ import com.cloud.utils.Pair; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTrafficTypeImplementorsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListTrafficTypeImplementorsCmd.class); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java index 6e36ca3bd8d..d106a736fca 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.usage; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listTrafficTypes", description = "Lists traffic types of a given physical network.", responseObject = ProviderResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTrafficTypesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListTrafficTypesCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageRecordsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageRecordsCmd.java index 3cb148c2af0..9ce1fcb2bc9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageRecordsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageRecordsCmd.java @@ -53,16 +53,12 @@ public class ListUsageRecordsCmd extends BaseListCmd { @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "List usage records for the specified domain.") private Long domainId; - @Parameter(name = ApiConstants.END_DATE, - type = CommandType.DATE, - required = true, - description = "End date range for usage record query (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\", e.g. startDate=2015-01-01 or startdate=2015-01-01 10:30:00).") + @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, required = true, description = "End date range for usage record query. " + + ApiConstants.PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS) private Date endDate; - @Parameter(name = ApiConstants.START_DATE, - type = CommandType.DATE, - required = true, - description = "Start date range for usage record query (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\", e.g. startDate=2015-01-01 or startdate=2015-01-01 11:00:00).") + @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, required = true, description = "Start date range for usage record query. " + + ApiConstants.PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS) private Date startDate; @Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "List usage records for the specified account") @@ -137,11 +133,11 @@ public class ListUsageRecordsCmd extends BaseListCmd { } public void setEndDate(Date endDate) { - this.endDate = endDate == null ? null : new Date(endDate.getTime()); + this.endDate = endDate; } public void setStartDate(Date startDate) { - this.startDate = startDate == null ? null : new Date(startDate.getTime()); + this.startDate = startDate; } public void setAccountId(Long accountId) { @@ -167,8 +163,8 @@ public class ListUsageRecordsCmd extends BaseListCmd { @Override public void execute() { Pair, Integer> usageRecords = _usageService.getUsageRecords(this); - ListResponse response = new ListResponse(); - List usageResponses = new ArrayList(); + ListResponse response = new ListResponse<>(); + List usageResponses = new ArrayList<>(); Map> resourceTagResponseMap = null; if (usageRecords != null) { //read the resource tags details for all the resources in usage data and store in Map diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageTypesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageTypesCmd.java index 15f9dd20e29..2772743c75a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageTypesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageTypesCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.usage; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; @@ -30,7 +29,6 @@ import com.cloud.user.Account; @APICommand(name = "listUsageTypes", description = "List Usage Types", responseObject = UsageTypeResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListUsageTypesCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ListUsageTypesCmd.class.getName()); @Override public long getEntityOwnerId() { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/RemoveRawUsageRecordsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/RemoveRawUsageRecordsCmd.java index 710a11c0d7f..3e698e61442 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/RemoveRawUsageRecordsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/RemoveRawUsageRecordsCmd.java @@ -29,11 +29,9 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SuccessResponse; -import org.apache.log4j.Logger; @APICommand(name = "removeRawUsageRecords", description = "Safely removes raw records from cloud_usage table", responseObject = SuccessResponse.class, since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RemoveRawUsageRecordsCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(RemoveRawUsageRecordsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/UpdateTrafficTypeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/UpdateTrafficTypeCmd.java index 103e58c4e03..c7b3c2b433b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/UpdateTrafficTypeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/UpdateTrafficTypeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.usage; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "updateTrafficType", description = "Updates traffic type of a physical network", responseObject = TrafficTypeResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateTrafficTypeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateTrafficTypeCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java index e8f5944e407..e2a2baecc86 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.context.CallContext; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.user.Account; import com.cloud.user.User; @@ -35,7 +34,6 @@ import com.cloud.user.User; @APICommand(name = "createUser", description = "Creates a user for an account that already exists", responseObject = UserResponse.class, requestHasSensitiveInfo = true, responseHasSensitiveInfo = true) public class CreateUserCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateUserCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java index a4f13d5e9c7..ddf21affb53 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.user; import javax.inject.Inject; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,6 @@ import com.cloud.user.User; @APICommand(name = "deleteUser", description = "Deletes a user for an account", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteUserCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteUserCmd.class.getName()); ///////////////////////////////////////////////////// @@ -86,11 +84,10 @@ public class DeleteUserCmd extends BaseCmd { public void execute() { CallContext.current().setEventDetails("UserId: " + getId()); boolean result = _regionService.deleteUser(this); - if (result) { - SuccessResponse response = new SuccessResponse(getCommandName()); - this.setResponseObject(response); - } else { + if (!result) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete user"); } + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java index f7a51d0b1d3..974c1c7bebe 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.user; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -39,7 +38,6 @@ import com.cloud.user.UserAccount; @APICommand(name = "disableUser", description = "Disables a user account", responseObject = UserResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DisableUserCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DisableUserCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java index f13eac8f2a9..77d8d530daf 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.admin.user; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.UserAccount; @APICommand(name = "enableUser", description = "Enables a user account", responseObject = UserResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class EnableUserCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(EnableUserCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java index 5fcad8068b1..3427cef3366 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.user; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -30,7 +29,6 @@ import com.cloud.user.UserAccount; @APICommand(name = "getUser", description = "Find user account by API key", responseObject = UserResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class GetUserCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(GetUserCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/GetUserKeysCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/GetUserKeysCmd.java index 253a55652ea..3a3414d95d8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/GetUserKeysCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/GetUserKeysCmd.java @@ -29,7 +29,6 @@ import org.apache.cloudstack.api.response.RegisterResponse; import org.apache.cloudstack.api.response.UserResponse; import java.util.Map; -import org.apache.log4j.Logger; @APICommand(name = "getUserKeys", description = "This command allows the user to query the seceret and API keys for the account", @@ -44,7 +43,6 @@ public class GetUserKeysCmd extends BaseCmd{ @Parameter(name= ApiConstants.ID, type = CommandType.UUID, entityType = UserResponse.class, required = true, description = "ID of the user whose keys are required") private Long id; - public static final Logger s_logger = Logger.getLogger(GetUserKeysCmd.class.getName()); public Long getID(){ return id; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java index a516a30e769..ef9e3fa2240 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java @@ -20,7 +20,6 @@ import com.cloud.server.ResourceIcon; import com.cloud.server.ResourceTag; import com.cloud.user.Account; import org.apache.cloudstack.api.response.ResourceIconResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import java.util.List; @APICommand(name = "listUsers", description = "Lists user accounts", responseObject = UserResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListUsersCmd extends BaseListAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListUsersCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/LockUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/LockUserCmd.java index df6ef4f7b0b..5c8bff0732a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/LockUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/LockUserCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.user; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -33,7 +32,6 @@ import com.cloud.user.UserAccount; @APICommand(name = "lockUser", description = "Locks a user account", responseObject = UserResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class LockUserCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(LockUserCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/MoveUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/MoveUserCmd.java index 56552ba95df..e57258a4571 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/MoveUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/MoveUserCmd.java @@ -32,21 +32,19 @@ import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.region.RegionService; import org.apache.commons.lang3.ObjectUtils; -import org.apache.log4j.Logger; import com.cloud.user.Account; import com.cloud.user.User; import com.google.common.base.Preconditions; @APICommand(name = "moveUser", - description = "Moves a user to another account", + description = "Moves a user to another account in the same domain.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.11", authorized = {RoleType.Admin}) public class MoveUserCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(MoveUserCmd.class.getName()); ///////////////////////////////////////////////////// @@ -56,18 +54,18 @@ public class MoveUserCmd extends BaseCmd { type = CommandType.UUID, entityType = UserResponse.class, required = true, - description = "id of the user to be deleted") + description = "id of the user to be moved.") private Long id; @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, - description = "Creates the user under the specified account. If no account is specified, the username will be used as the account name.") + description = "Moves the user under the specified account. If no account name is specified, it is necessary to provide an account id.") private String accountName; @Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, - description = "Creates the user under the specified domain. Has to be accompanied with the account parameter") + description = "Moves the user under the specified account. If no account id is specified, it is necessary to provide an account name.") private Long accountId; @Inject diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/RegisterCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/RegisterCmd.java index 4199015b9ca..b3e7d2bec82 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/RegisterCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/RegisterCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.user; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.User; description = "This command allows a user to register for the developer API, returning a secret key and an API key. This request is made through the integration API port, so it is a privileged command and must be made on behalf of a user. It is up to the implementer just how the username and password are entered, and then how that translates to an integration API request. Both secret key and API key should be returned to the user", requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RegisterCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(RegisterCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java index cb9f6e189f0..c9e1e934152 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.region.RegionService; -import org.apache.log4j.Logger; import com.cloud.user.Account; import com.cloud.user.User; @@ -37,7 +36,6 @@ import com.cloud.user.UserAccount; @APICommand(name = "updateUser", description = "Updates a user account", responseObject = UserResponse.class, requestHasSensitiveInfo = true, responseHasSensitiveInfo = true) public class UpdateUserCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateUserCmd.class.getName()); ///////////////////////////////////////////////////// @@ -68,7 +66,7 @@ public class UpdateUserCmd extends BaseCmd { @Parameter(name = ApiConstants.CURRENT_PASSWORD, type = CommandType.STRING, description = "Current password that was being used by the user. You must inform the current password when updating the password.", acceptedOnAdminPort = false) private String currentPassword; - @Parameter(name = ApiConstants.SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userApiKey") + @Parameter(name = ApiConstants.USER_SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userApiKey") private String secretKey; @Parameter(name = ApiConstants.TIMEZONE, diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/CreateVlanIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/CreateVlanIpRangeCmd.java index 66aefd46966..c0ba99a8233 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/CreateVlanIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/CreateVlanIpRangeCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.vlan; import com.cloud.utils.net.NetUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -40,10 +39,11 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; +import java.util.Objects; + @APICommand(name = "createVlanIpRange", description = "Creates a VLAN IP range.", responseObject = VlanIpRangeResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVlanIpRangeCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateVlanIpRangeCmd.class.getName()); ///////////////////////////////////////////////////// @@ -114,6 +114,9 @@ public class CreateVlanIpRangeCmd extends BaseCmd { @Parameter(name = ApiConstants.FOR_SYSTEM_VMS, type = CommandType.BOOLEAN, description = "true if IP range is set to system vms, false if not") private Boolean forSystemVms; + @Parameter(name = ApiConstants.FOR_NSX, type = CommandType.BOOLEAN, description = "true if the IP range is used for NSX resource", since = "4.20.0") + private boolean forNsx; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -154,8 +157,12 @@ public class CreateVlanIpRangeCmd extends BaseCmd { return startIp; } + public boolean isForNsx() { + return !Objects.isNull(forNsx) && forNsx; + } + public String getVlan() { - if (vlan == null || vlan.isEmpty()) { + if ((vlan == null || vlan.isEmpty()) && !isForNsx()) { vlan = "untagged"; } return vlan; @@ -226,10 +233,10 @@ public class CreateVlanIpRangeCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create vlan ip range"); } } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (InsufficientCapacityException ex) { - s_logger.info(ex); + logger.info(ex); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java index 7c122dfc22e..cac029f3aa1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.vlan; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.user.Account; @APICommand(name = "dedicatePublicIpRange", description = "Dedicates a Public IP range to an account", responseObject = VlanIpRangeResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DedicatePublicIpRangeCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DedicatePublicIpRangeCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DeleteVlanIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DeleteVlanIpRangeCmd.java index 15f0bde37a1..7ab0b053004 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DeleteVlanIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/DeleteVlanIpRangeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.vlan; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -29,10 +28,9 @@ import org.apache.cloudstack.api.response.VlanIpRangeResponse; import com.cloud.user.Account; -@APICommand(name = "deleteVlanIpRange", description = "Creates a VLAN IP range.", responseObject = SuccessResponse.class, +@APICommand(name = "deleteVlanIpRange", description = "Deletes a VLAN IP range.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVlanIpRangeCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteVlanIpRangeCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/ListVlanIpRangesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/ListVlanIpRangesCmd.java index 3b5370e3f15..c11b505c684 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/ListVlanIpRangesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/ListVlanIpRangesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.vlan; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listVlanIpRanges", description = "Lists all VLAN IP ranges.", responseObject = VlanIpRangeResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVlanIpRangesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListVlanIpRangesCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java index 846433a60fc..be4cea41cd8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.vlan; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,7 +31,6 @@ import com.cloud.user.Account; @APICommand(name = "releasePublicIpRange", description = "Releases a Public IP range back to the system pool", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ReleasePublicIpRangeCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ReleasePublicIpRangeCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/UpdateVlanIpRangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/UpdateVlanIpRangeCmd.java index caaf4c5ae01..df6d99f8e2a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/UpdateVlanIpRangeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vlan/UpdateVlanIpRangeCmd.java @@ -24,7 +24,6 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.VlanIpRangeResponse; -import org.apache.log4j.Logger; import com.cloud.dc.Vlan; import com.cloud.exception.ConcurrentOperationException; @@ -39,7 +38,6 @@ import com.cloud.utils.net.NetUtils; authorized = {RoleType.Admin}) public class UpdateVlanIpRangeCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVlanIpRangeCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -149,7 +147,7 @@ public class UpdateVlanIpRangeCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to Update vlan ip range"); } } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java index 1d53bbb39ad..ac63a5efac3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.vm; import java.util.List; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -46,7 +45,6 @@ import com.cloud.vm.VirtualMachine; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class AssignVMCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(AssignVMCmd.class.getName()); ///////////////////////////////////////////////////// @@ -133,7 +131,7 @@ public class AssignVMCmd extends BaseCmd { e.printStackTrace(); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } catch (Exception e) { - s_logger.error("Failed to move vm due to: " + e.getStackTrace()); + logger.error("Failed to move vm due to: " + e.getStackTrace()); if (e.getMessage() != null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to move vm due to " + e.getMessage()); } else if (e.getCause() != null) { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/DeployVMCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/DeployVMCmdByAdmin.java index acdc0e07427..6bb7657b86b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/DeployVMCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/DeployVMCmdByAdmin.java @@ -20,7 +20,6 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ClusterResponse; import org.apache.cloudstack.api.response.PodResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ResponseObject.ResponseView; @@ -34,7 +33,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "deployVirtualMachine", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", responseObject = UserVmResponse.class, responseView = ResponseView.Full, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DeployVMCmdByAdmin extends DeployVMCmd implements AdminCmd { - public static final Logger s_logger = Logger.getLogger(DeployVMCmdByAdmin.class.getName()); @Parameter(name = ApiConstants.POD_ID, type = CommandType.UUID, entityType = PodResponse.class, description = "destination Pod ID to deploy the VM to - parameter available for root admin only", since = "4.13") diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/DeployVnfApplianceCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/DeployVnfApplianceCmdByAdmin.java new file mode 100644 index 00000000000..5d2756c82fc --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/DeployVnfApplianceCmdByAdmin.java @@ -0,0 +1,34 @@ +// 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.vm; + +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.command.admin.AdminCmd; +import org.apache.cloudstack.api.command.user.vm.DeployVnfApplianceCmd; +import org.apache.cloudstack.api.response.UserVmResponse; + +@APICommand(name = "deployVnfAppliance", + description = "Creates and automatically starts a VNF appliance based on a service offering, disk offering, and template.", + responseObject = UserVmResponse.class, + responseView = ResponseObject.ResponseView.Full, + entityType = {VirtualMachine.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, + since = "4.19.0") +public class DeployVnfApplianceCmdByAdmin extends DeployVnfApplianceCmd implements AdminCmd { +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java index 4cd7f541c4e..a964e873bad 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.vm; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -43,7 +42,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "expungeVirtualMachine", description = "Expunge a virtual machine. Once expunged, it cannot be recoverd.", responseObject = SuccessResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ExpungeVMCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ExpungeVMCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/GetVMUserDataCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/GetVMUserDataCmd.java index 98af820201c..8745ef12ce4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/GetVMUserDataCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/GetVMUserDataCmd.java @@ -24,7 +24,6 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VMUserDataResponse; -import org.apache.log4j.Logger; import com.cloud.user.Account; import com.cloud.uservm.UserVm; @@ -32,7 +31,6 @@ import com.cloud.uservm.UserVm; @APICommand(name = "getVirtualMachineUserData", description = "Returns user data associated with the VM", responseObject = VMUserDataResponse.class, since = "4.4", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class GetVMUserDataCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(GetVMUserDataCmd.class); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java index 70233317cc5..ae6ceff26c7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportUnmanagedInstanceCmd.java @@ -41,7 +41,6 @@ import org.apache.cloudstack.vm.VmImportService; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -65,7 +64,6 @@ import com.cloud.vm.VmDetailConstants; authorized = {RoleType.Admin}, since = "4.14.0") public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { - public static final Logger LOGGER = Logger.getLogger(ImportUnmanagedInstanceCmd.class); @Inject public VmImportService vmImportService; @@ -84,7 +82,7 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, - description = "the hypervisor name of the instance") + description = "the name of the instance as it is known to the hypervisor") private String name; @Parameter(name = ApiConstants.DISPLAY_NAME, @@ -124,7 +122,7 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { type = CommandType.UUID, entityType = ServiceOfferingResponse.class, required = true, - description = "the ID of the service offering for the virtual machine") + description = "the service offering for the virtual machine") private Long serviceOfferingId; @Parameter(name = ApiConstants.NIC_NETWORK_LIST, @@ -154,7 +152,7 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN, - description = "VM is imported despite some of its NIC's MAC addresses are already present") + description = "VM is imported despite some of its NIC's MAC addresses are already present, in case the MAC address exists then a new MAC address is generated") private Boolean forced; ///////////////////////////////////////////////////// @@ -203,8 +201,8 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { for (Map entry : (Collection>)nicNetworkList.values()) { String nic = entry.get(VmDetailConstants.NIC); String networkUuid = entry.get(VmDetailConstants.NETWORK); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace(String.format("nic, '%s', goes on net, '%s'", nic, networkUuid)); + if (logger.isDebugEnabled()) { + logger.debug(String.format("nic, '%s', goes on net, '%s'", nic, networkUuid)); } if (StringUtils.isAnyEmpty(nic, networkUuid) || _entityMgr.findByUuid(Network.class, networkUuid) == null) { throw new InvalidParameterValueException(String.format("Network ID: %s for NIC ID: %s is invalid", networkUuid, nic)); @@ -221,8 +219,8 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { for (Map entry : (Collection>)nicIpAddressList.values()) { String nic = entry.get(VmDetailConstants.NIC); String ipAddress = StringUtils.defaultIfEmpty(entry.get(VmDetailConstants.IP4_ADDRESS), null); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace(String.format("nic, '%s', gets ip, '%s'", nic, ipAddress)); + if (logger.isDebugEnabled()) { + logger.debug(String.format("nic, '%s', gets ip, '%s'", nic, ipAddress)); } if (StringUtils.isEmpty(nic)) { throw new InvalidParameterValueException(String.format("NIC ID: '%s' is invalid for IP address mapping", nic)); @@ -246,8 +244,8 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { for (Map entry : (Collection>)dataDiskToDiskOfferingList.values()) { String disk = entry.get(VmDetailConstants.DISK); String offeringUuid = entry.get(VmDetailConstants.DISK_OFFERING); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace(String.format("disk, '%s', gets offering, '%s'", disk, offeringUuid)); + if (logger.isTraceEnabled()) { + logger.trace(String.format("disk, '%s', gets offering, '%s'", disk, offeringUuid)); } if (StringUtils.isAnyEmpty(disk, offeringUuid) || _entityMgr.findByUuid(DiskOffering.class, offeringUuid) == null) { throw new InvalidParameterValueException(String.format("Disk offering ID: %s for disk ID: %s is invalid", offeringUuid, disk)); @@ -279,7 +277,8 @@ public class ImportUnmanagedInstanceCmd extends BaseAsyncCmd { @Override public String getEventDescription() { - return "Importing unmanaged VM"; + String vmName = this.name; + return String.format("Importing unmanaged VM: %s", vmName); } public boolean isForced() { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportVmCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportVmCmd.java new file mode 100644 index 00000000000..6f148ff0ee4 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ImportVmCmd.java @@ -0,0 +1,265 @@ +// 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.vm; + +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.NetworkResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.VmwareDatacenterResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.vm.VmImportService; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import javax.inject.Inject; + +@APICommand(name = "importVm", + description = "Import virtual machine from a unmanaged host into CloudStack", + responseObject = UserVmResponse.class, + responseView = ResponseObject.ResponseView.Full, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true, + authorized = {RoleType.Admin}, + since = "4.19.0") +public class ImportVmCmd extends ImportUnmanagedInstanceCmd { + + @Inject + public VmImportService vmImportService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + + @Parameter(name = ApiConstants.ZONE_ID, + type = CommandType.UUID, + entityType = ZoneResponse.class, + required = true, + description = "the zone ID") + private Long zoneId; + + @Parameter(name = ApiConstants.USERNAME, + type = CommandType.STRING, + description = "the username for the host") + private String username; + + @Parameter(name = ApiConstants.PASSWORD, + type = CommandType.STRING, + description = "the password for the host") + private String password; + + @Parameter(name = ApiConstants.HOST, + type = CommandType.STRING, + description = "the host name or IP address") + private String host; + + @Parameter(name = ApiConstants.HYPERVISOR, + type = CommandType.STRING, + required = true, + description = "hypervisor type of the host") + private String hypervisor; + + @Parameter(name = ApiConstants.DISK_PATH, + type = CommandType.STRING, + description = "path of the disk image") + private String diskPath; + + @Parameter(name = ApiConstants.IMPORT_SOURCE, + type = CommandType.STRING, + required = true, + description = "Source location for Import" ) + private String importSource; + + @Parameter(name = ApiConstants.NETWORK_ID, + type = CommandType.UUID, + entityType = NetworkResponse.class, + description = "the network ID") + private Long networkId; + + @Parameter(name = ApiConstants.HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, description = "Host where local disk is located") + private Long hostId; + + @Parameter(name = ApiConstants.STORAGE_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, description = "Shared storage pool where disk is located") + private Long storagePoolId; + + @Parameter(name = ApiConstants.TEMP_PATH, + type = CommandType.STRING, + description = "Temp Path on external host for disk image copy" ) + private String tmpPath; + + // Import from VMware to KVM migration parameters + + @Parameter(name = ApiConstants.EXISTING_VCENTER_ID, + type = CommandType.UUID, + entityType = VmwareDatacenterResponse.class, + description = "(only for importing VMs from VMware to KVM) UUID of a linked existing vCenter") + private Long existingVcenterId; + + @Parameter(name = ApiConstants.HOST_IP, + type = BaseCmd.CommandType.STRING, + description = "(only for importing VMs from VMware to KVM) VMware ESXi host IP/Name.") + private String hostip; + + @Parameter(name = ApiConstants.VCENTER, + type = CommandType.STRING, + description = "(only for importing VMs from VMware to KVM) The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.") + private String vcenter; + + @Parameter(name = ApiConstants.DATACENTER_NAME, type = CommandType.STRING, + description = "(only for importing VMs from VMware to KVM) Name of VMware datacenter.") + private String datacenterName; + + @Parameter(name = ApiConstants.CLUSTER_NAME, type = CommandType.STRING, + description = "(only for importing VMs from VMware to KVM) Name of VMware cluster.") + private String clusterName; + + @Parameter(name = ApiConstants.CONVERT_INSTANCE_HOST_ID, type = CommandType.UUID, entityType = HostResponse.class, + description = "(only for importing VMs from VMware to KVM) optional - the host to perform the virt-v2v migration from VMware to KVM.") + private Long convertInstanceHostId; + + @Parameter(name = ApiConstants.CONVERT_INSTANCE_STORAGE_POOL_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, + description = "(only for importing VMs from VMware to KVM) optional - the temporary storage pool to perform the virt-v2v migration from VMware to KVM.") + private Long convertStoragePoolId; + + @Parameter(name = ApiConstants.FORCE_MS_TO_IMPORT_VM_FILES, type = CommandType.BOOLEAN, + description = "(only for importing VMs from VMware to KVM) optional - if true, forces MS to import VM file(s) to temporary storage, else uses KVM Host if ovftool is available, falls back to MS if not.") + private Boolean forceMsToImportVmFiles; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getZoneId() { + return zoneId; + } + + public Long getExistingVcenterId() { + return existingVcenterId; + } + + public String getHostIp() { + return hostip; + } + + public String getVcenter() { + return vcenter; + } + + public String getDatacenterName() { + return datacenterName; + } + + public String getClusterName() { + return clusterName; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getHost() { + return host; + } + + public Long getConvertInstanceHostId() { + return convertInstanceHostId; + } + + public Long getConvertStoragePoolId() { + return convertStoragePoolId; + } + + public Boolean getForceMsToImportVmFiles() { + return BooleanUtils.toBooleanDefaultIfNull(forceMsToImportVmFiles, false); + } + + public String getHypervisor() { + return hypervisor; + } + + public String getDiskPath() { + return diskPath; + } + + public String getImportSource() { + return importSource; + } + + public Long getHostId() { + return hostId; + } + + public Long getStoragePoolId() { + return storagePoolId; + } + + public String getTmpPath() { + return tmpPath; + } + + public Long getNetworkId() { + return networkId; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_VM_IMPORT; + } + + @Override + public String getEventDescription() { + String vmName = getName(); + if (ObjectUtils.anyNotNull(vcenter, existingVcenterId)) { + String msg = StringUtils.isNotBlank(vcenter) ? + String.format("external vCenter: %s - datacenter: %s", vcenter, datacenterName) : + String.format("existing vCenter Datacenter with ID: %s", existingVcenterId); + return String.format("Importing unmanaged VM: %s from %s - VM: %s", getDisplayName(), msg, vmName); + } + return String.format("Importing unmanaged VM: %s", vmName); + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + UserVmResponse response = vmImportService.importVm(this); + response.setResponseName(getCommandName()); + setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListAffectedVmsForStorageScopeChangeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListAffectedVmsForStorageScopeChangeCmd.java new file mode 100644 index 00000000000..d586a81b685 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListAffectedVmsForStorageScopeChangeCmd.java @@ -0,0 +1,77 @@ +/* + * 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.vm; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.VirtualMachineResponse; + +import com.cloud.vm.VirtualMachine; + +@APICommand(name = "listAffectedVmsForStorageScopeChange", + description = "List user and system VMs that need to be stopped and destroyed respectively for changing the scope of the storage pool from Zone to Cluster.", + responseObject = VirtualMachineResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.1", + authorized = {RoleType.Admin}) +public class ListAffectedVmsForStorageScopeChangeCmd extends BaseListCmd { + + @Parameter(name = ApiConstants.CLUSTER_ID, + type = CommandType.UUID, + entityType = ClusterResponse.class, + required = true, + description = "the Id of the cluster the scope of the storage pool is being changed to") + private Long clusterIdForScopeChange; + + @Parameter(name = ApiConstants.STORAGE_ID, + type = CommandType.UUID, + entityType = StoragePoolResponse.class, + required = true, + description = "the Id of the storage pool on which change scope operation is being done") + private Long storageId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getClusterIdForScopeChange() { + return clusterIdForScopeChange; + } + + public Long getStorageId() { + return storageId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() { + ListResponse response = _queryService.listAffectedVmsForStorageScopeChange(this); + response.setResponseName(getCommandName()); + response.setObjectName(VirtualMachine.class.getSimpleName().toLowerCase()); + setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java index 13b6748c74d..6932aa383fa 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListUnmanagedInstancesCmd.java @@ -32,7 +32,6 @@ import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.vm.UnmanagedInstanceTO; import org.apache.cloudstack.vm.VmImportService; -import org.apache.log4j.Logger; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -51,7 +50,6 @@ import com.cloud.user.Account; authorized = {RoleType.Admin}, since = "4.14.0") public class ListUnmanagedInstancesCmd extends BaseListCmd { - public static final Logger LOGGER = Logger.getLogger(ListUnmanagedInstancesCmd.class.getName()); @Inject public VmImportService vmImportService; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVMsCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVMsCmdByAdmin.java index 5b3e607416b..b48941e7d17 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVMsCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVMsCmdByAdmin.java @@ -27,14 +27,12 @@ import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.PodResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.log4j.Logger; import com.cloud.vm.VirtualMachine; @APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Full, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListVMsCmdByAdmin extends ListVMsCmd implements AdminCmd { - public static final Logger s_logger = Logger.getLogger(ListVMsCmdByAdmin.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVmsForImportCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVmsForImportCmd.java new file mode 100644 index 00000000000..f40f1c0cb4a --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVmsForImportCmd.java @@ -0,0 +1,132 @@ +// 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.vm; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.user.Account; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.vm.UnmanagedInstanceTO; +import org.apache.cloudstack.vm.VmImportService; + +import javax.inject.Inject; + +@APICommand(name = "listVmsForImport", + description = "Lists virtual machines on a unmanaged host", + responseObject = UnmanagedInstanceResponse.class, + responseView = ResponseObject.ResponseView.Full, + entityType = {UnmanagedInstanceTO.class}, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true, + authorized = {RoleType.Admin}, + since = "4.19.0") +public class ListVmsForImportCmd extends BaseListCmd { + + @Inject + public VmImportService vmImportService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ZONE_ID, + type = CommandType.UUID, + entityType = ZoneResponse.class, + required = true, + description = "the zone ID") + private Long zoneId; + + @Parameter(name = ApiConstants.USERNAME, + type = CommandType.STRING, + description = "the username for the host") + private String username; + + @Parameter(name = ApiConstants.PASSWORD, + type = CommandType.STRING, + description = "the password for the host") + private String password; + + @Parameter(name = ApiConstants.HOST, + type = CommandType.STRING, + required = true, + description = "the host name or IP address") + private String host; + + @Parameter(name = ApiConstants.HYPERVISOR, + type = CommandType.STRING, + required = true, + description = "hypervisor type of the host") + private String hypervisor; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getZoneId() { + return zoneId; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getHost() { + return host; + } + + public String getHypervisor() { + return hypervisor; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + ListResponse response = vmImportService.listVmsForImport(this); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + Account account = CallContext.current().getCallingAccount(); + if (account != null) { + return account.getId(); + } + return Account.ACCOUNT_ID_SYSTEM; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVnfAppliancesCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVnfAppliancesCmdByAdmin.java new file mode 100644 index 00000000000..1a820ab9a48 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ListVnfAppliancesCmdByAdmin.java @@ -0,0 +1,36 @@ +// 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.vm; + +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.admin.AdminCmd; + +import org.apache.cloudstack.api.command.user.vm.ListVnfAppliancesCmd; +import org.apache.cloudstack.api.response.UserVmResponse; + +@APICommand(name = "listVnfAppliances", description = "List VNF appliance owned by the account.", + responseObject = UserVmResponse.class, + responseView = ResponseView.Full, + entityType = {VirtualMachine.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin}, + since = "4.19.1") +public class ListVnfAppliancesCmdByAdmin extends ListVnfAppliancesCmd implements AdminCmd { +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java index b685b366cd1..8881a2bc354 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.vm; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -50,7 +49,6 @@ import com.cloud.vm.VirtualMachine; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class MigrateVMCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(MigrateVMCmd.class.getName()); ///////////////////////////////////////////////////// @@ -184,10 +182,10 @@ public class MigrateVMCmd extends BaseAsyncCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to migrate vm"); } } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (VirtualMachineMigrationException | ConcurrentOperationException | ManagementServerException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java index 549d02b4579..b736e860636 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java @@ -33,7 +33,6 @@ import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.SystemVmResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.commons.collections.MapUtils; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -52,7 +51,6 @@ import com.cloud.vm.VirtualMachine; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class MigrateVirtualMachineWithVolumeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(MigrateVirtualMachineWithVolumeCmd.class.getName()); ///////////////////////////////////////////////////// @@ -157,7 +155,7 @@ public class MigrateVirtualMachineWithVolumeCmd extends BaseAsyncCmd { Host destinationHost = _resourceService.getHost(getHostId()); // OfflineVmwareMigration: destination host would have to not be a required parameter for stopped VMs if (destinationHost == null) { - s_logger.error(String.format("Unable to find the host with ID [%s].", getHostId())); + logger.error(String.format("Unable to find the host with ID [%s].", getHostId())); throw new InvalidParameterValueException("Unable to find the specified host to migrate the VM."); } return destinationHost; @@ -193,10 +191,10 @@ public class MigrateVirtualMachineWithVolumeCmd extends BaseAsyncCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to migrate vm"); } } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ConcurrentOperationException | ManagementServerException | VirtualMachineMigrationException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java index b0698ed1e7a..f34d555dc70 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.vm; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -38,7 +37,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "recoverVirtualMachine", description = "Recovers a virtual machine.", responseObject = UserVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RecoverVMCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(RecoverVMCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/UnmanageVMInstanceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/UnmanageVMInstanceCmd.java index 20c7c536c45..bbcb8840f66 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/UnmanageVMInstanceCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vm/UnmanageVMInstanceCmd.java @@ -40,7 +40,6 @@ import org.apache.cloudstack.api.response.UnmanageVMInstanceResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.vm.UnmanagedVMsManager; -import org.apache.log4j.Logger; import javax.inject.Inject; @@ -53,7 +52,6 @@ import javax.inject.Inject; since = "4.15.0") public class UnmanageVMInstanceCmd extends BaseAsyncCmd { - public static final Logger LOGGER = Logger.getLogger(UnmanageVMInstanceCmd.class); @Inject private UnmanagedVMsManager unmanagedVMsManager; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/DestroyVolumeCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/DestroyVolumeCmdByAdmin.java index 44ce32f90c2..0840b4ce6f9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/DestroyVolumeCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/DestroyVolumeCmdByAdmin.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.volume; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,6 @@ import com.cloud.storage.Volume; responseHasSensitiveInfo = true) public class DestroyVolumeCmdByAdmin extends DestroyVolumeCmd implements AdminCmd { - public static final Logger s_logger = Logger.getLogger(DestroyVolumeCmdByAdmin.class.getName()); @Override public void execute() { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/ImportVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/ImportVolumeCmd.java new file mode 100644 index 00000000000..57c3ee586d3 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/ImportVolumeCmd.java @@ -0,0 +1,165 @@ +// 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.volume; + +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.DiskOfferingResponse; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.ProjectResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.storage.volume.VolumeImportUnmanageService; + +import javax.inject.Inject; + +@APICommand(name = "importVolume", + description = "Import an unmanaged volume from a storage pool on a host into CloudStack", + responseObject = VolumeResponse.class, + responseView = ResponseObject.ResponseView.Full, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true, + authorized = {RoleType.Admin}, + since = "4.19.1") +public class ImportVolumeCmd extends BaseAsyncCmd { + + @Inject + public VolumeImportUnmanageService volumeImportService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + + @Parameter(name = ApiConstants.PATH, + type = BaseCmd.CommandType.STRING, + required = true, + description = "the path of the volume") + private String path; + + @Parameter(name = ApiConstants.NAME, + type = BaseCmd.CommandType.STRING, + description = "the name of the volume. If not set, it will be set to the path of the volume.") + private String name; + + @Parameter(name = ApiConstants.STORAGE_ID, + type = BaseCmd.CommandType.UUID, + required = true, + entityType = StoragePoolResponse.class, + description = "the ID of the storage pool") + private Long storageId; + + @Parameter(name = ApiConstants.DISK_OFFERING_ID, + type = BaseCmd.CommandType.UUID, + entityType = DiskOfferingResponse.class, + description = "the ID of the disk offering linked to the volume") + private Long diskOfferingId; + + @Parameter(name = ApiConstants.ACCOUNT, + type = BaseCmd.CommandType.STRING, + description = "an optional account for the volume. Must be used with domainId.") + private String accountName; + + @Parameter(name = ApiConstants.DOMAIN_ID, + type = BaseCmd.CommandType.UUID, + entityType = DomainResponse.class, + description = "import volume to the domain specified") + private Long domainId; + + @Parameter(name = ApiConstants.PROJECT_ID, + type = BaseCmd.CommandType.UUID, + entityType = ProjectResponse.class, + description = "import volume for the project") + private Long projectId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getPath() { + return path; + } + + public String getName() { + return name; + } + + public Long getStorageId() { + return storageId; + } + + public Long getDiskOfferingId() { + return diskOfferingId; + } + + public String getAccountName() { + return accountName; + } + + public Long getDomainId() { + return domainId; + } + + public Long getProjectId() { + return projectId; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_VOLUME_IMPORT; + } + + @Override + public String getEventDescription() { + return String.format("Importing unmanaged Volume with path: %s", path); + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + VolumeResponse response = volumeImportService.importVolume(this); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + Long accountId = _accountService.finalyzeAccountId(accountName, domainId, projectId, true); + if (accountId == null) { + return CallContext.current().getCallingAccount().getId(); + } + return accountId; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/ListVolumesForImportCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/ListVolumesForImportCmd.java new file mode 100644 index 00000000000..dbe3d37e406 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/ListVolumesForImportCmd.java @@ -0,0 +1,93 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.volume; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.VolumeForImportResponse; +import org.apache.cloudstack.storage.volume.VolumeImportUnmanageService; +import org.apache.cloudstack.storage.volume.VolumeOnStorageTO; + +import javax.inject.Inject; + +@APICommand(name = "listVolumesForImport", + description = "Lists unmanaged volumes on a storage pool", + responseObject = VolumeForImportResponse.class, + responseView = ResponseObject.ResponseView.Full, + entityType = {VolumeOnStorageTO.class}, + requestHasSensitiveInfo = false, + responseHasSensitiveInfo = true, + authorized = {RoleType.Admin}, + since = "4.19.1") +public class ListVolumesForImportCmd extends BaseListCmd { + + @Inject + public VolumeImportUnmanageService volumeImportService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.STORAGE_ID, + type = BaseCmd.CommandType.UUID, + required = true, + entityType = StoragePoolResponse.class, + description = "the ID of the storage pool") + private Long storageId; + + @Parameter(name = ApiConstants.PATH, + type = BaseCmd.CommandType.STRING, + description = "the path of the volume on the storage pool") + private String path; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getStorageId() { + return storageId; + } + + public String getPath() { + return path; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + ListResponse response = volumeImportService.listVolumesForImport(this); + response.setResponseName(getCommandName()); + setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/RecoverVolumeCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/RecoverVolumeCmdByAdmin.java index f51aeec9719..e276c8a00b6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/RecoverVolumeCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/RecoverVolumeCmdByAdmin.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.volume; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,6 @@ import com.cloud.storage.Volume; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RecoverVolumeCmdByAdmin extends RecoverVolumeCmd implements AdminCmd { - public static final Logger s_logger = Logger.getLogger(RecoverVolumeCmdByAdmin.class.getName()); @Override public void execute() { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/UnmanageVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/UnmanageVolumeCmd.java new file mode 100644 index 00000000000..dcc8b2af8d7 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/volume/UnmanageVolumeCmd.java @@ -0,0 +1,127 @@ +// +// 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.volume; + +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.storage.Volume; +import com.cloud.user.Account; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.storage.volume.VolumeImportUnmanageService; + +import javax.inject.Inject; + +@APICommand(name = "unmanageVolume", + description = "Unmanage a volume on storage pool.", + entityType = {Volume.class}, + responseObject = SuccessResponse.class, + requestHasSensitiveInfo = false, + authorized = {RoleType.Admin}, + since = "4.19.1") +public class UnmanageVolumeCmd extends BaseAsyncCmd { + + @Inject + public VolumeImportUnmanageService volumeImportService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, + type = CommandType.UUID, + entityType = VolumeResponse.class, + required = true, + description = "The ID of the volume to unmanage") + private Long volumeId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public Long getVolumeId() { + return volumeId; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_VOLUME_UNMANAGE; + } + + @Override + public String getEventDescription() { + return String.format("Unmanaging Volume with ID %s", volumeId); + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, + ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException { + try { + boolean result = volumeImportService.unmanageVolume(volumeId); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to unmanage the volume"); + } + + } catch (Exception e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getLocalizedMessage()); + } + } + + @Override + public long getEntityOwnerId() { + Volume volume = _responseGenerator.findVolumeById(volumeId); + if (volume != null) { + return volume.getAccountId(); + } + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Volume; + } + + @Override + public Long getApiResourceId() { + return volumeId; + } + +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayByAdminCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayByAdminCmd.java index b5ba70cf5e2..1b2163853ec 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayByAdminCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayByAdminCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.vpc; import org.apache.commons.lang3.BooleanUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.network.vpc.VpcGateway; since = "4.17.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreatePrivateGatewayByAdminCmd extends CreatePrivateGatewayCmd implements AdminCmd { - public static final Logger s_logger = Logger.getLogger(CreatePrivateGatewayByAdminCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java index b69e7f4a828..dd5c815238e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java @@ -24,12 +24,16 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.Network; +import com.cloud.network.VirtualRouterProvider; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -45,10 +49,18 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.network.vpc.VpcOffering; import com.cloud.user.Account; +import static com.cloud.network.Network.Service.Dhcp; +import static com.cloud.network.Network.Service.Dns; +import static com.cloud.network.Network.Service.Lb; +import static com.cloud.network.Network.Service.StaticNat; +import static com.cloud.network.Network.Service.SourceNat; +import static com.cloud.network.Network.Service.PortForwarding; +import static com.cloud.network.Network.Service.NetworkACL; +import static com.cloud.network.Network.Service.UserData; + @APICommand(name = "createVPCOffering", description = "Creates VPC offering", responseObject = VpcOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateVPCOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -62,7 +74,6 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { @Parameter(name = ApiConstants.SUPPORTED_SERVICES, type = CommandType.LIST, - required = true, collectionType = CommandType.STRING, description = "services supported by the vpc offering") private List supportedServices; @@ -101,6 +112,24 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { since = "4.13") private List zoneIds; + @Parameter(name = ApiConstants.FOR_NSX, + type = CommandType.BOOLEAN, + description = "true if network offering is meant to be used for NSX, false otherwise.", + since = "4.20.0") + private Boolean forNsx; + + @Parameter(name = ApiConstants.NSX_MODE, + type = CommandType.STRING, + description = "Indicates the mode with which the network will operate. Valid option: NATTED or ROUTED", + since = "4.20.0") + private String nsxMode; + + @Parameter(name = ApiConstants.NSX_SUPPORT_LB, + type = CommandType.BOOLEAN, + description = "true if network offering for NSX VPC offering supports Load balancer service.", + since = "4.20.0") + private Boolean nsxSupportsLbService; + @Parameter(name = ApiConstants.ENABLE, type = CommandType.BOOLEAN, description = "set to true if the offering is to be enabled during creation. Default is false", @@ -120,21 +149,49 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { } public List getSupportedServices() { + if (!isForNsx() && CollectionUtils.isEmpty(supportedServices)) { + throw new InvalidParameterValueException("Supported services needs to be provided"); + } + if (isForNsx()) { + supportedServices = new ArrayList<>(List.of( + Dhcp.getName(), + Dns.getName(), + StaticNat.getName(), + SourceNat.getName(), + NetworkACL.getName(), + PortForwarding.getName(), + UserData.getName() + )); + if (getNsxSupportsLbService()) { + supportedServices.add(Lb.getName()); + } + } return supportedServices; } + public boolean isForNsx() { + return BooleanUtils.isTrue(forNsx); + } + + public String getNsxMode() { + return nsxMode; + } + + public boolean getNsxSupportsLbService() { + return org.apache.commons.lang3.BooleanUtils.isTrue(nsxSupportsLbService); + } + public Map> getServiceProviders() { - Map> serviceProviderMap = null; - if (serviceProviderList != null && !serviceProviderList.isEmpty()) { - serviceProviderMap = new HashMap>(); + Map> serviceProviderMap = new HashMap<>(); + if (serviceProviderList != null && !serviceProviderList.isEmpty() && !isForNsx()) { Collection> servicesCollection = serviceProviderList.values(); Iterator> iter = servicesCollection.iterator(); while (iter.hasNext()) { Map obj = iter.next(); - if (s_logger.isTraceEnabled()) { - s_logger.trace("service provider entry specified: " + obj); + if (logger.isTraceEnabled()) { + logger.trace("service provider entry specified: " + obj); } - HashMap services = (HashMap)obj; + HashMap services = (HashMap) obj; String service = services.get("service"); String provider = services.get("provider"); List providerList = null; @@ -146,11 +203,31 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { providerList.add(provider); serviceProviderMap.put(service, providerList); } + } else if (Boolean.TRUE.equals(forNsx)) { + getServiceProviderMapForNsx(serviceProviderMap); } return serviceProviderMap; } + private void getServiceProviderMapForNsx(Map> serviceProviderMap) { + List unsupportedServices = List.of("Vpn", "BaremetalPxeService", "SecurityGroup", "Connectivity", + "Gateway", "Firewall"); + List routerSupported = List.of("Dhcp", "Dns", "UserData"); + List allServices = Network.Service.listAllServices().stream().map(Network.Service::getName).collect(Collectors.toList()); + for (String service : allServices) { + if (unsupportedServices.contains(service)) + continue; + if (routerSupported.contains(service)) + serviceProviderMap.put(service, List.of(VirtualRouterProvider.Type.VPCVirtualRouter.name())); + else + serviceProviderMap.put(service, List.of(Network.Provider.Nsx.getName())); + } + if (!getNsxSupportsLbService()) { + serviceProviderMap.remove(Lb.getName()); + } + } + public Map> getServiceCapabilityList() { return serviceCapabilityList; } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java index d6c3cac68c7..d104edc381b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.vpc; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class DeletePrivateGatewayCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeletePrivateGatewayCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/DeleteVPCOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/DeleteVPCOfferingCmd.java index aba4c857b0b..6aa0c3f3afc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/DeleteVPCOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/DeleteVPCOfferingCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.vpc; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteVPCOffering", description = "Deletes VPC offering", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVPCOfferingCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteVPCOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/ListPrivateGatewaysCmdByAdminCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/ListPrivateGatewaysCmdByAdminCmd.java new file mode 100644 index 00000000000..1211bd3311c --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/ListPrivateGatewaysCmdByAdminCmd.java @@ -0,0 +1,33 @@ +// 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.vpc; + + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.command.admin.AdminCmd; +import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd; +import org.apache.cloudstack.api.response.PrivateGatewayResponse; + +import com.cloud.network.vpc.VpcGateway; + +@APICommand(name = "listPrivateGateways", description = "List private gateways", responseObject = PrivateGatewayResponse.class, entityType = {VpcGateway.class}, + responseView = ResponseObject.ResponseView.Full, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class ListPrivateGatewaysCmdByAdminCmd extends ListPrivateGatewaysCmd implements AdminCmd { + +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java index 12babad504e..b59837281ef 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.VpcOfferingResponse; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.domain.Domain; @@ -40,7 +39,6 @@ import com.cloud.user.Account; @APICommand(name = "updateVPCOffering", description = "Updates VPC offering", responseObject = VpcOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVPCOfferingCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVPCOfferingCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/CreateZoneCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/CreateZoneCmd.java index aca3e00d095..24660e41ed9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/CreateZoneCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/CreateZoneCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.zone; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "createZone", description = "Creates a Zone.", responseObject = ZoneResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateZoneCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateZoneCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/DeleteZoneCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/DeleteZoneCmd.java index c530e999bf8..b89636c6fe5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/DeleteZoneCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/DeleteZoneCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.admin.zone; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -33,7 +32,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteZone", description = "Deletes a Zone.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteZoneCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteZoneCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/MarkDefaultZoneForAccountCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/MarkDefaultZoneForAccountCmd.java index 264aea3f449..5d3f5dcd47f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/MarkDefaultZoneForAccountCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/MarkDefaultZoneForAccountCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.admin.zone; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "markDefaultZoneForAccount", description = "Marks a default zone for this account", responseObject = AccountResponse.class, since = "4.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class MarkDefaultZoneForAccountCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(MarkDefaultZoneForAccountCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/UpdateZoneCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/UpdateZoneCmd.java index 1379050cbf7..1b2793d3e15 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/UpdateZoneCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/zone/UpdateZoneCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.zone; import java.util.List; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "updateZone", description = "Updates a Zone.", responseObject = ZoneResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateZoneCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateZoneCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java index 57c0e484843..2fbcb6df1cc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java @@ -24,7 +24,6 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.response.ProjectRoleResponse; import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -44,7 +43,6 @@ import com.cloud.projects.ProjectAccount; @APICommand(name = "addAccountToProject", description = "Adds account to a project", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddAccountToProjectCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(AddAccountToProjectCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/account/DeleteAccountFromProjectCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/account/DeleteAccountFromProjectCmd.java index 34935f506ec..5e0977938a3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/account/DeleteAccountFromProjectCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/account/DeleteAccountFromProjectCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.account; import java.util.List; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,6 @@ import com.cloud.projects.Project; @APICommand(name = "deleteAccountFromProject", description = "Deletes account from the project", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAccountFromProjectCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteAccountFromProjectCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/account/DeleteUserFromProjectCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/account/DeleteUserFromProjectCmd.java index 596fb876008..8319911c5c8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/account/DeleteUserFromProjectCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/account/DeleteUserFromProjectCmd.java @@ -32,7 +32,6 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -41,7 +40,6 @@ import com.cloud.projects.Project; @APICommand(name = "deleteUserFromProject", description = "Deletes user from the project", responseObject = SuccessResponse.class, since = "4.15.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.DomainAdmin, RoleType.ResourceAdmin, RoleType.User}) public class DeleteUserFromProjectCmd extends BaseAsyncCmd { - public static final Logger LOGGER = Logger.getLogger(DeleteUserFromProjectCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java index 66a4d91172a..0a962b19e4f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java @@ -31,7 +31,7 @@ import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ResourceIconResponse; -import org.apache.log4j.Logger; +import org.apache.commons.collections.CollectionUtils; import com.cloud.exception.InvalidParameterValueException; import com.cloud.server.ResourceIcon; @@ -41,7 +41,6 @@ import com.cloud.user.Account; @APICommand(name = "listAccounts", description = "Lists accounts and provides detailed account information for listed accounts", responseObject = AccountResponse.class, responseView = ResponseView.Restricted, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListAccountsCmd.class.getName()); private static final String s_name = "listaccountsresponse"; ///////////////////////////////////////////////////// @@ -75,6 +74,9 @@ public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserC description = "flag to display the resource icon for accounts") private Boolean showIcon; + @Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for resource type to return usage", since = "4.20.0") + private String tag; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -118,10 +120,14 @@ public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserC return dv; } - public Boolean getShowIcon() { + public boolean getShowIcon() { return showIcon != null ? showIcon : false; } + public String getTag() { + return tag; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -136,12 +142,17 @@ public class ListAccountsCmd extends BaseListDomainResourcesCmd implements UserC ListResponse response = _queryService.searchForAccounts(this); response.setResponseName(getCommandName()); setResponseObject(response); - if (response != null && response.getCount() > 0 && getShowIcon()) { - updateAccountResponse(response.getResponses()); - } + updateAccountResponse(response.getResponses()); } - private void updateAccountResponse(List response) { + protected void updateAccountResponse(List response) { + if (CollectionUtils.isEmpty(response)) { + return; + } + _resourceLimitService.updateTaggedResourceLimitsAndCountsForAccounts(response, getTag()); + if (!getShowIcon()) { + return; + } for (AccountResponse accountResponse : response) { ResourceIcon resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.Account, accountResponse.getObjectId()); if (resourceIcon == null) { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListProjectAccountsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListProjectAccountsCmd.java index 3d50fc553b8..21aedc7d772 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListProjectAccountsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/account/ListProjectAccountsCmd.java @@ -26,14 +26,12 @@ import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.ProjectRoleResponse; import org.apache.cloudstack.api.response.UserResponse; -import org.apache.log4j.Logger; import com.cloud.user.Account; @APICommand(name = "listProjectAccounts", description = "Lists project's accounts", responseObject = ProjectResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListProjectAccountsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListProjectAccountsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java index 75b83b40f3e..5ea14478516 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.address; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -65,7 +64,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AssociateIPAddrCmd extends BaseAsyncCreateCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(AssociateIPAddrCmd.class.getName()); private static final String s_name = "associateipaddressresponse"; ///////////////////////////////////////////////////// @@ -325,11 +323,11 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd implements UserCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to allocate IP address"); } } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (InsufficientAddressCapacityException ex) { - s_logger.info(ex); - s_logger.trace(ex); + logger.info(ex); + logger.trace(ex); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java index b31520e1b88..f4c06e512f0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.address; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -39,17 +38,20 @@ import com.cloud.user.Account; @APICommand(name = "disassociateIpAddress", description = "Disassociates an IP address from the account.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { IpAddress.class }) public class DisassociateIPAddrCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DisassociateIPAddrCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IPAddressResponse.class, required = true, description = "the ID of the public IP address" - + " to disassociate") + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IPAddressResponse.class, description = "the ID of the public IP address" + + " to disassociate. Mutually exclusive with the ipaddress parameter") private Long id; + @Parameter(name=ApiConstants.IP_ADDRESS, type=CommandType.STRING, since="4.19.0", description="IP Address to be disassociated." + + " Mutually exclusive with the id parameter") + private String ipAddress; + // unexposed parameter needed for events logging @Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, expose = false) private Long ownerId; @@ -59,7 +61,18 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { ///////////////////////////////////////////////////// public Long getIpAddressId() { - return id; + if (id != null & ipAddress != null) { + throw new InvalidParameterValueException("id parameter is mutually exclusive with ipaddress parameter"); + } + + if (id != null) { + return id; + } else if (ipAddress != null) { + IpAddress ip = getIpAddressByIp(ipAddress); + return ip.getId(); + } + + throw new InvalidParameterValueException("Please specify either IP address or IP address ID"); } ///////////////////////////////////////////////////// @@ -68,12 +81,13 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { @Override public void execute() throws InsufficientAddressCapacityException { - CallContext.current().setEventDetails("IP ID: " + getIpAddressId()); + Long ipAddressId = getIpAddressId(); + CallContext.current().setEventDetails("IP ID: " + ipAddressId); boolean result = false; - if (!isPortable(id)) { - result = _networkService.releaseIpAddress(getIpAddressId()); + if (!isPortable()) { + result = _networkService.releaseIpAddress(ipAddressId); } else { - result = _networkService.releasePortableIpAddress(getIpAddressId()); + result = _networkService.releasePortableIpAddress(ipAddressId); } if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); @@ -85,7 +99,7 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { @Override public String getEventType() { - if (!isPortable(id)) { + if (!isPortable()) { return EventTypes.EVENT_NET_IP_RELEASE; } else { return EventTypes.EVENT_PORTABLE_IP_RELEASE; @@ -100,10 +114,7 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { if (ownerId == null) { - IpAddress ip = getIpAddress(id); - if (ip == null) { - throw new InvalidParameterValueException("Unable to find IP address by ID=" + id); - } + IpAddress ip = getIpAddress(); ownerId = ip.getAccountId(); } @@ -120,11 +131,11 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { @Override public Long getSyncObjId() { - IpAddress ip = getIpAddress(id); + IpAddress ip = getIpAddress(); return ip.getAssociatedWithNetworkId(); } - private IpAddress getIpAddress(long id) { + private IpAddress getIpAddressById(Long id) { IpAddress ip = _entityMgr.findById(IpAddress.class, id); if (ip == null) { @@ -134,6 +145,29 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { } } + private IpAddress getIpAddressByIp(String ipAddress) { + IpAddress ip = _networkService.getIp(ipAddress); + if (ip == null) { + throw new InvalidParameterValueException("Unable to find IP address by IP address=" + ipAddress); + } else { + return ip; + } + } + + private IpAddress getIpAddress() { + if (id != null & ipAddress != null) { + throw new InvalidParameterValueException("id parameter is mutually exclusive with ipaddress parameter"); + } + + if (id != null) { + return getIpAddressById(id); + } else if (ipAddress != null){ + return getIpAddressByIp(ipAddress); + } + + throw new InvalidParameterValueException("Please specify either IP address or IP address ID"); + } + @Override public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.IpAddress; @@ -144,8 +178,8 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { return getIpAddressId(); } - private boolean isPortable(long id) { - IpAddress ip = getIpAddress(id); + private boolean isPortable() { + IpAddress ip = getIpAddress(); return ip.isPortable(); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java index 22eb70cc0c2..5760ca3ba1c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java @@ -19,7 +19,7 @@ package org.apache.cloudstack.api.command.user.address; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; +import org.apache.commons.lang.BooleanUtils; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -43,7 +43,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listPublicIpAddresses", description = "Lists all public IP addresses", responseObject = IPAddressResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { IpAddress.class }) public class ListPublicIpAddressesCmd extends BaseListRetrieveOnlyResourceCountCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListPublicIpAddressesCmd.class.getName()); private static final String s_name = "listpublicipaddressesresponse"; @@ -106,6 +105,9 @@ public class ListPublicIpAddressesCmd extends BaseListRetrieveOnlyResourceCountC @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "list resources by display flag; only ROOT admin is eligible to pass this parameter", since = "4.4", authorized = {RoleType.Admin}) private Boolean display; + @Parameter(name = ApiConstants.FOR_SYSTEM_VMS, type = CommandType.BOOLEAN, description = "true if range is dedicated for system VMs", since = "4.20.0") + private Boolean forSystemVMs; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -177,6 +179,10 @@ public class ListPublicIpAddressesCmd extends BaseListRetrieveOnlyResourceCountC return state; } + public boolean getForSystemVMs() { + return BooleanUtils.isTrue(forSystemVMs); + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/address/ListQuarantinedIpsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/address/ListQuarantinedIpsCmd.java new file mode 100644 index 00000000000..cc014702c81 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/address/ListQuarantinedIpsCmd.java @@ -0,0 +1,51 @@ +// 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.user.address; + +import com.cloud.network.PublicIpQuarantine; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.IpQuarantineResponse; +import org.apache.cloudstack.api.response.ListResponse; + +@APICommand(name = "listQuarantinedIps", responseObject = IpQuarantineResponse.class, description = "List public IP addresses in quarantine.", since = "4.19", + entityType = {PublicIpQuarantine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.DomainAdmin}) +public class ListQuarantinedIpsCmd extends BaseListCmd { + + @Parameter(name = ApiConstants.SHOW_REMOVED, type = CommandType.BOOLEAN, description = "Show IPs removed from quarantine.") + private boolean showRemoved = false; + + @Parameter(name = ApiConstants.SHOW_INACTIVE, type = CommandType.BOOLEAN, description = "Show IPs that are no longer in quarantine.") + private boolean showInactive = false; + + public boolean isShowRemoved() { + return showRemoved; + } + public boolean isShowInactive() { + return showInactive; + } + + @Override + public void execute() { + ListResponse response = _queryService.listQuarantinedIps(this); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/address/ReleaseIPAddrCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/address/ReleaseIPAddrCmd.java index eb908300283..effe45c51ed 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/address/ReleaseIPAddrCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/address/ReleaseIPAddrCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.address; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,6 @@ import com.cloud.network.IpAddress; responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ReleaseIPAddrCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ReleaseIPAddrCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/address/RemoveQuarantinedIpCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/address/RemoveQuarantinedIpCmd.java new file mode 100644 index 00000000000..82e8373d93a --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/address/RemoveQuarantinedIpCmd.java @@ -0,0 +1,72 @@ +// 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.user.address; + +import com.cloud.network.PublicIpQuarantine; +import com.cloud.user.Account; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.IpQuarantineResponse; +import org.apache.cloudstack.api.response.SuccessResponse; + +@APICommand(name = "removeQuarantinedIp", responseObject = IpQuarantineResponse.class, description = "Removes a public IP address from quarantine. Only IPs in active " + + "quarantine can be removed.", + since = "4.19", entityType = {PublicIpQuarantine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.DomainAdmin}) +public class RemoveQuarantinedIpCmd extends BaseCmd { + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IpQuarantineResponse.class, description = "The ID of the public IP address in active quarantine. " + + "Either the IP address is informed, or the ID of the IP address in quarantine.") + private Long id; + + @Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, description = "The public IP address in active quarantine. Either the IP address is informed, or the ID" + + " of the IP address in quarantine.") + private String ipAddress; + + @Parameter(name = ApiConstants.REMOVAL_REASON, type = CommandType.STRING, required = true, description = "The reason for removing the public IP address from quarantine " + + "prematurely.") + private String removalReason; + + public Long getId() { + return id; + } + + public String getIpAddress() { + return ipAddress; + } + + public String getRemovalReason() { + return removalReason; + } + + @Override + public void execute() { + _networkService.removePublicIpAddressFromQuarantine(this); + final SuccessResponse response = new SuccessResponse(); + response.setResponseName(getCommandName()); + response.setSuccess(true); + setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/address/ReserveIPAddrCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/address/ReserveIPAddrCmd.java index 5e72986fb58..e323d413b9a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/address/ReserveIPAddrCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/address/ReserveIPAddrCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.address; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -51,7 +50,6 @@ import com.cloud.user.Account; responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ReserveIPAddrCmd extends BaseCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ReserveIPAddrCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java index 7055e1d5cb2..194967e2e4a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.address; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -42,7 +41,6 @@ import com.cloud.user.Account; @APICommand(name = "updateIpAddress", description = "Updates an IP address", responseObject = IPAddressResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { IpAddress.class }) public class UpdateIPAddrCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateIPAddrCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/address/UpdateQuarantinedIpCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/address/UpdateQuarantinedIpCmd.java new file mode 100644 index 00000000000..b3b71c33781 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/address/UpdateQuarantinedIpCmd.java @@ -0,0 +1,75 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.address; + +import com.cloud.network.PublicIpQuarantine; +import com.cloud.user.Account; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.IpQuarantineResponse; + +import java.util.Date; + +@APICommand(name = "updateQuarantinedIp", responseObject = IpQuarantineResponse.class, description = "Updates the quarantine end date for the given public IP address.", + since = "4.19", entityType = {PublicIpQuarantine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.DomainAdmin}) +public class UpdateQuarantinedIpCmd extends BaseCmd { + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = IpQuarantineResponse.class, description = "The ID of the public IP address in " + + "active quarantine.") + private Long id; + + @Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, description = "The public IP address in active quarantine. Either the IP address is informed, or the ID" + + " of the IP address in quarantine.") + private String ipAddress; + + @Parameter(name = ApiConstants.END_DATE, type = BaseCmd.CommandType.DATE, required = true, description = "The date when the quarantine will no longer be active.") + private Date endDate; + + public Long getId() { + return id; + } + + public String getIpAddress() { + return ipAddress; + } + + public Date getEndDate() { + return endDate; + } + + @Override + public void execute() { + PublicIpQuarantine publicIpQuarantine = _networkService.updatePublicIpAddressInQuarantine(this); + if (publicIpQuarantine == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update public IP quarantine."); + } + IpQuarantineResponse response = _responseGenerator.createQuarantinedIpsResponse(publicIpQuarantine); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java index 60dbc2a6e9a..ee0a38ef35d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.affinitygroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "createAffinityGroup", responseObject = AffinityGroupResponse.class, description = "Creates an affinity/anti-affinity group", entityType = {AffinityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateAffinityGroupCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java index c8967b08020..2f24158cadb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.affinitygroup; import org.apache.cloudstack.api.response.ProjectResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -40,7 +39,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class, entityType = {AffinityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAffinityGroupCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteAffinityGroupCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupTypesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupTypesCmd.java index 2d6f45cc06e..c90294171b3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupTypesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupTypesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.affinitygroup; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.affinity.AffinityGroupTypeResponse; import org.apache.cloudstack.api.APICommand; @@ -31,7 +30,6 @@ import com.cloud.user.Account; @APICommand(name = "listAffinityGroupTypes", description = "Lists affinity group types available", responseObject = AffinityGroupTypeResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAffinityGroupTypesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListAffinityGroupTypesCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java index ed6c3145198..ee23e3794ce 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.affinitygroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -31,7 +30,6 @@ import org.apache.cloudstack.api.response.UserVmResponse; @APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class, entityType = {AffinityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAffinityGroupsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListAffinityGroupsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java index c70e4fbda66..6cd9bce6259 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.EnumSet; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -55,7 +54,6 @@ import com.cloud.vm.VirtualMachine; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateVMAffinityGroupCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVMAffinityGroupCmd.class.getName()); private static final String s_name = "updatevirtualmachineresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java index eff93522b62..a000e265f93 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.autoscale; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -43,7 +42,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateAutoScalePolicyCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateAutoScalePolicyCmd.class.getName()); private static final String s_name = "autoscalepolicyresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java index cdbe153f017..7c9362d4b69 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.autoscale; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -45,7 +44,6 @@ import com.cloud.network.rules.LoadBalancer; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateAutoScaleVmGroupCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateAutoScaleVmGroupCmd.class.getName()); private static final String s_name = "autoscalevmgroupresponse"; @@ -233,7 +231,7 @@ public class CreateAutoScaleVmGroupCmd extends BaseAsyncCreateCmd { } } catch (Exception ex) { // TODO what will happen if Resource Layer fails in a step in between - s_logger.warn("Failed to create autoscale vm group", ex); + logger.warn("Failed to create autoscale vm group", ex); } finally { if (!success || vmGroup == null) { _autoScaleService.deleteAutoScaleVmGroup(getEntityId(), true); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java index db6ccd9ce53..2d84b20c582 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.Map; import org.apache.commons.collections.MapUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -51,7 +50,6 @@ import com.cloud.network.as.AutoScaleVmProfile; responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") public class CreateAutoScaleVmProfileCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateAutoScaleVmProfileCmd.class.getName()); private static final String s_name = "autoscalevmprofileresponse"; @@ -102,7 +100,7 @@ public class CreateAutoScaleVmProfileCmd extends BaseAsyncCreateCmd { description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. " + "This binary data must be base64 encoded before adding it to the request. " + "Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. " + - "Using HTTP POST(via POST body), you can send up to 1MB of data after base64 encoding." + + "Using HTTP POST (via POST body), you can send up to 1MB of data after base64 encoding. " + "You also need to change vm.userdata.max.length value", length = 1048576, since = "4.18.0") diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java index 77bc15b1e0f..0ffb9afdac4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.autoscale; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -39,7 +38,6 @@ import com.cloud.network.as.Condition; @APICommand(name = "createCondition", description = "Creates a condition for VM auto scaling", responseObject = ConditionResponse.class, entityType = {Condition.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateConditionCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateConditionCmd.class.getName()); private static final String s_name = "conditionresponse"; // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java index cf5ff366096..cee9460dbe6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.autoscale; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -38,7 +37,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteAutoScalePolicy", description = "Deletes a autoscale policy.", responseObject = SuccessResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAutoScalePolicyCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteAutoScalePolicyCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// // /////////////////////////////////////////////////// @@ -93,7 +91,7 @@ public class DeleteAutoScalePolicyCmd extends BaseAsyncCmd { SuccessResponse response = new SuccessResponse(getCommandName()); setResponseObject(response); } else { - s_logger.warn("Failed to delete autoscale policy " + getId()); + logger.warn("Failed to delete autoscale policy " + getId()); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete AutoScale Policy"); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java index badfcc0957e..6bf2157533e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.autoscale; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -38,7 +37,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteAutoScaleVmGroup", description = "Deletes a autoscale vm group.", responseObject = SuccessResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAutoScaleVmGroupCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteAutoScaleVmGroupCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// // /////////////////////////////////////////////////// @@ -103,7 +101,7 @@ public class DeleteAutoScaleVmGroupCmd extends BaseAsyncCmd { SuccessResponse response = new SuccessResponse(getCommandName()); setResponseObject(response); } else { - s_logger.warn("Failed to delete autoscale vm group " + getId()); + logger.warn("Failed to delete autoscale vm group " + getId()); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete autoscale vm group"); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java index 06bf7a9d378..b90f6aa8ffa 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.autoscale; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -38,7 +37,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteAutoScaleVmProfile", description = "Deletes a autoscale vm profile.", responseObject = SuccessResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAutoScaleVmProfileCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteAutoScaleVmProfileCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// // /////////////////////////////////////////////////// @@ -92,7 +90,7 @@ public class DeleteAutoScaleVmProfileCmd extends BaseAsyncCmd { SuccessResponse response = new SuccessResponse(getCommandName()); setResponseObject(response); } else { - s_logger.warn("Failed to delete autoscale vm profile " + getId()); + logger.warn("Failed to delete autoscale vm profile " + getId()); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete autoscale vm profile"); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java index 840484e45ad..9590012e037 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.autoscale; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -39,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteCondition", description = "Removes a condition for VM auto scaling", responseObject = SuccessResponse.class, entityType = {Condition.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteConditionCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteConditionCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// @@ -59,14 +57,14 @@ public class DeleteConditionCmd extends BaseAsyncCmd { try { result = _autoScaleService.deleteCondition(getId()); } catch (ResourceInUseException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_IN_USE_ERROR, ex.getMessage()); } if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); setResponseObject(response); } else { - s_logger.warn("Failed to delete condition " + getId()); + logger.warn("Failed to delete condition " + getId()); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete condition."); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java index b0daf2ec664..2414c0d82b6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.autoscale; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "disableAutoScaleVmGroup", description = "Disables an AutoScale Vm Group", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DisableAutoScaleVmGroupCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DisableAutoScaleVmGroupCmd.class.getName()); private static final String s_name = "disableautoscalevmGroupresponse"; // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java index b6f2a82ac49..96d329d3e0c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.autoscale; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "enableAutoScaleVmGroup", description = "Enables an AutoScale Vm Group", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class EnableAutoScaleVmGroupCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(EnableAutoScaleVmGroupCmd.class.getName()); private static final String s_name = "enableautoscalevmGroupresponse"; // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java index dc0baf4c786..4935889c525 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.autoscale; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.network.as.AutoScalePolicy; @APICommand(name = "listAutoScalePolicies", description = "Lists autoscale policies.", responseObject = AutoScalePolicyResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAutoScalePoliciesCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListAutoScalePoliciesCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java index 8404fbbb49f..6aa4abcccd8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.autoscale; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,6 @@ import com.cloud.network.as.AutoScaleVmGroup; @APICommand(name = "listAutoScaleVmGroups", description = "Lists autoscale vm groups.", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAutoScaleVmGroupsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListAutoScaleVmGroupsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java index 435471faf13..bcaea273ce8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.autoscale; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,6 @@ import com.cloud.network.as.AutoScaleVmProfile; @APICommand(name = "listAutoScaleVmProfiles", description = "Lists autoscale vm profiles.", responseObject = AutoScaleVmProfileResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAutoScaleVmProfilesCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListAutoScaleVmProfilesCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java index fc1ca7097c8..febf937d75f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java @@ -20,7 +20,6 @@ package org.apache.cloudstack.api.command.user.autoscale; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.network.as.Condition; @APICommand(name = "listConditions", description = "List Conditions for VM auto scaling", responseObject = ConditionResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListConditionsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListConditionsCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListCountersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListCountersCmd.java index 7da8bd40b61..d03584fd63d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListCountersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/ListCountersCmd.java @@ -20,7 +20,6 @@ package org.apache.cloudstack.api.command.user.autoscale; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "listCounters", description = "List the counters for VM auto scaling", responseObject = CounterResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListCountersCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListCountersCmd.class.getName()); private static final String s_name = "counterresponse"; // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java index a64b5cb1680..927a9191fcc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.autoscale; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -41,7 +40,6 @@ import com.cloud.user.Account; @APICommand(name = "updateAutoScalePolicy", description = "Updates an existing autoscale policy.", responseObject = AutoScalePolicyResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateAutoScalePolicyCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateAutoScalePolicyCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java index 87cd1fd3f4e..69ae8aa36aa 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.autoscale; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -42,7 +41,6 @@ import com.cloud.user.Account; @APICommand(name = "updateAutoScaleVmGroup", description = "Updates an existing autoscale vm group.", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateAutoScaleVmGroupCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateAutoScaleVmGroupCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java index 3e65d38e520..0b73fd91b52 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java @@ -20,7 +20,6 @@ package org.apache.cloudstack.api.command.user.autoscale; import java.util.HashMap; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -46,7 +45,6 @@ import com.cloud.user.Account; @APICommand(name = "updateAutoScaleVmProfile", description = "Updates an existing autoscale vm profile.", responseObject = AutoScaleVmProfileResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateAutoScaleVmProfileCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateAutoScaleVmProfileCmd.class.getName()); // /////////////////////////////////////////////////// @@ -97,7 +95,7 @@ public class UpdateAutoScaleVmProfileCmd extends BaseAsyncCustomIdCmd { description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. " + "This binary data must be base64 encoded before adding it to the request. " + "Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. " + - "Using HTTP POST(via POST body), you can send up to 1MB of data after base64 encoding." + + "Using HTTP POST (via POST body), you can send up to 1MB of data after base64 encoding. " + "You also need to change vm.userdata.max.length value", length = 1048576, since = "4.18.0") diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateConditionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateConditionCmd.java index e946dd370c1..4ed8244ff0c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateConditionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateConditionCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.autoscale; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -41,7 +40,6 @@ import com.cloud.user.Account; authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.18.0") public class UpdateConditionCmd extends BaseAsyncCmd { - public static final Logger LOGGER = Logger.getLogger(UpdateConditionCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// @@ -69,7 +67,7 @@ public class UpdateConditionCmd extends BaseAsyncCmd { response.setResponseName(getCommandName()); setResponseObject(response); } catch (ResourceInUseException ex) { - LOGGER.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_IN_USE_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java index 8597d97278c..7d87cc37e6c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java @@ -116,6 +116,7 @@ public class ListBackupsCmd extends BaseListProjectAndAccountResourcesCmd { Pair, Integer> result = backupManager.listBackups(this); setupResponseBackupList(result.first(), result.second()); } catch (Exception e) { + logger.debug("Exception while listing backups", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/CreateBucketCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/CreateBucketCmd.java new file mode 100644 index 00000000000..d2c91e57871 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/CreateBucketCmd.java @@ -0,0 +1,200 @@ +// 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.user.bucket; + +import com.cloud.event.EventTypes; +import com.cloud.exception.ResourceAllocationException; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.storage.object.Bucket; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCreateCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.user.UserCmd; +import org.apache.cloudstack.api.response.BucketResponse; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.ObjectStoreResponse; +import org.apache.cloudstack.api.response.ProjectResponse; +import org.apache.cloudstack.context.CallContext; + +@APICommand(name = "createBucket", responseObject = BucketResponse.class, + description = "Creates a bucket in the specified object storage pool. ", responseView = ResponseView.Restricted, + entityType = {Bucket.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.0", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class CreateBucketCmd extends BaseAsyncCreateCmd implements UserCmd { + private static final String s_name = "createbucketresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ACCOUNT, + type = CommandType.STRING, + description = "the account associated with the bucket. Must be used with the domainId parameter.") + private String accountName; + + @Parameter(name = ApiConstants.PROJECT_ID, + type = CommandType.UUID, + entityType = ProjectResponse.class, + description = "the project associated with the bucket. Mutually exclusive with account parameter") + private Long projectId; + + @Parameter(name = ApiConstants.DOMAIN_ID, + type = CommandType.UUID, + entityType = DomainResponse.class, + description = "the domain ID associated with the bucket. If used with the account parameter" + + " returns the bucket associated with the account for the specified domain.") + private Long domainId; + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true,description = "the name of the bucket") + private String bucketName; + + @Parameter(name = ApiConstants.OBJECT_STORAGE_ID, type = CommandType.UUID, + entityType = ObjectStoreResponse.class, required = true, + description = "Id of the Object Storage Pool where bucket is created") + private long objectStoragePoolId; + + @Parameter(name = ApiConstants.QUOTA, type = CommandType.INTEGER,description = "Bucket Quota in GB") + private Integer quota; + + @Parameter(name = ApiConstants.ENCRYPTION, type = CommandType.BOOLEAN, description = "Enable bucket encryption") + private boolean encryption; + + @Parameter(name = ApiConstants.VERSIONING, type = CommandType.BOOLEAN, description = "Enable bucket versioning") + private boolean versioning; + + @Parameter(name = ApiConstants.OBJECT_LOCKING, type = CommandType.BOOLEAN, description = "Enable object locking in bucket") + private boolean objectLocking; + + @Parameter(name = ApiConstants.POLICY, type = CommandType.STRING,description = "The Bucket access policy") + private String policy; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getAccountName() { + return accountName; + } + + public Long getDomainId() { + return domainId; + } + + public String getBucketName() { + return bucketName; + } + + private Long getProjectId() { + return projectId; + } + + public long getObjectStoragePoolId() { + return objectStoragePoolId; + } + + public Integer getQuota() { + return quota; + } + + public boolean isEncryption() { + return encryption; + } + + public boolean isVersioning() { + return versioning; + } + + public boolean isObjectLocking() { + return objectLocking; + } + + public String getPolicy() { + return policy; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + @Override + public String getCommandName() { + return s_name; + } + + public static String getResultObjectName() { + return "bucket"; + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Bucket; + } + + @Override + public long getEntityOwnerId() { + Long accountId = _accountService.finalyzeAccountId(accountName, domainId, projectId, true); + if (accountId == null) { + return CallContext.current().getCallingAccount().getId(); + } + + return accountId; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_BUCKET_CREATE; + } + + @Override + public String getEventDescription() { + return "creating bucket: " + getBucketName(); + } + + @Override + public void create() throws ResourceAllocationException { + Bucket bucket = _bucketService.allocBucket(this); + if (bucket != null) { + setEntityId(bucket.getId()); + setEntityUuid(bucket.getUuid()); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create bucket"); + } + } + + @Override + public void execute() { + CallContext.current().setEventDetails("Bucket Id: " + getEntityUuid()); + + Bucket bucket; + try { + bucket = _bucketService.createBucket(this); + } catch (Exception e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } + if (bucket != null) { + BucketResponse response = _responseGenerator.createBucketResponse(bucket); + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create bucket with name: "+getBucketName()); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/DeleteBucketCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/DeleteBucketCmd.java new file mode 100644 index 00000000000..8cd2790e4ae --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/DeleteBucketCmd.java @@ -0,0 +1,92 @@ +// 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.user.bucket; + +import com.cloud.exception.ConcurrentOperationException; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.storage.object.Bucket; +import com.cloud.user.Account; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ACL; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.BucketResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; + +@APICommand(name = "deleteBucket", description = "Deletes an empty Bucket.", responseObject = SuccessResponse.class, entityType = {Bucket.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.0", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class DeleteBucketCmd extends BaseCmd { + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @ACL(accessType = AccessType.OperateEntry) + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=BucketResponse.class, + required=true, description="The ID of the Bucket") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + public static String getResultObjectName() { + return "bucket"; + } + + @Override + public long getEntityOwnerId() { + Bucket Bucket = _entityMgr.findById(Bucket.class, getId()); + if (Bucket != null) { + return Bucket.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public Long getApiResourceId() { + return id; + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Bucket; + } + + @Override + public void execute() throws ConcurrentOperationException { + CallContext.current().setEventDetails("Bucket Id: " + this._uuidMgr.getUuid(Bucket.class, getId())); + boolean result = _bucketService.deleteBucket(id, CallContext.current().getCallingAccount()); + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setSuccess(result); + setResponseObject(response); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/ListBucketsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/ListBucketsCmd.java new file mode 100644 index 00000000000..bda0c7ed381 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/ListBucketsCmd.java @@ -0,0 +1,98 @@ +// 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.user.bucket; + +import org.apache.cloudstack.storage.object.Bucket; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.user.UserCmd; +import org.apache.cloudstack.api.response.BucketResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; + +import java.util.List; + +@APICommand(name = "listBuckets", description = "Lists all Buckets.", responseObject = BucketResponse.class, responseView = ResponseView.Restricted, entityType = { + Bucket.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.0", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class ListBucketsCmd extends BaseListTaggedResourcesCmd implements UserCmd { + + private static final String s_name = "listbucketsresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = BucketResponse.class, description = "the ID of the bucket") + private Long id; + + @Parameter(name = ApiConstants.IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = BucketResponse.class, description = "the IDs of the Buckets, mutually exclusive with id") + private List ids; + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the bucket") + private String bucketName; + + @Parameter(name = ApiConstants.OBJECT_STORAGE_ID, type = CommandType.UUID, entityType = StoragePoolResponse.class, description = "the ID of the object storage pool, available to ROOT admin only", authorized = { + RoleType.Admin}) + private Long objectStorageId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public String getBucketName() { + return bucketName; + } + + public Long getObjectStorageId() { + return objectStorageId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Bucket; + } + + @Override + public void execute() { + ListResponse response = _queryService.searchForBuckets(this); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + + public List getIds() { + return ids; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/UpdateBucketCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/UpdateBucketCmd.java new file mode 100644 index 00000000000..8e281b20e91 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/bucket/UpdateBucketCmd.java @@ -0,0 +1,130 @@ +// 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.user.bucket; + +import com.cloud.exception.ConcurrentOperationException; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.storage.object.Bucket; +import com.cloud.user.Account; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ACL; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.BucketResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; + +@APICommand(name = "updateBucket", description = "Updates Bucket properties", responseObject = SuccessResponse.class, entityType = {Bucket.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.0", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class UpdateBucketCmd extends BaseCmd { + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @ACL(accessType = AccessType.OperateEntry) + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=BucketResponse.class, + required=true, description="The ID of the Bucket") + private Long id; + + @Parameter(name = ApiConstants.VERSIONING, type = CommandType.BOOLEAN, description = "Enable/Disable Bucket Versioning") + private Boolean versioning; + + @Parameter(name = ApiConstants.ENCRYPTION, type = CommandType.BOOLEAN, description = "Enable/Disable Bucket encryption") + private Boolean encryption; + + @Parameter(name = ApiConstants.POLICY, type = CommandType.STRING, description = "Bucket Access Policy") + private String policy; + + @Parameter(name = ApiConstants.QUOTA, type = CommandType.INTEGER,description = "Bucket Quota in GB") + private Integer quota; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public Boolean getVersioning() { + return versioning; + } + + public Boolean getEncryption() { + return encryption; + } + + public String getPolicy() { + return policy; + } + + public Integer getQuota() { + return quota; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + public static String getResultObjectName() { + return "bucket"; + } + + @Override + public long getEntityOwnerId() { + Bucket Bucket = _entityMgr.findById(Bucket.class, getId()); + if (Bucket != null) { + return Bucket.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public Long getApiResourceId() { + return id; + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Bucket; + } + + @Override + public void execute() throws ConcurrentOperationException { + CallContext.current().setEventDetails("Bucket Id: " + this._uuidMgr.getUuid(Bucket.class, getId())); + boolean result = false; + try { + result = _bucketService.updateBucket(this, CallContext.current().getCallingAccount()); + } catch (Exception e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Error while updating bucket. "+e.getMessage()); + } + if(result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update bucket"); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java index 65920a97c98..cf25dfaf5b5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java @@ -23,14 +23,12 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.response.CapabilitiesResponse; import org.apache.cloudstack.config.ApiServiceConfiguration; -import org.apache.log4j.Logger; import com.cloud.user.Account; @APICommand(name = "listCapabilities", description = "Lists capabilities", responseObject = CapabilitiesResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListCapabilitiesCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ListCapabilitiesCmd.class.getName()); @Override diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/consoleproxy/CreateConsoleEndpointCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/consoleproxy/CreateConsoleEndpointCmd.java index 11e84f1bef9..63b47e163b6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/consoleproxy/CreateConsoleEndpointCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/consoleproxy/CreateConsoleEndpointCmd.java @@ -35,7 +35,6 @@ import org.apache.cloudstack.consoleproxy.ConsoleAccessManager; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.utils.consoleproxy.ConsoleAccessUtils; import org.apache.commons.collections.MapUtils; -import org.apache.log4j.Logger; import javax.inject.Inject; import java.util.Map; @@ -46,7 +45,6 @@ import java.util.Map; authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class CreateConsoleEndpointCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateConsoleEndpointCmd.class.getName()); @Inject private ConsoleAccessManager consoleManager; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java index cdff7882e65..669b1782e9e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.event; import java.util.Date; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,7 +38,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ArchiveEventsCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ArchiveEventsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java index 9d049ac5f06..c9c3f1d6955 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.event; import java.util.Date; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,7 +38,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteEventsCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteEventsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/event/ListEventTypesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/event/ListEventTypesCmd.java index dd0f5179278..e3f14f711ce 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/event/ListEventTypesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/event/ListEventTypesCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.event; import java.util.ArrayList; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseCmd; @@ -30,7 +29,6 @@ import com.cloud.user.Account; @APICommand(name = "listEventTypes", description = "List Event Types", responseObject = EventTypeResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListEventTypesCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ListEventTypesCmd.class.getName()); @Override public long getEntityOwnerId() { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java index 89f1c7090e0..b5273c64922 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java @@ -24,14 +24,12 @@ import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.EventResponse; import org.apache.cloudstack.api.response.ListResponse; -import org.apache.log4j.Logger; import com.cloud.event.Event; @APICommand(name = "listEvents", description = "A command to list events.", responseObject = EventResponse.class, entityType = {Event.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListEventsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListEventsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java index bedb073b880..8cbbcea6a59 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -48,7 +47,6 @@ import com.cloud.utils.net.NetUtils; @APICommand(name = "createEgressFirewallRule", description = "Creates a egress firewall rule for a given network ", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements FirewallRule { - public static final Logger s_logger = Logger.getLogger(CreateEgressFirewallRuleCmd.class.getName()); // /////////////////////////////////////////////////// @@ -257,10 +255,10 @@ public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements F } } catch (NetworkRuleConflictException ex) { String message = "Network rule conflict: "; - if (!s_logger.isTraceEnabled()) { - s_logger.info(message + ex.getMessage()); + if (!logger.isTraceEnabled()) { + logger.info(message + ex.getMessage()); } else { - s_logger.trace(message, ex); + logger.trace(message, ex); } throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage()); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java index b77041ee174..56c818f832b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.firewall; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -46,7 +45,6 @@ import com.cloud.utils.net.NetUtils; @APICommand(name = "createFirewallRule", description = "Creates a firewall rule for a given IP address", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements FirewallRule { - public static final Logger s_logger = Logger.getLogger(CreateFirewallRuleCmd.class.getName()); // /////////////////////////////////////////////////// @@ -96,11 +94,35 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal return ipAddressId; } + public void setIpAddressId(Long ipAddressId) { + this.ipAddressId = ipAddressId; + } + @Override public String getProtocol() { return protocol.trim(); } + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public Integer getPublicStartPort() { + return publicStartPort; + } + + public void setPublicStartPort(Integer publicStartPort) { + this.publicStartPort = publicStartPort; + } + + public Integer getPublicEndPort() { + return publicEndPort; + } + + public void setPublicEndPort(Integer publicEndPort) { + this.publicEndPort = publicEndPort; + } + @Override public List getSourceCidrList() { if (cidrlist != null) { @@ -248,7 +270,7 @@ public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements Firewal setEntityUuid(result.getUuid()); } } catch (NetworkRuleConflictException ex) { - s_logger.trace("Network Rule Conflict: ", ex); + logger.trace("Network Rule Conflict: ", ex); throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage(), ex); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java index 5e136210150..3545b3d21fb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.firewall; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -54,7 +53,6 @@ import com.cloud.vm.VirtualMachine; VirtualMachine.class, IpAddress.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements PortForwardingRule { - public static final Logger s_logger = Logger.getLogger(CreatePortForwardingRuleCmd.class.getName()); // /////////////////////////////////////////////////// @@ -352,7 +350,7 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P setEntityId(result.getId()); setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException ex) { - s_logger.trace("Network Rule Conflict: ", ex); + logger.trace("Network Rule Conflict: ", ex); throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage(), ex); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java index f0ba8a92d01..b93d943eab9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.firewall; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -41,7 +40,6 @@ import com.cloud.network.rules.FirewallRule; @APICommand(name = "deleteEgressFirewallRule", description = "Deletes an egress firewall rule", responseObject = SuccessResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteEgressFirewallRuleCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteEgressFirewallRuleCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java index da1f6b62eca..c4a4dfd75cb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.firewall; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -40,7 +39,6 @@ import com.cloud.network.rules.FirewallRule; @APICommand(name = "deleteFirewallRule", description = "Deletes a firewall rule", responseObject = SuccessResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteFirewallRuleCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteFirewallRuleCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java index aebf8da159b..267d18d8a8a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.firewall; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -39,7 +38,6 @@ import com.cloud.network.rules.PortForwardingRule; @APICommand(name = "deletePortForwardingRule", description = "Deletes a port forwarding rule", responseObject = SuccessResponse.class, entityType = {PortForwardingRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeletePortForwardingRuleCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeletePortForwardingRuleCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java index c8c0e85252b..aa0fd28fdec 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java @@ -20,7 +20,6 @@ package org.apache.cloudstack.api.command.user.firewall; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listEgressFirewallRules", description = "Lists all egress firewall rules for network ID.", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListEgressFirewallRulesCmd extends BaseListTaggedResourcesCmd implements IListFirewallRulesCmd { - public static final Logger s_logger = Logger.getLogger(ListEgressFirewallRulesCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java index f79b77893d2..19a05b15890 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.firewall; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -38,7 +37,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listFirewallRules", description = "Lists all firewall rules for an IP address.", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListFirewallRulesCmd extends BaseListTaggedResourcesCmd implements IListFirewallRulesCmd { - public static final Logger s_logger = Logger.getLogger(ListFirewallRulesCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java index 3a942c485fc..a2e9152a9e4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.firewall; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listPortForwardingRules", description = "Lists all port forwarding rules for an IP address.", responseObject = FirewallRuleResponse.class, entityType = {PortForwardingRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListPortForwardingRulesCmd extends BaseListTaggedResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListPortForwardingRulesCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdateEgressFirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdateEgressFirewallRuleCmd.java index 1aa06074367..a8db4ec2b29 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdateEgressFirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdateEgressFirewallRuleCmd.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.FirewallResponse; import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -37,7 +36,6 @@ import com.cloud.network.rules.FirewallRule.TrafficType; @APICommand(name = "updateEgressFirewallRule", description = "Updates egress firewall rule ", responseObject = FirewallResponse.class, since = "4.4", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateEgressFirewallRuleCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateEgressFirewallRuleCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdateFirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdateFirewallRuleCmd.java index b39efa01350..89c9bc891eb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdateFirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdateFirewallRuleCmd.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.FirewallResponse; import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -37,7 +36,6 @@ import com.cloud.network.rules.FirewallRule.TrafficType; @APICommand(name = "updateFirewallRule", description = "Updates firewall rule ", responseObject = FirewallResponse.class, since = "4.4", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateFirewallRuleCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateFirewallRuleCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java index 2afc0bb66ad..3fb66bd861f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java @@ -24,7 +24,6 @@ import org.apache.cloudstack.api.BaseAsyncCustomIdCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -38,7 +37,6 @@ import com.cloud.utils.net.Ip; description = "Updates a port forwarding rule. Only the private port and the virtual machine can be updated.", entityType = {PortForwardingRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdatePortForwardingRuleCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdatePortForwardingRuleCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCategoriesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCategoriesCmd.java index 18a209011c1..c74514d662c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCategoriesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCategoriesCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.guest; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listOsCategories", description = "Lists all supported OS categories for this cloud.", responseObject = GuestOSCategoryResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListGuestOsCategoriesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListGuestOsCategoriesCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java index 9d6cd438561..b31a4669220 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.BooleanUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listOsTypes", description = "Lists all supported OS types for this cloud.", responseObject = GuestOSResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListGuestOsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListGuestOsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/CreateIpv6FirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/CreateIpv6FirewallRuleCmd.java index d4c59cd8d47..4e3cf4621ef 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/CreateIpv6FirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/CreateIpv6FirewallRuleCmd.java @@ -32,7 +32,6 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.context.CallContext; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -50,7 +49,6 @@ import com.cloud.utils.net.NetUtils; responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class CreateIpv6FirewallRuleCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateIpv6FirewallRuleCmd.class.getName()); // /////////////////////////////////////////////////// @@ -224,7 +222,7 @@ public class CreateIpv6FirewallRuleCmd extends BaseAsyncCreateCmd { setEntityId(result.getId()); setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException e) { - s_logger.trace("Network Rule Conflict: ", e); + logger.trace("Network Rule Conflict: ", e); throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, e.getMessage(), e); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/DeleteIpv6FirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/DeleteIpv6FirewallRuleCmd.java index 5e176a3fabf..aaee19b5948 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/DeleteIpv6FirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/DeleteIpv6FirewallRuleCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ResourceUnavailableException; @@ -41,7 +40,6 @@ import com.cloud.user.Account; responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class DeleteIpv6FirewallRuleCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteIpv6FirewallRuleCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/ListIpv6FirewallRulesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/ListIpv6FirewallRulesCmd.java index 23941316275..7ade2e3ed04 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/ListIpv6FirewallRulesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/ListIpv6FirewallRulesCmd.java @@ -29,7 +29,6 @@ import org.apache.cloudstack.api.response.FirewallResponse; import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.NetworkResponse; -import org.apache.log4j.Logger; import com.cloud.network.rules.FirewallRule; import com.cloud.utils.Pair; @@ -41,7 +40,6 @@ import com.cloud.utils.Pair; responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ListIpv6FirewallRulesCmd extends BaseListTaggedResourcesCmd implements IListFirewallRulesCmd { - public static final Logger s_logger = Logger.getLogger(ListIpv6FirewallRulesCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/UpdateIpv6FirewallRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/UpdateIpv6FirewallRuleCmd.java index 49765c58daf..2d63d703dc5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/UpdateIpv6FirewallRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ipv6/UpdateIpv6FirewallRuleCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.FirewallResponse; import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ResourceUnavailableException; @@ -41,7 +40,6 @@ import com.cloud.user.Account; responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class UpdateIpv6FirewallRuleCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateIpv6FirewallRuleCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java index cdc72de4a10..d795fbabb52 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/AttachIsoCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.iso; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,7 +38,6 @@ import com.cloud.uservm.UserVm; @APICommand(name = "attachIso", description = "Attaches an ISO to a virtual machine.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class AttachIsoCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(AttachIsoCmd.class.getName()); private static final String s_name = "attachisoresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java index b7c13ce4adb..2db7b7e1eb9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.iso; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ResponseObject.ResponseView; @@ -26,6 +25,5 @@ import org.apache.cloudstack.api.response.TemplateResponse; @APICommand(name = "copyIso", description = "Copies an ISO from one zone to another.", responseObject = TemplateResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CopyIsoCmd extends CopyTemplateCmd { - public static final Logger s_logger = Logger.getLogger(CopyIsoCmd.class.getName()); private static final String s_name = "copyisoresponse"; } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DeleteIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DeleteIsoCmd.java index 504e7c1b5cf..feae31026b9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DeleteIsoCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DeleteIsoCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.iso; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteIso", description = "Deletes an ISO file.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteIsoCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteIsoCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java index e3b22c4a49f..292e1c6f099 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/DetachIsoCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.iso; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.uservm.UserVm; @APICommand(name = "detachIso", description = "Detaches any ISO file (if any) currently attached to a virtual machine.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DetachIsoCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(DetachIsoCmd.class.getName()); private static final String s_name = "detachisoresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java index 03ba2fab722..5db680066a6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ExtractIsoCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.iso; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -38,7 +37,6 @@ import com.cloud.user.Account; @APICommand(name = "extractIso", description = "Extracts an ISO", responseObject = ExtractResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ExtractIsoCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ExtractIsoCmd.class.getName()); ///////////////////////////////////////////////////// @@ -130,7 +128,7 @@ public class ExtractIsoCmd extends BaseAsyncCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to extract ISO"); } } catch (InternalErrorException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/GetUploadParamsForIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/GetUploadParamsForIsoCmd.java index a7a418f5a86..01a47f22b72 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/GetUploadParamsForIsoCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/GetUploadParamsForIsoCmd.java @@ -29,6 +29,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.GetUploadParamsResponse; import org.apache.cloudstack.api.response.GuestOSResponse; import org.apache.cloudstack.context.CallContext; +import org.apache.commons.lang3.StringUtils; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -54,7 +55,6 @@ public class GetUploadParamsForIsoCmd extends AbstractGetUploadParamsCmd { @Parameter(name = ApiConstants.DISPLAY_TEXT, type = BaseCmd.CommandType.STRING, - required = true, description = "the display text of the ISO. This is usually used for display purposes.", length = 4096) private String displayText; @@ -85,7 +85,7 @@ public class GetUploadParamsForIsoCmd extends AbstractGetUploadParamsCmd { } public String getDisplayText() { - return displayText; + return StringUtils.isBlank(displayText) ? getName() : displayText; } public Boolean isFeatured() { @@ -117,7 +117,7 @@ public class GetUploadParamsForIsoCmd extends AbstractGetUploadParamsCmd { response.setResponseName(getCommandName()); setResponseObject(response); } catch (ResourceAllocationException | MalformedURLException e) { - s_logger.error("Exception while registering ISO", e); + logger.error("Exception while registering ISO", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Exception while registering ISO: " + e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ListIsoPermissionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ListIsoPermissionsCmd.java index fbbe0880aef..6f220c774b8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ListIsoPermissionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ListIsoPermissionsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.iso; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd; @@ -40,10 +39,6 @@ public class ListIsoPermissionsCmd extends BaseListTemplateOrIsoPermissionsCmd i return "iso"; } - @Override - protected Logger getLogger() { - return Logger.getLogger(ListIsoPermissionsCmd.class.getName()); - } @Override protected boolean templateIsCorrectType(VirtualMachineTemplate template) { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java index 90ecaa47de0..04dcbf8ca96 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.iso; import com.cloud.server.ResourceIcon; import com.cloud.server.ResourceTag; import org.apache.cloudstack.api.response.ResourceIconResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -41,7 +40,6 @@ import java.util.List; @APICommand(name = "listIsos", description = "Lists all available ISO files.", responseObject = TemplateResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListIsosCmd extends BaseListTaggedResourcesCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListIsosCmd.class.getName()); private static final String s_name = "listisosresponse"; @@ -134,6 +132,10 @@ public class ListIsosCmd extends BaseListTaggedResourcesCmd implements UserCmd { return showUnique != null && showUnique; } + public Long getImageStoreId() { + return null; + } + public Boolean getShowIcon () { return showIcon != null ? showIcon : false; } @@ -191,4 +193,8 @@ public class ListIsosCmd extends BaseListTaggedResourcesCmd implements UserCmd { templateResponse.setResourceIconResponse(iconResponse); } } + + public Long getStoragePoolId() { + return null; + }; } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java index ecab3930e8b..becfdcd653d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmd.java @@ -35,7 +35,6 @@ import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.exception.ResourceAllocationException; import com.cloud.template.VirtualMachineTemplate; @@ -43,7 +42,6 @@ import com.cloud.template.VirtualMachineTemplate; @APICommand(name = "registerIso", responseObject = TemplateResponse.class, description = "Registers an existing ISO into the CloudStack Cloud.", responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RegisterIsoCmd extends BaseCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(RegisterIsoCmd.class.getName()); private static final String s_name = "registerisoresponse"; @@ -177,6 +175,9 @@ public class RegisterIsoCmd extends BaseCmd implements UserCmd { } public Long getZoneId() { + if (zoneId == null || zoneId == -1) { + return null; + } return zoneId; } @@ -220,6 +221,10 @@ public class RegisterIsoCmd extends BaseCmd implements UserCmd { return directDownload == null ? false : directDownload; } + public void setDirectDownload(Boolean directDownload) { + this.directDownload = directDownload; + } + public boolean isPasswordEnabled() { return passwordEnabled == null ? false : passwordEnabled; } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/UpdateIsoCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/UpdateIsoCmd.java index 58c475c661e..95d9feed7e3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/UpdateIsoCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/UpdateIsoCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.iso; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiErrorCode; @@ -33,7 +32,6 @@ import com.cloud.user.Account; @APICommand(name = "updateIso", description = "Updates an ISO file.", responseObject = TemplateResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateIsoCmd extends BaseUpdateTemplateOrIsoCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(UpdateIsoCmd.class.getName()); private static final String s_name = "updateisoresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/UpdateIsoPermissionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/UpdateIsoPermissionsCmd.java index dd07faf9a87..02ada253fd2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/iso/UpdateIsoPermissionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/iso/UpdateIsoPermissionsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.iso; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd; @@ -33,10 +32,6 @@ public class UpdateIsoPermissionsCmd extends BaseUpdateTemplateOrIsoPermissionsC return "updateisopermissionsresponse"; } - @Override - protected Logger getLogger() { - return Logger.getLogger(UpdateIsoPermissionsCmd.class.getName()); - } @Override public long getEntityOwnerId() { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/job/QueryAsyncJobResultCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/job/QueryAsyncJobResultCmd.java index f578078e3a1..3d328543dc2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/job/QueryAsyncJobResultCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/job/QueryAsyncJobResultCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.job; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -29,7 +28,6 @@ import com.cloud.user.Account; @APICommand(name = "queryAsyncJobResult", description = "Retrieves the current status of asynchronous job.", responseObject = AsyncJobResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class QueryAsyncJobResultCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(QueryAsyncJobResultCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/AssignCertToLoadBalancerCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/AssignCertToLoadBalancerCmd.java index 50d69c8d3ae..4f9d2f37d13 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/AssignCertToLoadBalancerCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/AssignCertToLoadBalancerCmd.java @@ -17,7 +17,6 @@ // under the License. package org.apache.cloudstack.api.command.user.loadbalancer; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -42,7 +41,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AssignCertToLoadBalancerCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(AssignCertToLoadBalancerCmd.class.getName()); @Parameter(name = ApiConstants.LBID, diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java index 7647b017f29..c4424b1d937 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.Map; import com.cloud.utils.exception.CloudRuntimeException; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -51,7 +50,6 @@ import com.cloud.vm.VirtualMachine; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(AssignToLoadBalancerRuleCmd.class.getName()); ///////////////////////////////////////////////////// @@ -74,7 +72,7 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID_IP, type = CommandType.MAP, - description = "VM ID and IP map, vmidipmap[0].vmid=1 vmidipmap[0].ip=10.1.1.75", + description = "VM ID and IP map, vmidipmap[0].vmid=1 vmidipmap[0].vmip=10.1.1.75", since = "4.4") private Map vmIdIpMap; @@ -133,7 +131,7 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd { throw new InvalidParameterValueException("Unable to find virtual machine ID: " + vmId); } - //check wether the given ip is valid ip or not + //check whether the given ip is valid ip or not if (vmIp == null || !NetUtils.isValidIp4(vmIp)) { throw new InvalidParameterValueException("Invalid ip address "+ vmIp +" passed in vmidipmap for " + "vmid " + vmId); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateApplicationLoadBalancerCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateApplicationLoadBalancerCmd.java index 8c63c8f7951..2199dfb4e8b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateApplicationLoadBalancerCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateApplicationLoadBalancerCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InsufficientAddressCapacityException; @@ -44,7 +43,6 @@ import com.cloud.utils.net.NetUtils; @APICommand(name = "createLoadBalancer", description = "Creates an internal load balancer", responseObject = ApplicationLoadBalancerResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateApplicationLoadBalancerCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateApplicationLoadBalancerCmd.class.getName()); ///////////////////////////////////////////////////// @@ -202,7 +200,7 @@ public class CreateApplicationLoadBalancerCmd extends BaseAsyncCreateCmd { setResponseObject(lbResponse); lbResponse.setResponseName(getCommandName()); } catch (Exception ex) { - s_logger.warn("Failed to create load balancer due to exception ", ex); + logger.warn("Failed to create load balancer due to exception ", ex); } finally { if (rule == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create load balancer"); @@ -220,13 +218,13 @@ public class CreateApplicationLoadBalancerCmd extends BaseAsyncCreateCmd { this.setEntityId(result.getId()); this.setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, e.getMessage()); } catch (InsufficientAddressCapacityException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, e.getMessage()); } catch (InsufficientVirtualNetworkCapacityException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java index 57cb8078738..c24a5f19f07 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.LBHealthCheckResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -44,7 +43,6 @@ import com.cloud.user.Account; responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") public class CreateLBHealthCheckPolicyCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateLBHealthCheckPolicyCmd.class.getName()); // /////////////////////////////////////////////////// @@ -181,7 +179,7 @@ public class CreateLBHealthCheckPolicyCmd extends BaseAsyncCreateCmd { this.setEntityId(result.getId()); this.setEntityUuid(result.getUuid()); } catch (InvalidParameterValueException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java index 66a15984ae4..c6b5036bc95 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBStickinessPolicyCmd.java @@ -29,7 +29,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.LBStickinessResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -44,7 +43,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") public class CreateLBStickinessPolicyCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateLBStickinessPolicyCmd.class.getName()); private static final String s_name = "createLBStickinessPolicy"; @@ -164,7 +162,7 @@ public class CreateLBStickinessPolicyCmd extends BaseAsyncCreateCmd { this.setEntityId(result.getId()); this.setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java index ef9e46f3a76..f86d1ae85da 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/CreateLoadBalancerRuleCmd.java @@ -33,7 +33,6 @@ import org.apache.cloudstack.api.response.LoadBalancerResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter.NetworkType; @@ -52,7 +51,6 @@ import com.cloud.utils.net.NetUtils; @APICommand(name = "createLoadBalancerRule", description = "Creates a load balancer rule", responseObject = LoadBalancerResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements LoadBalancer */{ - public static final Logger s_logger = Logger.getLogger(CreateLoadBalancerRuleCmd.class.getName()); ///////////////////////////////////////////////////// @@ -284,7 +282,7 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements L } lbResponse.setResponseName(getCommandName()); } catch (Exception ex) { - s_logger.warn("Failed to create LB rule due to exception ", ex); + logger.warn("Failed to create LB rule due to exception ", ex); } finally { if (!success || rule == null) { @@ -309,10 +307,10 @@ public class CreateLoadBalancerRuleCmd extends BaseAsyncCreateCmd /*implements L this.setEntityId(result.getId()); this.setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, e.getMessage()); } catch (InsufficientAddressCapacityException e) { - s_logger.warn("Exception: ", e); + logger.warn("Exception: ", e); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, e.getMessage()); } catch (InvalidParameterValueException e) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, e.getMessage()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteApplicationLoadBalancerCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteApplicationLoadBalancerCmd.java index 912c760168b..410df086393 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteApplicationLoadBalancerCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteApplicationLoadBalancerCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.loadbalancer; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -36,7 +35,6 @@ import com.cloud.exception.InvalidParameterValueException; @APICommand(name = "deleteLoadBalancer", description = "Deletes an internal load balancer", responseObject = SuccessResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteApplicationLoadBalancerCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteApplicationLoadBalancerCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBHealthCheckPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBHealthCheckPolicyCmd.java index 159d6b21cbc..3cf1f345037 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBHealthCheckPolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBHealthCheckPolicyCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.loadbalancer; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteLBHealthCheckPolicy", description = "Deletes a load balancer health check policy.", responseObject = SuccessResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteLBHealthCheckPolicyCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteLBHealthCheckPolicyCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBStickinessPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBStickinessPolicyCmd.java index 10c342911b4..5d04de3cae5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBStickinessPolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBStickinessPolicyCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.loadbalancer; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteLBStickinessPolicy", description = "Deletes a load balancer stickiness policy.", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteLBStickinessPolicyCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteLBStickinessPolicyCmd.class.getName()); private static final String s_name = "deleteLBstickinessrruleresponse"; // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLoadBalancerRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLoadBalancerRuleCmd.java index f05d4cd2be3..b4079430ee3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLoadBalancerRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLoadBalancerRuleCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.loadbalancer; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteLoadBalancerRule", description = "Deletes a load balancer rule.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteLoadBalancerRuleCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteLoadBalancerRuleCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteSslCertCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteSslCertCmd.java index 3db733182a1..887007e537e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteSslCertCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/DeleteSslCertCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.loadbalancer; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,6 @@ import com.cloud.utils.exception.CloudRuntimeException; @APICommand(name = "deleteSslCert", description = "Delete a certificate to CloudStack", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSslCertCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteSslCertCmd.class.getName()); @Inject diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListApplicationLoadBalancersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListApplicationLoadBalancersCmd.java index ad68b301844..d54f3e1155e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListApplicationLoadBalancersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListApplicationLoadBalancersCmd.java @@ -29,7 +29,6 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; -import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.rules.LoadBalancerContainer.Scheme; @@ -38,7 +37,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listLoadBalancers", description = "Lists internal load balancers", responseObject = ApplicationLoadBalancerResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListApplicationLoadBalancersCmd extends BaseListTaggedResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListApplicationLoadBalancersCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java index 1c1f5d1f9af..cb2cdb446d1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.LBHealthCheckResponse; import org.apache.cloudstack.api.response.ListResponse; -import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; @@ -37,7 +36,6 @@ import com.cloud.network.rules.LoadBalancer; @APICommand(name = "listLBHealthCheckPolicies", description = "Lists load balancer health check policies.", responseObject = LBHealthCheckResponse.class, since = "4.2.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListLBHealthCheckPoliciesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListLBHealthCheckPoliciesCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java index 3d08d925797..a48e2ea37b7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java @@ -29,7 +29,6 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.LBStickinessResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.StickinessPolicy; @@ -38,7 +37,6 @@ import com.cloud.user.Account; @APICommand(name = "listLBStickinessPolicies", description = "Lists load balancer stickiness policies.", responseObject = LBStickinessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListLBStickinessPoliciesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListLBStickinessPoliciesCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java index 77aaa6bc1d3..3bfc68a95ba 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java @@ -23,7 +23,6 @@ import com.cloud.vm.VirtualMachine; import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.response.LoadBalancerRuleVmMapResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -41,7 +40,6 @@ import com.cloud.utils.Pair; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListLoadBalancerRuleInstancesCmd extends BaseListCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListLoadBalancerRuleInstancesCmd.class.getName()); private static final String s_name = "listloadbalancerruleinstancesresponse"; @@ -97,52 +95,44 @@ public class ListLoadBalancerRuleInstancesCmd extends BaseListCmd implements Use public void execute() { Pair, List> vmServiceMap = _lbService.listLoadBalancerInstances(this); List result = vmServiceMap.first(); + logger.debug(String.format("A total of [%s] user VMs were obtained when listing the load balancer instances: [%s].", result.size(), result)); + List serviceStates = vmServiceMap.second(); + logger.debug(String.format("A total of [%s] service states were obtained when listing the load balancer instances: [%s].", serviceStates.size(), serviceStates)); if (!isListLbVmip()) { - // list lb instances - ListResponse response = new ListResponse(); - List vmResponses = new ArrayList(); - if (result != null) { - vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Restricted, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); + ListResponse response = new ListResponse<>(); + List vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Restricted, "loadbalancerruleinstance", result.toArray(new UserVm[0])); - - for (int i = 0; i < result.size(); i++) { - vmResponses.get(i).setServiceState(serviceStates.get(i)); - } + for (int i = 0; i < result.size(); i++) { + vmResponses.get(i).setServiceState(serviceStates.get(i)); } + response.setResponses(vmResponses); response.setResponseName(getCommandName()); setResponseObject(response); - - - } else { - ListResponse lbRes = new ListResponse(); - - List vmResponses = new ArrayList(); - List listlbVmRes = new ArrayList(); - - if (result != null) { - vmResponses = _responseGenerator.createUserVmResponse(getResponseView(), "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); - - - List ipaddr = null; - - for (int i=0;i lbRes = new ListResponse<>(); + + List vmResponses = _responseGenerator.createUserVmResponse(getResponseView(), "loadbalancerruleinstance", result.toArray(new UserVm[0])); + List lbRuleVmMapList = new ArrayList<>(); + + for (int i=0; i getSourceCidrList() { if (cidrlist != null) { return cidrlist; @@ -138,6 +140,9 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd { throw new InvalidParameterValueException("Invalid traffic type " + trafficType); } + public void setTrafficType(String trafficType) { + this.trafficType = trafficType; + } // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// // /////////////////////////////////////////////////// @@ -146,15 +151,23 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd { return action; } + public void setAction(String action) { + this.action = action; + } + public Integer getNumber() { return number; } - public Integer getSourcePortStart() { + public Integer getPublicStartPort() { return publicStartPort; } - public Integer getSourcePortEnd() { + public void setPublicStartPort(Integer publicStartPort) { + this.publicStartPort = publicStartPort; + } + + public Integer getPublicEndPort() { if (publicEndPort == null) { if (publicStartPort != null) { return publicStartPort; @@ -166,10 +179,18 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd { return null; } + public void setPublicEndPort(Integer publicEndPort) { + this.publicEndPort = publicEndPort; + } + public Long getNetworkId() { return networkId; } + public void setNetworkId(Long networkId) { + this.networkId = networkId; + } + @Override public long getEntityOwnerId() { Account caller = CallContext.current().getCallingAccount(); @@ -209,6 +230,10 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd { return aclId; } + public void setAclId(Long aclId) { + this.aclId = aclId; + } + public String getReason() { return reason; } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java index 14dbfcafd7b..cd25a604e77 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkACLListCmd.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.network; +import com.cloud.exception.PermissionDeniedException; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -26,7 +27,7 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.VpcResponse; -import org.apache.log4j.Logger; +import org.apache.cloudstack.context.CallContext; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -35,10 +36,10 @@ import com.cloud.network.vpc.NetworkACL; import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; -@APICommand(name = "createNetworkACLList", description = "Creates a network ACL for the given VPC", responseObject = NetworkACLResponse.class, +@APICommand(name = "createNetworkACLList", description = "Creates a network ACL. If no VPC is given, then it creates a global ACL that can be used by everyone.", + responseObject = NetworkACLResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateNetworkACLListCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateNetworkACLListCmd.class.getName()); // /////////////////////////////////////////////////// @@ -53,7 +54,6 @@ public class CreateNetworkACLListCmd extends BaseAsyncCreateCmd { @Parameter(name = ApiConstants.VPC_ID, type = CommandType.UUID, - required = true, entityType = VpcResponse.class, description = "ID of the VPC associated with this network ACL list") private Long vpcId; @@ -77,6 +77,10 @@ public class CreateNetworkACLListCmd extends BaseAsyncCreateCmd { return vpcId; } + public void setVpcId(Long vpcId) { + this.vpcId = vpcId; + } + @Override public boolean isDisplay() { if (display != null) { @@ -92,6 +96,9 @@ public class CreateNetworkACLListCmd extends BaseAsyncCreateCmd { @Override public void create() { + if (getVpcId() == null) { + setVpcId(0L); + } NetworkACL result = _networkACLService.createNetworkACL(getName(), getDescription(), getVpcId(), isDisplay()); setEntityId(result.getId()); setEntityUuid(result.getUuid()); @@ -111,12 +118,21 @@ public class CreateNetworkACLListCmd extends BaseAsyncCreateCmd { @Override public long getEntityOwnerId() { - Vpc vpc = _entityMgr.findById(Vpc.class, getVpcId()); - if (vpc == null) { - throw new InvalidParameterValueException("Invalid vpcId is given"); - } + Account account; + if (isAclAttachedToVpc(this.vpcId)) { + Vpc vpc = _entityMgr.findById(Vpc.class, this.vpcId); + if (vpc == null) { + throw new InvalidParameterValueException(String.format("Invalid VPC ID [%s] provided.", this.vpcId)); + } + account = _accountService.getAccount(vpc.getAccountId()); + } else { + account = CallContext.current().getCallingAccount(); + if (!Account.Type.ADMIN.equals(account.getType())) { + logger.warn(String.format("Only Root Admin can create global ACLs. Account [%s] cannot create any global ACL.", account)); + throw new PermissionDeniedException("Only Root Admin can create global ACLs."); + } - Account account = _accountService.getAccount(vpc.getAccountId()); + } return account.getId(); } @@ -139,4 +155,8 @@ public class CreateNetworkACLListCmd extends BaseAsyncCreateCmd { public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.NetworkAcl; } + + public boolean isAclAttachedToVpc(Long aclVpcId) { + return aclVpcId != null && aclVpcId != 0; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java index ca379fb1596..2395339a477 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.network; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -51,7 +50,6 @@ import com.cloud.utils.net.NetUtils; @APICommand(name = "createNetwork", description = "Creates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateNetworkCmd extends BaseCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(CreateNetworkCmd.class.getName()); private static final String s_name = "createnetworkresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkPermissionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkPermissionsCmd.java index 4a1f65ba7a2..1df472cbb22 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkPermissionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkPermissionsCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.SuccessResponse; -import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network; @@ -43,7 +42,6 @@ import java.util.List; since = "4.17.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class CreateNetworkPermissionsCmd extends BaseCmd { - public static final Logger LOGGER = Logger.getLogger(CreateNetworkPermissionsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java index f171492b2f6..ca42626eacb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.network; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteNetworkACL", description = "Deletes a network ACL", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteNetworkACLCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteNetworkACLCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java index 5c24efae6eb..45bc86e8c91 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkACLListCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.network; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteNetworkACLList", description = "Deletes a network ACL", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteNetworkACLListCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteNetworkACLListCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java index 5f15c23e23f..8e8e18c6702 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -37,7 +36,6 @@ import com.cloud.network.Network; @APICommand(name = "deleteNetwork", description = "Deletes a network", responseObject = SuccessResponse.class, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteNetworkCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteNetworkCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java index f3a06142d78..c88f956943b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkACLListsCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.VpcResponse; -import org.apache.log4j.Logger; import com.cloud.network.vpc.NetworkACL; import com.cloud.utils.Pair; @@ -36,7 +35,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listNetworkACLLists", description = "Lists all network ACLs", responseObject = NetworkACLResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNetworkACLListsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListNetworkACLListsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java index 945142f4df0..1ef2b9b7bfb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkACLsCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.NetworkACLItemResponse; import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.NetworkResponse; -import org.apache.log4j.Logger; import com.cloud.network.vpc.NetworkACLItem; import com.cloud.utils.Pair; @@ -36,7 +35,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listNetworkACLs", description = "Lists all network ACL items", responseObject = NetworkACLItemResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNetworkACLsCmd extends BaseListTaggedResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListNetworkACLsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java index 70c01fd1d88..33f452008d9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.NetworkOfferingResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; import com.cloud.offering.NetworkOffering; import com.cloud.utils.Pair; @@ -36,7 +35,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listNetworkOfferings", description = "Lists all available network offerings.", responseObject = NetworkOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNetworkOfferingsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListNetworkOfferingsCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkPermissionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkPermissionsCmd.java index 9e6b01d3676..6ea4937e115 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkPermissionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkPermissionsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -42,7 +41,6 @@ import java.util.List; since = "4.17.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ListNetworkPermissionsCmd extends BaseCmd implements UserCmd { - public static final Logger LOGGER = Logger.getLogger(ListNetworkPermissionsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkProtocolsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkProtocolsCmd.java new file mode 100644 index 00000000000..a7c359d66c2 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkProtocolsCmd.java @@ -0,0 +1,107 @@ +// 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.user.network; + +import com.cloud.utils.net.NetworkProtocols; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.NetworkProtocolResponse; +import org.apache.cloudstack.context.CallContext; + +import java.util.ArrayList; +import java.util.List; + +@APICommand(name = "listNetworkProtocols", description = "Lists details of network protocols", responseObject = NetworkProtocolResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = { RoleType.Admin, RoleType.DomainAdmin, RoleType.ResourceAdmin, RoleType.User}, since = "4.19.0") +public class ListNetworkProtocolsCmd extends BaseCmd { + + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.OPTION, type = CommandType.STRING, required = true, + description = "The option of network protocols. Supported values are: protocolnumber, icmptype.") + private String option; + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public String getOption() { + return option; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() { + ListResponse response = new ListResponse<>(); + List networkProtocolResponses = new ArrayList<>(); + + NetworkProtocols.Option option = NetworkProtocols.Option.getOption(getOption()); + switch (option) { + case ProtocolNumber: + updateResponseWithProtocolNumbers(networkProtocolResponses); + break; + case IcmpType: + updateResponseWithIcmpTypes(networkProtocolResponses); + break; + default: + break; + } + + response.setResponses(networkProtocolResponses); + response.setResponseName(getCommandName()); + setResponseObject(response); + } + + @Override + public long getEntityOwnerId() { + return CallContext.current().getCallingAccount().getId(); + } + + private void updateResponseWithProtocolNumbers(List responses) { + for (NetworkProtocols.ProtocolNumber protocolNumber : NetworkProtocols.ProtocolNumbers) { + NetworkProtocolResponse networkProtocolResponse = new NetworkProtocolResponse(protocolNumber.getNumber(), + protocolNumber.getKeyword(), protocolNumber.getProtocol()); + networkProtocolResponse.setObjectName("networkprotocol"); + responses.add(networkProtocolResponse); + } + } + + private void updateResponseWithIcmpTypes(List responses) { + for (NetworkProtocols.IcmpType icmpType : NetworkProtocols.IcmpTypes) { + NetworkProtocolResponse networkProtocolResponse = new NetworkProtocolResponse(icmpType.getType(), + null, icmpType.getDescription()); + for (NetworkProtocols.IcmpCode code : icmpType.getIcmpCodes()) { + networkProtocolResponse.addDetail(String.valueOf(code.getCode()), code.getDescription()); + } + networkProtocolResponse.setObjectName("networkprotocol"); + responses.add(networkProtocolResponse); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java index c1e85a9b4c3..0e8425b14b4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java @@ -24,7 +24,6 @@ import com.cloud.server.ResourceTag; import org.apache.cloudstack.api.response.NetworkOfferingResponse; import org.apache.cloudstack.api.response.ResourceIconResponse; import org.apache.commons.lang3.BooleanUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -46,7 +45,6 @@ import org.apache.commons.lang3.StringUtils; @APICommand(name = "listNetworks", description = "Lists all available networks.", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNetworksCmd extends BaseListRetrieveOnlyResourceCountCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListNetworksCmd.class.getName()); private static final String s_name = "listnetworksresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/MoveNetworkAclItemCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/MoveNetworkAclItemCmd.java index da6ac437aa0..5d36dcfd8e9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/MoveNetworkAclItemCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/MoveNetworkAclItemCmd.java @@ -23,7 +23,6 @@ import org.apache.cloudstack.api.BaseAsyncCustomIdCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.NetworkACLItemResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.network.vpc.NetworkACLItem; @@ -32,7 +31,6 @@ import com.cloud.user.Account; @APICommand(name = "moveNetworkAclItem", description = "Move an ACL rule to a position bettwen two other ACL rules of the same ACL network list", responseObject = NetworkACLItemResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class MoveNetworkAclItemCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(MoveNetworkAclItemCmd.class.getName()); private static final String s_name = "moveNetworkAclItemResponse"; @Parameter(name = ApiConstants.ID, type = CommandType.STRING, required = true, description = "The ID of the network ACL rule that is being moved to a new position.") diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RemoveNetworkPermissionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RemoveNetworkPermissionsCmd.java index 05785c81588..c199d872e0c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RemoveNetworkPermissionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RemoveNetworkPermissionsCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.SuccessResponse; -import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network; @@ -43,7 +42,6 @@ import java.util.List; since = "4.17.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class RemoveNetworkPermissionsCmd extends BaseCmd { - public static final Logger LOGGER = Logger.getLogger(RemoveNetworkPermissionsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java index ea4e74149f4..f6e9557aadb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ReplaceNetworkACLListCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.network; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "replaceNetworkACLList", description = "Replaces ACL associated with a network or private gateway", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ReplaceNetworkACLListCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ReplaceNetworkACLListCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ResetNetworkPermissionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ResetNetworkPermissionsCmd.java index f9817f9be5f..a23b98c84a8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ResetNetworkPermissionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ResetNetworkPermissionsCmd.java @@ -25,7 +25,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.SuccessResponse; -import org.apache.log4j.Logger; import com.cloud.network.Network; import com.cloud.user.Account; @@ -38,7 +37,6 @@ import com.cloud.user.Account; since = "4.17.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ResetNetworkPermissionsCmd extends BaseCmd { - public static final Logger LOGGER = Logger.getLogger(ResetNetworkPermissionsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java index 141dee3c9a0..ffc2e36dee5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.SuccessResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -43,7 +42,6 @@ import com.cloud.network.Network; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RestartNetworkCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RestartNetworkCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java index f675fa23e34..42cb0697edb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLItemCmd.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.BaseAsyncCustomIdCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.NetworkACLItemResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ResourceUnavailableException; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "updateNetworkACLItem", description = "Updates ACL item with specified ID", responseObject = NetworkACLItemResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateNetworkACLItemCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateNetworkACLItemCmd.class.getName()); private static final String s_name = "createnetworkaclresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLListCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLListCmd.java index ddcb202aa8d..adab885542d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLListCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkACLListCmd.java @@ -25,7 +25,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.NetworkACLResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ResourceUnavailableException; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "updateNetworkACLList", description = "Updates network ACL list", responseObject = SuccessResponse.class, since = "4.4", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateNetworkACLListCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateNetworkACLListCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java index d3cc169b7da..0d92a635e7f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java @@ -31,7 +31,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.response.NetworkOfferingResponse; import org.apache.cloudstack.api.response.NetworkResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -43,7 +42,6 @@ import com.cloud.offering.NetworkOffering; @APICommand(name = "updateNetwork", description = "Updates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateNetworkCmd extends BaseAsyncCustomIdCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(UpdateNetworkCmd.class.getName()); private static final String s_name = "updatenetworkresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmd.java index 5fa24ec1630..f9b9ec59a40 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmd.java @@ -16,22 +16,26 @@ // under the License. package org.apache.cloudstack.api.command.user.offering; -import org.apache.cloudstack.api.response.StoragePoolResponse; -import org.apache.cloudstack.api.response.VolumeResponse; -import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; +import static com.cloud.offering.DiskOffering.State.Active; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseListDomainResourcesCmd; +import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.commons.lang3.EnumUtils; +import org.apache.commons.lang3.StringUtils; + +import com.cloud.offering.DiskOffering.State; @APICommand(name = "listDiskOfferings", description = "Lists all available disk offerings.", responseObject = DiskOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class ListDiskOfferingsCmd extends BaseListDomainResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListDiskOfferingsCmd.class.getName()); +public class ListDiskOfferingsCmd extends BaseListProjectAndAccountResourcesCmd { ///////////////////////////////////////////////////// @@ -60,6 +64,24 @@ public class ListDiskOfferingsCmd extends BaseListDomainResourcesCmd { @Parameter(name = ApiConstants.ENCRYPT, type = CommandType.BOOLEAN, description = "listed offerings support disk encryption", since = "4.18") private Boolean encrypt; + @Parameter(name = ApiConstants.STORAGE_TYPE, + type = CommandType.STRING, + description = "the storage type of the service offering. Values are local and shared.", + since = "4.19") + private String storageType; + + @Parameter(name = ApiConstants.STATE, type = CommandType.STRING, + description = "Filter by state of the disk offering. Defaults to 'Active'. If set to 'all' shows both Active & Inactive offerings.", + since = "4.19") + private String diskOfferingState; + + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, + type = CommandType.UUID, + entityType = UserVmResponse.class, + description = "The ID of a virtual machine. Pass this in if you want to see the suitable disk offering that can be used to create and add a disk to the virtual machine. Suitability is returned with suitableforvirtualmachine flag in the response", + since = "4.20.0") + private Long virtualMachineId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -84,13 +106,31 @@ public class ListDiskOfferingsCmd extends BaseListDomainResourcesCmd { public Boolean getEncrypt() { return encrypt; } + public String getStorageType() { + return storageType; + } + + public State getState() { + if (StringUtils.isBlank(diskOfferingState)) { + return Active; + } + State state = EnumUtils.getEnumIgnoreCase(State.class, diskOfferingState); + if (!diskOfferingState.equalsIgnoreCase("all") && state == null) { + throw new IllegalArgumentException("Invalid state value: " + diskOfferingState); + } + return state; + } + + public Long getVirtualMachineId() { + return virtualMachineId; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @Override public void execute() { - ListResponse response = _queryService.searchForDiskOfferings(this); response.setResponseName(getCommandName()); this.setResponseObject(response); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java index 3208ef58a4f..1b3f531e370 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmd.java @@ -16,21 +16,25 @@ // under the License. package org.apache.cloudstack.api.command.user.offering; -import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; +import static com.cloud.offering.ServiceOffering.State.Active; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseListDomainResourcesCmd; +import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; +import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.commons.lang3.EnumUtils; +import org.apache.commons.lang3.StringUtils; + +import com.cloud.offering.ServiceOffering.State; @APICommand(name = "listServiceOfferings", description = "Lists all available service offerings.", responseObject = ServiceOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class ListServiceOfferingsCmd extends BaseListDomainResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListServiceOfferingsCmd.class.getName()); +public class ListServiceOfferingsCmd extends BaseListProjectAndAccountResourcesCmd { ///////////////////////////////////////////////////// @@ -88,6 +92,24 @@ public class ListServiceOfferingsCmd extends BaseListDomainResourcesCmd { since = "4.18") private Boolean encryptRoot; + @Parameter(name = ApiConstants.STORAGE_TYPE, + type = CommandType.STRING, + description = "the storage type of the service offering. Values are local and shared.", + since = "4.19") + private String storageType; + + @Parameter(name = ApiConstants.STATE, type = CommandType.STRING, + description = "Filter by state of the service offering. Defaults to 'Active'. If set to 'all' shows both Active & Inactive offerings.", + since = "4.19") + private String serviceOfferingState; + + @Parameter(name = ApiConstants.TEMPLATE_ID, + type = CommandType.UUID, + entityType = TemplateResponse.class, + description = "The ID of the template that listed offerings must support", + since = "4.20.0") + private Long templateId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -130,6 +152,25 @@ public class ListServiceOfferingsCmd extends BaseListDomainResourcesCmd { public Boolean getEncryptRoot() { return encryptRoot; } + public String getStorageType() { + return storageType; + } + + public State getState() { + if (StringUtils.isBlank(serviceOfferingState)) { + return Active; + } + State state = EnumUtils.getEnumIgnoreCase(State.class, serviceOfferingState); + if (!serviceOfferingState.equalsIgnoreCase("all") && state == null) { + throw new IllegalArgumentException("Invalid state value: " + serviceOfferingState); + } + return state; + } + + public Long getTemplateId() { + return templateId; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/project/ActivateProjectCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/project/ActivateProjectCmd.java index 58cc93ff95d..42e045d4389 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/project/ActivateProjectCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/project/ActivateProjectCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.project; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.projects.Project; @APICommand(name = "activateProject", description = "Activates a project", responseObject = ProjectResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ActivateProjectCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ActivateProjectCmd.class.getName()); private static final String s_name = "activaterojectresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/project/CreateProjectCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/project/CreateProjectCmd.java index a5742e8d0de..cb93729381a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/project/CreateProjectCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/project/CreateProjectCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.context.CallContext; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -39,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "createProject", description = "Creates a project", responseObject = ProjectResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateProjectCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateProjectCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectCmd.java index 85b411b075d..1fd205fdae4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.project; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.projects.Project; @APICommand(name = "deleteProject", description = "Deletes a project", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteProjectCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteProjectCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectInvitationCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectInvitationCmd.java index 600fac350de..d1b17eda76b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectInvitationCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/project/DeleteProjectInvitationCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.project; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteProjectInvitation", description = "Deletes project invitation", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteProjectInvitationCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteProjectInvitationCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/project/ListProjectInvitationsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/project/ListProjectInvitationsCmd.java index b8d2f9b5f1a..210394ec2dd 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/project/ListProjectInvitationsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/project/ListProjectInvitationsCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.project; import org.apache.cloudstack.api.response.UserResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import org.apache.cloudstack.api.response.ProjectResponse; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListProjectInvitationsCmd extends BaseListAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListProjectInvitationsCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/project/ListProjectsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/project/ListProjectsCmd.java index 39d1c0dfeda..d4679dbe057 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/project/ListProjectsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/project/ListProjectsCmd.java @@ -24,7 +24,6 @@ import java.util.Map; import com.cloud.server.ResourceIcon; import com.cloud.server.ResourceTag; import org.apache.cloudstack.api.response.ResourceIconResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -44,7 +43,6 @@ import com.cloud.exception.InvalidParameterValueException; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListProjectsCmd extends BaseListAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListProjectsCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/project/SuspendProjectCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/project/SuspendProjectCmd.java index 4937b164aab..a3eee8c80bb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/project/SuspendProjectCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/project/SuspendProjectCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.project; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,6 @@ import com.cloud.projects.Project; @APICommand(name = "suspendProject", description = "Suspends a project", responseObject = ProjectResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class SuspendProjectCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(SuspendProjectCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/project/UpdateProjectCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/project/UpdateProjectCmd.java index 6520aa63a64..4fabf7da788 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/project/UpdateProjectCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/project/UpdateProjectCmd.java @@ -29,7 +29,6 @@ import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.context.CallContext; import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -40,7 +39,6 @@ import com.cloud.projects.ProjectAccount; @APICommand(name = "updateProject", description = "Updates a project", responseObject = ProjectResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateProjectCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateProjectCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/project/UpdateProjectInvitationCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/project/UpdateProjectInvitationCmd.java index e783aa64467..0cbd9f702c2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/project/UpdateProjectInvitationCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/project/UpdateProjectInvitationCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.user.Account; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "updateProjectInvitation", description = "Accepts or declines project invitation", responseObject = SuccessResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateProjectInvitationCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateProjectInvitationCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ListRegionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ListRegionsCmd.java index d3eb8bf8b0f..777f437851c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ListRegionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ListRegionsCmd.java @@ -21,7 +21,6 @@ import java.util.List; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import org.apache.cloudstack.region.RegionService; @APICommand(name = "listRegions", description = "Lists Regions", responseObject = RegionResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListRegionsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListRegionsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java index aedc363e5cc..649b2a7bd9b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java @@ -25,7 +25,6 @@ import java.util.Map; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -53,7 +52,6 @@ import com.cloud.user.Account; responseHasSensitiveInfo = false) public class AssignToGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(AssignToGlobalLoadBalancerRuleCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java index 3aaf0607392..ddaadde7852 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java @@ -30,7 +30,6 @@ import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; import org.apache.cloudstack.api.response.RegionResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ResourceAllocationException; @@ -42,7 +41,6 @@ import com.cloud.region.ha.GlobalLoadBalancingRulesService; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateGlobalLoadBalancerRuleCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateGlobalLoadBalancerRuleCmd.class.getName()); ///////////////////////////////////////////////////// @@ -157,7 +155,7 @@ public class CreateGlobalLoadBalancerRuleCmd extends BaseAsyncCreateCmd { this.setEntityUuid(gslbRule.getUuid()); CallContext.current().setEventDetails("Rule Id: " + getEntityId()); } catch (Exception ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage()); } finally { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java index 87c4e60a90b..7f3308614cc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.region.ha.gslb; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -41,7 +40,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteGlobalLoadBalancerRuleCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java index 7a1bcfc37a7..bf0cf22a2ec 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java @@ -22,7 +22,6 @@ import java.util.List; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,6 @@ import com.cloud.region.ha.GlobalLoadBalancingRulesService; @APICommand(name = "listGlobalLoadBalancerRules", description = "Lists load balancer rules.", responseObject = GlobalLoadBalancerResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListGlobalLoadBalancerRuleCmd extends BaseListTaggedResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListGlobalLoadBalancerRuleCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/RemoveFromGlobalLoadBalancerRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/RemoveFromGlobalLoadBalancerRuleCmd.java index b9bbfec847f..d4b02139892 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/RemoveFromGlobalLoadBalancerRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/RemoveFromGlobalLoadBalancerRuleCmd.java @@ -21,7 +21,6 @@ import java.util.List; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -47,7 +46,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RemoveFromGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RemoveFromGlobalLoadBalancerRuleCmd.class.getName()); private static final String s_name = "removefromloadbalancerruleresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java index c8d307e4084..7996998e5d9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.region.ha.gslb; import javax.inject.Inject; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "updateGlobalLoadBalancerRule", description = "update global load balancer rules.", responseObject = GlobalLoadBalancerResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateGlobalLoadBalancerRuleCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/GetCloudIdentifierCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/GetCloudIdentifierCmd.java index b513b811e46..b9e43336217 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/GetCloudIdentifierCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/GetCloudIdentifierCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.resource; import java.util.ArrayList; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "getCloudIdentifier", description = "Retrieves a cloud identifier.", responseObject = CloudIdentifierResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class GetCloudIdentifierCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(GetCloudIdentifierCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/ListHypervisorsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/ListHypervisorsCmd.java index a0e750eb19f..556f3b081f0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/ListHypervisorsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/ListHypervisorsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.resource; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "listHypervisors", description = "List hypervisors", responseObject = HypervisorResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListHypervisorsCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(ListHypervisorsCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmd.java index adf1c93e4d0..71b886ed12b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmd.java @@ -19,22 +19,20 @@ package org.apache.cloudstack.api.command.user.resource; import java.util.ArrayList; import java.util.List; -import com.cloud.configuration.Resource; -import com.cloud.exception.InvalidParameterValueException; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ResourceLimitResponse; -import org.apache.log4j.Logger; +import com.cloud.configuration.Resource; import com.cloud.configuration.ResourceLimit; +import com.cloud.exception.InvalidParameterValueException; @APICommand(name = "listResourceLimits", description = "Lists resource limits.", responseObject = ResourceLimitResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListResourceLimitsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListResourceLimitsCmd.class.getName()); ///////////////////////////////////////////////////// @@ -74,6 +72,10 @@ public class ListResourceLimitsCmd extends BaseListProjectAndAccountResourcesCmd + "secondary_storage - SecondaryStorage. Total secondary storage space (in GiB) a user can use. ") private String resourceTypeName; + @Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for the resource type", since = "4.20.0") + private String tag; + + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -90,6 +92,10 @@ public class ListResourceLimitsCmd extends BaseListProjectAndAccountResourcesCmd return resourceTypeName; } + public String getTag() { + return tag; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -98,7 +104,7 @@ public class ListResourceLimitsCmd extends BaseListProjectAndAccountResourcesCmd public void execute() { List result = _resourceLimitService.searchForLimits(id, _accountService.finalyzeAccountId(this.getAccountName(), this.getDomainId(), this.getProjectId(), false), this.getDomainId(), - getResourceTypeEnum(), this.getStartIndex(), this.getPageSizeVal()); + getResourceTypeEnum(), getTag(), this.getStartIndex(), this.getPageSizeVal()); ListResponse response = new ListResponse(); List limitResponses = new ArrayList(); for (ResourceLimit limit : result) { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java index 424087bc71e..49c6ee605c8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java @@ -30,15 +30,16 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.ResourceCountResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.configuration.ResourceCount; import com.cloud.user.Account; -@APICommand(name = "updateResourceCount", description = "Recalculate and update resource count for an account or domain.", responseObject = ResourceCountResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = "updateResourceCount", + description = "Recalculate and update resource count for an account or domain. " + + "This also executes some cleanup tasks before calculating resource counts.", + responseObject = ResourceCountResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateResourceCountCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateResourceCountCmd.class.getName()); ///////////////////////////////////////////////////// @@ -77,6 +78,9 @@ public class UpdateResourceCountCmd extends BaseCmd { @Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "Update resource limits for project") private Long projectId; + @Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for the resource type", since = "4.20.0") + private String tag; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -93,6 +97,10 @@ public class UpdateResourceCountCmd extends BaseCmd { return resourceType; } + public String getTag() { + return tag; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -119,7 +127,7 @@ public class UpdateResourceCountCmd extends BaseCmd { @Override public void execute() { List result = - _resourceLimitService.recalculateResourceCount(_accountService.finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), getResourceType()); + _resourceLimitService.recalculateResourceCount(_accountService.finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), getResourceType(), getTag()); if ((result != null) && (result.size() > 0)) { ListResponse response = new ListResponse(); @@ -127,7 +135,6 @@ public class UpdateResourceCountCmd extends BaseCmd { for (ResourceCount count : result) { ResourceCountResponse resourceCountResponse = _responseGenerator.createResourceCountResponse(count); - resourceCountResponse.setObjectName("resourcecount"); countResponses.add(resourceCountResponse); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmd.java index 41676ed23ca..3538a389a6e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmd.java @@ -26,14 +26,12 @@ import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.ResourceLimitResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.configuration.ResourceLimit; @APICommand(name = "updateResourceLimit", description = "Updates resource limits for an account or domain.", responseObject = ResourceLimitResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateResourceLimitCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateResourceLimitCmd.class.getName()); ///////////////////////////////////////////////////// @@ -64,6 +62,7 @@ public class UpdateResourceLimitCmd extends BaseCmd { + "2 - Volume. Number of disk volumes a user can create. " + "3 - Snapshot. Number of snapshots a user can create. " + "4 - Template. Number of templates that a user can register/create. " + + "5 - Project. Number of projects a user can create. " + "6 - Network. Number of guest network a user can create. " + "7 - VPC. Number of VPC a user can create. " + "8 - CPU. Total number of CPU cores a user can use. " @@ -72,6 +71,9 @@ public class UpdateResourceLimitCmd extends BaseCmd { + "11 - SecondaryStorage. Total secondary storage space (in GiB) a user can use. ") private Integer resourceType; + @Parameter(name = ApiConstants.TAG, type = CommandType.STRING, description = "Tag for the resource type", since = "4.20.0") + private String tag; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -84,6 +86,10 @@ public class UpdateResourceLimitCmd extends BaseCmd { return domainId; } + public String getTag() { + return tag; + } + public Integer getResourceType() { return resourceType; } @@ -104,7 +110,7 @@ public class UpdateResourceLimitCmd extends BaseCmd { @Override public void execute() { - ResourceLimit result = _resourceLimitService.updateResourceLimit(_accountService.finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), resourceType, max); + ResourceLimit result = _resourceLimitService.updateResourceLimit(_accountService.finalyzeAccountId(accountName, domainId, projectId, true), getDomainId(), resourceType, max, getTag()); if (result != null || (result == null && max != null && max.longValue() == -1L)) { ResourceLimitResponse response = _responseGenerator.createResourceLimitResponse(result); response.setResponseName(getCommandName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java index 737bdc8773b..13faafe348c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java @@ -22,7 +22,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -50,7 +49,6 @@ import com.cloud.network.security.SecurityRule; responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") public class AuthorizeSecurityGroupEgressCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(AuthorizeSecurityGroupEgressCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java index b6918905f29..640870fc3de 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java @@ -22,7 +22,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -50,7 +49,6 @@ import com.cloud.network.security.SecurityRule; responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") public class AuthorizeSecurityGroupIngressCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(AuthorizeSecurityGroupIngressCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java index 4978aa174fc..673eaaef33d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.securitygroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "createSecurityGroup", responseObject = SecurityGroupResponse.class, description = "Creates a security group", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateSecurityGroupCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateSecurityGroupCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java index 57d365d5ce1..b2ea90792b8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.securitygroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -39,7 +38,6 @@ import com.cloud.network.security.SecurityGroup; @APICommand(name = "deleteSecurityGroup", description = "Deletes security group", responseObject = SuccessResponse.class, entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSecurityGroupCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteSecurityGroupCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -124,7 +122,7 @@ public class DeleteSecurityGroupCmd extends BaseCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete security group"); } } catch (ResourceInUseException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_IN_USE_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java index c4c103cf98e..f93e7b39586 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.securitygroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -32,7 +31,6 @@ import com.cloud.network.security.SecurityGroup; @APICommand(name = "listSecurityGroups", description = "Lists security groups", responseObject = SecurityGroupResponse.class, entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSecurityGroupsCmd extends BaseListTaggedResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListSecurityGroupsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java index f4a0362fce9..bf435406174 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.securitygroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -38,7 +37,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RevokeSecurityGroupEgressCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RevokeSecurityGroupEgressCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java index c5f88c9673f..c426647fe36 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.securitygroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -38,7 +37,6 @@ import com.cloud.user.Account; @APICommand(name = "revokeSecurityGroupIngress", responseObject = SuccessResponse.class, description = "Deletes a particular ingress rule from this security group", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RevokeSecurityGroupIngressCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RevokeSecurityGroupIngressCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/UpdateSecurityGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/UpdateSecurityGroupCmd.java index 9b3000b1bf7..801fb6ac5e5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/UpdateSecurityGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/securitygroup/UpdateSecurityGroupCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.securitygroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -37,7 +36,6 @@ import com.cloud.user.Account; since = "4.14.0.0", authorized = {RoleType.Admin}) public class UpdateSecurityGroupCmd extends BaseCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateSecurityGroupCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ArchiveSnapshotCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ArchiveSnapshotCmd.java index 78aa208ac1f..f72de2278cc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ArchiveSnapshotCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ArchiveSnapshotCmd.java @@ -35,13 +35,11 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SnapshotResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; @APICommand(name = "archiveSnapshot", description = "Archives (moves) a snapshot on primary storage to secondary storage", responseObject = SnapshotResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ArchiveSnapshotCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ArchiveSnapshotCmd.class.getName()); private static final String s_name = "createsnapshotresponse"; @ACL(accessType = SecurityChecker.AccessType.OperateEntry) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CopySnapshotCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CopySnapshotCmd.java new file mode 100644 index 00000000000..07973fcbfca --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CopySnapshotCmd.java @@ -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 org.apache.cloudstack.api.command.user.snapshot; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.user.UserCmd; +import org.apache.cloudstack.api.response.SnapshotResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.commons.collections.CollectionUtils; + +import com.cloud.dc.DataCenter; +import com.cloud.event.EventTypes; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.StorageUnavailableException; +import com.cloud.storage.Snapshot; +import com.cloud.user.Account; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@APICommand(name = "copySnapshot", description = "Copies a snapshot from one zone to another.", + responseObject = SnapshotResponse.class, responseView = ResponseObject.ResponseView.Restricted, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.19.0", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class CopySnapshotCmd extends BaseAsyncCmd implements UserCmd { + public static final Logger logger = LogManager.getLogger(CopySnapshotCmd.class.getName()); + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, + entityType = SnapshotResponse.class, required = true, description = "the ID of the snapshot.") + private Long id; + + @Parameter(name = ApiConstants.SOURCE_ZONE_ID, + type = CommandType.UUID, + entityType = ZoneResponse.class, + description = "The ID of the zone in which the snapshot is currently present. " + + "If not specified then the zone of snapshot's volume will be used.") + private Long sourceZoneId; + + @Parameter(name = ApiConstants.DESTINATION_ZONE_ID, + type = CommandType.UUID, + entityType = ZoneResponse.class, + required = false, + description = "The ID of the zone the snapshot is being copied to.") + protected Long destZoneId; + + @Parameter(name = ApiConstants.DESTINATION_ZONE_ID_LIST, + type=CommandType.LIST, + collectionType = CommandType.UUID, + entityType = ZoneResponse.class, + required = false, + description = "A comma-separated list of IDs of the zones that the snapshot needs to be copied to. " + + "Specify this list if the snapshot needs to copied to multiple zones in one go. " + + "Do not specify destzoneid and destzoneids together, however one of them is required.") + protected List destZoneIds; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public Long getId() { + return id; + } + + public Long getSourceZoneId() { + return sourceZoneId; + } + + public List getDestinationZoneIds() { + if (destZoneIds != null && destZoneIds.size() != 0) { + return destZoneIds; + } + if (destZoneId != null) { + List < Long > destIds = new ArrayList<>(); + destIds.add(destZoneId); + return destIds; + } + return null; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_SNAPSHOT_COPY; + } + + @Override + public String getEventDescription() { + StringBuilder descBuilder = new StringBuilder(); + if (getDestinationZoneIds() != null) { + for (Long destId : getDestinationZoneIds()) { + descBuilder.append(", "); + descBuilder.append(_uuidMgr.getUuid(DataCenter.class, destId)); + } + if (descBuilder.length() > 0) { + descBuilder.deleteCharAt(0); + } + } + + return "copying snapshot: " + _uuidMgr.getUuid(Snapshot.class, getId()) + ((descBuilder.length() > 0) ? " to zones: " + descBuilder.toString() : ""); + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Snapshot; + } + + @Override + public Long getApiResourceId() { + return getId(); + } + + @Override + public long getEntityOwnerId() { + Snapshot snapshot = _entityMgr.findById(Snapshot.class, getId()); + if (snapshot != null) { + return snapshot.getAccountId(); + } + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() throws ResourceUnavailableException { + try { + if (destZoneId == null && CollectionUtils.isEmpty(destZoneIds)) + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + "Either destzoneid or destzoneids parameters have to be specified."); + + if (destZoneId != null && CollectionUtils.isNotEmpty(destZoneIds)) + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + "Both destzoneid and destzoneids cannot be specified at the same time."); + + CallContext.current().setEventDetails(getEventDescription()); + Snapshot snapshot = _snapshotService.copySnapshot(this); + + if (snapshot != null) { + SnapshotResponse response = _queryService.listSnapshot(this); + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to copy snapshot"); + } + } catch (StorageUnavailableException ex) { + logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); + } catch (ResourceAllocationException ex) { + logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage()); + } + + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java index 56e112963a9..3289ac2fe10 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java @@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.user.snapshot; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.cloudstack.api.APICommand; @@ -32,8 +33,8 @@ import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.SnapshotPolicyResponse; import org.apache.cloudstack.api.response.SnapshotResponse; import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.commons.collections.MapUtils; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -48,7 +49,6 @@ import com.cloud.utils.exception.CloudRuntimeException; @APICommand(name = "createSnapshot", description = "Creates an instant snapshot of a volume.", responseObject = SnapshotResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateSnapshotCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateSnapshotCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// @@ -90,6 +90,15 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { @Parameter(name = ApiConstants.TAGS, type = CommandType.MAP, description = "Map of tags (key/value pairs)") private Map tags; + @Parameter(name = ApiConstants.ZONE_ID_LIST, + type=CommandType.LIST, + collectionType = CommandType.UUID, + entityType = ZoneResponse.class, + description = "A comma-separated list of IDs of the zones in which the snapshot will be made available. " + + "The snapshot will always be made available in the zone in which the volume is present.", + since = "4.19.0") + protected List zoneIds; + private String syncObjectType = BaseAsyncCmd.snapshotHostSyncObject; // /////////////////////////////////////////////////// @@ -148,6 +157,10 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { return _snapshotService.getHostIdForSnapshotOperation(volume); } + public List getZoneIds() { + return zoneIds; + } + // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// // /////////////////////////////////////////////////// @@ -196,7 +209,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { @Override public void create() throws ResourceAllocationException { - Snapshot snapshot = _volumeService.allocSnapshot(getVolumeId(), getPolicyId(), getSnapshotName(), getLocationType()); + Snapshot snapshot = _volumeService.allocSnapshot(getVolumeId(), getPolicyId(), getSnapshotName(), getLocationType(), getZoneIds()); if (snapshot != null) { setEntityId(snapshot.getId()); setEntityUuid(snapshot.getUuid()); @@ -210,7 +223,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { Snapshot snapshot; try { snapshot = - _volumeService.takeSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()), getQuiescevm(), getLocationType(), getAsyncBackup(), getTags()); + _volumeService.takeSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()), getQuiescevm(), getLocationType(), getAsyncBackup(), getTags(), getZoneIds()); if (snapshot != null) { SnapshotResponse response = _responseGenerator.createSnapshotResponse(snapshot); @@ -225,7 +238,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { } String errorMessage = "Failed to create snapshot due to an internal error creating snapshot for volume " + getVolumeUuid(); - s_logger.error(errorMessage, e); + logger.error(errorMessage, e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMessage); } } @@ -242,7 +255,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { } catch (IllegalArgumentException e) { String errMesg = "Invalid locationType " + locationType + "Specified for volume " + getVolumeId() + " Valid values are: primary,secondary "; - s_logger.warn(errMesg); + logger.warn(errMesg); throw new CloudRuntimeException(errMesg); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotFromVMSnapshotCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotFromVMSnapshotCmd.java index 1fd7cfd013b..6bebdc09f59 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotFromVMSnapshotCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotFromVMSnapshotCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.response.SnapshotResponse; import org.apache.cloudstack.api.response.VMSnapshotResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -43,7 +42,6 @@ import com.cloud.vm.snapshot.VMSnapshot; @APICommand(name = "createSnapshotFromVMSnapshot", description = "Creates an instant snapshot of a volume from existing vm snapshot.", responseObject = SnapshotResponse.class, entityType = {Snapshot.class}, since = "4.10.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateSnapshotFromVMSnapshotCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateSnapshotFromVMSnapshotCmd.class.getName()); // /////////////////////////////////////////////////// // ////////////// API parameters ///////////////////// @@ -166,7 +164,7 @@ public class CreateSnapshotFromVMSnapshotCmd extends BaseAsyncCreateCmd { @Override public void execute() { - s_logger.info("CreateSnapshotFromVMSnapshotCmd with vm snapshot id:" + getVMSnapshotId() + " and snapshot id:" + getEntityId() + " starts:" + System.currentTimeMillis()); + logger.info("CreateSnapshotFromVMSnapshotCmd with vm snapshot id:" + getVMSnapshotId() + " and snapshot id:" + getEntityId() + " starts:" + System.currentTimeMillis()); CallContext.current().setEventDetails("Vm Snapshot Id: "+ this._uuidMgr.getUuid(VMSnapshot.class, getVMSnapshotId())); Snapshot snapshot = null; try { @@ -181,14 +179,14 @@ public class CreateSnapshotFromVMSnapshotCmd extends BaseAsyncCreateCmd { } catch (InvalidParameterValueException ex) { throw ex; } catch (Exception e) { - s_logger.debug("Failed to create snapshot", e); + logger.debug("Failed to create snapshot", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create snapshot due to an internal error creating snapshot from vm snapshot " + getVMSnapshotId()); } finally { if (snapshot == null) { try { - _snapshotService.deleteSnapshot(getEntityId()); + _snapshotService.deleteSnapshot(getEntityId(), null); } catch (Exception e) { - s_logger.debug("Failed to clean failed snapshot" + getEntityId()); + logger.debug("Failed to clean failed snapshot" + getEntityId()); } } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java index a3b798405eb..e30b897db2e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java @@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.user.snapshot; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.cloudstack.acl.RoleType; @@ -30,8 +31,8 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SnapshotPolicyResponse; import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.commons.collections.MapUtils; -import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; @@ -43,7 +44,6 @@ import com.cloud.user.Account; @APICommand(name = "createSnapshotPolicy", description = "Creates a snapshot policy for the account.", responseObject = SnapshotPolicyResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateSnapshotPolicyCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateSnapshotPolicyCmd.class.getName()); ///////////////////////////////////////////////////// @@ -75,6 +75,14 @@ public class CreateSnapshotPolicyCmd extends BaseCmd { @Parameter(name = ApiConstants.TAGS, type = CommandType.MAP, description = "Map of tags (key/value pairs)") private Map tags; + @Parameter(name = ApiConstants.ZONE_ID_LIST, + type=CommandType.LIST, + collectionType = CommandType.UUID, + entityType = ZoneResponse.class, + description = "A list of IDs of the zones in which the snapshots will be made available." + + "The snapshots will always be made available in the zone in which the volume is present.") + protected List zoneIds; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -107,6 +115,10 @@ public class CreateSnapshotPolicyCmd extends BaseCmd { return display; } + public List getZoneIds() { + return zoneIds; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java index 8530e0ff584..a0a8cfac9bd 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java @@ -16,7 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.snapshot; -import org.apache.log4j.Logger; +import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -38,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteSnapshot", description = "Deletes a snapshot of a disk volume.", responseObject = SuccessResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSnapshotCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteSnapshotCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -48,6 +47,10 @@ public class DeleteSnapshotCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = SnapshotResponse.class, required=true, description="The ID of the snapshot") private Long id; + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class, + description="The ID of the zone for the snapshot", since = "4.19.0") + private Long zoneId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -57,6 +60,10 @@ public class DeleteSnapshotCmd extends BaseAsyncCmd { return id; } + public Long getZoneId() { + return zoneId; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -94,7 +101,7 @@ public class DeleteSnapshotCmd extends BaseAsyncCmd { @Override public void execute() { CallContext.current().setEventDetails("Snapshot Id: " + this._uuidMgr.getUuid(Snapshot.class, getId())); - boolean result = _snapshotService.deleteSnapshot(getId()); + boolean result = _snapshotService.deleteSnapshot(getId(), getZoneId()); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); setResponseObject(response); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotPoliciesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotPoliciesCmd.java index 1a72b22f06c..6f4b60dc8b2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotPoliciesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotPoliciesCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.snapshot; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteSnapshotPolicies", description = "Deletes snapshot policies for the account.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSnapshotPoliciesCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteSnapshotPoliciesCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotPoliciesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotPoliciesCmd.java index e30ee75dee7..126a4080e6d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotPoliciesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotPoliciesCmd.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.List; import org.apache.cloudstack.acl.RoleType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listSnapshotPolicies", description = "Lists snapshot policies.", responseObject = SnapshotPolicyResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSnapshotPoliciesCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListSnapshotPoliciesCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java index 0b4a215733c..826c54c2e05 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java @@ -16,28 +16,24 @@ // under the License. package org.apache.cloudstack.api.command.user.snapshot; -import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.SnapshotResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; import com.cloud.storage.Snapshot; -import com.cloud.utils.Pair; @APICommand(name = "listSnapshots", description = "Lists all available snapshots for the account.", responseObject = SnapshotResponse.class, entityType = { - Snapshot.class }, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) + Snapshot.class }, responseView = ResponseObject.ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListSnapshotsCmd.class.getName()); ///////////////////////////////////////////////////// @@ -65,6 +61,13 @@ public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd { @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, description = "list snapshots by zone id") private Long zoneId; + @Parameter(name = ApiConstants.SHOW_UNIQUE, type = CommandType.BOOLEAN, description = "If set to false, list templates across zones and their storages", since = "4.19.0") + private Boolean showUnique; + + @Parameter(name = ApiConstants.LOCATION_TYPE, type = CommandType.STRING, description = "list snapshots by location type. Used only when showunique=false. " + + "Valid location types: 'primary', 'secondary'. Default is empty", since = "4.19.0") + private String locationType; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -93,6 +96,28 @@ public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd { return zoneId; } + public boolean isShowUnique() { + if (Boolean.FALSE.equals(showUnique)) { + return false; + } + return true; + } + + public String getLocationType() { + if (!isShowUnique()) { + return locationType; + } + return null; + } + + public Long getImageStoreId() { + return null; + } + + public Long getStoragePoolId() { + return null; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -104,15 +129,7 @@ public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd { @Override public void execute() { - Pair, Integer> result = _snapshotService.listSnapshots(this); - ListResponse response = new ListResponse(); - List snapshotResponses = new ArrayList(); - for (Snapshot snapshot : result.first()) { - SnapshotResponse snapshotResponse = _responseGenerator.createSnapshotResponse(snapshot); - snapshotResponse.setObjectName("snapshot"); - snapshotResponses.add(snapshotResponse); - } - response.setResponses(snapshotResponses, result.second()); + ListResponse response = _queryService.listSnapshots(this); response.setResponseName(getCommandName()); setResponseObject(response); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java index e65a03812d6..fe3b4da0160 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java @@ -30,7 +30,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SnapshotResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.storage.Snapshot; @@ -39,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "revertSnapshot", description = "This is supposed to revert a volume snapshot. This command is only supported with KVM so far", responseObject = SnapshotResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RevertSnapshotCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RevertSnapshotCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/UpdateSnapshotPolicyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/UpdateSnapshotPolicyCmd.java index 0bedbe66199..e7feb11f4af 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/UpdateSnapshotPolicyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/UpdateSnapshotPolicyCmd.java @@ -33,13 +33,11 @@ import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SnapshotPolicyResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; @APICommand(name = "updateSnapshotPolicy", description = "Updates the snapshot policy.", responseObject = SnapshotPolicyResponse.class, responseView = ResponseObject.ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateSnapshotPolicyCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateSnapshotPolicyCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java index 28bdd4d57f6..5212779e965 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.ssh; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,7 +31,6 @@ import com.cloud.user.SSHKeyPair; @APICommand(name = "createSSHKeyPair", description = "Create a new keypair and returns the private key", responseObject = CreateSSHKeyPairResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class CreateSSHKeyPairCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateSSHKeyPairCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -95,5 +93,4 @@ public class CreateSSHKeyPairCmd extends BaseCmd { response.setObjectName("keypair"); setResponseObject(response); } - - } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java index 39c65c181c5..364ca77ae1f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.ssh; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.SSHKeyPair; @APICommand(name = "deleteSSHKeyPair", description = "Deletes a keypair by name", responseObject = SuccessResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSSHKeyPairCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteSSHKeyPairCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java index 71fbb66a337..6bf8dca864b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.ssh; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listSSHKeyPairs", description = "List registered keypairs", responseObject = SSHKeyPairResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSSHKeyPairsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListSSHKeyPairsCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java index 8bacfde7f73..6a0c0541bb4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.ssh; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -32,7 +31,6 @@ import com.cloud.user.SSHKeyPair; @APICommand(name = "registerSSHKeyPair", description = "Register a public key in a keypair under a certain name", responseObject = SSHKeyPairResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RegisterSSHKeyPairCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(RegisterSSHKeyPairCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java index 67705859419..30904db46c4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java @@ -20,7 +20,6 @@ package org.apache.cloudstack.api.command.user.tag; import java.util.List; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,6 @@ import com.cloud.server.ResourceTag.ResourceObjectType; @APICommand(name = "createTags", description = "Creates resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0", entityType = {ResourceTag.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateTagsCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(CreateTagsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java index 55dec6e9645..f8f319eba23 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java @@ -23,7 +23,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,6 @@ import com.cloud.server.ResourceTag.ResourceObjectType; @APICommand(name = "deleteTags", description = "Deleting resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0", entityType = {ResourceTag.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteTagsCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteTagsCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java index f672d4c8890..f094bc43507 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmd.java @@ -31,7 +31,6 @@ import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.event.EventTypes; @@ -43,7 +42,6 @@ import com.cloud.user.Account; @APICommand(name = "copyTemplate", description = "Copies a template from one zone to another.", responseObject = TemplateResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CopyTemplateCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(CopyTemplateCmd.class.getName()); private static final String s_name = "copytemplateresponse"; ///////////////////////////////////////////////////// @@ -191,7 +189,7 @@ public class CopyTemplateCmd extends BaseAsyncCmd implements UserCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to copy template"); } } catch (StorageUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java index ea4b5995bf3..0a7bf291843 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java @@ -21,17 +21,6 @@ import java.util.List; import java.util.Map; import org.apache.cloudstack.acl.SecurityChecker; -import org.apache.cloudstack.api.command.user.UserCmd; -import org.apache.cloudstack.api.response.GuestOSResponse; -import org.apache.cloudstack.api.response.SnapshotResponse; -import org.apache.cloudstack.api.response.TemplateResponse; -import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.cloudstack.api.response.VolumeResponse; -import org.apache.cloudstack.api.response.ProjectResponse; - -import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; @@ -40,13 +29,22 @@ import org.apache.cloudstack.api.BaseAsyncCreateCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.user.UserCmd; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.GuestOSResponse; +import org.apache.cloudstack.api.response.ProjectResponse; +import org.apache.cloudstack.api.response.SnapshotResponse; +import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; +import org.apache.commons.lang3.StringUtils; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; -import com.cloud.projects.Project; import com.cloud.storage.Snapshot; import com.cloud.storage.Volume; import com.cloud.template.VirtualMachineTemplate; @@ -56,7 +54,6 @@ import com.cloud.user.Account; + "A template created from this command is automatically designated as a private template visible to the account that created it.", responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(CreateTemplateCmd.class.getName()); private static final String s_name = "createtemplateresponse"; // /////////////////////////////////////////////////// @@ -135,6 +132,22 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd { @Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "create template for the project") private Long projectId; + @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, description = "the zone for the template. Can be specified with snapshot only", since = "4.19.0") + private Long zoneId; + + @Parameter(name = ApiConstants.DOMAIN_ID, + type = CommandType.UUID, + entityType = DomainResponse.class, + description = "an optional domainId. If the account parameter is used, domainId must also be used.", + since = "4.19.0") + private Long domainId; + + @Parameter(name = ApiConstants.ACCOUNT, + type = CommandType.STRING, + description = "an optional accountName. Must be used with domainId.", + since = "4.19.0") + private String accountName; + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// @@ -209,6 +222,18 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd { return isDynamicallyScalable == null ? false : isDynamicallyScalable; } + public Long getZoneId() { + return zoneId; + } + + public Long getDomainId() { + return domainId; + } + + public String getAccountName() { + return accountName; + } + // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// // /////////////////////////////////////////////////// @@ -224,47 +249,12 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd { @Override public long getEntityOwnerId() { - Long volumeId = getVolumeId(); - Long snapshotId = getSnapshotId(); Account callingAccount = CallContext.current().getCallingAccount(); - if (volumeId != null) { - Volume volume = _entityMgr.findById(Volume.class, volumeId); - if (volume != null) { - _accountService.checkAccess(callingAccount, SecurityChecker.AccessType.UseEntry, false, volume); - } else { - throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId); - } - } else { - Snapshot snapshot = _entityMgr.findById(Snapshot.class, snapshotId); - if (snapshot != null) { - _accountService.checkAccess(callingAccount, SecurityChecker.AccessType.UseEntry, false, snapshot); - } else { - throw new InvalidParameterValueException("Unable to find snapshot by id=" + snapshotId); - } - } - - if(projectId != null){ - final Project project = _projectService.getProject(projectId); - if (project != null) { - if (project.getState() == Project.State.Active) { - Account projectAccount= _accountService.getAccount(project.getProjectAccountId()); - _accountService.checkAccess(callingAccount, SecurityChecker.AccessType.UseEntry, false, projectAccount); - return project.getProjectAccountId(); - } else { - final PermissionDeniedException ex = - new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() + - " as it's no longer active"); - ex.addProxyObject(project.getUuid(), "projectId"); - throw ex; - } - } else { - throw new InvalidParameterValueException("Unable to find project by id"); - } - } - - return callingAccount.getId(); + ensureAccessCheck(callingAccount); + return findAccountIdToUse(callingAccount); } + @Override public String getEventType() { return EventTypes.EVENT_TEMPLATE_CREATE; @@ -322,4 +312,47 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd { } } + + /*** + * Performs access check on volume and snapshot for given account + * @param account + */ + private void ensureAccessCheck(Account account) { + if (volumeId != null) { + Volume volume = _entityMgr.findById(Volume.class, volumeId); + if (volume != null) { + _accountService.checkAccess(account, SecurityChecker.AccessType.UseEntry, false, volume); + } else { + throw new InvalidParameterValueException("Unable to find volume by id=" + volumeId); + } + } else { + Snapshot snapshot = _entityMgr.findById(Snapshot.class, snapshotId); + if (snapshot != null) { + _accountService.checkAccess(account, SecurityChecker.AccessType.UseEntry, false, snapshot); + } else { + throw new InvalidParameterValueException("Unable to find snapshot by id=" + snapshotId); + } + } + } + + /*** + * Find accountId based on accountName and domainId or projectId + * if not found, return callingAccountId for further use + * @param callingAccount + * @return accountId + */ + private Long findAccountIdToUse(Account callingAccount) { + Long accountIdToUse = null; + try { + accountIdToUse = _accountService.finalyzeAccountId(accountName, domainId, projectId, true); + } catch (InvalidParameterValueException | PermissionDeniedException ex) { + if (logger.isDebugEnabled()) { + logger.debug(String.format("An exception occurred while finalizing account id with accountName, domainId and projectId" + + "using callingAccountId=%s", callingAccount.getUuid()), ex); + } + logger.warn("Unable to find accountId associated with accountName=" + accountName + " and domainId=" + + domainId + " or projectId=" + projectId + ", using callingAccountId=" + callingAccount.getUuid()); + } + return accountIdToUse != null ? accountIdToUse : callingAccount.getAccountId(); + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/DeleteTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/DeleteTemplateCmd.java index 6923751ea77..245baf1e07e 100755 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/DeleteTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/DeleteTemplateCmd.java @@ -16,7 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.template; -import org.apache.log4j.Logger; +import org.apache.commons.lang3.BooleanUtils; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -39,7 +39,6 @@ import com.cloud.user.Account; description = "Deletes a template from the system. All virtual machines using the deleted template will not be affected.", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteTemplateCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteTemplateCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -67,8 +66,9 @@ public class DeleteTemplateCmd extends BaseAsyncCmd { } public boolean isForced() { - return (forced != null) ? forced : true; + return BooleanUtils.toBooleanDefaultIfNull(forced, false); } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/DeleteVnfTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/DeleteVnfTemplateCmd.java new file mode 100755 index 00000000000..c2c712cd2bb --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/DeleteVnfTemplateCmd.java @@ -0,0 +1,47 @@ +// 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.user.template; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.response.SuccessResponse; + +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.user.Account; + +@APICommand(name = "deleteVnfTemplate", + responseObject = SuccessResponse.class, + description = "Deletes a VNF template from the system. All virtual machines using the deleted template will not be affected.", + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}, + since = "4.19.0") +public class DeleteVnfTemplateCmd extends DeleteTemplateCmd { + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public long getEntityOwnerId() { + VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, getId()); + if (template != null) { + return template.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java index 91e8d168ecb..ce6ba5e300c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/ExtractTemplateCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.response.ExtractResponse; import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.event.EventTypes; @@ -38,7 +37,6 @@ import com.cloud.user.Account; @APICommand(name = "extractTemplate", description = "Extracts a template", responseObject = ExtractResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ExtractTemplateCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ExtractTemplateCmd.class.getName()); ///////////////////////////////////////////////////// @@ -129,7 +127,7 @@ public class ExtractTemplateCmd extends BaseAsyncCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to extract template"); } } catch (InternalErrorException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/GetUploadParamsForTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/GetUploadParamsForTemplateCmd.java index 3a9e1c8b429..c878fda8240 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/GetUploadParamsForTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/GetUploadParamsForTemplateCmd.java @@ -33,7 +33,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.GetUploadParamsResponse; import org.apache.cloudstack.api.response.GuestOSResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; +import org.apache.commons.lang3.StringUtils; import com.cloud.exception.ResourceAllocationException; @@ -42,11 +42,10 @@ import com.cloud.exception.ResourceAllocationException; authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class GetUploadParamsForTemplateCmd extends AbstractGetUploadParamsCmd { - public static final Logger s_logger = Logger.getLogger(GetUploadParamsForTemplateCmd.class.getName()); private static final String s_name = "postuploadtemplateresponse"; - @Parameter(name = ApiConstants.DISPLAY_TEXT, type = CommandType.STRING, required = true, description = "the display text of the template. This is usually used for display purposes.", length = 4096) + @Parameter(name = ApiConstants.DISPLAY_TEXT, type = CommandType.STRING, description = "the display text of the template. This is usually used for display purposes.", length = 4096) private String displayText; @Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, required = true, description = "the target hypervisor for the template") @@ -95,7 +94,7 @@ public class GetUploadParamsForTemplateCmd extends AbstractGetUploadParamsCmd { private Boolean deployAsIs; public String getDisplayText() { - return displayText; + return StringUtils.isBlank(displayText) ? getName() : displayText; } public String getHypervisor() { @@ -171,7 +170,7 @@ public class GetUploadParamsForTemplateCmd extends AbstractGetUploadParamsCmd { response.setResponseName(getCommandName()); setResponseObject(response); } catch (ResourceAllocationException | MalformedURLException e) { - s_logger.error("exception while registering template", e); + logger.error("exception while registering template", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "exception while registering template: " + e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListTemplatePermissionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListTemplatePermissionsCmd.java index 970c6b34743..6d544df4187 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListTemplatePermissionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListTemplatePermissionsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.template; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd; @@ -40,11 +39,6 @@ public class ListTemplatePermissionsCmd extends BaseListTemplateOrIsoPermissions return "template"; } - @Override - protected Logger getLogger() { - return Logger.getLogger(ListTemplatePermissionsCmd.class.getName()); - } - @Override protected boolean templateIsCorrectType(VirtualMachineTemplate template) { return !template.getFormat().equals(ImageFormat.ISO); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java index a64ce195c0f..113080257d0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java @@ -21,9 +21,9 @@ import com.cloud.server.ResourceIcon; import com.cloud.server.ResourceTag; import org.apache.cloudstack.api.response.ResourceIconResponse; import org.apache.commons.collections.CollectionUtils; -import org.apache.log4j.Logger; import java.util.ArrayList; +import java.util.Collections; import java.util.EnumSet; import java.util.List; import org.apache.cloudstack.api.APICommand; @@ -45,7 +45,6 @@ import com.cloud.user.Account; @APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {VirtualMachineTemplate.class}, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListTemplatesCmd.class.getName()); private static final String s_name = "listtemplatesresponse"; @@ -96,6 +95,15 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User description = "comma separated list of template details requested, value can be a list of [ all, min]") private List viewDetails; + @Parameter(name = ApiConstants.TEMPLATE_TYPE, type = CommandType.STRING, + description = "the type of the template", since = "4.19.0") + private String templateType; + + @Parameter(name = ApiConstants.IS_VNF, type = CommandType.BOOLEAN, + description = "flag to list VNF templates or not; true if need to list VNF templates, false otherwise.", + since = "4.19.0") + private Boolean isVnf; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -151,6 +159,10 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User return parentTemplateId; } + public String getTemplateType() { + return templateType; + } + public boolean listInReadyState() { Account account = CallContext.current().getCallingAccount(); @@ -175,6 +187,10 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User return showIcon != null ? showIcon : false; } + public Boolean getVnf() { + return isVnf; + } + @Override public String getCommandName() { return s_name; @@ -207,6 +223,17 @@ public class ListTemplatesCmd extends BaseListTaggedResourcesCmd implements User } public List getIds() { + if (ids == null) { + return Collections.emptyList(); + } return ids; } + + public Long getImageStoreId() { + return null; + } + + public Long getStoragePoolId() { + return null; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListVnfTemplatesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListVnfTemplatesCmd.java new file mode 100644 index 00000000000..0a98a159527 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/ListVnfTemplatesCmd.java @@ -0,0 +1,33 @@ +// 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.user.template; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.user.UserCmd; +import org.apache.cloudstack.api.response.TemplateResponse; + +import com.cloud.template.VirtualMachineTemplate; + +@APICommand(name = "listVnfTemplates", description = "List all public, private, and privileged VNF templates.", + responseObject = TemplateResponse.class, entityType = {VirtualMachineTemplate.class}, responseView = ResponseView.Restricted, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}, + since = "4.19.0") +public class ListVnfTemplatesCmd extends ListTemplatesCmd implements UserCmd { +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java index 5709e3ed900..1e5c4af9c15 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java @@ -41,7 +41,6 @@ import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.exception.ResourceAllocationException; import com.cloud.template.VirtualMachineTemplate; @@ -49,7 +48,6 @@ import com.cloud.template.VirtualMachineTemplate; @APICommand(name = "registerTemplate", description = "Registers an existing template into the CloudStack cloud. ", responseObject = TemplateResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RegisterTemplateCmd extends BaseCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(RegisterTemplateCmd.class.getName()); private static final String s_name = "registertemplateresponse"; @@ -143,6 +141,7 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd { description = "true if template contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory") protected Boolean isDynamicallyScalable; + @Deprecated @Parameter(name = ApiConstants.ROUTING, type = CommandType.BOOLEAN, description = "true if the template type is routing i.e., if template is used to deploy router") protected Boolean isRoutingType; @@ -168,6 +167,11 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd { description = "(VMware only) true if VM deployments should preserve all the configurations defined for this template", since = "4.15.1") protected Boolean deployAsIs; + @Parameter(name = ApiConstants.TEMPLATE_TYPE, type = CommandType.STRING, + description = "the type of the template. Valid options are: USER/VNF (for all users) and SYSTEM/ROUTING/BUILTIN (for admins only).", + since = "4.19.0") + private String templateType; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -285,6 +289,10 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd { Boolean.TRUE.equals(deployAsIs); } + public String getTemplateType() { + return templateType; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -315,7 +323,7 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd { VirtualMachineTemplate template = _templateService.registerTemplate(this); if (template != null) { - ListResponse response = new ListResponse(); + ListResponse response = new ListResponse<>(); List templateResponses = _responseGenerator.createTemplateResponses(getResponseView(), template, getZoneIds(), false); response.setResponses(templateResponses); @@ -325,7 +333,7 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to register template"); } } catch (URISyntaxException ex1) { - s_logger.info(ex1); + logger.info(ex1); throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex1.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterVnfTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterVnfTemplateCmd.java new file mode 100644 index 00000000000..c3e99d5791f --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterVnfTemplateCmd.java @@ -0,0 +1,79 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.template; + +import java.util.List; +import java.util.Map; + +import com.cloud.network.VNF; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.user.UserCmd; +import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.storage.template.VnfTemplateUtils; + +@APICommand(name = "registerVnfTemplate", + description = "Registers an existing VNF template into the CloudStack cloud. ", + responseObject = TemplateResponse.class, responseView = ResponseView.Restricted, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}, + since = "4.19.0") +public class RegisterVnfTemplateCmd extends RegisterTemplateCmd implements UserCmd { + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.VNF_NICS, + type = CommandType.MAP, + description = "VNF nics in key/value pairs using format vnfnics[i].keyname=keyvalue. " + + " Example: vnfnics[0].deviceid=0&&vnfnics[0].name=FirstNIC&&vnfnics[0].required=true" + + "&&vnfnics[1].deviceid=1&&vnfnics[1].name=SecondNIC") + protected Map vnfNics; + + @Parameter(name = ApiConstants.VNF_DETAILS, + type = CommandType.MAP, + description = "VNF details in key/value pairs using format vnfdetails[i].keyname=keyvalue. " + + "Example: vnfdetails[0].vendor=xxx&&vnfdetails[0].version=2.0") + protected Map vnfDetails; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public List getVnfNics() { + return VnfTemplateUtils.getVnfNicsList(this.vnfNics); + } + + public Map getVnfDetails() { + return convertDetailsToMap(vnfDetails); + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + protected void validateParameters() { + super.validateParameters(); + + VnfTemplateUtils.validateApiCommandParams(this, null); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java index 28ecd453d26..dbbd771293a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmd.java @@ -16,10 +16,9 @@ // under the License. package org.apache.cloudstack.api.command.user.template; -import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; import org.apache.cloudstack.api.Parameter; @@ -34,16 +33,19 @@ import com.cloud.user.Account; @APICommand(name = "updateTemplate", description = "Updates attributes of a template.", responseObject = TemplateResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(UpdateTemplateCmd.class.getName()); private static final String s_name = "updatetemplateresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name = "templatetype", type = CommandType.STRING, description = "the type of the template") + @Parameter(name = ApiConstants.TEMPLATE_TYPE, type = CommandType.STRING, + description = "the type of the template. Valid options are: USER/VNF (for all users) and SYSTEM/ROUTING/BUILTIN (for admins only).") private String templateType; + @Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.", since = "4.20.0") + private String templateTag; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -57,6 +59,10 @@ public class UpdateTemplateCmd extends BaseUpdateTemplateOrIsoCmd implements Use return templateType; } + public String getTemplateTag() { + return templateTag; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java index 7cf5e0bc3f5..de8f09a6400 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.template; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd; @@ -35,10 +34,6 @@ public class UpdateTemplatePermissionsCmd extends BaseUpdateTemplateOrIsoPermiss return "updatetemplatepermissionsresponse"; } - @Override - protected Logger getLogger() { - return Logger.getLogger(UpdateTemplatePermissionsCmd.class.getName()); - } @Override public long getEntityOwnerId() { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateVnfTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateVnfTemplateCmd.java new file mode 100644 index 00000000000..7479dd3be09 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/UpdateVnfTemplateCmd.java @@ -0,0 +1,87 @@ +// 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.user.template; + +import com.cloud.network.VNF; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.user.UserCmd; +import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.storage.template.VnfTemplateUtils; + +import java.util.List; +import java.util.Map; + +@APICommand(name = "updateVnfTemplate", description = "Updates a template to VNF template or attributes of a VNF template.", + responseObject = TemplateResponse.class, responseView = ResponseView.Restricted, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}, + since = "4.19.0") +public class UpdateVnfTemplateCmd extends UpdateTemplateCmd implements UserCmd { + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.VNF_NICS, + type = CommandType.MAP, + description = "VNF nics in key/value pairs using format vnfnics[i].keyname=keyvalue. " + + " Example: vnfnics[0].deviceid=0&&vnfnics[0].name=FirstNIC&&vnfnics[0].required=true" + + "&&vnfnics[1].deviceid=1&&vnfnics[1].name=SecondNIC") + protected Map vnfNics; + + @Parameter(name = ApiConstants.VNF_DETAILS, + type = CommandType.MAP, + description = "VNF details in key/value pairs using format vnfdetails[i].keyname=keyvalue. " + + "Example: vnfdetails[0].vendor=xxx&&vnfdetails[0].version=2.0") + protected Map vnfDetails; + + @Parameter(name = ApiConstants.CLEAN_UP_VNF_DETAILS, + type = CommandType.BOOLEAN, + description = "optional boolean field, which indicates if VNF details will be cleaned up or not") + private Boolean cleanupVnfDetails = null; + + @Parameter(name = ApiConstants.CLEAN_UP_VNF_NICS, + type = CommandType.BOOLEAN, + description = "optional boolean field, which indicates if VNF nics will be cleaned up or not") + private Boolean cleanupVnfNics = null; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public List getVnfNics() { + return VnfTemplateUtils.getVnfNicsList(this.vnfNics); + } + + public Map getVnfDetails() { + return convertDetailsToMap(vnfDetails); + } + + public boolean isCleanupVnfDetails(){ + return cleanupVnfDetails == null ? false : cleanupVnfDetails.booleanValue(); + } + + public boolean isCleanupVnfNics(){ + return cleanupVnfNics == null ? false : cleanupVnfNics.booleanValue(); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/DeleteUserDataCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/DeleteUserDataCmd.java index d27b90f07a1..a1d1afc7b05 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/DeleteUserDataCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/DeleteUserDataCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.UserDataResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.user.Account; import com.cloud.user.UserData; @@ -39,7 +38,6 @@ import com.cloud.user.UserData; authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class DeleteUserDataCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteUserDataCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/LinkUserDataToTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/LinkUserDataToTemplateCmd.java index be1a95c3694..e322de00bb1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/LinkUserDataToTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/LinkUserDataToTemplateCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.admin.AdminCmd; import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.UserDataResponse; -import org.apache.log4j.Logger; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; @@ -39,7 +38,6 @@ import com.cloud.utils.exception.CloudRuntimeException; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.18.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class LinkUserDataToTemplateCmd extends BaseCmd implements AdminCmd { - public static final Logger s_logger = Logger.getLogger(LinkUserDataToTemplateCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/ListUserDataCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/ListUserDataCmd.java index aa30066c2a3..64ab3ec3d70 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/ListUserDataCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/ListUserDataCmd.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UserDataResponse; -import org.apache.log4j.Logger; import com.cloud.user.UserData; import com.cloud.utils.Pair; @@ -35,7 +34,6 @@ import com.cloud.utils.Pair; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.18", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ListUserDataCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListUserDataCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -76,5 +74,4 @@ public class ListUserDataCmd extends BaseListProjectAndAccountResourcesCmd { response.setResponseName(getCommandName()); setResponseObject(response); } - - } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmd.java index a8a87c40725..41d865d678c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmd.java @@ -32,7 +32,6 @@ import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.UserDataResponse; import org.apache.cloudstack.context.CallContext; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -52,7 +51,6 @@ import com.cloud.user.UserData; authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class RegisterUserDataCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(RegisterUserDataCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -74,7 +72,14 @@ public class RegisterUserDataCmd extends BaseCmd { @Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "an optional project for the userdata") private Long projectId; - @Parameter(name = ApiConstants.USER_DATA, type = CommandType.STRING, required = true, description = "Userdata content", length = 1048576) + @Parameter(name = ApiConstants.USER_DATA, + type = CommandType.STRING, + required = true, + description = "Base64 encoded userdata content. " + + "Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. " + + "Using HTTP POST (via POST body), you can send up to 1MB of data after base64 encoding. " + + "You also need to change vm.userdata.max.length value", + length = 1048576) private String userData; @Parameter(name = ApiConstants.PARAMS, type = CommandType.STRING, description = "comma separated list of variables declared in userdata content") @@ -142,5 +147,4 @@ public class RegisterUserDataCmd extends BaseCmd { response.setObjectName(ApiConstants.USER_DATA); setResponseObject(response); } - - } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java index fc009c7e5db..0dc3dcdbdcc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.NicResponse; import org.apache.cloudstack.api.response.NicSecondaryIpResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.event.EventTypes; @@ -46,7 +45,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "addIpToNic", description = "Assigns secondary IP to NIC", responseObject = NicSecondaryIpResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddIpToVmNicCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(AddIpToVmNicCmd.class.getName()); private static final String s_name = "addiptovmnicresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java index 1e395831a6f..ecd066d98cd 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java @@ -37,7 +37,6 @@ import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -51,7 +50,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "addNicToVirtualMachine", description = "Adds VM to specified network by creating a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class AddNicToVMCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(AddNicToVMCmd.class); private static final String s_name = "addnictovirtualmachineresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmd.java index 935f39bf4dd..5811eb1abfc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmd.java @@ -68,7 +68,7 @@ public class CreateVMScheduleCmd extends BaseCmd { @Parameter(name = ApiConstants.ACTION, type = CommandType.STRING, required = true, - description = "Action to take on the VM (start/stop/restart/force_stop/force_reboot).") + description = "Action to take on the VM (start/stop/reboot/force_stop/force_reboot).") private String action; @Parameter(name = ApiConstants.START_DATE, diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java index c140a1e1c22..68dd49d9ce5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java @@ -56,7 +56,6 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import com.cloud.agent.api.LogLevel; import com.cloud.event.EventTypes; @@ -80,7 +79,6 @@ import com.cloud.vm.VmDetailConstants; @APICommand(name = "deployVirtualMachine", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityGroupAction, UserCmd { - public static final Logger s_logger = Logger.getLogger(DeployVMCmd.class.getName()); private static final String s_name = "deployvirtualmachineresponse"; @@ -105,6 +103,10 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG @Parameter(name = ApiConstants.DISPLAY_NAME, type = CommandType.STRING, description = "an optional user generated name for the virtual machine") private String displayName; + @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, description="The password of the virtual machine. If null, a random password will be generated for the VM.", + since="4.19.0.0") + protected String password; + //Owner information @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional account for the virtual machine. Must be used with domainId.") private String accountName; @@ -152,7 +154,11 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG private String hypervisor; @Parameter(name = ApiConstants.USER_DATA, type = CommandType.STRING, - description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. This binary data must be base64 encoded before adding it to the request. Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. Using HTTP POST(via POST body), you can send up to 1MB of data after base64 encoding.", + description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. " + + "This binary data must be base64 encoded before adding it to the request. " + + "Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. " + + "Using HTTP POST (via POST body), you can send up to 1MB of data after base64 encoding. " + + "You also need to change vm.userdata.max.length value", length = 1048576) private String userData; @@ -309,7 +315,7 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG } catch (IllegalArgumentException e) { String errMesg = "Invalid bootType " + bootType + "Specified for vm " + getName() + " Valid values are: " + Arrays.toString(ApiConstants.BootType.values()); - s_logger.warn(errMesg); + logger.warn(errMesg); throw new InvalidParameterValueException(errMesg); } } @@ -356,14 +362,14 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG } catch (IllegalArgumentException e) { String msg = String.format("Invalid %s: %s specified for VM: %s. Valid values are: %s", ApiConstants.BOOT_MODE, bootMode, getName(), Arrays.toString(ApiConstants.BootMode.values())); - s_logger.error(msg); + logger.error(msg); throw new InvalidParameterValueException(msg); } } if (ApiConstants.BootType.UEFI.equals(getBootType())) { String msg = String.format("%s must be specified for the VM with boot type: %s. Valid values are: %s", ApiConstants.BOOT_MODE, getBootType(), Arrays.toString(ApiConstants.BootMode.values())); - s_logger.error(msg); + logger.error(msg); throw new InvalidParameterValueException(msg); } return null; @@ -396,8 +402,8 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG nic = null; } String networkUuid = entry.get(VmDetailConstants.NETWORK); - if (s_logger.isTraceEnabled()) { - s_logger.trace(String.format("nic, '%s', goes on net, '%s'", nic, networkUuid)); + if (logger.isTraceEnabled()) { + logger.trace(String.format("nic, '%s', goes on net, '%s'", nic, networkUuid)); } if (nic == null || StringUtils.isEmpty(networkUuid) || _entityMgr.findByUuid(Network.class, networkUuid) == null) { throw new InvalidParameterValueException(String.format("Network ID: %s for NIC ID: %s is invalid", networkUuid, nic)); @@ -464,6 +470,10 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG return zoneId; } + public String getPassword() { + return password; + } + public List getNetworkIds() { if (MapUtils.isNotEmpty(vAppNetworks)) { if (CollectionUtils.isNotEmpty(networkIds) || ipAddress != null || getIp6Address() != null || MapUtils.isNotEmpty(ipToNetworkList)) { @@ -703,7 +713,7 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG return ApiConstants.IoDriverPolicy.valueOf(policyType); } catch (IllegalArgumentException e) { String errMesg = String.format("Invalid io policy %s specified for vm %s. Valid values are: %s", ioDriverPolicy, getName(), Arrays.toString(ApiConstants.IoDriverPolicy.values())); - s_logger.warn(errMesg); + logger.warn(errMesg); throw new InvalidParameterValueException(errMesg); } } @@ -769,13 +779,13 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG try { result = _userVmService.startVirtualMachine(this); } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ResourceAllocationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (InsufficientCapacityException ex) { StringBuilder message = new StringBuilder(ex.getMessage()); @@ -784,12 +794,12 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them"); } } - s_logger.info(String.format("%s: %s", message.toString(), ex.getLocalizedMessage())); - s_logger.debug(message.toString(), ex); + logger.info(String.format("%s: %s", message.toString(), ex.getLocalizedMessage())); + logger.debug(message.toString(), ex); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, message.toString()); } } else { - s_logger.info("VM " + getEntityUuid() + " already created, load UserVm from DB"); + logger.info("VM " + getEntityUuid() + " already created, load UserVm from DB"); result = _userVmService.finalizeCreateVirtualMachine(getEntityId()); } @@ -815,17 +825,17 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd implements SecurityG throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to deploy vm"); } } catch (InsufficientCapacityException ex) { - s_logger.info(ex); - s_logger.trace(ex.getMessage(), ex); + logger.info(ex); + logger.trace(ex.getMessage(), ex); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (ResourceAllocationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVnfApplianceCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVnfApplianceCmd.java new file mode 100644 index 00000000000..4d50dd9c39b --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DeployVnfApplianceCmd.java @@ -0,0 +1,74 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.vm; + +import com.cloud.exception.ResourceAllocationException; +import com.cloud.utils.net.NetUtils; +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.command.user.UserCmd; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.storage.template.VnfTemplateUtils; +import org.apache.commons.collections.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; + +@APICommand(name = "deployVnfAppliance", + description = "Creates and automatically starts a VNF appliance based on a service offering, disk offering, and template.", + responseObject = UserVmResponse.class, + responseView = ResponseObject.ResponseView.Restricted, + entityType = {VirtualMachine.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}, + since = "4.19.0") +public class DeployVnfApplianceCmd extends DeployVMCmd implements UserCmd { + + @Parameter(name = ApiConstants.VNF_CONFIGURE_MANAGEMENT, type = CommandType.BOOLEAN, required = false, + description = "True by default, security group or network rules (source nat and firewall rules) will be configured for VNF management interfaces. False otherwise. " + + "Network rules are configured if management network is an isolated network or shared network with security groups.") + private Boolean vnfConfigureManagement; + + @Parameter(name = ApiConstants.VNF_CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, + description = "the CIDR list to forward traffic from to the VNF management interface. Multiple entries must be separated by a single comma character (,). The default value is 0.0.0.0/0.") + private List vnfCidrlist; + + public Boolean getVnfConfigureManagement() { + return vnfConfigureManagement != null && vnfConfigureManagement; + } + + public List getVnfCidrlist() { + if (CollectionUtils.isNotEmpty(vnfCidrlist)) { + return vnfCidrlist; + } else { + List defaultCidrList = new ArrayList(); + defaultCidrList.add(NetUtils.ALL_IP4_CIDRS); + return defaultCidrList; + } + } + + @Override + public void create() throws ResourceAllocationException { + VnfTemplateUtils.validateVnfCidrList(this.getVnfCidrlist()); + + super.create(); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java index 07fd55276f8..aa121162cb4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.vm; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -46,7 +45,6 @@ import com.cloud.vm.VirtualMachine; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DestroyVMCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(DestroyVMCmd.class.getName()); private static final String s_name = "destroyvirtualmachineresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java index d3cbf82f755..ce6114c7fd8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.vm; import java.security.InvalidParameterException; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -36,7 +35,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "getVMPassword", responseObject = GetVMPasswordResponse.class, description = "Returns an encrypted password for the VM", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class GetVMPasswordCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(GetVMPasswordCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java index 08235c56ca9..0e659fc02a1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListNicsCmd.java @@ -33,7 +33,6 @@ import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.NicResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -45,13 +44,12 @@ import com.cloud.vm.Nic; @APICommand(name = "listNics", description = "list the vm nics IP to NIC", responseObject = NicResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNicsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListNicsCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name = ApiConstants.NIC_ID, type = CommandType.UUID, entityType = NicResponse.class, required = false, description = "the ID of the nic to to list IPs") + @Parameter(name = ApiConstants.NIC_ID, type = CommandType.UUID, entityType = NicResponse.class, required = false, description = "the ID of the nic to list IPs") private Long nicId; @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, required = true, description = "the ID of the vm") @@ -157,7 +155,7 @@ public class ListNicsCmd extends BaseListCmd { this.setResponseObject(response); } } catch (Exception e) { - s_logger.warn("Failed to list secondary ip address per nic "); + logger.warn("Failed to list secondary ip address per nic "); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java index 07d83b47d3c..50e1798112d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java @@ -16,9 +16,10 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import java.util.ArrayList; import java.util.EnumSet; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -45,7 +46,7 @@ import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VpcResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.commons.lang3.BooleanUtils; -import org.apache.log4j.Logger; +import org.apache.commons.collections.CollectionUtils; import com.cloud.exception.InvalidParameterValueException; import com.cloud.server.ResourceIcon; @@ -56,9 +57,7 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListVMsCmd.class.getName()); - private static final String s_name = "listvirtualmachinesresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -96,9 +95,10 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements @Parameter(name = ApiConstants.DETAILS, type = CommandType.LIST, collectionType = CommandType.STRING, - description = "comma separated list of host details requested, " - + "value can be a list of [all, group, nics, stats, secgrp, tmpl, servoff, diskoff, iso, volume, min, affgrp]." - + " If no parameter is passed in, the details will be defaulted to all") + description = "comma separated list of vm details requested, " + + "value can be a list of [all, group, nics, stats, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp]." + + " When no parameters are passed, all the details are returned if list.vm.default.details.stats is true (default)," + + " otherwise when list.vm.default.details.stats is false the API response will exclude the stats details.") private List viewDetails; @Parameter(name = ApiConstants.TEMPLATE_ID, type = CommandType.UUID, entityType = TemplateResponse.class, description = "list vms by template") @@ -189,6 +189,10 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements return zoneId; } + @Parameter(name = ApiConstants.IS_VNF, type = CommandType.BOOLEAN, + description = "flag to list vms created from VNF templates (as known as VNF appliances) or not; true if need to list VNF appliances, false otherwise.", + since = "4.19.0") + private Boolean isVnf; public Long getNetworkId() { return networkId; @@ -235,22 +239,32 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements return autoScaleVmGroupId; } + protected boolean isViewDetailsEmpty() { + return CollectionUtils.isEmpty(viewDetails); + } + public EnumSet getDetails() throws InvalidParameterValueException { - EnumSet dv; - if (viewDetails == null || viewDetails.size() <= 0) { - dv = EnumSet.of(VMDetails.all); - } else { - try { - ArrayList dc = new ArrayList(); - for (String detail : viewDetails) { - dc.add(VMDetails.valueOf(detail)); - } - dv = EnumSet.copyOf(dc); - } catch (IllegalArgumentException e) { - throw new InvalidParameterValueException("The details parameter contains a non permitted value. The allowed values are " + EnumSet.allOf(VMDetails.class)); + if (isViewDetailsEmpty()) { + if (_queryService.ReturnVmStatsOnVmList.value()) { + return EnumSet.of(VMDetails.all); } + + Set allDetails = new HashSet<>(Set.of(VMDetails.values())); + allDetails.remove(VMDetails.stats); + allDetails.remove(VMDetails.all); + return EnumSet.copyOf(allDetails); + } + + try { + Set dc = new HashSet<>(); + for (String detail : viewDetails) { + dc.add(VMDetails.valueOf(detail)); + } + + return EnumSet.copyOf(dc); + } catch (IllegalArgumentException e) { + throw new InvalidParameterValueException("The details parameter contains a non permitted value. The allowed values are " + EnumSet.allOf(VMDetails.class)); } - return dv; } @Override @@ -266,13 +280,13 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements return accumulate; } + public Boolean getVnf() { + return isVnf; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// - @Override - public String getCommandName() { - return s_name; - } @Override public ApiCommandResourceType getApiResourceType() { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVnfAppliancesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVnfAppliancesCmd.java new file mode 100644 index 00000000000..e7bbb97d78c --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVnfAppliancesCmd.java @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.vm; + +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.user.UserCmd; + +import org.apache.cloudstack.api.response.UserVmResponse; + +@APICommand(name = "listVnfAppliances", description = "List VNF appliance owned by the account.", + responseObject = UserVmResponse.class, + responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}, + since = "4.19.1") +public class ListVnfAppliancesCmd extends ListVMsCmd implements UserCmd { + + @Override + public Boolean getVnf() { + return true; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java index 9bdcc1aed56..153f5ea6563 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java @@ -16,8 +16,8 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.log4j.Logger; +import com.cloud.exception.ResourceAllocationException; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -42,7 +42,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "rebootVirtualMachine", description = "Reboots a virtual machine.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RebootVMCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(RebootVMCmd.class.getName()); private static final String s_name = "rebootvirtualmachineresponse"; ///////////////////////////////////////////////////// @@ -115,7 +114,7 @@ public class RebootVMCmd extends BaseAsyncCmd implements UserCmd { } @Override - public void execute() throws ResourceUnavailableException, InsufficientCapacityException { + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException { CallContext.current().setEventDetails("Vm Id: " + this._uuidMgr.getUuid(VirtualMachine.class, getId())); UserVm result; result = _userVmService.rebootVirtualMachine(this); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java index e964cc69231..a4cd6159dfc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -41,7 +40,6 @@ import com.cloud.vm.NicSecondaryIp; @APICommand(name = "removeIpFromNic", description = "Removes secondary IP from the NIC.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RemoveIpFromVmNicCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RemoveIpFromVmNicCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java index 5fd016c38ed..d9024f34022 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.EnumSet; import com.cloud.vm.Nic; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -45,7 +44,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "removeNicFromVirtualMachine", description = "Removes VM from specified network by deleting a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RemoveNicFromVMCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(RemoveNicFromVMCmd.class); private static final String s_name = "removenicfromvirtualmachineresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java index e275a988cd1..7270004aeed 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java @@ -16,7 +16,7 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.log4j.Logger; +import org.apache.commons.lang3.StringUtils; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -44,7 +44,6 @@ import com.cloud.vm.VirtualMachine; "support this feature for this command to take effect. [async]", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ResetVMPasswordCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ResetVMPasswordCmd.class.getName()); private static final String s_name = "resetpasswordforvirtualmachineresponse"; @@ -56,8 +55,7 @@ public class ResetVMPasswordCmd extends BaseAsyncCmd implements UserCmd { required=true, description="The ID of the virtual machine") private Long id; - // unexposed parameter needed for serializing/deserializing the command - @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, expose=false) + @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, description="The new password of the virtual machine. If null, a random password will be generated for the VM.", since="4.19.0") protected String password; @@ -118,7 +116,14 @@ public class ResetVMPasswordCmd extends BaseAsyncCmd implements UserCmd { @Override public void execute() throws ResourceUnavailableException, InsufficientCapacityException { - password = _mgr.generateRandomPassword(); + password = getPassword(); + UserVm vm = _responseGenerator.findUserVmById(getId()); + if (StringUtils.isBlank(password)) { + password = _mgr.generateRandomPassword(); + logger.debug(String.format("Resetting VM [%s] password to a randomly generated password.", vm.getUuid())); + } else { + logger.debug(String.format("Resetting VM [%s] password to password defined by user.", vm.getUuid())); + } CallContext.current().setEventDetails("Vm Id: " + getId()); UserVm result = _userVmService.resetVMPassword(this, password); if (result != null){ diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java index 259cfebbad5..a4019411e1d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.vm; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -50,7 +49,6 @@ import java.util.List; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ResetVMSSHKeyCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ResetVMSSHKeyCmd.class.getName()); private static final String s_name = "resetSSHKeyforvirtualmachineresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMUserDataCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMUserDataCmd.java index 3ead67e2106..0ecf4ff1384 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMUserDataCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ResetVMUserDataCmd.java @@ -37,7 +37,6 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.UserDataResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import java.util.Map; @@ -46,7 +45,6 @@ import java.util.Map; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, since = "4.18.0") public class ResetVMUserDataCmd extends BaseCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ResetVMUserDataCmd.class.getName()); private static final String s_name = "resetuserdataforvirtualmachineresponse"; @@ -62,7 +60,7 @@ public class ResetVMUserDataCmd extends BaseCmd implements UserCmd { description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. " + "This binary data must be base64 encoded before adding it to the request. " + "Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. " + - "Using HTTP POST(via POST body), you can send up to 1MB of data after base64 encoding." + + "Using HTTP POST (via POST body), you can send up to 1MB of data after base64 encoding. " + "You also need to change vm.userdata.max.length value", length = 1048576) private String userData; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java index 4b59bf560cb..3839049eee5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java @@ -16,10 +16,9 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; - +import com.cloud.vm.VmDetailConstants; import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -29,6 +28,7 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.user.UserCmd; +import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.context.CallContext; @@ -42,11 +42,12 @@ import com.cloud.user.Account; import com.cloud.uservm.UserVm; import com.cloud.vm.VirtualMachine; +import java.util.Map; + @APICommand(name = "restoreVirtualMachine", description = "Restore a VM to original template/ISO or new template/ISO", responseObject = UserVmResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RestoreVMCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(RestoreVMCmd.class); private static final String s_name = "restorevmresponse"; @ACL(accessType = AccessType.OperateEntry) @@ -60,6 +61,28 @@ public class RestoreVMCmd extends BaseAsyncCmd implements UserCmd { description = "an optional template Id to restore vm from the new template. This can be an ISO id in case of restore vm deployed using ISO") private Long templateId; + @Parameter(name = ApiConstants.DISK_OFFERING_ID, + type = CommandType.UUID, + entityType = DiskOfferingResponse.class, + description = "Override root volume's diskoffering.", since = "4.19.1") + private Long rootDiskOfferingId; + + @Parameter(name = ApiConstants.ROOT_DISK_SIZE, + type = CommandType.LONG, + description = "Override root volume's size (in GB). Analogous to details[0].rootdisksize, which takes precedence over this parameter if both are provided", + since = "4.19.1") + private Long rootDiskSize; + + @Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, since = "4.19.1", + description = "used to specify the custom parameters") + private Map details; + + @Parameter(name = ApiConstants.EXPUNGE, + type = CommandType.BOOLEAN, + description = "Optional field to expunge old root volume after restore.", + since = "4.19.1") + private Boolean expungeRootDisk; + @Override public String getEventType() { return EventTypes.EVENT_VM_RESTORE; @@ -112,6 +135,22 @@ public class RestoreVMCmd extends BaseAsyncCmd implements UserCmd { return getVmId(); } + public Long getRootDiskOfferingId() { + return rootDiskOfferingId; + } + + public Map getDetails() { + Map customparameterMap = convertDetailsToMap(details); + if (rootDiskSize != null && !customparameterMap.containsKey(VmDetailConstants.ROOT_DISK_SIZE)) { + customparameterMap.put(VmDetailConstants.ROOT_DISK_SIZE, rootDiskSize.toString()); + } + return customparameterMap; + } + + public Boolean getExpungeRootDisk() { + return expungeRootDisk != null && expungeRootDisk; + } + @Override public Long getApiResourceId() { return getId(); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java index 5af45762ece..3af6d5245f0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java @@ -33,7 +33,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -49,7 +48,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "scaleVirtualMachine", description = "Scales the virtual machine to a new service offering. This command also considers the volume size in the service offering or disk offering linked to the new service offering and apply all characteristics to the root volume.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ScaleVMCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ScaleVMCmd.class.getName()); private static final String s_name = "scalevirtualmachineresponse"; ///////////////////////////////////////////////////// @@ -169,16 +167,16 @@ public class ScaleVMCmd extends BaseAsyncCmd implements UserCmd { try { result = _userVmService.upgradeVirtualMachine(this); } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (ManagementServerException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (VirtualMachineMigrationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } if (result != null){ diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java index 10c50dc380b..c0311d59997 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.vm; import org.apache.cloudstack.api.response.ClusterResponse; import org.apache.cloudstack.api.response.PodResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -51,7 +50,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "startVirtualMachine", responseObject = UserVmResponse.class, description = "Starts a virtual machine.", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class StartVMCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(StartVMCmd.class.getName()); private static final String s_name = "startvirtualmachineresponse"; @@ -104,6 +102,10 @@ public class StartVMCmd extends BaseAsyncCmd implements UserCmd { return id; } + public void setId(Long id) { + this.id = id; + } + public Long getHostId() { return hostId; } @@ -188,19 +190,19 @@ public class StartVMCmd extends BaseAsyncCmd implements UserCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to start a vm"); } } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (StorageUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ExecutionException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ResourceAllocationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage()); } catch (InsufficientCapacityException ex) { StringBuilder message = new StringBuilder(ex.getMessage()); @@ -209,8 +211,8 @@ public class StartVMCmd extends BaseAsyncCmd implements UserCmd { message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them"); } } - s_logger.info(ex); - s_logger.info(message.toString(), ex); + logger.info(ex); + logger.info(message.toString(), ex); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, message.toString()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java index 113ba9ed25d..bfd5d8d07f6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -41,7 +40,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "stopVirtualMachine", responseObject = UserVmResponse.class, description = "Stops a virtual machine.", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class StopVMCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(StopVMCmd.class.getName()); private static final String s_name = "stopvirtualmachineresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java index ff533f82095..837bde06a6c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.EnumSet; import com.cloud.vm.Nic; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -45,7 +44,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "updateDefaultNicForVirtualMachine", description = "Changes the default NIC on a VM", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateDefaultNicForVMCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(UpdateDefaultNicForVMCmd.class); private static final String s_name = "updatedefaultnicforvirtualmachineresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java index 32ce1f6db52..024337356fd 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java @@ -23,7 +23,6 @@ import java.util.Map; import com.cloud.utils.exception.CloudRuntimeException; import org.apache.cloudstack.api.response.UserDataResponse; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -54,7 +53,6 @@ import com.cloud.vm.VirtualMachine; "Therefore, stop the VM manually before issuing this call.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction, UserCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVMCmd.class.getName()); private static final String s_name = "updatevirtualmachineresponse"; ///////////////////////////////////////////////////// @@ -86,7 +84,7 @@ public class UpdateVMCmd extends BaseCustomIdCmd implements SecurityGroupAction, description = "an optional binary data that can be sent to the virtual machine upon a successful deployment. " + "This binary data must be base64 encoded before adding it to the request. " + "Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. " + - "Using HTTP POST(via POST body), you can send up to 1MB of data after base64 encoding." + + "Using HTTP POST (via POST body), you can send up to 1MB of data after base64 encoding. " + "You also need to change vm.userdata.max.length value", length = 1048576, since = "4.16.0") diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVmNicIpCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVmNicIpCmd.java index 40658f9b58d..5c654701de9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVmNicIpCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpdateVmNicIpCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.vm; import java.util.ArrayList; import java.util.EnumSet; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -49,7 +48,6 @@ import com.cloud.vm.Nic; @APICommand(name = "updateVmNicIp", description = "Update the default Ip of a VM Nic", responseObject = UserVmResponse.class) public class UpdateVmNicIpCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVmNicIpCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java index 4b31c12ec0a..6a7422e70bb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.vm; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -47,7 +46,6 @@ import com.cloud.vm.VirtualMachine; "this command to take effect.", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpgradeVMCmd extends BaseCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(UpgradeVMCmd.class.getName()); private static final String s_name = "changeserviceforvirtualmachineresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java index 154ec45873a..e2952b5bd81 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vmgroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.vm.InstanceGroup; @APICommand(name = "createInstanceGroup", description = "Creates a vm group", responseObject = InstanceGroupResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVMGroupCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(CreateVMGroupCmd.class.getName()); // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java index 0bdda0bb9e7..b74bc43eeb7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vmgroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -35,7 +34,6 @@ import com.cloud.vm.InstanceGroup; @APICommand(name = "deleteInstanceGroup", description = "Deletes a vm group", responseObject = SuccessResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVMGroupCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteVMGroupCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java index 2e61c898ae0..31845a956e9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vmgroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -30,7 +29,6 @@ import com.cloud.vm.InstanceGroup; @APICommand(name = "listInstanceGroups", description = "Lists vm groups", responseObject = InstanceGroupResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVMGroupsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListVMGroupsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java index 8873c852460..5c553f06404 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vmgroup; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -35,7 +34,6 @@ import com.cloud.vm.InstanceGroup; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVMGroupCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVMGroupCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java index 2c0ea6bc4ae..18a478e9dae 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java @@ -30,7 +30,6 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VMSnapshotResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ResourceAllocationException; @@ -42,7 +41,6 @@ import com.cloud.vm.snapshot.VMSnapshot; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVMSnapshotCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateVMSnapshotCmd.class.getName()); @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, required = true, entityType = UserVmResponse.class, description = "The ID of the vm") @@ -138,4 +136,10 @@ public class CreateVMSnapshotCmd extends BaseAsyncCreateCmd { public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.VmSnapshot; } + + @Override + public Long getApiResourceId() { + return getEntityId(); + } + } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java index bcddc75a8e7..94b8824f868 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.vmsnapshot; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -39,7 +38,6 @@ import com.cloud.vm.snapshot.VMSnapshot; @APICommand(name = "deleteVMSnapshot", description = "Deletes a vmsnapshot.", responseObject = SuccessResponse.class, since = "4.2.0", entityType = {VMSnapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVMSnapshotCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteVMSnapshotCmd.class.getName()); @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.VM_SNAPSHOT_ID, diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/RevertToVMSnapshotCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/RevertToVMSnapshotCmd.java index 42cd18bfa2f..310b45687d4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/RevertToVMSnapshotCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vmsnapshot/RevertToVMSnapshotCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.vmsnapshot; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -45,7 +44,6 @@ import com.cloud.vm.snapshot.VMSnapshot; @APICommand(name = "revertToVMSnapshot", description = "Revert VM from a vmsnapshot.", responseObject = UserVmResponse.class, since = "4.2.0", responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RevertToVMSnapshotCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(RevertToVMSnapshotCmd.class.getName()); private static final String s_name = "reverttovmsnapshotresponse"; @ACL(accessType = AccessType.OperateEntry, pointerToEntity = "getVmId()") diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AddResourceDetailCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AddResourceDetailCmd.java index 8d472d96eef..287991fa984 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AddResourceDetailCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AddResourceDetailCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.volume; import java.util.Map; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -33,7 +32,6 @@ import com.cloud.server.ResourceTag; @APICommand(name = "addResourceDetail", description = "Adds detail for the Resource.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddResourceDetailCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(AddResourceDetailCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AssignVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AssignVolumeCmd.java index 03413682c4f..1a51aa03c22 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AssignVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AssignVolumeCmd.java @@ -29,7 +29,6 @@ import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.VolumeResponse; -import org.apache.log4j.Logger; import com.cloud.storage.Volume; @@ -38,7 +37,6 @@ import java.util.Map; @APICommand(name = AssignVolumeCmd.CMD_NAME, responseObject = VolumeResponse.class, description = "Changes ownership of a Volume from one account to another.", entityType = { Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.18.0.0") public class AssignVolumeCmd extends BaseCmd implements UserCmd { - public static final Logger LOGGER = Logger.getLogger(AssignVolumeCmd.class.getName()); public static final String CMD_NAME = "assignVolume"; ///////////////////////////////////////////////////// @@ -96,7 +94,7 @@ public class AssignVolumeCmd extends BaseCmd implements UserCmd { } catch (CloudRuntimeException | ResourceAllocationException e) { String msg = String.format("Assign volume command for volume [%s] failed due to [%s].", getFullUrlParams().get("volumeid"), e.getMessage()); - LOGGER.error(msg, e); + logger.error(msg, e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, msg); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java index 687d683309c..1a3b9220877 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.volume; import org.apache.cloudstack.api.BaseAsyncCmd; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -41,7 +40,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "attachVolume", description = "Attaches a disk volume to a virtual machine.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AttachVolumeCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(AttachVolumeCmd.class.getName()); private static final String s_name = "attachvolumeresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CheckAndRepairVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CheckAndRepairVolumeCmd.java new file mode 100644 index 00000000000..56fdf6bc126 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CheckAndRepairVolumeCmd.java @@ -0,0 +1,138 @@ +// 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.user.volume; + +import java.util.Arrays; + +import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.commons.lang3.EnumUtils; + +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.storage.Volume; +import com.cloud.user.Account; +import com.cloud.utils.Pair; +import com.cloud.utils.StringUtils; + +@APICommand(name = "checkVolume", description = "Check the volume for any errors or leaks and also repairs when repair parameter is passed, this is currently supported for KVM only", responseObject = VolumeResponse.class, entityType = {Volume.class}, + since = "4.19.1", + authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class CheckAndRepairVolumeCmd extends BaseAsyncCmd { + + private static final String s_name = "checkandrepairvolumeresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VolumeResponse.class, required = true, description = "The ID of the volume") + private Long id; + + @Parameter(name = ApiConstants.REPAIR, type = CommandType.STRING, required = false, description = "parameter to repair the volume, leaks or all are the possible values") + private String repair; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public enum RepairValues { + LEAKS, ALL + } + + public Long getId() { + return id; + } + + public String getRepair() { + if (org.apache.commons.lang3.StringUtils.isNotEmpty(repair)) { + RepairValues repairType = EnumUtils.getEnumIgnoreCase(RepairValues.class, repair); + if (repairType == null) { + throw new InvalidParameterValueException(String.format("Repair parameter can only take the following values: %s", Arrays.toString(RepairValues.values()))); + } + return repair.toLowerCase(); + } + return null; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Volume volume = _entityMgr.findById(Volume.class, getId()); + if (volume != null) { + return volume.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public String getEventType() { + return EventTypes.EVENT_VOLUME_CHECK; + } + + @Override + public String getEventDescription() { + return String.format("check and repair operation on volume: %s", this._uuidMgr.getUuid(Volume.class, getId())); + } + + @Override + public Long getApiResourceId() { + return id; + } + + @Override + public ApiCommandResourceType getApiResourceType() { + return ApiCommandResourceType.Volume; + } + + @Override + public void execute() throws ResourceAllocationException { + CallContext.current().setEventDetails("Volume Id: " + getId()); + Pair result = _volumeService.checkAndRepairVolume(this); + Volume volume = _responseGenerator.findVolumeById(getId()); + if (result != null) { + VolumeResponse response = _responseGenerator.createVolumeResponse(ResponseView.Full, volume); + response.setVolumeCheckResult(StringUtils.parseJsonToMap(result.first())); + if (getRepair() != null) { + response.setVolumeRepairResult(StringUtils.parseJsonToMap(result.second())); + } + response.setResponseName(getCommandName()); + setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to check volume and repair"); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java index 566e8a46bd9..7ffcea50b21 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -48,7 +47,6 @@ import com.cloud.vm.VirtualMachine; Volume.class, VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVolumeCmd extends BaseAsyncCreateCustomIdCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(CreateVolumeCmd.class.getName()); private static final String s_name = "createvolumeresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java index 4bcc8a88545..6111488a802 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteVolume", description = "Deletes a detached disk volume.", responseObject = SuccessResponse.class, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVolumeCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(DeleteVolumeCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DestroyVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DestroyVolumeCmd.java index f4007ce9f40..2eafb76e591 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DestroyVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DestroyVolumeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -42,7 +41,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DestroyVolumeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DestroyVolumeCmd.class.getName()); private static final String s_name = "destroyvolumeresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java index e92f6a3cb0d..2fddcace84d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.volume; import org.apache.cloudstack.api.BaseAsyncCmd; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -42,7 +41,6 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "detachVolume", description = "Detaches a disk volume from a virtual machine.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DetachVolumeCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(DetachVolumeCmd.class.getName()); private static final String s_name = "detachvolumeresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java index 8f6e3a6c120..1146f80f0e2 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -41,7 +40,6 @@ import com.cloud.user.Account; @APICommand(name = "extractVolume", description = "Extracts volume", responseObject = ExtractResponse.class, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ExtractVolumeCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ExtractVolumeCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/GetUploadParamsForVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/GetUploadParamsForVolumeCmd.java index 1342ffc4748..4ccd5f97993 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/GetUploadParamsForVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/GetUploadParamsForVolumeCmd.java @@ -30,12 +30,10 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.GetUploadParamsResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; @APICommand(name = "getUploadParamsForVolume", description = "Upload a data disk to the cloudstack cloud.", responseObject = GetUploadParamsResponse.class, since = "4.6.0", requestHasSensitiveInfo= false, responseHasSensitiveInfo = false) public class GetUploadParamsForVolumeCmd extends AbstractGetUploadParamsCmd { - public static final Logger s_logger = Logger.getLogger(GetUploadParamsForVolumeCmd.class.getName()); private static final String s_name = "postuploadvolumeresponse"; @@ -62,7 +60,7 @@ public class GetUploadParamsForVolumeCmd extends AbstractGetUploadParamsCmd { response.setResponseName(getCommandName()); setResponseObject(response); } catch (MalformedURLException | ResourceAllocationException e) { - s_logger.error("exception while uploading volume", e); + logger.error("exception while uploading volume", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "exception while uploading a volume: " + e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java index b62a909d71f..a1024a98898 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java @@ -31,19 +31,18 @@ import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.PodResponse; +import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.commons.lang3.BooleanUtils; -import org.apache.log4j.Logger; import com.cloud.storage.Volume; @APICommand(name = "listVolumes", description = "Lists all volumes.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = { Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVolumesCmd extends BaseListRetrieveOnlyResourceCountCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListVolumesCmd.class.getName()); private static final String s_name = "listvolumesresponse"; @@ -82,6 +81,12 @@ public class ListVolumesCmd extends BaseListRetrieveOnlyResourceCountCmd impleme RoleType.Admin}) private String storageId; + @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, type = CommandType.UUID, + entityType = ServiceOfferingResponse.class, + description = "list volumes by disk offering of a service offering. If both service offering and " + + "disk offering are passed, service offering is ignored", since = "4.19.1") + private Long serviceOfferingId; + @Parameter(name = ApiConstants.DISK_OFFERING_ID, type = CommandType.UUID, entityType = DiskOfferingResponse.class, description = "list volumes by disk offering", since = "4.4") private Long diskOfferingId; @@ -96,6 +101,9 @@ public class ListVolumesCmd extends BaseListRetrieveOnlyResourceCountCmd impleme @Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "state of the volume. Possible values are: Ready, Allocated, Destroy, Expunging, Expunged.") private String state; + @Parameter(name = ApiConstants.IS_ENCRYPTED, type = CommandType.BOOLEAN, description = "list only volumes that are encrypted", since = "4.19.1", + authorized = { RoleType.Admin }) + private Boolean encrypted; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -120,6 +128,10 @@ public class ListVolumesCmd extends BaseListRetrieveOnlyResourceCountCmd impleme return podId; } + public Long getServiceOfferingId() { + return serviceOfferingId; + } + public Long getDiskOfferingId() { return diskOfferingId; } @@ -153,6 +165,10 @@ public class ListVolumesCmd extends BaseListRetrieveOnlyResourceCountCmd impleme return state; } + public Boolean isEncrypted() { + return encrypted; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RecoverVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RecoverVolumeCmd.java index 2589f816bc6..cd5a7735e38 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RecoverVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RecoverVolumeCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.volume; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,6 @@ import com.cloud.user.Account; requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RecoverVolumeCmd extends BaseCmd { - public static final Logger s_logger = Logger.getLogger(RecoverVolumeCmd.class.getName()); private static final String s_name = "recovervolumeresponse"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RemoveResourceDetailCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RemoveResourceDetailCmd.java index 98fe6a7e821..bad839f8ac7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RemoveResourceDetailCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/RemoveResourceDetailCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -31,7 +30,6 @@ import com.cloud.server.ResourceTag; @APICommand(name = "removeResourceDetail", description = "Removes detail for the Resource.", responseObject = SuccessResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RemoveResourceDetailCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RemoveResourceDetailCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java index 0daf141ba4a..65a3d6a7063 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; import org.apache.cloudstack.api.BaseAsyncCmd; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -44,7 +43,6 @@ import com.cloud.user.Account; @APICommand(name = "resizeVolume", description = "Resizes a volume", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ResizeVolumeCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ResizeVolumeCmd.class.getName()); private static final String s_name = "resizevolumeresponse"; @@ -103,6 +101,10 @@ public class ResizeVolumeCmd extends BaseAsyncCmd implements UserCmd { return getEntityId(); } + public void setId(Long id) { + this.id = id; + } + public Long getMinIops() { return minIops; } @@ -115,6 +117,10 @@ public class ResizeVolumeCmd extends BaseAsyncCmd implements UserCmd { return size; } + public void setSize(Long size) { + this.size = size; + } + public boolean isShrinkOk() { return shrinkOk; } @@ -195,10 +201,10 @@ public class ResizeVolumeCmd extends BaseAsyncCmd implements UserCmd { volume = _volumeService.resizeVolume(this); } catch (ResourceAllocationException ex) { - s_logger.error(ex.getMessage()); + logger.error(ex.getMessage()); throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage()); } catch (InvalidParameterValueException ex) { - s_logger.info(ex.getMessage()); + logger.info(ex.getMessage()); throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, ex.getMessage()); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java index e7782674828..467c587cc73 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -41,7 +40,6 @@ import com.cloud.storage.Volume; @APICommand(name = "updateVolume", description = "Updates the volume.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVolumeCmd extends BaseAsyncCustomIdCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVolumeCmd.class.getName()); private static final String s_name = "updatevolumeresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java index c622081079d..339c276d59e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java @@ -31,7 +31,6 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.event.EventTypes; @@ -45,7 +44,6 @@ import com.cloud.storage.Volume; @APICommand(name = "uploadVolume", description = "Uploads a data disk.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UploadVolumeCmd extends BaseAsyncCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(UploadVolumeCmd.class.getName()); private static final String s_name = "uploadvolumeresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreatePrivateGatewayCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreatePrivateGatewayCmd.java index 8527bd0e7fb..dceaabf648d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreatePrivateGatewayCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreatePrivateGatewayCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vpc; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -52,7 +51,6 @@ import com.cloud.network.vpc.VpcGateway; requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(CreatePrivateGatewayCmd.class.getName()); private static final String s_name = "createprivategatewayresponse"; @@ -149,11 +147,11 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd implements UserC try { result = _vpcService.createVpcPrivateGateway(this); } catch (InsufficientCapacityException ex) { - s_logger.info(ex); - s_logger.trace(ex); + logger.info(ex); + logger.trace(ex); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } @@ -169,7 +167,7 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd implements UserC public void execute() throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException, ResourceUnavailableException { PrivateGateway result = _vpcService.applyVpcPrivateGateway(getEntityId(), true); if (result != null) { - PrivateGatewayResponse response = _responseGenerator.createPrivateGatewayResponse(result); + PrivateGatewayResponse response = _responseGenerator.createPrivateGatewayResponse(getResponseView(), result); response.setResponseName(getCommandName()); setResponseObject(response); } else { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java index 68d7a77d946..b28c02cb800 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vpc; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -42,7 +41,6 @@ import com.cloud.network.vpc.VpcGateway; @APICommand(name = "createStaticRoute", description = "Creates a static route", responseObject = StaticRouteResponse.class, entityType = {StaticRoute.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateStaticRouteCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateStaticRouteCmd.class.getName()); @Parameter(name = ApiConstants.GATEWAY_ID, type = CommandType.UUID, @@ -75,8 +73,8 @@ public class CreateStaticRouteCmd extends BaseAsyncCreateCmd { setEntityId(result.getId()); setEntityUuid(result.getUuid()); } catch (NetworkRuleConflictException ex) { - s_logger.info("Network rule conflict: " + ex.getMessage()); - s_logger.trace("Network rule conflict: ", ex); + logger.info("Network rule conflict: " + ex.getMessage()); + logger.trace("Network rule conflict: ", ex); throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java index 7ca66b2a471..89a65f8c27c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.vpc; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -46,7 +45,6 @@ import com.cloud.network.vpc.Vpc; @APICommand(name = "createVPC", description = "Creates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVPCCmd extends BaseAsyncCreateCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(CreateVPCCmd.class.getName()); private static final String s_name = "createvpcresponse"; // /////////////////////////////////////////////////// @@ -210,21 +208,17 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd implements UserCmd { public void execute() { Vpc vpc = null; try { - if (isStart()) { - _vpcService.startVpc(getEntityId(), true); - } else { - s_logger.debug("Not starting VPC as " + ApiConstants.START + "=false was passed to the API"); - } + _vpcService.startVpc(this); vpc = _entityMgr.findById(Vpc.class, getEntityId()); } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (InsufficientCapacityException ex) { - s_logger.info(ex); - s_logger.trace(ex); + logger.info(ex); + logger.trace(ex); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java index 6210d80586f..01b6aae425b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vpc; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -40,7 +39,6 @@ import com.cloud.network.vpc.StaticRoute; @APICommand(name = "deleteStaticRoute", description = "Deletes a static route", responseObject = SuccessResponse.class, entityType = {StaticRoute.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteStaticRouteCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteStaticRouteCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java index f408e32f62d..c35d9084bcc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.vpc; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -39,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteVPC", description = "Deletes a VPC", responseObject = SuccessResponse.class, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVPCCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteVPCCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -81,10 +79,10 @@ public class DeleteVPCCmd extends BaseAsyncCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete VPC"); } } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java index 47861c8362e..2304cef3c6d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java @@ -19,12 +19,13 @@ package org.apache.cloudstack.api.command.user.vpc; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ResponseObject; +import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.PrivateGatewayResponse; import org.apache.cloudstack.api.response.VpcResponse; @@ -34,9 +35,9 @@ import com.cloud.network.vpc.VpcGateway; import com.cloud.utils.Pair; @APICommand(name = "listPrivateGateways", description = "List private gateways", responseObject = PrivateGatewayResponse.class, entityType = {VpcGateway.class}, + responseView = ResponseObject.ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) -public class ListPrivateGatewaysCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListPrivateGatewaysCmd.class.getName()); +public class ListPrivateGatewaysCmd extends BaseListProjectAndAccountResourcesCmd implements UserCmd { ///////////////////////////////////////////////////// @@ -90,7 +91,7 @@ public class ListPrivateGatewaysCmd extends BaseListProjectAndAccountResourcesCm ListResponse response = new ListResponse(); List projectResponses = new ArrayList(); for (PrivateGateway gateway : gateways.first()) { - PrivateGatewayResponse gatewayResponse = _responseGenerator.createPrivateGatewayResponse(gateway); + PrivateGatewayResponse gatewayResponse = _responseGenerator.createPrivateGatewayResponse(getResponseView(), gateway); projectResponses.add(gatewayResponse); } response.setResponses(projectResponses, gateways.second()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java index c0f95fcd361..f48e113286a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.VpcOfferingResponse; import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; import com.cloud.network.vpc.VpcOffering; import com.cloud.utils.Pair; @@ -35,7 +34,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listVPCOfferings", description = "Lists VPC offerings", responseObject = VpcOfferingResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVPCOfferingsCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListVPCOfferingsCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java index 76cbcca61bb..d128be1414d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java @@ -33,7 +33,6 @@ import org.apache.cloudstack.api.response.ResourceIconResponse; import org.apache.cloudstack.api.response.VpcOfferingResponse; import org.apache.cloudstack.api.response.VpcResponse; import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; import com.cloud.network.vpc.Vpc; import com.cloud.utils.Pair; @@ -42,7 +41,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listVPCs", description = "Lists VPCs", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVPCsCmd extends BaseListTaggedResourcesCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListVPCsCmd.class.getName()); private static final String s_name = "listvpcsresponse"; ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java index 04946619c0a..5ccd496eeb4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java @@ -27,7 +27,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.VpcResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -39,7 +38,6 @@ import com.cloud.user.Account; @APICommand(name = "restartVPC", description = "Restarts a VPC", responseObject = SuccessResponse.class, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RestartVPCCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RestartVPCCmd.class.getName()); ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -101,14 +99,14 @@ public class RestartVPCCmd extends BaseAsyncCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to restart VPC"); } } catch (final ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (final ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); } catch (final InsufficientCapacityException ex) { - s_logger.info(ex); - s_logger.trace(ex); + logger.info(ex); + logger.trace(ex); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java index d4c7d0d5c59..6fcfb5311f6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.vpc; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -42,7 +41,6 @@ import com.cloud.user.Account; @APICommand(name = "updateVPC", description = "Updates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVPCCmd extends BaseAsyncCustomIdCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVPCCmd.class.getName()); private static final String s_name = "updatevpcresponse"; ///////////////////////////////////////////////////// @@ -129,11 +127,11 @@ public class UpdateVPCCmd extends BaseAsyncCustomIdCmd implements UserCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update VPC"); } } catch (final ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } catch (final InsufficientCapacityException ex) { - s_logger.info(ex); - s_logger.trace(ex); + logger.info(ex); + logger.trace(ex); throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java index 9c9f1c0f50f..9e950310cdc 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vpn; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "addVpnUser", description = "Adds vpn users", responseObject = VpnUsersResponse.class, entityType = {VpnUser.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddVpnUserCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(AddVpnUserCmd.class.getName()); ///////////////////////////////////////////////////// @@ -125,6 +123,9 @@ public class AddVpnUserCmd extends BaseAsyncCreateCmd { vpnResponse.setId(vpnUser.getUuid()); vpnResponse.setUserName(vpnUser.getUsername()); vpnResponse.setAccountName(account.getAccountName()); + // re-retrieve the vpnuser, as the call to `applyVpnUsers` might have changed the state + vpnUser = _entityMgr.findById(VpnUser.class, getEntityId()); + vpnResponse.setState(vpnUser.getState().toString()); Domain domain = _entityMgr.findById(Domain.class, account.getDomainId()); if (domain != null) { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java index 8ecf4b051ce..417ba2773c4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.vpn; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,6 @@ import com.cloud.network.RemoteAccessVpn; @APICommand(name = "createRemoteAccessVpn", description = "Creates a l2tp/ipsec remote access vpn", responseObject = RemoteAccessVpnResponse.class, entityType = {RemoteAccessVpn.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateRemoteAccessVpnCmd.class.getName()); ///////////////////////////////////////////////////// @@ -148,8 +146,8 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create remote access vpn"); } } catch (NetworkRuleConflictException e) { - s_logger.info("Network rule conflict: " + e.getMessage()); - s_logger.trace("Network Rule Conflict: ", e); + logger.info("Network rule conflict: " + e.getMessage()); + logger.trace("Network Rule Conflict: ", e); throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, e.getMessage()); } } @@ -166,7 +164,7 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create remote access vpn"); } } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java index 84aaafc60ed..0b5c46d36eb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vpn; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,6 @@ import com.cloud.network.vpc.Vpc; @APICommand(name = "createVpnConnection", description = "Create site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVpnConnectionCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateVpnConnectionCmd.class.getName()); ///////////////////////////////////////////////////// @@ -135,8 +133,8 @@ public class CreateVpnConnectionCmd extends BaseAsyncCreateCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create site to site vpn connection"); } } catch (NetworkRuleConflictException e) { - s_logger.info("Network rule conflict: " + e.getMessage()); - s_logger.trace("Network Rule Conflict: ", e); + logger.info("Network rule conflict: " + e.getMessage()); + logger.trace("Network Rule Conflict: ", e); throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, e.getMessage()); } } @@ -153,7 +151,7 @@ public class CreateVpnConnectionCmd extends BaseAsyncCreateCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create site to site vpn connection"); } } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java index 88c6c12fac7..a2fa0d9829c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java @@ -28,7 +28,6 @@ import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.Site2SiteCustomerGatewayResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ResourceAllocationException; @@ -37,7 +36,6 @@ import com.cloud.network.Site2SiteCustomerGateway; @APICommand(name = "createVpnCustomerGateway", description = "Creates site to site vpn customer gateway", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVpnCustomerGatewayCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateVpnCustomerGatewayCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java index c354e972737..6f31176c4ff 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java @@ -31,12 +31,10 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.Site2SiteVpnGatewayResponse; import org.apache.cloudstack.api.response.VpcResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; @APICommand(name = "createVpnGateway", description = "Creates site to site vpn local gateway", responseObject = Site2SiteVpnGatewayResponse.class, entityType = {Site2SiteVpnGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVpnGatewayCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreateVpnGatewayCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java index dfc80b2fabc..bf8d0157923 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.vpn; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,6 @@ import com.cloud.network.RemoteAccessVpn; @APICommand(name = "deleteRemoteAccessVpn", description = "Destroys a l2tp/ipsec remote access vpn", responseObject = SuccessResponse.class, entityType = {RemoteAccessVpn.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteRemoteAccessVpnCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteRemoteAccessVpnCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java index 8a57dfc8edd..2528d93a042 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vpn; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteVpnConnection", description = "Delete site to site vpn connection", responseObject = SuccessResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVpnConnectionCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteVpnConnectionCmd.class.getName()); ///////////////////////////////////////////////////// @@ -86,7 +84,7 @@ public class DeleteVpnConnectionCmd extends BaseAsyncCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete site to site VPN connection"); } } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java index e2f0aee90ec..2b657fd3c08 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.vpn; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteVpnCustomerGateway", description = "Delete site to site vpn customer gateway", responseObject = SuccessResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVpnCustomerGatewayCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteVpnCustomerGatewayCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java index b7acc5c4506..27ded12dc58 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vpn; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.user.Account; @APICommand(name = "deleteVpnGateway", description = "Delete site to site vpn gateway", responseObject = SuccessResponse.class, entityType = {Site2SiteVpnGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVpnGatewayCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DeleteVpnGatewayCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java index 1f2f95188e7..4efc70c8419 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.vpn; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listRemoteAccessVpns", description = "Lists remote access vpns", responseObject = RemoteAccessVpnResponse.class, entityType = {RemoteAccessVpn.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListRemoteAccessVpnsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListRemoteAccessVpnsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java index 763a374645b..aeeae44d004 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.vpn; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listVpnConnections", description = "Lists site to site vpn connection gateways", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnConnectionsCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListVpnConnectionsCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java index b66c47899f7..258a8a753eb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.vpn; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listVpnCustomerGateways", description = "Lists site to site vpn customer gateways", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnCustomerGatewaysCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListVpnCustomerGatewaysCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java index fb9c8262003..d30fbf8d32b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.vpn; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listVpnGateways", description = "Lists site 2 site vpn gateways", responseObject = Site2SiteVpnGatewayResponse.class, entityType = {Site2SiteVpnGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnGatewaysCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListVpnGatewaysCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java index 9f8581eb014..48591765ec3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java @@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.user.vpn; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,6 @@ import com.cloud.utils.Pair; @APICommand(name = "listVpnUsers", description = "Lists vpn users", responseObject = VpnUsersResponse.class, entityType = {VpnUser.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnUsersCmd extends BaseListProjectAndAccountResourcesCmd { - public static final Logger s_logger = Logger.getLogger(ListVpnUsersCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java index 4adf385b127..48e7a9ee519 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vpn; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,6 @@ import com.cloud.user.Account; @APICommand(name = "removeVpnUser", description = "Removes vpn user", responseObject = SuccessResponse.class, entityType = {VpnUser.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RemoveVpnUserCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(RemoveVpnUserCmd.class.getName()); ///////////////////////////////////////////////////// @@ -109,7 +107,7 @@ public class RemoveVpnUserCmd extends BaseAsyncCmd { boolean result = _ravService.removeVpnUser(ownerId, userName, CallContext.current().getCallingAccount()); if (!result) { String errorMessage = String.format("Failed to remove VPN user=[%s]. VPN owner id=[%s].", userName, ownerId); - s_logger.error(errorMessage); + logger.error(errorMessage); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMessage); } @@ -118,13 +116,13 @@ public class RemoveVpnUserCmd extends BaseAsyncCmd { appliedVpnUsers = _ravService.applyVpnUsers(ownerId, userName, true); } catch (ResourceUnavailableException ex) { String errorMessage = String.format("Failed to refresh VPN user=[%s] due to resource unavailable. VPN owner id=[%s].", userName, ownerId); - s_logger.error(errorMessage, ex); + logger.error(errorMessage, ex); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMessage, ex); } if (!appliedVpnUsers) { String errorMessage = String.format("Failed to refresh VPN user=[%s]. VPN owner id=[%s].", userName, ownerId); - s_logger.debug(errorMessage); + logger.debug(errorMessage); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMessage); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java index c63126578f2..736295b4119 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.vpn; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.user.Account; @APICommand(name = "resetVpnConnection", description = "Reset site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ResetVpnConnectionCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(ResetVpnConnectionCmd.class.getName()); ///////////////////////////////////////////////////// @@ -105,7 +103,7 @@ public class ResetVpnConnectionCmd extends BaseAsyncCmd { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to reset site to site VPN connection"); } } catch (ResourceUnavailableException ex) { - s_logger.warn("Exception: ", ex); + logger.warn("Exception: ", ex); throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateRemoteAccessVpnCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateRemoteAccessVpnCmd.java index d5b36f662f9..defde70b63a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateRemoteAccessVpnCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateRemoteAccessVpnCmd.java @@ -23,7 +23,6 @@ import org.apache.cloudstack.api.BaseAsyncCustomIdCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.RemoteAccessVpnResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; @@ -32,7 +31,6 @@ import com.cloud.network.RemoteAccessVpn; @APICommand(name = "updateRemoteAccessVpn", description = "Updates remote access vpn", responseObject = RemoteAccessVpnResponse.class, since = "4.4", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateRemoteAccessVpnCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateRemoteAccessVpnCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnConnectionCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnConnectionCmd.java index 67cb65bdb93..62dd6167b75 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnConnectionCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnConnectionCmd.java @@ -22,7 +22,6 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseAsyncCustomIdCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.Site2SiteVpnConnectionResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.network.Site2SiteVpnConnection; @@ -31,7 +30,6 @@ import com.cloud.user.Account; @APICommand(name = "updateVpnConnection", description = "Updates site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, since = "4.4", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVpnConnectionCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVpnConnectionCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java index 179bc0407b4..9f3ac2ec436 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.api.command.user.vpn; import org.apache.cloudstack.api.ApiArgValidator; import org.apache.cloudstack.api.ApiCommandResourceType; -import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,6 @@ import com.cloud.network.Site2SiteCustomerGateway; @APICommand(name = "updateVpnCustomerGateway", description = "Update site to site vpn customer gateway", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVpnCustomerGatewayCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVpnCustomerGatewayCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnGatewayCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnGatewayCmd.java index c69bbb5689f..9fe5ae0480f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnGatewayCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpn/UpdateVpnGatewayCmd.java @@ -22,7 +22,6 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseAsyncCustomIdCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.Site2SiteVpnGatewayResponse; -import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.network.Site2SiteVpnGateway; @@ -31,7 +30,6 @@ import com.cloud.user.Account; @APICommand(name = "updateVpnGateway", description = "Updates site to site vpn local gateway", responseObject = Site2SiteVpnGatewayResponse.class, since = "4.4", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVpnGatewayCmd extends BaseAsyncCustomIdCmd { - public static final Logger s_logger = Logger.getLogger(UpdateVpnGatewayCmd.class.getName()); ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/zone/ListZonesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/zone/ListZonesCmd.java index c79afb1c972..d926257437e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/zone/ListZonesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/zone/ListZonesCmd.java @@ -16,10 +16,9 @@ // under the License. package org.apache.cloudstack.api.command.user.zone; +import java.util.List; import java.util.Map; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; @@ -34,7 +33,6 @@ import org.apache.cloudstack.api.response.ZoneResponse; @APICommand(name = "listZones", description = "Lists zones", responseObject = ZoneResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListZonesCmd extends BaseListCmd implements UserCmd { - public static final Logger s_logger = Logger.getLogger(ListZonesCmd.class.getName()); private static final String s_name = "listzonesresponse"; @@ -44,6 +42,9 @@ public class ListZonesCmd extends BaseListCmd implements UserCmd { @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ZoneResponse.class, description = "the ID of the zone") private Long id; + @Parameter(name = ApiConstants.IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = ZoneResponse.class, description = "the IDs of the zones, mutually exclusive with id", since = "4.19.0") + private List ids; + @Parameter(name = ApiConstants.AVAILABLE, type = CommandType.BOOLEAN, description = "true if you want to retrieve all available Zones. False if you only want to return the Zones" @@ -76,6 +77,10 @@ public class ListZonesCmd extends BaseListCmd implements UserCmd { return id; } + public List getIds() { + return ids; + } + public Boolean isAvailable() { return available; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/AccountResponse.java index 7ffe7d095e4..7a84e85a4a6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/AccountResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/AccountResponse.java @@ -267,6 +267,10 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou @Param(description = "Base64 string representation of the resource icon", since = "4.16.0.0") ResourceIconResponse icon; + @SerializedName(ApiConstants.TAGGED_RESOURCES) + @Param(description = "The tagged resource limit and count for the account", since = "4.20.0") + List taggedResources; + @Override public String getObjectId() { return id; @@ -545,4 +549,9 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou public void setResourceIconResponse(ResourceIconResponse icon) { this.icon = icon; } + + @Override + public void setTaggedResourceLimitsAndCounts(List taggedResourceLimitsAndCounts) { + this.taggedResources = taggedResourceLimitsAndCounts; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/AcquireIPAddressResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/AcquireIPAddressResponse.java index a74c95780d1..7270fa949c8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/AcquireIPAddressResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/AcquireIPAddressResponse.java @@ -124,7 +124,7 @@ public class AcquireIPAddressResponse extends BaseResponse implements Controlle private String networkId; @SerializedName(ApiConstants.STATE) - @Param(description = "State of the ip address. Can be: Allocatin, Allocated and Releasing") + @Param(description = "State of the ip address. Can be: Allocating, Allocated and Releasing") private String state; @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) diff --git a/api/src/main/java/org/apache/cloudstack/api/response/AlertTypeResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/AlertTypeResponse.java new file mode 100644 index 00000000000..3f91cde0178 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/AlertTypeResponse.java @@ -0,0 +1,55 @@ +// 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.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +public class AlertTypeResponse extends BaseResponse { + + @SerializedName("alerttypeid") + @Param(description = "alert type") + private short alertType; + + @SerializedName(ApiConstants.NAME) + @Param(description = "description of alert type") + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public short getUsageType() { + return alertType; + } + + public void setUsageType(short alertType) { + this.alertType = alertType; + } + + public AlertTypeResponse(short alertType, String name) { + this.alertType = alertType; + this.name = name; + setObjectName("alerttype"); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/AutoScaleVmProfileResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/AutoScaleVmProfileResponse.java index 9f238344730..678c4fcaaca 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/AutoScaleVmProfileResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/AutoScaleVmProfileResponse.java @@ -69,7 +69,7 @@ public class AutoScaleVmProfileResponse extends BaseResponse implements Controll private Map counterParams; @SerializedName(ApiConstants.USER_DATA) - @Param(description = "Base 64 encoded VM user data") + @Param(description = "Base64 encoded VM user data") private String userData; @SerializedName(ApiConstants.USER_DATA_ID) @Param(description="the id of userdata used for the VM", since = "4.18.1") diff --git a/api/src/main/java/org/apache/cloudstack/api/response/BucketResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/BucketResponse.java new file mode 100644 index 00000000000..a1cce6e43d7 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/BucketResponse.java @@ -0,0 +1,293 @@ +// 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.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponseWithTagInformation; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.storage.object.Bucket; + +import java.util.Date; +import java.util.LinkedHashSet; +import java.util.Set; + +@EntityReference(value = Bucket.class) +@SuppressWarnings("unused") +public class BucketResponse extends BaseResponseWithTagInformation implements ControlledViewEntityResponse, ControlledEntityResponse { + @SerializedName(ApiConstants.ID) + @Param(description = "ID of the Bucket") + private String id; + @SerializedName(ApiConstants.NAME) + @Param(description = "name of the Bucket") + private String name; + @SerializedName(ApiConstants.CREATED) + @Param(description = "the date the Bucket was created") + private Date created; + @SerializedName(ApiConstants.ACCOUNT) + @Param(description = "the account associated with the Bucket") + private String accountName; + @SerializedName(ApiConstants.PROJECT_ID) + @Param(description = "the project id of the bucket") + private String projectId; + @SerializedName(ApiConstants.PROJECT) + @Param(description = "the project name of the bucket") + private String projectName; + @SerializedName(ApiConstants.DOMAIN_ID) + @Param(description = "the ID of the domain associated with the bucket") + private String domainId; + @SerializedName(ApiConstants.DOMAIN) + @Param(description = "the domain associated with the bucket") + private String domainName; + @SerializedName(ApiConstants.OBJECT_STORAGE_ID) + @Param(description = "id of the object storage hosting the Bucket; returned to admin user only") + private String objectStoragePoolId; + + @SerializedName(ApiConstants.OBJECT_STORAGE) + @Param(description = "Name of the object storage hosting the Bucket; returned to admin user only") + private String objectStoragePool; + + @SerializedName(ApiConstants.SIZE) + @Param(description = "Total size of objects in Bucket") + private Long size; + + @SerializedName(ApiConstants.STATE) + @Param(description = "State of the Bucket") + private String state; + + @SerializedName(ApiConstants.QUOTA) + @Param(description = "Bucket Quota in GB") + private Integer quota; + + @SerializedName(ApiConstants.ENCRYPTION) + @Param(description = "Bucket Encryption") + private Boolean encryption; + + @SerializedName(ApiConstants.VERSIONING) + @Param(description = "Bucket Versioning") + private Boolean versioning; + + @SerializedName(ApiConstants.OBJECT_LOCKING) + @Param(description = "Bucket Object Locking") + private Boolean objectLock; + + @SerializedName(ApiConstants.POLICY) + @Param(description = "Bucket Access Policy") + private String policy; + + @SerializedName(ApiConstants.URL) + @Param(description = "Bucket URL") + private String bucketURL; + + @SerializedName(ApiConstants.ACCESS_KEY) + @Param(description = "Bucket Access Key") + private String accessKey; + + @SerializedName(ApiConstants.USER_SECRET_KEY) + @Param(description = "Bucket Secret Key") + private String secretKey; + + @SerializedName(ApiConstants.PROVIDER) + @Param(description = "Object storage provider") + private String provider; + + public BucketResponse() { + tags = new LinkedHashSet(); + } + + @Override + public String getObjectId() { + return this.getId(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public void setCreated(Date created) { + this.created = created; + } + + @Override + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + @Override + public void setDomainId(String domainId) { + this.domainId = domainId; + } + + @Override + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + @Override + public void setProjectId(String projectId) { + this.projectId = projectId; + } + + @Override + public void setProjectName(String projectName) { + this.projectName = projectName; + } + + public void setTags(Set tags) { + this.tags = tags; + } + + public void setObjectStoragePoolId(String objectStoragePoolId) { + this.objectStoragePoolId = objectStoragePoolId; + } + + public String getName() { + return name; + } + + public Date getCreated() { + return created; + } + + public String getAccountName() { + return accountName; + } + + public String getProjectId() { + return projectId; + } + + public String getProjectName() { + return projectName; + } + + public String getDomainId() { + return domainId; + } + + public String getDomainName() { + return domainName; + } + + public String getObjectStoragePoolId() { + return objectStoragePoolId; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + public long getQuota() { + return quota; + } + + public void setQuota(Integer quota) { + this.quota = quota; + } + + public boolean isVersioning() { + return versioning; + } + + public void setVersioning(boolean versioning) { + this.versioning = versioning; + } + + public boolean isEncryption() { + return encryption; + } + + public void setEncryption(boolean encryption) { + this.encryption = encryption; + } + + public boolean isObjectLock() { + return objectLock; + } + + public void setObjectLock(boolean objectLock) { + this.objectLock = objectLock; + } + + public String getPolicy() { + return policy; + } + + public void setPolicy(String policy) { + this.policy = policy; + } + + public String getBucketURL() { + return bucketURL; + } + + public void setBucketURL(String bucketURL) { + this.bucketURL = bucketURL; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public void setState(Bucket.State state) { + this.state = state.toString(); + } + + public String getState() { + return state; + } + + public void setObjectStoragePool(String objectStoragePool) { + this.objectStoragePool = objectStoragePool; + } + + public String getObjectStoragePool() { + return objectStoragePool; + } + + public String getProvider() { + return provider; + } + + public void setProvider(String provider) { + this.provider = provider; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/CapacityResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/CapacityResponse.java index e9724497c38..2d0e2158651 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/CapacityResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/CapacityResponse.java @@ -16,12 +16,11 @@ // under the License. package org.apache.cloudstack.api.response; -import com.google.gson.annotations.SerializedName; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; public class CapacityResponse extends BaseResponse { @SerializedName(ApiConstants.TYPE) @@ -72,6 +71,10 @@ public class CapacityResponse extends BaseResponse { @Param(description = "the percentage of capacity currently in use") private String percentUsed; + @SerializedName(ApiConstants.TAG) + @Param(description = "The tag for the capacity type", since = "4.20.0") + private String tag; + public Short getCapacityType() { return capacityType; } @@ -167,4 +170,8 @@ public class CapacityResponse extends BaseResponse { public void setPercentUsed(String percentUsed) { this.percentUsed = percentUsed; } + + public void setTag(String tag) { + this.tag = tag; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ChildTemplateResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ChildTemplateResponse.java index b036cd48e87..8f5b5de2919 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/ChildTemplateResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/ChildTemplateResponse.java @@ -39,7 +39,7 @@ public class ChildTemplateResponse extends BaseResponse { @Param(description = "the size of the template") private Integer size; - @SerializedName("templatetype") + @SerializedName(ApiConstants.TEMPLATE_TYPE) @Param(description = "the type of the template") private String templateType; diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ClusterDrsPlanMigrationResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ClusterDrsPlanMigrationResponse.java new file mode 100644 index 00000000000..4114c228e26 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/ClusterDrsPlanMigrationResponse.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cloudstack.api.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.jobs.JobInfo; + +public class ClusterDrsPlanMigrationResponse extends BaseResponse { + @SerializedName(ApiConstants.VIRTUAL_MACHINE_ID) + @Param(description = "VM to migrate") + String vmId; + + @SerializedName(ApiConstants.VIRTUAL_MACHINE_NAME) + @Param(description = "VM to migrate") + String vmName; + + @SerializedName("sourcehostid") + @Param(description = "Original host for VM migration") + String srcHostId; + + @SerializedName("sourcehostname") + @Param(description = "Original host for VM migration") + String srcHostName; + + @SerializedName("destinationhostid") + @Param(description = "Destination host for VM migration") + String destHostId; + + @SerializedName("destinationhostname") + @Param(description = "Destination host for VM migration") + String destHostName; + + @SerializedName(ApiConstants.JOB_ID) + @Param(description = "id of VM migration async job") + private Long jobId; + + @SerializedName(ApiConstants.JOB_STATUS) + @Param(description = "Job status of VM migration async job") + private JobInfo.Status jobStatus; + + + public ClusterDrsPlanMigrationResponse(String vmId, String vmName, String srcHostId, String srcHostName, + String destHostId, String destHostName, Long jobId, + JobInfo.Status jobStatus) { + this.vmId = vmId; + this.vmName = vmName; + this.srcHostId = srcHostId; + this.srcHostName = srcHostName; + this.destHostId = destHostId; + this.destHostName = destHostName; + this.jobId = jobId; + this.jobStatus = jobStatus; + this.setObjectName(ApiConstants.MIGRATIONS); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ClusterDrsPlanResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ClusterDrsPlanResponse.java new file mode 100644 index 00000000000..2a7fed7da4c --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/ClusterDrsPlanResponse.java @@ -0,0 +1,83 @@ +/* + * 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.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.cluster.ClusterDrsPlan; + +import java.util.Date; +import java.util.List; + +@EntityReference(value = ClusterDrsPlan.class) +public class ClusterDrsPlanResponse extends BaseResponse { + @SerializedName(ApiConstants.MIGRATIONS) + @Param(description = "List of migrations") + List migrationPlans; + + @SerializedName(ApiConstants.ID) + @Param(description = "unique ID of the drs plan for cluster") + private String id; + + @SerializedName(ApiConstants.CLUSTER_ID) + @Param(description = "Id of the cluster") + private String clusterId; + + @SerializedName("eventid") + @Param(description = "Start event Id of the DRS Plan") + private String eventId; + + @SerializedName(ApiConstants.TYPE) + @Param(description = "Type of DRS Plan (Automated or Manual))") + private ClusterDrsPlan.Type type; + + @SerializedName(ApiConstants.STATUS) + @Param(description = "Status of DRS Plan") + private ClusterDrsPlan.Status status; + + @SerializedName(ApiConstants.CREATED) + private Date created; + + + public ClusterDrsPlanResponse(String clusterId, ClusterDrsPlan plan, String eventId, + List migrationPlans) { + this.clusterId = clusterId; + this.eventId = eventId; + if (plan != null) { + this.id = plan.getUuid(); + this.type = plan.getType(); + this.status = plan.getStatus(); + this.created = plan.getCreated(); + } + this.migrationPlans = migrationPlans; + this.setObjectName("drsPlan"); + } + + public List getMigrationPlans() { + return migrationPlans; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/DiskOfferingResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/DiskOfferingResponse.java index b8244aebc60..0fed9827ef1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/DiskOfferingResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/DiskOfferingResponse.java @@ -53,6 +53,10 @@ public class DiskOfferingResponse extends BaseResponseWithAnnotations { @Param(description = "the name of the disk offering") private String name; + @SerializedName(ApiConstants.STATE) + @Param(description = "state of the disk offering") + private String state; + @SerializedName(ApiConstants.DISPLAY_TEXT) @Param(description = "an alternate display text of the disk offering.") private String displayText; @@ -169,6 +173,10 @@ public class DiskOfferingResponse extends BaseResponseWithAnnotations { @Param(description = "additional key/value details tied with this disk offering", since = "4.17") private Map details; + @SerializedName(ApiConstants.SUITABLE_FOR_VM) + @Param(description = "Returns true if the disk offering is suitable for the given virtual machine for disk creation otherwise false", since = "4.20.0") + private Boolean suitableForVm; + public Boolean getDisplayOffering() { return displayOffering; } @@ -226,6 +234,14 @@ public class DiskOfferingResponse extends BaseResponseWithAnnotations { this.name = name; } + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + public String getDisplayText() { return displayText; } @@ -391,4 +407,8 @@ public class DiskOfferingResponse extends BaseResponseWithAnnotations { public void setDetails(Map details) { this.details = details; } + + public void setSuitableForVm(Boolean suitableForVm) { + this.suitableForVm = suitableForVm; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/DomainResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/DomainResponse.java index e4e409a40ee..7c6ad3a91c3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/DomainResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/DomainResponse.java @@ -26,6 +26,7 @@ import com.cloud.domain.Domain; import com.cloud.serializer.Param; import java.util.Date; +import java.util.List; import java.util.Map; @EntityReference(value = Domain.class) @@ -184,6 +185,10 @@ public class DomainResponse extends BaseResponseWithAnnotations implements Resou @Param(description = "details for the domain") private Map details; + @SerializedName(ApiConstants.TAGGED_RESOURCES) + @Param(description = "The tagged resource limit and count for the domain", since = "4.20.0") + List taggedResources; + public String getId() { return this.id; } @@ -447,4 +452,9 @@ public class DomainResponse extends BaseResponseWithAnnotations implements Resou public void setDetails(Map details) { this.details = details; } + + @Override + public void setTaggedResourceLimitsAndCounts(List taggedResourceLimitsAndCounts) { + this.taggedResources = taggedResourceLimitsAndCounts; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/GuestOSResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/GuestOSResponse.java index 6ad5e2ac828..f870a2f0d94 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/GuestOSResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/GuestOSResponse.java @@ -53,7 +53,7 @@ public class GuestOSResponse extends BaseResponse { @SerializedName(ApiConstants.IS_USER_DEFINED) @Param(description = "is the guest OS user defined") - private String isUserDefined; + private Boolean isUserDefined; @SerializedName(ApiConstants.FOR_DISPLAY) @Param(description = "is the guest OS visible for the users") @@ -99,11 +99,11 @@ public class GuestOSResponse extends BaseResponse { this.description = description; } - public String getIsUserDefined() { + public Boolean getIsUserDefined() { return isUserDefined; } - public void setIsUserDefined(String isUserDefined) { + public void setIsUserDefined(Boolean isUserDefined) { this.isUserDefined = isUserDefined; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/HostForMigrationResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/HostForMigrationResponse.java index 41a0fdc4567..24015e0b459 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/HostForMigrationResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/HostForMigrationResponse.java @@ -208,6 +208,14 @@ public class HostForMigrationResponse extends BaseResponse { @Param(description = "comma-separated list of tags for the host") private String hostTags; + @SerializedName("explicithosttags") + @Param(description = "comma-separated list of explicit host tags for the host", since = "4.20.0") + private String explicitHostTags; + + @SerializedName("implicithosttags") + @Param(description = "comma-separated list of implicit host tags for the host", since = "4.20.0") + private String implicitHostTags; + @SerializedName("hasenoughcapacity") @Param(description = "true if this host has enough CPU and RAM capacity to migrate a VM to it, false otherwise") private Boolean hasEnoughCapacity; @@ -414,6 +422,14 @@ public class HostForMigrationResponse extends BaseResponse { this.hostTags = hostTags; } + public void setExplicitHostTags(String explicitHostTags) { + this.explicitHostTags = explicitHostTags; + } + + public void setImplicitHostTags(String implicitHostTags) { + this.implicitHostTags = implicitHostTags; + } + public void setHasEnoughCapacity(Boolean hasEnoughCapacity) { this.hasEnoughCapacity = hasEnoughCapacity; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java index e1f1e5ee241..8d98b6573f4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java @@ -29,6 +29,7 @@ import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement; import com.cloud.host.Host; import com.cloud.host.Status; +import com.cloud.hypervisor.Hypervisor; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; @@ -221,6 +222,18 @@ public class HostResponse extends BaseResponseWithAnnotations { @Param(description = "comma-separated list of tags for the host") private String hostTags; + @SerializedName("explicithosttags") + @Param(description = "comma-separated list of explicit host tags for the host", since = "4.20.0") + private String explicitHostTags; + + @SerializedName("implicithosttags") + @Param(description = "comma-separated list of implicit host tags for the host", since = "4.20.0") + private String implicitHostTags; + + @SerializedName(ApiConstants.IS_TAG_A_RULE) + @Param(description = ApiConstants.PARAMETER_DESCRIPTION_IS_TAG_A_RULE) + private Boolean isTagARule; + @SerializedName("hasenoughcapacity") @Param(description = "true if this host has enough CPU and RAM capacity to migrate a VM to it, false otherwise") private Boolean hasEnoughCapacity; @@ -273,6 +286,10 @@ public class HostResponse extends BaseResponseWithAnnotations { @Param(description = "true if the host supports encryption", since = "4.18") private Boolean encryptionSupported; + @SerializedName(ApiConstants.INSTANCE_CONVERSION_SUPPORTED) + @Param(description = "true if the host supports instance conversion (using virt-v2v)", since = "4.19.1") + private Boolean instanceConversionSupported; + @Override public String getObjectId() { return this.getId(); @@ -454,6 +471,22 @@ public class HostResponse extends BaseResponseWithAnnotations { this.hostTags = hostTags; } + public String getExplicitHostTags() { + return explicitHostTags; + } + + public void setExplicitHostTags(String explicitHostTags) { + this.explicitHostTags = explicitHostTags; + } + + public String getImplicitHostTags() { + return implicitHostTags; + } + + public void setImplicitHostTags(String implicitHostTags) { + this.implicitHostTags = implicitHostTags; + } + public void setHasEnoughCapacity(Boolean hasEnoughCapacity) { this.hasEnoughCapacity = hasEnoughCapacity; } @@ -522,7 +555,7 @@ public class HostResponse extends BaseResponseWithAnnotations { this.username = username; } - public void setDetails(Map details) { + public void setDetails(Map details, Hypervisor.HypervisorType hypervisorType) { if (details == null) { return; @@ -543,6 +576,15 @@ public class HostResponse extends BaseResponseWithAnnotations { this.setEncryptionSupported(new Boolean(false)); // default } + if (Hypervisor.HypervisorType.KVM.equals(hypervisorType)) { + if (detailsCopy.containsKey(Host.HOST_INSTANCE_CONVERSION)) { + this.setInstanceConversionSupported(Boolean.parseBoolean((String) detailsCopy.get(Host.HOST_INSTANCE_CONVERSION))); + detailsCopy.remove(Host.HOST_INSTANCE_CONVERSION); + } else { + this.setInstanceConversionSupported(new Boolean(false)); // default + } + } + this.details = detailsCopy; } @@ -732,4 +774,16 @@ public class HostResponse extends BaseResponseWithAnnotations { public void setEncryptionSupported(Boolean encryptionSupported) { this.encryptionSupported = encryptionSupported; } + + public void setInstanceConversionSupported(Boolean instanceConversionSupported) { + this.instanceConversionSupported = instanceConversionSupported; + } + + public Boolean getIsTagARule() { + return isTagARule; + } + + public void setIsTagARule(Boolean tagARule) { + isTagARule = tagARule; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/HostTagResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/HostTagResponse.java index 4a924ea78a0..f772da6dcb6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/HostTagResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/HostTagResponse.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.api.response; import com.google.gson.annotations.SerializedName; import com.cloud.serializer.Param; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; public class HostTagResponse extends BaseResponse { @@ -34,6 +35,10 @@ public class HostTagResponse extends BaseResponse { @Param(description = "the name of the host tag") private String name; + @SerializedName(ApiConstants.IS_IMPLICIT) + @Param(description = "true if the host tag is implicit", since = "4.20.0") + private boolean isImplicit; + public String getId() { return id; } @@ -57,4 +62,12 @@ public class HostTagResponse extends BaseResponse { public void setName(String name) { this.name = name; } + + public boolean isImplicit() { + return isImplicit; + } + + public void setImplicit(boolean implicit) { + isImplicit = implicit; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/IPAddressResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/IPAddressResponse.java index 7e3adc4ba01..8a9bf7789dd 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/IPAddressResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/IPAddressResponse.java @@ -128,7 +128,7 @@ public class IPAddressResponse extends BaseResponseWithAnnotations implements Co private String networkId; @SerializedName(ApiConstants.STATE) - @Param(description = "State of the ip address. Can be: Allocatin, Allocated and Releasing") + @Param(description = "State of the ip address. Can be: Allocating, Allocated, Releasing, Reserved and Free") private String state; @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @@ -167,6 +167,10 @@ public class IPAddressResponse extends BaseResponseWithAnnotations implements Co @Param(description="whether the ip address has Firewall/PortForwarding/LoadBalancing rules defined") private boolean hasRules; + @SerializedName(ApiConstants.FOR_SYSTEM_VMS) + @Param(description="true if range is dedicated for System VMs") + private boolean forSystemVms; + public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; } @@ -316,4 +320,8 @@ public class IPAddressResponse extends BaseResponseWithAnnotations implements Co public void setHasRules(final boolean hasRules) { this.hasRules = hasRules; } + + public void setForSystemVms(boolean forSystemVms) { + this.forSystemVms = forSystemVms; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ImageStoreResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ImageStoreResponse.java index 532963dbddc..ee44b6bc474 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/ImageStoreResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/ImageStoreResponse.java @@ -27,11 +27,11 @@ import com.google.gson.annotations.SerializedName; @EntityReference(value = ImageStore.class) public class ImageStoreResponse extends BaseResponseWithAnnotations { - @SerializedName("id") + @SerializedName(ApiConstants.ID) @Param(description = "the ID of the image store") private String id; - @SerializedName("zoneid") + @SerializedName(ApiConstants.ZONE_ID) @Param(description = "the Zone ID of the image store") private String zoneId; @@ -39,15 +39,15 @@ public class ImageStoreResponse extends BaseResponseWithAnnotations { @Param(description = "the Zone name of the image store") private String zoneName; - @SerializedName("name") + @SerializedName(ApiConstants.NAME) @Param(description = "the name of the image store") private String name; - @SerializedName("url") + @SerializedName(ApiConstants.URL) @Param(description = "the url of the image store") private String url; - @SerializedName("protocol") + @SerializedName(ApiConstants.PROTOCOL) @Param(description = "the protocol of the image store") private String protocol; @@ -55,11 +55,11 @@ public class ImageStoreResponse extends BaseResponseWithAnnotations { @Param(description = "the provider name of the image store") private String providerName; - @SerializedName("scope") + @SerializedName(ApiConstants.SCOPE) @Param(description = "the scope of the image store") private ScopeType scope; - @SerializedName("readonly") + @SerializedName(ApiConstants.READ_ONLY) @Param(description = "defines if store is read-only") private Boolean readonly; diff --git a/api/src/main/java/org/apache/cloudstack/api/response/IpQuarantineResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/IpQuarantineResponse.java new file mode 100644 index 00000000000..c93f259382c --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/IpQuarantineResponse.java @@ -0,0 +1,142 @@ +//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.response; + +import com.cloud.network.PublicIpQuarantine; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import java.util.Date; + +@EntityReference(value = {PublicIpQuarantine.class}) +public class IpQuarantineResponse extends BaseResponse { + + @SerializedName(ApiConstants.ID) + @Param(description = "ID of the quarantine process.") + private String id; + + @SerializedName(ApiConstants.IP_ADDRESS) + @Param(description = "The public IP address in quarantine.") + private String publicIpAddress; + + @SerializedName(ApiConstants.PREVIOUS_OWNER_ID) + @Param(description = "Account ID of the previous public IP address owner.") + private String previousOwnerId; + + @SerializedName(ApiConstants.PREVIOUS_OWNER_NAME) + @Param(description = "Account name of the previous public IP address owner.") + private String previousOwnerName; + + @SerializedName(ApiConstants.CREATED) + @Param(description = "When the quarantine was created.") + private Date created; + + @SerializedName(ApiConstants.REMOVED) + @Param(description = "When the quarantine was removed.") + private Date removed; + + @SerializedName(ApiConstants.END_DATE) + @Param(description = "End date for the quarantine.") + private Date endDate; + + @SerializedName(ApiConstants.REMOVAL_REASON) + @Param(description = "The reason for removing the IP from quarantine prematurely.") + private String removalReason; + + @SerializedName(ApiConstants.REMOVER_ACCOUNT_ID) + @Param(description = "ID of the account that removed the IP from quarantine.") + private String removerAccountId; + + public IpQuarantineResponse() { + super("quarantinedips"); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getPublicIpAddress() { + return publicIpAddress; + } + + public void setPublicIpAddress(String publicIpAddress) { + this.publicIpAddress = publicIpAddress; + } + + public String getPreviousOwnerId() { + return previousOwnerId; + } + + public void setPreviousOwnerId(String previousOwnerId) { + this.previousOwnerId = previousOwnerId; + } + + public String getPreviousOwnerName() { + return previousOwnerName; + } + + public void setPreviousOwnerName(String previousOwnerName) { + this.previousOwnerName = previousOwnerName; + } + + public Date getCreated() { + return created; + } + + public void setCreated(Date created) { + this.created = created; + } + + public Date getRemoved() { + return removed; + } + + public void setRemoved(Date removed) { + this.removed = removed; + } + + public Date getEndDate() { + return endDate; + } + + public void setEndDate(Date endDate) { + this.endDate = endDate; + } + + public String getRemovalReason() { + return removalReason; + } + + public void setRemovalReason(String removalReason) { + this.removalReason = removalReason; + } + + public String getRemoverAccountId() { + return removerAccountId; + } + + public void setRemoverAccountId(String removerAccountId) { + this.removerAccountId = removerAccountId; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NetworkOfferingResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NetworkOfferingResponse.java index b92725d883e..b73163a5d05 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NetworkOfferingResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NetworkOfferingResponse.java @@ -99,10 +99,18 @@ public class NetworkOfferingResponse extends BaseResponseWithAnnotations { @Param(description = "true if network offering can be used by VPC networks only") private Boolean forVpc; + @SerializedName(ApiConstants.FOR_NSX) + @Param(description = "true if network offering can be used by NSX networks only") + private Boolean forNsx; + @SerializedName(ApiConstants.FOR_TUNGSTEN) @Param(description = "true if network offering can be used by Tungsten-Fabric networks only") private Boolean forTungsten; + @SerializedName(ApiConstants.NSX_MODE) + @Param(description = "Mode in which the network will operate. This parameter is only relevant for NSX offerings") + private String nsxMode; + @SerializedName(ApiConstants.IS_PERSISTENT) @Param(description = "true if network offering supports persistent networks, false otherwise") private Boolean isPersistent; @@ -127,6 +135,10 @@ public class NetworkOfferingResponse extends BaseResponseWithAnnotations { @Param(description = "true if network offering supports public access for guest networks", since = "4.10.0") private Boolean supportsPublicAccess; + @SerializedName(ApiConstants.SUPPORTS_INTERNAL_LB) + @Param(description = "true if network offering supports public access for guest networks", since = "4.20.0") + private Boolean supportsInternalLb; + @SerializedName(ApiConstants.DOMAIN_ID) @Param(description = "the domain ID(s) this disk offering belongs to. Ignore this information as it is not currently applicable.") private String domainId; @@ -215,10 +227,18 @@ public class NetworkOfferingResponse extends BaseResponseWithAnnotations { this.forVpc = forVpc; } + public void setForNsx(Boolean forNsx) { + this.forNsx = forNsx; + } + public void setForTungsten(Boolean forTungsten) { this.forTungsten = forTungsten; } + public void setNsxMode(String nsxMode) { + this.nsxMode = nsxMode; + } + public void setIsPersistent(Boolean isPersistent) { this.isPersistent = isPersistent; } @@ -243,6 +263,10 @@ public class NetworkOfferingResponse extends BaseResponseWithAnnotations { this.supportsPublicAccess = supportsPublicAccess; } + public void setSupportsInternalLb(Boolean supportsInternalLb) { + this.supportsInternalLb = supportsInternalLb; + } + public String getDomainId() { return domainId; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NetworkProtocolResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NetworkProtocolResponse.java new file mode 100644 index 00000000000..775333f7192 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/NetworkProtocolResponse.java @@ -0,0 +1,89 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.response; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class NetworkProtocolResponse extends BaseResponse { + @SerializedName(ApiConstants.INDEX) + @Param(description = "the index (ID, Value, Code, Type, Option, etc) of the protocol parameter") + private Integer index; + + @SerializedName(ApiConstants.NAME) + @Param(description = "the name of the protocol parameter") + private String name; + + @SerializedName(ApiConstants.DESCRIPTION) + @Param(description = "the description of the protocol parameter") + private String description; + + @SerializedName(ApiConstants.DETAILS) + @Param(description = "the details of the protocol parameter") + private Map details; + + public NetworkProtocolResponse(Integer index, String name, String description) { + this.index = index; + this.name = name; + this.description = description; + } + + public Integer getIndex() { + return index; + } + + public void setIndex(Integer index) { + this.index = index; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Map getDetails() { + return details; + } + + public void setDetails(Map details) { + this.details = details; + } + + public void addDetail(String key, String value) { + if (this.details == null) { + this.details = new LinkedHashMap(); + } + this.details.put(key, value); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java index 243579e2f71..d34f949372a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java @@ -163,6 +163,10 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement @Param(description = "the domain name of the network owner") private String domain; + @SerializedName(ApiConstants.DOMAIN_PATH) + @Param(description = "path of the Domain the network belongs to", since = "4.19.0.0") + private String domainPath; + @SerializedName("isdefault") @Param(description = "true if network is default, false otherwise") private Boolean isDefault; @@ -420,6 +424,10 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement this.domain = domain; } + public void setDomainPath(String domainPath) { + this.domainPath = domainPath; + } + public void setNetworkOfferingAvailability(String networkOfferingAvailability) { this.networkOfferingAvailability = networkOfferingAvailability; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java index c267323cb7a..65e126de545 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NicResponse.java @@ -138,6 +138,14 @@ public class NicResponse extends BaseResponse { @Param(description = "MTU configured on the NIC", since="4.18.0") private Integer mtu; + @SerializedName(ApiConstants.PUBLIC_IP_ID) + @Param(description = "public IP address id associated with this nic via Static nat rule") + private String publicIpId; + + @SerializedName(ApiConstants.PUBLIC_IP) + @Param(description = "public IP address associated with this nic via Static nat rule") + private String publicIp; + public void setVmId(String vmId) { this.vmId = vmId; } @@ -400,4 +408,12 @@ public class NicResponse extends BaseResponse { public String getVpcId() { return vpcId; } + + public void setPublicIpId(String publicIpId) { + this.publicIpId = publicIpId; + } + + public void setPublicIp(String publicIp) { + this.publicIp = publicIp; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ObjectStoreResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ObjectStoreResponse.java new file mode 100644 index 00000000000..e4030799aa7 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/ObjectStoreResponse.java @@ -0,0 +1,106 @@ +// 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.response; + +import com.cloud.serializer.Param; +import org.apache.cloudstack.storage.object.ObjectStore; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.BaseResponseWithAnnotations; +import org.apache.cloudstack.api.EntityReference; + +@EntityReference(value = ObjectStore.class) +public class ObjectStoreResponse extends BaseResponseWithAnnotations { + @SerializedName("id") + @Param(description = "the ID of the object store") + private String id; + + @SerializedName("name") + @Param(description = "the name of the object store") + private String name; + + @SerializedName("url") + @Param(description = "the url of the object store") + private String url; + + @SerializedName("providername") + @Param(description = "the provider name of the object store") + private String providerName; + + @SerializedName("storagetotal") + @Param(description = "the total size of the object store") + private Long storageTotal; + + @SerializedName("storageused") + @Param(description = "the object store currently used size") + private Long storageUsed; + + public ObjectStoreResponse() { + } + + @Override + public String getObjectId() { + return this.getId(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getProviderName() { + return providerName; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public Long getStorageTotal() { + return storageTotal; + } + + public void setStorageTotal(Long storageTotal) { + this.storageTotal = storageTotal; + } + + public Long getStorageUsed() { + return storageUsed; + } + + public void setStorageUsed(Long storageUsed) { + this.storageUsed = storageUsed; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/PortableIpResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/PortableIpResponse.java index 73008b01ccd..e477b111561 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/PortableIpResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/PortableIpResponse.java @@ -68,7 +68,7 @@ public class PortableIpResponse extends BaseResponse { private Date allocated; @SerializedName(ApiConstants.STATE) - @Param(description = "State of the ip address. Can be: Allocatin, Allocated and Releasing") + @Param(description = "State of the ip address. Can be: Allocating, Allocated, Releasing and Free") private String state; public void setRegionId(Integer regionId) { diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ProjectResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ProjectResponse.java index c43dd09b127..1c63697559b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/ProjectResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/ProjectResponse.java @@ -216,6 +216,10 @@ public class ProjectResponse extends BaseResponse implements ResourceLimitAndCou @Param(description = "the date this project was created", since = "4.16.0") private Date created; + @SerializedName(ApiConstants.TAGGED_RESOURCES) + @Param(description = "The tagged resource limit and count for the project", since = "4.20.0") + List taggedResources; + public void setId(String id) { this.id = id; } @@ -447,4 +451,9 @@ public class ProjectResponse extends BaseResponse implements ResourceLimitAndCou public void setCreated(Date created) { this.created = created; } + + @Override + public void setTaggedResourceLimitsAndCounts(List taggedResourceLimitsAndCounts) { + this.taggedResources = taggedResourceLimitsAndCounts; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/PurgeExpungedResourcesResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/PurgeExpungedResourcesResponse.java new file mode 100644 index 00000000000..3807d0d5b16 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/PurgeExpungedResourcesResponse.java @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.response; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class PurgeExpungedResourcesResponse extends BaseResponse { + + @SerializedName(ApiConstants.RESOURCE_COUNT) + @Param(description = "The count of the purged expunged resources") + private Long resourceCount; + + public Long getResourceCount() { + return resourceCount; + } + + public void setResourceCount(Long resourceCount) { + this.resourceCount = resourceCount; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ResourceCountResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ResourceCountResponse.java index d0a4982f872..3a698618585 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/ResourceCountResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/ResourceCountResponse.java @@ -16,13 +16,12 @@ // under the License. package org.apache.cloudstack.api.response; -import com.cloud.configuration.Resource; -import com.google.gson.annotations.SerializedName; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; +import com.cloud.configuration.Resource; import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; @SuppressWarnings("unused") public class ResourceCountResponse extends BaseResponse implements ControlledEntityResponse { @@ -54,10 +53,14 @@ public class ResourceCountResponse extends BaseResponse implements ControlledEnt @Param(description = "resource type name. Values include user_vm, public_ip, volume, snapshot, template, project, network, vpc, cpu, memory, primary_storage, secondary_storage.") private String resourceTypeName; - @SerializedName("resourcecount") - @Param(description = "resource count") + @SerializedName(ApiConstants.RESOURCE_COUNT) + @Param(description = "The resource count") private long resourceCount; + @SerializedName(ApiConstants.TAG) + @Param(description = "Tag for the resource", since = "4.20.0") + private String tag; + @Override public void setAccountName(String accountName) { this.accountName = accountName; @@ -92,4 +95,7 @@ public class ResourceCountResponse extends BaseResponse implements ControlledEnt this.projectName = projectName; } + public void setTag(String tag) { + this.tag = tag; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ResourceLimitAndCountResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ResourceLimitAndCountResponse.java index f247be834cb..f9e6df3a038 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/ResourceLimitAndCountResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/ResourceLimitAndCountResponse.java @@ -20,6 +20,8 @@ have limits and resource count **/ package org.apache.cloudstack.api.response; +import java.util.List; + public interface ResourceLimitAndCountResponse { public void setNetworkLimit(String networkLimit); @@ -92,4 +94,6 @@ public interface ResourceLimitAndCountResponse { public void setVmRunning(Integer vmRunning); + public void setTaggedResourceLimitsAndCounts(List taggedResourceLimitsAndCounts); + } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ResourceLimitResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ResourceLimitResponse.java index 13e1198177d..72c1c66f5e8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/ResourceLimitResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/ResourceLimitResponse.java @@ -16,15 +16,14 @@ // under the License. package org.apache.cloudstack.api.response; -import com.cloud.configuration.Resource; -import com.google.gson.annotations.SerializedName; - import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; +import com.cloud.configuration.Resource; import com.cloud.configuration.ResourceLimit; import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; @EntityReference(value = ResourceLimit.class) @SuppressWarnings("unused") @@ -61,6 +60,10 @@ public class ResourceLimitResponse extends BaseResponse implements ControlledEnt @Param(description = "the project name of the resource limit") private String projectName; + @SerializedName(ApiConstants.TAG) + @Param(description = "The tag for the resource limit", since = "4.20.0") + private String tag; + @Override public void setAccountName(String accountName) { this.accountName = accountName; @@ -94,4 +97,8 @@ public class ResourceLimitResponse extends BaseResponse implements ControlledEnt public void setProjectId(String projectId) { this.projectId = projectId; } + + public void setTag(String tag) { + this.tag = tag; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/SecondaryStorageHeuristicsResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/SecondaryStorageHeuristicsResponse.java new file mode 100644 index 00000000000..25a6b2eca75 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/SecondaryStorageHeuristicsResponse.java @@ -0,0 +1,141 @@ +//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.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.secstorage.heuristics.Heuristic; + +import java.util.Date; + +import static org.apache.cloudstack.api.ApiConstants.HEURISTIC_TYPE_VALID_OPTIONS; + +@EntityReference(value = {Heuristic.class}) +public class SecondaryStorageHeuristicsResponse extends BaseResponse { + + @SerializedName(ApiConstants.ID) + @Param(description = "ID of the heuristic.") + private String id; + + @SerializedName(ApiConstants.NAME) + @Param(description = "Name of the heuristic.") + private String name; + + @SerializedName(ApiConstants.DESCRIPTION) + @Param(description = "Description of the heuristic.") + private String description; + + @SerializedName(ApiConstants.ZONE_ID) + @Param(description = "The zone which the heuristic is valid upon.") + private String zoneId; + + @SerializedName(ApiConstants.TYPE) + @Param(description = "The resource type directed to a specific secondary storage by the selector. " + HEURISTIC_TYPE_VALID_OPTIONS) + private String type; + + @SerializedName(ApiConstants.HEURISTIC_RULE) + @Param(description = "The heuristic rule, in JavaScript language, used to select a secondary storage to be directed.") + private String heuristicRule; + + @SerializedName(ApiConstants.CREATED) + @Param(description = "When the heuristic was created.") + private Date created; + + @SerializedName(ApiConstants.REMOVED) + @Param(description = "When the heuristic was removed.") + private Date removed; + + + public SecondaryStorageHeuristicsResponse(String id, String name, String description, String zoneId, String type, String heuristicRule, Date created, Date removed) { + super("heuristics"); + this.id = id; + this.name = name; + this.description = description; + this.zoneId = zoneId; + this.type = type; + this.heuristicRule = heuristicRule; + this.created = created; + this.removed = removed; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getZoneId() { + return zoneId; + } + + public void setZoneId(String zoneId) { + this.zoneId = zoneId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getHeuristicRule() { + return heuristicRule; + } + + public void setHeuristicRule(String heuristicRule) { + this.heuristicRule = heuristicRule; + } + + public Date getCreated() { + return created; + } + + public void setCreated(Date created) { + this.created = created; + } + + public Date getRemoved() { + return removed; + } + + public void setRemoved(Date removed) { + this.removed = removed; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingResponse.java index 53767adf17d..0622b936f6e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/ServiceOfferingResponse.java @@ -37,6 +37,10 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations { @Param(description = "the name of the service offering") private String name; + @SerializedName("state") + @Param(description = "state of the service offering") + private String state; + @SerializedName("displaytext") @Param(description = "an alternate display text of the service offering.") private String displayText; @@ -230,6 +234,10 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations { @Param(description = "true if virtual machine root disk will be encrypted on storage", since = "4.18") private Boolean encryptRoot; + @SerializedName(ApiConstants.PURGE_RESOURCES) + @Param(description = "Whether to cleanup VM and its associated resource upon expunge", since = "4.20") + private Boolean purgeResources; + public ServiceOfferingResponse() { } @@ -249,6 +257,14 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations { this.name = name; } + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + public Boolean getIsSystem() { return isSystem; } @@ -543,4 +559,8 @@ public class ServiceOfferingResponse extends BaseResponseWithAnnotations { } public void setEncryptRoot(Boolean encrypt) { this.encryptRoot = encrypt; } + + public void setPurgeResources(Boolean purgeResources) { + this.purgeResources = purgeResources; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/SnapshotPolicyResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/SnapshotPolicyResponse.java index d1e535ee743..bfa1cca1ca0 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/SnapshotPolicyResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/SnapshotPolicyResponse.java @@ -58,8 +58,13 @@ public class SnapshotPolicyResponse extends BaseResponseWithTagInformation { @Param(description = "is this policy for display to the regular user", since = "4.4", authorized = {RoleType.Admin}) private Boolean forDisplay; + @SerializedName(ApiConstants.ZONE) + @Param(description = "The list of zones in which snapshot backup is scheduled", responseObject = ZoneResponse.class, since = "4.19.0") + protected Set zones; + public SnapshotPolicyResponse() { tags = new LinkedHashSet(); + zones = new LinkedHashSet<>(); } public String getId() { @@ -121,4 +126,8 @@ public class SnapshotPolicyResponse extends BaseResponseWithTagInformation { public void setTags(Set tags) { this.tags = tags; } + + public void setZones(Set zones) { + this.zones = zones; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/SnapshotResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/SnapshotResponse.java index 5490e8a4046..02132416b8a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/SnapshotResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/SnapshotResponse.java @@ -18,6 +18,7 @@ package org.apache.cloudstack.api.response; import java.util.Date; import java.util.LinkedHashSet; +import java.util.Map; import java.util.Set; import org.apache.cloudstack.api.ApiConstants; @@ -29,7 +30,7 @@ import com.cloud.storage.Snapshot; import com.google.gson.annotations.SerializedName; @EntityReference(value = Snapshot.class) -public class SnapshotResponse extends BaseResponseWithTagInformation implements ControlledEntityResponse { +public class SnapshotResponse extends BaseResponseWithTagInformation implements ControlledViewEntityResponse { @SerializedName(ApiConstants.ID) @Param(description = "ID of the snapshot") private String id; @@ -70,6 +71,10 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements @Param(description = "type of the disk volume") private String volumeType; + @SerializedName(ApiConstants.VOLUME_STATE) + @Param(description = "state of the disk volume") + private String volumeState; + @SerializedName(ApiConstants.CREATED) @Param(description = " the date the snapshot was created") private Date created; @@ -90,6 +95,10 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements @Param(description = "the state of the snapshot. BackedUp means that snapshot is ready to be used; Creating - the snapshot is being allocated on the primary storage; BackingUp - the snapshot is being backed up on secondary storage") private Snapshot.State state; + @SerializedName(ApiConstants.STATUS) + @Param(description = "the status of the template") + private String status; + @SerializedName(ApiConstants.PHYSICAL_SIZE) @Param(description = "physical size of backedup snapshot on image store") private long physicalSize; @@ -98,6 +107,10 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements @Param(description = "id of the availability zone") private String zoneId; + @SerializedName(ApiConstants.ZONE_NAME) + @Param(description = "name of the availability zone") + private String zoneName; + @SerializedName(ApiConstants.REVERTABLE) @Param(description = "indicates whether the underlying storage supports reverting the volume to this snapshot") private boolean revertable; @@ -114,6 +127,26 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements @Param(description = "virtual size of backedup snapshot on image store") private long virtualSize; + @SerializedName(ApiConstants.DATASTORE_ID) + @Param(description = "ID of the datastore for the snapshot entry", since = "4.19.0") + private String datastoreId; + + @SerializedName(ApiConstants.DATASTORE_NAME) + @Param(description = "name of the datastore for the snapshot entry", since = "4.19.0") + private String datastoreName; + + @SerializedName(ApiConstants.DATASTORE_STATE) + @Param(description = "state of the snapshot on the datastore", since = "4.19.0") + private String datastoreState; + + @SerializedName(ApiConstants.DATASTORE_TYPE) + @Param(description = "type of the datastore for the snapshot entry", since = "4.19.0") + private String datastoreType; + + @SerializedName(ApiConstants.DOWNLOAD_DETAILS) + @Param(description = "download progress of a snapshot", since = "4.19.0") + private Map downloadDetails; + public SnapshotResponse() { tags = new LinkedHashSet(); } @@ -170,6 +203,10 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements this.volumeType = volumeType; } + public void setVolumeState(String volumeState) { + this.volumeState = volumeState; + } + public void setCreated(Date created) { this.created = created; } @@ -190,7 +227,11 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements this.state = state; } - public void setPhysicaSize(long physicalSize) { + public void setStatus(String status) { + this.status = status; + } + + public void setPhysicalSize(long physicalSize) { this.physicalSize = physicalSize; } @@ -208,6 +249,10 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements this.zoneId = zoneId; } + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + public void setTags(Set tags) { this.tags = tags; } @@ -231,4 +276,24 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements public void setVirtualSize(long virtualSize) { this.virtualSize = virtualSize; } + + public void setDatastoreId(String datastoreId) { + this.datastoreId = datastoreId; + } + + public void setDatastoreName(String datastoreName) { + this.datastoreName = datastoreName; + } + + public void setDatastoreState(String datastoreState) { + this.datastoreState = datastoreState; + } + + public void setDatastoreType(String datastoreType) { + this.datastoreType = datastoreType; + } + + public void setDownloadDetails(Map downloadDetails) { + this.downloadDetails = downloadDetails; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/StoragePoolResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/StoragePoolResponse.java index 89256c26473..9e7f5159e0e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/StoragePoolResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/StoragePoolResponse.java @@ -97,10 +97,22 @@ public class StoragePoolResponse extends BaseResponseWithAnnotations { @Param(description = "total min IOPS currently in use by volumes") private Long allocatedIops; + @SerializedName(ApiConstants.STORAGE_CUSTOM_STATS) + @Param(description = "the storage pool custom stats", since = "4.18.1") + private Map customStats; + @SerializedName("tags") @Param(description = "the tags for the storage pool") private String tags; + @SerializedName(ApiConstants.NFS_MOUNT_OPTIONS) + @Param(description = "the nfs mount options for the storage pool", since = "4.19.1") + private String nfsMountOpts; + + @SerializedName(ApiConstants.IS_TAG_A_RULE) + @Param(description = ApiConstants.PARAMETER_DESCRIPTION_IS_TAG_A_RULE) + private Boolean isTagARule; + @SerializedName(ApiConstants.STATE) @Param(description = "the state of the storage pool") private StoragePoolStatus state; @@ -296,6 +308,14 @@ public class StoragePoolResponse extends BaseResponseWithAnnotations { this.allocatedIops = allocatedIops; } + public Map getCustomStats() { + return customStats; + } + + public void setCustomStats(Map customStats) { + this.customStats = customStats; + } + public String getTags() { return tags; } @@ -304,6 +324,14 @@ public class StoragePoolResponse extends BaseResponseWithAnnotations { this.tags = tags; } + public Boolean getIsTagARule() { + return isTagARule; + } + + public void setIsTagARule(Boolean tagARule) { + isTagARule = tagARule; + } + public StoragePoolStatus getState() { return state; } @@ -335,4 +363,12 @@ public class StoragePoolResponse extends BaseResponseWithAnnotations { public void setProvider(String provider) { this.provider = provider; } + + public String getNfsMountOpts() { + return nfsMountOpts; + } + + public void setNfsMountOpts(String nfsMountOpts) { + this.nfsMountOpts = nfsMountOpts; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java index 69b9b4cad9c..31a8b731491 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/SystemVmResponse.java @@ -178,6 +178,14 @@ public class SystemVmResponse extends BaseResponseWithAnnotations { @Param(description = "true if vm contains XS/VMWare tools inorder to support dynamic scaling of VM cpu/memory.") private Boolean isDynamicallyScalable; + @SerializedName(ApiConstants.SERVICE_OFFERING_ID) + @Param(description = "the ID of the service offering of the system virtual machine.") + private String serviceOfferingId; + + @SerializedName("serviceofferingname") + @Param(description = "the name of the service offering of the system virtual machine.") + private String serviceOfferingName; + @Override public String getObjectId() { return this.getId(); @@ -466,4 +474,20 @@ public class SystemVmResponse extends BaseResponseWithAnnotations { public void setDynamicallyScalable(Boolean dynamicallyScalable) { isDynamicallyScalable = dynamicallyScalable; } + + public String getServiceOfferingId() { + return serviceOfferingId; + } + + public void setServiceOfferingId(String serviceOfferingId) { + this.serviceOfferingId = serviceOfferingId; + } + + public String getServiceOfferingName() { + return serviceOfferingName; + } + + public void setServiceOfferingName(String serviceOfferingName) { + this.serviceOfferingName = serviceOfferingName; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/TaggedResourceLimitAndCountResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/TaggedResourceLimitAndCountResponse.java new file mode 100644 index 00000000000..bfb03b7667c --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/TaggedResourceLimitAndCountResponse.java @@ -0,0 +1,86 @@ +// 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.response; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.configuration.Resource; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class TaggedResourceLimitAndCountResponse extends BaseResponse { + + @SerializedName(ApiConstants.RESOURCE_TYPE) + @Param(description = "Numerical value for the type of the resource. See the ResourceType for more information on these values.") + private Integer resourceType; + + @SerializedName(ApiConstants.RESOURCE_TYPE_NAME) + @Param(description = "Name for the type of the resource") + private String resourceTypeName; + + @SerializedName(ApiConstants.TAG) + @Param(description = "The tag for the resource type") + private String tag; + + @SerializedName(ApiConstants.LIMIT) + @Param(description = "The limit for the resource count for the type and tag for the owner") + private Long limit; + + @SerializedName(ApiConstants.TOTAL) + @Param(description = "The total amount of the resource for the type and tag that is used by the owner") + private Long total; + + @SerializedName(ApiConstants.AVAILABLE) + @Param(description = "The available amount of the resource for the type and tag that is available for the owner") + private Long available; + + + public void setResourceType(Resource.ResourceType resourceType) { + this.resourceType = resourceType.getOrdinal(); + this.resourceTypeName = resourceType.getName(); + } + + public void setTag(String tag) { + this.tag = tag; + } + + public void setLimit(Long limit) { + this.limit = limit; + } + + public void setTotal(Long total) { + this.total = total; + } + + public void setAvailable(Long available) { + this.available = available; + } + + public Long getLimit() { + return limit; + } + + public Long getTotal() { + return total; + } + + public Long getAvailable() { + return available; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/TemplateResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/TemplateResponse.java index bd09d098708..3abd44941d9 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/TemplateResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/TemplateResponse.java @@ -123,7 +123,7 @@ public class TemplateResponse extends BaseResponseWithTagInformation implements @Param(description = "the physical size of the template") private Long physicalSize; - @SerializedName(ApiConstants.TEMPLATETYPE) + @SerializedName(ApiConstants.TEMPLATE_TYPE) @Param(description = "the type of the template") private String templateType; diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java index e866b19e1c1..7a26b178591 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UnmanagedInstanceResponse.java @@ -39,6 +39,10 @@ public class UnmanagedInstanceResponse extends BaseResponse { @Param(description = "the ID of the cluster to which virtual machine belongs") private String clusterId; + @SerializedName(ApiConstants.CLUSTER_NAME) + @Param(description = "the name of the cluster to which virtual machine belongs") + private String clusterName; + @SerializedName(ApiConstants.HOST_ID) @Param(description = "the ID of the host to which virtual machine belongs") private String hostId; @@ -104,6 +108,14 @@ public class UnmanagedInstanceResponse extends BaseResponse { this.clusterId = clusterId; } + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + public String getHostId() { return hostId; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java index 7bcb1afd2d2..4522315b499 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.response; +import java.util.Date; import java.util.LinkedHashSet; import java.util.Set; @@ -133,11 +134,11 @@ public class UsageRecordResponse extends BaseResponseWithTagInformation implemen @SerializedName(ApiConstants.START_DATE) @Param(description = "start date of the usage record") - private String startDate; + private Date startDate; @SerializedName(ApiConstants.END_DATE) @Param(description = "end date of the usage record") - private String endDate; + private Date endDate; @SerializedName("issourcenat") @Param(description = "True if the IPAddress is source NAT") @@ -160,7 +161,7 @@ public class UsageRecordResponse extends BaseResponseWithTagInformation implemen private String vpcId; public UsageRecordResponse() { - tags = new LinkedHashSet(); + tags = new LinkedHashSet<>(); } public void setTags(Set tags) { @@ -245,11 +246,11 @@ public class UsageRecordResponse extends BaseResponseWithTagInformation implemen this.size = size; } - public void setStartDate(String startDate) { + public void setStartDate(Date startDate) { this.startDate = startDate; } - public void setEndDate(String endDate) { + public void setEndDate(Date endDate) { this.endDate = endDate; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UserDataResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UserDataResponse.java index bbe27f84520..e69094c8f80 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UserDataResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UserDataResponse.java @@ -24,7 +24,7 @@ import org.apache.cloudstack.api.BaseResponseWithAnnotations; import org.apache.cloudstack.api.EntityReference; @EntityReference(value = UserData.class) -public class UserDataResponse extends BaseResponseWithAnnotations { +public class UserDataResponse extends BaseResponseWithAnnotations implements ControlledEntityResponse { @SerializedName(ApiConstants.ID) @Param(description = "ID of the ssh keypair") @@ -40,6 +40,14 @@ public class UserDataResponse extends BaseResponseWithAnnotations { @SerializedName(ApiConstants.ACCOUNT) @Param(description="the owner of the userdata") private String accountName; + @SerializedName(ApiConstants.PROJECT_ID) + @Param(description = "the project id of the userdata", since = "4.19.1") + private String projectId; + + @SerializedName(ApiConstants.PROJECT) + @Param(description = "the project name of the userdata", since = "4.19.1") + private String projectName; + @SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain id of the userdata owner") private String domainId; @@ -118,6 +126,16 @@ public class UserDataResponse extends BaseResponseWithAnnotations { this.accountName = accountName; } + @Override + public void setProjectId(String projectId) { + this.projectId = projectId; + } + + @Override + public void setProjectName(String projectName) { + this.projectName = projectName; + } + public String getDomainName() { return domain; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java index 114403da7bc..8deae7d80d3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java @@ -16,9 +16,12 @@ // under the License. package org.apache.cloudstack.api.response; +import java.util.ArrayList; import java.util.Comparator; import java.util.Date; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -34,6 +37,7 @@ import com.cloud.serializer.Param; import com.cloud.uservm.UserVm; import com.cloud.vm.VirtualMachine; import com.google.gson.annotations.SerializedName; +import org.apache.commons.collections.CollectionUtils; @SuppressWarnings("unused") @EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class}) @@ -130,6 +134,14 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co @Param(description = "the name of the template for the virtual machine") private String templateName; + @SerializedName(ApiConstants.TEMPLATE_TYPE) + @Param(description = "the type of the template for the virtual machine", since = "4.19.0") + private String templateType; + + @SerializedName(ApiConstants.TEMPLATE_FORMAT) + @Param(description = "the format of the template for the virtual machine", since = "4.19.1") + private String templateFormat; + @SerializedName("templatedisplaytext") @Param(description = " an alternate display text of the template for the virtual machine") private String templateDisplayText; @@ -159,11 +171,11 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co private String serviceOfferingName; @SerializedName(ApiConstants.DISK_OFFERING_ID) - @Param(description = "the ID of the disk offering of the virtual machine", since = "4.4") + @Param(description = "the ID of the disk offering of the virtual machine. This parameter should not be used for retrieving disk offering details of DATA volumes. Use listVolumes API instead", since = "4.4") private String diskOfferingId; @SerializedName("diskofferingname") - @Param(description = "the name of the disk offering of the virtual machine", since = "4.4") + @Param(description = "the name of the disk offering of the virtual machine. This parameter should not be used for retrieving disk offering details of DATA volumes. Use listVolumes API instead", since = "4.4") private String diskOfferingName; @SerializedName(ApiConstants.BACKUP_OFFERING_ID) @@ -262,6 +274,10 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co @Param(description = "the hypervisor on which the template runs") private String hypervisor; + @SerializedName(ApiConstants.IP_ADDRESS) + @Param(description = "the VM's primary IP address") + private String ipAddress; + @SerializedName(ApiConstants.PUBLIC_IP_ID) @Param(description = "public IP address id associated with vm via Static nat rule") private String publicIpId; @@ -360,6 +376,14 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co @SerializedName(ApiConstants.USER_DATA_DETAILS) @Param(description="list of variables and values for the variables declared in userdata", since = "4.18.0") private String userDataDetails; + @SerializedName(ApiConstants.VNF_NICS) + @Param(description = "NICs of the VNF appliance", since = "4.19.0") + private List vnfNics; + + @SerializedName(ApiConstants.VNF_DETAILS) + @Param(description = "VNF details", since = "4.19.0") + private Map vnfDetails; + public UserVmResponse() { securityGroupList = new LinkedHashSet<>(); nics = new TreeSet<>(Comparator.comparingInt(x -> Integer.parseInt(x.getDeviceId()))); @@ -608,6 +632,10 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co return hypervisor; } + public String getIpAddress() { + return ipAddress; + } + public String getPublicIpId() { return publicIpId; } @@ -844,6 +872,13 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co public void setNics(Set nics) { this.nics = nics; + setIpAddress(nics); + } + + public void setIpAddress(final Set nics) { + if (CollectionUtils.isNotEmpty(nics)) { + this.ipAddress = nics.iterator().next().getIpaddress(); + } } public void addNic(NicResponse nic) { @@ -1045,4 +1080,57 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co this.userDataDetails = userDataDetails; } + public Long getBytesReceived() { + return bytesReceived; + } + + public Long getBytesSent() { + return bytesSent; + } + + public String getTemplateType() { + return templateType; + } + + public void setTemplateType(String templateType) { + this.templateType = templateType; + } + + public String getTemplateFormat() { + return templateFormat; + } + + public void setTemplateFormat(String templateFormat) { + this.templateFormat = templateFormat; + } + + public List getVnfNics() { + return vnfNics; + } + + public void setVnfNics(List vnfNics) { + this.vnfNics = vnfNics; + } + + public Map getVnfDetails() { + return vnfDetails; + } + + public void setVnfDetails(Map vnfDetails) { + this.vnfDetails = vnfDetails; + } + + public void addVnfNic(VnfNicResponse vnfNic) { + if (this.vnfNics == null) { + this.vnfNics = new ArrayList<>(); + } + this.vnfNics.add(vnfNic); + } + + public void addVnfDetail(String key, String value) { + if (this.vnfDetails == null) { + this.vnfDetails = new LinkedHashMap<>(); + } + this.vnfDetails.put(key,value); + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VMUserDataResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VMUserDataResponse.java index 1b739e56442..cf819491c2c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/VMUserDataResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/VMUserDataResponse.java @@ -30,7 +30,7 @@ public class VMUserDataResponse extends BaseResponse { private String vmId; @SerializedName(ApiConstants.USER_DATA) - @Param(description = "Base 64 encoded VM user data") + @Param(description = "Base64 encoded VM user data") private String userData; public void setUserData(String userData) { diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VirtualMachineResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VirtualMachineResponse.java new file mode 100644 index 00000000000..7d676292b8a --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/VirtualMachineResponse.java @@ -0,0 +1,124 @@ +// 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.response; + +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.serializer.Param; +import com.cloud.vm.VirtualMachine; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value = VirtualMachine.class) +public class VirtualMachineResponse extends BaseResponse { + @SerializedName("id") + @Param(description = "the ID of the VM") + private String id; + + @SerializedName("type") + @Param(description = "the type of VM") + private String type; + + @SerializedName("name") + @Param(description = "the name of the VM") + private String name; + + @SerializedName("clusterid") + @Param(description = "the cluster ID for the VM") + private String clusterId; + + @SerializedName("clustername") + @Param(description = "the cluster name for the VM") + private String clusterName; + + @SerializedName("hostid") + @Param(description = "the host ID for the VM") + private String hostId; + + @SerializedName("hostname") + @Param(description = "the hostname for the VM") + private String hostName; + + @Override + public String getObjectId() { + return this.getId(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getVmType() { + return type; + } + + public void setVmType(String type) { + this.type = type; + } + + public String getVmName() { + return name; + } + + public void setVmName(String name) { + this.name = name; + } + + public String getClusterId() { + return clusterId; + } + + public void setClusterId(String clusterId) { + this.clusterId = clusterId; + } + + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getHostId() { + return hostId; + } + + public void setHostId(String hostId) { + this.hostId = hostId; + } + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VlanIpRangeResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VlanIpRangeResponse.java index a22e2eb7024..aac6dd3c577 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/VlanIpRangeResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/VlanIpRangeResponse.java @@ -123,6 +123,10 @@ public class VlanIpRangeResponse extends BaseResponse implements ControlledEntit @Param(description = "indicates whether VLAN IP range is dedicated to system vms or not") private Boolean forSystemVms; + @SerializedName(ApiConstants.FOR_NSX) + @Param(description = "indicates whether IP range is dedicated to NSX resources or not") + private Boolean forNsx; + public void setId(String id) { this.id = id; } @@ -235,4 +239,8 @@ public class VlanIpRangeResponse extends BaseResponse implements ControlledEntit public void setIp6Cidr(String ip6Cidr) { this.ip6Cidr = ip6Cidr; } + + public void setForNsx(Boolean forNsx) { + this.forNsx = forNsx; + } } diff --git a/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java similarity index 97% rename from plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java rename to api/src/main/java/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java index ddd4a364a0a..3cf06f38242 100644 --- a/plugins/hypervisors/vmware/src/main/java/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java @@ -23,7 +23,7 @@ import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; -import com.cloud.hypervisor.vmware.VmwareDatacenter; +import com.cloud.dc.VmwareDatacenter; import com.cloud.serializer.Param; @EntityReference(value = VmwareDatacenter.class) diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VnfNicResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VnfNicResponse.java new file mode 100644 index 00000000000..af238c5a330 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/VnfNicResponse.java @@ -0,0 +1,119 @@ +// 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.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; + +@SuppressWarnings("unused") +public class VnfNicResponse { + @SerializedName(ApiConstants.DEVICE_ID) + @Param(description = "Device id of the NIC") + private long deviceId; + + @SerializedName(ApiConstants.NAME) + @Param(description = "Name of the NIC") + private String name; + + @SerializedName(ApiConstants.REQUIRED) + @Param(description = "True if the NIC is required. False if optional") + private Boolean required; + + @SerializedName(ApiConstants.MANAGEMENT) + @Param(description = "True if the NIC is a management interface. False otherwise") + private Boolean management; + + @SerializedName(ApiConstants.DESCRIPTION) + @Param(description = "Description of the NIC") + private String description; + + @SerializedName(ApiConstants.NETWORK_ID) + @Param(description = "Network id of the NIC") + private String networkId; + + @SerializedName(ApiConstants.NETWORK_NAME) + @Param(description = "Network name of the NIC") + private String networkName; + + public void setDeviceId(long deviceId) { + this.deviceId = deviceId; + } + + public void setName(String name) { + this.name = name; + } + + public void setRequired(Boolean required) { + this.required = required; + } + + public void setManagement(Boolean management) { + this.management = management; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setNetworkId(String networkId) { + this.networkId = networkId; + } + + public void setNetworkName(String networkName) { + this.networkName = networkName; + } + + public VnfNicResponse() { + } + + public VnfNicResponse(long deviceId, String name, Boolean required, Boolean management, String description) { + this.deviceId = deviceId; + this.name = name; + this.required = required; + this.management = management; + this.description = description; + } + + public long getDeviceId() { + return deviceId; + } + + public String getName() { + return name; + } + + public Boolean isRequired() { + return required; + } + + public Boolean isManagement() { + return management; + } + + public String getDescription() { + return description; + } + + public String getNetworkId() { + return networkId; + } + + public String getNetworkName() { + return networkName; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VnfTemplateResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VnfTemplateResponse.java new file mode 100644 index 00000000000..5fd17efca88 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/VnfTemplateResponse.java @@ -0,0 +1,60 @@ +// 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.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("unused") +public class VnfTemplateResponse extends TemplateResponse { + + @SerializedName(ApiConstants.VNF_NICS) + @Param(description = "NICs of the VNF template") + private List vnfNics; + + @SerializedName(ApiConstants.VNF_DETAILS) + @Param(description = "VNF details") + private Map vnfDetails; + + public void addVnfNic(VnfNicResponse vnfNic) { + if (this.vnfNics == null) { + this.vnfNics = new ArrayList<>(); + } + this.vnfNics.add(vnfNic); + } + + public void addVnfDetail(String key, String value) { + if (this.vnfDetails == null) { + this.vnfDetails = new LinkedHashMap<>(); + } + this.vnfDetails.put(key,value); + } + + public List getVnfNics() { + return vnfNics; + } + + public Map getVnfDetails() { + return vnfDetails; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VolumeForImportResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VolumeForImportResponse.java new file mode 100644 index 00000000000..803f154816a --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/api/response/VolumeForImportResponse.java @@ -0,0 +1,176 @@ +// 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.response; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.storage.volume.VolumeOnStorageTO; + +import java.util.Map; + +@EntityReference(value = VolumeOnStorageTO.class) +public class VolumeForImportResponse extends BaseResponse { + + @SerializedName(ApiConstants.NAME) + @Param(description = "the name of the volume") + private String name; + + @SerializedName(ApiConstants.PATH) + @Param(description = "the path of the volume") + private String path; + + @SerializedName(ApiConstants.FULL_PATH) + @Param(description = "the full path of the volume") + private String fullPath; + + @SerializedName(ApiConstants.FORMAT) + @Param(description = "the format of the volume") + private String format; + + @SerializedName(ApiConstants.SIZE) + @Param(description = "the size of the volume") + private long size; + + @SerializedName(ApiConstants.VIRTUAL_SIZE) + @Param(description = "the virtual size of the volume") + private long virtualSize; + + @SerializedName(ApiConstants.ENCRYPT_FORMAT) + @Param(description = "the encrypt format of the volume") + private String qemuEncryptFormat; + + @SerializedName(ApiConstants.STORAGE_ID) + @Param(description = "id of the primary storage hosting the volume") + private String storagePoolId; + + @SerializedName(ApiConstants.STORAGE) + @Param(description = "name of the primary storage hosting the volume") + private String storagePoolName; + + @SerializedName(ApiConstants.STORAGE_TYPE) + @Param(description = "type of the primary storage hosting the volume") + private String storagePoolType; + + @SerializedName(ApiConstants.DETAILS) + @Param(description = "volume details in key/value pairs.") + private Map details; + + @SerializedName(ApiConstants.CHAIN_INFO) + @Param(description = "the chain info of the volume") + String chainInfo; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getFullPath() { + return fullPath; + } + + public void setFullPath(String fullPath) { + this.fullPath = fullPath; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public long getVirtualSize() { + return virtualSize; + } + + public void setVirtualSize(long virtualSize) { + this.virtualSize = virtualSize; + } + + public String getQemuEncryptFormat() { + return qemuEncryptFormat; + } + + public void setQemuEncryptFormat(String qemuEncryptFormat) { + this.qemuEncryptFormat = qemuEncryptFormat; + } + + public String getStoragePoolId() { + return storagePoolId; + } + + public void setStoragePoolId(String storagePoolId) { + this.storagePoolId = storagePoolId; + } + + public String getStoragePoolName() { + return storagePoolName; + } + + public void setStoragePoolName(String storagePoolName) { + this.storagePoolName = storagePoolName; + } + + public String getStoragePoolType() { + return storagePoolType; + } + + public void setStoragePoolType(String storagePoolType) { + this.storagePoolType = storagePoolType; + } + + public Map getDetails() { + return details; + } + + public void setDetails(Map details) { + this.details = details; + } + + public String getChainInfo() { + return chainInfo; + } + + public void setChainInfo(String chainInfo) { + this.chainInfo = chainInfo; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java index 00a1eabc40b..726c9adf8a3 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java @@ -18,6 +18,7 @@ package org.apache.cloudstack.api.response; import java.util.Date; import java.util.LinkedHashSet; +import java.util.Map; import java.util.Set; import org.apache.cloudstack.acl.RoleType; @@ -288,6 +289,18 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co @Param(description = "volume uuid that is given by virtualisation provider (only for VMware)") private String externalUuid; + @SerializedName(ApiConstants.VOLUME_CHECK_RESULT) + @Param(description = "details for the volume check result, they may vary for different hypervisors", since = "4.19.1") + private Map volumeCheckResult; + + @SerializedName(ApiConstants.VOLUME_REPAIR_RESULT) + @Param(description = "details for the volume repair result, they may vary for different hypervisors", since = "4.19.1") + private Map volumeRepairResult; + + @SerializedName(ApiConstants.ENCRYPT_FORMAT) + @Param(description = "the format of the disk encryption if applicable", since = "4.19.1") + private String encryptionFormat; + public String getPath() { return path; } @@ -817,4 +830,24 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co public void setExternalUuid(String externalUuid) { this.externalUuid = externalUuid; } + + public Map getVolumeCheckResult() { + return volumeCheckResult; + } + + public void setVolumeCheckResult(Map volumeCheckResult) { + this.volumeCheckResult = volumeCheckResult; + } + + public Map getVolumeRepairResult() { + return volumeRepairResult; + } + + public void setVolumeRepairResult(Map volumeRepairResult) { + this.volumeRepairResult = volumeRepairResult; + } + + public void setEncryptionFormat(String encryptionFormat) { + this.encryptionFormat = encryptionFormat; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VpcOfferingResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VpcOfferingResponse.java index 6881969646b..ce00827f06d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/VpcOfferingResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/VpcOfferingResponse.java @@ -63,9 +63,17 @@ public class VpcOfferingResponse extends BaseResponse { private Boolean supportsDistributedRouter; @SerializedName((ApiConstants.SUPPORTS_REGION_LEVEL_VPC)) - @Param(description = " indicated if the offering can support region level vpc", since = "4.4") + @Param(description = "indicated if the offering can support region level vpc", since = "4.4") private Boolean supportsRegionLevelVpc; + @SerializedName(ApiConstants.FOR_NSX) + @Param(description = "true if vpc offering can be used by NSX networks only") + private Boolean forNsx; + + @SerializedName(ApiConstants.NSX_MODE) + @Param(description = "Mode in which the network will operate. This parameter is only relevant for NSX offerings") + private String nsxMode; + @SerializedName(ApiConstants.DOMAIN_ID) @Param(description = "the domain ID(s) this disk offering belongs to. Ignore this information as it is not currently applicable.") private String domainId; @@ -138,6 +146,14 @@ public class VpcOfferingResponse extends BaseResponse { this.domain = domain; } + public void setForNsx(Boolean forNsx) { + this.forNsx = forNsx; + } + + public void setNsxMode(String nsxMode) { + this.nsxMode = nsxMode; + } + public String getZoneId() { return zoneId; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VpnUsersResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VpnUsersResponse.java index 3a0e84285aa..d3e4d941678 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/VpnUsersResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/VpnUsersResponse.java @@ -57,7 +57,7 @@ public class VpnUsersResponse extends BaseResponse implements ControlledEntityRe private String projectName; @SerializedName(ApiConstants.STATE) - @Param(description = "the state of the Vpn User") + @Param(description = "the state of the Vpn User, can be 'Add', 'Revoke' or 'Active'.") private String state; public void setId(String id) { diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java index b8824fd66f8..a898cd9d577 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java @@ -95,7 +95,7 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso @SerializedName("securitygroupsenabled") @Param(description = "true if security groups support is enabled, false otherwise") - private boolean securityGroupsEnabled; + private Boolean securityGroupsEnabled; @SerializedName("allocationstate") @Param(description = "the allocation state of the cluster") @@ -115,7 +115,7 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso @SerializedName(ApiConstants.LOCAL_STORAGE_ENABLED) @Param(description = "true if local storage offering enabled, false otherwise") - private boolean localStorageEnabled; + private Boolean localStorageEnabled; @SerializedName(ApiConstants.TAGS) @Param(description = "the list of resource tags associated with zone.", responseObject = ResourceTagResponse.class, since = "4.3") @@ -131,7 +131,7 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso @SerializedName(ApiConstants.ALLOW_USER_SPECIFY_VR_MTU) @Param(description = "Allow end users to specify VR MTU", since = "4.18.0") - private boolean allowUserSpecifyVRMtu; + private Boolean allowUserSpecifyVRMtu; @SerializedName(ApiConstants.ROUTER_PRIVATE_INTERFACE_MAX_MTU) @Param(description = "The maximum value the MTU can have on the VR's private interfaces", since = "4.18.0") @@ -145,6 +145,10 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso @Param(description = "the type of the zone - core or edge", since = "4.18.0") String type; + @SerializedName(ApiConstants.NSX_ENABLED) + @Param(description = "true, if zone is NSX enabled", since = "4.20.0") + private boolean nsxEnabled = false; + public ZoneResponse() { tags = new LinkedHashSet(); } @@ -197,7 +201,7 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso this.networkType = networkType; } - public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) { + public void setSecurityGroupsEnabled(Boolean securityGroupsEnabled) { this.securityGroupsEnabled = securityGroupsEnabled; } @@ -221,7 +225,7 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso this.domainName = domainName; } - public void setLocalStorageEnabled(boolean localStorageEnabled) { + public void setLocalStorageEnabled(Boolean localStorageEnabled) { this.localStorageEnabled = localStorageEnabled; } @@ -241,6 +245,10 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso this.ip6Dns2 = ip6Dns2; } + public void setTags(Set tags) { + this.tags = tags; + } + public void addTag(ResourceTagResponse tag) { this.tags.add(tag); } @@ -345,7 +353,7 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso return resourceIconResponse; } - public void setAllowUserSpecifyVRMtu(boolean allowUserSpecifyVRMtu) { + public void setAllowUserSpecifyVRMtu(Boolean allowUserSpecifyVRMtu) { this.allowUserSpecifyVRMtu = allowUserSpecifyVRMtu; } @@ -364,4 +372,8 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso public String getType() { return type; } + + public void setNsxEnabled(boolean nsxEnabled) { + this.nsxEnabled = nsxEnabled; + } } diff --git a/api/src/main/java/org/apache/cloudstack/auth/UserOAuth2Authenticator.java b/api/src/main/java/org/apache/cloudstack/auth/UserOAuth2Authenticator.java new file mode 100644 index 00000000000..ee3b98b8a4b --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/auth/UserOAuth2Authenticator.java @@ -0,0 +1,53 @@ +// 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.auth; + +import com.cloud.utils.component.Adapter; +import com.cloud.utils.exception.CloudRuntimeException; + +public interface UserOAuth2Authenticator extends Adapter { + /** + * Returns the unique name of the provider + * @return returns provider name + */ + String getName(); + + /** + * Returns description about the OAuth2 provider plugin + * @return returns description + */ + String getDescription(); + + /** + * Verifies if the logged in user is + * @return returns true if its valid user + */ + boolean verifyUser(String email, String secretCode); + + /** + * Verifies the code provided by provider and fetches email + * @return returns email + */ + String verifyCodeAndFetchEmail(String secretCode); + + + /** + * Fetches email using the accessToken + * @return returns email + */ + String getUserEmailAddress() throws CloudRuntimeException; +} diff --git a/api/src/main/java/org/apache/cloudstack/backup/Backup.java b/api/src/main/java/org/apache/cloudstack/backup/Backup.java index f369367957d..df1b243dbab 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/Backup.java +++ b/api/src/main/java/org/apache/cloudstack/backup/Backup.java @@ -134,6 +134,7 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity { } long getVmId(); + long getBackupOfferingId(); String getExternalId(); String getType(); Date getDate(); diff --git a/api/src/main/java/org/apache/cloudstack/ca/CAManager.java b/api/src/main/java/org/apache/cloudstack/ca/CAManager.java index 12a9d3d7b41..b0fb1ac73c2 100644 --- a/api/src/main/java/org/apache/cloudstack/ca/CAManager.java +++ b/api/src/main/java/org/apache/cloudstack/ca/CAManager.java @@ -77,6 +77,14 @@ public interface CAManager extends CAService, Configurable, PluggableService { "15", "The number of days before expiry of a client certificate, the validations are checked. Admins are alerted when auto-renewal is not allowed, otherwise auto-renewal is attempted.", true, ConfigKey.Scope.Cluster); + + ConfigKey CertManagementCustomSubjectAlternativeName = new ConfigKey<>("Advanced", String.class, + "ca.framework.cert.management.custom.san", + "cloudstack.internal", + "The custom Subject Alternative Name that will be added to the management server certificate. " + + "The actual implementation will depend on the configured CA provider.", + false); + /** * Returns a list of available CA provider plugins * @return returns list of CAProvider diff --git a/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsAlgorithm.java b/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsAlgorithm.java new file mode 100644 index 00000000000..15f7fcd8174 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsAlgorithm.java @@ -0,0 +1,263 @@ +/* + * 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.cluster; + +import com.cloud.host.Host; +import com.cloud.offering.ServiceOffering; +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.math3.stat.descriptive.moment.Mean; +import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation; + +import javax.naming.ConfigurationException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.apache.cloudstack.cluster.ClusterDrsService.ClusterDrsMetric; +import static org.apache.cloudstack.cluster.ClusterDrsService.ClusterDrsMetricType; +import static org.apache.cloudstack.cluster.ClusterDrsService.ClusterDrsMetricUseRatio; + +public interface ClusterDrsAlgorithm extends Adapter { + + /** + * Determines whether a DRS operation is needed for a given cluster and host-VM + * mapping. + * + * @param clusterId + * the ID of the cluster to check + * @param cpuList + * a list of Ternary of used, reserved & total CPU for each host in the cluster + * @param memoryList + * a list of Ternary of used, reserved & total memory values for each host in the cluster + * + * @return true if a DRS operation is needed, false otherwise + * + * @throws ConfigurationException + * if there is an error in the configuration + */ + boolean needsDrs(long clusterId, List> cpuList, + List> 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 + * + * @return a ternary containing improvement, cost, benefit + */ + Ternary getMetrics(long clusterId, VirtualMachine vm, ServiceOffering serviceOffering, + Host destHost, Map> hostCpuMap, + Map> hostMemoryMap, + Boolean requiresStorageMotion) throws ConfigurationException; + + /** + * Calculates the imbalance of the cluster after a virtual machine migration. + * + * @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 + */ + default Double getImbalancePostMigration(ServiceOffering serviceOffering, VirtualMachine vm, + Host destHost, Map> hostCpuMap, + Map> hostMemoryMap) throws ConfigurationException { + Pair>> pair = getHostMetricsMapAndType(destHost.getClusterId(), serviceOffering, hostCpuMap, hostMemoryMap); + long vmMetric = pair.first(); + Map> hostMetricsMap = pair.second(); + + List list = new ArrayList<>(); + for (Long hostId : hostMetricsMap.keySet()) { + list.add(getMetricValuePostMigration(destHost.getClusterId(), hostMetricsMap.get(hostId), vmMetric, hostId, destHost.getId(), vm.getHostId())); + } + return getImbalance(list); + } + + private Pair>> getHostMetricsMapAndType(Long clusterId, + ServiceOffering serviceOffering, Map> hostCpuMap, + Map> hostMemoryMap) throws ConfigurationException { + String metric = getClusterDrsMetric(clusterId); + Pair>> pair; + switch (metric) { + case "cpu": + pair = new Pair<>((long) serviceOffering.getCpu() * serviceOffering.getSpeed(), hostCpuMap); + break; + case "memory": + pair = new Pair<>(serviceOffering.getRamSize() * 1024L * 1024L, hostMemoryMap); + break; + default: + throw new ConfigurationException( + String.format("Invalid metric: %s for cluster: %d", metric, clusterId)); + } + return pair; + } + + private Double getMetricValuePostMigration(Long clusterId, Ternary metrics, long vmMetric, + long hostId, long destHostId, long vmHostId) { + long used = metrics.first(); + long actualTotal = metrics.third() - metrics.second(); + long free = actualTotal - metrics.first(); + + if (hostId == destHostId) { + used += vmMetric; + free -= vmMetric; + } else if (hostId == vmHostId) { + used -= vmMetric; + free += vmMetric; + } + return getMetricValue(clusterId, used, free, actualTotal, null); + } + + private static Double getImbalance(List metricList) { + Double clusterMeanMetric = getClusterMeanMetric(metricList); + Double clusterStandardDeviation = getClusterStandardDeviation(metricList, clusterMeanMetric); + return clusterStandardDeviation / clusterMeanMetric; + } + + static String getClusterDrsMetric(long clusterId) { + return ClusterDrsMetric.valueIn(clusterId); + } + + static Double getMetricValue(long clusterId, long used, long free, long total, Float skipThreshold) { + boolean useRatio = getDrsMetricUseRatio(clusterId); + switch (getDrsMetricType(clusterId)) { + case "free": + if (skipThreshold != null && free < skipThreshold * total) return null; + if (useRatio) { + return (double) free / total; + } else { + return (double) free; + } + case "used": + if (skipThreshold != null && used > skipThreshold * total) return null; + if (useRatio) { + return (double) used / total; + } else { + return (double) used; + } + } + 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 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((∑∣mi−mavg∣^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 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); + } + + static String getDrsMetricType(long clusterId) { + return ClusterDrsMetricType.valueIn(clusterId); + } + + /** + * The cluster imbalance is defined as the percentage deviation from the mean + * for a configured metric of the cluster. The standard deviation is used as a + * mathematical tool to normalize the metric data for all the resource and the + * percentage deviation provides an easy tool to compare a cluster’s current + * state against the defined imbalance threshold. Because this is essentially a + * percentage, the value is a number between 0.0 and 1.0. + * Cluster Imbalance, Ic = σc / mavg , where σc is the standard deviation and + * mavg is the mean metric value for the cluster. + */ + static Double getClusterImbalance(Long clusterId, List> cpuList, + List> memoryList, Float skipThreshold) throws ConfigurationException { + String metric = getClusterDrsMetric(clusterId); + List list; + switch (metric) { + case "cpu": + list = getMetricList(clusterId, cpuList, skipThreshold); + break; + case "memory": + list = getMetricList(clusterId, memoryList, skipThreshold); + break; + default: + throw new ConfigurationException( + String.format("Invalid metric: %s for cluster: %d", metric, clusterId)); + } + return getImbalance(list); + } + + static List getMetricList(Long clusterId, List> hostMetricsList, + Float skipThreshold) { + List list = new ArrayList<>(); + for (Ternary ternary : hostMetricsList) { + long used = ternary.first(); + long actualTotal = ternary.third() - ternary.second(); + long free = actualTotal - ternary.first(); + Double metricValue = getMetricValue(clusterId, used, free, actualTotal, skipThreshold); + if (metricValue != null) { + list.add(metricValue); + } + } + return list; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsPlan.java b/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsPlan.java new file mode 100644 index 00000000000..bc1bea12752 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsPlan.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cloudstack.cluster; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +import java.util.Date; + +public interface ClusterDrsPlan extends Identity, InternalIdentity { + + long getClusterId(); + + Type getType(); + + Date getCreated(); + + Status getStatus(); + + String getUuid(); + + long getEventId(); + + enum Type { + AUTOMATED, MANUAL + } + + enum Status { + UNDER_REVIEW, READY, IN_PROGRESS, COMPLETED + } +} diff --git a/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsPlanMigration.java b/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsPlanMigration.java new file mode 100644 index 00000000000..755406926fd --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsPlanMigration.java @@ -0,0 +1,25 @@ +/* + * 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.cluster; + +import org.apache.cloudstack.api.InternalIdentity; + +public interface ClusterDrsPlanMigration extends InternalIdentity { +} diff --git a/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsService.java b/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsService.java new file mode 100644 index 00000000000..ba6a6464fc2 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/cluster/ClusterDrsService.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cloudstack.cluster; + +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.utils.component.Manager; +import com.cloud.utils.concurrency.Scheduler; +import org.apache.cloudstack.api.command.admin.cluster.ExecuteClusterDrsPlanCmd; +import org.apache.cloudstack.api.command.admin.cluster.GenerateClusterDrsPlanCmd; +import org.apache.cloudstack.api.command.admin.cluster.ListClusterDrsPlanCmd; +import org.apache.cloudstack.api.response.ClusterDrsPlanResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.Configurable; + +public interface ClusterDrsService extends Manager, Configurable, Scheduler { + + ConfigKey ClusterDrsPlanExpireInterval = new ConfigKey<>(Integer.class, "drs.plan.expire.interval", + ConfigKey.CATEGORY_ADVANCED, "30", "The interval in days after which the DRS events will be cleaned up.", + false, ConfigKey.Scope.Global, null, "Expire interval for old DRS plans", null, null, null); + + ConfigKey ClusterDrsEnabled = new ConfigKey<>(Boolean.class, "drs.automatic.enable", + ConfigKey.CATEGORY_ADVANCED, "false", "Enable/disable automatic DRS on a cluster.", true, + ConfigKey.Scope.Cluster, null, "Enable automatic DRS", null, null, null); + + ConfigKey ClusterDrsInterval = new ConfigKey<>(Integer.class, "drs.automatic.interval", + ConfigKey.CATEGORY_ADVANCED, "60", + "The interval in minutes after which a periodic background thread will schedule DRS for a cluster.", true, + ConfigKey.Scope.Cluster, null, "Interval for Automatic DRS ", null, null, null); + + ConfigKey ClusterDrsMaxMigrations = new ConfigKey<>(Integer.class, "drs.max.migrations", + ConfigKey.CATEGORY_ADVANCED, "50", + "Maximum number of live migrations in a DRS execution.", + true, ConfigKey.Scope.Cluster, null, "Maximum number of migrations for DRS", null, null, null); + + ConfigKey ClusterDrsAlgorithm = new ConfigKey<>(String.class, "drs.algorithm", + ConfigKey.CATEGORY_ADVANCED, "balanced", "The DRS algorithm to be executed on the cluster. Possible values are condensed, balanced.", + true, ConfigKey.Scope.Cluster, null, "DRS algorithm", null, null, + null, ConfigKey.Kind.Select, "condensed,balanced"); + + ConfigKey ClusterDrsImbalanceThreshold = new ConfigKey<>(Float.class, "drs.imbalance", + ConfigKey.CATEGORY_ADVANCED, "0.4", + "Value of imbalance allowed in the cluster. 1.0 means no imbalance is allowed and 0.0 means full imbalance is allowed", + true, ConfigKey.Scope.Cluster, null, "DRS imbalance", null, null, null); + + ConfigKey ClusterDrsMetric = new ConfigKey<>(String.class, "drs.metric", ConfigKey.CATEGORY_ADVANCED, + "memory", + "The allocated resource metric used to measure imbalance in a cluster. Possible values are memory, cpu.", + true, ConfigKey.Scope.Cluster, null, "DRS metric", null, null, null, ConfigKey.Kind.Select, + "memory,cpu"); + + ConfigKey ClusterDrsMetricType = new ConfigKey<>(String.class, "drs.metric.type", ConfigKey.CATEGORY_ADVANCED, + "used", + "The metric type used to measure imbalance in a cluster. This can completely change the imbalance value. Possible values are free, used.", + true, ConfigKey.Scope.Cluster, null, "DRS metric type", null, null, null, ConfigKey.Kind.Select, + "free,used"); + + ConfigKey ClusterDrsMetricUseRatio = new ConfigKey<>(Boolean.class, "drs.metric.use.ratio", ConfigKey.CATEGORY_ADVANCED, + "true", + "Whether to use ratio of selected metric & total. Useful when the cluster has hosts with different capacities", + true, ConfigKey.Scope.Cluster, null, "DRS metric use ratio", null, null, null, ConfigKey.Kind.Select, + "true,false"); + + ConfigKey ClusterDrsImbalanceSkipThreshold = new ConfigKey<>(Float.class, + "drs.imbalance.condensed.skip.threshold", ConfigKey.CATEGORY_ADVANCED, "0.95", + "Threshold to ignore the metric for a host while calculating the imbalance to decide " + + "whether DRS is required for a cluster.This is to avoid cases when the calculated imbalance" + + " gets skewed due to a single host having a very high/low metric value resulting in imbalance" + + " being higher than 1. If " + ClusterDrsMetricType.key() + " is 'free', set a lower value and if it is 'used' " + + "set a higher value. The value should be between 0.0 and 1.0", + true, ConfigKey.Scope.Cluster, null, "DRS imbalance skip threshold for Condensed algorithm", + null, null, null); + + + /** + * Generate a DRS plan for a cluster and save it as per the parameters + * + * @param cmd + * the GenerateClusterDrsPlanCmd object containing the command parameters + * + * @return a ClusterDrsPlanResponse object containing information regarding the migrations + */ + ClusterDrsPlanResponse generateDrsPlan(GenerateClusterDrsPlanCmd cmd); + + /** + * Executes a DRS plan for a cluster. + * + * @param cmd + * the ExecuteClusterDrsPlanCmd object containing the ID of the cluster and the map of virtual + * machines to hosts + * + * @return ClusterDrsPlanResponse response object + * + * @throws InvalidParameterValueException + * if there is already a plan in READY or IN_PROGRESS state for the + * cluster or if the + * cluster cannot be found by ID + */ + ClusterDrsPlanResponse executeDrsPlan(ExecuteClusterDrsPlanCmd cmd); + + /** + * Lists DRS plans for a cluster or a specific plan. + * + * @param cmd + * the ListClusterDrsPlanCmd object containing the ID of the cluster or the ID of the plan + * + * @return a ListResponse object containing a list of ClusterDrsPlanResponse objects and the total number of plans + * + * @throws InvalidParameterValueException + * if both clusterId and planId are specified or if the cluster cannot be + * found by ID + */ + ListResponse listDrsPlan(ListClusterDrsPlanCmd cmd); +} diff --git a/api/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManager.java b/api/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManager.java index f19b5398dd9..5bd9699b201 100644 --- a/api/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManager.java +++ b/api/src/main/java/org/apache/cloudstack/consoleproxy/ConsoleAccessManager.java @@ -20,6 +20,7 @@ import com.cloud.utils.component.Manager; import org.apache.cloudstack.api.command.user.consoleproxy.ConsoleEndpoint; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; +import java.util.Date; public interface ConsoleAccessManager extends Manager, Configurable { @@ -44,4 +45,7 @@ public interface ConsoleAccessManager extends Manager, Configurable { void removeSessions(String[] sessionUuids); void acquireSession(String sessionUuid); + + String genAccessTicket(String host, String port, String sid, String tag, String sessionUuid); + String genAccessTicket(String host, String port, String sid, String tag, Date normalizedHashTime, String sessionUuid); } diff --git a/api/src/main/java/org/apache/cloudstack/context/CallContext.java b/api/src/main/java/org/apache/cloudstack/context/CallContext.java index ecc109977eb..69376e4f6d7 100644 --- a/api/src/main/java/org/apache/cloudstack/context/CallContext.java +++ b/api/src/main/java/org/apache/cloudstack/context/CallContext.java @@ -23,8 +23,8 @@ import java.util.UUID; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.managed.threadlocal.ManagedThreadLocal; -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import com.cloud.exception.CloudAuthenticationException; import com.cloud.projects.Project; @@ -33,6 +33,7 @@ import com.cloud.user.User; import com.cloud.utils.UuidUtils; import com.cloud.utils.db.EntityManager; import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.logging.log4j.ThreadContext; /** * CallContext records information about the environment the call is made. This @@ -40,7 +41,7 @@ import com.cloud.utils.exception.CloudRuntimeException; * entry point must set the context and remove it when the thread finishes. */ public class CallContext { - private static final Logger s_logger = Logger.getLogger(CallContext.class); + protected static Logger LOGGER = LogManager.getLogger(CallContext.class); private static ManagedThreadLocal s_currentContext = new ManagedThreadLocal(); private static ManagedThreadLocal> s_currentContextStack = new ManagedThreadLocal>() { @Override @@ -178,9 +179,9 @@ public class CallContext { callingContext = new CallContext(userId, accountId, contextId); } s_currentContext.set(callingContext); - NDC.push("ctx-" + UuidUtils.first(contextId)); - if (s_logger.isTraceEnabled()) { - s_logger.trace("Registered: " + callingContext); + ThreadContext.push("ctx-" + UuidUtils.first(contextId)); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Registered: " + callingContext); } s_currentContextStack.get().push(callingContext); @@ -209,7 +210,7 @@ public class CallContext { assert context.getCallingUserId() == User.UID_SYSTEM : "You are calling a very specific method that registers a one time system context. This method is meant for background threads that does processing."; return context; } catch (Exception e) { - s_logger.error("Failed to register the system call context.", e); + LOGGER.error("Failed to register the system call context.", e); throw new CloudRuntimeException("Failed to register system call context", e); } } @@ -278,18 +279,18 @@ public class CallContext { return null; } s_currentContext.remove(); - if (s_logger.isTraceEnabled()) { - s_logger.trace("Unregistered: " + context); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Unregistered: " + context); } String contextId = context.getContextId(); String sessionIdOnStack = null; String sessionIdPushedToNDC = "ctx-" + UuidUtils.first(contextId); - while ((sessionIdOnStack = NDC.pop()) != null) { + while ((sessionIdOnStack = ThreadContext.pop()) != null) { if (sessionIdOnStack.isEmpty() || sessionIdPushedToNDC.equals(sessionIdOnStack)) { break; } - if (s_logger.isTraceEnabled()) { - s_logger.trace("Popping from NDC: " + contextId); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Popping from NDC: " + contextId); } } diff --git a/api/src/main/java/org/apache/cloudstack/context/LogContext.java b/api/src/main/java/org/apache/cloudstack/context/LogContext.java index c81d0f499cb..c367975aba3 100644 --- a/api/src/main/java/org/apache/cloudstack/context/LogContext.java +++ b/api/src/main/java/org/apache/cloudstack/context/LogContext.java @@ -20,8 +20,8 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -import org.apache.log4j.Logger; -import org.apache.log4j.MDC; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import org.apache.cloudstack.managed.threadlocal.ManagedThreadLocal; @@ -31,13 +31,14 @@ import com.cloud.user.User; import com.cloud.utils.UuidUtils; import com.cloud.utils.db.EntityManager; import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.logging.log4j.ThreadContext; /** * LogContext records information about the environment the API call is made. This * class must be always be available in all CloudStack code. */ public class LogContext { - private static final Logger s_logger = Logger.getLogger(LogContext.class); + protected static Logger LOGGER = LogManager.getLogger(LogContext.class); private static ManagedThreadLocal s_currentContext = new ManagedThreadLocal(); private String logContextId; @@ -134,9 +135,9 @@ public class LogContext { callingContext = new LogContext(userId, accountId, contextId); } s_currentContext.set(callingContext); - MDC.put("logcontextid", UuidUtils.first(contextId)); - if (s_logger.isTraceEnabled()) { - s_logger.trace("Registered for log: " + callingContext); + ThreadContext.put("logcontextid", UuidUtils.first(contextId)); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Registered for log: " + callingContext); } return callingContext; } @@ -160,7 +161,7 @@ public class LogContext { assert context.getCallingUserId() == User.UID_SYSTEM : "You are calling a very specific method that registers a one time system context. This method is meant for background threads that does processing."; return context; } catch (Exception e) { - s_logger.error("Failed to register the system log context.", e); + LOGGER.error("Failed to register the system log context.", e); throw new CloudRuntimeException("Failed to register system log context", e); } } @@ -206,11 +207,11 @@ public class LogContext { LogContext context = s_currentContext.get(); if (context != null) { s_currentContext.remove(); - if (s_logger.isTraceEnabled()) { - s_logger.trace("Unregistered: " + context); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Unregistered: " + context); } } - MDC.clear(); + ThreadContext.clearMap(); } public void setStartEventId(long startEventId) { diff --git a/api/src/main/java/org/apache/cloudstack/network/element/InternalLoadBalancerElementService.java b/api/src/main/java/org/apache/cloudstack/network/element/InternalLoadBalancerElementService.java index 76706a4cfc9..1fff54f5f8f 100644 --- a/api/src/main/java/org/apache/cloudstack/network/element/InternalLoadBalancerElementService.java +++ b/api/src/main/java/org/apache/cloudstack/network/element/InternalLoadBalancerElementService.java @@ -52,4 +52,6 @@ public interface InternalLoadBalancerElementService extends PluggableService { * @return */ List searchForInternalLoadBalancerElements(Long id, Long ntwkSvsProviderId, Boolean enabled); + + VirtualRouterProvider.Type getProviderType(); } diff --git a/api/src/main/java/org/apache/cloudstack/query/QueryService.java b/api/src/main/java/org/apache/cloudstack/query/QueryService.java index 0587294a826..c93e43d9f37 100644 --- a/api/src/main/java/org/apache/cloudstack/query/QueryService.java +++ b/api/src/main/java/org/apache/cloudstack/query/QueryService.java @@ -28,13 +28,17 @@ import org.apache.cloudstack.api.command.admin.resource.icon.ListResourceIconCmd import org.apache.cloudstack.api.command.admin.router.GetRouterHealthCheckResultsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; import org.apache.cloudstack.api.command.admin.storage.ListImageStoresCmd; +import org.apache.cloudstack.api.command.admin.storage.ListObjectStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListSecondaryStagingStoresCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.storage.ListStorageTagsCmd; +import org.apache.cloudstack.api.command.admin.storage.heuristics.ListSecondaryStorageSelectorsCmd; import org.apache.cloudstack.api.command.admin.user.ListUsersCmd; import org.apache.cloudstack.api.command.user.account.ListAccountsCmd; import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; +import org.apache.cloudstack.api.command.user.address.ListQuarantinedIpsCmd; import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupsCmd; +import org.apache.cloudstack.api.command.user.bucket.ListBucketsCmd; import org.apache.cloudstack.api.command.user.event.ListEventsCmd; import org.apache.cloudstack.api.command.user.iso.ListIsosCmd; import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd; @@ -44,8 +48,11 @@ import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd; import org.apache.cloudstack.api.command.user.project.ListProjectsCmd; import org.apache.cloudstack.api.command.user.resource.ListDetailOptionsCmd; import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd; +import org.apache.cloudstack.api.command.user.snapshot.CopySnapshotCmd; +import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd; import org.apache.cloudstack.api.command.user.tag.ListTagsCmd; import org.apache.cloudstack.api.command.user.template.ListTemplatesCmd; +import org.apache.cloudstack.api.command.admin.vm.ListAffectedVmsForStorageScopeChangeCmd; import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; import org.apache.cloudstack.api.command.user.volume.ListResourceDetailsCmd; @@ -53,6 +60,7 @@ import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd; import org.apache.cloudstack.api.command.user.zone.ListZonesCmd; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.AsyncJobResponse; +import org.apache.cloudstack.api.response.BucketResponse; import org.apache.cloudstack.api.response.DetailOptionsResponse; import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.DomainResponse; @@ -62,8 +70,10 @@ import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.HostTagResponse; import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; +import org.apache.cloudstack.api.response.IpQuarantineResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ManagementServerResponse; +import org.apache.cloudstack.api.response.ObjectStoreResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse; import org.apache.cloudstack.api.response.ProjectResponse; @@ -71,13 +81,16 @@ import org.apache.cloudstack.api.response.ResourceDetailResponse; import org.apache.cloudstack.api.response.ResourceIconResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse; +import org.apache.cloudstack.api.response.SecondaryStorageHeuristicsResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; +import org.apache.cloudstack.api.response.SnapshotResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.StorageTagResponse; import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.VirtualMachineResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.framework.config.ConfigKey; @@ -114,6 +127,9 @@ public interface QueryService { static final ConfigKey SharePublicTemplatesWithOtherDomains = new ConfigKey<>("Advanced", Boolean.class, "share.public.templates.with.other.domains", "true", "If false, templates of this domain will not show up in the list templates of other domains.", true, ConfigKey.Scope.Domain); + ConfigKey ReturnVmStatsOnVmList = new ConfigKey<>("Advanced", Boolean.class, "list.vm.default.details.stats", "true", + "Determines whether VM stats should be returned when details are not explicitly specified in listVirtualMachines API request. When false, details default to [group, nics, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp]. When true, all details are returned including 'stats'.", true, ConfigKey.Scope.Global); + ListResponse searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException; ListResponse searchForUsers(Long domainId, boolean recursive) throws PermissionDeniedException; @@ -126,6 +142,8 @@ public interface QueryService { ListResponse searchForUserVMs(ListVMsCmd cmd); + ListResponse listAffectedVmsForStorageScopeChange(ListAffectedVmsForStorageScopeChangeCmd cmd); + ListResponse searchForSecurityGroups(ListSecurityGroupsCmd cmd); ListResponse searchForRouters(ListRoutersCmd cmd); @@ -179,4 +197,16 @@ public interface QueryService { ListResponse listManagementServers(ListMgmtsCmd cmd); List listRouterHealthChecks(GetRouterHealthCheckResultsCmd cmd); + + ListResponse listSecondaryStorageSelectors(ListSecondaryStorageSelectorsCmd cmd); + + ListResponse listQuarantinedIps(ListQuarantinedIpsCmd cmd); + + ListResponse listSnapshots(ListSnapshotsCmd cmd); + + SnapshotResponse listSnapshot(CopySnapshotCmd cmd); + + ListResponse searchForObjectStores(ListObjectStoragePoolsCmd listObjectStoragePoolsCmd); + + ListResponse searchForBuckets(ListBucketsCmd listBucketsCmd); } diff --git a/api/src/main/java/org/apache/cloudstack/quota/QuotaTariff.java b/api/src/main/java/org/apache/cloudstack/quota/QuotaTariff.java new file mode 100644 index 00000000000..7de66a168f9 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/quota/QuotaTariff.java @@ -0,0 +1,25 @@ +// 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 +// 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.quota; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface QuotaTariff extends InternalIdentity, Identity { + +} diff --git a/api/src/main/java/org/apache/cloudstack/resource/ResourceCleanupService.java b/api/src/main/java/org/apache/cloudstack/resource/ResourceCleanupService.java new file mode 100644 index 00000000000..0d72edb0748 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/resource/ResourceCleanupService.java @@ -0,0 +1,74 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.resource; + +import org.apache.cloudstack.api.command.admin.resource.PurgeExpungedResourcesCmd; +import org.apache.cloudstack.framework.config.ConfigKey; + +import com.cloud.vm.VirtualMachine; + +public interface ResourceCleanupService { + int MINIMUM_EXPUNGED_RESOURCE_PURGE_JOB_DELAY_IN_SECONDS = 3 * 60; + ConfigKey ExpungedResourcePurgeEnabled = new ConfigKey<>("Advanced", Boolean.class, + "expunged.resources.purge.enabled", "false", + "Whether to run a background task to purge the DB records of the expunged resources", + false, ConfigKey.Scope.Global); + ConfigKey ExpungedResourcePurgeResources = new ConfigKey<>("Advanced", String.class, + "expunged.resources.purge.resources", "", + "A comma-separated list of resource types that will be considered by the background task " + + "to purge the DB records of the expunged resources. Currently only VirtualMachine is supported. " + + "An empty value will result in considering all resource types for purging", + false, ConfigKey.Scope.Global); + ConfigKey ExpungedResourcesPurgeInterval = new ConfigKey<>("Advanced", Integer.class, + "expunged.resources.purge.interval", "86400", + "Interval (in seconds) for the background task to purge the DB records of the expunged resources", + false); + ConfigKey ExpungedResourcesPurgeDelay = new ConfigKey<>("Advanced", Integer.class, + "expunged.resources.purge.delay", "300", + "Initial delay (in seconds) to start the background task to purge the DB records of the " + + "expunged resources task", false); + ConfigKey ExpungedResourcesPurgeBatchSize = new ConfigKey<>("Advanced", Integer.class, + "expunged.resources.purge.batch.size", "50", + "Batch size to be used during purging of the DB records of the expunged resources", + true); + ConfigKey ExpungedResourcesPurgeStartTime = new ConfigKey<>("Advanced", String.class, + "expunged.resources.purge.start.time", "", + "Start time to be used by the background task to purge the DB records of the expunged " + + "resources. Use format \"yyyy-MM-dd\" or \"yyyy-MM-dd HH:mm:ss\"", true); + ConfigKey ExpungedResourcesPurgeKeepPastDays = new ConfigKey<>("Advanced", Integer.class, + "expunged.resources.purge.keep.past.days", "30", + "The number of days in the past from the execution time of the background task to purge " + + "the DB records of the expunged resources for which the expunged resources must not be purged. " + + "To enable purging DB records of the expunged resource till the execution of the background " + + "task, set the value to zero.", true); + ConfigKey ExpungedResourcePurgeJobDelay = new ConfigKey<>("Advanced", Integer.class, + "expunged.resource.purge.job.delay", + String.valueOf(MINIMUM_EXPUNGED_RESOURCE_PURGE_JOB_DELAY_IN_SECONDS), + String.format("Delay (in seconds) to execute the purging of the DB records of an expunged resource " + + "initiated by the configuration in the offering. Minimum value should be %d seconds " + + "and if a lower value is set then the minimum value will be used", + MINIMUM_EXPUNGED_RESOURCE_PURGE_JOB_DELAY_IN_SECONDS), + true); + + enum ResourceType { + VirtualMachine + } + + long purgeExpungedResources(PurgeExpungedResourcesCmd cmd); + void purgeExpungedVmResourcesLaterIfNeeded(VirtualMachine vm); +} diff --git a/api/src/main/java/org/apache/cloudstack/secstorage/heuristics/Heuristic.java b/api/src/main/java/org/apache/cloudstack/secstorage/heuristics/Heuristic.java new file mode 100644 index 00000000000..2a0b8d6ea24 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/secstorage/heuristics/Heuristic.java @@ -0,0 +1,40 @@ +// 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.secstorage.heuristics; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +import java.util.Date; + +public interface Heuristic extends InternalIdentity, Identity { + + String getName(); + + String getDescription(); + + Long getZoneId(); + + String getType(); + + String getHeuristicRule(); + + Date getCreated(); + + Date getRemoved(); + +} diff --git a/api/src/main/java/org/apache/cloudstack/secstorage/heuristics/HeuristicType.java b/api/src/main/java/org/apache/cloudstack/secstorage/heuristics/HeuristicType.java new file mode 100644 index 00000000000..f23e4b0b633 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/secstorage/heuristics/HeuristicType.java @@ -0,0 +1,25 @@ +// 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.secstorage.heuristics; + +/** + * The type of the heuristic used in the allocation process of secondary storage resources. + * Valid options are: {@link #ISO}, {@link #SNAPSHOT}, {@link #TEMPLATE} and {@link #VOLUME} + */ +public enum HeuristicType { + ISO, SNAPSHOT, TEMPLATE, VOLUME +} diff --git a/api/src/main/java/org/apache/cloudstack/storage/ImageStoreObjectDownload.java b/api/src/main/java/org/apache/cloudstack/storage/ImageStoreObjectDownload.java new file mode 100644 index 00000000000..02bce11dfa4 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/storage/ImageStoreObjectDownload.java @@ -0,0 +1,34 @@ +// 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.storage; + +import org.apache.cloudstack.api.InternalIdentity; + +import java.util.Date; + +public interface ImageStoreObjectDownload extends InternalIdentity { + + long getId(); + + Long getStoreId(); + + String getPath(); + + String getDownloadUrl(); + + Date getCreated(); +} diff --git a/api/src/main/java/org/apache/cloudstack/storage/ImageStoreService.java b/api/src/main/java/org/apache/cloudstack/storage/ImageStoreService.java index b8f14ad2bfa..9dd54dc4336 100644 --- a/api/src/main/java/org/apache/cloudstack/storage/ImageStoreService.java +++ b/api/src/main/java/org/apache/cloudstack/storage/ImageStoreService.java @@ -17,6 +17,7 @@ package org.apache.cloudstack.storage; +import org.apache.cloudstack.api.command.admin.storage.MigrateResourcesToAnotherSecondaryStorageCmd; import org.apache.cloudstack.api.command.admin.storage.MigrateSecondaryStorageDataCmd; import org.apache.cloudstack.api.response.MigrationResponse; @@ -26,4 +27,5 @@ public interface ImageStoreService { BALANCE, COMPLETE } MigrationResponse migrateData(MigrateSecondaryStorageDataCmd cmd); + MigrationResponse migrateResources(MigrateResourcesToAnotherSecondaryStorageCmd migrateResourcesToAnotherSecondaryStorageCmd); } diff --git a/api/src/main/java/org/apache/cloudstack/storage/browser/DataStoreObjectResponse.java b/api/src/main/java/org/apache/cloudstack/storage/browser/DataStoreObjectResponse.java new file mode 100644 index 00000000000..cac5cc91b03 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/storage/browser/DataStoreObjectResponse.java @@ -0,0 +1,120 @@ +// 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.storage.browser; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import java.util.Date; + +public class DataStoreObjectResponse extends BaseResponse { + + @SerializedName(ApiConstants.NAME) + @Param(description = "Name of the data store object.") + private String name; + + @SerializedName("isdirectory") + @Param(description = "Is it a directory.") + private boolean isDirectory; + + @SerializedName(ApiConstants.SIZE) + @Param(description = "Size is in Bytes.") + private long size; + + @SerializedName(ApiConstants.TEMPLATE_ID) + @Param(description = "Template ID associated with the data store object.") + private String templateId; + + @SerializedName(ApiConstants.FORMAT) + @Param(description = "Format of template associated with the data store object.") + private String format; + + @SerializedName(ApiConstants.SNAPSHOT_ID) + @Param(description = "Snapshot ID associated with the data store object.") + private String snapshotId; + + @SerializedName(ApiConstants.VOLUME_ID) + @Param(description = "Volume ID associated with the data store object.") + private String volumeId; + + @SerializedName(ApiConstants.LAST_UPDATED) + @Param(description = "Last modified date of the file/directory.") + private Date lastUpdated; + + public DataStoreObjectResponse(String name, boolean isDirectory, long size, Date lastUpdated) { + this.name = name; + this.isDirectory = isDirectory; + this.size = size; + this.lastUpdated = lastUpdated; + this.setObjectName("datastoreobject"); + } + + public DataStoreObjectResponse() { + super(); + this.setObjectName("datastoreobject"); + } + + public void setTemplateId(String templateId) { + this.templateId = templateId; + } + + public void setFormat(String format) { + this.format = format; + } + + public void setSnapshotId(String snapshotId) { + this.snapshotId = snapshotId; + } + + public void setVolumeId(String volumeId) { + this.volumeId = volumeId; + } + + public String getName() { + return name; + } + + public boolean isDirectory() { + return isDirectory; + } + + public long getSize() { + return size; + } + + public String getTemplateId() { + return templateId; + } + + public String getFormat() { + return format; + } + + public String getSnapshotId() { + return snapshotId; + } + + public String getVolumeId() { + return volumeId; + } + + public Date getLastUpdated() { + return lastUpdated; + } +} diff --git a/api/src/main/java/org/apache/cloudstack/storage/browser/StorageBrowser.java b/api/src/main/java/org/apache/cloudstack/storage/browser/StorageBrowser.java new file mode 100644 index 00000000000..b9fe5b07fec --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/storage/browser/StorageBrowser.java @@ -0,0 +1,35 @@ +/* + * 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.storage.browser; + +import com.cloud.utils.component.PluggableService; +import org.apache.cloudstack.api.command.admin.storage.DownloadImageStoreObjectCmd; +import org.apache.cloudstack.api.command.admin.storage.ListImageStoreObjectsCmd; +import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolObjectsCmd; +import org.apache.cloudstack.api.response.ExtractResponse; +import org.apache.cloudstack.api.response.ListResponse; + +public interface StorageBrowser extends PluggableService { + ListResponse listImageStoreObjects(ListImageStoreObjectsCmd cmd); + + ListResponse listPrimaryStoreObjects(ListStoragePoolObjectsCmd cmd); + + ExtractResponse downloadImageStoreObject(DownloadImageStoreObjectCmd cmd); +} diff --git a/api/src/main/java/org/apache/cloudstack/storage/object/Bucket.java b/api/src/main/java/org/apache/cloudstack/storage/object/Bucket.java new file mode 100644 index 00000000000..c821dbac589 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/storage/object/Bucket.java @@ -0,0 +1,64 @@ +// 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.storage.object; + +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +import java.util.Date; + +public interface Bucket extends ControlledEntity, Identity, InternalIdentity { + + long getObjectStoreId(); + + Date getCreated(); + + State getState(); + + void setName(String name); + + Long getSize(); + + Integer getQuota(); + + boolean isVersioning(); + + boolean isEncryption(); + + boolean isObjectLock(); + + String getPolicy(); + + String getBucketURL(); + + String getAccessKey(); + + String getSecretKey(); + + public enum State { + Allocated, Created, Destroyed; + @Override + public String toString() { + return this.name(); + } + + public boolean equals(String status) { + return this.toString().equalsIgnoreCase(status); + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/storage/object/BucketApiService.java b/api/src/main/java/org/apache/cloudstack/storage/object/BucketApiService.java new file mode 100644 index 00000000000..7e1361d1e71 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/storage/object/BucketApiService.java @@ -0,0 +1,54 @@ +/* + * 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.storage.object; + +import com.cloud.exception.ResourceAllocationException; +import com.cloud.user.Account; +import org.apache.cloudstack.api.command.user.bucket.CreateBucketCmd; +import org.apache.cloudstack.api.command.user.bucket.UpdateBucketCmd; + +public interface BucketApiService { + + + /** + * Creates the database object for a Bucket based on the given criteria + * + * @param cmd + * the API command wrapping the criteria (account/domainId [admin only], zone, diskOffering, snapshot, + * name) + * @return the Bucket object + */ + Bucket allocBucket(CreateBucketCmd cmd) throws ResourceAllocationException; + + /** + * Creates the Bucket based on the given criteria + * + * @param cmd + * the API command wrapping the criteria (account/domainId [admin only], zone, diskOffering, snapshot, + * name) + * @return the Bucket object + */ + Bucket createBucket(CreateBucketCmd cmd); + + boolean deleteBucket(long bucketId, Account caller); + + boolean updateBucket(UpdateBucketCmd cmd, Account caller); + + void getBucketUsage(); +} diff --git a/api/src/main/java/org/apache/cloudstack/storage/object/ObjectStore.java b/api/src/main/java/org/apache/cloudstack/storage/object/ObjectStore.java new file mode 100644 index 00000000000..47741fc67f4 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/storage/object/ObjectStore.java @@ -0,0 +1,40 @@ +// 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.storage.object; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface ObjectStore extends Identity, InternalIdentity { + + /** + * @return name of the object store. + */ + String getName(); + + /** + * @return object store provider name + */ + String getProviderName(); + + /** + * + * @return uri + */ + String getUrl(); + +} diff --git a/api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateManager.java b/api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateManager.java new file mode 100644 index 00000000000..6571346ad65 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateManager.java @@ -0,0 +1,52 @@ +// 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.storage.template; + +import com.cloud.dc.DataCenter; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.security.SecurityGroup; +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.user.Account; +import com.cloud.uservm.UserVm; +import org.apache.cloudstack.api.command.user.template.RegisterVnfTemplateCmd; +import org.apache.cloudstack.api.command.user.template.UpdateVnfTemplateCmd; +import org.apache.cloudstack.api.command.user.vm.DeployVnfApplianceCmd; +import org.apache.cloudstack.framework.config.ConfigKey; +import java.util.List; + +public interface VnfTemplateManager { + + ConfigKey VnfTemplateAndApplianceEnabled = new ConfigKey("Advanced", Boolean.class, + "vnf.template.appliance.enabled", + "true", + "Indicates whether the creation of VNF templates and VNF appliances is enabled or not.", + false); + + void persistVnfTemplate(long templateId, RegisterVnfTemplateCmd cmd); + + void updateVnfTemplate(long templateId, UpdateVnfTemplateCmd cmd); + + void validateVnfApplianceNics(VirtualMachineTemplate template, List networkIds); + + SecurityGroup createSecurityGroupForVnfAppliance(DataCenter zone, VirtualMachineTemplate template, Account owner, DeployVnfApplianceCmd cmd); + + void createIsolatedNetworkRulesForVnfAppliance(DataCenter zone, VirtualMachineTemplate template, Account owner, + UserVm vm, DeployVnfApplianceCmd cmd) + throws InsufficientAddressCapacityException, ResourceAllocationException, ResourceUnavailableException; +} diff --git a/api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateUtils.java b/api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateUtils.java new file mode 100644 index 00000000000..e997a50cec0 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateUtils.java @@ -0,0 +1,152 @@ +// 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.storage.template; + +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.VNF; +import com.cloud.storage.Storage; +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.utils.net.NetUtils; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.command.user.template.DeleteVnfTemplateCmd; +import org.apache.cloudstack.api.command.user.template.RegisterVnfTemplateCmd; +import org.apache.cloudstack.api.command.user.template.UpdateVnfTemplateCmd; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.EnumUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class VnfTemplateUtils { + private VnfTemplateUtils() { + } + + public static List getVnfNicsList(Map vnfNics) { + List nicsList = new ArrayList<>(); + if (MapUtils.isNotEmpty(vnfNics)) { + Collection nicsCollection = vnfNics.values(); + Iterator iter = nicsCollection.iterator(); + while (iter.hasNext()) { + HashMap nicDetails = (HashMap)iter.next(); + String deviceIdString = nicDetails.get("deviceid"); + String name = nicDetails.get("name"); + String requiredString = nicDetails.get("required"); + String managementString = nicDetails.get("management"); + String description = nicDetails.get("description"); + Integer deviceId = null; + if (StringUtils.isAnyBlank(name, deviceIdString)) { + throw new InvalidParameterValueException("VNF nic name and deviceid cannot be null"); + } + try { + deviceId = Integer.parseInt(deviceIdString); + } catch (NumberFormatException e) { + throw new InvalidParameterValueException("Unable to parse VNF nic deviceId to Integer: " + deviceId); + } + boolean required = StringUtils.isBlank(requiredString) || Boolean.parseBoolean(requiredString); + boolean management = StringUtils.isBlank(managementString) || Boolean.parseBoolean(managementString); + nicsList.add(new VNF.VnfNic(deviceId, name, required, management, description)); + } + Collections.sort(nicsList, Comparator.comparing(VNF.VnfNic::getDeviceId)); + } + return nicsList; + } + + public static void validateApiCommandParams(Map vnfDetails, List vnfNics, String templateType) { + if (templateType != null && !Storage.TemplateType.VNF.name().equals(templateType)) { + throw new InvalidParameterValueException("The template type must be VNF for VNF templates."); + } + + if (vnfDetails != null) { + for (String vnfDetail : vnfDetails.keySet()) { + if (!EnumUtils.isValidEnumIgnoreCase(VNF.VnfDetail.class, vnfDetail) && + !EnumUtils.isValidEnumIgnoreCase(VNF.AccessDetail.class, vnfDetail)) { + throw new InvalidParameterValueException(String.format("Invalid VNF detail found: %s. Valid values are %s and %s", vnfDetail, + Arrays.stream(VNF.AccessDetail.values()).map(method -> method.toString()).collect(Collectors.joining(", ")), + Arrays.stream(VNF.VnfDetail.values()).map(method -> method.toString()).collect(Collectors.joining(", ")))); + } + if (vnfDetails.get(vnfDetail) == null) { + throw new InvalidParameterValueException("Empty value found for VNF detail: " + vnfDetail); + } + if (VNF.AccessDetail.ACCESS_METHODS.name().equalsIgnoreCase(vnfDetail)) { + String[] accessMethods = vnfDetails.get(vnfDetail).split(","); + for (String accessMethod : accessMethods) { + if (VNF.AccessMethod.fromValue(accessMethod.trim()) == null) { + throw new InvalidParameterValueException(String.format("Invalid VNF access method found: %s. Valid values are %s", accessMethod, + Arrays.stream(VNF.AccessMethod.values()).map(method -> method.toString()).sorted().collect(Collectors.joining(", ")))); + } + } + } + } + } + + validateVnfNics(vnfNics); + } + + public static void validateVnfNics(List nicsList) { + long deviceId = 0L; + boolean required = true; + for (VNF.VnfNic nic : nicsList) { + if (nic.getDeviceId() != deviceId) { + throw new InvalidParameterValueException(String.format("deviceid must be consecutive and start from 0. Nic deviceid should be %s but actual is %s.", deviceId, nic.getDeviceId())); + } + if (!required && nic.isRequired()) { + throw new InvalidParameterValueException(String.format("required cannot be true if a preceding nic is optional. Nic with deviceid %s should be required but actual is optional.", deviceId)); + } + deviceId ++; + required = nic.isRequired(); + } + } + + public static void validateApiCommandParams(BaseCmd cmd, VirtualMachineTemplate template) { + if (cmd instanceof RegisterVnfTemplateCmd) { + RegisterVnfTemplateCmd registerCmd = (RegisterVnfTemplateCmd) cmd; + validateApiCommandParams(registerCmd.getVnfDetails(), registerCmd.getVnfNics(), registerCmd.getTemplateType()); + } else if (cmd instanceof UpdateVnfTemplateCmd) { + UpdateVnfTemplateCmd updateCmd = (UpdateVnfTemplateCmd) cmd; + if (!Storage.TemplateType.VNF.equals(template.getTemplateType())) { + throw new InvalidParameterValueException(String.format("Cannot update as template %s is not a VNF template. The template type is %s.", updateCmd.getId(), template.getTemplateType())); + } + validateApiCommandParams(updateCmd.getVnfDetails(), updateCmd.getVnfNics(), updateCmd.getTemplateType()); + } else if (cmd instanceof DeleteVnfTemplateCmd) { + if (!Storage.TemplateType.VNF.equals(template.getTemplateType())) { + DeleteVnfTemplateCmd deleteCmd = (DeleteVnfTemplateCmd) cmd; + throw new InvalidParameterValueException(String.format("Cannot delete as Template %s is not a VNF template. The template type is %s.", deleteCmd.getId(), template.getTemplateType())); + } + } + } + + public static void validateVnfCidrList(List cidrList) { + if (CollectionUtils.isEmpty(cidrList)) { + return; + } + for (String cidr : cidrList) { + if (!NetUtils.isValidIp4Cidr(cidr)) { + throw new InvalidParameterValueException(String.format("Invalid cidr for VNF appliance: %s", cidr)); + } + } + } +} diff --git a/api/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageService.java b/api/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageService.java new file mode 100644 index 00000000000..5f69f3e46e7 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageService.java @@ -0,0 +1,46 @@ +// 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.storage.volume; + +import com.cloud.hypervisor.Hypervisor; +import com.cloud.storage.Storage; +import com.cloud.utils.component.PluggableService; +import org.apache.cloudstack.api.command.admin.volume.ListVolumesForImportCmd; +import org.apache.cloudstack.api.command.admin.volume.ImportVolumeCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.VolumeForImportResponse; +import org.apache.cloudstack.api.response.VolumeResponse; + +import java.util.Arrays; +import java.util.List; + +public interface VolumeImportUnmanageService extends PluggableService { + + List SUPPORTED_HYPERVISORS = + Arrays.asList(Hypervisor.HypervisorType.KVM, Hypervisor.HypervisorType.VMware); + + List SUPPORTED_STORAGE_POOL_TYPES_FOR_KVM = Arrays.asList(Storage.StoragePoolType.NetworkFilesystem, + Storage.StoragePoolType.Filesystem, Storage.StoragePoolType.RBD); + + ListResponse listVolumesForImport(ListVolumesForImportCmd cmd); + + VolumeResponse importVolume(ImportVolumeCmd cmd); + + boolean unmanageVolume(long volumeId); + +} diff --git a/api/src/main/java/org/apache/cloudstack/storage/volume/VolumeOnStorageTO.java b/api/src/main/java/org/apache/cloudstack/storage/volume/VolumeOnStorageTO.java new file mode 100644 index 00000000000..1a8fd6ee273 --- /dev/null +++ b/api/src/main/java/org/apache/cloudstack/storage/volume/VolumeOnStorageTO.java @@ -0,0 +1,130 @@ +// 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.storage.volume; + +import com.cloud.hypervisor.Hypervisor; + +import java.util.HashMap; +import java.util.Map; + +public class VolumeOnStorageTO { + Hypervisor.HypervisorType hypervisorType; + private String path; + private String fullPath; + + private String name; + + private String format; + private long size; + private long virtualSize; + private String qemuEncryptFormat; + private Map details = new HashMap<>(); + + public enum Detail { + BACKING_FILE, BACKING_FILE_FORMAT, CLUSTER_SIZE, FILE_FORMAT, IS_LOCKED, IS_ENCRYPTED + } + + public VolumeOnStorageTO() { + } + + public VolumeOnStorageTO(Hypervisor.HypervisorType hypervisorType, String path, String name, String fullPath, String format, long size, long virtualSize) { + this.hypervisorType = hypervisorType; + this.path = path; + this.name = name; + this.fullPath = fullPath; + this.format = format; + this.size = size; + this.virtualSize = virtualSize; + } + + public Hypervisor.HypervisorType getHypervisorType() { + return hypervisorType; + } + + public void setHypervisorType(Hypervisor.HypervisorType hypervisorType) { + this.hypervisorType = hypervisorType; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getFullPath() { + return fullPath; + } + + public void setFullPath(String fullPath) { + this.fullPath = fullPath; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public long getVirtualSize() { + return virtualSize; + } + + public void setVirtualSize(long virtualSize) { + this.virtualSize = virtualSize; + } + + public String getQemuEncryptFormat() { + return qemuEncryptFormat; + } + + public void setQemuEncryptFormat(String qemuEncryptFormat) { + this.qemuEncryptFormat = qemuEncryptFormat; + } + + public Map getDetails() { + return details; + } + + public void setDetails(Map details) { + this.details = details; + } + + public void addDetail(Detail detail, String value) { + details.put(detail, value); + } +} diff --git a/api/src/main/java/org/apache/cloudstack/usage/UsageTypes.java b/api/src/main/java/org/apache/cloudstack/usage/UsageTypes.java index 48cff3076fd..32ae34056ec 100644 --- a/api/src/main/java/org/apache/cloudstack/usage/UsageTypes.java +++ b/api/src/main/java/org/apache/cloudstack/usage/UsageTypes.java @@ -45,6 +45,9 @@ public class UsageTypes { public static final int VOLUME_SECONDARY = 26; public static final int VM_SNAPSHOT_ON_PRIMARY = 27; public static final int BACKUP = 28; + public static final int BUCKET = 29; + public static final int NETWORK = 30; + public static final int VPC = 31; public static List listUsageTypes() { List responseList = new ArrayList(); @@ -70,6 +73,9 @@ public class UsageTypes { responseList.add(new UsageTypeResponse(VOLUME_SECONDARY, "Volume on secondary storage usage")); responseList.add(new UsageTypeResponse(VM_SNAPSHOT_ON_PRIMARY, "VM Snapshot on primary storage usage")); responseList.add(new UsageTypeResponse(BACKUP, "Backup storage usage")); + responseList.add(new UsageTypeResponse(BUCKET, "Bucket storage usage")); + responseList.add(new UsageTypeResponse(NETWORK, "Network usage")); + responseList.add(new UsageTypeResponse(VPC, "VPC usage")); return responseList; } } diff --git a/api/src/main/java/org/apache/cloudstack/user/ResourceReservation.java b/api/src/main/java/org/apache/cloudstack/user/ResourceReservation.java index 170193570cf..d49120d4491 100644 --- a/api/src/main/java/org/apache/cloudstack/user/ResourceReservation.java +++ b/api/src/main/java/org/apache/cloudstack/user/ResourceReservation.java @@ -18,9 +18,12 @@ // package org.apache.cloudstack.user; -import com.cloud.configuration.Resource; import org.apache.cloudstack.api.InternalIdentity; +import com.cloud.configuration.Resource; + +import java.util.Date; + /** * an interface defining an {code}AutoClosable{code} reservation object */ @@ -33,5 +36,11 @@ ResourceReservation extends InternalIdentity { Resource.ResourceType getResourceType(); + Long getResourceId(); + + String getTag(); + Long getReservedAmount(); + + Date getCreated(); } diff --git a/api/src/main/java/org/apache/cloudstack/userdata/UserDataManager.java b/api/src/main/java/org/apache/cloudstack/userdata/UserDataManager.java index 4dfcd0a7de1..b4bede24890 100644 --- a/api/src/main/java/org/apache/cloudstack/userdata/UserDataManager.java +++ b/api/src/main/java/org/apache/cloudstack/userdata/UserDataManager.java @@ -17,11 +17,16 @@ package org.apache.cloudstack.userdata; import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; import com.cloud.utils.component.Manager; public interface UserDataManager extends Manager, Configurable { + String VM_USERDATA_MAX_LENGTH_STRING = "vm.userdata.max.length"; + ConfigKey VM_USERDATA_MAX_LENGTH = new ConfigKey<>("Advanced", Integer.class, VM_USERDATA_MAX_LENGTH_STRING, "32768", + "Max length of vm userdata after base64 encoding. Default is 32768 and maximum is 1048576", true); + String concatenateUserData(String userdata1, String userdata2, String userdataProvider); String validateUserData(String userData, BaseCmd.HTTPMethod httpmethod); } diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java index 95675f2bf34..5697a040b81 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java @@ -17,6 +17,8 @@ package org.apache.cloudstack.vm; +import static com.cloud.utils.NumbersUtil.toHumanReadableSize; + import java.util.List; public class UnmanagedInstanceTO { @@ -33,6 +35,8 @@ public class UnmanagedInstanceTO { private PowerState powerState; + private PowerState cloneSourcePowerState; + private Integer cpuCores; private Integer cpuCoresPerSocket; @@ -45,10 +49,16 @@ public class UnmanagedInstanceTO { private String operatingSystem; + private String clusterName; + + private String hostName; + private List disks; private List nics; + private String vncPassword; + public String getName() { return name; } @@ -73,6 +83,14 @@ public class UnmanagedInstanceTO { this.powerState = powerState; } + public PowerState getCloneSourcePowerState() { + return cloneSourcePowerState; + } + + public void setCloneSourcePowerState(PowerState cloneSourcePowerState) { + this.cloneSourcePowerState = cloneSourcePowerState; + } + public Integer getCpuCores() { return cpuCores; } @@ -121,6 +139,22 @@ public class UnmanagedInstanceTO { this.operatingSystem = operatingSystem; } + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } + public List getDisks() { return disks; } @@ -137,6 +171,14 @@ public class UnmanagedInstanceTO { this.nics = nics; } + public String getVncPassword() { + return vncPassword; + } + + public void setVncPassword(String vncPassword) { + this.vncPassword = vncPassword; + } + public static class Disk { private String diskId; @@ -162,6 +204,8 @@ public class UnmanagedInstanceTO { private String datastorePath; + private int datastorePort; + private String datastoreType; public String getDiskId() { @@ -267,6 +311,24 @@ public class UnmanagedInstanceTO { public void setDatastoreType(String datastoreType) { this.datastoreType = datastoreType; } + + public void setDatastorePort(int datastorePort) { + this.datastorePort = datastorePort; + } + + public int getDatastorePort() { + return datastorePort; + } + + @Override + public String toString() { + return "Disk {" + + "diskId='" + diskId + '\'' + + ", capacity=" + toHumanReadableSize(capacity) + + ", controller='" + controller + '\'' + + ", controllerUnit=" + controllerUnit + + "}"; + } } public static class Nic { @@ -359,5 +421,14 @@ public class UnmanagedInstanceTO { public void setPciSlot(String pciSlot) { this.pciSlot = pciSlot; } + + @Override + public String toString() { + return "Nic{" + + "nicId='" + nicId + '\'' + + ", adapterType='" + adapterType + '\'' + + ", macAddress='" + macAddress + '\'' + + "}"; + } } } diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManager.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManager.java index 2876a0127be..b6233b9c270 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManager.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManager.java @@ -17,13 +17,60 @@ package org.apache.cloudstack.vm; +import com.cloud.hypervisor.Hypervisor; import com.cloud.utils.component.PluggableService; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; +import static com.cloud.hypervisor.Hypervisor.HypervisorType.KVM; +import static com.cloud.hypervisor.Hypervisor.HypervisorType.VMware; public interface UnmanagedVMsManager extends VmImportService, UnmanageVMService, PluggableService, Configurable { ConfigKey UnmanageVMPreserveNic = new ConfigKey<>("Advanced", Boolean.class, "unmanage.vm.preserve.nics", "false", "If set to true, do not remove VM nics (and its MAC addresses) when unmanaging a VM, leaving them allocated but not reserved. " + "If set to false, nics are removed and MAC addresses can be reassigned", true, ConfigKey.Scope.Zone); + + ConfigKey RemoteKvmInstanceDisksCopyTimeout = new ConfigKey<>(Integer.class, + "remote.kvm.instance.disks.copy.timeout", + "Advanced", + "30", + "Timeout (in mins) to prepare and copy the disks of remote KVM instance while importing the instance from an external host", + true, + ConfigKey.Scope.Global, + null); + + ConfigKey ConvertVmwareInstanceToKvmTimeout = new ConfigKey<>(Integer.class, + "convert.vmware.instance.to.kvm.timeout", + "Advanced", + "3", + "Timeout (in hours) for the instance conversion process from VMware through the virt-v2v binary on a KVM host", + true, + ConfigKey.Scope.Global, + null); + + ConfigKey ThreadsOnMSToImportVMwareVMFiles = new ConfigKey<>(Integer.class, + "threads.on.ms.to.import.vmware.vm.files", + "Advanced", + "0", + "Threads to use on the management server when importing VM files from VMWare." + + " -1 or 1 disables threads, 0 uses a thread per VM disk (disabled for single disk) and >1 for manual thread configuration." + + " Max number is 10, Default is 0.", + true, + ConfigKey.Scope.Global, + null); + + ConfigKey ThreadsOnKVMHostToImportVMwareVMFiles = new ConfigKey<>(Integer.class, + "threads.on.kvm.host.to.import.vmware.vm.files", + "Advanced", + "0", + "Threads to use on the KVM host (by the ovftool, if the version is 4.4.0+) when importing VM files from VMWare." + + " -1 or 1 disables threads, 0 uses a thread per VM disk (disabled for single disk) and >1 for manual thread configuration." + + " Max number is 10, Default is 0.", + true, + ConfigKey.Scope.Global, + null); + + static boolean isSupported(Hypervisor.HypervisorType hypervisorType) { + return hypervisorType == VMware || hypervisorType == KVM; + } } diff --git a/api/src/main/java/org/apache/cloudstack/vm/VmImportService.java b/api/src/main/java/org/apache/cloudstack/vm/VmImportService.java index cce28474541..04ef248fb8a 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/VmImportService.java +++ b/api/src/main/java/org/apache/cloudstack/vm/VmImportService.java @@ -18,12 +18,28 @@ package org.apache.cloudstack.vm; import org.apache.cloudstack.api.command.admin.vm.ImportUnmanagedInstanceCmd; +import org.apache.cloudstack.api.command.admin.vm.ImportVmCmd; import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; +import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; import org.apache.cloudstack.api.response.UserVmResponse; public interface VmImportService { + + enum ImportSource { + UNMANAGED, VMWARE, EXTERNAL, SHARED, LOCAL; + + @Override + public String toString() { + return name().toLowerCase(); + } + } + ListResponse listUnmanagedInstances(ListUnmanagedInstancesCmd cmd); UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd); + + UserVmResponse importVm(ImportVmCmd cmd); + + ListResponse listVmsForImport(ListVmsForImportCmd cmd); } diff --git a/api/src/main/resources/META-INF/cloudstack/api-config/spring-api-config-context.xml b/api/src/main/resources/META-INF/cloudstack/api-config/spring-api-config-context.xml index 5ea32464ee9..12d3c2361ac 100644 --- a/api/src/main/resources/META-INF/cloudstack/api-config/spring-api-config-context.xml +++ b/api/src/main/resources/META-INF/cloudstack/api-config/spring-api-config-context.xml @@ -28,5 +28,5 @@ > - + diff --git a/api/src/main/resources/META-INF/cloudstack/api-planner/spring-api-planner-context.xml b/api/src/main/resources/META-INF/cloudstack/api-planner/spring-api-planner-context.xml index 8523daf1d21..b614e362950 100644 --- a/api/src/main/resources/META-INF/cloudstack/api-planner/spring-api-planner-context.xml +++ b/api/src/main/resources/META-INF/cloudstack/api-planner/spring-api-planner-context.xml @@ -30,5 +30,5 @@ - + diff --git a/api/src/test/java/com/cloud/agent/api/storage/OVFHelperTest.java b/api/src/test/java/com/cloud/agent/api/storage/OVFHelperTest.java index f52d3045e40..c8f7ef3ec9b 100644 --- a/api/src/test/java/com/cloud/agent/api/storage/OVFHelperTest.java +++ b/api/src/test/java/com/cloud/agent/api/storage/OVFHelperTest.java @@ -393,6 +393,131 @@ public class OVFHelperTest { "\n" + ""; + private String eulaSectionsWithOVFprefix = + "\n" + + "\n" + + " end-user license agreement\n" + + " END USER LICENSE AGREEMENT\n" + + "\n" + + "IMPORTANT: PLEASE READ THIS END USER LICENSE AGREEMENT CAREFULLY. IT IS VERY IMPORTANT THAT YOU CHECK THAT YOU ARE PURCHASING CISCO SOFTWARE OR EQUIPMENT FROM AN APPROVED SOURCE AND THAT YOU, OR THE ENTITY YOU REPRESENT (COLLECTIVELY, THE \"CUSTOMER\") HAVE BEEN REGISTERED AS THE END USER FOR THE PURPOSES OF THIS CISCO END USER LICENSE AGREEMENT. IF YOU ARE NOT REGISTERED AS THE END USER YOU HAVE NO LICENSE TO USE THE SOFTWARE AND THE LIMITED WARRANTY IN THIS END USER LICENSE AGREEMENT DOES NOT APPLY. ASSUMING YOU HAVE PURCHASED FROM AN APPROVED SOURCE, DOWNLOADING, INSTALLING OR USING CISCO OR CISCO-SUPPLIED SOFTWARE CONSTITUTES ACCEPTANCE OF THIS AGREEMENT.\n" + + "\n" + + "CISCO SYSTEMS, INC. OR ITS AFFILIATE LICENSING THE SOFTWARE (\"CISCO\") IS WILLING TO LICENSE THIS SOFTWARE TO YOU ONLY UPON THE CONDITION THAT YOU PURCHASED THE SOFTWARE FROM AN APPROVED SOURCE AND THAT YOU ACCEPT ALL OF THE TERMS CONTAINED IN THIS END USER LICENSE AGREEMENT PLUS ANY ADDITIONAL LIMITATIONS ON THE LICENSE SET FORTH IN A SUPPLEMENTAL LICENSE AGREEMENT ACCOMPANYING THE PRODUCT, MADE AVAILABLE AT THE TIME OF YOUR ORDER, OR POSTED ON THE CISCO WEBSITE AT www.cisco.com/go/terms (COLLECTIVELY THE \"AGREEMENT\"). TO THE EXTENT OF ANY CONFLICT BETWEEN THE TERMS OF THIS END USER LICENSE AGREEMENT AND ANY SUPPLEMENTAL LICENSE AGREEMENT, THE SUPPLEMENTAL LICENSE AGREEMENT SHALL APPLY. BY DOWNLOADING, INSTALLING, OR USING THE SOFTWARE, YOU ARE REPRESENTING THAT YOU PURCHASED THE SOFTWARE FROM AN APPROVED SOURCE AND BINDING YOURSELF TO THE AGREEMENT. IF YOU DO " + + "NOT AGREE TO ALL OF THE TERMS OF THE AGREEMENT, THEN CISCO IS UNWILLING TO LICENSE THE SOFTWARE TO YOU AND (A) YOU MAY NOT DOWNLOAD, INSTALL OR USE THE SOFTWARE, AND (B) YOU MAY RETURN THE SOFTWARE (INCLUDING ANY UNOPENED CD PACKAGE AND ANY WRITTEN MATERIALS) FOR A FULL REFUND, OR, IF THE SOFTWARE AND WRITTEN MATERIALS ARE SUPPLIED AS PART OF ANOTHER PRODUCT, YOU MAY RETURN THE ENTIRE PRODUCT FOR A FULL REFUND. YOUR RIGHT TO RETURN AND REFUND EXPIRES 30 DAYS AFTER PURCHASE FROM AN APPROVED SOURCE, AND APPLIES ONLY IF YOU ARE THE ORIGINAL AND REGISTERED END USER PURCHASER. FOR THE PURPOSES OF THIS END USER LICENSE AGREEMENT, AN \"APPROVED SOURCE\" MEANS (A) CISCO; OR (B) A DISTRIBUTOR OR SYSTEMS INTEGRATOR AUTHORIZED BY CISCO TO DISTRIBUTE / SELL CISCO EQUIPMENT, SOFTWARE AND SERVICES WITHIN YOUR TERRITORY TO END " + + "USERS; OR (C) A RESELLER AUTHORIZED BY ANY SUCH DISTRIBUTOR OR SYSTEMS INTEGRATOR IN ACCORDANCE WITH THE TERMS OF THE DISTRIBUTOR'S AGREEMENT WITH CISCO TO DISTRIBUTE / SELL THE CISCO EQUIPMENT, SOFTWARE AND SERVICES WITHIN YOUR TERRITORY TO END USERS.\n" + + "\n" + + "THE FOLLOWING TERMS OF THE AGREEMENT GOVERN CUSTOMER'S USE OF THE SOFTWARE (DEFINED BELOW), EXCEPT TO THE EXTENT: (A) THERE IS A SEPARATE SIGNED CONTRACT BETWEEN CUSTOMER AND CISCO GOVERNING CUSTOMER'S USE OF THE SOFTWARE, OR (B) THE SOFTWARE INCLUDES A SEPARATE \"CLICK-ACCEPT\" LICENSE AGREEMENT OR THIRD PARTY LICENSE AGREEMENT AS PART OF THE INSTALLATION OR DOWNLOAD PROCESS GOVERNING CUSTOMER'S USE OF THE SOFTWARE. TO THE EXTENT OF A CONFLICT BETWEEN THE PROVISIONS OF THE FOREGOING DOCUMENTS, THE ORDER OF PRECEDENCE SHALL BE (1)THE SIGNED CONTRACT, (2) THE CLICK-ACCEPT AGREEMENT OR THIRD PARTY LICENSE AGREEMENT, AND (3) THE AGREEMENT. FOR PURPOSES OF THE AGREEMENT, \"SOFTWARE\" SHALL MEAN COMPUTER PROGRAMS, INCLUDING FIRMWARE AND COMPUTER PROGRAMS EMBEDDED IN CISCO EQUIPMENT, AS PROVIDED TO CUSTOMER BY AN APPROVED SOURCE, AND ANY UPGRADES, UPDATES, BUG FIXES " + + "OR MODIFIED VERSIONS THERETO (COLLECTIVELY, \"UPGRADES\"), ANY OF THE SAME WHICH HAS BEEN RELICENSED UNDER THE CISCO SOFTWARE TRANSFER AND RE-LICENSING POLICY (AS MAY BE AMENDED BY CISCO FROM TIME TO TIME) OR BACKUP COPIES OF ANY OF THE FOREGOING.\n" + + "\n" + + "License. Conditioned upon compliance with the terms and conditions of the Agreement, Cisco grants to Customer a nonexclusive and nontransferable license to use for Customer's internal business purposes the Software and the Documentation for which Customer has paid the required license fees to an Approved Source. \"Documentation\" means written information (whether contained in user or technical manuals, training materials, specifications or otherwise) pertaining to the Software and made available by an Approved Source with the Software in any manner (including on CD-Rom, or on-line). In order to use the Software, Customer may be required to input a registration number or product authorization key and register Customer's copy of the Software online at Cisco's website to obtain the necessary license key or license file.\n" + + "\n" + + "Customer's license to use the Software shall be limited to, and Customer shall not use the Software in excess of, a single hardware chassis or card or such other limitations as are set forth in the applicable Supplemental License Agreement or in the applicable purchase order which has been accepted by an Approved Source and for which Customer has paid to an Approved Source the required license fee (the \"Purchase Order\").\n" + + "\n" + + "Unless otherwise expressly provided in the Documentation or any applicable Supplemental License Agreement, Customer shall use the Software solely as embedded in, for execution on, or (where the applicable Documentation permits installation on non-Cisco equipment) for communication with Cisco equipment owned or leased by Customer and used for Customer's internal business purposes. No other licenses are granted by implication, estoppel or otherwise.\n" + + "\n" + + "For evaluation or beta copies for which Cisco does not charge a license fee, the above requirement to pay license fees does not apply.\n" + + "\n" + + "General Limitations. This is a license, not a transfer of title, to the Software and Documentation, and Cisco retains ownership of all copies of the Software and Documentation. Customer acknowledges that the Software and Documentation contain trade secrets of Cisco or its suppliers or licensors, including but not limited to the specific internal design and structure of individual programs and associated interface information. Except as otherwise expressly provided under the Agreement, Customer shall only use the Software in connection with the use of Cisco equipment purchased by the Customer from an Approved Source and Customer shall have no right, and Customer specifically agrees not to:\n" + + "\n" + + "(i) transfer, assign or sublicense its license rights to any other person or entity (other than in compliance with any Cisco relicensing/transfer policy then in force), or use the Software on Cisco equipment not purchased by the Customer from an Approved Source or on secondhand Cisco equipment, and Customer acknowledges that any attempted transfer, assignment, sublicense or use shall be void;\n" + + "\n" + + "(ii) make error corrections to or otherwise modify or adapt the Software or create derivative works based upon the Software, or permit third parties to do the same;\n" + + "\n" + + "(iii) reverse engineer or decompile, decrypt, disassemble or otherwise reduce the Software to human-readable form, except to the extent otherwise expressly permitted under applicable law notwithstanding this restriction or except to the extent that Cisco is legally required to permit such specific activity pursuant to any applicable open source license;\n" + + "\n" + + "(iv) publish any results of benchmark tests run on the Software;\n" + + "\n" + + "(v) use or permit the Software to be used to perform services for third parties, whether on a service bureau or time sharing basis or otherwise, without the express written authorization of Cisco; or\n" + + "\n" + + "(vi) disclose, provide, or otherwise make available trade secrets contained within the Software and Documentation in any form to any third party without the prior written consent of Cisco. Customer shall implement reasonable security measures to protect such trade secrets.\n" + + "\n" + + "To the extent required by applicable law, and at Customer's written request, Cisco shall provide Customer with the interface information needed to achieve interoperability between the Software and another independently created program, on payment of Cisco's applicable fee, if any. Customer shall observe strict obligations of confidentiality with respect to such information and shall use such information in compliance with any applicable terms and conditions upon which Cisco makes such information available.\n" + + "\n" + + "Software, Upgrades and Additional Copies. NOTWITHSTANDING ANY OTHER PROVISION OF THE AGREEMENT: (1) CUSTOMER HAS NO LICENSE OR RIGHT TO MAKE OR USE ANY ADDITIONAL COPIES OR UPGRADES UNLESS CUSTOMER, AT THE TIME OF MAKING OR ACQUIRING SUCH COPY OR UPGRADE, ALREADY HOLDS A VALID LICENSE TO THE ORIGINAL SOFTWARE AND HAS PAID THE APPLICABLE FEE TO AN APPROVED SOURCE FOR THE UPGRADE OR ADDITIONAL COPIES; (2) USE OF UPGRADES IS LIMITED TO CISCO EQUIPMENT SUPPLIED BY AN APPROVED SOURCE FOR WHICH CUSTOMER IS THE ORIGINAL END USER PURCHASER OR LESSEE OR OTHERWISE HOLDS A VALID LICENSE TO USE THE SOFTWARE WHICH IS BEING UPGRADED; AND (3) THE MAKING AND USE OF ADDITIONAL COPIES IS LIMITED TO NECESSARY BACKUP PURPOSES ONLY.\n" + + "\n" + + "Proprietary Notices. Customer agrees to maintain and reproduce all copyright, proprietary, and other notices on all copies, in any form, of the Software in the same form and manner that such copyright and other proprietary notices are included on the Software. Except as expressly authorized in the Agreement, Customer shall not make any copies or duplicates of any Software without the prior written permission of Cisco.\n" + + "\n" + + "Term and Termination. The Agreement and the license granted herein shall remain effective until terminated. Customer may terminate the Agreement and the license at any time by destroying all copies of Software and any Documentation. Customer's rights under the Agreement will terminate immediately without notice from Cisco if Customer fails to comply with any provision of the Agreement. Upon termination, Customer shall destroy all copies of Software and Documentation in its possession or control. All confidentiality obligations of Customer, all restrictions and limitations imposed on the Customer under the section titled \"General Limitations\" and all limitations of liability and disclaimers and restrictions of warranty shall survive termination of this Agreement. In addition, the provisions of the sections titled \"U.S. Government End User Purchasers\" and \"General Terms Applicable to the Limited Warranty Statement " + + "and End User License Agreement\" shall survive termination of the Agreement.\n" + + "\n" + + "Customer Records. Customer grants to Cisco and its independent accountants the right to examine Customer's books, records and accounts during Customer's normal business hours to verify compliance with this Agreement. In the event such audit discloses non-compliance with this Agreement, Customer shall promptly pay to Cisco the appropriate license fees, plus the reasonable cost of conducting the audit.\n" + + "\n" + + "Export, Re-Export, Transfer and Use Controls. The Software, Documentation and technology or direct products thereof (hereafter referred to as Software and Technology), supplied by Cisco under the Agreement are subject to export controls under the laws and regulations of the United States (\"U.S.\") and any other applicable countries' laws and regulations. Customer shall comply with such laws and regulations governing export, re-export, import, transfer and use of Cisco Software and Technology and will obtain all required U.S. and local authorizations, permits, or licenses. Cisco and Customer each agree to provide the other information, support documents, and assistance as may reasonably be required by the other in connection with securing authorizations or licenses. Information regarding compliance with export, re-export, transfer and use may be located at the following URL: " + + "www.cisco.com/web/about/doing_business/legal/global_export_trade/general_export/contract_compliance.html\n" + + "\n" + + "U.S. Government End User Purchasers. The Software and Documentation qualify as \"commercial items,\" as that term is defined at Federal Acquisition Regulation (\"FAR\") (48 C.F.R.) 2.101, consisting of \"commercial computer software\" and \"commercial computer software documentation\" as such terms are used in FAR 12.212. Consistent with FAR 12.212 and DoD FAR Supp. 227.7202-1 through 227.7202-4, and notwithstanding any other FAR or other contractual clause to the contrary in any agreement into which the Agreement may be incorporated, Customer may provide to Government end user or, if the Agreement is direct, Government end user will acquire, the Software and Documentation with only those rights set forth in the Agreement. Use of either the Software or Documentation or both constitutes agreement by the Government that the Software and Documentation are \"commercial computer software\" and \"commercial computer " + + "software documentation,\" and constitutes acceptance of the rights and restrictions herein.\n" + + "\n" + + "Identified Components; Additional Terms. The Software may contain or be delivered with one or more components, which may include third-party components, identified by Cisco in the Documentation, readme.txt file, third-party click-accept or elsewhere (e.g. on www.cisco.com) (the \"Identified Component(s)\") as being subject to different license agreement terms, disclaimers of warranties, limited warranties or other terms and conditions (collectively, \"Additional Terms\") than those set forth herein. You agree to the applicable Additional Terms for any such Identified Component(s).\n" + + "\n" + + "Limited Warranty\n" + + "\n" + + "Subject to the limitations and conditions set forth herein, Cisco warrants that commencing from the date of shipment to Customer (but in case of resale by an Approved Source other than Cisco, commencing not more than ninety (90) days after original shipment by Cisco), and continuing for a period of the longer of (a) ninety (90) days or (b) the warranty period (if any) expressly set forth as applicable specifically to software in the warranty card accompanying the product of which the Software is a part (the \"Product\") (if any): (a) the media on which the Software is furnished will be free of defects in materials and workmanship under normal use; and (b) the Software substantially conforms to the Documentation. The date of shipment of a Product by Cisco is set forth on the packaging material in which the Product is shipped. Except for the foregoing, the Software is provided \"AS IS\". This limited warranty extends only to the " + + "Software purchased from an Approved Source by a Customer who is the first registered end user. Customer's sole and exclusive remedy and the entire liability of Cisco and its suppliers under this limited warranty will be (i) replacement of defective media and/or (ii) at Cisco's option, repair, replacement, or refund of the purchase price of the Software, in both cases subject to the condition that any error or defect constituting a breach of this limited warranty is reported to the Approved Source supplying the Software to Customer, within the warranty period. Cisco or the Approved Source supplying the Software to Customer may, at its option, require return of the Software and/or Documentation as a condition to the remedy. In no event does Cisco warrant that the Software is error free or that Customer will be able to operate the Software without problems or interruptions. In addition, due to the continual development of new " + + "techniques for intruding upon and attacking networks, Cisco does not warrant that the Software or any equipment, system or network on which the Software is used will be free of vulnerability to intrusion or attack.\n" + + "\n" + + "Restrictions. This warranty does not apply if the Software, Product or any other equipment upon which the Software is authorized to be used (a) has been altered, except by Cisco or its authorized representative, (b) has not been installed, operated, repaired, or maintained in accordance with instructions supplied by Cisco, (c) has been subjected to abnormal physical or electrical stress, abnormal environmental conditions, misuse, negligence, or accident; or (d) is licensed for beta, evaluation, testing or demonstration purposes. The Software warranty also does not apply to (e) any temporary Software modules; (f) any Software not posted on Cisco's Software Center; (g) any Software that Cisco expressly provides on an \"AS IS\" basis on Cisco's Software Center; (h) any Software for which an Approved Source does not receive a license fee; and (i) Software supplied by any third party which is not an Approved Source.\n" + + "\n" + + "DISCLAIMER OF WARRANTY\n" + + "\n" + + "EXCEPT AS SPECIFIED IN THIS WARRANTY SECTION, ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS, AND WARRANTIES INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTY OR CONDITION OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, SATISFACTORY QUALITY, NON-INTERFERENCE, ACCURACY OF INFORMATIONAL CONTENT, OR ARISING FROM A COURSE OF DEALING, LAW, USAGE, OR TRADE PRACTICE, ARE HEREBY EXCLUDED TO THE EXTENT ALLOWED BY APPLICABLE LAW AND ARE EXPRESSLY DISCLAIMED BY CISCO, ITS SUPPLIERS AND LICENSORS. TO THE EXTENT THAT ANY OF THE SAME CANNOT BE EXCLUDED, SUCH IMPLIED CONDITION, REPRESENTATION AND/OR WARRANTY IS LIMITED IN DURATION TO THE EXPRESS WARRANTY PERIOD REFERRED TO IN THE \"LIMITED WARRANTY\" SECTION ABOVE. BECAUSE SOME STATES OR JURISDICTIONS DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED WARRANTY LASTS, THE ABOVE LIMITATION MAY NOT APPLY IN SUCH STATES. THIS WARRANTY GIVES CUSTOMER SPECIFIC LEGAL RIGHTS, " + + "AND CUSTOMER MAY ALSO HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO JURISDICTION. This disclaimer and exclusion shall apply even if the express warranty set forth above fails of its essential purpose.\n" + + "\n" + + "Disclaimer of Liabilities-Limitation of Liability. IF YOU ACQUIRED THE SOFTWARE IN THE UNITED STATES, LATIN AMERICA, CANADA, JAPAN OR THE CARIBBEAN, NOTWITHSTANDING ANYTHING ELSE IN THE AGREEMENT TO THE CONTRARY, ALL LIABILITY OF CISCO, ITS AFFILIATES, OFFICERS, DIRECTORS, EMPLOYEES, AGENTS, SUPPLIERS AND LICENSORS COLLECTIVELY, TO CUSTOMER, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF WARRANTY OR OTHERWISE, SHALL NOT EXCEED THE PRICE PAID BY CUSTOMER TO ANY APPROVED SOURCE FOR THE SOFTWARE THAT GAVE RISE TO THE CLAIM OR IF THE SOFTWARE IS PART OF ANOTHER PRODUCT, THE PRICE PAID FOR SUCH OTHER PRODUCT. THIS LIMITATION OF LIABILITY FOR SOFTWARE IS CUMULATIVE AND NOT PER INCIDENT (I.E. THE EXISTENCE OF TWO OR MORE CLAIMS WILL NOT ENLARGE THIS LIMIT).\n" + + "\n" + + "IF YOU ACQUIRED THE SOFTWARE IN EUROPE, THE MIDDLE EAST, AFRICA, ASIA OR OCEANIA, NOTWITHSTANDING ANYTHING ELSE IN THE AGREEMENT TO THE CONTRARY, ALL LIABILITY OF CISCO, ITS AFFILIATES, OFFICERS, DIRECTORS, EMPLOYEES, AGENTS, SUPPLIERS AND LICENSORS COLLECTIVELY, TO CUSTOMER, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF WARRANTY OR OTHERWISE, SHALL NOT EXCEED THE PRICE PAID BY CUSTOMER TO CISCO FOR THE SOFTWARE THAT GAVE RISE TO THE CLAIM OR IF THE SOFTWARE IS PART OF ANOTHER PRODUCT, THE PRICE PAID FOR SUCH OTHER PRODUCT. THIS LIMITATION OF LIABILITY FOR SOFTWARE IS CUMULATIVE AND NOT PER INCIDENT (I.E. THE EXISTENCE OF TWO OR MORE CLAIMS WILL NOT ENLARGE THIS LIMIT). NOTHING IN THE AGREEMENT SHALL LIMIT (I) THE LIABILITY OF CISCO, ITS AFFILIATES, OFFICERS, DIRECTORS, EMPLOYEES, AGENTS, SUPPLIERS AND LICENSORS TO CUSTOMER FOR PERSONAL INJURY OR DEATH CAUSED BY THEIR NEGLIGENCE, (II) CISCO'S LIABILITY FOR FRAUDULENT" + + " MISREPRESENTATION, OR (III) ANY LIABILITY OF CISCO WHICH CANNOT BE EXCLUDED UNDER APPLICABLE LAW.\n" + + "\n" + + "Disclaimer of Liabilities-Waiver of Consequential Damages and Other Losses. IF YOU ACQUIRED THE SOFTWARE IN THE UNITED STATES, LATIN AMERICA, THE CARIBBEAN OR CANADA, REGARDLESS OF WHETHER ANY REMEDY SET FORTH HEREIN FAILS OF ITS ESSENTIAL PURPOSE OR OTHERWISE, IN NO EVENT WILL CISCO OR ITS SUPPLIERS BE LIABLE FOR ANY LOST REVENUE, PROFIT, OR LOST OR DAMAGED DATA, BUSINESS INTERRUPTION, LOSS OF CAPITAL, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR PUNITIVE DAMAGES HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY OR WHETHER ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE OR OTHERWISE AND EVEN IF CISCO OR ITS SUPPLIERS OR LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME STATES OR JURISDICTIONS DO NOT ALLOW LIMITATION OR EXCLUSION OF CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO YOU.\n" + + "\n" + + "IF YOU ACQUIRED THE SOFTWARE IN JAPAN, EXCEPT FOR LIABILITY ARISING OUT OF OR IN CONNECTION WITH DEATH OR PERSONAL INJURY, FRAUDULENT MISREPRESENTATION, AND REGARDLESS OF WHETHER ANY REMEDY SET FORTH HEREIN FAILS OF ITS ESSENTIAL PURPOSE OR OTHERWISE, IN NO EVENT WILL CISCO, ITS AFFILIATES, OFFICERS, DIRECTORS, EMPLOYEES, AGENTS, SUPPLIERS AND LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT, OR LOST OR DAMAGED DATA, BUSINESS INTERRUPTION, LOSS OF CAPITAL, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR PUNITIVE DAMAGES HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY OR WHETHER ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE OR OTHERWISE AND EVEN IF CISCO OR ANY APPROVED SOURCE OR THEIR SUPPLIERS OR LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n" + + "\n" + + "IF YOU ACQUIRED THE SOFTWARE IN EUROPE, THE MIDDLE EAST, AFRICA, ASIA OR OCEANIA, IN NO EVENT WILL CISCO, ITS AFFILIATES, OFFICERS, DIRECTORS, EMPLOYEES, AGENTS, SUPPLIERS AND LICENSORS, BE LIABLE FOR ANY LOST REVENUE, LOST PROFIT, OR LOST OR DAMAGED DATA, BUSINESS INTERRUPTION, LOSS OF CAPITAL, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR PUNITIVE DAMAGES, HOWSOEVER ARISING, INCLUDING, WITHOUT LIMITATION, IN CONTRACT, TORT (INCLUDING NEGLIGENCE) OR WHETHER ARISING OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF, IN EACH CASE, CISCO, ITS AFFILIATES, OFFICERS, DIRECTORS, EMPLOYEES, AGENTS, SUPPLIERS AND LICENSORS, HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME STATES OR JURISDICTIONS DO NOT ALLOW LIMITATION OR EXCLUSION OF CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT FULLY APPLY TO YOU. THE FOREGOING EXCLUSION SHALL NOT APPLY TO ANY LIABILITY ARISING OUT OF OR IN " + + "CONNECTION WITH: (I) DEATH OR PERSONAL INJURY, (II) FRAUDULENT MISREPRESENTATION, OR (III) CISCO'S LIABILITY IN CONNECTION WITH ANY TERMS THAT CANNOT BE EXCLUDED UNDER APPLICABLE LAW.\n" + + "\n" + + "Customer acknowledges and agrees that Cisco has set its prices and entered into the Agreement in reliance upon the disclaimers of warranty and the limitations of liability set forth herein, that the same reflect an allocation of risk between the parties (including the risk that a contract remedy may fail of its essential purpose and cause consequential loss), and that the same form an essential basis of the bargain between the parties.\n" + + "\n" + + "Controlling Law, Jurisdiction. If you acquired, by reference to the address on the purchase order accepted by the Approved Source, the Software in the United States, Latin America, or the Caribbean, the Agreement and warranties (\"Warranties\") are controlled by and construed under the laws of the State of California, United States of America, notwithstanding any conflicts of law provisions; and the state and federal courts of California shall have exclusive jurisdiction over any claim arising under the Agreement or Warranties. If you acquired the Software in Canada, unless expressly prohibited by local law, the Agreement and Warranties are controlled by and construed under the laws of the Province of Ontario, Canada, notwithstanding any conflicts of law provisions; and the courts of the Province of Ontario shall have exclusive jurisdiction over any claim arising under the Agreement or Warranties. If you acquired the Software in " + + "Europe, the Middle East, Africa, Asia or Oceania (excluding Australia), unless expressly prohibited by local law, the Agreement and Warranties are controlled by and construed under the laws of England, notwithstanding any conflicts of law provisions; and the English courts shall have exclusive jurisdiction over any claim arising under the Agreement or Warranties. In addition, if the Agreement is controlled by the laws of England, no person who is not a party to the Agreement shall be entitled to enforce or take the benefit of any of its terms under the Contracts (Rights of Third Parties) Act 1999. If you acquired the Software in Japan, unless expressly prohibited by local law, the Agreement and Warranties are controlled by and construed under the laws of Japan, notwithstanding any conflicts of law provisions; and the Tokyo District Court of Japan shall have exclusive jurisdiction over any claim arising under the Agreement or Warranties. " + + "If you acquired the Software in Australia, unless expressly prohibited by local law, the Agreement and Warranties are controlled by and construed under the laws of the State of New South Wales, Australia, notwithstanding any conflicts of law provisions; and the State and federal courts of New South Wales shall have exclusive jurisdiction over any claim arising under the Agreement or Warranties. If you acquired the Software in any other country, unless expressly prohibited by local law, the Agreement and Warranties are controlled by and construed under the laws of the State of California, United States of America, notwithstanding any conflicts of law provisions; and the state and federal courts of California shall have exclusive jurisdiction over any claim arising under the Agreement or Warranties.\n" + + "\n" + + "For all countries referred to above, the parties specifically disclaim the application of the UN Convention on Contracts for the International Sale of Goods. Notwithstanding the foregoing, either party may seek interim injunctive relief in any court of appropriate jurisdiction with respect to any alleged breach of such party's intellectual property or proprietary rights. If any portion hereof is found to be void or unenforceable, the remaining provisions of the Agreement and Warranties shall remain in full force and effect. Except as expressly provided herein, the Agreement constitutes the entire agreement between the parties with respect to the license of the Software and Documentation and supersedes any conflicting or additional terms contained in any Purchase Order or elsewhere, all of which terms are excluded. The Agreement has been written in the English language, and the parties agree that the English version will govern.\n" + + "\n" + + "Product warranty terms and other information applicable to Cisco products are available at the following URL: www.cisco.com/go/warranty\n" + + "\n" + + "Cisco and the Cisco logo are trademarks or registered trademarks of Cisco and/or its affiliates in the U.S. and other countries. To view a list of Cisco trademarks, go to this URL: www.cisco.com/go/trademarks. Third-party trademarks mentioned are the property of their respective owners. The use of the word partner does not imply a partnership relationship between Cisco and any other company. (1110R)\n" + + "\n" + + "© 1998, 2001, 2003, 2008-2014 Cisco Systems, Inc. All rights reserved.\n" + + "\n" + + "\n" + + " supplemental end-user license agreement\n" + + " SUPPLEMENTAL END USER LICENSE AGREEMENT FOR VIRTUAL SOFTWARE PRODUCTS\n" + + "\n" + + "IMPORTANT: READ CAREFULLY\n" + + "\n" + + "This Supplemental End User License Agreement (\"SEULA\") contains additional terms and conditions for the Software licensed under the End User License Agreement (\"EULA\") between you and Cisco (collectively, the \"Agreement\"). Capitalized terms used in this SEULA but not defined will have the meanings assigned to them in the EULA. To the extent that there is a conflict between the terms and conditions of the EULA and this SEULA, the terms and conditions of this SEULA will take precedence. In addition to the limitations set forth in the EULA on your access and use of the Software, you agree to comply at all times with the terms and conditions provided in this SEULA.\n" + + "\n" + + "DOWNLOADING, INSTALLING, OR USING THE SOFTWARE CONSTITUTES ACCEPTANCE OF THE AGREEMENT, AND YOU ARE BINDING YOURSELF AND THE BUSINESS ENTITY THAT YOU REPRESENT (COLLECTIVELY, \"CUSTOMER\") TO THE AGREEMENT. IF YOU DO NOT AGREE TO ALL OF THE TERMS OF THE AGREEMENT, THEN CISCO IS UNWILLING TO LICENSE THE SOFTWARE TO YOU AND (A) YOU MAY NOT DOWNLOAD, INSTALL OR USE THE SOFTWARE, AND (B) YOU MAY RETURN THE SOFTWARE (INCLUDING ANY UNOPENED CD PACKAGE AND ANY WRITTEN MATERIALS) FOR A FULL REFUND, OR, IF THE SOFTWARE AND WRITTEN MATERIALS ARE SUPPLIED AS PART OF ANOTHER PRODUCT, YOU MAY RETURN THE ENTIRE PRODUCT FOR A FULL REFUND. YOUR RIGHT TO RETURN AND REFUND EXPIRES 30 DAYS AFTER PURCHASE FROM CISCO OR AN AUTHORIZED CISCO RESELLER, AND APPLIES ONLY IF YOU ARE THE ORIGINAL END USER PURCHASER.\n" + + "\n" + + "Definitions\n" + + "\"CPU\" means a central processing unit that encompasses part of a Server.\n" + + "\"Failover Pair\" means a primary Instance and a standby Instance with the same Software configuration where the standby Instance can take over in case of failure of the primary Instance.\n" + + "\"Instance\" means a single copy of the Software. Each copy of the Software loaded into memory is an Instance.\n" + + "\"Server\" means a single physical computer or device on a network that manages or provides network resources for multiple users.\n" + + "\"Service Provider\" means a company that provides information technology services to external end user customers.\n" + + "\"Software\" means Cisco's Adaptive Security Virtual Appliance (\"ASAv\"), Adaptive Security Appliance 1000V Cloud Firewall Software (\"ASA 1000V\"), Nexus 1000V series switch products, Virtual Security Gateway products, or other Cisco virtual software products that Cisco includes under this SEULA.\n" + + "\"vCPU\" means a virtual central processing resource assigned to the VM by the underlying virtualization technology.\n" + + "\"Virtual Machine\" or \"VM\" means a software container that can run its own operating system and execute applications like a Server.\n" + + "\n" + + "Additional License Terms and Conditions\n" + + "1. Cisco hereby grants Customer the right to install and use the Software on single or multiple Cisco or non-Cisco Servers or on Virtual Machines. In order to use the Software Customer may be required to input a registration number or product activation key and register each Instance online at Cisco's website in order to obtain the necessary entitlements.\n" + + "2. Customer shall pay a unit license fee to Cisco or an authorized Cisco reseller, as applicable, for each Instance installed on a Cisco or non-Cisco Server CPU, vCPU or Virtual Machine, as determined by Cisco.\n" + + "3. For the ASA 1000V, Customer is licensed the number of Instances equal to the number of CPUs covered by the unit license fee. If Customer deploys a Failover Pair, then the fee for the additional standby Instance is included in the fee for each primary Instance.\n" + + "4. If Customer is a Service Provider, Customer may use the Software under the terms of this Agreement for the purpose of delivering hosted information technology services to Customer's end user customers, subject to payment of the required license fee(s).\n" + + "5. Customer may also use the Software under the terms of this Agreement to deliver hosted information technology services to Customer affiliates, subject to payment of the required license fee(s).\n" + + "6. If the Software is subject to Cisco's Smart Licensing program, Cisco will be able to assess if Customer is using the Software within the limits and entitlements paid for by Customer. If the Smart Licensing program is applicable, Customer will be required to enter into a separate terms of service agreement relating to Smart Licensing.\n" + + "\n" + + ""; + private String productSectionWithCategories = "\n" + "\n" + @@ -488,7 +613,7 @@ public class OVFHelperTest { " \n" + " \n" + " \n" + - " String naming the the hostname of the server on which the external database is running (ignored when db.type is 'embedded').\n" + + " String naming the hostname of the server on which the external database is running (ignored when db.type is 'embedded').\n" + " \n" + " \n" + " \n" + @@ -731,6 +856,12 @@ public class OVFHelperTest { Assert.assertEquals(2, eulas.size()); } + @Test + public void testGetOVFEulaSectionValidOVFwithOVFprefix() throws IOException, SAXException { + List eulas = ovfHelper.getOVFEulaSectionFromXmlString(eulaSectionsWithOVFprefix); + Assert.assertEquals(2, eulas.size()); + } + @Test public void testGetOVFPropertiesWithCategories() throws IOException, SAXException { List props = ovfHelper.getOVFPropertiesFromXmlString(productSectionWithCategories); diff --git a/api/src/test/java/com/cloud/network/VNFTest.java b/api/src/test/java/com/cloud/network/VNFTest.java new file mode 100644 index 00000000000..d38e9cc1b93 --- /dev/null +++ b/api/src/test/java/com/cloud/network/VNFTest.java @@ -0,0 +1,58 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + + +@RunWith(MockitoJUnitRunner.class) +public class VNFTest { + + static long deviceId = 0L; + static String deviceName = "eth0"; + static boolean required = true; + static boolean management = false; + static String description = "description of vnf nic"; + + @Before + public void setUp() { + } + + @Test + public void testAccessMethods() { + Assert.assertEquals(VNF.AccessMethod.CONSOLE, VNF.AccessMethod.fromValue("console")); + Assert.assertEquals(VNF.AccessMethod.HTTP, VNF.AccessMethod.fromValue("http")); + Assert.assertEquals(VNF.AccessMethod.HTTPS, VNF.AccessMethod.fromValue("https")); + Assert.assertEquals(VNF.AccessMethod.SSH_WITH_KEY, VNF.AccessMethod.fromValue("ssh-key")); + Assert.assertEquals(VNF.AccessMethod.SSH_WITH_PASSWORD, VNF.AccessMethod.fromValue("ssh-password")); + } + + @Test + public void testVnfNic() { + VNF.VnfNic vnfNic = new VNF.VnfNic(deviceId, deviceName, required, management, description); + + Assert.assertEquals(deviceId, vnfNic.getDeviceId()); + Assert.assertEquals(deviceName, vnfNic.getName()); + Assert.assertEquals(required, vnfNic.isRequired()); + Assert.assertEquals(management, vnfNic.isManagement()); + Assert.assertEquals(description, vnfNic.getDescription()); + } +} diff --git a/api/src/test/java/com/cloud/storage/StorageTest.java b/api/src/test/java/com/cloud/storage/StorageTest.java index 951ee9fe76a..2bcc28e2b4b 100644 --- a/api/src/test/java/com/cloud/storage/StorageTest.java +++ b/api/src/test/java/com/cloud/storage/StorageTest.java @@ -52,7 +52,7 @@ public class StorageTest { } @Test - public void supportsOverprovisioningStoragePool() { + public void supportsOverProvisioningTestAllStoragePoolTypes() { Assert.assertTrue(StoragePoolType.Filesystem.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.NetworkFilesystem.supportsOverProvisioning()); Assert.assertFalse(StoragePoolType.IscsiLUN.supportsOverProvisioning()); @@ -63,7 +63,7 @@ public class StorageTest { Assert.assertFalse(StoragePoolType.CLVM.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.RBD.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.PowerFlex.supportsOverProvisioning()); - Assert.assertFalse(StoragePoolType.SharedMountPoint.supportsOverProvisioning()); + Assert.assertTrue(StoragePoolType.SharedMountPoint.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.VMFS.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.PreSetup.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.EXT.supportsOverProvisioning()); @@ -74,4 +74,13 @@ public class StorageTest { Assert.assertTrue(StoragePoolType.DatastoreCluster.supportsOverProvisioning()); Assert.assertTrue(StoragePoolType.Linstor.supportsOverProvisioning()); } + + @Test + public void equalityTest() { + StoragePoolType t1 = StoragePoolType.NetworkFilesystem; + StoragePoolType t2 = StoragePoolType.NetworkFilesystem; + Assert.assertTrue(t1 == StoragePoolType.NetworkFilesystem); + Assert.assertTrue(t1.equals(StoragePoolType.NetworkFilesystem)); + Assert.assertFalse(t1.equals(StoragePoolType.EXT)); + } } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/account/CreateAccountCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/account/CreateAccountCmdTest.java index ee942a22913..365646de7a3 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/account/CreateAccountCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/account/CreateAccountCmdTest.java @@ -22,7 +22,8 @@ import org.apache.cloudstack.acl.RoleService; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -38,7 +39,7 @@ import com.cloud.user.AccountService; import com.cloud.user.User; public class CreateAccountCmdTest { - public static final Logger s_logger = Logger.getLogger(CreateAccountCmdTest.class.getName()); + protected Logger logger = LogManager.getLogger(getClass()); @Mock private AccountService accountService; @@ -52,9 +53,11 @@ public class CreateAccountCmdTest { private Integer accountType = 1; private Long domainId = 1L; + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); ReflectionTestUtils.setField(createAccountCmd, "domainId", domainId); ReflectionTestUtils.setField(createAccountCmd, "accountType", accountType); CallContext.register(Mockito.mock(User.class), Mockito.mock(Account.class)); @@ -62,6 +65,7 @@ public class CreateAccountCmdTest { @After public void tearDown() throws Exception { + closeable.close(); CallContext.unregister(); } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/annotation/AddAnnotationCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/annotation/AddAnnotationCmdTest.java index 06656868994..443460f2fff 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/annotation/AddAnnotationCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/annotation/AddAnnotationCmdTest.java @@ -18,6 +18,7 @@ */ package org.apache.cloudstack.api.command.admin.annotation; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.MockitoAnnotations; @@ -26,9 +27,16 @@ public class AddAnnotationCmdTest { private AddAnnotationCmd addAnnotationCmd = new AddAnnotationCmd(); + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); } @Test (expected = IllegalStateException.class) diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmdTest.java new file mode 100644 index 00000000000..3c9d4cb67ae --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/domain/ListDomainsCmdTest.java @@ -0,0 +1,77 @@ +// 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.domain; + +import java.util.List; + +import org.apache.cloudstack.api.response.DomainResponse; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import com.cloud.user.ResourceLimitService; + +@RunWith(MockitoJUnitRunner.class) +public class ListDomainsCmdTest { + + @Mock + ResourceLimitService resourceLimitService; + + + @Test + public void testGetShowIcon() { + ListDomainsCmd cmd = new ListDomainsCmd(); + ReflectionTestUtils.setField(cmd, "showIcon", null); + Assert.assertFalse(cmd.getShowIcon()); + ReflectionTestUtils.setField(cmd, "showIcon", false); + Assert.assertFalse(cmd.getShowIcon()); + ReflectionTestUtils.setField(cmd, "showIcon", true); + Assert.assertTrue(cmd.getShowIcon()); + } + + @Test + public void testGetTag() { + ListDomainsCmd cmd = new ListDomainsCmd(); + ReflectionTestUtils.setField(cmd, "tag", null); + Assert.assertNull(cmd.getTag()); + String tag = "ABC"; + ReflectionTestUtils.setField(cmd, "tag", tag); + Assert.assertEquals(tag, cmd.getTag()); + } + + @Test + public void testUpdateDomainResponseNoDomains() { + ListDomainsCmd cmd = new ListDomainsCmd(); + cmd._resourceLimitService = resourceLimitService; + cmd.updateDomainResponse(null); + Mockito.verify(resourceLimitService, Mockito.never()).updateTaggedResourceLimitsAndCountsForDomains(Mockito.anyList(), Mockito.anyString()); + } + + @Test + public void testUpdateDomainResponseWithDomains() { + ListDomainsCmd cmd = new ListDomainsCmd(); + cmd._resourceLimitService = resourceLimitService; + ReflectionTestUtils.setField(cmd, "tag", "abc"); + cmd.updateDomainResponse(List.of(Mockito.mock(DomainResponse.class))); + Mockito.verify(resourceLimitService, Mockito.times(1)).updateTaggedResourceLimitsAndCountsForDomains(Mockito.any(), Mockito.any()); + } + +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/iso/ListIsosCmdByAdminTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/iso/ListIsosCmdByAdminTest.java new file mode 100644 index 00000000000..943db0cdfb7 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/iso/ListIsosCmdByAdminTest.java @@ -0,0 +1,128 @@ +// 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.iso; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.junit.Assert.assertEquals; + +public class ListIsosCmdByAdminTest { + + @InjectMocks + ListIsosCmdByAdmin cmd; + private AutoCloseable closeable; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test + public void testGetImageStoreId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "imageStoreId", id); + assertEquals(id, cmd.getImageStoreId()); + } + + @Test + public void testGetZoneId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "zoneId", id); + assertEquals(id, cmd.getZoneId()); + } + + @Test + public void testGetShowRemoved() { + Boolean showRemoved = true; + ReflectionTestUtils.setField(cmd, "showRemoved", showRemoved); + assertEquals(showRemoved, cmd.getShowRemoved()); + } + + @Test + public void testGetIsoName() { + String isoName = "test"; + ReflectionTestUtils.setField(cmd, "isoName", isoName); + assertEquals(isoName, cmd.getIsoName()); + } + + @Test + public void testGetIsoFilter() { + String isoFilter = "test"; + ReflectionTestUtils.setField(cmd, "isoFilter", isoFilter); + assertEquals(isoFilter, cmd.getIsoFilter()); + } + + @Test + public void testGetShowUnique() { + Boolean showUnique = true; + ReflectionTestUtils.setField(cmd, "showUnique", showUnique); + assertEquals(showUnique, cmd.getShowUnique()); + } + + @Test + public void testGetShowIcon() { + Boolean showIcon = true; + ReflectionTestUtils.setField(cmd, "showIcon", showIcon); + assertEquals(showIcon, cmd.getShowIcon()); + } + + @Test + public void testGetBootable() { + Boolean bootable = true; + ReflectionTestUtils.setField(cmd, "bootable", bootable); + assertEquals(bootable, cmd.isBootable()); + } + + @Test + public void testGetHypervisor() { + String hypervisor = "test"; + ReflectionTestUtils.setField(cmd, "hypervisor", hypervisor); + assertEquals(hypervisor, cmd.getHypervisor()); + } + + @Test + public void testGetId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "id", id); + assertEquals(id, cmd.getId()); + } + + @Test + public void testGetPublic() { + Boolean publicIso = true; + ReflectionTestUtils.setField(cmd, "publicIso", publicIso); + assertEquals(publicIso, cmd.isPublic()); + } + + @Test + public void testGetReady() { + Boolean ready = true; + ReflectionTestUtils.setField(cmd, "ready", ready); + assertEquals(ready, cmd.isReady()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/CreateNetworkOfferingCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/CreateNetworkOfferingCmdTest.java index 8b95456a84c..ef10ebff467 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/CreateNetworkOfferingCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/CreateNetworkOfferingCmdTest.java @@ -23,14 +23,16 @@ import org.junit.Test; import org.mockito.InjectMocks; import org.springframework.test.util.ReflectionTestUtils; + public class CreateNetworkOfferingCmdTest { @InjectMocks private CreateNetworkOfferingCmd createNetworkOfferingCmd = new CreateNetworkOfferingCmd(); + String netName = "network"; + @Test public void createVpcNtwkOffWithEmptyDisplayText() { - String netName = "network"; ReflectionTestUtils.setField(createNetworkOfferingCmd, "networkOfferingName", netName); Assert.assertEquals(createNetworkOfferingCmd.getDisplayText(), netName); } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmdTest.java index 717b5c3262d..6daa5de07cb 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmdTest.java @@ -21,7 +21,7 @@ import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; @RunWith(MockitoJUnitRunner.class) @@ -37,4 +37,22 @@ public class CreateServiceOfferingCmdTest { Assert.assertEquals(createServiceOfferingCmd.getDisplayText(), netName); } + @Test + public void testIsPurgeResourcesNoOrNullValue() { + Assert.assertFalse(createServiceOfferingCmd.isPurgeResources()); + ReflectionTestUtils.setField(createServiceOfferingCmd, "purgeResources", false); + Assert.assertFalse(createServiceOfferingCmd.isPurgeResources()); + } + + @Test + public void testIsPurgeResourcesFalse() { + ReflectionTestUtils.setField(createServiceOfferingCmd, "purgeResources", false); + Assert.assertFalse(createServiceOfferingCmd.isPurgeResources()); + } + + @Test + public void testIsPurgeResourcesTrue() { + ReflectionTestUtils.setField(createServiceOfferingCmd, "purgeResources", true); + Assert.assertTrue(createServiceOfferingCmd.isPurgeResources()); + } } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmdTest.java new file mode 100644 index 00000000000..1bb2be041e1 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/offering/UpdateServiceOfferingCmdTest.java @@ -0,0 +1,51 @@ +// 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.offering; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class UpdateServiceOfferingCmdTest { + + @InjectMocks + private UpdateServiceOfferingCmd updateServiceOfferingCmd; + + @Test + public void testIsPurgeResourcesNoOrNullValue() { + Assert.assertFalse(updateServiceOfferingCmd.isPurgeResources()); + ReflectionTestUtils.setField(updateServiceOfferingCmd, "purgeResources", false); + Assert.assertFalse(updateServiceOfferingCmd.isPurgeResources()); + } + + @Test + public void testIsPurgeResourcesFalse() { + ReflectionTestUtils.setField(updateServiceOfferingCmd, "purgeResources", false); + Assert.assertFalse(updateServiceOfferingCmd.isPurgeResources()); + } + + @Test + public void testIsPurgeResourcesTrue() { + ReflectionTestUtils.setField(updateServiceOfferingCmd, "purgeResources", true); + Assert.assertTrue(updateServiceOfferingCmd.isPurgeResources()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmdTest.java new file mode 100644 index 00000000000..fc0e6face52 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/resource/ListCapacityCmdTest.java @@ -0,0 +1,34 @@ +// 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.resource; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +public class ListCapacityCmdTest { + + @Test + public void testGetTag() { + ListCapacityCmd cmd = new ListCapacityCmd(); + ReflectionTestUtils.setField(cmd, "tag", null); + Assert.assertNull(cmd.getTag()); + String tag = "ABC"; + ReflectionTestUtils.setField(cmd, "tag", tag); + Assert.assertEquals(tag, cmd.getTag()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/resource/PurgeExpungedResourcesCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/resource/PurgeExpungedResourcesCmdTest.java new file mode 100644 index 00000000000..a628f13275c --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/resource/PurgeExpungedResourcesCmdTest.java @@ -0,0 +1,104 @@ +// 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.resource; + +import static org.junit.Assert.assertNull; + +import java.util.Date; + +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.PurgeExpungedResourcesResponse; +import org.apache.cloudstack.resource.ResourceCleanupService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; +import org.springframework.test.util.ReflectionTestUtils; + +import com.cloud.utils.exception.CloudRuntimeException; + +@RunWith(MockitoJUnitRunner.class) +public class PurgeExpungedResourcesCmdTest { + @Mock + ResourceCleanupService resourceCleanupService; + + @Spy + @InjectMocks + PurgeExpungedResourcesCmd spyCmd = Mockito.spy(new PurgeExpungedResourcesCmd()); + + @Test + public void testGetResourceType() { + PurgeExpungedResourcesCmd cmd = new PurgeExpungedResourcesCmd(); + assertNull(cmd.getResourceType()); + ReflectionTestUtils.setField(cmd, "resourceType", ResourceCleanupService.ResourceType.VirtualMachine.toString()); + Assert.assertEquals(ResourceCleanupService.ResourceType.VirtualMachine.toString(), cmd.getResourceType()); + } + + @Test + public void testGetBatchSize() { + PurgeExpungedResourcesCmd cmd = new PurgeExpungedResourcesCmd(); + assertNull(cmd.getBatchSize()); + Long batchSize = 100L; + ReflectionTestUtils.setField(cmd, "batchSize", batchSize); + Assert.assertEquals(batchSize, cmd.getBatchSize()); + } + + @Test + public void testGetStartDate() { + PurgeExpungedResourcesCmd cmd = new PurgeExpungedResourcesCmd(); + assertNull(cmd.getStartDate()); + Date date = new Date(); + ReflectionTestUtils.setField(cmd, "startDate", date); + Assert.assertEquals(date, cmd.getStartDate()); + } + + @Test + public void testGetEndDate() { + PurgeExpungedResourcesCmd cmd = new PurgeExpungedResourcesCmd(); + assertNull(cmd.getEndDate()); + Date date = new Date(); + ReflectionTestUtils.setField(cmd, "endDate", date); + Assert.assertEquals(date, cmd.getEndDate()); + } + + @Test + public void testExecute() { + final PurgeExpungedResourcesResponse[] executeResponse = new PurgeExpungedResourcesResponse[1]; + Long result = 100L; + Mockito.when(resourceCleanupService.purgeExpungedResources(Mockito.any())).thenReturn(result); + Mockito.doAnswer((Answer) invocation -> { + executeResponse[0] = (PurgeExpungedResourcesResponse)invocation.getArguments()[0]; + return null; + }).when(spyCmd).setResponseObject(Mockito.any()); + spyCmd.execute(); + PurgeExpungedResourcesResponse response = executeResponse[0]; + Assert.assertNotNull(response); + Assert.assertEquals(result, response.getResourceCount()); + } + + @Test(expected = ServerApiException.class) + public void testExecuteException() { + Mockito.doThrow(CloudRuntimeException.class).when(resourceCleanupService).purgeExpungedResources(Mockito.any()); + spyCmd.execute(); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/AddObjectStoragePoolCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/AddObjectStoragePoolCmdTest.java new file mode 100644 index 00000000000..a69a7a858ce --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/AddObjectStoragePoolCmdTest.java @@ -0,0 +1,98 @@ +/* + * 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.storage; + +import com.cloud.exception.DiscoveryException; +import com.cloud.storage.StorageService; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.response.ObjectStoreResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.storage.object.ObjectStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; + +@RunWith(MockitoJUnitRunner.class) +public class AddObjectStoragePoolCmdTest { + + @Mock + StorageService storageService; + + @Mock + ObjectStore objectStore; + + @Mock + ResponseGenerator responseGenerator; + + @Spy + AddObjectStoragePoolCmd addObjectStoragePoolCmdSpy; + + String name = "testObjStore"; + + String url = "testURL"; + + String provider = "Simulator"; + + Map details; + + private AutoCloseable closeable; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + details = new HashMap<>(); + addObjectStoragePoolCmdSpy = Mockito.spy(new AddObjectStoragePoolCmd()); + ReflectionTestUtils.setField(addObjectStoragePoolCmdSpy, "name", name); + ReflectionTestUtils.setField(addObjectStoragePoolCmdSpy, "url", url); + ReflectionTestUtils.setField(addObjectStoragePoolCmdSpy, "providerName", provider); + ReflectionTestUtils.setField(addObjectStoragePoolCmdSpy, "details", details); + addObjectStoragePoolCmdSpy._storageService = storageService; + addObjectStoragePoolCmdSpy._responseGenerator = responseGenerator; + } + + @After + public void tearDown() throws Exception { + CallContext.unregister(); + closeable.close(); + } + + @Test + public void testAddObjectStore() throws DiscoveryException { + Mockito.doReturn(objectStore).when(storageService).discoverObjectStore(Mockito.anyString(), + Mockito.anyString(), Mockito.anyString(), any()); + ObjectStoreResponse objectStoreResponse = new ObjectStoreResponse(); + Mockito.doReturn(objectStoreResponse).when(responseGenerator).createObjectStoreResponse(any()); + addObjectStoragePoolCmdSpy.execute(); + + Mockito.verify(storageService, Mockito.times(1)) + .discoverObjectStore(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/DeleteObjectStoragePoolCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/DeleteObjectStoragePoolCmdTest.java new file mode 100644 index 00000000000..dc5b9f5fa32 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/DeleteObjectStoragePoolCmdTest.java @@ -0,0 +1,60 @@ +/* + * 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.storage; + +import com.cloud.storage.StorageService; +import org.apache.cloudstack.context.CallContext; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + +public class DeleteObjectStoragePoolCmdTest { + @Mock + private StorageService storageService; + + @Spy + DeleteObjectStoragePoolCmd deleteObjectStoragePoolCmd; + + private AutoCloseable closeable; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + deleteObjectStoragePoolCmd = Mockito.spy(new DeleteObjectStoragePoolCmd()); + deleteObjectStoragePoolCmd._storageService = storageService; + } + + @After + public void tearDown() throws Exception { + CallContext.unregister(); + closeable.close(); + } + + @Test + public void testDeleteObjectStore() { + Mockito.doReturn(true).when(storageService).deleteObjectStore(deleteObjectStoragePoolCmd); + deleteObjectStoragePoolCmd.execute(); + Mockito.verify(storageService, Mockito.times(1)) + .deleteObjectStore(deleteObjectStoragePoolCmd); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/DownloadImageStoreObjectCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/DownloadImageStoreObjectCmdTest.java new file mode 100644 index 00000000000..98435bf6e38 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/DownloadImageStoreObjectCmdTest.java @@ -0,0 +1,119 @@ +// 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.storage; + +import com.cloud.utils.Pair; +import org.apache.cloudstack.api.response.ExtractResponse; +import org.apache.cloudstack.storage.browser.StorageBrowser; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.List; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class DownloadImageStoreObjectCmdTest { + + @Mock + private StorageBrowser storageBrowser; + + @InjectMocks + @Spy + private DownloadImageStoreObjectCmd cmd; + + private AutoCloseable closeable; + + @Before + public void setUp() { + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test + public void testExecute() throws Exception { + ReflectionTestUtils.setField(cmd, "storeId", 1L); + ReflectionTestUtils.setField(cmd, "path", "path/to/object"); + ExtractResponse response = mock(ExtractResponse.class); + when(storageBrowser.downloadImageStoreObject(cmd)).thenReturn(response); + + cmd.execute(); + + verify(storageBrowser).downloadImageStoreObject(cmd); + verify(response).setResponseName("downloadImageStoreObjectResponse".toLowerCase()); + verify(response).setObjectName("downloadImageStoreObjectResponse".toLowerCase()); + verify(cmd).setResponseObject(response); + } + + @Test + public void testGetPath() { + List> pair = List.of( + new Pair<>("", null), + new Pair<>("", ""), + new Pair<>("", "/"), + new Pair<>("etc", "etc"), + new Pair<>("etc", "/etc"), + new Pair<>("etc/passwd", "etc/passwd"), + new Pair<>("etc/passwd", "//etc/passwd"), + new Pair<>("", "/etc/passwd/../../.."), + new Pair<>("etc/passwd", "../../etc/passwd"), + new Pair<>("etc/passwd", "/../../etc/passwd"), + new Pair<>("etc/passwd", ";../../../etc/passwd"), + new Pair<>("etc/passwd", "///etc/passwd"), + new Pair<>("etc/passwd", "/abc/xyz/../../../etc/passwd") + ); + + for (Pair p : pair) { + String expectedPath = p.first(); + String path = p.second(); + ReflectionTestUtils.setField(cmd, "path", path); + Assert.assertEquals(expectedPath, cmd.getPath()); + } + } + + @Test + public void testGetEventType() { + String eventType = cmd.getEventType(); + + Assert.assertEquals("IMAGE.STORE.OBJECT.DOWNLOAD", eventType); + } + + @Test + public void testGetEventDescription() { + ReflectionTestUtils.setField(cmd, "storeId", 1L); + ReflectionTestUtils.setField(cmd, "path", "path/to/object"); + String eventDescription = cmd.getEventDescription(); + + Assert.assertEquals("Downloading object at path path/to/object on image store 1", eventDescription); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmdTest.java index 5244ff1ef9a..fbf4d2c495d 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmdTest.java @@ -23,7 +23,7 @@ import org.apache.cloudstack.api.response.StoragePoolResponse; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class FindStoragePoolsForMigrationCmdTest { diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/ListImageStoreObjectsCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/ListImageStoreObjectsCmdTest.java new file mode 100644 index 00000000000..88dcde1a4b0 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/ListImageStoreObjectsCmdTest.java @@ -0,0 +1,98 @@ +/* + * 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.storage; + +import com.cloud.utils.Pair; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.storage.browser.DataStoreObjectResponse; +import org.apache.cloudstack.storage.browser.StorageBrowser; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.List; + +public class ListImageStoreObjectsCmdTest { + + @Mock + StorageBrowser storageBrowser; + + @InjectMocks + private ListImageStoreObjectsCmd cmd = new ListImageStoreObjectsCmd(); + + private AutoCloseable closeable; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test + public void testGetStoreId() { + Long id = 123L; + ReflectionTestUtils.setField(cmd, "storeId", id); + Assert.assertEquals(id, cmd.getStoreId()); + } + + @Test + public void testGetPath() { + List> pair = List.of( + new Pair<>("", null), + new Pair<>("", ""), + new Pair<>("", "/"), + new Pair<>("etc", "etc"), + new Pair<>("etc", "/etc"), + new Pair<>("etc/passwd", "etc/passwd"), + new Pair<>("etc/passwd", "//etc/passwd"), + new Pair<>("", "/etc/passwd/../../.."), + new Pair<>("etc/passwd", "../../etc/passwd"), + new Pair<>("etc/passwd", "/../../etc/passwd"), + new Pair<>("etc/passwd", ";../../../etc/passwd"), + new Pair<>("etc/passwd", "///etc/passwd"), + new Pair<>("etc/passwd", "/abc/xyz/../../../etc/passwd") + ); + + for (Pair p : pair) { + String expectedPath = p.first(); + String path = p.second(); + ReflectionTestUtils.setField(cmd, "path", path); + Assert.assertEquals(expectedPath, cmd.getPath()); + } + } + + @Test + public void testSuccessfulExecution() { + ListResponse response = Mockito.mock(ListResponse.class); + Mockito.when(storageBrowser.listImageStoreObjects(cmd)).thenReturn(response); + cmd.execute(); + Assert.assertEquals(response, cmd.getResponseObject()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolObjectsCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolObjectsCmdTest.java new file mode 100644 index 00000000000..a15740da819 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/ListStoragePoolObjectsCmdTest.java @@ -0,0 +1,96 @@ +/* + * 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.storage; + +import com.cloud.utils.Pair; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.storage.browser.DataStoreObjectResponse; +import org.apache.cloudstack.storage.browser.StorageBrowser; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.List; + +public class ListStoragePoolObjectsCmdTest { + @Mock + StorageBrowser storageBrowser; + + @InjectMocks + private ListStoragePoolObjectsCmd cmd = new ListStoragePoolObjectsCmd(); + private AutoCloseable closeable; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test + public void testGetStoreId() { + Long id = 123L; + ReflectionTestUtils.setField(cmd, "storeId", id); + Assert.assertEquals(id, cmd.getStoreId()); + } + + @Test + public void testGetPath() { + List> pair = List.of( + new Pair<>("", null), + new Pair<>("", ""), + new Pair<>("", "/"), + new Pair<>("etc", "etc"), + new Pair<>("etc", "/etc"), + new Pair<>("etc/passwd", "etc/passwd"), + new Pair<>("etc/passwd", "//etc/passwd"), + new Pair<>("", "/etc/passwd/../../.."), + new Pair<>("etc/passwd", "../../etc/passwd"), + new Pair<>("etc/passwd", "/../../etc/passwd"), + new Pair<>("etc/passwd", ";../../../etc/passwd"), + new Pair<>("etc/passwd", "///etc/passwd"), + new Pair<>("etc/passwd", "/abc/xyz/../../../etc/passwd") + ); + + for (Pair p : pair) { + String expectedPath = p.first(); + String path = p.second(); + ReflectionTestUtils.setField(cmd, "path", path); + Assert.assertEquals(expectedPath, cmd.getPath()); + } + } + + @Test + public void testSuccessfulExecution() { + ListResponse response = Mockito.mock(ListResponse.class); + Mockito.when(storageBrowser.listPrimaryStoreObjects(cmd)).thenReturn(response); + cmd.execute(); + Assert.assertEquals(response, cmd.getResponseObject()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/MigrateResourcesToAnotherSecondaryStorageCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/MigrateResourcesToAnotherSecondaryStorageCmdTest.java new file mode 100644 index 00000000000..2f000ee2b42 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/MigrateResourcesToAnotherSecondaryStorageCmdTest.java @@ -0,0 +1,90 @@ +// 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.storage; + +import org.apache.cloudstack.api.response.MigrationResponse; +import org.apache.cloudstack.storage.ImageStoreService; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.List; + +public class MigrateResourcesToAnotherSecondaryStorageCmdTest { + + + @Mock + ImageStoreService _imageStoreService; + + @InjectMocks + MigrateResourcesToAnotherSecondaryStorageCmd cmd; + private AutoCloseable closeable; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test + public void testGetDestStoreId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "destStoreId", id); + Assert.assertEquals(id, cmd.getDestStoreId()); + } + + @Test + public void testGetId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "id", id); + Assert.assertEquals(id, cmd.getId()); + } + + @Test + public void testGetTemplateIdList() { + List ids = List.of(1234L, 5678L); + ReflectionTestUtils.setField(cmd, "templateIdList", ids); + Assert.assertEquals(ids, cmd.getTemplateIdList()); + } + + @Test + public void testGetSnapshotIdList() { + List ids = List.of(1234L, 5678L); + ReflectionTestUtils.setField(cmd, "snapshotIdList", ids); + Assert.assertEquals(ids, cmd.getSnapshotIdList()); + } + + @Test + public void testExecute() { + MigrationResponse response = Mockito.mock(MigrationResponse.class); + Mockito.when(_imageStoreService.migrateResources(Mockito.any())).thenReturn(response); + cmd.execute(); + Assert.assertEquals(response, cmd.getResponseObject()); + } + +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/UpdateObjectStoragePoolCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/UpdateObjectStoragePoolCmdTest.java new file mode 100644 index 00000000000..307d80aa3f8 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/storage/UpdateObjectStoragePoolCmdTest.java @@ -0,0 +1,86 @@ +/* + * 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.storage; + +import com.cloud.storage.StorageService; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.response.ObjectStoreResponse; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.storage.object.ObjectStore; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.mockito.ArgumentMatchers.any; + +public class UpdateObjectStoragePoolCmdTest { + + @Mock + private StorageService storageService; + + @Spy + UpdateObjectStoragePoolCmd updateObjectStoragePoolCmd; + + @Mock + ObjectStore objectStore; + + @Mock + ResponseGenerator responseGenerator; + + private String name = "testObjStore"; + + private String url = "testURL"; + + private String provider = "Simulator"; + + private AutoCloseable closeable; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + updateObjectStoragePoolCmd = Mockito.spy(new UpdateObjectStoragePoolCmd()); + updateObjectStoragePoolCmd._storageService = storageService; + updateObjectStoragePoolCmd._responseGenerator = responseGenerator; + ReflectionTestUtils.setField(updateObjectStoragePoolCmd, "name", name); + ReflectionTestUtils.setField(updateObjectStoragePoolCmd, "url", url); + ReflectionTestUtils.setField(updateObjectStoragePoolCmd, "id", 1L); + } + + @After + public void tearDown() throws Exception { + CallContext.unregister(); + closeable.close(); + } + + @Test + public void testUpdateObjectStore() { + Mockito.doReturn(objectStore).when(storageService).updateObjectStore(1L, updateObjectStoragePoolCmd); + ObjectStoreResponse objectStoreResponse = new ObjectStoreResponse(); + Mockito.doReturn(objectStoreResponse).when(responseGenerator).createObjectStoreResponse(any()); + updateObjectStoragePoolCmd.execute(); + Mockito.verify(storageService, Mockito.times(1)) + .updateObjectStore(1L, updateObjectStoragePoolCmd); + } + +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java index 125c8b56665..4f58bd6d391 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/systemvm/PatchSystemVMCmdTest.java @@ -20,23 +20,20 @@ import com.cloud.server.ManagementService; import com.cloud.user.Account; import com.cloud.utils.Pair; import org.apache.cloudstack.context.CallContext; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; -@RunWith(PowerMockRunner.class) -@PrepareForTest(CallContext.class) -@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) +@RunWith(MockitoJUnitRunner.class) public class PatchSystemVMCmdTest { @Mock @@ -45,9 +42,16 @@ public class PatchSystemVMCmdTest { @InjectMocks PatchSystemVMCmd cmd = new PatchSystemVMCmd(); + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); } @Test @@ -76,17 +80,16 @@ public class PatchSystemVMCmdTest { @Test public void validateArgsForPatchSystemVMApi() { - PowerMockito.mockStatic(CallContext.class); - CallContext callContextMock = PowerMockito.mock(CallContext.class); - PowerMockito.when(CallContext.current()).thenReturn(callContextMock); - Account accountMock = PowerMockito.mock(Account.class); - PowerMockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); - Mockito.when(accountMock.getId()).thenReturn(2L); - ReflectionTestUtils.setField(cmd, "id", 1L); - Assert.assertEquals((long)cmd.getId(), 1L); - Assert.assertFalse(cmd.isForced()); - Assert.assertEquals(cmd.getEntityOwnerId(), 2L); - - + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + Account accountMock = Mockito.mock(Account.class); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); + Mockito.when(accountMock.getId()).thenReturn(2L); + ReflectionTestUtils.setField(cmd, "id", 1L); + Assert.assertEquals((long) cmd.getId(), 1L); + Assert.assertFalse(cmd.isForced()); + Assert.assertEquals(cmd.getEntityOwnerId(), 2L); + } } } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdminTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdminTest.java new file mode 100644 index 00000000000..bdb14964eee --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdminTest.java @@ -0,0 +1,94 @@ +// 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.template; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.junit.Assert.assertEquals; + +public class ListTemplatesCmdByAdminTest { + + @InjectMocks + ListTemplatesCmdByAdmin cmd; + private AutoCloseable closeable; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test + public void testGetImageStoreId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "imageStoreId", id); + assertEquals(id, cmd.getImageStoreId()); + } + + @Test + public void testGetZoneId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "zoneId", id); + assertEquals(id, cmd.getZoneId()); + } + + @Test + public void testGetShowRemoved() { + Boolean showRemoved = true; + ReflectionTestUtils.setField(cmd, "showRemoved", showRemoved); + assertEquals(showRemoved, cmd.getShowRemoved()); + } + + @Test + public void testGetShowUnique() { + Boolean showUnique = true; + ReflectionTestUtils.setField(cmd, "showUnique", showUnique); + assertEquals(showUnique, cmd.getShowUnique()); + } + + @Test + public void testGetShowIcon() { + Boolean showIcon = true; + ReflectionTestUtils.setField(cmd, "showIcon", showIcon); + assertEquals(showIcon, cmd.getShowIcon()); + } + + @Test + public void testGetHypervisor() { + String hypervisor = "test"; + ReflectionTestUtils.setField(cmd, "hypervisor", hypervisor); + assertEquals(hypervisor, cmd.getHypervisor()); + } + + @Test + public void testGetId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "id", id); + assertEquals(id, cmd.getId()); + } + +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/user/CreateUserCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/user/CreateUserCmdTest.java index cde3b2da87f..8a57ac3eb22 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/user/CreateUserCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/user/CreateUserCmdTest.java @@ -22,7 +22,8 @@ package org.apache.cloudstack.api.command.admin.user; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.context.CallContext; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -38,7 +39,7 @@ import com.cloud.user.AccountService; import com.cloud.user.User; public class CreateUserCmdTest { - public static final Logger s_logger = Logger.getLogger(CreateUserCmdTest.class.getName()); + protected Logger logger = LogManager.getLogger(getClass()); @Mock private AccountService accountService; @@ -46,14 +47,17 @@ public class CreateUserCmdTest { @InjectMocks private CreateUserCmd createUserCmd = new CreateUserCmd(); + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); CallContext.register(Mockito.mock(User.class), Mockito.mock(Account.class)); } @After public void tearDown() throws Exception { + closeable.close(); CallContext.unregister(); } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/volume/ImportVolumeCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/volume/ImportVolumeCmdTest.java new file mode 100644 index 00000000000..a7c41b9271b --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/volume/ImportVolumeCmdTest.java @@ -0,0 +1,83 @@ +// 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.volume; + +import com.cloud.event.EventTypes; +import com.cloud.user.AccountService; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.storage.volume.VolumeImportUnmanageService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class ImportVolumeCmdTest { + + VolumeImportUnmanageService volumeImportService = Mockito.spy(VolumeImportUnmanageService.class); + AccountService accountService = Mockito.spy(AccountService.class); + + @Test + public void testImportVolumeCmd() { + String name = "volume name"; + String path = "file path"; + Long storageId = 2L; + Long diskOfferingId = 3L; + String accountName = "account"; + Long domainId = 4L; + Long projectId = 5L; + long accountId = 6L; + + Mockito.when(accountService.finalyzeAccountId(accountName, domainId, projectId, true)).thenReturn(accountId); + + ImportVolumeCmd cmd = new ImportVolumeCmd(); + ReflectionTestUtils.setField(cmd, "path", path); + ReflectionTestUtils.setField(cmd, "name", name); + ReflectionTestUtils.setField(cmd, "storageId", storageId); + ReflectionTestUtils.setField(cmd, "diskOfferingId", diskOfferingId); + ReflectionTestUtils.setField(cmd, "accountName", accountName); + ReflectionTestUtils.setField(cmd, "domainId", domainId); + ReflectionTestUtils.setField(cmd, "projectId", projectId); + ReflectionTestUtils.setField(cmd,"volumeImportService", volumeImportService); + ReflectionTestUtils.setField(cmd, "_accountService", accountService); + + Assert.assertEquals(path, cmd.getPath()); + Assert.assertEquals(name, cmd.getName()); + Assert.assertEquals(storageId, cmd.getStorageId()); + Assert.assertEquals(diskOfferingId, cmd.getDiskOfferingId()); + Assert.assertEquals(accountName, cmd.getAccountName()); + Assert.assertEquals(domainId, cmd.getDomainId()); + Assert.assertEquals(projectId, cmd.getProjectId()); + + Assert.assertEquals(EventTypes.EVENT_VOLUME_IMPORT, cmd.getEventType()); + Assert.assertEquals("Importing unmanaged Volume with path: " + path, cmd.getEventDescription()); + Assert.assertEquals(accountId, cmd.getEntityOwnerId()); + + VolumeResponse response = Mockito.mock(VolumeResponse.class); + Mockito.when(volumeImportService.importVolume(cmd)).thenReturn(response); + try { + cmd.execute(); + } catch (Exception ignored) { + } + + Assert.assertEquals(response, cmd.getResponseObject()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/volume/ListVolumesForImportCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/volume/ListVolumesForImportCmdTest.java new file mode 100644 index 00000000000..959940d2a91 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/volume/ListVolumesForImportCmdTest.java @@ -0,0 +1,58 @@ +// 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.volume; + +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.VolumeForImportResponse; +import org.apache.cloudstack.storage.volume.VolumeImportUnmanageService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class ListVolumesForImportCmdTest { + + VolumeImportUnmanageService volumeImportService = Mockito.spy(VolumeImportUnmanageService.class); + + @Test + public void testListVolumesForImportCmd() { + Long storageId = 2L; + String filePath = "file path"; + + ListVolumesForImportCmd cmd = new ListVolumesForImportCmd(); + ReflectionTestUtils.setField(cmd, "storageId", storageId); + ReflectionTestUtils.setField(cmd, "path", filePath); + ReflectionTestUtils.setField(cmd,"volumeImportService", volumeImportService); + + Assert.assertEquals(storageId, cmd.getStorageId()); + Assert.assertEquals(filePath, cmd.getPath()); + + ListResponse response = Mockito.mock(ListResponse.class); + Mockito.when(volumeImportService.listVolumesForImport(cmd)).thenReturn(response); + try { + cmd.execute(); + } catch (Exception ignored) { + } + + Assert.assertEquals(response, cmd.getResponseObject()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/volume/UnmanageVolumeCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/volume/UnmanageVolumeCmdTest.java new file mode 100644 index 00000000000..ba7e351a8a8 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/volume/UnmanageVolumeCmdTest.java @@ -0,0 +1,70 @@ +// 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.volume; + +import com.cloud.event.EventTypes; +import com.cloud.storage.Volume; +import org.apache.cloudstack.api.ApiCommandResourceType; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.storage.volume.VolumeImportUnmanageService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class UnmanageVolumeCmdTest { + + VolumeImportUnmanageService volumeImportService = Mockito.spy(VolumeImportUnmanageService.class); + ResponseGenerator responseGenerator = Mockito.spy(ResponseGenerator.class); + + @Test + public void testUnmanageVolumeCmd() { + long accountId = 2L; + Long volumeId = 3L; + Volume volume = Mockito.mock(Volume.class); + + Mockito.when(responseGenerator.findVolumeById(volumeId)).thenReturn(volume); + Mockito.when(volume.getAccountId()).thenReturn(accountId); + + UnmanageVolumeCmd cmd = new UnmanageVolumeCmd(); + ReflectionTestUtils.setField(cmd, "volumeId", volumeId); + ReflectionTestUtils.setField(cmd,"volumeImportService", volumeImportService); + ReflectionTestUtils.setField(cmd,"_responseGenerator", responseGenerator); + + Assert.assertEquals(volumeId, cmd.getVolumeId()); + Assert.assertEquals(accountId, cmd.getEntityOwnerId()); + Assert.assertEquals(volumeId, cmd.getApiResourceId()); + Assert.assertEquals(ApiCommandResourceType.Volume, cmd.getApiResourceType()); + Assert.assertEquals(EventTypes.EVENT_VOLUME_UNMANAGE, cmd.getEventType()); + Assert.assertEquals("Unmanaging Volume with ID " + volumeId, cmd.getEventDescription()); + + Mockito.when(volumeImportService.unmanageVolume(volumeId)).thenReturn(true); + try { + cmd.execute(); + } catch (Exception ignored) { + } + + Object response = cmd.getResponseObject(); + Assert.assertTrue(response instanceof SuccessResponse); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmdTest.java index 16b716d7d63..290a2850c9a 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmdTest.java @@ -52,15 +52,15 @@ public class CreateVPCOfferingCmdTest { IllegalAccessException { CreateVPCOfferingCmd cmd = new CreateVPCOfferingCmd(); ApiCmdTestUtil.set(cmd, ApiConstants.SERVICE_PROVIDER_LIST, new HashMap>()); - Assert.assertNull(cmd.getServiceProviders()); + Assert.assertTrue(cmd.getServiceProviders().isEmpty()); } @Test - public void getDetailsNull() throws IllegalArgumentException, + public void getDetailsEmpty() throws IllegalArgumentException, IllegalAccessException { CreateVPCOfferingCmd cmd = new CreateVPCOfferingCmd(); ApiCmdTestUtil.set(cmd, ApiConstants.SERVICE_PROVIDER_LIST, null); - Assert.assertNull(cmd.getServiceProviders()); + Assert.assertTrue(cmd.getServiceProviders().isEmpty()); } @Test diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/ActivateProjectCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/ActivateProjectCmdTest.java index 1e4bb326f7e..2c43278a582 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/ActivateProjectCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/ActivateProjectCmdTest.java @@ -23,7 +23,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.mockito.Matchers; +import org.mockito.ArgumentMatchers; import org.mockito.Mockito; import org.apache.cloudstack.api.command.user.project.ActivateProjectCmd; @@ -57,7 +57,7 @@ public class ActivateProjectCmdTest extends TestCase { @Test public void testGetEntityOwnerIdForNullProject() { ProjectService projectService = Mockito.mock(ProjectService.class); - Mockito.when(projectService.getProject(Matchers.anyLong())).thenReturn(null); + Mockito.when(projectService.getProject(ArgumentMatchers.anyLong())).thenReturn(null); activateProjectCmd._projectService = projectService; try { @@ -74,9 +74,9 @@ public class ActivateProjectCmdTest extends TestCase { ProjectService projectService = Mockito.mock(ProjectService.class); Account account = Mockito.mock(Account.class); Mockito.when(account.getId()).thenReturn(2L); - Mockito.when(projectService.getProject(Matchers.anyLong())).thenReturn(project); + Mockito.when(projectService.getProject(ArgumentMatchers.anyLong())).thenReturn(project); - Mockito.when(projectService.getProjectOwner(Matchers.anyLong())).thenReturn(account); + Mockito.when(projectService.getProjectOwner(ArgumentMatchers.anyLong())).thenReturn(account); activateProjectCmd._projectService = projectService; Assert.assertEquals(2L, activateProjectCmd.getEntityOwnerId()); diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/AddAccountToProjectCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/AddAccountToProjectCmdTest.java index 199ee00551d..f100822b8c7 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/AddAccountToProjectCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/AddAccountToProjectCmdTest.java @@ -23,7 +23,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.mockito.Matchers; +import org.mockito.ArgumentMatchers; import org.mockito.Mockito; import org.apache.cloudstack.api.command.user.account.AddAccountToProjectCmd; @@ -101,9 +101,9 @@ public class AddAccountToProjectCmdTest extends TestCase { Account account = Mockito.mock(Account.class); Mockito.when(account.getId()).thenReturn(2L); - Mockito.when(projectService.getProject(Matchers.anyLong())).thenReturn(project); + Mockito.when(projectService.getProject(ArgumentMatchers.anyLong())).thenReturn(project); - Mockito.when(projectService.getProjectOwner(Matchers.anyLong())).thenReturn(account); + Mockito.when(projectService.getProjectOwner(ArgumentMatchers.anyLong())).thenReturn(account); addAccountToProjectCmd._projectService = projectService; Assert.assertEquals(2L, addAccountToProjectCmd.getEntityOwnerId()); diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java index d0cc8be716a..9ea3a6446e8 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/AddIpToVmNicTest.java @@ -21,7 +21,7 @@ import junit.framework.TestCase; import org.junit.Before; import org.junit.Test; -import org.mockito.Matchers; +import org.mockito.ArgumentMatchers; import org.mockito.Mockito; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.command.user.vm.AddIpToVmNicCmd; @@ -59,7 +59,7 @@ public class AddIpToVmNicTest extends TestCase { NicSecondaryIp secIp = Mockito.mock(NicSecondaryIp.class); Mockito.when( - networkService.allocateSecondaryGuestIP(Matchers.anyLong(), Matchers.any())) + networkService.allocateSecondaryGuestIP(ArgumentMatchers.anyLong(), ArgumentMatchers.any())) .thenReturn(secIp); ipTonicCmd._networkService = networkService; @@ -79,7 +79,7 @@ public class AddIpToVmNicTest extends TestCase { AddIpToVmNicCmd ipTonicCmd = Mockito.mock(AddIpToVmNicCmd.class); Mockito.when( - networkService.allocateSecondaryGuestIP(Matchers.anyLong(), Matchers.any())) + networkService.allocateSecondaryGuestIP(ArgumentMatchers.anyLong(), ArgumentMatchers.any())) .thenReturn(null); ipTonicCmd._networkService = networkService; @@ -98,7 +98,7 @@ public class AddIpToVmNicTest extends TestCase { NetworkService networkService = Mockito.mock(NetworkService.class); RemoveIpFromVmNicCmd removeIpFromNic = Mockito.mock(RemoveIpFromVmNicCmd.class); - Mockito.when(networkService.releaseSecondaryIpFromNic(Matchers.anyInt())).thenReturn(true); + Mockito.when(networkService.releaseSecondaryIpFromNic(ArgumentMatchers.anyInt())).thenReturn(true); removeIpFromNic._networkService = networkService; removeIpFromNic.execute(); @@ -109,7 +109,7 @@ public class AddIpToVmNicTest extends TestCase { NetworkService networkService = Mockito.mock(NetworkService.class); RemoveIpFromVmNicCmd removeIpFromNic = Mockito.mock(RemoveIpFromVmNicCmd.class); - Mockito.when(networkService.releaseSecondaryIpFromNic(Matchers.anyInt())).thenReturn(false); + Mockito.when(networkService.releaseSecondaryIpFromNic(ArgumentMatchers.anyInt())).thenReturn(false); removeIpFromNic._networkService = networkService; successResponseGenerator = Mockito.mock(SuccessResponse.class); diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/AddNetworkServiceProviderCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/AddNetworkServiceProviderCmdTest.java index 8760fc87556..a62c29e487a 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/AddNetworkServiceProviderCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/AddNetworkServiceProviderCmdTest.java @@ -26,7 +26,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.mockito.Matchers; +import org.mockito.ArgumentMatchers; import org.mockito.Mockito; import org.apache.cloudstack.api.ServerApiException; @@ -86,7 +86,7 @@ public class AddNetworkServiceProviderCmdTest extends TestCase { addNetworkServiceProviderCmd._networkService = networkService; PhysicalNetworkServiceProvider physicalNetworkServiceProvider = Mockito.mock(PhysicalNetworkServiceProvider.class); - Mockito.when(networkService.addProviderToPhysicalNetwork(Matchers.anyLong(), Matchers.anyString(), Matchers.anyLong(), Matchers.anyList())).thenReturn( + Mockito.when(networkService.addProviderToPhysicalNetwork(ArgumentMatchers.anyLong(), ArgumentMatchers.anyString(), ArgumentMatchers.anyLong(), ArgumentMatchers.anyList())).thenReturn( physicalNetworkServiceProvider); try { @@ -103,7 +103,7 @@ public class AddNetworkServiceProviderCmdTest extends TestCase { NetworkService networkService = Mockito.mock(NetworkService.class); addNetworkServiceProviderCmd._networkService = networkService; - Mockito.when(networkService.addProviderToPhysicalNetwork(Matchers.anyLong(), Matchers.anyString(), Matchers.anyLong(), Matchers.anyList())).thenReturn(null); + Mockito.when(networkService.addProviderToPhysicalNetwork(ArgumentMatchers.anyLong(), ArgumentMatchers.anyString(), ArgumentMatchers.anyLong(), ArgumentMatchers.anyList())).thenReturn(null); try { addNetworkServiceProviderCmd.create(); diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java index 46fd6905683..86a53787e08 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/AddSecondaryStorageCmdTest.java @@ -18,7 +18,7 @@ package org.apache.cloudstack.api.command.test; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyObject; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.isNull; @@ -86,7 +86,7 @@ public class AddSecondaryStorageCmdTest extends TestCase { StorageService resourceService = Mockito.mock(StorageService.class); addImageStoreCmd._storageService = resourceService; - Mockito.when(resourceService.discoverImageStore(anyString(), anyString(), anyString(), anyLong(), (Map)anyObject())) + Mockito.when(resourceService.discoverImageStore(anyString(), anyString(), anyString(), anyLong(), (Map)any())) .thenReturn(null); try { diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java index 0d3251a64df..34baebe5257 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java @@ -17,12 +17,13 @@ package org.apache.cloudstack.api.command.test; import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.isNull; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.isNull; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.cloudstack.api.ResponseGenerator; @@ -92,7 +93,7 @@ public class CreateSnapshotCmdTest extends TestCase { Snapshot snapshot = Mockito.mock(Snapshot.class); try { Mockito.when(volumeApiService.takeSnapshot(nullable(Long.class), nullable(Long.class), isNull(), - nullable(Account.class), nullable(Boolean.class), nullable(Snapshot.LocationType.class), nullable(Boolean.class), nullable(Map.class))).thenReturn(snapshot); + nullable(Account.class), nullable(Boolean.class), nullable(Snapshot.LocationType.class), nullable(Boolean.class), nullable(Map.class), nullable(List.class))).thenReturn(snapshot); } catch (Exception e) { Assert.fail("Received exception when success expected " + e.getMessage()); @@ -125,7 +126,7 @@ public class CreateSnapshotCmdTest extends TestCase { try { Mockito.when(volumeApiService.takeSnapshot(nullable(Long.class), nullable(Long.class), nullable(Long.class), - nullable(Account.class), nullable(Boolean.class), nullable(Snapshot.LocationType.class), nullable(Boolean.class), anyObject())).thenReturn(null); + nullable(Account.class), nullable(Boolean.class), nullable(Snapshot.LocationType.class), nullable(Boolean.class), any(), Mockito.anyList())).thenReturn(null); } catch (Exception e) { Assert.fail("Received exception when success expected " + e.getMessage()); } @@ -159,4 +160,14 @@ public class CreateSnapshotCmdTest extends TestCase { ReflectionTestUtils.setField(createSnapshotCmd, "tags", tagsParams); Assert.assertEquals(createSnapshotCmd.getTags(), expectedTags); } + + @Test + public void testGetZoneIds() { + final CreateSnapshotCmd cmd = new CreateSnapshotCmd(); + List ids = List.of(400L, 500L); + ReflectionTestUtils.setField(cmd, "zoneIds", ids); + Assert.assertEquals(ids.size(), cmd.getZoneIds().size()); + Assert.assertEquals(ids.get(0), cmd.getZoneIds().get(0)); + Assert.assertEquals(ids.get(1), cmd.getZoneIds().get(1)); + } } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/test/ResetVMUserDataCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/test/ResetVMUserDataCmdTest.java index afd5bd79827..50fe08d1030 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/test/ResetVMUserDataCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/test/ResetVMUserDataCmdTest.java @@ -24,18 +24,17 @@ import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.command.user.vm.ResetVMUserDataCmd; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.context.CallContext; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; import java.util.ArrayList; @@ -45,9 +44,7 @@ import java.util.Map; import static org.mockito.Mockito.when; -@RunWith(PowerMockRunner.class) -@PrepareForTest(CallContext.class) -@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) +@RunWith(MockitoJUnitRunner.class) public class ResetVMUserDataCmdTest { @InjectMocks @@ -66,14 +63,22 @@ public class ResetVMUserDataCmdTest { private static final long PROJECT_ID = 10L; private static final String ACCOUNT_NAME = "user"; + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); ReflectionTestUtils.setField(cmd, "accountName", ACCOUNT_NAME); ReflectionTestUtils.setField(cmd, "domainId", DOMAIN_ID); ReflectionTestUtils.setField(cmd, "projectId", PROJECT_ID); } + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test public void testValidResetVMUserDataExecute() { UserVm result = Mockito.mock(UserVm.class); @@ -95,22 +100,23 @@ public class ResetVMUserDataCmdTest { @Test public void validateArgsCmd() { - PowerMockito.mockStatic(CallContext.class); - CallContext callContextMock = PowerMockito.mock(CallContext.class); - PowerMockito.when(CallContext.current()).thenReturn(callContextMock); + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); - ReflectionTestUtils.setField(cmd, "id", 1L); - ReflectionTestUtils.setField(cmd, "userdataId", 2L); - ReflectionTestUtils.setField(cmd, "userData", "testUserdata"); + ReflectionTestUtils.setField(cmd, "id", 1L); + ReflectionTestUtils.setField(cmd, "userdataId", 2L); + ReflectionTestUtils.setField(cmd, "userData", "testUserdata"); - UserVm vm = Mockito.mock(UserVm.class); - when(_responseGenerator.findUserVmById(1L)).thenReturn(vm); - when(vm.getAccountId()).thenReturn(200L); + UserVm vm = Mockito.mock(UserVm.class); + when(_responseGenerator.findUserVmById(1L)).thenReturn(vm); + when(vm.getAccountId()).thenReturn(200L); - Assert.assertEquals(1L, (long)cmd.getId()); - Assert.assertEquals(2L, (long)cmd.getUserdataId()); - Assert.assertEquals("testUserdata", cmd.getUserData()); - Assert.assertEquals(200L, cmd.getEntityOwnerId()); + Assert.assertEquals(1L, (long) cmd.getId()); + Assert.assertEquals(2L, (long) cmd.getUserdataId()); + Assert.assertEquals("testUserdata", cmd.getUserData()); + Assert.assertEquals(200L, cmd.getEntityOwnerId()); + } } @Test diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmdTest.java new file mode 100644 index 00000000000..896a7a6c826 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/account/ListAccountsCmdTest.java @@ -0,0 +1,76 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.account; + +import java.util.List; + +import org.apache.cloudstack.api.response.AccountResponse; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import com.cloud.user.ResourceLimitService; + +@RunWith(MockitoJUnitRunner.class) +public class ListAccountsCmdTest { + + @Mock + ResourceLimitService resourceLimitService; + + + @Test + public void testGetShowIcon() { + ListAccountsCmd cmd = new ListAccountsCmd(); + ReflectionTestUtils.setField(cmd, "showIcon", null); + Assert.assertFalse(cmd.getShowIcon()); + ReflectionTestUtils.setField(cmd, "showIcon", false); + Assert.assertFalse(cmd.getShowIcon()); + ReflectionTestUtils.setField(cmd, "showIcon", true); + Assert.assertTrue(cmd.getShowIcon()); + } + + @Test + public void testGetTag() { + ListAccountsCmd cmd = new ListAccountsCmd(); + ReflectionTestUtils.setField(cmd, "tag", null); + Assert.assertNull(cmd.getTag()); + String tag = "ABC"; + ReflectionTestUtils.setField(cmd, "tag", tag); + Assert.assertEquals(tag, cmd.getTag()); + } + + @Test + public void testUpdateDomainResponseNoDomains() { + ListAccountsCmd cmd = new ListAccountsCmd(); + cmd._resourceLimitService = resourceLimitService; + cmd.updateAccountResponse(null); + Mockito.verify(resourceLimitService, Mockito.never()).updateTaggedResourceLimitsAndCountsForAccounts(Mockito.anyList(), Mockito.anyString()); + } + + @Test + public void testUpdateDomainResponseWithDomains() { + ListAccountsCmd cmd = new ListAccountsCmd(); + cmd._resourceLimitService = resourceLimitService; + ReflectionTestUtils.setField(cmd, "tag", "abc"); + cmd.updateAccountResponse(List.of(Mockito.mock(AccountResponse.class))); + Mockito.verify(resourceLimitService, Mockito.times(1)).updateTaggedResourceLimitsAndCountsForAccounts(Mockito.any(), Mockito.any()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmdTest.java index 6dcecc32a14..beba0c1da46 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmdTest.java @@ -20,29 +20,41 @@ import com.cloud.network.Network; import com.cloud.network.NetworkService; import com.cloud.utils.net.NetUtils; import org.apache.cloudstack.api.ServerApiException; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.Spy; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; import java.util.ArrayList; -@PrepareForTest(NetUtils.class) -@RunWith(PowerMockRunner.class) +@RunWith(MockitoJUnitRunner.class) public class CreateEgressFirewallRuleCmdTest { @Mock NetworkService networkServiceMock; @Spy - @InjectMocks CreateEgressFirewallRuleCmd cmdMock = new CreateEgressFirewallRuleCmd(); + MockedStatic netUtilsMocked; + + @Before + public void setUp() throws Exception { + ReflectionTestUtils.setField(cmdMock, "_networkService", networkServiceMock);; + netUtilsMocked = Mockito.mockStatic(NetUtils.class); + } + + @After + public void tearDown() throws Exception { + netUtilsMocked.close(); + } + @Test public void validateCidrsTestValidCidrs(){ ArrayList listMock = new ArrayList<>(); @@ -59,10 +71,9 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.doReturn(cidrMock).when(networkMock).getCidr(); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.isValidIp4Cidr(cidrMock)).thenReturn(true); - PowerMockito.when(NetUtils.isValidIp6Cidr(cidrMock)).thenReturn(false); - PowerMockito.when(NetUtils.isNetworkAWithinNetworkB(cidrMock,cidrMock)).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp4Cidr(cidrMock)).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp6Cidr(cidrMock)).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isNetworkAWithinNetworkB(cidrMock,cidrMock)).thenReturn(true); cmdMock.validateCidrs(); @@ -71,12 +82,9 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.verify(networkServiceMock).getNetwork(networkIdMock); Mockito.verify(networkMock).getCidr(); - PowerMockito.verifyStatic(NetUtils.class, Mockito.times(2)); - NetUtils.isValidIp4Cidr(cidrMock); - NetUtils.isValidIp6Cidr(cidrMock); - - PowerMockito.verifyStatic(NetUtils.class); - NetUtils.isNetworkAWithinNetworkB(cidrMock,cidrMock); + netUtilsMocked.verify(() -> NetUtils.isValidIp4Cidr(cidrMock), Mockito.times(2)); + netUtilsMocked.verify(() -> NetUtils.isValidIp6Cidr(cidrMock), Mockito.never()); + netUtilsMocked.verify(() -> NetUtils.isNetworkAWithinNetworkB(cidrMock,cidrMock), Mockito.times(1)); } @Test @@ -95,10 +103,9 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.doReturn("10.1.1.0/24").when(networkMock).getCidr(); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.isValidIp4Cidr(Mockito.eq("10.1.1.0/24"))).thenReturn(true); - PowerMockito.when(NetUtils.isValidIp6Cidr(Mockito.eq("10.1.1.0/24"))).thenReturn(false); - PowerMockito.when(NetUtils.isNetworkAWithinNetworkB(Mockito.eq("10.1.1.0/24"), Mockito.eq("10.1.1.0/24"))).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp4Cidr(Mockito.eq("10.1.1.0/24"))).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp6Cidr(Mockito.eq("10.1.1.0/24"))).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isNetworkAWithinNetworkB(Mockito.eq("10.1.1.0/24"), Mockito.eq("10.1.1.0/24"))).thenReturn(true); cmdMock.validateCidrs(); @@ -107,12 +114,10 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.verify(networkServiceMock).getNetwork(networkIdMock); Mockito.verify(networkMock).getCidr(); - PowerMockito.verifyStatic(NetUtils.class, Mockito.times(2)); - NetUtils.isValidIp4Cidr(Mockito.eq("10.1.1.0/24")); - NetUtils.isValidIp6Cidr(Mockito.eq("10.1.1.0/24")); + netUtilsMocked.verify(() -> NetUtils.isValidIp4Cidr(Mockito.eq("10.1.1.0/24")), Mockito.times(2)); + netUtilsMocked.verify(() -> NetUtils.isValidIp6Cidr(Mockito.eq("10.1.1.0/24")), Mockito.never()); - PowerMockito.verifyStatic(NetUtils.class); - NetUtils.isNetworkAWithinNetworkB(Mockito.eq("10.1.1.0/24"), Mockito.eq("10.1.1.0/24")); + netUtilsMocked.verify(() -> NetUtils.isNetworkAWithinNetworkB(Mockito.eq("10.1.1.0/24"), Mockito.eq("10.1.1.0/24"))); } @Test (expected = ServerApiException.class) @@ -131,9 +136,8 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.doReturn("10.1.1.0/24").when(networkMock).getCidr(); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.isValidIp4Cidr(sourceCidrMock)).thenReturn(false); - PowerMockito.when(NetUtils.isValidIp6Cidr(sourceCidrMock)).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isValidIp4Cidr(sourceCidrMock)).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isValidIp6Cidr(sourceCidrMock)).thenReturn(false); cmdMock.validateCidrs(); @@ -142,9 +146,8 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.verify(networkServiceMock).getNetwork(networkIdMock); Mockito.verify(networkMock).getCidr(); - PowerMockito.verifyStatic(NetUtils.class, Mockito.times(1)); - NetUtils.isValidIp4Cidr(sourceCidrMock); - NetUtils.isValidIp6Cidr(sourceCidrMock); + netUtilsMocked.verify(() -> NetUtils.isValidIp4Cidr(sourceCidrMock), Mockito.times(1)); + netUtilsMocked.verify(() -> NetUtils.isValidIp6Cidr(sourceCidrMock), Mockito.times(1)); } @Test (expected = ServerApiException.class) @@ -167,13 +170,12 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.doReturn(sourceCidrMock).when(networkMock).getCidr(); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.isValidIp4Cidr(Mockito.eq(sourceCidrMock))).thenReturn(true); - PowerMockito.when(NetUtils.isValidIp6Cidr(Mockito.eq(sourceCidrMock))).thenReturn(false); - PowerMockito.when(NetUtils.isNetworkAWithinNetworkB(sourceCidrMock, sourceCidrMock)).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp4Cidr(Mockito.eq(sourceCidrMock))).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp6Cidr(Mockito.eq(sourceCidrMock))).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isNetworkAWithinNetworkB(sourceCidrMock, sourceCidrMock)).thenReturn(true); - PowerMockito.when(NetUtils.isValidIp4Cidr(Mockito.eq(destCidrMock))).thenReturn(false); - PowerMockito.when(NetUtils.isValidIp6Cidr(Mockito.eq(destCidrMock))).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isValidIp4Cidr(Mockito.eq(destCidrMock))).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isValidIp6Cidr(Mockito.eq(destCidrMock))).thenReturn(false); cmdMock.validateCidrs(); @@ -182,16 +184,14 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.verify(networkServiceMock).getNetwork(networkIdMock); Mockito.verify(networkMock).getCidr(); - PowerMockito.verifyStatic(NetUtils.class); - NetUtils.isValidIp4Cidr(sourceCidrMock); - NetUtils.isValidIp6Cidr(sourceCidrMock); + netUtilsMocked.verify(() -> NetUtils.isValidIp4Cidr(sourceCidrMock)); + netUtilsMocked.verify(() -> NetUtils.isValidIp6Cidr(sourceCidrMock)); - PowerMockito.verifyStatic(NetUtils.class); - NetUtils.isNetworkAWithinNetworkB(sourceCidrMock,sourceCidrMock); + netUtilsMocked.verify(() -> NetUtils.isNetworkAWithinNetworkB(sourceCidrMock, sourceCidrMock)); - PowerMockito.verifyStatic(NetUtils.class); - NetUtils.isValidIp4Cidr(destCidrMock); - NetUtils.isValidIp6Cidr(destCidrMock); + + netUtilsMocked.verify(() -> NetUtils.isValidIp4Cidr(destCidrMock)); + netUtilsMocked.verify(() -> NetUtils.isValidIp6Cidr(destCidrMock)); } @Test @@ -214,12 +214,11 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.doReturn(sourceCidrMock).when(networkMock).getCidr(); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.isValidIp4Cidr(Mockito.eq(sourceCidrMock))).thenReturn(true); - PowerMockito.when(NetUtils.isValidIp6Cidr(Mockito.eq(sourceCidrMock))).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isValidIp4Cidr(Mockito.eq(sourceCidrMock))).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp6Cidr(Mockito.eq(sourceCidrMock))).thenReturn(false); - PowerMockito.when(NetUtils.isValidIp4Cidr(Mockito.eq(destCidrMock))).thenReturn(true); - PowerMockito.when(NetUtils.isValidIp6Cidr(Mockito.eq(destCidrMock))).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isValidIp4Cidr(Mockito.eq(destCidrMock))).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp6Cidr(Mockito.eq(destCidrMock))).thenReturn(false); cmdMock.validateCidrs(); @@ -228,16 +227,13 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.verify(networkServiceMock).getNetwork(networkIdMock); Mockito.verify(networkMock).getCidr(); - PowerMockito.verifyStatic(NetUtils.class); - NetUtils.isValidIp4Cidr(sourceCidrMock); - NetUtils.isValidIp6Cidr(sourceCidrMock); + netUtilsMocked.verify(() -> NetUtils.isValidIp4Cidr(sourceCidrMock), Mockito.times(1)); + netUtilsMocked.verify(() -> NetUtils.isValidIp6Cidr(sourceCidrMock), Mockito.never()); - PowerMockito.verifyStatic(NetUtils.class, Mockito.never()); - NetUtils.isNetworkAWithinNetworkB(sourceCidrMock,sourceCidrMock); + netUtilsMocked.verify(() -> NetUtils.isNetworkAWithinNetworkB(sourceCidrMock, sourceCidrMock), Mockito.never()); - PowerMockito.verifyStatic(NetUtils.class); - NetUtils.isValidIp4Cidr(destCidrMock); - NetUtils.isValidIp6Cidr(destCidrMock); + netUtilsMocked.verify(() -> NetUtils.isValidIp4Cidr(destCidrMock)); + netUtilsMocked.verify(() -> NetUtils.isValidIp6Cidr(destCidrMock), Mockito.never()); } @Test(expected = ServerApiException.class) @@ -256,10 +252,9 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.doReturn(cidrMock).when(networkMock).getCidr(); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.isValidIp4Cidr(cidrMock)).thenReturn(true); - PowerMockito.when(NetUtils.isValidIp6Cidr(cidrMock)).thenReturn(false); - PowerMockito.when(NetUtils.isNetworkAWithinNetworkB(cidrMock, cidrMock)).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isValidIp4Cidr(cidrMock)).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp6Cidr(cidrMock)).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isNetworkAWithinNetworkB(cidrMock, cidrMock)).thenReturn(false); cmdMock.validateCidrs(); @@ -268,12 +263,10 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.verify(networkServiceMock).getNetwork(networkIdMock); Mockito.verify(networkMock).getCidr(); - PowerMockito.verifyStatic(NetUtils.class, Mockito.times(1)); - NetUtils.isValidIp4Cidr(cidrMock); - NetUtils.isValidIp6Cidr(cidrMock); + netUtilsMocked.verify(() -> NetUtils.isValidIp4Cidr(cidrMock)); + netUtilsMocked.verify(() -> NetUtils.isValidIp6Cidr(cidrMock)); - PowerMockito.verifyStatic(NetUtils.class); - NetUtils.isNetworkAWithinNetworkB(cidrMock, cidrMock); + netUtilsMocked.verify(() -> NetUtils.isNetworkAWithinNetworkB(cidrMock, cidrMock)); } @Test @@ -291,10 +284,9 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.doReturn(sourceCidrMock).when(networkMock).getCidr(); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.isValidIp4Cidr(Mockito.eq(sourceCidrMock))).thenReturn(true); - PowerMockito.when(NetUtils.isValidIp6Cidr(Mockito.eq(sourceCidrMock))).thenReturn(false); - PowerMockito.when(NetUtils.isNetworkAWithinNetworkB(sourceCidrMock, sourceCidrMock)).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp4Cidr(Mockito.eq(sourceCidrMock))).thenReturn(true); + netUtilsMocked.when(() -> NetUtils.isValidIp6Cidr(Mockito.eq(sourceCidrMock))).thenReturn(false); + netUtilsMocked.when(() -> NetUtils.isNetworkAWithinNetworkB(sourceCidrMock, sourceCidrMock)).thenReturn(true); cmdMock.validateCidrs(); @@ -303,15 +295,12 @@ public class CreateEgressFirewallRuleCmdTest { Mockito.verify(networkServiceMock).getNetwork(networkIdMock); Mockito.verify(networkMock).getCidr(); - PowerMockito.verifyStatic(NetUtils.class); - NetUtils.isValidIp4Cidr(sourceCidrMock); - NetUtils.isValidIp6Cidr(sourceCidrMock); + netUtilsMocked.verify(() -> NetUtils.isValidIp4Cidr(sourceCidrMock)); + netUtilsMocked.verify(() -> NetUtils.isValidIp6Cidr(sourceCidrMock), Mockito.never()); - PowerMockito.verifyStatic(NetUtils.class); - NetUtils.isNetworkAWithinNetworkB(sourceCidrMock,sourceCidrMock); + netUtilsMocked.verify(() -> NetUtils.isNetworkAWithinNetworkB(sourceCidrMock, sourceCidrMock)); - PowerMockito.verifyStatic(NetUtils.class, Mockito.never()); - NetUtils.isValidIp4Cidr(null); - NetUtils.isValidIp6Cidr(null); + netUtilsMocked.verify(() -> NetUtils.isValidIp4Cidr(null), Mockito.never()); + netUtilsMocked.verify(() -> NetUtils.isValidIp6Cidr(null), Mockito.never()); } } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/iso/ListIsosCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/iso/ListIsosCmdTest.java new file mode 100644 index 00000000000..cc8a31f3ea8 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/iso/ListIsosCmdTest.java @@ -0,0 +1,128 @@ +// 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.user.iso; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class ListIsosCmdTest { + + @InjectMocks + ListIsosCmd cmd; + private AutoCloseable closeable; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test + public void testGetImageStoreId() { + ListIsosCmd cmd = new ListIsosCmd(); + assertNull(cmd.getImageStoreId()); + } + + @Test + public void testGetZoneId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "zoneId", id); + assertEquals(id, cmd.getZoneId()); + } + + @Test + public void testGetShowRemoved() { + Boolean showRemoved = true; + ReflectionTestUtils.setField(cmd, "showRemoved", showRemoved); + assertEquals(showRemoved, cmd.getShowRemoved()); + } + + @Test + public void testGetIsoName() { + String isoName = "test"; + ReflectionTestUtils.setField(cmd, "isoName", isoName); + assertEquals(isoName, cmd.getIsoName()); + } + + @Test + public void testGetIsoFilter() { + String isoFilter = "test"; + ReflectionTestUtils.setField(cmd, "isoFilter", isoFilter); + assertEquals(isoFilter, cmd.getIsoFilter()); + } + + @Test + public void testGetShowUnique() { + Boolean showUnique = true; + ReflectionTestUtils.setField(cmd, "showUnique", showUnique); + assertEquals(showUnique, cmd.getShowUnique()); + } + + @Test + public void testGetShowIcon() { + Boolean showIcon = true; + ReflectionTestUtils.setField(cmd, "showIcon", showIcon); + assertEquals(showIcon, cmd.getShowIcon()); + } + + @Test + public void testGetBootable() { + Boolean bootable = true; + ReflectionTestUtils.setField(cmd, "bootable", bootable); + assertEquals(bootable, cmd.isBootable()); + } + + @Test + public void testGetHypervisor() { + String hypervisor = "test"; + ReflectionTestUtils.setField(cmd, "hypervisor", hypervisor); + assertEquals(hypervisor, cmd.getHypervisor()); + } + + @Test + public void testGetId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "id", id); + assertEquals(id, cmd.getId()); + } + + @Test + public void testGetPublic() { + Boolean publicIso = true; + ReflectionTestUtils.setField(cmd, "publicIso", publicIso); + assertEquals(publicIso, cmd.isPublic()); + } + + @Test + public void testGetReady() { + Boolean ready = true; + ReflectionTestUtils.setField(cmd, "ready", ready); + assertEquals(ready, cmd.isReady()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmdTest.java index 55a41c61ce6..76836caef28 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/iso/RegisterIsoCmdTest.java @@ -21,7 +21,7 @@ import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; @RunWith(MockitoJUnitRunner.class) diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/network/ListNetworkProtocolsCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/network/ListNetworkProtocolsCmdTest.java new file mode 100644 index 00000000000..7c29de69ade --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/network/ListNetworkProtocolsCmdTest.java @@ -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.api.command.user.network; + +import com.cloud.utils.net.NetworkProtocols; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.NetworkProtocolResponse; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class ListNetworkProtocolsCmdTest { + + @Test + public void testListNetworkProtocolNumbers() { + ListNetworkProtocolsCmd cmd = new ListNetworkProtocolsCmd(); + String option = NetworkProtocols.Option.ProtocolNumber.toString(); + ReflectionTestUtils.setField(cmd, "option", option); + Assert.assertEquals(cmd.getOption(), option); + + try { + cmd.execute(); + } catch (Exception e) { + e.printStackTrace(); + } + Object response = cmd.getResponseObject(); + Assert.assertTrue(response instanceof ListResponse); + ListResponse listResponse = (ListResponse) response; + Assert.assertEquals(BaseCmd.getResponseNameByClass(cmd.getClass()), listResponse.getResponseName()); + Assert.assertNotNull(listResponse.getResponses()); + Assert.assertNotEquals(0, listResponse.getResponses().size()); + Object firstResponse = listResponse.getResponses().get(0); + Assert.assertTrue(firstResponse instanceof NetworkProtocolResponse); + Assert.assertEquals("networkprotocol", ((NetworkProtocolResponse) firstResponse).getObjectName()); + Assert.assertEquals(Integer.valueOf(0), ((NetworkProtocolResponse) firstResponse).getIndex()); + Assert.assertEquals("HOPOPT", ((NetworkProtocolResponse) firstResponse).getName()); + } + + @Test + public void testListIcmpTypes() { + ListNetworkProtocolsCmd cmd = new ListNetworkProtocolsCmd(); + String option = NetworkProtocols.Option.IcmpType.toString(); + ReflectionTestUtils.setField(cmd, "option", option); + Assert.assertEquals(cmd.getOption(), option); + + try { + cmd.execute(); + } catch (Exception e) { + e.printStackTrace(); + } + Object response = cmd.getResponseObject(); + Assert.assertTrue(response instanceof ListResponse); + ListResponse listResponse = (ListResponse) response; + Assert.assertEquals(BaseCmd.getResponseNameByClass(cmd.getClass()), listResponse.getResponseName()); + Assert.assertNotNull(listResponse.getResponses()); + Assert.assertNotEquals(0, listResponse.getResponses().size()); + Object firstResponse = listResponse.getResponses().get(0); + Assert.assertTrue(firstResponse instanceof NetworkProtocolResponse); + Assert.assertEquals("networkprotocol", ((NetworkProtocolResponse) firstResponse).getObjectName()); + Assert.assertEquals(Integer.valueOf(0), ((NetworkProtocolResponse) firstResponse).getIndex()); + Assert.assertNotNull(((NetworkProtocolResponse) firstResponse).getDetails()); + System.out.println(((NetworkProtocolResponse) firstResponse).getDetails()); + Assert.assertEquals("Echo reply", ((NetworkProtocolResponse) firstResponse).getDetails().get("0")); + } + + @Test(expected = IllegalArgumentException.class) + public void testListInvalidOption() { + ListNetworkProtocolsCmd cmd = new ListNetworkProtocolsCmd(); + String option = "invalid-option"; + ReflectionTestUtils.setField(cmd, "option", option); + Assert.assertEquals(cmd.getOption(), option); + + cmd.execute(); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmdTest.java new file mode 100644 index 00000000000..598fdd8ac4f --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/offering/ListDiskOfferingsCmdTest.java @@ -0,0 +1,37 @@ +// 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.user.offering; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class ListDiskOfferingsCmdTest { + + @Test + public void testGetVirtualMachineId() { + ListDiskOfferingsCmd cmd = new ListDiskOfferingsCmd(); + ReflectionTestUtils.setField(cmd, "virtualMachineId", null); + Assert.assertNull(cmd.getVirtualMachineId()); + Long id = 100L; + ReflectionTestUtils.setField(cmd, "virtualMachineId", id); + Assert.assertEquals(id, cmd.getVirtualMachineId()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmdTest.java new file mode 100644 index 00000000000..f408132e5fc --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/offering/ListServiceOfferingsCmdTest.java @@ -0,0 +1,38 @@ +// 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.user.offering; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + + +@RunWith(MockitoJUnitRunner.class) +public class ListServiceOfferingsCmdTest { + + @Test + public void testGetTemplateId() { + ListServiceOfferingsCmd cmd = new ListServiceOfferingsCmd(); + ReflectionTestUtils.setField(cmd, "templateId", null); + Assert.assertNull(cmd.getTemplateId()); + Long id = 100L; + ReflectionTestUtils.setField(cmd, "templateId", id); + Assert.assertEquals(id, cmd.getTemplateId()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/project/CreateProjectCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/project/CreateProjectCmdTest.java index ee3193123e0..dc1f2ca5189 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/project/CreateProjectCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/project/CreateProjectCmdTest.java @@ -21,7 +21,7 @@ import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; @RunWith(MockitoJUnitRunner.class) diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmdTest.java new file mode 100644 index 00000000000..3e999be2cfd --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/resource/ListResourceLimitsCmdTest.java @@ -0,0 +1,37 @@ +// 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.user.resource; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class ListResourceLimitsCmdTest { + + @Test + public void testGetTag() { + ListResourceLimitsCmd cmd = new ListResourceLimitsCmd(); + ReflectionTestUtils.setField(cmd, "tag", null); + Assert.assertNull(cmd.getTag()); + String tag = "ABC"; + ReflectionTestUtils.setField(cmd, "tag", tag); + Assert.assertEquals(tag, cmd.getTag()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmdTest.java new file mode 100644 index 00000000000..ab7d3253ab5 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmdTest.java @@ -0,0 +1,37 @@ +// 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.user.resource; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class UpdateResourceCountCmdTest { + + @Test + public void testGetTag() { + UpdateResourceCountCmd cmd = new UpdateResourceCountCmd(); + ReflectionTestUtils.setField(cmd, "tag", null); + Assert.assertNull(cmd.getTag()); + String tag = "ABC"; + ReflectionTestUtils.setField(cmd, "tag", tag); + Assert.assertEquals(tag, cmd.getTag()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmdTest.java new file mode 100644 index 00000000000..dff27a20044 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceLimitCmdTest.java @@ -0,0 +1,37 @@ +// 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.user.resource; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class UpdateResourceLimitCmdTest { + + @Test + public void testGetTag() { + UpdateResourceLimitCmd cmd = new UpdateResourceLimitCmd(); + ReflectionTestUtils.setField(cmd, "tag", null); + Assert.assertNull(cmd.getTag()); + String tag = "ABC"; + ReflectionTestUtils.setField(cmd, "tag", tag); + Assert.assertEquals(tag, cmd.getTag()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/CopySnapshotCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/CopySnapshotCmdTest.java new file mode 100644 index 00000000000..632496ad215 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/CopySnapshotCmdTest.java @@ -0,0 +1,133 @@ +// 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.user.snapshot; + +import java.util.List; +import java.util.UUID; + +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SnapshotResponse; +import org.apache.cloudstack.query.QueryService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import com.cloud.dc.DataCenter; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.storage.Snapshot; +import com.cloud.storage.snapshot.SnapshotApiService; +import com.cloud.utils.db.UUIDManager; + +@RunWith(MockitoJUnitRunner.class) +public class CopySnapshotCmdTest { + + @Test + public void testGetId() { + final CopySnapshotCmd cmd = new CopySnapshotCmd(); + Long id = 100L; + ReflectionTestUtils.setField(cmd, "id", id); + Assert.assertEquals(id, cmd.getId()); + } + + @Test + public void testGetSourceZoneId() { + final CopySnapshotCmd cmd = new CopySnapshotCmd(); + Long id = 200L; + ReflectionTestUtils.setField(cmd, "sourceZoneId", id); + Assert.assertEquals(id, cmd.getSourceZoneId()); + } + + @Test + public void testGetDestZoneIdWithSingleId() { + final CopySnapshotCmd cmd = new CopySnapshotCmd(); + Long id = 300L; + ReflectionTestUtils.setField(cmd, "destZoneId", id); + Assert.assertEquals(1, cmd.getDestinationZoneIds().size()); + Assert.assertEquals(id, cmd.getDestinationZoneIds().get(0)); + } + + @Test + public void testGetDestZoneIdWithMultipleId() { + final CopySnapshotCmd cmd = new CopySnapshotCmd(); + List ids = List.of(400L, 500L); + ReflectionTestUtils.setField(cmd, "destZoneIds", ids); + Assert.assertEquals(ids.size(), cmd.getDestinationZoneIds().size()); + Assert.assertEquals(ids.get(0), cmd.getDestinationZoneIds().get(0)); + Assert.assertEquals(ids.get(1), cmd.getDestinationZoneIds().get(1)); + } + + @Test + public void testGetDestZoneIdWithBothParams() { + final CopySnapshotCmd cmd = new CopySnapshotCmd(); + List ids = List.of(400L, 500L); + ReflectionTestUtils.setField(cmd, "destZoneIds", ids); + ReflectionTestUtils.setField(cmd, "destZoneId", 100L); + Assert.assertEquals(ids.size(), cmd.getDestinationZoneIds().size()); + Assert.assertEquals(ids.get(0), cmd.getDestinationZoneIds().get(0)); + Assert.assertEquals(ids.get(1), cmd.getDestinationZoneIds().get(1)); + } + + @Test (expected = ServerApiException.class) + public void testExecuteWrongNoParams() { + final CopySnapshotCmd cmd = new CopySnapshotCmd(); + try { + cmd.execute(); + } catch (ResourceUnavailableException e) { + Assert.fail(String.format("Exception: %s", e.getMessage())); + } + } + + @Test (expected = ServerApiException.class) + public void testExecuteWrongBothParams() { + final CopySnapshotCmd cmd = new CopySnapshotCmd(); + List ids = List.of(400L, 500L); + ReflectionTestUtils.setField(cmd, "destZoneIds", ids); + ReflectionTestUtils.setField(cmd, "destZoneId", 100L); + try { + cmd.execute(); + } catch (ResourceUnavailableException e) { + Assert.fail(String.format("Exception: %s", e.getMessage())); + } + } + + @Test + public void testExecuteSuccess() { + SnapshotApiService snapshotApiService = Mockito.mock(SnapshotApiService.class); + QueryService queryService = Mockito.mock(QueryService.class); + UUIDManager uuidManager = Mockito.mock(UUIDManager.class); + final CopySnapshotCmd cmd = new CopySnapshotCmd(); + cmd._snapshotService = snapshotApiService; + cmd._queryService = queryService; + cmd._uuidMgr = uuidManager; + Snapshot snapshot = Mockito.mock(Snapshot.class); + final Long id = 100L; + ReflectionTestUtils.setField(cmd, "destZoneId", id); + SnapshotResponse snapshotResponse = Mockito.mock(SnapshotResponse.class); + try { + Mockito.when(snapshotApiService.copySnapshot(cmd)).thenReturn(snapshot); + Mockito.when(queryService.listSnapshot(cmd)).thenReturn(snapshotResponse); + Mockito.when(uuidManager.getUuid(DataCenter.class, id)).thenReturn(UUID.randomUUID().toString()); + cmd.execute(); + } catch (ResourceAllocationException | ResourceUnavailableException e) { + Assert.fail(String.format("Exception: %s", e.getMessage())); + } + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmdTest.java index 111ac7081e1..258f29e8ad6 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmdTest.java @@ -17,6 +17,7 @@ package org.apache.cloudstack.api.command.user.snapshot; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.junit.Assert; @@ -43,4 +44,14 @@ public class CreateSnapshotPolicyCmdTest { ReflectionTestUtils.setField(createSnapshotPolicyCmd, "tags", tagsParams); Assert.assertEquals(createSnapshotPolicyCmd.getTags(), expectedTags); } + + @Test + public void testGetZoneIds() { + final CreateSnapshotPolicyCmd cmd = new CreateSnapshotPolicyCmd(); + List ids = List.of(400L, 500L); + ReflectionTestUtils.setField(cmd, "zoneIds", ids); + Assert.assertEquals(ids.size(), cmd.getZoneIds().size()); + Assert.assertEquals(ids.get(0), cmd.getZoneIds().get(0)); + Assert.assertEquals(ids.get(1), cmd.getZoneIds().get(1)); + } } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmdTest.java new file mode 100644 index 00000000000..48c4279a1da --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmdTest.java @@ -0,0 +1,32 @@ +// 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.user.snapshot; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +public class DeleteSnapshotCmdTest { + + @Test + public void testGetZoneId() { + final DeleteSnapshotCmd cmd = new DeleteSnapshotCmd(); + Long id = 400L; + ReflectionTestUtils.setField(cmd, "zoneId", id); + Assert.assertEquals(id, cmd.getZoneId()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmdTest.java new file mode 100644 index 00000000000..c882691cb43 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmdTest.java @@ -0,0 +1,60 @@ +// 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.user.snapshot; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +public class ListSnapshotsCmdTest { + + @Test + public void testIsShowUniqueNoValue() { + final ListSnapshotsCmd cmd = new ListSnapshotsCmd(); + Assert.assertTrue(cmd.isShowUnique()); + } + + @Test + public void testIsShowUniqueFalse() { + final ListSnapshotsCmd cmd = new ListSnapshotsCmd(); + ReflectionTestUtils.setField(cmd, "showUnique", false); + Assert.assertFalse(cmd.isShowUnique()); + } + + @Test + public void testIsShowUniqueTrue() { + final ListSnapshotsCmd cmd = new ListSnapshotsCmd(); + ReflectionTestUtils.setField(cmd, "showUnique", true); + Assert.assertTrue(cmd.isShowUnique()); + } + + @Test + public void testGetLocationTypeNoUnique() { + final ListSnapshotsCmd cmd = new ListSnapshotsCmd(); + ReflectionTestUtils.setField(cmd, "locationType", "primary"); + Assert.assertNull(cmd.getLocationType()); + } + + @Test + public void testGetLocationTypeUnique() { + final ListSnapshotsCmd cmd = new ListSnapshotsCmd(); + ReflectionTestUtils.setField(cmd, "showUnique", false); + String value = "secondary"; + ReflectionTestUtils.setField(cmd, "locationType", value); + Assert.assertEquals(value, cmd.getLocationType()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmdByAdminTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmdByAdminTest.java index 8639e135599..29b6144fd07 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmdByAdminTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmdByAdminTest.java @@ -28,7 +28,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import java.util.ArrayList; diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmdTest.java index 269a7b8a9e6..fb55e86dc0c 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/template/CopyTemplateCmdTest.java @@ -26,7 +26,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import java.util.ArrayList; diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmdTest.java new file mode 100644 index 00000000000..55e9c8dba1e --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmdTest.java @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.template; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +public class CreateTemplateCmdTest { + + @Test + public void testGetZoneId() { + final CreateTemplateCmd cmd = new CreateTemplateCmd(); + Long id = 400L; + ReflectionTestUtils.setField(cmd, "zoneId", id); + Assert.assertEquals(id, cmd.getZoneId()); + } + + @Test + public void testDomainId() { + final CreateTemplateCmd cmd = new CreateTemplateCmd(); + Long id = 2L; + ReflectionTestUtils.setField(cmd, "domainId", id); + Assert.assertEquals(id, cmd.getDomainId()); + } + + @Test + public void testGetAccountName() { + final CreateTemplateCmd cmd = new CreateTemplateCmd(); + String accountName = "user1"; + ReflectionTestUtils.setField(cmd, "accountName", accountName); + Assert.assertEquals(accountName, cmd.getAccountName()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/template/ListTemplatesCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/template/ListTemplatesCmdTest.java new file mode 100644 index 00000000000..c48ca47db7c --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/template/ListTemplatesCmdTest.java @@ -0,0 +1,94 @@ +// 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.user.template; + +import org.apache.cloudstack.api.command.user.iso.ListIsosCmd; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class ListTemplatesCmdTest { + + @InjectMocks + ListTemplatesCmd cmd; + private AutoCloseable closeable; + + @Before + public void setUp() throws Exception { + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test + public void testGetImageStoreId() { + ListIsosCmd cmd = new ListIsosCmd(); + assertNull(cmd.getImageStoreId()); + } + + @Test + public void testGetZoneId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "zoneId", id); + assertEquals(id, cmd.getZoneId()); + } + + @Test + public void testGetShowRemoved() { + Boolean showRemoved = true; + ReflectionTestUtils.setField(cmd, "showRemoved", showRemoved); + assertEquals(showRemoved, cmd.getShowRemoved()); + } + + @Test + public void testGetShowUnique() { + Boolean showUnique = true; + ReflectionTestUtils.setField(cmd, "showUnique", showUnique); + assertEquals(showUnique, cmd.getShowUnique()); + } + + @Test + public void testGetShowIcon() { + Boolean showIcon = true; + ReflectionTestUtils.setField(cmd, "showIcon", showIcon); + assertEquals(showIcon, cmd.getShowIcon()); + } + + @Test + public void testGetHypervisor() { + String hypervisor = "test"; + ReflectionTestUtils.setField(cmd, "hypervisor", hypervisor); + assertEquals(hypervisor, cmd.getHypervisor()); + } + + @Test + public void testGetId() { + Long id = 1234L; + ReflectionTestUtils.setField(cmd, "id", id); + assertEquals(id, cmd.getId()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmdByAdminTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmdByAdminTest.java index 1ba7963b2b9..1dc05888608 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmdByAdminTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmdByAdminTest.java @@ -29,7 +29,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import java.util.ArrayList; @RunWith(MockitoJUnitRunner.class) diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmdTest.java index 0c31e501519..a063f6c2d6b 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmdTest.java @@ -29,7 +29,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; import java.util.ArrayList; diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmdTest.java new file mode 100644 index 00000000000..03e558b58a8 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/template/UpdateTemplateCmdTest.java @@ -0,0 +1,49 @@ +// 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.user.template; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import com.cloud.storage.Storage; + +@RunWith(MockitoJUnitRunner.class) +public class UpdateTemplateCmdTest { + + @Test + public void testGetTemplateType() { + UpdateTemplateCmd cmd = new UpdateTemplateCmd(); + ReflectionTestUtils.setField(cmd, "templateType", null); + Assert.assertNull(cmd.getTemplateType()); + String type = Storage.TemplateType.ROUTING.toString(); + ReflectionTestUtils.setField(cmd, "templateTag", type); + Assert.assertEquals(type, cmd.getTemplateTag()); + } + + @Test + public void testGetTemplateTag() { + UpdateTemplateCmd cmd = new UpdateTemplateCmd(); + ReflectionTestUtils.setField(cmd, "templateTag", null); + Assert.assertNull(cmd.getTemplateTag()); + String tag = "ABC"; + ReflectionTestUtils.setField(cmd, "templateTag", tag); + Assert.assertEquals(tag, cmd.getTemplateTag()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/DeleteUserDataCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/DeleteUserDataCmdTest.java index fbaf46f1a28..255c9f4ca12 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/DeleteUserDataCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/DeleteUserDataCmdTest.java @@ -22,23 +22,20 @@ import com.cloud.user.AccountService; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; -@RunWith(PowerMockRunner.class) -@PrepareForTest(CallContext.class) -@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) +@RunWith(MockitoJUnitRunner.class) public class DeleteUserDataCmdTest { @InjectMocks @@ -53,14 +50,21 @@ public class DeleteUserDataCmdTest { private static final long PROJECT_ID = 10L; private static final String ACCOUNT_NAME = "user"; + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); ReflectionTestUtils.setField(cmd, "accountName", ACCOUNT_NAME); ReflectionTestUtils.setField(cmd, "domainId", DOMAIN_ID); ReflectionTestUtils.setField(cmd, "projectId", PROJECT_ID); } + @After + public void tearDown() throws Exception { + closeable.close(); + } + @Test public void testValidUserDataExecute() { Mockito.doReturn(true).when(_mgr).deleteUserData(cmd); @@ -81,18 +85,18 @@ public class DeleteUserDataCmdTest { @Test public void validateArgsCmd() { - PowerMockito.mockStatic(CallContext.class); - CallContext callContextMock = PowerMockito.mock(CallContext.class); - PowerMockito.when(CallContext.current()).thenReturn(callContextMock); - Account accountMock = PowerMockito.mock(Account.class); - PowerMockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); - Mockito.when(accountMock.getId()).thenReturn(2L); - Mockito.doReturn(false).when(_accountService).isAdmin(2L); + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + Account accountMock = Mockito.mock(Account.class); + Mockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); + Mockito.when(accountMock.getId()).thenReturn(2L); + Mockito.doReturn(false).when(_accountService).isAdmin(2L); - ReflectionTestUtils.setField(cmd, "id", 1L); + ReflectionTestUtils.setField(cmd, "id", 1L); - Assert.assertEquals(1L, (long)cmd.getId()); - Assert.assertEquals(2L, cmd.getEntityOwnerId()); + Assert.assertEquals(1L, (long) cmd.getId()); + Assert.assertEquals(2L, cmd.getEntityOwnerId()); + } } - } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/LinkUserDataToTemplateCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/LinkUserDataToTemplateCmdTest.java index c5581ed5a11..b431c7cc205 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/LinkUserDataToTemplateCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/LinkUserDataToTemplateCmdTest.java @@ -20,29 +20,25 @@ package org.apache.cloudstack.api.command.user.userdata; import com.cloud.storage.Storage; import com.cloud.template.TemplateApiService; import com.cloud.template.VirtualMachineTemplate; -import com.cloud.user.Account; import com.cloud.user.UserData; import com.cloud.utils.db.EntityManager; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.context.CallContext; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; -@RunWith(PowerMockRunner.class) -@PrepareForTest(CallContext.class) -@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) +@RunWith(MockitoJUnitRunner.class) public class LinkUserDataToTemplateCmdTest { @Mock @@ -60,9 +56,16 @@ public class LinkUserDataToTemplateCmdTest { @Mock VirtualMachineTemplate virtualMachineTemplate; + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); } @Test @@ -84,21 +87,19 @@ public class LinkUserDataToTemplateCmdTest { @Test public void validateArgsCmd() { - PowerMockito.mockStatic(CallContext.class); - CallContext callContextMock = PowerMockito.mock(CallContext.class); - PowerMockito.when(CallContext.current()).thenReturn(callContextMock); - Account accountMock = PowerMockito.mock(Account.class); - PowerMockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); - Mockito.when(accountMock.getId()).thenReturn(2L); - ReflectionTestUtils.setField(cmd, "templateId", 1L); - ReflectionTestUtils.setField(cmd, "userdataId", 3L); + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + ReflectionTestUtils.setField(cmd, "templateId", 1L); + ReflectionTestUtils.setField(cmd, "userdataId", 3L); - Mockito.doReturn(virtualMachineTemplate).when(_entityMgr).findById(VirtualMachineTemplate.class, cmd.getTemplateId()); - PowerMockito.when(virtualMachineTemplate.getAccountId()).thenReturn(1L); + Mockito.doReturn(virtualMachineTemplate).when(_entityMgr).findById(VirtualMachineTemplate.class, cmd.getTemplateId()); + Mockito.when(virtualMachineTemplate.getAccountId()).thenReturn(1L); - Assert.assertEquals(1L, (long)cmd.getTemplateId()); - Assert.assertEquals(3L, (long)cmd.getUserdataId()); - Assert.assertEquals(1L, cmd.getEntityOwnerId()); + Assert.assertEquals(1L, (long) cmd.getTemplateId()); + Assert.assertEquals(3L, (long) cmd.getUserdataId()); + Assert.assertEquals(1L, cmd.getEntityOwnerId()); + } } @Test diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/ListUserDataCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/ListUserDataCmdTest.java index fd3b1a7a320..3f47a078445 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/ListUserDataCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/ListUserDataCmdTest.java @@ -20,10 +20,10 @@ import com.cloud.server.ManagementService; import com.cloud.user.UserData; import com.cloud.utils.Pair; import org.apache.cloudstack.api.response.ListResponse; +import org.junit.After; import org.junit.Assert; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.response.UserDataResponse; -import org.apache.cloudstack.context.CallContext; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -31,16 +31,12 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; import java.util.ArrayList; import java.util.List; -@RunWith(PowerMockRunner.class) -@PrepareForTest(CallContext.class) -@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) +@RunWith(MockitoJUnitRunner.class) public class ListUserDataCmdTest { @InjectMocks @@ -52,9 +48,16 @@ public class ListUserDataCmdTest { @Mock ResponseGenerator _responseGenerator; + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); } @Test diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmdTest.java index 901ec8477fb..e9605526f86 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmdTest.java @@ -18,31 +18,27 @@ package org.apache.cloudstack.api.command.user.userdata; import com.cloud.exception.InvalidParameterValueException; import com.cloud.server.ManagementService; -import com.cloud.user.Account; import com.cloud.user.AccountService; import com.cloud.user.UserData; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.response.UserDataResponse; import org.apache.cloudstack.context.CallContext; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; import static org.mockito.Mockito.when; -@RunWith(PowerMockRunner.class) -@PrepareForTest(CallContext.class) -@PowerMockIgnore({"javax.xml.*", "org.w3c.dom.*", "org.apache.xerces.*", "org.xml.*"}) +@RunWith(MockitoJUnitRunner.class) public class RegisterUserDataCmdTest { @InjectMocks @@ -61,14 +57,22 @@ public class RegisterUserDataCmdTest { private static final long PROJECT_ID = 10L; private static final String ACCOUNT_NAME = "user"; + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); ReflectionTestUtils.setField(cmd, "accountName", ACCOUNT_NAME); ReflectionTestUtils.setField(cmd, "domainId", DOMAIN_ID); ReflectionTestUtils.setField(cmd, "projectId", PROJECT_ID); } + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test public void testValidUserDataExecute() { UserData result = Mockito.mock(UserData.class); @@ -87,20 +91,18 @@ public class RegisterUserDataCmdTest { @Test public void validateArgsCmd() { - PowerMockito.mockStatic(CallContext.class); - CallContext callContextMock = PowerMockito.mock(CallContext.class); - PowerMockito.when(CallContext.current()).thenReturn(callContextMock); - Account accountMock = PowerMockito.mock(Account.class); - PowerMockito.when(callContextMock.getCallingAccount()).thenReturn(accountMock); - Mockito.when(accountMock.getId()).thenReturn(2L); - ReflectionTestUtils.setField(cmd, "name", "testUserdataName"); - ReflectionTestUtils.setField(cmd, "userData", "testUserdata"); + try (MockedStatic callContextMocked = Mockito.mockStatic(CallContext.class)) { + CallContext callContextMock = Mockito.mock(CallContext.class); + callContextMocked.when(CallContext::current).thenReturn(callContextMock); + ReflectionTestUtils.setField(cmd, "name", "testUserdataName"); + ReflectionTestUtils.setField(cmd, "userData", "testUserdata"); - when(_accountService.finalyzeAccountId(ACCOUNT_NAME, DOMAIN_ID, PROJECT_ID, true)).thenReturn(200L); + when(_accountService.finalyzeAccountId(ACCOUNT_NAME, DOMAIN_ID, PROJECT_ID, true)).thenReturn(200L); - Assert.assertEquals("testUserdataName", cmd.getName()); - Assert.assertEquals("testUserdata", cmd.getUserData()); - Assert.assertEquals(200L, cmd.getEntityOwnerId()); + Assert.assertEquals("testUserdataName", cmd.getName()); + Assert.assertEquals("testUserdata", cmd.getUserData()); + Assert.assertEquals(200L, cmd.getEntityOwnerId()); + } } @Test(expected = InvalidParameterValueException.class) diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmdTest.java index 2fdef2acaa9..c9eb672c9e9 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmdTest.java @@ -23,6 +23,7 @@ import com.cloud.utils.db.EntityManager; import com.cloud.vm.VirtualMachine; import org.apache.cloudstack.api.response.VMScheduleResponse; import org.apache.cloudstack.vm.schedule.VMScheduleManager; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -41,9 +42,16 @@ public class CreateVMScheduleCmdTest { @InjectMocks private CreateVMScheduleCmd createVMScheduleCmd = new CreateVMScheduleCmd(); + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); } /** diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/vm/DeleteVMScheduleCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/vm/DeleteVMScheduleCmdTest.java index 6adfc2b905c..9b4decc83aa 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/vm/DeleteVMScheduleCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/vm/DeleteVMScheduleCmdTest.java @@ -25,6 +25,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.vm.schedule.VMSchedule; import org.apache.cloudstack.vm.schedule.VMScheduleManager; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -44,9 +45,16 @@ public class DeleteVMScheduleCmdTest { @InjectMocks private DeleteVMScheduleCmd deleteVMScheduleCmd = new DeleteVMScheduleCmd(); + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); } /** diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/vm/ListVMScheduleCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/vm/ListVMScheduleCmdTest.java index 18657b4c397..f9a1d945f03 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/vm/ListVMScheduleCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/vm/ListVMScheduleCmdTest.java @@ -21,6 +21,7 @@ package org.apache.cloudstack.api.command.user.vm; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.VMScheduleResponse; import org.apache.cloudstack.vm.schedule.VMScheduleManager; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -38,10 +39,16 @@ public class ListVMScheduleCmdTest { public VMScheduleManager vmScheduleManager; @InjectMocks private ListVMScheduleCmd listVMScheduleCmd = new ListVMScheduleCmd(); + private AutoCloseable closeable; @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); } /** diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/vm/UpdateVMScheduleCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/vm/UpdateVMScheduleCmdTest.java index 044685b579c..5ce133382f3 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/vm/UpdateVMScheduleCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/vm/UpdateVMScheduleCmdTest.java @@ -24,6 +24,7 @@ import com.cloud.vm.VirtualMachine; import org.apache.cloudstack.api.response.VMScheduleResponse; import org.apache.cloudstack.vm.schedule.VMSchedule; import org.apache.cloudstack.vm.schedule.VMScheduleManager; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -42,9 +43,16 @@ public class UpdateVMScheduleCmdTest { @InjectMocks private UpdateVMScheduleCmd updateVMScheduleCmd = new UpdateVMScheduleCmd(); + private AutoCloseable closeable; + @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); } /** diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/volume/CheckAndRepairVolumeCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/volume/CheckAndRepairVolumeCmdTest.java new file mode 100644 index 00000000000..226ff882fa7 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/volume/CheckAndRepairVolumeCmdTest.java @@ -0,0 +1,63 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.user.volume; + +import com.cloud.exception.InvalidParameterValueException; +import junit.framework.TestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class CheckAndRepairVolumeCmdTest extends TestCase { + private CheckAndRepairVolumeCmd checkAndRepairVolumeCmd; + private AutoCloseable closeable; + + @Before + public void setup() { + closeable = MockitoAnnotations.openMocks(this); + checkAndRepairVolumeCmd = new CheckAndRepairVolumeCmd(); + } + + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test + public void testGetRepair() { + ReflectionTestUtils.setField(checkAndRepairVolumeCmd, "repair", "all"); + assertEquals("all", checkAndRepairVolumeCmd.getRepair()); + + ReflectionTestUtils.setField(checkAndRepairVolumeCmd, "repair", "LEAKS"); + assertEquals("leaks", checkAndRepairVolumeCmd.getRepair()); + + ReflectionTestUtils.setField(checkAndRepairVolumeCmd, "repair", null); + assertNull(checkAndRepairVolumeCmd.getRepair()); + } + + @Test(expected = InvalidParameterValueException.class) + public void testGetRepairInvalid() { + ReflectionTestUtils.setField(checkAndRepairVolumeCmd, "repair", "RANDOM STRING"); + checkAndRepairVolumeCmd.getRepair(); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmdTest.java index 17c8e2392ed..a28e9e9fd04 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmdTest.java @@ -30,14 +30,15 @@ import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.response.VpcResponse; import org.junit.Assert; +import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; -@RunWith(PowerMockRunner.class) +@RunWith(MockitoJUnitRunner.class) public class CreateVPCCmdTest extends TestCase { @Mock @@ -48,97 +49,107 @@ public class CreateVPCCmdTest extends TestCase { public AccountService _accountService; private ResponseGenerator responseGenerator; @InjectMocks - CreateVPCCmd cmd = new CreateVPCCmd() { - @Override - public Long getEntityId() { - return 2L; - } - }; + CreateVPCCmd cmd = new CreateVPCCmd(); + @Test public void testGetAccountName() { String accountName = "admin"; ReflectionTestUtils.setField(cmd, "accountName", accountName); Assert.assertEquals(cmd.getAccountName(), accountName); } + @Test public void testGetDomainId() { Long domainId = 1L; ReflectionTestUtils.setField(cmd, "domainId", domainId); Assert.assertEquals(cmd.getDomainId(), domainId); } + @Test public void testGetZoneId() { Long zoneId = 1L; ReflectionTestUtils.setField(cmd, "zoneId", zoneId); Assert.assertEquals(cmd.getZoneId(), zoneId); } + @Test public void testGetVpcName() { String vpcName = "vpcNet"; ReflectionTestUtils.setField(cmd, "vpcName", vpcName); Assert.assertEquals(cmd.getVpcName(), vpcName); } + @Test public void testGetCidr() { String cidr = "10.0.0.0/8"; ReflectionTestUtils.setField(cmd, "cidr", cidr); Assert.assertEquals(cmd.getCidr(), cidr); } + @Test public void testGetDisplayText() { String displayText = "VPC Network"; ReflectionTestUtils.setField(cmd, "displayText", displayText); Assert.assertEquals(cmd.getDisplayText(), displayText); } + @Test public void testGetVpcOffering() { Long vpcOffering = 1L; ReflectionTestUtils.setField(cmd, "vpcOffering", vpcOffering); Assert.assertEquals(cmd.getVpcOffering(), vpcOffering); } + @Test public void testGetNetworkDomain() { String netDomain = "cs1cloud.internal"; ReflectionTestUtils.setField(cmd, "networkDomain", netDomain); Assert.assertEquals(cmd.getNetworkDomain(), netDomain); } + @Test public void testGetPublicMtuWhenNotSet() { Integer publicMtu = null; ReflectionTestUtils.setField(cmd, "publicMtu", publicMtu); Assert.assertEquals(NetworkService.DEFAULT_MTU, cmd.getPublicMtu()); } + @Test public void testGetPublicMtuWhenSet() { Integer publicMtu = 1450; ReflectionTestUtils.setField(cmd, "publicMtu", publicMtu); Assert.assertEquals(cmd.getPublicMtu(), publicMtu); } + @Test public void testIsStartWhenNull() { Boolean start = null; ReflectionTestUtils.setField(cmd, "start", start); Assert.assertTrue(cmd.isStart()); } + @Test public void testIsStartWhenValidValuePassed() { Boolean start = true; ReflectionTestUtils.setField(cmd, "start", start); Assert.assertTrue(cmd.isStart()); } + @Test public void testGetDisplayVpc() { Boolean display = true; ReflectionTestUtils.setField(cmd, "display", display); Assert.assertTrue(cmd.getDisplayVpc()); } + @Test public void testGetDisplayTextWhenEmpty() { String netName = "net-vpc"; ReflectionTestUtils.setField(cmd, "vpcName", netName); Assert.assertEquals(cmd.getDisplayText(), netName); } + @Test public void testCreate() throws ResourceAllocationException { Vpc vpc = Mockito.mock(Vpc.class); ReflectionTestUtils.setField(cmd, "zoneId", 1L); @@ -149,23 +160,23 @@ public class CreateVPCCmdTest extends TestCase { ReflectionTestUtils.setField(cmd, "networkDomain", "cs1cloud.internal"); ReflectionTestUtils.setField(cmd, "display", true); ReflectionTestUtils.setField(cmd, "publicMtu", 1450); - Mockito.when(_accountService.finalyzeAccountId(Mockito.anyString(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyBoolean())).thenReturn(1L); - Mockito.when(cmd.getEntityOwnerId()).thenReturn(1L); Mockito.when(_vpcService.createVpc(Mockito.any(CreateVPCCmd.class))).thenReturn(vpc); cmd.create(); Mockito.verify(_vpcService, Mockito.times(1)).createVpc(Mockito.any(CreateVPCCmd.class)); } + @Test public void testExecute() throws ResourceUnavailableException, InsufficientCapacityException { - ReflectionTestUtils.setField(cmd, "start", true); Vpc vpc = Mockito.mock(Vpc.class); VpcResponse response = Mockito.mock(VpcResponse.class); + + ReflectionTestUtils.setField(cmd, "id", 1L); responseGenerator = Mockito.mock(ResponseGenerator.class); - Mockito.when(_vpcService.startVpc(1L, true)).thenReturn(true); + Mockito.doNothing().when(_vpcService).startVpc(cmd); Mockito.when(_entityMgr.findById(Mockito.eq(Vpc.class), Mockito.any(Long.class))).thenReturn(vpc); cmd._responseGenerator = responseGenerator; Mockito.when(responseGenerator.createVpcResponse(ResponseObject.ResponseView.Restricted, vpc)).thenReturn(response); cmd.execute(); - Mockito.verify(_vpcService, Mockito.times(1)).startVpc(Mockito.anyLong(), Mockito.anyBoolean()); + Mockito.verify(_vpcService, Mockito.times(1)).startVpc(cmd); } } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmdTest.java index d174d3694cd..acb2dc68597 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmdTest.java @@ -23,17 +23,17 @@ import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcService; import junit.framework.TestCase; import org.apache.cloudstack.api.ResponseGenerator; -import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.response.VpcResponse; import org.junit.Assert; +import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.util.ReflectionTestUtils; -@RunWith(PowerMockRunner.class) +@RunWith(MockitoJUnitRunner.class) public class UpdateVPCCmdTest extends TestCase { @Mock @@ -44,36 +44,42 @@ public class UpdateVPCCmdTest extends TestCase { @InjectMocks UpdateVPCCmd cmd = new UpdateVPCCmd(); + @Test public void testGetVpcName() { String vpcName = "updatedVpcName"; ReflectionTestUtils.setField(cmd, "vpcName", vpcName); Assert.assertEquals(cmd.getVpcName(), vpcName); } + @Test public void testGetDisplayText() { String displayText = "Updated VPC Name"; ReflectionTestUtils.setField(cmd, "displayText", displayText); Assert.assertEquals(cmd.getDisplayText(), displayText); } + @Test public void testGetId() { Long id = 1L; ReflectionTestUtils.setField(cmd, "id", id); Assert.assertEquals(cmd.getId(), id); } + @Test public void testIsDisplayVpc() { Boolean display = true; ReflectionTestUtils.setField(cmd, "display", display); Assert.assertEquals(cmd.isDisplayVpc(), display); } + @Test public void testGetPublicMtu() { Integer publicMtu = 1450; ReflectionTestUtils.setField(cmd, "publicMtu", publicMtu); Assert.assertEquals(cmd.getPublicMtu(), publicMtu); } + @Test public void testExecute() throws ResourceUnavailableException, InsufficientCapacityException { ReflectionTestUtils.setField(cmd, "id", 1L); ReflectionTestUtils.setField(cmd, "vpcName", "updatedVpcName"); @@ -86,9 +92,6 @@ public class UpdateVPCCmdTest extends TestCase { VpcResponse response = Mockito.mock(VpcResponse.class); responseGenerator = Mockito.mock(ResponseGenerator.class); cmd._responseGenerator = responseGenerator; - Mockito.when(_vpcService.updateVpc(Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), - Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyInt(), Mockito.anyString())).thenReturn(vpc); - Mockito.when(responseGenerator.createVpcResponse(ResponseObject.ResponseView.Full, vpc)).thenReturn(response); Mockito.verify(_vpcService, Mockito.times(0)).updateVpc(Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyInt(), Mockito.anyString()); diff --git a/api/src/test/java/org/apache/cloudstack/api/response/HostResponseTest.java b/api/src/test/java/org/apache/cloudstack/api/response/HostResponseTest.java index 523b3de9e3c..04e3ad7df60 100644 --- a/api/src/test/java/org/apache/cloudstack/api/response/HostResponseTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/response/HostResponseTest.java @@ -23,6 +23,8 @@ import org.junit.Test; import java.util.HashMap; import java.util.Map; +import com.cloud.hypervisor.Hypervisor; + public final class HostResponseTest extends TestCase { private static final String VALID_KEY = "validkey"; @@ -32,7 +34,7 @@ public final class HostResponseTest extends TestCase { public void testSetDetailsNull() { final HostResponse hostResponse = new HostResponse(); - hostResponse.setDetails(null); + hostResponse.setDetails(null, null); assertEquals(null, hostResponse.getDetails()); @@ -51,7 +53,7 @@ public final class HostResponseTest extends TestCase { final Map expectedDetails = new HashedMap(); expectedDetails.put(VALID_KEY, VALID_VALUE); - hostResponse.setDetails(details); + hostResponse.setDetails(details, Hypervisor.HypervisorType.KVM); final Map actualDetails = hostResponse.getDetails(); assertTrue(details != actualDetails); @@ -70,7 +72,7 @@ public final class HostResponseTest extends TestCase { final Map expectedDetails = new HashedMap(); expectedDetails.put(VALID_KEY, VALID_VALUE); - hostResponse.setDetails(details); + hostResponse.setDetails(details, Hypervisor.HypervisorType.KVM); final Map actualDetails = hostResponse.getDetails(); assertTrue(details != actualDetails); diff --git a/api/src/test/java/org/apache/cloudstack/api/response/VnfNicResponseTest.java b/api/src/test/java/org/apache/cloudstack/api/response/VnfNicResponseTest.java new file mode 100644 index 00000000000..cdfbf451e86 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/response/VnfNicResponseTest.java @@ -0,0 +1,54 @@ +// 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.response; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public final class VnfNicResponseTest { + + static long deviceId = 0L; + static String deviceName = "eth0"; + static boolean required = true; + static boolean management = false; + static String description = "description of vnf nic"; + + static String networkUuid = "networkuuid"; + static String networkName = "networkname"; + + @Test + public void testNewVnfNicResponse() { + final VnfNicResponse response = new VnfNicResponse(deviceId, deviceName, required, management, description); + Assert.assertEquals(deviceId, response.getDeviceId()); + Assert.assertEquals(deviceName, response.getName()); + Assert.assertEquals(required, response.isRequired()); + Assert.assertEquals(management, response.isManagement()); + Assert.assertEquals(description, response.getDescription()); + } + + @Test + public void testSetVnfNicResponse() { + final VnfNicResponse response = new VnfNicResponse(); + response.setNetworkId(networkUuid); + response.setNetworkName(networkName); + Assert.assertEquals(networkUuid, response.getNetworkId()); + Assert.assertEquals(networkName, response.getNetworkName()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/response/VnfTemplateResponseTest.java b/api/src/test/java/org/apache/cloudstack/api/response/VnfTemplateResponseTest.java new file mode 100644 index 00000000000..38875c07713 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/response/VnfTemplateResponseTest.java @@ -0,0 +1,47 @@ +// 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.response; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public final class VnfTemplateResponseTest { + + @Test + public void testAddVnfNicToResponse() { + final VnfTemplateResponse response = new VnfTemplateResponse(); + + response.addVnfNic(new VnfNicResponse()); + response.addVnfNic(new VnfNicResponse()); + + Assert.assertEquals(2, response.getVnfNics().size()); + } + + @Test + public void testAddVnfDetailToResponse() { + final VnfTemplateResponse response = new VnfTemplateResponse(); + + response.addVnfDetail("key1", "value1"); + response.addVnfDetail("key2", "value2"); + response.addVnfDetail("key3", "value3"); + + Assert.assertEquals(3, response.getVnfDetails().size()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/api/response/VolumeForImportResponseTest.java b/api/src/test/java/org/apache/cloudstack/api/response/VolumeForImportResponseTest.java new file mode 100644 index 00000000000..7d0538836bf --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/api/response/VolumeForImportResponseTest.java @@ -0,0 +1,77 @@ +// 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.response; + +import com.cloud.hypervisor.Hypervisor; +import com.cloud.storage.Storage; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.HashMap; +import java.util.Map; + +@RunWith(MockitoJUnitRunner.class) +public final class VolumeForImportResponseTest { + + private static String path = "path"; + private static String name = "name"; + private static String fullPath = "fullPath"; + private static String format = "qcow2"; + private static long size = 10; + private static long virtualSize = 20; + private static String encryptFormat = "LUKS"; + private static Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM; + private static String storagePoolId = "storage pool uuid"; + private static String storagePoolName = "storage pool 1"; + private static String storagePoolType = Storage.StoragePoolType.NetworkFilesystem.name(); + private static String chainInfo = "chain info"; + + @Test + public void testVolumeForImportResponse() { + final VolumeForImportResponse response = new VolumeForImportResponse(); + + response.setPath(path); + response.setName(name); + response.setFullPath(fullPath); + response.setFormat(format); + response.setSize(size); + response.setVirtualSize(virtualSize); + response.setQemuEncryptFormat(encryptFormat); + response.setStoragePoolType(storagePoolType); + response.setStoragePoolName(storagePoolName); + response.setStoragePoolId(storagePoolId); + response.setChainInfo(chainInfo); + Map details = new HashMap<>(); + details.put("key", "value"); + response.setDetails(details); + + Assert.assertEquals(path, response.getPath()); + Assert.assertEquals(name, response.getName()); + Assert.assertEquals(fullPath, response.getFullPath()); + Assert.assertEquals(format, response.getFormat()); + Assert.assertEquals(size, response.getSize()); + Assert.assertEquals(virtualSize, response.getVirtualSize()); + Assert.assertEquals(encryptFormat, response.getQemuEncryptFormat()); + Assert.assertEquals(storagePoolType, response.getStoragePoolType()); + Assert.assertEquals(storagePoolName, response.getStoragePoolName()); + Assert.assertEquals(storagePoolId, response.getStoragePoolId()); + Assert.assertEquals(chainInfo, response.getChainInfo()); + Assert.assertEquals(details, response.getDetails()); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/cluster/ClusterDrsAlgorithmTest.java b/api/src/test/java/org/apache/cloudstack/cluster/ClusterDrsAlgorithmTest.java new file mode 100644 index 00000000000..88379810944 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/cluster/ClusterDrsAlgorithmTest.java @@ -0,0 +1,97 @@ +/* + * 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.cluster; + +import com.cloud.utils.Ternary; +import junit.framework.TestCase; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.List; + +import static org.apache.cloudstack.cluster.ClusterDrsAlgorithm.getMetricValue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyFloat; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class ClusterDrsAlgorithmTest extends TestCase { + + @Test + public void testGetMetricValue() { + List> testData = List.of( + new Ternary<>(true, "free", 0.4), + new Ternary<>(false, "free", 40.0), + new Ternary<>(true, "used", 0.3), + new Ternary<>(false, "used", 30.0) + ); + + long used = 30; + long free = 40; + long total = 100; + + for (Ternary data : testData) { + boolean useRatio = data.first(); + String metricType = data.second(); + double expectedValue = data.third(); + + try (MockedStatic ignored = Mockito.mockStatic(ClusterDrsAlgorithm.class)) { + when(ClusterDrsAlgorithm.getDrsMetricUseRatio(1L)).thenReturn(useRatio); + when(ClusterDrsAlgorithm.getDrsMetricType(1L)).thenReturn(metricType); + when(ClusterDrsAlgorithm.getMetricValue(anyLong(), anyLong(), anyLong(), anyLong(), any())).thenCallRealMethod(); + + assertEquals(expectedValue, getMetricValue(1, used, free, total, null)); + } + } + } + + @Test + public void testGetMetricValueWithSkipThreshold() { + List> testData = List.of( + new Ternary<>(true, "free", 0.15), + new Ternary<>(false, "free", 15.0), + new Ternary<>(true, "used", null), + new Ternary<>(false, "used", null) + ); + + long used = 80; + long free = 15; + long total = 100; + + for (Ternary data : testData) { + boolean useRatio = data.first(); + String metricType = data.second(); + Double expectedValue = data.third(); + float skipThreshold = metricType.equals("free") ? 0.1f : 0.7f; + + try (MockedStatic ignored = Mockito.mockStatic(ClusterDrsAlgorithm.class)) { + when(ClusterDrsAlgorithm.getDrsMetricUseRatio(1L)).thenReturn(useRatio); + when(ClusterDrsAlgorithm.getDrsMetricType(1L)).thenReturn(metricType); + when(ClusterDrsAlgorithm.getMetricValue(anyLong(), anyLong(), anyLong(), anyLong(), anyFloat())).thenCallRealMethod(); + + assertEquals(expectedValue, ClusterDrsAlgorithm.getMetricValue(1L, used, free, total, skipThreshold)); + } + } + } +} diff --git a/api/src/test/java/org/apache/cloudstack/context/CallContextTest.java b/api/src/test/java/org/apache/cloudstack/context/CallContextTest.java index eb1336f90e9..d3537d6f831 100644 --- a/api/src/test/java/org/apache/cloudstack/context/CallContextTest.java +++ b/api/src/test/java/org/apache/cloudstack/context/CallContextTest.java @@ -28,7 +28,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import com.cloud.user.Account; import com.cloud.user.User; diff --git a/api/src/test/java/org/apache/cloudstack/storage/template/VnfTemplateUtilsTest.java b/api/src/test/java/org/apache/cloudstack/storage/template/VnfTemplateUtilsTest.java new file mode 100644 index 00000000000..7ba8564faf4 --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/storage/template/VnfTemplateUtilsTest.java @@ -0,0 +1,261 @@ +// 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.storage.template; + +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.VNF.VnfNic; +import com.cloud.storage.Storage; +import com.cloud.template.VirtualMachineTemplate; +import org.apache.cloudstack.api.command.user.template.RegisterVnfTemplateCmd; +import org.apache.cloudstack.api.command.user.template.UpdateVnfTemplateCmd; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RunWith(MockitoJUnitRunner.class) +public class VnfTemplateUtilsTest { + + @Test + public void testGetVnfNicsListAllGood() { + final Map vnfNics = new HashMap<>(); + vnfNics.put("0", new HashMap<>(Map.ofEntries( + Map.entry("deviceid", "1"), + Map.entry("name", "eth1"), + Map.entry("required", "true"), + Map.entry("description", "The second NIC of VNF appliance") + ))); + vnfNics.put("1", new HashMap<>(Map.ofEntries( + Map.entry("deviceid", "2"), + Map.entry("name", "eth2"), + Map.entry("required", "false"), + Map.entry("description", "The third NIC of VNF appliance") + ))); + vnfNics.put("2", new HashMap<>(Map.ofEntries( + Map.entry("deviceid", "0"), + Map.entry("name", "eth0"), + Map.entry("description", "The first NIC of VNF appliance") + ))); + + Map vnfNicsMock = Mockito.mock(Map.class); + Mockito.when(vnfNicsMock.values()).thenReturn(vnfNics.values()); + + List nicsList = VnfTemplateUtils.getVnfNicsList(vnfNicsMock); + Mockito.verify(vnfNicsMock).values(); + + Assert.assertEquals(3, nicsList.size()); + Assert.assertEquals(0, nicsList.get(0).getDeviceId()); + Assert.assertEquals("eth0", nicsList.get(0).getName()); + Assert.assertTrue(nicsList.get(0).isRequired()); + Assert.assertEquals(1, nicsList.get(1).getDeviceId()); + Assert.assertEquals("eth1", nicsList.get(1).getName()); + Assert.assertTrue(nicsList.get(1).isRequired()); + Assert.assertEquals(2, nicsList.get(2).getDeviceId()); + Assert.assertEquals("eth2", nicsList.get(2).getName()); + Assert.assertFalse(nicsList.get(2).isRequired()); + } + + @Test(expected = InvalidParameterValueException.class) + public void testGetVnfNicsListWithEmptyName() { + final Map vnfNics = new HashMap<>(); + vnfNics.put("0", new HashMap<>(Map.ofEntries( + Map.entry("deviceid", "1"), + Map.entry("required", "true"), + Map.entry("description", "The second NIC of VNF appliance") + ))); + + Map vnfNicsMock = Mockito.mock(Map.class); + Mockito.when(vnfNicsMock.values()).thenReturn(vnfNics.values()); + + List nicsList = VnfTemplateUtils.getVnfNicsList(vnfNicsMock); + } + + @Test(expected = InvalidParameterValueException.class) + public void testGetVnfNicsListWithEmptyDeviceId() { + final Map vnfNics = new HashMap<>(); + vnfNics.put("0", new HashMap<>(Map.ofEntries( + Map.entry("name", "eth1"), + Map.entry("required", "true"), + Map.entry("description", "The second NIC of VNF appliance") + ))); + + Map vnfNicsMock = Mockito.mock(Map.class); + Mockito.when(vnfNicsMock.values()).thenReturn(vnfNics.values()); + + List nicsList = VnfTemplateUtils.getVnfNicsList(vnfNicsMock); + } + + @Test(expected = InvalidParameterValueException.class) + public void testGetVnfNicsListWithInvalidDeviceId() { + final Map vnfNics = new HashMap<>(); + vnfNics.put("0", new HashMap<>(Map.ofEntries( + Map.entry("deviceid", "invalid"), + Map.entry("name", "eth1"), + Map.entry("required", "true"), + Map.entry("description", "The second NIC of VNF appliance") + ))); + + Map vnfNicsMock = Mockito.mock(Map.class); + Mockito.when(vnfNicsMock.values()).thenReturn(vnfNics.values()); + + List nicsList = VnfTemplateUtils.getVnfNicsList(vnfNicsMock); + } + + @Test + public void testValidateVnfNicsAllGood() { + VnfNic nic1 = Mockito.mock(VnfNic.class); + Mockito.when(nic1.getDeviceId()).thenReturn(0L); + Mockito.when(nic1.isRequired()).thenReturn(true); + + VnfNic nic2 = Mockito.mock(VnfNic.class); + Mockito.when(nic2.getDeviceId()).thenReturn(1L); + Mockito.when(nic2.isRequired()).thenReturn(true); + + VnfNic nic3 = Mockito.mock(VnfNic.class); + Mockito.when(nic3.getDeviceId()).thenReturn(2L); + Mockito.when(nic3.isRequired()).thenReturn(false); + + List nicsList = Arrays.asList(nic1, nic2, nic3); + + VnfTemplateUtils.validateVnfNics(nicsList); + } + + @Test(expected = InvalidParameterValueException.class) + public void testValidateVnfNicsStartWithNonzero() { + VnfNic nic1 = Mockito.mock(VnfNic.class); + Mockito.when(nic1.getDeviceId()).thenReturn(1L); + + VnfNic nic2 = Mockito.mock(VnfNic.class); + + VnfNic nic3 = Mockito.mock(VnfNic.class); + + List nicsList = Arrays.asList(nic1, nic2, nic3); + + VnfTemplateUtils.validateVnfNics(nicsList); + } + + @Test(expected = InvalidParameterValueException.class) + public void testValidateVnfNicsWithNonConstantDeviceIds() { + VnfNic nic1 = Mockito.mock(VnfNic.class); + Mockito.when(nic1.getDeviceId()).thenReturn(0L); + Mockito.when(nic1.isRequired()).thenReturn(true); + + VnfNic nic2 = Mockito.mock(VnfNic.class); + Mockito.when(nic2.getDeviceId()).thenReturn(2L); + + VnfNic nic3 = Mockito.mock(VnfNic.class); + + List nicsList = Arrays.asList(nic1, nic2, nic3); + + VnfTemplateUtils.validateVnfNics(nicsList); + } + + @Test(expected = InvalidParameterValueException.class) + public void testValidateVnfNicsWithInvalidRequired() { + VnfNic nic1 = Mockito.mock(VnfNic.class); + Mockito.when(nic1.getDeviceId()).thenReturn(0L); + Mockito.when(nic1.isRequired()).thenReturn(true); + + VnfNic nic2 = Mockito.mock(VnfNic.class); + Mockito.when(nic2.getDeviceId()).thenReturn(1L); + Mockito.when(nic2.isRequired()).thenReturn(false); + + VnfNic nic3 = Mockito.mock(VnfNic.class); + Mockito.when(nic3.getDeviceId()).thenReturn(2L); + Mockito.when(nic3.isRequired()).thenReturn(true); + + List nicsList = Arrays.asList(nic1, nic2, nic3); + + VnfTemplateUtils.validateVnfNics(nicsList); + } + + @Test + public void testValidateApiCommandParamsAllGood() { + VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class); + RegisterVnfTemplateCmd cmd = Mockito.mock(RegisterVnfTemplateCmd.class); + Map vnfDetails = Mockito.spy(new HashMap<>()); + vnfDetails.put("username", "admin"); + vnfDetails.put("password", "password"); + vnfDetails.put("version", "4.19.0"); + vnfDetails.put("vendor", "cloudstack"); + Mockito.when(cmd.getVnfDetails()).thenReturn(vnfDetails); + + VnfTemplateUtils.validateApiCommandParams(cmd, template); + } + + @Test(expected = InvalidParameterValueException.class) + public void testValidateApiCommandParamsInvalidAccessMethods() { + VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class); + Mockito.when(template.getTemplateType()).thenReturn(Storage.TemplateType.VNF); + UpdateVnfTemplateCmd cmd = Mockito.mock(UpdateVnfTemplateCmd.class); + Map vnfDetails = Mockito.spy(new HashMap<>()); + vnfDetails.put("access_methods", "invalid"); + Mockito.when(cmd.getVnfDetails()).thenReturn(vnfDetails); + + VnfTemplateUtils.validateApiCommandParams(cmd, template); + } + + @Test(expected = InvalidParameterValueException.class) + public void testValidateApiCommandParamsInvalidAccessDetails() { + VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class); + Mockito.when(template.getTemplateType()).thenReturn(Storage.TemplateType.VNF); + UpdateVnfTemplateCmd cmd = Mockito.mock(UpdateVnfTemplateCmd.class); + Map vnfDetails = Mockito.spy(new HashMap<>()); + vnfDetails.put("invalid", "value"); + Mockito.when(cmd.getVnfDetails()).thenReturn(vnfDetails); + + VnfTemplateUtils.validateApiCommandParams(cmd, template); + } + + @Test(expected = InvalidParameterValueException.class) + public void testValidateApiCommandParamsInvalidTemplateType() { + VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class); + Mockito.when(template.getTemplateType()).thenReturn(Storage.TemplateType.USER); + UpdateVnfTemplateCmd cmd = Mockito.mock(UpdateVnfTemplateCmd.class); + + VnfTemplateUtils.validateApiCommandParams(cmd, template); + } + + @Test + public void testValidateVnfCidrList() { + List cidrList = new ArrayList<>(); + cidrList.add("10.10.10.0/24"); + VnfTemplateUtils.validateVnfCidrList(cidrList); + } + + @Test + public void testValidateVnfCidrListWithEmptyList() { + List cidrList = new ArrayList<>(); + VnfTemplateUtils.validateVnfCidrList(cidrList); + } + + @Test(expected = InvalidParameterValueException.class) + public void testValidateVnfCidrListwithInvalidList() { + List cidrList = new ArrayList<>(); + cidrList.add("10.10.10.0/24"); + cidrList.add("10.10.10.0/33"); + VnfTemplateUtils.validateVnfCidrList(cidrList); + } +} diff --git a/api/src/test/java/org/apache/cloudstack/storage/volume/VolumeOnStorageTOTest.java b/api/src/test/java/org/apache/cloudstack/storage/volume/VolumeOnStorageTOTest.java new file mode 100644 index 00000000000..59de3b8ac4e --- /dev/null +++ b/api/src/test/java/org/apache/cloudstack/storage/volume/VolumeOnStorageTOTest.java @@ -0,0 +1,84 @@ +// 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.storage.volume; + +import com.cloud.hypervisor.Hypervisor; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class VolumeOnStorageTOTest { + + private static String path = "path"; + private static String name = "name"; + private static String fullPath = "fullPath"; + private static String format = "qcow2"; + private static long size = 10; + private static long virtualSize = 20; + private static String encryptFormat = "LUKS"; + private static Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM; + private static String BACKING_FILE = "backing file"; + private static String BACKING_FILE_FORMAT = "qcow2"; + + @Test + public void testVolumeOnStorageTO() { + VolumeOnStorageTO volumeOnStorageTO = new VolumeOnStorageTO(hypervisorType, path, name, fullPath, + format, size, virtualSize); + + Assert.assertEquals(hypervisorType, volumeOnStorageTO.getHypervisorType()); + Assert.assertEquals(path, volumeOnStorageTO.getPath()); + Assert.assertEquals(name, volumeOnStorageTO.getName()); + Assert.assertEquals(fullPath, volumeOnStorageTO.getFullPath()); + Assert.assertEquals(format, volumeOnStorageTO.getFormat()); + Assert.assertEquals(size, volumeOnStorageTO.getSize()); + Assert.assertEquals(virtualSize, volumeOnStorageTO.getVirtualSize()); + } + + @Test + public void testVolumeOnStorageTO3() { + VolumeOnStorageTO volumeOnStorageTO = new VolumeOnStorageTO(); + volumeOnStorageTO.setHypervisorType(hypervisorType); + volumeOnStorageTO.setPath(path); + volumeOnStorageTO.setFullPath(fullPath); + volumeOnStorageTO.setName(name); + volumeOnStorageTO.setFormat(format); + volumeOnStorageTO.setSize(size); + volumeOnStorageTO.setVirtualSize(virtualSize); + volumeOnStorageTO.setQemuEncryptFormat(encryptFormat); + + Map details = new HashMap<>(); + details.put(VolumeOnStorageTO.Detail.BACKING_FILE, BACKING_FILE); + volumeOnStorageTO.setDetails(details); + volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.BACKING_FILE_FORMAT, BACKING_FILE_FORMAT); + + Assert.assertEquals(hypervisorType, volumeOnStorageTO.getHypervisorType()); + Assert.assertEquals(path, volumeOnStorageTO.getPath()); + Assert.assertEquals(name, volumeOnStorageTO.getName()); + Assert.assertEquals(fullPath, volumeOnStorageTO.getFullPath()); + Assert.assertEquals(format, volumeOnStorageTO.getFormat()); + Assert.assertEquals(size, volumeOnStorageTO.getSize()); + Assert.assertEquals(virtualSize, volumeOnStorageTO.getVirtualSize()); + Assert.assertEquals(encryptFormat, volumeOnStorageTO.getQemuEncryptFormat()); + + details = volumeOnStorageTO.getDetails(); + Assert.assertEquals(2, details.size()); + Assert.assertEquals(BACKING_FILE, details.get(VolumeOnStorageTO.Detail.BACKING_FILE)); + Assert.assertEquals(BACKING_FILE_FORMAT, details.get(VolumeOnStorageTO.Detail.BACKING_FILE_FORMAT)); + } +} diff --git a/build/replace.properties b/build/replace.properties index 3d9a4597060..ce38727b80a 100644 --- a/build/replace.properties +++ b/build/replace.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/client/bindir/cloud-update-xenserver-licenses.in b/client/bindir/cloud-update-xenserver-licenses.in index 9ce1898dc81..2be3a083f97 100755 --- a/client/bindir/cloud-update-xenserver-licenses.in +++ b/client/bindir/cloud-update-xenserver-licenses.in @@ -7,9 +7,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -46,7 +46,7 @@ cfg = "@MSCONF@/db.properties" #---------------------- option parsing and command line checks ------------------------ -usage = """%prog <-a | host names / IP addresses...> +usage = """%prog <-a | host names / IP addresses...> This command deploys the license file specified in the command line into a specific XenServer host or all XenServer hosts known to the management server.""" @@ -88,7 +88,7 @@ def parseuserpwfromhosts(hosts): return creds class XenServerConfigurator(Thread): - + def __init__(self,host,user,password,keyfiledata): Thread.__init__(self) self.host = host @@ -99,7 +99,7 @@ class XenServerConfigurator(Thread): self.stdout = "" self.stderr = "" self.state = 'initialized' - + def run(self): try: self.state = 'running' @@ -120,18 +120,18 @@ class XenServerConfigurator(Thread): c.close() if self.retval != 0: self.state = 'failed' else: self.state = 'finished' - + except Exception as e: self.state = 'failed' self.retval = e #raise - + def __str__(self): if self.state == 'failed': return "<%s XenServerConfigurator on %s@%s: %s>"%(self.state,self.user,self.host,str(self.retval)) else: return "<%s XenServerConfigurator on %s@%s>"%(self.state,self.user,self.host) - + #------------- actual code -------------------- (options, args) = parser.parse_args() @@ -162,7 +162,7 @@ for host,(user,password) in list(creds.items()): for c in configurators: c.start() - + for c in configurators: print(c.host + "...", end=' ') c.join() diff --git a/client/conf/db.properties.in b/client/conf/db.properties.in index 572cfbc1ff2..8f31aff17e6 100644 --- a/client/conf/db.properties.in +++ b/client/conf/db.properties.in @@ -29,6 +29,10 @@ db.cloud.driver=@DBDRIVER@ db.cloud.port=3306 db.cloud.name=cloud +# Connection URI to the database "cloud". When this property is set, only the following properties will be used along with it: db.cloud.maxActive, db.cloud.maxIdle, db.cloud.maxWait, db.cloud.username, db.cloud.password, db.cloud.driver, db.cloud.validationQuery, db.cloud.isolation.level. Other properties will be ignored. +db.cloud.uri= + + # CloudStack database tuning parameters db.cloud.maxActive=250 db.cloud.maxIdle=30 @@ -61,6 +65,10 @@ db.usage.driver=@DBDRIVER@ db.usage.port=3306 db.usage.name=cloud_usage +# Connection URI to the database "usage". When this property is set, only the following properties will be used along with it: db.usage.maxActive, db.cloud.maxIdle, db.cloud.maxWait, db.usage.username, db.usage.password, db.usage.driver, db.usage.validationQuery, db.usage.isolation.level. Other properties will be ignored. +db.usage.uri= + + # usage database tuning parameters db.usage.maxActive=100 db.usage.maxIdle=30 @@ -79,6 +87,9 @@ db.simulator.maxIdle=30 db.simulator.maxWait=10000 db.simulator.autoReconnect=true +# Connection URI to the database "simulator". When this property is set, only the following properties will be used along with it: db.simulator.host, db.simulator.port, db.simulator.name, db.simulator.autoReconnect. Other properties will be ignored. +db.simulator.uri= + # High Availability And Cluster Properties db.ha.enabled=false diff --git a/client/conf/log4j-cloud.xml.in b/client/conf/log4j-cloud.xml.in index 223692881de..148ccbfbb41 100755 --- a/client/conf/log4j-cloud.xml.in +++ b/client/conf/log4j-cloud.xml.in @@ -17,183 +17,118 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - + + - - + + net.sf.cglib.proxy + - - - + + + - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - + + + + + + + - - - - - - - - + + + - - - + + + + - - - - - - - - + + + - - - + + + + - - - - - - - - - - + + + - - - + + + + - - - - - - - + + + - - - + + + + - - - + - - - + - - - + - - - + - - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + + + - - - - + - - - - + - - - - + + + + + + + - - - + + + - - - - - - - - + + + + + - - - - - - - - - - - - + + diff --git a/client/conf/server.properties.in b/client/conf/server.properties.in index 42d98a6eb29..57d81c81217 100644 --- a/client/conf/server.properties.in +++ b/client/conf/server.properties.in @@ -29,19 +29,22 @@ http.port=8080 # Max inactivity time in minutes for the session session.timeout=30 -# Options to configure and enable HTTPS on management server +# Max allowed API request payload/content size in bytes +request.content.size=1048576 + +# Options to configure and enable HTTPS on the management server # -# For management server to pickup these configuration settings, the configured -# keystore file should exists and be readable by the management server. +# For the management server to pick up these configuration settings, the configured +# keystore file should exist and be readable by the management server. https.enable=false https.port=8443 # The keystore and manager passwords are assumed to be same. https.keystore=/etc/cloudstack/management/cloud.jks -# If you want to encrypt the password follow the steps mentioned at: -# http://docs.cloudstack.apache.org/projects/archived-cloudstack-administration/en/latest/management.html?highlight=jasypt#changing-the-database-password +# If you want to encrypt the password itself, follow the steps mentioned at: +http://docs.cloudstack.apache.org/en/latest/adminguide/management.html?highlight=jasypt#changing-the-database-password https.keystore.password=vmops.com -# If an encrypted password is used, specify the encryption type - valid types: file, env (set environment variable CLOUD_SECRET_KEY), web +# If an encrypted password is used, specify the encryption type. Valid types: file, web, env (set environment variable CLOUD_SECRET_KEY) # password.encryption.type=none # The path to webapp directory diff --git a/client/pom.xml b/client/pom.xml index 502f889eec6..5d683411c95 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -25,13 +25,9 @@ org.apache.cloudstack cloudstack - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT - - juniper-contrail - https://juniper.github.io/contrail-maven/snapshots - juniper-tungsten-api https://github.com/radu-todirica/tungsten-api/raw/master @@ -68,8 +64,58 @@ jetty-util - mysql - mysql-connector-java + com.mysql + mysql-connector-j + + + org.apache.cloudstack + cloud-agent + ${project.version} + + + org.apache.cloudstack + cloud-api + ${project.version} + + + org.apache.cloudstack + cloud-core + ${project.version} + + + org.apache.cloudstack + cloud-framework-cluster + ${project.version} + + + org.apache.cloudstack + cloud-framework-config + ${project.version} + + + org.apache.cloudstack + cloud-framework-db + ${project.version} + + + org.apache.cloudstack + cloud-framework-events + ${project.version} + + + org.apache.cloudstack + cloud-framework-jobs + ${project.version} + + + org.apache.cloudstack + cloud-framework-managed-context + ${project.version} + + + org.apache.cloudstack + cloud-framework-security + ${project.version} org.apache.cloudstack @@ -81,6 +127,11 @@ cloud-framework-spring-lifecycle ${project.version} + + org.apache.cloudstack + cloud-plugin-storage-volume-adaptive + ${project.version} + org.apache.cloudstack cloud-plugin-storage-volume-solidfire @@ -111,6 +162,16 @@ cloud-plugin-storage-volume-storpool ${project.version} + + org.apache.cloudstack + cloud-plugin-storage-volume-primera + ${project.version} + + + org.apache.cloudstack + cloud-plugin-storage-volume-flasharray + ${project.version} + org.apache.cloudstack cloud-server @@ -161,6 +222,11 @@ cloud-plugin-user-authenticator-md5 ${project.version} + + org.apache.cloudstack + cloud-plugin-user-authenticator-oauth2 + ${project.version} + org.apache.cloudstack cloud-plugin-user-authenticator-pbkdf2 @@ -201,11 +267,6 @@ cloud-plugin-network-nvp ${project.version} - - org.apache.cloudstack - cloud-plugin-network-contrail - ${project.version} - org.apache.cloudstack cloud-plugin-network-palo-alto @@ -377,6 +438,11 @@ cloud-mom-kafka ${project.version} + + org.apache.cloudstack + cloud-mom-webhook + ${project.version} + org.apache.cloudstack cloud-framework-agent-lb @@ -417,11 +483,6 @@ cloud-engine-components-api ${project.version} - - org.apache.cloudstack - cloud-engine-network - ${project.version} - org.apache.cloudstack cloud-engine-orchestration @@ -532,6 +593,16 @@ cloud-plugin-network-globodns ${project.version} + + org.apache.cloudstack + cloud-plugin-cluster-drs-balanced + ${project.version} + + + org.apache.cloudstack + cloud-plugin-cluster-drs-condensed + ${project.version} + org.apache.cloudstack cloud-plugin-database-quota @@ -572,6 +643,31 @@ cloud-plugin-shutdown ${project.version} + + org.apache.cloudstack + cloud-engine-storage-object + ${project.version} + + + org.apache.cloudstack + cloud-plugin-storage-object-minio + ${project.version} + + + org.apache.cloudstack + cloud-plugin-storage-object-simulator + ${project.version} + + + org.apache.cloudstack + cloud-usage + ${project.version} + + + org.apache.cloudstack + cloud-utils + ${project.version} + @@ -614,8 +710,8 @@ - mysql - mysql-connector-java + com.mysql + mysql-connector-j ${cs.mysql.version} @@ -657,7 +753,7 @@ - log4j.configuration + log4j2.configurationFile log4j-cloud.xml @@ -803,8 +899,8 @@ ${project.build.directory}/pythonlibs - mysql - mysql-connector-java + com.mysql + mysql-connector-j false ${project.build.directory}/lib @@ -832,6 +928,12 @@ false ${project.build.directory}/lib + + com.linbit.linstor.api + java-linstor + false + ${project.build.directory}/lib + org.bouncycastle bctls-jdk15on @@ -865,8 +967,6 @@ com.tngtech.java:junit-dataprovider org.mockito:mockito-all org.hamcrest:hamcrest-all - org.powermock:powermock-module-junit4 - org.powermock:powermock-api-mockito2 org.springframework:spring-test org.apache.tomcat.embed:tomcat-embed-core org.apache.geronimo.specs:geronimo-servlet_3.0_spec @@ -874,9 +974,11 @@ org.bouncycastle:bcprov-jdk15on org.bouncycastle:bcpkix-jdk15on org.bouncycastle:bctls-jdk15on - mysql:mysql-connector-java + com.mysql:mysql-connector-j org.apache.cloudstack:cloud-plugin-storage-volume-storpool org.apache.cloudstack:cloud-plugin-storage-volume-linstor + org.apache.cloudstack:cloud-usage + com.linbit.linstor.api:java-linstor @@ -996,11 +1098,21 @@ cloud-plugin-network-cisco-vnmc ${project.version} + + org.apache.cloudstack + cloud-plugin-network-nsx + ${project.version} + org.apache.cloudstack cloud-plugin-api-vmware-sioc ${project.version} + + org.apache.cloudstack + cloud-plugin-network-contrail + ${project.version} + org.apache.cloudstack cloud-plugin-backup-veeam diff --git a/client/src/main/java/org/apache/cloudstack/ServerDaemon.java b/client/src/main/java/org/apache/cloudstack/ServerDaemon.java index 63cdc45b8dc..d2e4483835e 100644 --- a/client/src/main/java/org/apache/cloudstack/ServerDaemon.java +++ b/client/src/main/java/org/apache/cloudstack/ServerDaemon.java @@ -26,12 +26,10 @@ import java.lang.management.ManagementFactory; import java.net.URL; import java.util.Properties; -import com.cloud.utils.Pair; -import com.cloud.utils.server.ServerProperties; import org.apache.commons.daemon.Daemon; import org.apache.commons.daemon.DaemonContext; +import org.apache.commons.lang3.StringUtils; import org.eclipse.jetty.jmx.MBeanContainer; -import org.eclipse.jetty.server.ForwardedRequestCustomizer; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.NCSARequestLog; @@ -40,6 +38,7 @@ import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.MovedContextHandler; import org.eclipse.jetty.server.handler.RequestLogHandler; @@ -50,10 +49,12 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; import org.eclipse.jetty.webapp.WebAppContext; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import com.cloud.utils.Pair; import com.cloud.utils.PropertiesUtil; -import org.apache.commons.lang3.StringUtils; +import com.cloud.utils.server.ServerProperties; /*** * The ServerDaemon class implements the embedded server, it can be started either @@ -61,7 +62,7 @@ import org.apache.commons.lang3.StringUtils; * Configuration parameters are read from server.properties file available on the classpath. */ public class ServerDaemon implements Daemon { - private static final Logger LOG = Logger.getLogger(ServerDaemon.class); + protected Logger logger = LogManager.getLogger(getClass()); private static final String WEB_XML = "META-INF/webapp/WEB-INF/web.xml"; ///////////////////////////////////////////////////// @@ -79,6 +80,8 @@ public class ServerDaemon implements Daemon { private static final String KEYSTORE_PASSWORD = "https.keystore.password"; private static final String WEBAPP_DIR = "webapp.dir"; private static final String ACCESS_LOG = "access.log"; + private static final String REQUEST_CONTENT_SIZE_KEY = "request.content.size"; + private static final int DEFAULT_REQUEST_CONTENT_SIZE = 1048576; //////////////////////////////////////////////////////// /////////////// Server Configuration /////////////////// @@ -90,6 +93,7 @@ public class ServerDaemon implements Daemon { private int httpPort = 8080; private int httpsPort = 8443; private int sessionTimeout = 30; + private int maxFormContentSize = DEFAULT_REQUEST_CONTENT_SIZE; private boolean httpsEnable = false; private String accessLogFile = "access.log"; private String bindInterface = null; @@ -112,12 +116,12 @@ public class ServerDaemon implements Daemon { public void init(final DaemonContext context) { final File confFile = PropertiesUtil.findConfigFile("server.properties"); if (confFile == null) { - LOG.warn(String.format("Server configuration file not found. Initializing server daemon on %s, with http.enable=%s, http.port=%s, https.enable=%s, https.port=%s, context.path=%s", + logger.warn(String.format("Server configuration file not found. Initializing server daemon on %s, with http.enable=%s, http.port=%s, https.enable=%s, https.port=%s, context.path=%s", bindInterface, httpEnable, httpPort, httpsEnable, httpsPort, contextPath)); return; } - LOG.info("Server configuration file found: " + confFile.getAbsolutePath()); + logger.info("Server configuration file found: " + confFile.getAbsolutePath()); try { InputStream is = new FileInputStream(confFile); @@ -136,16 +140,17 @@ public class ServerDaemon implements Daemon { setWebAppLocation(properties.getProperty(WEBAPP_DIR)); setAccessLogFile(properties.getProperty(ACCESS_LOG, "access.log")); setSessionTimeout(Integer.valueOf(properties.getProperty(SESSION_TIMEOUT, "30"))); + setMaxFormContentSize(Integer.valueOf(properties.getProperty(REQUEST_CONTENT_SIZE_KEY, String.valueOf(DEFAULT_REQUEST_CONTENT_SIZE)))); } catch (final IOException e) { - LOG.warn("Failed to read configuration from server.properties file", e); + logger.warn("Failed to read configuration from server.properties file", e); } finally { // make sure that at least HTTP is enabled if both of them are set to false (misconfiguration) if (!httpEnable && !httpsEnable) { setHttpEnable(true); - LOG.warn("Server configuration malformed, neither http nor https is enabled, http will be enabled."); + logger.warn("Server configuration malformed, neither http nor https is enabled, http will be enabled."); } } - LOG.info(String.format("Initializing server daemon on %s, with http.enable=%s, http.port=%s, https.enable=%s, https.port=%s, context.path=%s", + logger.info(String.format("Initializing server daemon on %s, with http.enable=%s, http.port=%s, https.enable=%s, https.port=%s, context.path=%s", bindInterface, httpEnable, httpPort, httpsEnable, httpsPort, contextPath)); } @@ -168,7 +173,7 @@ public class ServerDaemon implements Daemon { // HTTP config final HttpConfiguration httpConfig = new HttpConfiguration(); - httpConfig.addCustomizer( new ForwardedRequestCustomizer() ); +// it would be nice to make this dynamic but we take care of this ourselves for now: httpConfig.addCustomizer( new ForwardedRequestCustomizer() ); httpConfig.setSecureScheme("https"); httpConfig.setSecurePort(httpsPort); httpConfig.setOutputBufferSize(32768); @@ -186,6 +191,7 @@ public class ServerDaemon implements Daemon { // Extra config options server.setStopAtShutdown(true); + server.setAttribute(ContextHandler.MAX_FORM_CONTENT_SIZE_KEY, maxFormContentSize); // HTTPS Connector createHttpsConnector(httpConfig); @@ -248,7 +254,7 @@ public class ServerDaemon implements Daemon { KeyStoreScanner scanner = new KeyStoreScanner(sslContextFactory); server.addBean(scanner); } catch (Exception ex) { - LOG.error("failed to set up keystore scanner, manual refresh of certificates will be required", ex); + logger.error("failed to set up keystore scanner, manual refresh of certificates will be required", ex); } } } @@ -257,6 +263,7 @@ public class ServerDaemon implements Daemon { final WebAppContext webApp = new WebAppContext(); webApp.setContextPath(contextPath); webApp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false"); + webApp.setMaxFormContentSize(maxFormContentSize); // GZIP handler final GzipHandler gzipHandler = new GzipHandler(); @@ -355,4 +362,8 @@ public class ServerDaemon implements Daemon { public void setSessionTimeout(int sessionTimeout) { this.sessionTimeout = sessionTimeout; } + + public void setMaxFormContentSize(int maxFormContentSize) { + this.maxFormContentSize = maxFormContentSize; + } } diff --git a/client/src/main/resources/META-INF/cloudstack/webApplicationContext.xml b/client/src/main/resources/META-INF/cloudstack/webApplicationContext.xml index 3b3c6dbe35c..e1c46268618 100644 --- a/client/src/main/resources/META-INF/cloudstack/webApplicationContext.xml +++ b/client/src/main/resources/META-INF/cloudstack/webApplicationContext.xml @@ -25,7 +25,7 @@ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" - > + > diff --git a/client/src/main/webapp/WEB-INF/web.xml b/client/src/main/webapp/WEB-INF/web.xml index 9a3d8bc5b29..43bee7e59d8 100644 --- a/client/src/main/webapp/WEB-INF/web.xml +++ b/client/src/main/webapp/WEB-INF/web.xml @@ -21,7 +21,7 @@ version="2.5"> - log4jConfigLocation + log4jConfiguration classpath:log4j-cloud.xml diff --git a/core/pom.xml b/core/pom.xml index 339439abbee..83cdee8cf4f 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -24,7 +24,7 @@ org.apache.cloudstack cloudstack - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT diff --git a/core/src/main/java/com/cloud/agent/api/CheckConvertInstanceAnswer.java b/core/src/main/java/com/cloud/agent/api/CheckConvertInstanceAnswer.java new file mode 100644 index 00000000000..a02ac92927a --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/CheckConvertInstanceAnswer.java @@ -0,0 +1,43 @@ +// 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; + +public class CheckConvertInstanceAnswer extends Answer { + + private boolean ovfExportSupported = false; + + public CheckConvertInstanceAnswer() { + super(); + } + + public CheckConvertInstanceAnswer(Command command, boolean success) { + super(command, success, ""); + } + + public CheckConvertInstanceAnswer(Command command, boolean success, String details) { + super(command, success, details); + } + + public CheckConvertInstanceAnswer(Command command, boolean success, boolean ovfExportSupported, String details) { + super(command, success, details); + this.ovfExportSupported = ovfExportSupported; + } + + public boolean isOvfExportSupported() { + return ovfExportSupported; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/CheckConvertInstanceCommand.java b/core/src/main/java/com/cloud/agent/api/CheckConvertInstanceCommand.java new file mode 100644 index 00000000000..fc066e5c589 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/CheckConvertInstanceCommand.java @@ -0,0 +1,37 @@ +// 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; + +public class CheckConvertInstanceCommand extends Command { + boolean checkWindowsGuestConversionSupport = false; + + public CheckConvertInstanceCommand() { + } + + public CheckConvertInstanceCommand(boolean checkWindowsGuestConversionSupport) { + this.checkWindowsGuestConversionSupport = checkWindowsGuestConversionSupport; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public boolean getCheckWindowsGuestConversionSupport() { + return checkWindowsGuestConversionSupport; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/CheckOnHostCommand.java b/core/src/main/java/com/cloud/agent/api/CheckOnHostCommand.java index b4055179e4d..982e10cf2eb 100644 --- a/core/src/main/java/com/cloud/agent/api/CheckOnHostCommand.java +++ b/core/src/main/java/com/cloud/agent/api/CheckOnHostCommand.java @@ -24,6 +24,7 @@ import com.cloud.host.Host; public class CheckOnHostCommand extends Command { HostTO host; + boolean reportCheckFailureIfOneStorageIsDown; protected CheckOnHostCommand() { } @@ -33,10 +34,20 @@ public class CheckOnHostCommand extends Command { setWait(20); } + public CheckOnHostCommand(Host host, boolean reportCheckFailureIfOneStorageIsDown) { + super(); + this.host = new HostTO(host); + this.reportCheckFailureIfOneStorageIsDown = reportCheckFailureIfOneStorageIsDown; + } + public HostTO getHost() { return host; } + public boolean isCheckFailedOnOneStorage() { + return reportCheckFailureIfOneStorageIsDown; + } + @Override public boolean executeInSequence() { return false; diff --git a/agent/src/main/java/com/cloud/agent/dhcp/DhcpSnooper.java b/core/src/main/java/com/cloud/agent/api/CheckVolumeAnswer.java similarity index 61% rename from agent/src/main/java/com/cloud/agent/dhcp/DhcpSnooper.java rename to core/src/main/java/com/cloud/agent/api/CheckVolumeAnswer.java index 67718d50095..5a32ab59a7a 100644 --- a/agent/src/main/java/com/cloud/agent/dhcp/DhcpSnooper.java +++ b/core/src/main/java/com/cloud/agent/api/CheckVolumeAnswer.java @@ -14,28 +14,26 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.agent.dhcp; -import java.net.InetAddress; -import java.util.List; -import java.util.Map; +package com.cloud.agent.api; -import com.cloud.utils.Pair; -import com.cloud.utils.component.Adapter; +public class CheckVolumeAnswer extends Answer { -public interface DhcpSnooper extends Adapter { + private long size; - public InetAddress getIPAddr(String macAddr, String vmName); + CheckVolumeAnswer() { + } - public InetAddress getDhcpServerIP(); + public CheckVolumeAnswer(CheckVolumeCommand cmd, String details, long size) { + super(cmd, true, details); + this.size = size; + } - public void cleanup(String macAddr, String vmName); - - public Map syncIpAddr(); - - @Override - public boolean stop(); - - public void initializeMacTable(List> macVmNameList); + public long getSize() { + return size; + } + public String getString() { + return "CheckVolumeAnswer [size=" + size + "]"; + } } diff --git a/core/src/main/java/com/cloud/agent/api/CheckVolumeCommand.java b/core/src/main/java/com/cloud/agent/api/CheckVolumeCommand.java new file mode 100644 index 00000000000..bd44b35c895 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/CheckVolumeCommand.java @@ -0,0 +1,58 @@ +// +// 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; + +import com.cloud.agent.api.to.StorageFilerTO; + +public class CheckVolumeCommand extends Command { + + String srcFile; + + StorageFilerTO storageFilerTO; + + + public String getSrcFile() { + return srcFile; + } + + public void setSrcFile(String srcFile) { + this.srcFile = srcFile; + } + + public CheckVolumeCommand() { + } + + @Override + public boolean executeInSequence() { + return false; + } + + public String getString() { + return "CheckVolumeCommand [srcFile=" + srcFile + "]"; + } + + public StorageFilerTO getStorageFilerTO() { + return storageFilerTO; + } + + public void setStorageFilerTO(StorageFilerTO storageFilerTO) { + this.storageFilerTO = storageFilerTO; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/ConvertInstanceAnswer.java b/core/src/main/java/com/cloud/agent/api/ConvertInstanceAnswer.java new file mode 100644 index 00000000000..829888570a6 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/ConvertInstanceAnswer.java @@ -0,0 +1,40 @@ +// 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; + +import org.apache.cloudstack.vm.UnmanagedInstanceTO; + +public class ConvertInstanceAnswer extends Answer { + + public ConvertInstanceAnswer() { + super(); + } + private UnmanagedInstanceTO convertedInstance; + + public ConvertInstanceAnswer(Command command, boolean success, String details) { + super(command, success, details); + } + + public ConvertInstanceAnswer(Command command, UnmanagedInstanceTO convertedInstance) { + super(command, true, ""); + this.convertedInstance = convertedInstance; + } + + public UnmanagedInstanceTO getConvertedInstance() { + return convertedInstance; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/ConvertInstanceCommand.java b/core/src/main/java/com/cloud/agent/api/ConvertInstanceCommand.java new file mode 100644 index 00000000000..b8250903f85 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/ConvertInstanceCommand.java @@ -0,0 +1,91 @@ +// 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; + +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.RemoteInstanceTO; +import com.cloud.hypervisor.Hypervisor; + +import java.util.List; + +public class ConvertInstanceCommand extends Command { + + private RemoteInstanceTO sourceInstance; + private Hypervisor.HypervisorType destinationHypervisorType; + private List destinationStoragePools; + private DataStoreTO conversionTemporaryLocation; + private String templateDirOnConversionLocation; + private boolean checkConversionSupport; + private boolean exportOvfToConversionLocation; + private int threadsCountToExportOvf = 0; + + public ConvertInstanceCommand() { + } + + public ConvertInstanceCommand(RemoteInstanceTO sourceInstance, Hypervisor.HypervisorType destinationHypervisorType, + List destinationStoragePools, DataStoreTO conversionTemporaryLocation, + String templateDirOnConversionLocation, boolean checkConversionSupport, boolean exportOvfToConversionLocation) { + this.sourceInstance = sourceInstance; + this.destinationHypervisorType = destinationHypervisorType; + this.destinationStoragePools = destinationStoragePools; + this.conversionTemporaryLocation = conversionTemporaryLocation; + this.templateDirOnConversionLocation = templateDirOnConversionLocation; + this.checkConversionSupport = checkConversionSupport; + this.exportOvfToConversionLocation = exportOvfToConversionLocation; + } + + public RemoteInstanceTO getSourceInstance() { + return sourceInstance; + } + + public Hypervisor.HypervisorType getDestinationHypervisorType() { + return destinationHypervisorType; + } + + public List getDestinationStoragePools() { + return destinationStoragePools; + } + + public DataStoreTO getConversionTemporaryLocation() { + return conversionTemporaryLocation; + } + + public String getTemplateDirOnConversionLocation() { + return templateDirOnConversionLocation; + } + + public boolean getCheckConversionSupport() { + return checkConversionSupport; + } + + public boolean getExportOvfToConversionLocation() { + return exportOvfToConversionLocation; + } + + public int getThreadsCountToExportOvf() { + return threadsCountToExportOvf; + } + + public void setThreadsCountToExportOvf(int threadsCountToExportOvf) { + this.threadsCountToExportOvf = threadsCountToExportOvf; + } + + @Override + public boolean executeInSequence() { + return false; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/CopyRemoteVolumeAnswer.java b/core/src/main/java/com/cloud/agent/api/CopyRemoteVolumeAnswer.java new file mode 100644 index 00000000000..e79005be71b --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/CopyRemoteVolumeAnswer.java @@ -0,0 +1,60 @@ +// 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; + +public class CopyRemoteVolumeAnswer extends Answer { + + private String remoteIp; + private String filename; + + private long size; + + CopyRemoteVolumeAnswer() { + } + + public CopyRemoteVolumeAnswer(CopyRemoteVolumeCommand cmd, String details, String filename, long size) { + super(cmd, true, details); + this.remoteIp = cmd.getRemoteIp(); + this.filename = filename; + this.size = size; + } + + public String getRemoteIp() { + return remoteIp; + } + + public void setRemoteIp(String remoteIp) { + this.remoteIp = remoteIp; + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public String getFilename() { + return filename; + } + + public long getSize() { + return size; + } + + public String getString() { + return "CopyRemoteVolumeAnswer [remoteIp=" + remoteIp + "]"; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/CopyRemoteVolumeCommand.java b/core/src/main/java/com/cloud/agent/api/CopyRemoteVolumeCommand.java new file mode 100644 index 00000000000..798336b0e72 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/CopyRemoteVolumeCommand.java @@ -0,0 +1,98 @@ +// +// 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; + +import com.cloud.agent.api.to.StorageFilerTO; + +public class CopyRemoteVolumeCommand extends Command { + String remoteIp; + String username; + @LogLevel(LogLevel.Log4jLevel.Off) + String password; + String srcFile; + String tmpPath; + StorageFilerTO storageFilerTO; + + public CopyRemoteVolumeCommand(String remoteIp, String username, String password) { + this.remoteIp = remoteIp; + this.username = username; + this.password = password; + } + + public String getRemoteIp() { + return remoteIp; + } + + public void setRemoteIp(String remoteIp) { + this.remoteIp = remoteIp; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getSrcFile() { + return srcFile; + } + + public void setSrcFile(String srcFile) { + this.srcFile = srcFile; + } + + public CopyRemoteVolumeCommand() { + } + + @Override + public boolean executeInSequence() { + return false; + } + + public String getString() { + return "CopyRemoteVolumeCommand [remoteIp=" + remoteIp + "]"; + } + + public void setTempPath(String tmpPath) { + this.tmpPath = tmpPath; + } + + public String getTmpPath() { + return tmpPath; + } + + public StorageFilerTO getStorageFilerTO() { + return storageFilerTO; + } + + public void setStorageFilerTO(StorageFilerTO storageFilerTO) { + this.storageFilerTO = storageFilerTO; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/FenceCommand.java b/core/src/main/java/com/cloud/agent/api/FenceCommand.java index 88e508ad1e2..2158923223f 100644 --- a/core/src/main/java/com/cloud/agent/api/FenceCommand.java +++ b/core/src/main/java/com/cloud/agent/api/FenceCommand.java @@ -19,6 +19,7 @@ package com.cloud.agent.api; +import com.cloud.agent.api.to.HostTO; import com.cloud.host.Host; import com.cloud.vm.VirtualMachine; @@ -32,6 +33,8 @@ public class FenceCommand extends Command { String hostGuid; String hostIp; boolean inSeq; + HostTO host; + boolean reportCheckFailureIfOneStorageIsDown; public FenceCommand(VirtualMachine vm, Host host) { super(); @@ -39,6 +42,7 @@ public class FenceCommand extends Command { hostGuid = host.getGuid(); hostIp = host.getPrivateIpAddress(); inSeq = false; + this.host = new HostTO(host); } public void setSeq(boolean inseq) { @@ -61,4 +65,16 @@ public class FenceCommand extends Command { public boolean executeInSequence() { return inSeq; } + + public HostTO getHost() { + return host; + } + + public boolean isReportCheckFailureIfOneStorageIsDown() { + return reportCheckFailureIfOneStorageIsDown; + } + + public void setReportCheckFailureIfOneStorageIsDown(boolean reportCheckFailureIfOneStorageIsDown) { + this.reportCheckFailureIfOneStorageIsDown = reportCheckFailureIfOneStorageIsDown; + } } diff --git a/core/src/main/java/com/cloud/agent/api/GetRemoteVmsAnswer.java b/core/src/main/java/com/cloud/agent/api/GetRemoteVmsAnswer.java new file mode 100644 index 00000000000..c4e590591d0 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/GetRemoteVmsAnswer.java @@ -0,0 +1,75 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package com.cloud.agent.api; + +import org.apache.cloudstack.vm.UnmanagedInstanceTO; + +import java.util.HashMap; +import java.util.List; + +public class GetRemoteVmsAnswer extends Answer { + + private String remoteIp; + @LogLevel(LogLevel.Log4jLevel.Trace) + private HashMap unmanagedInstances; + + List vmNames; + + GetRemoteVmsAnswer() { + } + + public GetRemoteVmsAnswer(GetRemoteVmsCommand cmd, String details, HashMap unmanagedInstances) { + super(cmd, true, details); + this.remoteIp = cmd.getRemoteIp(); + this.unmanagedInstances = unmanagedInstances; + } + + public GetRemoteVmsAnswer(GetRemoteVmsCommand cmd, String details, List vmNames) { + super(cmd, true, details); + this.remoteIp = cmd.getRemoteIp(); + this.vmNames = vmNames; + } + + public String getRemoteIp() { + return remoteIp; + } + + public void setRemoteIp(String remoteIp) { + this.remoteIp = remoteIp; + } + + public HashMap getUnmanagedInstances() { + return unmanagedInstances; + } + + public void setUnmanagedInstances(HashMap unmanagedInstances) { + this.unmanagedInstances = unmanagedInstances; + } + + public List getVmNames() { + return vmNames; + } + + public void setVmNames(List vmNames) { + this.vmNames = vmNames; + } + + public String getString() { + return "GetRemoteVmsAnswer [remoteIp=" + remoteIp + "]"; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/GetRemoteVmsCommand.java b/core/src/main/java/com/cloud/agent/api/GetRemoteVmsCommand.java new file mode 100644 index 00000000000..5b6b9bdd360 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/GetRemoteVmsCommand.java @@ -0,0 +1,70 @@ +// +// 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; + +public class GetRemoteVmsCommand extends Command { + + String remoteIp; + String username; + @LogLevel(LogLevel.Log4jLevel.Off) + String password; + + public GetRemoteVmsCommand(String remoteIp, String username, String password) { + this.remoteIp = remoteIp; + this.username = username; + this.password = password; + } + + public String getRemoteIp() { + return remoteIp; + } + + public void setRemoteIp(String remoteIp) { + this.remoteIp = remoteIp; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public GetRemoteVmsCommand() { + } + + @Override + public boolean executeInSequence() { + return false; + } + + public String getString() { + return "GetRemoteVmsCommand [remoteIp=" + remoteIp + "]"; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java index 3c6118d426e..950930ec614 100644 --- a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java +++ b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesAnswer.java @@ -21,15 +21,19 @@ import java.util.HashMap; import org.apache.cloudstack.vm.UnmanagedInstanceTO; -@LogLevel(LogLevel.Log4jLevel.Trace) public class GetUnmanagedInstancesAnswer extends Answer { private String instanceName; + @LogLevel(LogLevel.Log4jLevel.Trace) private HashMap unmanagedInstances; GetUnmanagedInstancesAnswer() { } + public GetUnmanagedInstancesAnswer(GetUnmanagedInstancesCommand cmd, String details) { + super(cmd, false, details); + } + public GetUnmanagedInstancesAnswer(GetUnmanagedInstancesCommand cmd, String details, HashMap unmanagedInstances) { super(cmd, true, details); this.instanceName = cmd.getInstanceName(); diff --git a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java index 2cd80aebea1..c0b8987e152 100644 --- a/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java +++ b/core/src/main/java/com/cloud/agent/api/GetUnmanagedInstancesCommand.java @@ -28,10 +28,10 @@ import org.apache.commons.collections.CollectionUtils; * All managed instances will be filtered while trying to find unmanaged instances. */ -@LogLevel(LogLevel.Log4jLevel.Trace) public class GetUnmanagedInstancesCommand extends Command { String instanceName; + @LogLevel(LogLevel.Log4jLevel.Trace) List managedInstancesNames; public GetUnmanagedInstancesCommand() { diff --git a/core/src/main/java/com/cloud/agent/api/GetVolumeStatAnswer.java b/core/src/main/java/com/cloud/agent/api/GetVolumeStatAnswer.java new file mode 100644 index 00000000000..8352c97c108 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/GetVolumeStatAnswer.java @@ -0,0 +1,85 @@ +// +// 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; + +import com.cloud.agent.api.LogLevel.Log4jLevel; +import com.cloud.storage.Storage.StoragePoolType; + +@LogLevel(Log4jLevel.Trace) +public class GetVolumeStatAnswer extends Answer { + String poolUuid; + StoragePoolType poolType; + String volumePath; + long size = 0; + long virtualSize = 0; + + public GetVolumeStatAnswer(GetVolumeStatCommand cmd, long size, long virtualSize) { + super(cmd, true, ""); + this.poolUuid = cmd.getPoolUuid(); + this.poolType = cmd.getPoolType(); + this.volumePath = cmd.getVolumePath(); + this.size = size; + this.virtualSize = virtualSize; + } + + public GetVolumeStatAnswer(GetVolumeStatCommand cmd, boolean success, String details) { + super(cmd, success, details); + } + + protected GetVolumeStatAnswer() { + //no-args constructor for json serialization-deserialization + } + + public String getPoolUuid() { + return poolUuid; + } + + public void setPoolUuid(String poolUuid) { + this.poolUuid = poolUuid; + } + + public StoragePoolType getPoolType() { + return poolType; + } + + public void setPoolType(StoragePoolType poolType) { + this.poolType = poolType; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public long getVirtualSize() { + return virtualSize; + } + + public void setVirtualSize(long virtualSize) { + this.virtualSize = virtualSize; + } + + public String getString() { + return "GetVolumeStatAnswer [poolUuid=" + poolUuid + ", poolType=" + poolType + ", volumePath=" + volumePath + ", size=" + size + ", virtualSize=" + virtualSize + "]"; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/GetVolumeStatCommand.java b/core/src/main/java/com/cloud/agent/api/GetVolumeStatCommand.java new file mode 100644 index 00000000000..1be3d6a0419 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/GetVolumeStatCommand.java @@ -0,0 +1,72 @@ +// +// 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; + +import com.cloud.agent.api.LogLevel.Log4jLevel; +import com.cloud.storage.Storage.StoragePoolType; + +@LogLevel(Log4jLevel.Trace) +public class GetVolumeStatCommand extends Command { + String volumePath; + StoragePoolType poolType; + String poolUuid; + + protected GetVolumeStatCommand() { + } + + public GetVolumeStatCommand(String volumePath, StoragePoolType poolType, String poolUuid) { + this.volumePath = volumePath; + this.poolType = poolType; + this.poolUuid = poolUuid; + } + + public String getVolumePath() { + return volumePath; + } + + public void setVolumePath(String volumePath) { + this.volumePath = volumePath; + } + + public StoragePoolType getPoolType() { + return poolType; + } + + public void setPoolType(StoragePoolType poolType) { + this.poolType = poolType; + } + + public String getPoolUuid() { + return poolUuid; + } + + public void setPoolUuid(String storeUuid) { + this.poolUuid = storeUuid; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public String getString() { + return "GetVolumeStatCommand [volumePath=" + volumePath + ", poolType=" + poolType + ", poolUuid=" + poolUuid + "]"; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/GetVolumesOnStorageAnswer.java b/core/src/main/java/com/cloud/agent/api/GetVolumesOnStorageAnswer.java new file mode 100644 index 00000000000..3c46994499d --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/GetVolumesOnStorageAnswer.java @@ -0,0 +1,42 @@ +// 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; + +import org.apache.cloudstack.storage.volume.VolumeOnStorageTO; + +import java.util.List; + +public class GetVolumesOnStorageAnswer extends Answer { + private List volumes; + + GetVolumesOnStorageAnswer() { + } + + public GetVolumesOnStorageAnswer(GetVolumesOnStorageCommand cmd, List volumes) { + super(cmd, true, null); + this.volumes = volumes; + } + + public GetVolumesOnStorageAnswer(final GetVolumesOnStorageCommand cmd, final boolean success, final String details) { + super(cmd, success, details); + } + + public List getVolumes() { + return volumes; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/GetVolumesOnStorageCommand.java b/core/src/main/java/com/cloud/agent/api/GetVolumesOnStorageCommand.java new file mode 100644 index 00000000000..6bc3356eb67 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/GetVolumesOnStorageCommand.java @@ -0,0 +1,55 @@ +// +// 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; + +import com.cloud.agent.api.to.StorageFilerTO; + +public class GetVolumesOnStorageCommand extends Command { + + StorageFilerTO pool; + private String volumePath; //search by file path + private String keyword; //filter by keyword + + public GetVolumesOnStorageCommand() { + } + + public GetVolumesOnStorageCommand(StorageFilerTO pool, String filePath, String keyword) { + this.pool = pool; + this.volumePath = filePath; + this.keyword = keyword; + } + + public StorageFilerTO getPool() { + return pool; + } + + public String getVolumePath() { + return volumePath; + } + + public String getKeyword() { + return keyword; + } + + @Override + public boolean executeInSequence() { + return false; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/MigrateCommand.java b/core/src/main/java/com/cloud/agent/api/MigrateCommand.java index 27251f4bb78..3acdb9c351b 100644 --- a/core/src/main/java/com/cloud/agent/api/MigrateCommand.java +++ b/core/src/main/java/com/cloud/agent/api/MigrateCommand.java @@ -40,6 +40,9 @@ public class MigrateCommand extends Command { private boolean executeInSequence = false; private List migrateDiskInfoList = new ArrayList<>(); private Map dpdkInterfaceMapping = new HashMap<>(); + + private int newVmCpuShares; + Map vlanToPersistenceMap = new HashMap<>(); public Map getDpdkInterfaceMapping() { @@ -138,6 +141,14 @@ public class MigrateCommand extends Command { this.migrateDiskInfoList = migrateDiskInfoList; } + public int getNewVmCpuShares() { + return newVmCpuShares; + } + + public void setNewVmCpuShares(int newVmCpuShares) { + this.newVmCpuShares = newVmCpuShares; + } + public static class MigrateDiskInfo { public enum DiskType { FILE, BLOCK; diff --git a/core/src/main/java/com/cloud/agent/api/ModifyStoragePoolCommand.java b/core/src/main/java/com/cloud/agent/api/ModifyStoragePoolCommand.java index ad05fe1d615..06940266b53 100644 --- a/core/src/main/java/com/cloud/agent/api/ModifyStoragePoolCommand.java +++ b/core/src/main/java/com/cloud/agent/api/ModifyStoragePoolCommand.java @@ -46,6 +46,10 @@ public class ModifyStoragePoolCommand extends Command { this.details = details; } + public ModifyStoragePoolCommand(boolean add, StoragePool pool, Map details) { + this(add, pool, LOCAL_PATH_PREFIX + File.separator + UUID.nameUUIDFromBytes((pool.getHostAddress() + pool.getPath()).getBytes()), details); + } + public ModifyStoragePoolCommand(boolean add, StoragePool pool) { this(add, pool, LOCAL_PATH_PREFIX + File.separator + UUID.nameUUIDFromBytes((pool.getHostAddress() + pool.getPath()).getBytes())); } diff --git a/core/src/main/java/com/cloud/agent/api/PingAnswer.java b/core/src/main/java/com/cloud/agent/api/PingAnswer.java index 35242380739..6353b121583 100644 --- a/core/src/main/java/com/cloud/agent/api/PingAnswer.java +++ b/core/src/main/java/com/cloud/agent/api/PingAnswer.java @@ -22,15 +22,26 @@ package com.cloud.agent.api; public class PingAnswer extends Answer { private PingCommand _command = null; + private boolean sendStartup = false; + protected PingAnswer() { } - public PingAnswer(PingCommand cmd) { + public PingAnswer(PingCommand cmd, boolean sendStartup) { super(cmd); _command = cmd; + this.sendStartup = sendStartup; } public PingCommand getCommand() { return _command; } + + public boolean isSendStartup() { + return sendStartup; + } + + public void setSendStartup(boolean sendStartup) { + this.sendStartup = sendStartup; + } } diff --git a/core/src/main/java/com/cloud/agent/api/PingCommand.java b/core/src/main/java/com/cloud/agent/api/PingCommand.java index 1d62c5d1359..4192fc2e747 100644 --- a/core/src/main/java/com/cloud/agent/api/PingCommand.java +++ b/core/src/main/java/com/cloud/agent/api/PingCommand.java @@ -24,6 +24,7 @@ import com.cloud.host.Host; public class PingCommand extends Command { Host.Type hostType; long hostId; + boolean outOfBand; protected PingCommand() { } @@ -33,6 +34,12 @@ public class PingCommand extends Command { hostId = id; } + public PingCommand(Host.Type type, long id, boolean oob) { + hostType = type; + hostId = id; + outOfBand = oob; + } + public Host.Type getHostType() { return hostType; } @@ -41,6 +48,10 @@ public class PingCommand extends Command { return hostId; } + public boolean getOutOfBand() { return outOfBand; } + + public void setOutOfBand(boolean oob) { this.outOfBand = oob; } + @Override public boolean executeInSequence() { return false; diff --git a/core/src/main/java/com/cloud/agent/api/PrepareForMigrationAnswer.java b/core/src/main/java/com/cloud/agent/api/PrepareForMigrationAnswer.java index d0a544ba081..190e844ddc5 100644 --- a/core/src/main/java/com/cloud/agent/api/PrepareForMigrationAnswer.java +++ b/core/src/main/java/com/cloud/agent/api/PrepareForMigrationAnswer.java @@ -28,6 +28,8 @@ public class PrepareForMigrationAnswer extends Answer { private Map dpdkInterfaceMapping = new HashMap<>(); + private Integer newVmCpuShares = null; + protected PrepareForMigrationAnswer() { } @@ -50,4 +52,12 @@ public class PrepareForMigrationAnswer extends Answer { public Map getDpdkInterfaceMapping() { return this.dpdkInterfaceMapping; } + + public Integer getNewVmCpuShares() { + return newVmCpuShares; + } + + public void setNewVmCpuShares(Integer newVmCpuShares) { + this.newVmCpuShares = newVmCpuShares; + } } diff --git a/core/src/main/java/com/cloud/agent/api/PrepareStorageClientAnswer.java b/core/src/main/java/com/cloud/agent/api/PrepareStorageClientAnswer.java new file mode 100644 index 00000000000..85afb925646 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/PrepareStorageClientAnswer.java @@ -0,0 +1,43 @@ +// +// 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; + +import java.util.Map; + +public class PrepareStorageClientAnswer extends Answer { + Map detailsMap; + + public PrepareStorageClientAnswer() { + super(); + } + + public PrepareStorageClientAnswer(Command command, boolean success, Map detailsMap) { + super(command, success, ""); + this.detailsMap = detailsMap; + } + + public PrepareStorageClientAnswer(Command command, boolean success, String details) { + super(command, success, details); + } + + public Map getDetailsMap() { + return detailsMap; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/PrepareStorageClientCommand.java b/core/src/main/java/com/cloud/agent/api/PrepareStorageClientCommand.java new file mode 100644 index 00000000000..8dea9c11c53 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/PrepareStorageClientCommand.java @@ -0,0 +1,56 @@ +// +// 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; + +import java.util.Map; + +import com.cloud.storage.Storage.StoragePoolType; + +public class PrepareStorageClientCommand extends Command { + private StoragePoolType poolType; + private String poolUuid; + private Map details; + + public PrepareStorageClientCommand() { + } + + public PrepareStorageClientCommand(StoragePoolType poolType, String poolUuid, Map details) { + this.poolType = poolType; + this.poolUuid = poolUuid; + this.details = details; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public StoragePoolType getPoolType() { + return poolType; + } + + public String getPoolUuid() { + return poolUuid; + } + + public Map getDetails() { + return details; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/SecurityGroupRulesCmd.java b/core/src/main/java/com/cloud/agent/api/SecurityGroupRulesCmd.java index ea4ab96c5a7..5d202172c35 100644 --- a/core/src/main/java/com/cloud/agent/api/SecurityGroupRulesCmd.java +++ b/core/src/main/java/com/cloud/agent/api/SecurityGroupRulesCmd.java @@ -27,7 +27,6 @@ import java.util.zip.DeflaterOutputStream; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; -import org.apache.log4j.Logger; import com.cloud.agent.api.LogLevel.Log4jLevel; import com.cloud.agent.api.to.VirtualMachineTO; @@ -39,7 +38,6 @@ public class SecurityGroupRulesCmd extends Command { public static final char RULE_COMMAND_SEPARATOR = ';'; protected static final String EGRESS_RULE = "E:"; protected static final String INGRESS_RULE = "I:"; - private static final Logger LOGGER = Logger.getLogger(SecurityGroupRulesCmd.class); private final String guestIp; private final String guestIp6; @@ -233,7 +231,7 @@ public class SecurityGroupRulesCmd extends Command { dzip.close(); encodedResult = Base64.encodeBase64String(out.toByteArray()); } catch (final IOException e) { - LOGGER.warn("Exception while compressing security group rules"); + logger.warn("Exception while compressing security group rules"); } return encodedResult; } diff --git a/core/src/main/java/com/cloud/agent/api/SetupGuestNetworkCommand.java b/core/src/main/java/com/cloud/agent/api/SetupGuestNetworkCommand.java index e9781993239..06583f2d0d3 100644 --- a/core/src/main/java/com/cloud/agent/api/SetupGuestNetworkCommand.java +++ b/core/src/main/java/com/cloud/agent/api/SetupGuestNetworkCommand.java @@ -35,6 +35,7 @@ public class SetupGuestNetworkCommand extends NetworkElementCommand { String routerIpv6 = null; String routerIpv6Gateway = null; String routerIpv6Cidr = null; + boolean isVrGuestGateway = false; public NicTO getNic() { return nic; @@ -114,4 +115,12 @@ public class SetupGuestNetworkCommand extends NetworkElementCommand { public void setDefaultIp6Dns2(String defaultIp6Dns2) { this.defaultIp6Dns2 = defaultIp6Dns2; } + + public boolean isVrGuestGateway() { + return isVrGuestGateway; + } + + public void setVrGuestGateway(boolean vrGuestGateway) { + isVrGuestGateway = vrGuestGateway; + } } diff --git a/core/src/main/java/com/cloud/agent/api/StartupRoutingCommand.java b/core/src/main/java/com/cloud/agent/api/StartupRoutingCommand.java index b4f9d20df5e..2d4ed8c9cc4 100644 --- a/core/src/main/java/com/cloud/agent/api/StartupRoutingCommand.java +++ b/core/src/main/java/com/cloud/agent/api/StartupRoutingCommand.java @@ -174,6 +174,10 @@ public class StartupRoutingCommand extends StartupCommand { this.hostTags.add(hostTag); } + public void setHostTags(List hostTags) { + this.hostTags = hostTags; + } + public HashMap> getGpuGroupDetails() { return groupDetails; } diff --git a/core/src/main/java/com/cloud/agent/api/UnprepareStorageClientAnswer.java b/core/src/main/java/com/cloud/agent/api/UnprepareStorageClientAnswer.java new file mode 100644 index 00000000000..1280293db0d --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/UnprepareStorageClientAnswer.java @@ -0,0 +1,34 @@ +// +// 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; + +public class UnprepareStorageClientAnswer extends Answer { + public UnprepareStorageClientAnswer() { + super(); + } + + public UnprepareStorageClientAnswer(Command command, boolean success) { + super(command, success, ""); + } + + public UnprepareStorageClientAnswer(Command command, boolean success, String details) { + super(command, success, details); + } +} diff --git a/core/src/main/java/com/cloud/agent/api/UnprepareStorageClientCommand.java b/core/src/main/java/com/cloud/agent/api/UnprepareStorageClientCommand.java new file mode 100644 index 00000000000..bebd30ca519 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/UnprepareStorageClientCommand.java @@ -0,0 +1,48 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.agent.api; + +import com.cloud.storage.Storage.StoragePoolType; + +public class UnprepareStorageClientCommand extends Command { + private StoragePoolType poolType; + private String poolUuid; + + public UnprepareStorageClientCommand() { + } + + public UnprepareStorageClientCommand(StoragePoolType poolType, String poolUuid) { + this.poolType = poolType; + this.poolUuid = poolUuid; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public StoragePoolType getPoolType() { + return poolType; + } + + public String getPoolUuid() { + return poolUuid; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/storage/CheckAndRepairVolumeAnswer.java b/core/src/main/java/com/cloud/agent/api/storage/CheckAndRepairVolumeAnswer.java new file mode 100644 index 00000000000..3dc7752bfef --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/storage/CheckAndRepairVolumeAnswer.java @@ -0,0 +1,57 @@ +// +// 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.storage; + +import com.cloud.agent.api.Answer; + +public class CheckAndRepairVolumeAnswer extends Answer { + private String volumeCheckExecutionResult; + private String volumeRepairExecutionResult; + + protected CheckAndRepairVolumeAnswer() { + super(); + } + + public CheckAndRepairVolumeAnswer(CheckAndRepairVolumeCommand cmd, boolean result, String details, String volumeCheckExecutionResult, String volumeRepairedExecutionResult) { + super(cmd, result, details); + this.volumeCheckExecutionResult = volumeCheckExecutionResult; + this.volumeRepairExecutionResult = volumeRepairedExecutionResult; + } + + public CheckAndRepairVolumeAnswer(CheckAndRepairVolumeCommand cmd, boolean result, String details) { + super(cmd, result, details); + } + + public String getVolumeCheckExecutionResult() { + return volumeCheckExecutionResult; + } + + public String getVolumeRepairExecutionResult() { + return volumeRepairExecutionResult; + } + + public void setVolumeCheckExecutionResult(String volumeCheckExecutionResult) { + this.volumeCheckExecutionResult = volumeCheckExecutionResult; + } + + public void setVolumeRepairExecutionResult(String volumeRepairExecutionResult) { + this.volumeRepairExecutionResult = volumeRepairExecutionResult; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/storage/CheckAndRepairVolumeCommand.java b/core/src/main/java/com/cloud/agent/api/storage/CheckAndRepairVolumeCommand.java new file mode 100644 index 00000000000..2553fdf477c --- /dev/null +++ b/core/src/main/java/com/cloud/agent/api/storage/CheckAndRepairVolumeCommand.java @@ -0,0 +1,77 @@ +// +// 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.storage; + +import com.cloud.agent.api.Command; +import com.cloud.agent.api.LogLevel; +import com.cloud.agent.api.to.StorageFilerTO; + +import java.util.Arrays; + +public class CheckAndRepairVolumeCommand extends Command { + private String path; + private StorageFilerTO pool; + private String repair; + @LogLevel(LogLevel.Log4jLevel.Off) + private byte[] passphrase; + private String encryptFormat; + + public CheckAndRepairVolumeCommand(String path, StorageFilerTO pool, String repair, byte[] passphrase, String encryptFormat) { + this.path = path; + this.pool = pool; + this.repair = repair; + this.passphrase = passphrase; + this.encryptFormat = encryptFormat; + } + + public String getPath() { + return path; + } + + public String getPoolUuid() { + return pool.getUuid(); + } + + public StorageFilerTO getPool() { + return pool; + } + + public String getRepair() { + return repair; + } + + public String getEncryptFormat() { return encryptFormat; } + + public byte[] getPassphrase() { return passphrase; } + + public void clearPassphrase() { + if (this.passphrase != null) { + Arrays.fill(this.passphrase, (byte) 0); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean executeInSequence() { + return false; + } +} diff --git a/core/src/main/java/com/cloud/agent/api/storage/CreateEntityDownloadURLAnswer.java b/core/src/main/java/com/cloud/agent/api/storage/CreateEntityDownloadURLAnswer.java index cdcb3c0445a..4fdd6d48896 100644 --- a/core/src/main/java/com/cloud/agent/api/storage/CreateEntityDownloadURLAnswer.java +++ b/core/src/main/java/com/cloud/agent/api/storage/CreateEntityDownloadURLAnswer.java @@ -23,18 +23,15 @@ import com.cloud.agent.api.Answer; public class CreateEntityDownloadURLAnswer extends Answer { - String resultString; - short resultCode; public static final short RESULT_SUCCESS = 1; public static final short RESULT_FAILURE = 0; public CreateEntityDownloadURLAnswer(String resultString, short resultCode) { super(); - this.resultString = resultString; - this.resultCode = resultCode; + this.details = resultString; + this.result = resultCode == RESULT_SUCCESS; } public CreateEntityDownloadURLAnswer() { } - } diff --git a/core/src/main/java/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java b/core/src/main/java/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java index c84eceb0ca2..33403580b6f 100644 --- a/core/src/main/java/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java +++ b/core/src/main/java/com/cloud/agent/api/storage/CreateEntityDownloadURLCommand.java @@ -23,18 +23,19 @@ import com.cloud.agent.api.to.DataTO; public class CreateEntityDownloadURLCommand extends AbstractDownloadCommand { - public CreateEntityDownloadURLCommand(String parent, String installPath, String uuid, DataTO data) { // this constructor is for creating template download url + public CreateEntityDownloadURLCommand(String parent, String installPath, String fileName, String filePath, DataTO data) { // this constructor is for creating template download url super(); this.parent = parent; // parent is required as not the template can be child of one of many parents this.installPath = installPath; - this.extractLinkUUID = uuid; + this.filenameInExtractURL = fileName; + this.filepathInExtractURL = filePath; this.data = data; } - public CreateEntityDownloadURLCommand(String installPath, String uuid) { + public CreateEntityDownloadURLCommand(String installPath, String filename) { super(); this.installPath = installPath; - this.extractLinkUUID = uuid; + this.filenameInExtractURL = filename; } public CreateEntityDownloadURLCommand() { @@ -42,7 +43,8 @@ public class CreateEntityDownloadURLCommand extends AbstractDownloadCommand { private String installPath; private String parent; - private String extractLinkUUID; + private String filenameInExtractURL; + private String filepathInExtractURL; public DataTO getData() { return data; @@ -75,12 +77,19 @@ public class CreateEntityDownloadURLCommand extends AbstractDownloadCommand { this.parent = parent; } - public String getExtractLinkUUID() { - return extractLinkUUID; + public String getFilenameInExtractURL() { + return filenameInExtractURL; } - public void setExtractLinkUUID(String extractLinkUUID) { - this.extractLinkUUID = extractLinkUUID; + public void setFilenameInExtractURL(String filenameInExtractURL) { + this.filenameInExtractURL = filenameInExtractURL; } + public String getFilepathInExtractURL() { + return filepathInExtractURL; + } + + public void setFilepathInExtractURL(String filepathInExtractURL) { + this.filepathInExtractURL = filepathInExtractURL; + } } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java index ebe5e9a7ec9..e435c838b7d 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VRScripts.java @@ -81,4 +81,5 @@ public class VRScripts { public static final String VR_UPDATE_INTERFACE_CONFIG = "update_interface_config.sh"; public static final String ROUTER_FILESYSTEM_WRITABLE_CHECK = "filesystem_writable_check.py"; + public static final String MANAGE_SERVICE = "manage_service.sh"; } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index 4492947b2cc..4afac9b43cb 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -34,6 +34,7 @@ import java.util.concurrent.locks.ReentrantLock; import javax.naming.ConfigurationException; +import org.apache.cloudstack.agent.routing.ManageServiceCommand; import com.cloud.agent.api.routing.UpdateNetworkCommand; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.network.router.VirtualRouter; @@ -51,7 +52,8 @@ import org.apache.cloudstack.diagnostics.PrepareFilesCommand; import org.apache.cloudstack.utils.security.KeyStoreUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.net.util.SubnetUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import org.joda.time.Duration; import com.cloud.agent.api.Answer; @@ -85,7 +87,7 @@ import com.cloud.utils.exception.CloudRuntimeException; **/ public class VirtualRoutingResource { - private static final Logger s_logger = Logger.getLogger(VirtualRoutingResource.class); + protected Logger logger = LogManager.getLogger(getClass()); private VirtualRouterDeployer _vrDeployer; private Map> _vrAggregateCommandsSet; protected Map _vrLockMap = new HashMap(); @@ -117,7 +119,7 @@ public class VirtualRoutingResource { try { ExecutionResult rc = _vrDeployer.prepareCommand(cmd); if (!rc.isSuccess()) { - s_logger.error("Failed to prepare VR command due to " + rc.getDetails()); + logger.error("Failed to prepare VR command due to " + rc.getDetails()); return new Answer(cmd, false, rc.getDetails()); } @@ -143,6 +145,10 @@ public class VirtualRoutingResource { return execute((UpdateNetworkCommand) cmd); } + if (cmd instanceof ManageServiceCommand) { + return execute((ManageServiceCommand) cmd); + } + if (_vrAggregateCommandsSet.containsKey(routerName)) { _vrAggregateCommandsSet.get(routerName).add(cmd); aggregated = true; @@ -164,7 +170,7 @@ public class VirtualRoutingResource { if (!aggregated) { ExecutionResult rc = _vrDeployer.cleanupCommand(cmd); if (!rc.isSuccess()) { - s_logger.error("Failed to cleanup VR command due to " + rc.getDetails()); + logger.error("Failed to cleanup VR command due to " + rc.getDetails()); } } } @@ -220,15 +226,15 @@ public class VirtualRoutingResource { } else if (cmd instanceof GetRouterMonitorResultsCommand) { return execute((GetRouterMonitorResultsCommand)cmd); } else { - s_logger.error("Unknown query command in VirtualRoutingResource!"); + logger.error("Unknown query command in VirtualRoutingResource!"); return Answer.createUnsupportedCommandAnswer(cmd); } } - private static String getRouterSshControlIp(NetworkElementCommand cmd) { + private String getRouterSshControlIp(NetworkElementCommand cmd) { String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); - if (s_logger.isDebugEnabled()) - s_logger.debug("Use router's private IP for SSH control. IP : " + routerIp); + if (logger.isDebugEnabled()) + logger.debug("Use router's private IP for SSH control. IP : " + routerIp); return routerIp; } @@ -243,24 +249,24 @@ public class VirtualRoutingResource { String subnet = address.split("/")[1]; ExecutionResult result = _vrDeployer.executeInVR(routerIp, VRScripts.VR_UPDATE_INTERFACE_CONFIG, ipAddressTO.getPublicIp() + " " + subnet + " " + ipAddressTO.getMtu() + " " + 15); - if (s_logger.isDebugEnabled()) - s_logger.debug("result: " + result.isSuccess() + ", output: " + result.getDetails()); + if (logger.isDebugEnabled()) + logger.debug("result: " + result.isSuccess() + ", output: " + result.getDetails()); if (!Boolean.TRUE.equals(result.isSuccess())) { if (result.getDetails().contains(String.format("Interface with IP %s not found", ipAddressTO.getPublicIp()))) { - s_logger.warn(String.format("Skipping IP: %s as it isn't configured on router interface", ipAddressTO.getPublicIp())); + logger.warn(String.format("Skipping IP: %s as it isn't configured on router interface", ipAddressTO.getPublicIp())); } else if (ipAddressTO.getDetails().get(ApiConstants.REDUNDANT_STATE).equals(VirtualRouter.RedundantState.PRIMARY.name())) { - s_logger.warn(String.format("Failed to update interface mtu to %s on interface with ip: %s", + logger.warn(String.format("Failed to update interface mtu to %s on interface with ip: %s", ipAddressTO.getMtu(), ipAddressTO.getPublicIp())); finalResult = false; } continue; } - s_logger.info(String.format("Successfully updated mtu to %s on interface with ip: %s", + logger.info(String.format("Successfully updated mtu to %s on interface with ip: %s", ipAddressTO.getMtu(), ipAddressTO.getPublicIp())); finalResult &= true; } catch (Exception e) { String msg = "Prepare UpdateNetwork failed due to " + e.toString(); - s_logger.error(msg, e); + logger.error(msg, e); return new Answer(cmd, e); } } @@ -270,6 +276,20 @@ public class VirtualRoutingResource { return new Answer(cmd, new CloudRuntimeException("Failed to update interface mtu")); } + private Answer execute(ManageServiceCommand cmd) { + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + String args = cmd.getAction() + " " + cmd.getServiceName(); + ExecutionResult result = _vrDeployer.executeInVR(routerIp, VRScripts.MANAGE_SERVICE, args); + if (result.isSuccess()) { + return new Answer(cmd, true, + String.format("Successfully executed action: %s on service: %s. Details: %s", + cmd.getAction(), cmd.getServiceName(), result.getDetails())); + } else { + return new Answer(cmd, false, String.format("Failed to execute action: %s on service: %s. Details: %s", + cmd.getAction(), cmd.getServiceName(), result.getDetails())); + } + } + private ExecutionResult applyConfigToVR(String routerAccessIp, ConfigItem c) { return applyConfigToVR(routerAccessIp, c, VRScripts.VR_SCRIPT_EXEC_TIMEOUT); } @@ -296,9 +316,9 @@ public class VirtualRoutingResource { for (ConfigItem configItem : cfg) { long startTimestamp = System.currentTimeMillis(); ExecutionResult result = applyConfigToVR(cmd.getRouterAccessIp(), configItem, VRScripts.VR_SCRIPT_EXEC_TIMEOUT); - if (s_logger.isDebugEnabled()) { + if (logger.isDebugEnabled()) { long elapsed = System.currentTimeMillis() - startTimestamp; - s_logger.debug("Processing " + configItem + " took " + elapsed + "ms"); + logger.debug("Processing " + configItem + " took " + elapsed + "ms"); } if (result == null) { result = new ExecutionResult(false, "null execution result"); @@ -310,7 +330,7 @@ public class VirtualRoutingResource { // Not sure why this matters, but log it anyway if (cmd.getAnswersCount() != results.size()) { - s_logger.warn("Expected " + cmd.getAnswersCount() + " answers while executing " + cmd.getClass().getSimpleName() + " but received " + results.size()); + logger.warn("Expected " + cmd.getAnswersCount() + " answers while executing " + cmd.getClass().getSimpleName() + " but received " + results.size()); } if (results.size() == 1) { @@ -359,7 +379,7 @@ public class VirtualRoutingResource { } else if (!readingFailedChecks && readingMonitorResults) { // Reading monitor checks result monitorResults.append(line); } else { - s_logger.error("Unexpected lines reached while parsing health check response. Skipping line:- " + line); + logger.error("Unexpected lines reached while parsing health check response. Skipping line:- " + line); } } @@ -379,16 +399,16 @@ public class VirtualRoutingResource { } String args = cmd.shouldPerformFreshChecks() ? "true" : "false"; - s_logger.info("Fetching health check result for " + routerIp + " and executing fresh checks: " + args); + logger.info("Fetching health check result for " + routerIp + " and executing fresh checks: " + args); ExecutionResult result = _vrDeployer.executeInVR(routerIp, VRScripts.ROUTER_MONITOR_RESULTS, args); if (!result.isSuccess()) { - s_logger.warn("Result of " + cmd + " failed with details: " + result.getDetails()); + logger.warn("Result of " + cmd + " failed with details: " + result.getDetails()); return new GetRouterMonitorResultsAnswer(cmd, false, null, result.getDetails()); } if (result.getDetails().isEmpty()) { - s_logger.warn("Result of " + cmd + " received no details."); + logger.warn("Result of " + cmd + " received no details."); return new GetRouterMonitorResultsAnswer(cmd, false, null, "No results available."); } @@ -398,12 +418,12 @@ public class VirtualRoutingResource { private Pair checkRouterFileSystem(String routerIp) { ExecutionResult fileSystemWritableTestResult = _vrDeployer.executeInVR(routerIp, VRScripts.ROUTER_FILESYSTEM_WRITABLE_CHECK, null); if (fileSystemWritableTestResult.isSuccess()) { - s_logger.debug("Router connectivity and file system writable check passed"); + logger.debug("Router connectivity and file system writable check passed"); return new Pair(true, "success"); } String resultDetails = fileSystemWritableTestResult.getDetails(); - s_logger.warn("File system writable check failed with details: " + resultDetails); + logger.warn("File system writable check failed with details: " + resultDetails); if (StringUtils.isNotBlank(resultDetails)) { final String readOnlyFileSystemError = "Read-only file system"; if (resultDetails.contains(readOnlyFileSystemError)) { @@ -488,8 +508,8 @@ public class VirtualRoutingResource { if (params.get("router.aggregation.command.each.timeout") != null) { String value = (String)params.get("router.aggregation.command.each.timeout"); _eachTimeout = Duration.standardSeconds(NumbersUtil.parseLong(value, 600)); - if (s_logger.isDebugEnabled()){ - s_logger.debug("The router.aggregation.command.each.timeout in seconds is set to " + _eachTimeout.getStandardSeconds()); + if (logger.isDebugEnabled()){ + logger.debug("The router.aggregation.command.each.timeout in seconds is set to " + _eachTimeout.getStandardSeconds()); } } @@ -510,8 +530,8 @@ public class VirtualRoutingResource { value = (String)params.get("router.aggregation.command.each.timeout"); _eachTimeout = Duration.standardSeconds(NumbersUtil.parseInt(value, (int)VRScripts.VR_SCRIPT_EXEC_TIMEOUT.getStandardSeconds())); - if (s_logger.isDebugEnabled()){ - s_logger.debug("The router.aggregation.command.each.timeout in seconds is set to " + _eachTimeout.getStandardSeconds()); + if (logger.isDebugEnabled()){ + logger.debug("The router.aggregation.command.each.timeout in seconds is set to " + _eachTimeout.getStandardSeconds()); } if (_vrDeployer == null) { @@ -534,8 +554,8 @@ public class VirtualRoutingResource { for (int i = 0; i <= retry; i++) { SocketChannel sch = null; try { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Trying to connect to " + ipAddress); + if (logger.isDebugEnabled()) { + logger.debug("Trying to connect to " + ipAddress); } sch = SocketChannel.open(); sch.configureBlocking(true); @@ -544,8 +564,8 @@ public class VirtualRoutingResource { sch.connect(addr); return true; } catch (final IOException e) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Could not connect to " + ipAddress); + if (logger.isDebugEnabled()) { + logger.debug("Could not connect to " + ipAddress); } } finally { if (sch != null) { @@ -561,7 +581,7 @@ public class VirtualRoutingResource { } } - s_logger.debug("Unable to logon to " + ipAddress); + logger.debug("Unable to logon to " + ipAddress); return false; } @@ -571,7 +591,7 @@ public class VirtualRoutingResource { * [TODO] Still have to migrate LoadBalancerConfigCommand and BumpUpPriorityCommand * [FIXME] Have a look at SetSourceNatConfigItem */ - s_logger.debug("Transforming " + cmd.getClass().getCanonicalName() + " to ConfigItems"); + logger.debug("Transforming " + cmd.getClass().getCanonicalName() + " to ConfigItems"); final AbstractConfigItemFacade configItemFacade = AbstractConfigItemFacade.getInstance(cmd.getClass()); @@ -601,7 +621,7 @@ public class VirtualRoutingResource { answerCounts += command.getAnswersCount(); List cfg = generateCommandCfg(command); if (cfg == null) { - s_logger.warn("Unknown commands for VirtualRoutingResource, but continue: " + cmd.toString()); + logger.warn("Unknown commands for VirtualRoutingResource, but continue: " + cmd.toString()); continue; } @@ -616,8 +636,8 @@ public class VirtualRoutingResource { ScriptConfigItem scriptConfigItem = new ScriptConfigItem(VRScripts.VR_CFG, "-c " + VRScripts.CONFIG_CACHE_LOCATION + cfgFileName); // 120s is the minimal timeout Duration timeout = _eachTimeout.withDurationAdded(_eachTimeout.getStandardSeconds(), answerCounts); - if (s_logger.isDebugEnabled()){ - s_logger.debug("Aggregate action timeout in seconds is " + timeout.getStandardSeconds()); + if (logger.isDebugEnabled()){ + logger.debug("Aggregate action timeout in seconds is " + timeout.getStandardSeconds()); } ExecutionResult result = applyConfigToVR(cmd.getRouterAccessIp(), fileConfigItem, timeout); diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java index bed472b6880..46dd801bebf 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java @@ -24,7 +24,6 @@ import java.util.LinkedList; import java.util.List; import java.util.UUID; -import org.apache.log4j.Logger; import com.cloud.agent.api.BumpUpPriorityCommand; import com.cloud.agent.api.SetupGuestNetworkCommand; @@ -59,10 +58,12 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; public abstract class AbstractConfigItemFacade { - private static final Logger s_logger = Logger.getLogger(AbstractConfigItemFacade.class); + protected Logger logger = LogManager.getLogger(getClass()); private final static Gson gson; @@ -123,8 +124,8 @@ public abstract class AbstractConfigItemFacade { final List cfg = new LinkedList<>(); final String remoteFilename = appendUuidToJsonFiles(destinationFile); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Transformed filename: " + destinationFile + " to: " + remoteFilename); + if (logger.isDebugEnabled()) { + logger.debug("Transformed filename: " + destinationFile + " to: " + remoteFilename); } final ConfigItem configFile = new FileConfigItem(VRScripts.CONFIG_PERSIST_LOCATION, remoteFilename, gson.toJson(configuration)); diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetGuestNetworkConfigItem.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetGuestNetworkConfigItem.java index aee1e779571..1a6824ceb7f 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetGuestNetworkConfigItem.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetGuestNetworkConfigItem.java @@ -75,6 +75,7 @@ public class SetGuestNetworkConfigItem extends AbstractConfigItemFacade { guestNetwork.setRouterIp6(command.getRouterIpv6()); guestNetwork.setRouterIp6Gateway(command.getRouterIpv6Gateway()); guestNetwork.setRouterIp6Cidr(command.getRouterIpv6Cidr()); + guestNetwork.setVrGuestGateway(command.isVrGuestGateway()); return generateConfigItems(guestNetwork); } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetMonitorServiceConfigItem.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetMonitorServiceConfigItem.java index 52d8442b5ac..227675ebf4e 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetMonitorServiceConfigItem.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetMonitorServiceConfigItem.java @@ -21,7 +21,6 @@ package com.cloud.agent.resource.virtualnetwork.facade; import java.util.List; -import org.apache.log4j.Logger; import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.routing.SetMonitorServiceCommand; @@ -32,7 +31,6 @@ import com.cloud.agent.resource.virtualnetwork.model.ConfigBase; import com.cloud.agent.resource.virtualnetwork.model.MonitorService; public class SetMonitorServiceConfigItem extends AbstractConfigItemFacade { - private static final Logger s_logger = Logger.getLogger(SetMonitorServiceConfigItem.class); @Override public List generateConfig(final NetworkElementCommand cmd) { @@ -58,14 +56,14 @@ public class SetMonitorServiceConfigItem extends AbstractConfigItemFacade { try { monitorService.setHealthChecksBasicRunInterval(Integer.parseInt(command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_BASIC_INTERVAL))); } catch (NumberFormatException exception) { - s_logger.error("Unexpected health check basic interval set" + command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_BASIC_INTERVAL) + + logger.error("Unexpected health check basic interval set" + command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_BASIC_INTERVAL) + ". Exception: " + exception + "Will use default value"); } try { monitorService.setHealthChecksAdvancedRunInterval(Integer.parseInt(command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_ADVANCED_INTERVAL))); } catch (NumberFormatException exception) { - s_logger.error("Unexpected health check advanced interval set" + command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_ADVANCED_INTERVAL) + + logger.error("Unexpected health check advanced interval set" + command.getAccessDetail(SetMonitorServiceCommand.ROUTER_HEALTH_CHECKS_ADVANCED_INTERVAL) + ". Exception: " + exception + "Will use default value"); } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetNetworkAclConfigItem.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetNetworkAclConfigItem.java index a64328d516a..f4c3275aa2b 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetNetworkAclConfigItem.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/facade/SetNetworkAclConfigItem.java @@ -22,7 +22,6 @@ package com.cloud.agent.resource.virtualnetwork.facade; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.api.routing.SetNetworkACLCommand; @@ -41,7 +40,6 @@ import com.cloud.utils.net.NetUtils; public class SetNetworkAclConfigItem extends AbstractConfigItemFacade { - public static final Logger s_logger = Logger.getLogger(SetNetworkAclConfigItem.class.getName()); @Override public List generateConfig(final NetworkElementCommand cmd) { @@ -81,7 +79,7 @@ public class SetNetworkAclConfigItem extends AbstractConfigItemFacade { try { aclRule = new ProtocolAclRule(ruleParts[4], "ACCEPT".equals(ruleParts[5]), Integer.parseInt(ruleParts[1])); } catch (final Exception e) { - s_logger.warn("Problem occurred when reading the entries in the ruleParts array. Actual array size is '" + ruleParts.length + "', but trying to read from index 5."); + logger.warn("Problem occurred when reading the entries in the ruleParts array. Actual array size is '" + ruleParts.length + "', but trying to read from index 5."); continue; } } diff --git a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/GuestNetwork.java b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/GuestNetwork.java index bb5e443c2e8..a416b4bc5e4 100644 --- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/GuestNetwork.java +++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/model/GuestNetwork.java @@ -37,6 +37,7 @@ public class GuestNetwork extends ConfigBase { private String routerIp6; private String routerIp6Gateway; private String routerIp6Cidr; + private boolean isVrGuestGateway; private Integer mtu; @@ -202,4 +203,12 @@ public class GuestNetwork extends ConfigBase { public Integer getMtu() { return mtu; } + + public boolean isVrGuestGateway() { + return isVrGuestGateway; + } + + public void setVrGuestGateway(boolean vrGuestGateway) { + isVrGuestGateway = vrGuestGateway; + } } diff --git a/core/src/main/java/com/cloud/agent/transport/LoggingExclusionStrategy.java b/core/src/main/java/com/cloud/agent/transport/LoggingExclusionStrategy.java index 90e964e7139..2301c1fc205 100644 --- a/core/src/main/java/com/cloud/agent/transport/LoggingExclusionStrategy.java +++ b/core/src/main/java/com/cloud/agent/transport/LoggingExclusionStrategy.java @@ -19,7 +19,8 @@ package com.cloud.agent.transport; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import com.google.gson.ExclusionStrategy; import com.google.gson.FieldAttributes; @@ -29,7 +30,9 @@ import com.cloud.agent.api.LogLevel; import com.cloud.agent.api.LogLevel.Log4jLevel; public class LoggingExclusionStrategy implements ExclusionStrategy { - Logger _logger = null; + protected Logger exclusionLogger = null; + + protected Logger logger = LogManager.getLogger(getClass()); @Override public boolean shouldSkipClass(Class clazz) { @@ -40,20 +43,24 @@ public class LoggingExclusionStrategy implements ExclusionStrategy { LogLevel level = clazz.getAnnotation(LogLevel.class); if (level == null) { log4jLevel = LogLevel.Log4jLevel.Debug; + logger.trace("Class {} does not have any log level annotation, considering level as debug.", clazz); } else { log4jLevel = level.value(); } - return !log4jLevel.enabled(_logger); + return !log4jLevel.enabled(exclusionLogger); } @Override public boolean shouldSkipField(FieldAttributes field) { LogLevel level = field.getAnnotation(LogLevel.class); - return level != null && !level.value().enabled(_logger); + return level != null && !level.value().enabled(exclusionLogger); } public LoggingExclusionStrategy(Logger logger) { - _logger = logger; + exclusionLogger = logger; + } + + public LoggingExclusionStrategy() { } } diff --git a/core/src/main/java/com/cloud/agent/transport/Request.java b/core/src/main/java/com/cloud/agent/transport/Request.java index 28809341f78..3769dbbd612 100644 --- a/core/src/main/java/com/cloud/agent/transport/Request.java +++ b/core/src/main/java/com/cloud/agent/transport/Request.java @@ -32,12 +32,21 @@ import java.util.List; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import com.cloud.utils.HumanReadableJson; - import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.BadCommand; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig; +import com.cloud.exception.UnsupportedVersionException; +import com.cloud.serializer.GsonHelper; +import com.cloud.utils.HumanReadableJson; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; @@ -49,16 +58,6 @@ import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import com.google.gson.stream.JsonReader; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.BadCommand; -import com.cloud.agent.api.Command; -import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig; -import com.cloud.exception.UnsupportedVersionException; -import com.cloud.serializer.GsonHelper; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.Pair; -import com.cloud.utils.exception.CloudRuntimeException; - /** * Request is a simple wrapper around command and answer to add sequencing, * versioning, and flags. Note that the version here represents the changes @@ -77,7 +76,7 @@ import com.cloud.utils.exception.CloudRuntimeException; * */ public class Request { - private static final Logger s_logger = Logger.getLogger(Request.class); + protected static Logger LOGGER = LogManager.getLogger(Request.class); protected static final Gson s_gson = GsonHelper.getGson(); protected static final Gson s_gogger = GsonHelper.getGsonLogger(); @@ -253,9 +252,10 @@ public class Request { jsonReader.setLenient(true); _cmds = s_gson.fromJson(jsonReader, (Type)Command[].class); } catch (JsonParseException e) { + LOGGER.error("Caught problem while parsing JSON command " + _content, e); _cmds = new Command[] { new BadCommand() }; } catch (RuntimeException e) { - s_logger.error("Caught problem with " + _content, e); + LOGGER.error("Caught problem with " + _content, e); throw e; } } @@ -301,7 +301,7 @@ public class Request { } in.close(); } catch (IOException e) { - s_logger.error("Fail to decompress the request!", e); + LOGGER.error("Fail to decompress the request!", e); } retBuff.flip(); return retBuff; @@ -322,7 +322,7 @@ public class Request { out.finish(); out.close(); } catch (IOException e) { - s_logger.error("Fail to compress the request!", e); + LOGGER.error("Fail to compress the request!", e); } return ByteBuffer.wrap(byteOut.toByteArray()); } @@ -370,24 +370,24 @@ public class Request { } public void logD(String msg, boolean logContent) { - if (s_logger.isDebugEnabled()) { + if (LOGGER.isDebugEnabled()) { String log = log(msg, logContent, Level.DEBUG); if (log != null) { - s_logger.debug(log); + LOGGER.debug(log); } } } public void logT(String msg, boolean logD) { - if (s_logger.isTraceEnabled()) { + if (LOGGER.isTraceEnabled()) { String log = log(msg, true, Level.TRACE); if (log != null) { - s_logger.trace(log); + LOGGER.trace(log); } - } else if (logD && s_logger.isDebugEnabled()) { + } else if (logD && LOGGER.isDebugEnabled()) { String log = log(msg, false, Level.DEBUG); if (log != null) { - s_logger.debug(log); + LOGGER.debug(log); } } } @@ -404,7 +404,7 @@ public class Request { try { _cmds = s_gson.fromJson(_content, this instanceof Response ? Answer[].class : Command[].class); } catch (RuntimeException e) { - s_logger.error("Unable to deserialize from json: " + _content); + LOGGER.error("Unable to deserialize from json: " + _content); throw e; } } @@ -415,7 +415,7 @@ public class Request { for (Command cmd : _cmds) { buff.append(cmd.getClass().getSimpleName()).append("/"); } - s_logger.error("Gson serialization error " + buff.toString(), e); + LOGGER.error("Gson serialization error " + buff.toString(), e); assert false : "More gson errors on " + buff.toString(); return ""; } diff --git a/core/src/main/java/com/cloud/agent/transport/StoragePoolTypeAdaptor.java b/core/src/main/java/com/cloud/agent/transport/StoragePoolTypeAdaptor.java new file mode 100644 index 00000000000..635f6d06cf5 --- /dev/null +++ b/core/src/main/java/com/cloud/agent/transport/StoragePoolTypeAdaptor.java @@ -0,0 +1,53 @@ +// 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.transport; + +import com.cloud.storage.Storage.StoragePoolType; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import java.lang.reflect.Type; + +/** + * {@link StoragePoolType} acts as extendable set of singleton objects and should return same result when used "==" + * or {@link Object#equals(Object)}. + * To support that, need to return existing object for a given name instead of creating new. + */ +public class StoragePoolTypeAdaptor implements JsonDeserializer, JsonSerializer { + @Override + public StoragePoolType deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json instanceof JsonPrimitive && ((JsonPrimitive) json).isString()) { + return StoragePoolType.valueOf(json.getAsString()); + } + return null; + } + + @Override + public JsonElement serialize(StoragePoolType src, Type typeOfSrc, JsonSerializationContext context) { + String name = src.name(); + if (name == null) { + return new JsonNull(); + } + return new JsonPrimitive(name); + } +} diff --git a/core/src/main/java/com/cloud/network/HAProxyConfigurator.java b/core/src/main/java/com/cloud/network/HAProxyConfigurator.java index 8352895e621..9d07fc95c2f 100644 --- a/core/src/main/java/com/cloud/network/HAProxyConfigurator.java +++ b/core/src/main/java/com/cloud/network/HAProxyConfigurator.java @@ -28,7 +28,8 @@ import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import com.cloud.agent.api.routing.LoadBalancerConfigCommand; import com.cloud.agent.api.to.LoadBalancerTO; @@ -41,7 +42,7 @@ import com.cloud.utils.net.NetUtils; public class HAProxyConfigurator implements LoadBalancerConfigurator { - private static final Logger s_logger = Logger.getLogger(HAProxyConfigurator.class); + protected Logger logger = LogManager.getLogger(getClass()); private static final String blankLine = "\t "; private static String[] globalSection = {"global", "\tlog 127.0.0.1:3914 local0 warning", "\tmaxconn 4096", "\tmaxpipes 1024", "\tchroot /var/lib/haproxy", "\tuser haproxy", "\tgroup haproxy", "\tstats socket /run/haproxy/admin.sock", "\tdaemon"}; @@ -458,7 +459,7 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator { * Not supposed to reach here, validation of methods are * done at the higher layer */ - s_logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":" + lbTO.getSrcPort() + ": Not Applied, cause:invalid method "); + logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":" + lbTO.getSrcPort() + ": Not Applied, cause:invalid method "); return null; } } @@ -541,7 +542,7 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator { result.addAll(dstSubRule); } if (stickinessSubRule != null && !destsAvailable) { - s_logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":" + lbTO.getSrcPort() + ": Not Applied, cause: backends are unavailable"); + logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":" + lbTO.getSrcPort() + ": Not Applied, cause: backends are unavailable"); } if (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled || httpbasedStickiness) { sb = new StringBuilder(); @@ -566,7 +567,7 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator { final StringBuilder rule = new StringBuilder("\nlisten ").append(ruleName).append("\n\tbind ").append(statsIp).append(":").append(lbCmd.lbStatsPort); // TODO DH: write test for this in both cases if (!lbCmd.keepAliveEnabled) { - s_logger.info("Haproxy mode http enabled"); + logger.info("Haproxy mode http enabled"); rule.append("\n\tmode http\n\toption httpclose"); } rule.append("\n\tstats enable\n\tstats uri ") @@ -575,8 +576,8 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator { .append(lbCmd.lbStatsAuth); rule.append("\n"); final String result = rule.toString(); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Haproxystats rule: " + result); + if (logger.isDebugEnabled()) { + logger.debug("Haproxystats rule: " + result); } return result; } @@ -590,9 +591,9 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator { // TODO DH: write test for this function final String pipesLine = "\tmaxpipes " + Long.toString(Long.parseLong(lbCmd.maxconn) / 4); gSection.set(3, pipesLine); - if (s_logger.isDebugEnabled()) { + if (logger.isDebugEnabled()) { for (final String s : gSection) { - s_logger.debug("global section: " + s); + logger.debug("global section: " + s); } } result.addAll(gSection); @@ -606,9 +607,9 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator { dSection.set(7, "\tno option httpclose"); } - if (s_logger.isDebugEnabled()) { + if (logger.isDebugEnabled()) { for (final String s : dSection) { - s_logger.debug("default section: " + s); + logger.debug("default section: " + s); } } result.addAll(dSection); diff --git a/core/src/main/java/com/cloud/network/resource/TrafficSentinelResource.java b/core/src/main/java/com/cloud/network/resource/TrafficSentinelResource.java index c6596b3c630..43fb459978a 100644 --- a/core/src/main/java/com/cloud/network/resource/TrafficSentinelResource.java +++ b/core/src/main/java/com/cloud/network/resource/TrafficSentinelResource.java @@ -35,7 +35,8 @@ import java.util.StringTokenizer; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; @@ -66,7 +67,7 @@ public class TrafficSentinelResource implements ServerResource { private String _inclZones; private String _exclZones; - private static final Logger s_logger = Logger.getLogger(TrafficSentinelResource.class); + protected Logger logger = LogManager.getLogger(getClass()); @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -242,10 +243,10 @@ public class TrafficSentinelResource implements ServerResource { } } } catch (MalformedURLException e1) { - s_logger.info("Invalid Traffic Sentinel URL", e1); + logger.info("Invalid Traffic Sentinel URL", e1); throw new ExecutionException(e1.getMessage()); } catch (IOException e) { - s_logger.debug("Error in direct network usage accounting", e); + logger.debug("Error in direct network usage accounting", e); throw new ExecutionException(e.getMessage()); } finally { if (os != null) { @@ -256,7 +257,7 @@ public class TrafficSentinelResource implements ServerResource { } } } catch (Exception e) { - s_logger.debug(e); + logger.debug(e); throw new ExecutionException(e.getMessage()); } return answer; diff --git a/core/src/main/java/com/cloud/resource/AgentStatusUpdater.java b/core/src/main/java/com/cloud/resource/AgentStatusUpdater.java new file mode 100644 index 00000000000..63d5576c060 --- /dev/null +++ b/core/src/main/java/com/cloud/resource/AgentStatusUpdater.java @@ -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. +package com.cloud.resource; + +/** + * AgentStatusUpdater is an agent with triggerable update functionality + */ +public interface AgentStatusUpdater { + /** + * Trigger the sending of an update (Ping). + */ + void triggerUpdate(); +} diff --git a/core/src/main/java/com/cloud/resource/CommandWrapper.java b/core/src/main/java/com/cloud/resource/CommandWrapper.java index d9c1ea234e8..72d1348dfe7 100644 --- a/core/src/main/java/com/cloud/resource/CommandWrapper.java +++ b/core/src/main/java/com/cloud/resource/CommandWrapper.java @@ -19,12 +19,16 @@ package com.cloud.resource; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; -import org.apache.log4j.Logger; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; public abstract class CommandWrapper { - protected Logger logger = Logger.getLogger(getClass()); + protected Logger logger = LogManager.getLogger(getClass()); /** * @param T is the command to be used. @@ -32,4 +36,26 @@ public abstract class CommandWrapper*?![]{}~".indexOf(c) != -1) { + sanitized.append('\\'); + } + sanitized.append(c); + } + return sanitized.toString(); + } + + public void removeDpdkPort(String portToRemove) { + logger.debug("Removing DPDK port: " + portToRemove); + int port; + try { + port = Integer.valueOf(portToRemove); + } catch (NumberFormatException nfe) { + throw new CloudRuntimeException(String.format("Invalid DPDK port specified: '%s'", portToRemove)); + } + Script.executeCommand("ovs-vsctl", "del-port", String.valueOf(port)); + } } diff --git a/core/src/main/java/com/cloud/resource/RequestWrapper.java b/core/src/main/java/com/cloud/resource/RequestWrapper.java index e43cf02e13c..54d8b289c8d 100644 --- a/core/src/main/java/com/cloud/resource/RequestWrapper.java +++ b/core/src/main/java/com/cloud/resource/RequestWrapper.java @@ -23,7 +23,8 @@ import java.text.MessageFormat; import java.util.Hashtable; import java.util.Set; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; @@ -39,7 +40,7 @@ public abstract class RequestWrapper { } } - private static final Logger s_logger = Logger.getLogger(RequestWrapper.class); + protected Logger logger = LogManager.getLogger(RequestWrapper.class); @SuppressWarnings("rawtypes") protected Hashtable, Hashtable, CommandWrapper>> resources = new Hashtable, Hashtable, CommandWrapper>>(); @@ -141,9 +142,9 @@ public abstract class RequestWrapper { try { commands.put(annotation.handles(), wrapper.newInstance()); } catch (final InstantiationException e) { - s_logger.warn(MessageFormat.format(errorMessage, e.getLocalizedMessage(), wrapper.toString())); + logger.warn(MessageFormat.format(errorMessage, e.getLocalizedMessage(), wrapper.toString())); } catch (final IllegalAccessException e) { - s_logger.warn(MessageFormat.format(errorMessage, e.getLocalizedMessage(), wrapper.toString())); + logger.warn(MessageFormat.format(errorMessage, e.getLocalizedMessage(), wrapper.toString())); } } diff --git a/core/src/main/java/com/cloud/resource/ResourceStatusUpdater.java b/core/src/main/java/com/cloud/resource/ResourceStatusUpdater.java new file mode 100644 index 00000000000..df59e3a152e --- /dev/null +++ b/core/src/main/java/com/cloud/resource/ResourceStatusUpdater.java @@ -0,0 +1,29 @@ +// 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.resource; + +/** + * ResourceStatusUpdater is a resource that can trigger out of band status updates + */ +public interface ResourceStatusUpdater { + /** + * Register an AgentStatusUpdater to use for triggering out of band updates. + * + * @param updater The object to call triggerUpdate() on + */ + void registerStatusUpdater(AgentStatusUpdater updater); +} diff --git a/core/src/main/java/com/cloud/resource/ServerResourceBase.java b/core/src/main/java/com/cloud/resource/ServerResourceBase.java index f3bad610998..bb44b307047 100644 --- a/core/src/main/java/com/cloud/resource/ServerResourceBase.java +++ b/core/src/main/java/com/cloud/resource/ServerResourceBase.java @@ -19,6 +19,7 @@ package com.cloud.resource; +import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.net.NetworkInterface; @@ -33,9 +34,11 @@ import java.util.Map; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsAnswer; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; @@ -45,19 +48,19 @@ import com.cloud.utils.net.NetUtils; import com.cloud.utils.script.Script; public abstract class ServerResourceBase implements ServerResource { - private static final Logger s_logger = Logger.getLogger(ServerResourceBase.class); - protected String _name; - private ArrayList _warnings = new ArrayList(); - private ArrayList _errors = new ArrayList(); - protected NetworkInterface _publicNic; - protected NetworkInterface _privateNic; - protected NetworkInterface _storageNic; - protected NetworkInterface _storageNic2; - protected IAgentControl _agentControl; + protected Logger logger = LogManager.getLogger(getClass()); + protected String name; + private ArrayList warnings = new ArrayList(); + private ArrayList errors = new ArrayList(); + protected NetworkInterface publicNic; + protected NetworkInterface privateNic; + protected NetworkInterface storageNic; + protected NetworkInterface storageNic2; + protected IAgentControl agentControl; @Override public String getName() { - return _name; + return name; } protected String findScript(String script) { @@ -68,17 +71,17 @@ public abstract class ServerResourceBase implements ServerResource { @Override public boolean configure(final String name, Map params) throws ConfigurationException { - _name = name; + this.name = name; defineResourceNetworkInterfaces(params); - if (_privateNic == null) { + if (privateNic == null) { tryToAutoDiscoverResourcePrivateNetworkInterface(); } - String infos[] = NetUtils.getNetworkParams(_privateNic); + String infos[] = NetUtils.getNetworkParams(privateNic); if (infos == null) { - s_logger.warn("Incorrect details for private Nic during initialization of ServerResourceBase"); + logger.warn("Incorrect details for private Nic during initialization of ServerResourceBase"); return false; } params.put("host.ip", infos[0]); @@ -97,14 +100,14 @@ public abstract class ServerResourceBase implements ServerResource { String storageNic = (String) params.get("storage.network.device"); String storageNic2 = (String) params.get("storage.network.device.2"); - _privateNic = NetUtils.getNetworkInterface(privateNic); - _publicNic = NetUtils.getNetworkInterface(publicNic); - _storageNic = NetUtils.getNetworkInterface(storageNic); - _storageNic2 = NetUtils.getNetworkInterface(storageNic2); + this.privateNic = NetUtils.getNetworkInterface(privateNic); + this.publicNic = NetUtils.getNetworkInterface(publicNic); + this.storageNic = NetUtils.getNetworkInterface(storageNic); + this.storageNic2 = NetUtils.getNetworkInterface(storageNic2); } protected void tryToAutoDiscoverResourcePrivateNetworkInterface() throws ConfigurationException { - s_logger.info("Trying to autodiscover this resource's private network interface."); + logger.info("Trying to autodiscover this resource's private network interface."); List nics; try { @@ -116,12 +119,12 @@ public abstract class ServerResourceBase implements ServerResource { throw new ConfigurationException(String.format("Could not retrieve the environment NICs due to [%s].", e.getMessage())); } - s_logger.debug(String.format("Searching the private NIC along the environment NICs [%s].", Arrays.toString(nics.toArray()))); + logger.debug(String.format("Searching the private NIC along the environment NICs [%s].", Arrays.toString(nics.toArray()))); for (NetworkInterface nic : nics) { if (isValidNicToUseAsPrivateNic(nic)) { - s_logger.info(String.format("Using NIC [%s] as private NIC.", nic)); - _privateNic = nic; + logger.info(String.format("Using NIC [%s] as private NIC.", nic)); + privateNic = nic; return; } } @@ -132,31 +135,64 @@ public abstract class ServerResourceBase implements ServerResource { protected boolean isValidNicToUseAsPrivateNic(NetworkInterface nic) { String nicName = nic.getName(); - s_logger.debug(String.format("Verifying if NIC [%s] can be used as private NIC.", nic)); + logger.debug(String.format("Verifying if NIC [%s] can be used as private NIC.", nic)); String[] nicNameStartsToAvoid = {"vnif", "vnbr", "peth", "vif", "virbr"}; if (nic.isVirtual() || StringUtils.startsWithAny(nicName, nicNameStartsToAvoid) || nicName.contains(":")) { - s_logger.debug(String.format("Not using NIC [%s] because it is either virtual, starts with %s, or contains \":\"" + + logger.debug(String.format("Not using NIC [%s] because it is either virtual, starts with %s, or contains \":\"" + " in its name.", Arrays.toString(nicNameStartsToAvoid), nic)); return false; } String[] info = NetUtils.getNicParams(nicName); if (info == null || info[0] == null) { - s_logger.debug(String.format("Not using NIC [%s] because it does not have a valid IP to use as the private IP.", nic)); + logger.debug(String.format("Not using NIC [%s] because it does not have a valid IP to use as the private IP.", nic)); return false; } return true; } + protected Answer listFilesAtPath(String nfsMountPoint, String relativePath, int startIndex, int pageSize) { + int count = 0; + File file = new File(nfsMountPoint, relativePath); + List names = new ArrayList<>(); + List paths = new ArrayList<>(); + List absPaths = new ArrayList<>(); + List isDirs = new ArrayList<>(); + List sizes = new ArrayList<>(); + List modifiedList = new ArrayList<>(); + if (file.isFile()) { + count = 1; + names.add(file.getName()); + paths.add(file.getPath().replace(nfsMountPoint, "")); + absPaths.add(file.getPath()); + isDirs.add(file.isDirectory()); + sizes.add(file.length()); + modifiedList.add(file.lastModified()); + } else if (file.isDirectory()) { + String[] files = file.list(); + count = files.length; + for (int i = startIndex; i < startIndex + pageSize && i < count; i++) { + File f = new File(nfsMountPoint, relativePath + '/' + files[i]); + names.add(f.getName()); + paths.add(f.getPath().replace(nfsMountPoint, "")); + absPaths.add(f.getPath()); + isDirs.add(f.isDirectory()); + sizes.add(f.length()); + modifiedList.add(f.lastModified()); + } + } + return new ListDataStoreObjectsAnswer(file.exists(), count, names, paths, absPaths, isDirs, sizes, modifiedList); + } + protected void fillNetworkInformation(final StartupCommand cmd) { String[] info = null; - if (_privateNic != null) { - info = NetUtils.getNetworkParams(_privateNic); + if (privateNic != null) { + info = NetUtils.getNetworkParams(privateNic); if (info != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Parameters for private nic: " + info[0] + " - " + info[1] + "-" + info[2]); + if (logger.isDebugEnabled()) { + logger.debug("Parameters for private nic: " + info[0] + " - " + info[1] + "-" + info[2]); } cmd.setPrivateIpAddress(info[0]); cmd.setPrivateMacAddress(info[1]); @@ -164,28 +200,28 @@ public abstract class ServerResourceBase implements ServerResource { } } - if (_storageNic != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Storage has its now nic: " + _storageNic.getName()); + if (storageNic != null) { + if (logger.isDebugEnabled()) { + logger.debug("Storage has its now nic: " + storageNic.getName()); } - info = NetUtils.getNetworkParams(_storageNic); + info = NetUtils.getNetworkParams(storageNic); } // NOTE: In case you're wondering, this is not here by mistake. if (info != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Parameters for storage nic: " + info[0] + " - " + info[1] + "-" + info[2]); + if (logger.isDebugEnabled()) { + logger.debug("Parameters for storage nic: " + info[0] + " - " + info[1] + "-" + info[2]); } cmd.setStorageIpAddress(info[0]); cmd.setStorageMacAddress(info[1]); cmd.setStorageNetmask(info[2]); } - if (_publicNic != null) { - info = NetUtils.getNetworkParams(_publicNic); + if (publicNic != null) { + info = NetUtils.getNetworkParams(publicNic); if (info != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Parameters for public nic: " + info[0] + " - " + info[1] + "-" + info[2]); + if (logger.isDebugEnabled()) { + logger.debug("Parameters for public nic: " + info[0] + " - " + info[1] + "-" + info[2]); } cmd.setPublicIpAddress(info[0]); cmd.setPublicMacAddress(info[1]); @@ -193,11 +229,11 @@ public abstract class ServerResourceBase implements ServerResource { } } - if (_storageNic2 != null) { - info = NetUtils.getNetworkParams(_storageNic2); + if (storageNic2 != null) { + info = NetUtils.getNetworkParams(storageNic2); if (info != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Parameters for storage nic 2: " + info[0] + " - " + info[1] + "-" + info[2]); + if (logger.isDebugEnabled()) { + logger.debug("Parameters for storage nic 2: " + info[0] + " - " + info[1] + "-" + info[2]); } cmd.setStorageIpAddressDeux(info[0]); cmd.setStorageMacAddressDeux(info[1]); @@ -212,18 +248,18 @@ public abstract class ServerResourceBase implements ServerResource { @Override public IAgentControl getAgentControl() { - return _agentControl; + return agentControl; } @Override public void setAgentControl(IAgentControl agentControl) { - _agentControl = agentControl; + this.agentControl = agentControl; } protected void recordWarning(final String msg, final Throwable th) { final String str = getLogStr(msg, th); - synchronized (_warnings) { - _warnings.add(str); + synchronized (warnings) { + warnings.add(str); } } @@ -232,25 +268,25 @@ public abstract class ServerResourceBase implements ServerResource { } protected List getWarnings() { - synchronized (_warnings) { - final List results = new LinkedList(_warnings); - _warnings.clear(); + synchronized (warnings) { + final List results = new LinkedList(warnings); + warnings.clear(); return results; } } protected List getErrors() { - synchronized (_errors) { - final List result = new LinkedList(_errors); - _errors.clear(); + synchronized (errors) { + final List result = new LinkedList(errors); + errors.clear(); return result; } } protected void recordError(final String msg, final Throwable th) { final String str = getLogStr(msg, th); - synchronized (_errors) { - _errors.add(str); + synchronized (errors) { + errors.add(str); } } diff --git a/core/src/main/java/com/cloud/serializer/GsonHelper.java b/core/src/main/java/com/cloud/serializer/GsonHelper.java index 7ac85d39317..2d2cecf2618 100644 --- a/core/src/main/java/com/cloud/serializer/GsonHelper.java +++ b/core/src/main/java/com/cloud/serializer/GsonHelper.java @@ -21,7 +21,10 @@ package com.cloud.serializer; import java.util.List; -import org.apache.log4j.Logger; +import com.cloud.hypervisor.Hypervisor; +import org.apache.cloudstack.transport.HypervisorTypeAdaptor; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -37,10 +40,12 @@ import com.cloud.agent.transport.InterfaceTypeAdaptor; import com.cloud.agent.transport.LoggingExclusionStrategy; import com.cloud.agent.transport.Request.NwGroupsCommandTypeAdaptor; import com.cloud.agent.transport.Request.PortConfigListTypeAdaptor; +import com.cloud.agent.transport.StoragePoolTypeAdaptor; +import com.cloud.storage.Storage; import com.cloud.utils.Pair; public class GsonHelper { - private static final Logger s_logger = Logger.getLogger(GsonHelper.class); + protected static Logger LOGGER = LogManager.getLogger(GsonHelper.class); protected static final Gson s_gson; protected static final Gson s_gogger; @@ -48,11 +53,13 @@ public class GsonHelper { static { GsonBuilder gsonBuilder = new GsonBuilder(); s_gson = setDefaultGsonConfig(gsonBuilder); - GsonBuilder loggerBuilder = new GsonBuilder(); - loggerBuilder.disableHtmlEscaping(); - loggerBuilder.setExclusionStrategies(new LoggingExclusionStrategy(s_logger)); - s_gogger = setDefaultGsonConfig(loggerBuilder); - s_logger.info("Default Builder inited."); + GsonBuilder LOGGERBuilder = new GsonBuilder(); + LOGGERBuilder.disableHtmlEscaping(); + LOGGERBuilder.setExclusionStrategies(new LoggingExclusionStrategy(LOGGER)); + LOGGERBuilder.serializeSpecialFloatingPointValues(); + // maybe add LOGGERBuilder.serializeNulls(); as well? + s_gogger = setDefaultGsonConfig(LOGGERBuilder); + LOGGER.info("Default Builder inited."); } static Gson setDefaultGsonConfig(GsonBuilder builder) { @@ -69,6 +76,8 @@ public class GsonHelper { }.getType(), new PortConfigListTypeAdaptor()); builder.registerTypeAdapter(new TypeToken>() { }.getType(), new NwGroupsCommandTypeAdaptor()); + builder.registerTypeAdapter(Storage.StoragePoolType.class, new StoragePoolTypeAdaptor()); + builder.registerTypeAdapter(Hypervisor.HypervisorType.class, new HypervisorTypeAdaptor()); Gson gson = builder.create(); dsAdaptor.initGson(gson); dtAdaptor.initGson(gson); @@ -86,6 +95,6 @@ public class GsonHelper { } public final static Logger getLogger() { - return s_logger; + return LOGGER; } } diff --git a/core/src/main/java/com/cloud/storage/JavaStorageLayer.java b/core/src/main/java/com/cloud/storage/JavaStorageLayer.java index d4c2639d478..0e51ef7eb20 100644 --- a/core/src/main/java/com/cloud/storage/JavaStorageLayer.java +++ b/core/src/main/java/com/cloud/storage/JavaStorageLayer.java @@ -34,10 +34,11 @@ import java.util.Set; import java.util.UUID; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; public class JavaStorageLayer implements StorageLayer { - private static final Logger s_logger = Logger.getLogger(JavaStorageLayer.class); + protected Logger logger = LogManager.getLogger(getClass()); private static final String STD_TMP_DIR_PATH = "/tmp"; String _name; boolean _makeWorldWriteable = true; @@ -198,9 +199,9 @@ public class JavaStorageLayer implements StorageLayer { if (dir.exists()) { if (isWorldReadable(dir)) { if (STD_TMP_DIR_PATH.equals(dir.getAbsolutePath())) { - s_logger.warn(String.format("The temp dir is %s", STD_TMP_DIR_PATH)); + logger.warn(String.format("The temp dir is %s", STD_TMP_DIR_PATH)); } else { - s_logger.warn("The temp dir " + dir.getAbsolutePath() + " is World Readable"); + logger.warn("The temp dir " + dir.getAbsolutePath() + " is World Readable"); } } String uniqDirName = dir.getAbsolutePath() + File.separator + UUID.randomUUID().toString(); diff --git a/core/src/main/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java b/core/src/main/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java index 4a9a24a9f53..7d8225462ca 100644 --- a/core/src/main/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java +++ b/core/src/main/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java @@ -19,23 +19,22 @@ package com.cloud.storage.resource; -import com.cloud.serializer.GsonHelper; import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand; -import org.apache.cloudstack.storage.to.VolumeObjectTO; -import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand; -import org.apache.log4j.Logger; - import org.apache.cloudstack.storage.command.AttachCommand; +import org.apache.cloudstack.storage.command.CheckDataStoreStoragePolicyComplainceCommand; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.CreateObjectAnswer; import org.apache.cloudstack.storage.command.CreateObjectCommand; import org.apache.cloudstack.storage.command.DeleteCommand; import org.apache.cloudstack.storage.command.DettachCommand; import org.apache.cloudstack.storage.command.IntroduceObjectCmd; +import org.apache.cloudstack.storage.command.QuerySnapshotZoneCopyAnswer; +import org.apache.cloudstack.storage.command.QuerySnapshotZoneCopyCommand; import org.apache.cloudstack.storage.command.ResignatureCommand; import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.command.SyncVolumePathCommand; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; @@ -43,12 +42,15 @@ import com.cloud.agent.api.to.DataObjectType; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DiskTO; +import com.cloud.serializer.GsonHelper; import com.cloud.storage.DataStoreRole; import com.cloud.storage.Volume; import com.google.gson.Gson; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; public class StorageSubsystemCommandHandlerBase implements StorageSubsystemCommandHandler { - private static final Logger s_logger = Logger.getLogger(StorageSubsystemCommandHandlerBase.class); + protected Logger logger = LogManager.getLogger(getClass()); protected static final Gson s_gogger = GsonHelper.getGsonLogger(); protected StorageProcessor processor; @@ -81,6 +83,8 @@ public class StorageSubsystemCommandHandlerBase implements StorageSubsystemComma return processor.checkDataStoreStoragePolicyCompliance((CheckDataStoreStoragePolicyComplainceCommand) command); } else if (command instanceof SyncVolumePathCommand) { return processor.syncVolumePath((SyncVolumePathCommand) command); + } else if (command instanceof QuerySnapshotZoneCopyCommand) { + return execute((QuerySnapshotZoneCopyCommand)command); } return new Answer((Command)command, false, "not implemented yet"); @@ -138,7 +142,7 @@ public class StorageSubsystemCommandHandlerBase implements StorageSubsystemComma } return new CreateObjectAnswer("not supported type"); } catch (Exception e) { - s_logger.debug("Failed to create object: " + data.getObjectType() + ": " + e.toString()); + logger.debug("Failed to create object: " + data.getObjectType() + ": " + e.toString()); return new CreateObjectAnswer(e.toString()); } } @@ -175,11 +179,15 @@ public class StorageSubsystemCommandHandlerBase implements StorageSubsystemComma } } + protected Answer execute(QuerySnapshotZoneCopyCommand cmd) { + return new QuerySnapshotZoneCopyAnswer(cmd, "Unsupported command"); + } + private void logCommand(Command cmd) { try { - s_logger.debug(String.format("Executing command %s: [%s].", cmd.getClass().getSimpleName(), s_gogger.toJson(cmd))); + logger.debug(String.format("Executing command %s: [%s].", cmd.getClass().getSimpleName(), s_gogger.toJson(cmd))); } catch (Exception e) { - s_logger.debug(String.format("Executing command %s.", cmd.getClass().getSimpleName())); + logger.debug(String.format("Executing command %s.", cmd.getClass().getSimpleName())); } } } diff --git a/core/src/main/java/com/cloud/storage/template/FtpTemplateUploader.java b/core/src/main/java/com/cloud/storage/template/FtpTemplateUploader.java index eb0c4f84601..14bf6fe1b74 100644 --- a/core/src/main/java/com/cloud/storage/template/FtpTemplateUploader.java +++ b/core/src/main/java/com/cloud/storage/template/FtpTemplateUploader.java @@ -29,11 +29,12 @@ import java.net.URL; import java.net.URLConnection; import java.util.Date; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; public class FtpTemplateUploader implements TemplateUploader { - public static final Logger s_logger = Logger.getLogger(FtpTemplateUploader.class.getName()); + protected Logger logger = LogManager.getLogger(getClass()); public TemplateUploader.Status status = TemplateUploader.Status.NOT_STARTED; public String errorString = ""; public long totalBytes = 0; @@ -110,11 +111,11 @@ public class FtpTemplateUploader implements TemplateUploader { } catch (MalformedURLException e) { status = TemplateUploader.Status.UNRECOVERABLE_ERROR; errorString = e.getMessage(); - s_logger.error(errorString); + logger.error(errorString); } catch (IOException e) { status = TemplateUploader.Status.UNRECOVERABLE_ERROR; errorString = e.getMessage(); - s_logger.error(errorString); + logger.error(errorString); } finally { try { if (inputStream != null) { @@ -124,7 +125,7 @@ public class FtpTemplateUploader implements TemplateUploader { outputStream.close(); } } catch (IOException ioe) { - s_logger.error(" Caught exception while closing the resources"); + logger.error(" Caught exception while closing the resources"); } if (callback != null) { callback.uploadComplete(status); @@ -139,7 +140,7 @@ public class FtpTemplateUploader implements TemplateUploader { try { upload(completionCallback); } catch (Throwable t) { - s_logger.warn("Caught exception during upload " + t.getMessage(), t); + logger.warn("Caught exception during upload " + t.getMessage(), t); errorString = "Failed to install: " + t.getMessage(); status = TemplateUploader.Status.UNRECOVERABLE_ERROR; } @@ -207,7 +208,7 @@ public class FtpTemplateUploader implements TemplateUploader { inputStream.close(); } } catch (IOException e) { - s_logger.error(" Caught exception while closing the resources"); + logger.error(" Caught exception while closing the resources"); } status = TemplateUploader.Status.ABORTED; return true; diff --git a/core/src/main/java/com/cloud/storage/template/HttpTemplateDownloader.java b/core/src/main/java/com/cloud/storage/template/HttpTemplateDownloader.java index 2e331cab227..9b126846827 100755 --- a/core/src/main/java/com/cloud/storage/template/HttpTemplateDownloader.java +++ b/core/src/main/java/com/cloud/storage/template/HttpTemplateDownloader.java @@ -19,6 +19,8 @@ package com.cloud.storage.template; +import static com.cloud.utils.NumbersUtil.toHumanReadableSize; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -26,8 +28,10 @@ import java.io.RandomAccessFile; import java.net.URI; import java.net.URISyntaxException; import java.util.Date; +import java.util.List; -import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; +import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import org.apache.cloudstack.utils.imagestore.ImageStoreUtil; import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.Header; @@ -42,24 +46,18 @@ import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.HttpMethodParams; -import org.apache.log4j.Logger; - -import org.apache.cloudstack.managed.context.ManagedContextRunnable; -import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import com.cloud.storage.StorageLayer; import com.cloud.utils.Pair; import com.cloud.utils.UriUtils; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.Proxy; -import static com.cloud.utils.NumbersUtil.toHumanReadableSize; - /** * Download a template file using HTTP * */ public class HttpTemplateDownloader extends ManagedContextRunnable implements TemplateDownloader { - public static final Logger s_logger = Logger.getLogger(HttpTemplateDownloader.class.getName()); private static final MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager(); private static final int CHUNK_SIZE = 1024 * 1024; //1M @@ -81,6 +79,7 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te private long maxTemplateSizeInBytes; private ResourceType resourceType = ResourceType.TEMPLATE; private final HttpMethodRetryHandler myretryhandler; + private boolean followRedirects = false; public HttpTemplateDownloader(StorageLayer storageLayer, String downloadUrl, String toDir, DownloadCompleteCallback callback, long maxTemplateSizeInBytes, String user, String password, Proxy proxy, ResourceType resourceType) { @@ -103,16 +102,16 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te } catch (Exception ex) { errorString = "Unable to start download -- check url? "; status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; - s_logger.warn("Exception in constructor -- " + ex.toString()); + logger.warn("Exception in constructor -- " + ex.toString()); } catch (Throwable th) { - s_logger.warn("throwable caught ", th); + logger.warn("throwable caught ", th); } } private GetMethod createRequest(String downloadUrl) { GetMethod request = new GetMethod(downloadUrl); request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler); - request.setFollowRedirects(true); + request.setFollowRedirects(followRedirects); return request; } @@ -128,7 +127,7 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te } catch (IOException ex) { errorString = "Unable to start download -- check url? "; status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; - s_logger.warn("Exception in constructor -- " + ex.toString()); + logger.warn("Exception in constructor -- " + ex.toString()); } } @@ -139,9 +138,9 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te client.getParams().setAuthenticationPreemptive(true); Credentials defaultcreds = new UsernamePasswordCredentials(user, password); client.getState().setCredentials(new AuthScope(hostAndPort.first(), hostAndPort.second(), AuthScope.ANY_REALM), defaultcreds); - s_logger.info("Added username=" + user + ", password=" + password + "for host " + hostAndPort.first() + ":" + hostAndPort.second()); + logger.info("Added username=" + user + ", password=" + password + "for host " + hostAndPort.first() + ":" + hostAndPort.second()); } else { - s_logger.info("No credentials configured for host=" + hostAndPort.first() + ":" + hostAndPort.second()); + logger.info("No credentials configured for host=" + hostAndPort.first() + ":" + hostAndPort.second()); } } catch (IllegalArgumentException iae) { errorString = iae.getMessage(); @@ -207,7 +206,7 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te ) { out.seek(localFileSize); - s_logger.info("Starting download from " + downloadUrl + " to " + toFile + " remoteSize=" + toHumanReadableSize(remoteSize) + " , max size=" + toHumanReadableSize(maxTemplateSizeInBytes)); + logger.info("Starting download from " + downloadUrl + " to " + toFile + " remoteSize=" + toHumanReadableSize(remoteSize) + " , max size=" + toHumanReadableSize(maxTemplateSizeInBytes)); if (copyBytes(file, in, out)) return 0; @@ -247,7 +246,9 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te while (!done && status != Status.ABORTED && offset <= remoteSize) { if ((bytes = in.read(block, 0, CHUNK_SIZE)) > -1) { offset = writeBlock(bytes, out, block, offset); - if (!verifyFormat.isVerifiedFormat() && (offset >= 1048576 || offset >= remoteSize)) { //let's check format after we get 1MB or full file + if (!ResourceType.SNAPSHOT.equals(resourceType) && + !verifyFormat.isVerifiedFormat() && + (offset >= 1048576 || offset >= remoteSize)) { //let's check format after we get 1MB or full file verifyFormat.invoke(); } } else { @@ -277,7 +278,7 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te private boolean canHandleDownloadSize() { if (remoteSize > maxTemplateSizeInBytes) { - s_logger.info("Remote size is too large: " + toHumanReadableSize(remoteSize) + " , max=" + toHumanReadableSize(maxTemplateSizeInBytes)); + logger.info("Remote size is too large: " + toHumanReadableSize(remoteSize) + " , max=" + toHumanReadableSize(maxTemplateSizeInBytes)); status = Status.UNRECOVERABLE_ERROR; errorString = "Download file size is too large"; return false; @@ -336,6 +337,12 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te } else if ((responseCode = client.executeMethod(request)) != HttpStatus.SC_OK) { status = Status.UNRECOVERABLE_ERROR; errorString = " HTTP Server returned " + responseCode + " (expected 200 OK) "; + if (List.of(HttpStatus.SC_MOVED_PERMANENTLY, HttpStatus.SC_MOVED_TEMPORARILY).contains(responseCode) + && !followRedirects) { + errorString = String.format("Failed to download %s due to redirection, response code: %d", + downloadUrl, responseCode); + logger.error(errorString); + } return true; //FIXME: retry? } return false; @@ -346,7 +353,7 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te long localFileSize = 0; if (file.exists() && resume) { localFileSize = file.length(); - s_logger.info("Resuming download to file (current size)=" + toHumanReadableSize(localFileSize)); + logger.info("Resuming download to file (current size)=" + toHumanReadableSize(localFileSize)); } return localFileSize; } @@ -430,7 +437,7 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te try { download(resume, completionCallback); } catch (Throwable t) { - s_logger.warn("Caught exception during download " + t.getMessage(), t); + logger.warn("Caught exception during download " + t.getMessage(), t); errorString = "Failed to install: " + t.getMessage(); status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; } @@ -518,23 +525,31 @@ public class HttpTemplateDownloader extends ManagedContextRunnable implements Te URI str = new URI(downloadUrl); uripath = str.getPath(); } catch (URISyntaxException e) { - s_logger.warn("Invalid download url: " + downloadUrl + ", This should not happen since we have validated the url before!!"); + logger.warn("Invalid download url: " + downloadUrl + ", This should not happen since we have validated the url before!!"); } String unsupportedFormat = ImageStoreUtil.checkTemplateFormat(file.getAbsolutePath(), uripath); if (unsupportedFormat == null || !unsupportedFormat.isEmpty()) { try { request.abort(); } catch (Exception ex) { - s_logger.debug("Error on http connection : " + ex.getMessage()); + logger.debug("Error on http connection : " + ex.getMessage()); } status = Status.UNRECOVERABLE_ERROR; errorString = "Template content is unsupported, or mismatch between selected format and template content. Found : " + unsupportedFormat; throw new CloudRuntimeException(errorString); } else { - s_logger.debug("Verified format of downloading file " + file.getAbsolutePath() + " is supported"); + logger.debug("Verified format of downloading file " + file.getAbsolutePath() + " is supported"); verifiedFormat = true; } return this; } } + + @Override + public void setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + if (this.request != null) { + this.request.setFollowRedirects(followRedirects); + } + } } diff --git a/core/src/main/java/com/cloud/storage/template/IsoProcessor.java b/core/src/main/java/com/cloud/storage/template/IsoProcessor.java index 4cd2f1a2a02..6ab42effb52 100644 --- a/core/src/main/java/com/cloud/storage/template/IsoProcessor.java +++ b/core/src/main/java/com/cloud/storage/template/IsoProcessor.java @@ -24,14 +24,12 @@ import java.util.Map; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageLayer; import com.cloud.utils.component.AdapterBase; public class IsoProcessor extends AdapterBase implements Processor { - private static final Logger s_logger = Logger.getLogger(IsoProcessor.class); StorageLayer _storage; @@ -43,14 +41,14 @@ public class IsoProcessor extends AdapterBase implements Processor { @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) { if (format != null) { - s_logger.debug("We don't handle conversion from " + format + " to ISO."); + logger.debug("We don't handle conversion from " + format + " to ISO."); return null; } String isoPath = templatePath + File.separator + templateName + "." + ImageFormat.ISO.getFileExtension(); if (!_storage.exists(isoPath)) { - s_logger.debug("Unable to find the iso file: " + isoPath); + logger.debug("Unable to find the iso file: " + isoPath); return null; } diff --git a/core/src/main/java/com/cloud/storage/template/LocalTemplateDownloader.java b/core/src/main/java/com/cloud/storage/template/LocalTemplateDownloader.java index 564eba3d5ee..e4044412c52 100644 --- a/core/src/main/java/com/cloud/storage/template/LocalTemplateDownloader.java +++ b/core/src/main/java/com/cloud/storage/template/LocalTemplateDownloader.java @@ -29,12 +29,10 @@ import java.net.URISyntaxException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; -import org.apache.log4j.Logger; import com.cloud.storage.StorageLayer; public class LocalTemplateDownloader extends TemplateDownloaderBase implements TemplateDownloader { - public static final Logger s_logger = Logger.getLogger(LocalTemplateDownloader.class); public LocalTemplateDownloader(StorageLayer storageLayer, String downloadUrl, String toDir, long maxTemplateSizeInBytes, DownloadCompleteCallback callback) { super(storageLayer, downloadUrl, toDir, maxTemplateSizeInBytes, callback); @@ -55,7 +53,7 @@ public class LocalTemplateDownloader extends TemplateDownloaderBase implements T try { src = new File(new URI(_downloadUrl)); } catch (URISyntaxException e1) { - s_logger.warn("Invalid URI " + _downloadUrl); + logger.warn("Invalid URI " + _downloadUrl); _status = Status.UNRECOVERABLE_ERROR; return 0; } @@ -77,7 +75,7 @@ public class LocalTemplateDownloader extends TemplateDownloaderBase implements T try { fis = new FileInputStream(src); } catch (FileNotFoundException e) { - s_logger.warn("Unable to find " + _downloadUrl); + logger.warn("Unable to find " + _downloadUrl); _errorString = "Unable to find " + _downloadUrl; return -1; } @@ -85,7 +83,7 @@ public class LocalTemplateDownloader extends TemplateDownloaderBase implements T try { fos = new FileOutputStream(dst); } catch (FileNotFoundException e) { - s_logger.warn("Unable to find " + _toFile); + logger.warn("Unable to find " + _toFile); return -1; } foc = fos.getChannel(); @@ -102,7 +100,7 @@ public class LocalTemplateDownloader extends TemplateDownloaderBase implements T buffer.clear(); } } catch (IOException e) { - s_logger.warn("Unable to download", e); + logger.warn("Unable to download", e); } String downloaded = "(incomplete download)"; @@ -123,7 +121,7 @@ public class LocalTemplateDownloader extends TemplateDownloaderBase implements T try { fic.close(); } catch (IOException e) { - s_logger.info("[ignore] error while closing file input channel."); + logger.info("[ignore] error while closing file input channel."); } } @@ -131,7 +129,7 @@ public class LocalTemplateDownloader extends TemplateDownloaderBase implements T try { foc.close(); } catch (IOException e) { - s_logger.info("[ignore] error while closing file output channel."); + logger.info("[ignore] error while closing file output channel."); } } @@ -139,7 +137,7 @@ public class LocalTemplateDownloader extends TemplateDownloaderBase implements T try { fis.close(); } catch (IOException e) { - s_logger.info("[ignore] error while closing file input stream."); + logger.info("[ignore] error while closing file input stream."); } } @@ -147,7 +145,7 @@ public class LocalTemplateDownloader extends TemplateDownloaderBase implements T try { fos.close(); } catch (IOException e) { - s_logger.info("[ignore] error while closing file output stream."); + logger.info("[ignore] error while closing file output stream."); } } diff --git a/core/src/main/java/com/cloud/storage/template/MetalinkTemplateDownloader.java b/core/src/main/java/com/cloud/storage/template/MetalinkTemplateDownloader.java index dd452f2e2d9..2e62809dfed 100644 --- a/core/src/main/java/com/cloud/storage/template/MetalinkTemplateDownloader.java +++ b/core/src/main/java/com/cloud/storage/template/MetalinkTemplateDownloader.java @@ -28,7 +28,6 @@ import org.apache.commons.httpclient.NoHttpResponseException; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.io.IOUtils; -import org.apache.log4j.Logger; import org.springframework.util.CollectionUtils; import java.io.File; @@ -47,7 +46,6 @@ public class MetalinkTemplateDownloader extends TemplateDownloaderBase implement protected GetMethod request; private boolean toFileSet = false; - private static final Logger LOGGER = Logger.getLogger(MetalinkTemplateDownloader.class.getName()); public MetalinkTemplateDownloader(StorageLayer storageLayer, String downloadUrl, String toDir, DownloadCompleteCallback callback, long maxTemplateSize) { super(storageLayer, downloadUrl, toDir, maxTemplateSize, callback); @@ -60,7 +58,7 @@ public class MetalinkTemplateDownloader extends TemplateDownloaderBase implement protected GetMethod createRequest(String downloadUrl) { GetMethod request = new GetMethod(downloadUrl); request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler); - request.setFollowRedirects(true); + request.setFollowRedirects(followRedirects); if (!toFileSet) { String[] parts = downloadUrl.split("/"); String filename = parts[parts.length - 1]; @@ -97,7 +95,7 @@ public class MetalinkTemplateDownloader extends TemplateDownloaderBase implement try { client.executeMethod(request); } catch (IOException e) { - LOGGER.error("Error on HTTP request: " + e.getMessage()); + logger.error("Error on HTTP request: " + e.getMessage()); return false; } return performDownload(); @@ -110,7 +108,7 @@ public class MetalinkTemplateDownloader extends TemplateDownloaderBase implement ) { IOUtils.copy(in, out); } catch (IOException e) { - LOGGER.error("Error downloading template from: " + _downloadUrl + " due to: " + e.getMessage()); + logger.error("Error downloading template from: " + _downloadUrl + " due to: " + e.getMessage()); return false; } return true; @@ -121,13 +119,13 @@ public class MetalinkTemplateDownloader extends TemplateDownloaderBase implement return 0; } - LOGGER.info("Starting metalink download from: " + _downloadUrl); + logger.info("Starting metalink download from: " + _downloadUrl); _start = System.currentTimeMillis(); status = Status.IN_PROGRESS; List metalinkUrls = UriUtils.getMetalinkUrls(_downloadUrl); if (CollectionUtils.isEmpty(metalinkUrls)) { - LOGGER.error("No URLs found for metalink: " + _downloadUrl); + logger.error("No URLs found for metalink: " + _downloadUrl); status = Status.UNRECOVERABLE_ERROR; return 0; } @@ -140,11 +138,11 @@ public class MetalinkTemplateDownloader extends TemplateDownloaderBase implement i++; } if (!downloaded) { - LOGGER.error("Template couldn't be downloaded"); + logger.error("Template couldn't be downloaded"); status = Status.UNRECOVERABLE_ERROR; return 0; } - LOGGER.info("Template downloaded successfully on: " + _toFile); + logger.info("Template downloaded successfully on: " + _toFile); status = Status.DOWNLOAD_FINISHED; _downloadTime = System.currentTimeMillis() - _start; if (_callback != null) { @@ -173,4 +171,12 @@ public class MetalinkTemplateDownloader extends TemplateDownloaderBase implement public void setStatus(Status status) { this.status = status; } + + @Override + public void setFollowRedirects(boolean followRedirects) { + super.setFollowRedirects(followRedirects); + if (this.request != null) { + this.request.setFollowRedirects(followRedirects); + } + } } diff --git a/core/src/main/java/com/cloud/storage/template/OVAProcessor.java b/core/src/main/java/com/cloud/storage/template/OVAProcessor.java index 33f7e28ac03..ab3aa0d0e3a 100644 --- a/core/src/main/java/com/cloud/storage/template/OVAProcessor.java +++ b/core/src/main/java/com/cloud/storage/template/OVAProcessor.java @@ -34,7 +34,6 @@ import com.cloud.agent.api.to.deployasis.OVFVirtualHardwareSectionTO; import com.cloud.agent.api.to.deployasis.OVFNetworkTO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -52,7 +51,6 @@ import com.cloud.utils.script.Script; * processes the content of an OVA for registration of a template */ public class OVAProcessor extends AdapterBase implements Processor { - private static final Logger LOGGER = Logger.getLogger(OVAProcessor.class); StorageLayer _storage; @Override @@ -66,11 +64,11 @@ public class OVAProcessor extends AdapterBase implements Processor { return null; } - LOGGER.info("Template processing. templatePath: " + templatePath + ", templateName: " + templateName); + logger.info("Template processing. templatePath: " + templatePath + ", templateName: " + templateName); String templateFilePath = templatePath + File.separator + templateName + "." + ImageFormat.OVA.getFileExtension(); if (!_storage.exists(templateFilePath)) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("Unable to find the vmware template file: " + templateFilePath); + if (logger.isInfoEnabled()) { + logger.info("Unable to find the vmware template file: " + templateFilePath); } return null; } @@ -114,46 +112,46 @@ public class OVAProcessor extends AdapterBase implements Processor { List disks = ovfHelper.getOVFVolumeInfoFromFile(ovfFilePath, doc, null); if (CollectionUtils.isNotEmpty(disks)) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace(String.format("Found %d disks in template %s", disks.size(), ovfFilePath)); + if (logger.isTraceEnabled()) { + logger.trace(String.format("Found %d disks in template %s", disks.size(), ovfFilePath)); } ovfInformationTO.setDisks(disks); } List nets = ovfHelper.getNetPrerequisitesFromDocument(doc); if (CollectionUtils.isNotEmpty(nets)) { - LOGGER.info("Found " + nets.size() + " prerequisite networks"); + logger.info("Found " + nets.size() + " prerequisite networks"); ovfInformationTO.setNetworks(nets); - } else if (LOGGER.isTraceEnabled()) { - LOGGER.trace(String.format("no net prerequisites found in template %s", ovfFilePath)); + } else if (logger.isTraceEnabled()) { + logger.trace(String.format("no net prerequisites found in template %s", ovfFilePath)); } List ovfProperties = ovfHelper.getConfigurableOVFPropertiesFromDocument(doc); if (CollectionUtils.isNotEmpty(ovfProperties)) { - LOGGER.info("Found " + ovfProperties.size() + " configurable OVF properties"); + logger.info("Found " + ovfProperties.size() + " configurable OVF properties"); ovfInformationTO.setProperties(ovfProperties); - } else if (LOGGER.isTraceEnabled()) { - LOGGER.trace(String.format("no ovf properties found in template %s", ovfFilePath)); + } else if (logger.isTraceEnabled()) { + logger.trace(String.format("no ovf properties found in template %s", ovfFilePath)); } OVFVirtualHardwareSectionTO hardwareSection = ovfHelper.getVirtualHardwareSectionFromDocument(doc); List configurations = hardwareSection.getConfigurations(); if (CollectionUtils.isNotEmpty(configurations)) { - LOGGER.info("Found " + configurations.size() + " deployment option configurations"); + logger.info("Found " + configurations.size() + " deployment option configurations"); } List hardwareItems = hardwareSection.getCommonHardwareItems(); if (CollectionUtils.isNotEmpty(hardwareItems)) { - LOGGER.info("Found " + hardwareItems.size() + " virtual hardware items"); + logger.info("Found " + hardwareItems.size() + " virtual hardware items"); } if (StringUtils.isNotBlank(hardwareSection.getMinimiumHardwareVersion())) { - LOGGER.info("Found minimum hardware version " + hardwareSection.getMinimiumHardwareVersion()); + logger.info("Found minimum hardware version " + hardwareSection.getMinimiumHardwareVersion()); } ovfInformationTO.setHardwareSection(hardwareSection); List eulaSections = ovfHelper.getEulaSectionsFromDocument(doc); if (CollectionUtils.isNotEmpty(eulaSections)) { - LOGGER.info("Found " + eulaSections.size() + " license agreements"); + logger.info("Found " + eulaSections.size() + " license agreements"); ovfInformationTO.setEulaSections(eulaSections); } Pair guestOsPair = ovfHelper.getOperatingSystemInfoFromDocument(doc); if (guestOsPair != null) { - LOGGER.info("Found guest OS information: " + guestOsPair.first() + " - " + guestOsPair.second()); + logger.info("Found guest OS information: " + guestOsPair.first() + " - " + guestOsPair.second()); ovfInformationTO.setGuestOsInfo(guestOsPair); } return ovfInformationTO; @@ -163,33 +161,33 @@ public class OVAProcessor extends AdapterBase implements Processor { Script command; String result; - command = new Script("chmod", 0, LOGGER); + command = new Script("chmod", 0, logger); command.add("-R"); command.add("666", templatePath); result = command.execute(); if (result != null) { - LOGGER.warn("Unable to set permissions for files in " + templatePath + " due to " + result); + logger.warn("Unable to set permissions for files in " + templatePath + " due to " + result); } - command = new Script("chmod", 0, LOGGER); + command = new Script("chmod", 0, logger); command.add("777", templatePath); result = command.execute(); if (result != null) { - LOGGER.warn("Unable to set permissions for " + templatePath + " due to " + result); + logger.warn("Unable to set permissions for " + templatePath + " due to " + result); } } private String unpackOva(String templatePath, String templateName, long processTimeout) throws InternalErrorException { - LOGGER.info("Template processing - untar OVA package. templatePath: " + templatePath + ", templateName: " + templateName); + logger.info("Template processing - untar OVA package. templatePath: " + templatePath + ", templateName: " + templateName); String templateFileFullPath = templatePath + File.separator + templateName + "." + ImageFormat.OVA.getFileExtension(); File templateFile = new File(templateFileFullPath); - Script command = new Script("tar", processTimeout, LOGGER); + Script command = new Script("tar", processTimeout, logger); command.add("--no-same-owner"); command.add("--no-same-permissions"); command.add("-xf", templateFileFullPath); command.setWorkDir(templateFile.getParent()); String result = command.execute(); if (result != null) { - LOGGER.info("failed to untar OVA package due to " + result + ". templatePath: " + templatePath + ", templateName: " + templateName); + logger.info("failed to untar OVA package due to " + result + ". templatePath: " + templatePath + ", templateName: " + templateName); throw new InternalErrorException("failed to untar OVA package"); } return templateFileFullPath; @@ -197,13 +195,13 @@ public class OVAProcessor extends AdapterBase implements Processor { private boolean conversionChecks(ImageFormat format) { if (format != null) { - if (LOGGER.isInfoEnabled()) { - LOGGER.info("We currently don't handle conversion from " + format + " to OVA."); + if (logger.isInfoEnabled()) { + logger.info("We currently don't handle conversion from " + format + " to OVA."); } return false; } - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("We are handling format " + format + "."); + if (logger.isTraceEnabled()) { + logger.trace("We are handling format " + format + "."); } return true; } @@ -214,7 +212,7 @@ public class OVAProcessor extends AdapterBase implements Processor { long size = getTemplateVirtualSize(file.getParent(), file.getName()); return size; } catch (Exception e) { - LOGGER.info("[ignored]" + logger.info("[ignored]" + "failed to get virtual template size for ova: " + e.getLocalizedMessage()); } return file.length(); @@ -234,7 +232,7 @@ public class OVAProcessor extends AdapterBase implements Processor { OVFHelper ovfHelper = new OVFHelper(); if (ovfFileName == null) { String msg = "Unable to locate OVF file in template package directory: " + templatePath; - LOGGER.error(msg); + logger.error(msg); throw new InternalErrorException(msg); } try { @@ -248,7 +246,7 @@ public class OVAProcessor extends AdapterBase implements Processor { diskSize = Long.parseLong(diskSizeValue); } catch (NumberFormatException e) { // ASSUMEably the diskSize contains a property for replacement - LOGGER.warn(String.format("the disksize for disk %s is not a valid number: %s", disk.getAttribute("diskId"), diskSizeValue)); + logger.warn(String.format("the disksize for disk %s is not a valid number: %s", disk.getAttribute("diskId"), diskSizeValue)); // TODO parse the property to get any value can not be done at registration time // and will have to be done at deploytime, so for orchestration purposes // we now assume, a value of one @@ -260,7 +258,7 @@ public class OVAProcessor extends AdapterBase implements Processor { return virtualSize; } catch (InternalErrorException | NumberFormatException e) { String msg = "getTemplateVirtualSize: Unable to parse OVF XML document " + templatePath + " to get the virtual disk " + templateName + " size due to " + e; - LOGGER.error(msg); + logger.error(msg); throw new InternalErrorException(msg); } } diff --git a/core/src/main/java/com/cloud/storage/template/QCOW2Processor.java b/core/src/main/java/com/cloud/storage/template/QCOW2Processor.java index 56ae078dc51..df1722a0201 100644 --- a/core/src/main/java/com/cloud/storage/template/QCOW2Processor.java +++ b/core/src/main/java/com/cloud/storage/template/QCOW2Processor.java @@ -27,7 +27,6 @@ import java.util.Map; import javax.naming.ConfigurationException; import com.cloud.exception.InternalErrorException; -import org.apache.log4j.Logger; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageLayer; @@ -35,7 +34,6 @@ import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.AdapterBase; public class QCOW2Processor extends AdapterBase implements Processor { - private static final Logger s_logger = Logger.getLogger(QCOW2Processor.class); private static final int VIRTUALSIZE_HEADER_LOCATION = 24; private StorageLayer _storage; @@ -48,14 +46,14 @@ public class QCOW2Processor extends AdapterBase implements Processor { @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) throws InternalErrorException { if (format != null) { - s_logger.debug("We currently don't handle conversion from " + format + " to QCOW2."); + logger.debug("We currently don't handle conversion from " + format + " to QCOW2."); return null; } String qcow2Path = templatePath + File.separator + templateName + "." + ImageFormat.QCOW2.getFileExtension(); if (!_storage.exists(qcow2Path)) { - s_logger.debug("Unable to find the qcow2 file: " + qcow2Path); + logger.debug("Unable to find the qcow2 file: " + qcow2Path); return null; } @@ -70,7 +68,7 @@ public class QCOW2Processor extends AdapterBase implements Processor { try { info.virtualSize = getTemplateVirtualSize(qcow2File); } catch (IOException e) { - s_logger.error("Unable to get virtual size from " + qcow2File.getName()); + logger.error("Unable to get virtual size from " + qcow2File.getName()); throw new InternalErrorException("unable to get virtual size from qcow2 file"); } @@ -83,7 +81,7 @@ public class QCOW2Processor extends AdapterBase implements Processor { long size = getTemplateVirtualSize(file); return size; } catch (Exception e) { - s_logger.info("[ignored]" + "failed to get template virtual size for QCOW2: " + e.getLocalizedMessage()); + logger.info("[ignored]" + "failed to get template virtual size for QCOW2: " + e.getLocalizedMessage()); } return file.length(); } diff --git a/core/src/main/java/com/cloud/storage/template/RawImageProcessor.java b/core/src/main/java/com/cloud/storage/template/RawImageProcessor.java index 5fbc626f271..d6c1f7a808f 100644 --- a/core/src/main/java/com/cloud/storage/template/RawImageProcessor.java +++ b/core/src/main/java/com/cloud/storage/template/RawImageProcessor.java @@ -24,7 +24,6 @@ import java.util.Map; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; import com.cloud.exception.InternalErrorException; import com.cloud.storage.Storage.ImageFormat; @@ -32,7 +31,6 @@ import com.cloud.storage.StorageLayer; import com.cloud.utils.component.AdapterBase; public class RawImageProcessor extends AdapterBase implements Processor { - private static final Logger s_logger = Logger.getLogger(RawImageProcessor.class); StorageLayer _storage; @Override @@ -53,13 +51,13 @@ public class RawImageProcessor extends AdapterBase implements Processor { @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) throws InternalErrorException { if (format != null) { - s_logger.debug("We currently don't handle conversion from " + format + " to raw image."); + logger.debug("We currently don't handle conversion from " + format + " to raw image."); return null; } String imgPath = templatePath + File.separator + templateName + "." + ImageFormat.RAW.getFileExtension(); if (!_storage.exists(imgPath)) { - s_logger.debug("Unable to find raw image:" + imgPath); + logger.debug("Unable to find raw image:" + imgPath); return null; } FormatInfo info = new FormatInfo(); @@ -67,7 +65,7 @@ public class RawImageProcessor extends AdapterBase implements Processor { info.filename = templateName + "." + ImageFormat.RAW.getFileExtension(); info.size = _storage.getSize(imgPath); info.virtualSize = info.size; - s_logger.debug("Process raw image " + info.filename + " successfully"); + logger.debug("Process raw image " + info.filename + " successfully"); return info; } diff --git a/core/src/main/java/com/cloud/storage/template/S3TemplateDownloader.java b/core/src/main/java/com/cloud/storage/template/S3TemplateDownloader.java index 44565c4416c..c24a4cc221f 100644 --- a/core/src/main/java/com/cloud/storage/template/S3TemplateDownloader.java +++ b/core/src/main/java/com/cloud/storage/template/S3TemplateDownloader.java @@ -34,16 +34,17 @@ import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.URIException; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Date; +import java.util.List; import static com.cloud.utils.NumbersUtil.toHumanReadableSize; import static java.util.Arrays.asList; @@ -56,7 +57,6 @@ import static java.util.Arrays.asList; * Execution of the instance is started when runInContext() is called. */ public class S3TemplateDownloader extends ManagedContextRunnable implements TemplateDownloader { - private static final Logger LOGGER = Logger.getLogger(S3TemplateDownloader.class.getName()); private final String downloadUrl; private final String s3Key; @@ -72,8 +72,8 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp private long downloadTime; private long totalBytes; private long maxTemplateSizeInByte; - private boolean resume = false; + private boolean followRedirects = false; public S3TemplateDownloader(S3TO s3TO, String downloadUrl, String installPath, DownloadCompleteCallback downloadCompleteCallback, long maxTemplateSizeInBytes, String username, String password, Proxy proxy, ResourceType resourceType) { @@ -91,7 +91,7 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp this.getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, HTTPUtils.getHttpMethodRetryHandler(5)); // Follow redirects - this.getMethod.setFollowRedirects(true); + this.getMethod.setFollowRedirects(followRedirects); // Set file extension. this.fileExtension = StringUtils.substringAfterLast(StringUtils.substringAfterLast(downloadUrl, "/"), "."); @@ -110,7 +110,7 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp public long download(boolean resume, DownloadCompleteCallback callback) { if (!status.equals(Status.NOT_STARTED)) { // Only start downloading if we haven't started yet. - LOGGER.debug("Template download is already started, not starting again. Template: " + downloadUrl); + logger.debug("Template download is already started, not starting again. Template: " + downloadUrl); return 0; } @@ -118,16 +118,17 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp int responseCode; if ((responseCode = HTTPUtils.executeMethod(httpClient, getMethod)) == -1) { errorString = "Exception while executing HttpMethod " + getMethod.getName() + " on URL " + downloadUrl; - LOGGER.warn(errorString); + logger.warn(errorString); status = Status.UNRECOVERABLE_ERROR; return 0; } - if (!HTTPUtils.verifyResponseCode(responseCode)) { + boolean failedDueToRedirection = List.of(HttpStatus.SC_MOVED_PERMANENTLY, + HttpStatus.SC_MOVED_TEMPORARILY).contains(responseCode) && !followRedirects; + if (!HTTPUtils.verifyResponseCode(responseCode) || failedDueToRedirection) { errorString = "Response code for GetMethod of " + downloadUrl + " is incorrect, responseCode: " + responseCode; - LOGGER.warn(errorString); - + logger.warn(errorString); status = Status.UNRECOVERABLE_ERROR; return 0; } @@ -139,7 +140,7 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp // Check the contentLengthHeader and transferEncodingHeader. if (contentLengthHeader == null) { errorString = "The ContentLengthHeader of " + downloadUrl + " isn't supplied"; - LOGGER.warn(errorString); + logger.warn(errorString); status = Status.UNRECOVERABLE_ERROR; return 0; @@ -150,7 +151,7 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp if (remoteSize > maxTemplateSizeInByte) { errorString = "Remote size is too large for template " + downloadUrl + " remote size is " + remoteSize + " max allowed is " + maxTemplateSizeInByte; - LOGGER.warn(errorString); + logger.warn(errorString); status = Status.UNRECOVERABLE_ERROR; return 0; @@ -162,13 +163,13 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp inputStream = new BufferedInputStream(getMethod.getResponseBodyAsStream()); } catch (IOException e) { errorString = "Exception occurred while opening InputStream for template " + downloadUrl; - LOGGER.warn(errorString); + logger.warn(errorString); status = Status.UNRECOVERABLE_ERROR; return 0; } - LOGGER.info("Starting download from " + downloadUrl + " to S3 bucket " + s3TO.getBucketName() + " and size " + toHumanReadableSize(remoteSize) + " bytes"); + logger.info("Starting download from " + downloadUrl + " to S3 bucket " + s3TO.getBucketName() + " and size " + toHumanReadableSize(remoteSize) + " bytes"); // Time the upload starts. final Date start = new Date(); @@ -197,7 +198,7 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp // Record the amount of bytes transferred. totalBytes += progressEvent.getBytesTransferred(); - LOGGER.trace("Template download from " + downloadUrl + " to S3 bucket " + s3TO.getBucketName() + " transferred " + toHumanReadableSize(totalBytes) + " in " + ((new Date().getTime() - start.getTime()) / 1000) + " seconds"); + logger.trace("Template download from " + downloadUrl + " to S3 bucket " + s3TO.getBucketName() + " transferred " + toHumanReadableSize(totalBytes) + " in " + ((new Date().getTime() - start.getTime()) / 1000) + " seconds"); if (progressEvent.getEventType() == ProgressEventType.TRANSFER_STARTED_EVENT) { status = Status.IN_PROGRESS; @@ -216,15 +217,15 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp upload.waitForCompletion(); } catch (InterruptedException e) { // Interruption while waiting for the upload to complete. - LOGGER.warn("Interruption occurred while waiting for upload of " + downloadUrl + " to complete"); + logger.warn("Interruption occurred while waiting for upload of " + downloadUrl + " to complete"); } downloadTime = new Date().getTime() - start.getTime(); if (status == Status.DOWNLOAD_FINISHED) { - LOGGER.info("Template download from " + downloadUrl + " to S3 bucket " + s3TO.getBucketName() + " transferred " + toHumanReadableSize(totalBytes) + " in " + (downloadTime / 1000) + " seconds, completed successfully!"); + logger.info("Template download from " + downloadUrl + " to S3 bucket " + s3TO.getBucketName() + " transferred " + toHumanReadableSize(totalBytes) + " in " + (downloadTime / 1000) + " seconds, completed successfully!"); } else { - LOGGER.warn("Template download from " + downloadUrl + " to S3 bucket " + s3TO.getBucketName() + " transferred " + toHumanReadableSize(totalBytes) + " in " + (downloadTime / 1000) + " seconds, completed with status " + status.toString()); + logger.warn("Template download from " + downloadUrl + " to S3 bucket " + s3TO.getBucketName() + " transferred " + toHumanReadableSize(totalBytes) + " in " + (downloadTime / 1000) + " seconds, completed with status " + status.toString()); } // Close input stream @@ -278,7 +279,7 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp } public void cleanupAfterError() { - LOGGER.warn("Cleanup after error, trying to remove object: " + s3Key); + logger.warn("Cleanup after error, trying to remove object: " + s3Key); S3Utils.deleteObject(s3TO, s3TO.getBucketName(), s3Key); } @@ -373,4 +374,12 @@ public class S3TemplateDownloader extends ManagedContextRunnable implements Temp public String getFileExtension() { return fileExtension; } + + @Override + public void setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + if (this.getMethod != null) { + this.getMethod.setFollowRedirects(followRedirects); + } + } } diff --git a/core/src/main/java/com/cloud/storage/template/ScpTemplateDownloader.java b/core/src/main/java/com/cloud/storage/template/ScpTemplateDownloader.java index 912809ca722..44379efcd55 100644 --- a/core/src/main/java/com/cloud/storage/template/ScpTemplateDownloader.java +++ b/core/src/main/java/com/cloud/storage/template/ScpTemplateDownloader.java @@ -23,7 +23,6 @@ import java.io.File; import java.net.URI; import java.net.URISyntaxException; -import org.apache.log4j.Logger; import com.trilead.ssh2.SCPClient; @@ -31,7 +30,6 @@ import com.cloud.storage.StorageLayer; import com.cloud.utils.exception.CloudRuntimeException; public class ScpTemplateDownloader extends TemplateDownloaderBase implements TemplateDownloader { - private static final Logger s_logger = Logger.getLogger(ScpTemplateDownloader.class); public ScpTemplateDownloader(StorageLayer storageLayer, String downloadUrl, String toDir, long maxTemplateSizeInBytes, DownloadCompleteCallback callback) { super(storageLayer, downloadUrl, toDir, maxTemplateSizeInBytes, callback); @@ -40,7 +38,7 @@ public class ScpTemplateDownloader extends TemplateDownloaderBase implements Tem try { uri = new URI(_downloadUrl); } catch (URISyntaxException e) { - s_logger.warn("URI syntax error: " + _downloadUrl); + logger.warn("URI syntax error: " + _downloadUrl); _status = Status.UNRECOVERABLE_ERROR; return; } @@ -108,7 +106,7 @@ public class ScpTemplateDownloader extends TemplateDownloaderBase implements Tem if (!file.exists()) { _status = Status.UNRECOVERABLE_ERROR; - s_logger.debug("unable to scp the file " + _downloadUrl); + logger.debug("unable to scp the file " + _downloadUrl); return 0; } @@ -123,7 +121,7 @@ public class ScpTemplateDownloader extends TemplateDownloaderBase implements Tem return _totalBytes; } catch (Exception e) { - s_logger.warn("Unable to download " + _downloadUrl, e); + logger.warn("Unable to download " + _downloadUrl, e); _status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; _errorString = e.getMessage(); return 0; diff --git a/core/src/main/java/com/cloud/storage/template/SimpleHttpMultiFileDownloader.java b/core/src/main/java/com/cloud/storage/template/SimpleHttpMultiFileDownloader.java new file mode 100644 index 00000000000..8719947cb4f --- /dev/null +++ b/core/src/main/java/com/cloud/storage/template/SimpleHttpMultiFileDownloader.java @@ -0,0 +1,495 @@ +// 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.storage.template; + +import static com.cloud.utils.NumbersUtil.toHumanReadableSize; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.cloudstack.managed.context.ManagedContextRunnable; +import org.apache.cloudstack.storage.command.DownloadCommand; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpMethodRetryHandler; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.NoHttpResponseException; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.HeadMethod; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.lang3.StringUtils; + +import com.cloud.storage.StorageLayer; + +public class SimpleHttpMultiFileDownloader extends ManagedContextRunnable implements TemplateDownloader { + private static final MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager(); + + private static final int CHUNK_SIZE = 1024 * 1024; //1M + private String[] downloadUrls; + private String currentToFile; + public TemplateDownloader.Status currentStatus; + public TemplateDownloader.Status status; + private String errorString = null; + private long totalRemoteSize = 0; + private long currentRemoteSize = 0; + public long downloadTime = 0; + public long currentTotalBytes; + public long totalBytes = 0; + private final HttpClient client; + private GetMethod request; + private boolean resume = false; + private DownloadCompleteCallback completionCallback; + StorageLayer _storage; + boolean inited = true; + + private String toDir; + private long maxTemplateSizeInBytes; + private DownloadCommand.ResourceType resourceType = DownloadCommand.ResourceType.TEMPLATE; + private final HttpMethodRetryHandler retryHandler; + + private HashMap urlFileMap; + private boolean followRedirects = false; + + public SimpleHttpMultiFileDownloader(StorageLayer storageLayer, String[] downloadUrls, String toDir, + DownloadCompleteCallback callback, long maxTemplateSizeInBytes, + DownloadCommand.ResourceType resourceType) { + _storage = storageLayer; + this.downloadUrls = downloadUrls; + this.toDir = toDir; + this.resourceType = resourceType; + this.maxTemplateSizeInBytes = maxTemplateSizeInBytes; + completionCallback = callback; + status = TemplateDownloader.Status.NOT_STARTED; + currentStatus = TemplateDownloader.Status.NOT_STARTED; + currentTotalBytes = 0; + client = new HttpClient(s_httpClientManager); + retryHandler = createRetryTwiceHandler(); + urlFileMap = new HashMap<>(); + } + + private GetMethod createRequest(String downloadUrl) { + GetMethod request = new GetMethod(downloadUrl); + request.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryHandler); + request.setFollowRedirects(followRedirects); + return request; + } + + private void checkTemporaryDestination(String toDir) { + try { + File f = File.createTempFile("dnld", "tmp_", new File(toDir)); + if (_storage != null) { + _storage.setWorldReadableAndWriteable(f); + } + currentToFile = f.getAbsolutePath(); + } catch (IOException ex) { + errorString = "Unable to start download -- check url? "; + currentStatus = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + logger.warn("Exception in constructor -- " + ex.toString()); + } + } + + private HttpMethodRetryHandler createRetryTwiceHandler() { + return new HttpMethodRetryHandler() { + @Override + public boolean retryMethod(final HttpMethod method, final IOException exception, int executionCount) { + if (executionCount >= 2) { + // Do not retry if over max retry count + return false; + } + if (exception instanceof NoHttpResponseException) { + // Retry if the server dropped connection on us + return true; + } + if (!method.isRequestSent()) { + // Retry if the request has not been sent fully or + // if it's OK to retry methods that have been sent + return true; + } + // otherwise do not retry + return false; + } + }; + } + + private void tryAndGetTotalRemoteSize() { + for (String downloadUrl : downloadUrls) { + if (StringUtils.isBlank(downloadUrl)) { + continue; + } + HeadMethod headMethod = new HeadMethod(downloadUrl); + try { + if (client.executeMethod(headMethod) != HttpStatus.SC_OK) { + continue; + } + Header contentLengthHeader = headMethod.getResponseHeader("content-length"); + if (contentLengthHeader == null) { + continue; + } + totalRemoteSize += Long.parseLong(contentLengthHeader.getValue()); + } catch (IOException e) { + logger.warn(String.format("Cannot reach URL: %s while trying to get remote sizes due to: %s", downloadUrl, e.getMessage()), e); + } finally { + headMethod.releaseConnection(); + } + } + } + + private long downloadFile(String downloadUrl) { + logger.debug("Starting download for " + downloadUrl); + currentTotalBytes = 0; + currentRemoteSize = 0; + File file = null; + request = null; + try { + request = createRequest(downloadUrl); + checkTemporaryDestination(toDir); + urlFileMap.put(downloadUrl, currentToFile); + file = new File(currentToFile); + long localFileSize = checkLocalFileSizeForResume(resume, file); + if (checkServerResponse(localFileSize, downloadUrl)) return 0; + if (!tryAndGetRemoteSize()) return 0; + if (!canHandleDownloadSize()) return 0; + checkAndSetDownloadSize(); + try (InputStream in = request.getResponseBodyAsStream(); + RandomAccessFile out = new RandomAccessFile(file, "rw"); + ) { + out.seek(localFileSize); + logger.info("Starting download from " + downloadUrl + " to " + currentToFile + " remoteSize=" + toHumanReadableSize(currentRemoteSize) + " , max size=" + toHumanReadableSize(maxTemplateSizeInBytes)); + if (copyBytes(file, in, out)) return 0; + checkDownloadCompletion(); + } + return currentTotalBytes; + } catch (HttpException hte) { + currentStatus = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + errorString = hte.getMessage(); + } catch (IOException ioe) { + currentStatus = TemplateDownloader.Status.UNRECOVERABLE_ERROR; //probably a file write error? + // Let's not overwrite the original error message. + if (errorString == null) { + errorString = ioe.getMessage(); + } + } finally { + if (currentStatus == Status.UNRECOVERABLE_ERROR && file != null && file.exists() && !file.isDirectory()) { + file.delete(); + } + if (request != null) { + request.releaseConnection(); + } + } + return 0; + } + + @Override + public long download(boolean resume, DownloadCompleteCallback callback) { + if (skipDownloadOnStatus()) return 0; + if (resume) { + logger.error("Resume not allowed for this downloader"); + status = Status.UNRECOVERABLE_ERROR; + return 0; + } + logger.debug("Starting downloads"); + status = Status.IN_PROGRESS; + Date start = new Date(); + tryAndGetTotalRemoteSize(); + for (String downloadUrl : downloadUrls) { + if (StringUtils.isBlank(downloadUrl)) { + continue; + } + long bytes = downloadFile(downloadUrl); + if (currentStatus != Status.DOWNLOAD_FINISHED) { + break; + } + totalBytes += bytes; + } + status = currentStatus; + Date finish = new Date(); + downloadTime += finish.getTime() - start.getTime(); + if (callback != null) { + callback.downloadComplete(status); + } + return 0; + } + + private boolean copyBytes(File file, InputStream in, RandomAccessFile out) throws IOException { + int bytes; + byte[] block = new byte[CHUNK_SIZE]; + long offset = 0; + boolean done = false; + currentStatus = Status.IN_PROGRESS; + while (!done && currentStatus != Status.ABORTED && offset <= currentRemoteSize) { + if ((bytes = in.read(block, 0, CHUNK_SIZE)) > -1) { + offset = writeBlock(bytes, out, block, offset); + } else { + done = true; + } + } + out.getFD().sync(); + return false; + } + + private long writeBlock(int bytes, RandomAccessFile out, byte[] block, long offset) throws IOException { + out.write(block, 0, bytes); + offset += bytes; + out.seek(offset); + currentTotalBytes += bytes; + return offset; + } + + private void checkDownloadCompletion() { + String downloaded = "(incomplete download)"; + if (currentTotalBytes >= currentRemoteSize) { + currentStatus = Status.DOWNLOAD_FINISHED; + downloaded = "(download complete remote=" + toHumanReadableSize(currentRemoteSize) + " bytes)"; + } + errorString = "Downloaded " + toHumanReadableSize(currentTotalBytes) + " bytes " + downloaded; + } + + private boolean canHandleDownloadSize() { + if (currentRemoteSize > maxTemplateSizeInBytes) { + logger.info("Remote size is too large: " + toHumanReadableSize(currentRemoteSize) + " , max=" + toHumanReadableSize(maxTemplateSizeInBytes)); + currentStatus = Status.UNRECOVERABLE_ERROR; + errorString = "Download file size is too large"; + return false; + } + return true; + } + + private void checkAndSetDownloadSize() { + if (currentRemoteSize == 0) { + currentRemoteSize = maxTemplateSizeInBytes; + } + if (totalRemoteSize == 0) { + totalRemoteSize = currentRemoteSize; + } + } + + private boolean tryAndGetRemoteSize() { + Header contentLengthHeader = request.getResponseHeader("content-length"); + boolean chunked = false; + long reportedRemoteSize = 0; + if (contentLengthHeader == null) { + Header chunkedHeader = request.getResponseHeader("Transfer-Encoding"); + if (chunkedHeader == null || !"chunked".equalsIgnoreCase(chunkedHeader.getValue())) { + currentStatus = Status.UNRECOVERABLE_ERROR; + errorString = " Failed to receive length of download "; + return false; + } else if ("chunked".equalsIgnoreCase(chunkedHeader.getValue())) { + chunked = true; + } + } else { + reportedRemoteSize = Long.parseLong(contentLengthHeader.getValue()); + if (reportedRemoteSize == 0) { + currentStatus = Status.DOWNLOAD_FINISHED; + String downloaded = "(download complete remote=" + currentRemoteSize + "bytes)"; + errorString = "Downloaded " + currentTotalBytes + " bytes " + downloaded; + downloadTime = 0; + return false; + } + } + + if (currentRemoteSize == 0) { + currentRemoteSize = reportedRemoteSize; + } + return true; + } + + private boolean checkServerResponse(long localFileSize, String downloadUrl) throws IOException { + int responseCode = 0; + + if (localFileSize > 0) { + // require partial content support for resume + request.addRequestHeader("Range", "bytes=" + localFileSize + "-"); + if (client.executeMethod(request) != HttpStatus.SC_PARTIAL_CONTENT) { + errorString = "HTTP Server does not support partial get"; + currentStatus = Status.UNRECOVERABLE_ERROR; + return true; + } + } else if ((responseCode = client.executeMethod(request)) != HttpStatus.SC_OK) { + currentStatus = Status.UNRECOVERABLE_ERROR; + errorString = " HTTP Server returned " + responseCode + " (expected 200 OK) "; + if (List.of(HttpStatus.SC_MOVED_PERMANENTLY, HttpStatus.SC_MOVED_TEMPORARILY).contains(responseCode) + && !followRedirects) { + errorString = String.format("Failed to download %s due to redirection, response code: %d", + downloadUrl, responseCode); + logger.error(errorString); + } + return true; //FIXME: retry? + } + return false; + } + + private long checkLocalFileSizeForResume(boolean resume, File file) { + // TODO check the status of this downloader as well? + long localFileSize = 0; + if (file.exists() && resume) { + localFileSize = file.length(); + logger.info("Resuming download to file (current size)=" + toHumanReadableSize(localFileSize)); + } + return localFileSize; + } + + private boolean skipDownloadOnStatus() { + switch (currentStatus) { + case ABORTED: + case UNRECOVERABLE_ERROR: + case DOWNLOAD_FINISHED: + return true; + default: + + } + return false; + } + + public String[] getDownloadUrls() { + return downloadUrls; + } + + public String getCurrentToFile() { + File file = new File(currentToFile); + + return file.getAbsolutePath(); + } + + @Override + public TemplateDownloader.Status getStatus() { + return currentStatus; + } + + @Override + public long getDownloadTime() { + return downloadTime; + } + + @Override + public long getDownloadedBytes() { + return totalBytes; + } + + @Override + @SuppressWarnings("fallthrough") + public boolean stopDownload() { + switch (getStatus()) { + case IN_PROGRESS: + if (request != null) { + request.abort(); + } + currentStatus = TemplateDownloader.Status.ABORTED; + return true; + case UNKNOWN: + case NOT_STARTED: + case RECOVERABLE_ERROR: + case UNRECOVERABLE_ERROR: + case ABORTED: + currentStatus = TemplateDownloader.Status.ABORTED; + case DOWNLOAD_FINISHED: + File f = new File(currentToFile); + if (f.exists()) { + f.delete(); + } + return true; + + default: + return true; + } + } + + @Override + public int getDownloadPercent() { + if (totalRemoteSize == 0) { + return 0; + } + + return (int)(100.0 * totalBytes / totalRemoteSize); + } + + @Override + protected void runInContext() { + try { + download(resume, completionCallback); + } catch (Throwable t) { + logger.warn("Caught exception during download " + t.getMessage(), t); + errorString = "Failed to install: " + t.getMessage(); + currentStatus = TemplateDownloader.Status.UNRECOVERABLE_ERROR; + } + + } + + @Override + public void setStatus(TemplateDownloader.Status status) { + this.currentStatus = status; + } + + public boolean isResume() { + return resume; + } + + @Override + public String getDownloadError() { + return errorString == null ? " " : errorString; + } + + @Override + public String getDownloadLocalPath() { + return toDir; + } + + @Override + public void setResume(boolean resume) { + this.resume = resume; + } + + @Override + public long getMaxTemplateSizeInBytes() { + return maxTemplateSizeInBytes; + } + + @Override + public void setDownloadError(String error) { + errorString = error; + } + + @Override + public boolean isInited() { + return inited; + } + + public DownloadCommand.ResourceType getResourceType() { + return resourceType; + } + + public Map getDownloadedFilesMap() { + return urlFileMap; + } + + @Override + public void setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + if (this.request != null) { + this.request.setFollowRedirects(followRedirects); + } + } +} diff --git a/core/src/main/java/com/cloud/storage/template/TARProcessor.java b/core/src/main/java/com/cloud/storage/template/TARProcessor.java index 51aeb234c50..70b59336323 100644 --- a/core/src/main/java/com/cloud/storage/template/TARProcessor.java +++ b/core/src/main/java/com/cloud/storage/template/TARProcessor.java @@ -22,14 +22,12 @@ package com.cloud.storage.template; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageLayer; import com.cloud.utils.component.AdapterBase; -import org.apache.log4j.Logger; import javax.naming.ConfigurationException; import java.io.File; import java.util.Map; public class TARProcessor extends AdapterBase implements Processor { - private static final Logger s_logger = Logger.getLogger(TARProcessor.class); private StorageLayer _storage; @@ -41,14 +39,14 @@ public class TARProcessor extends AdapterBase implements Processor { @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) { if (format != null) { - s_logger.debug("We currently don't handle conversion from " + format + " to TAR."); + logger.debug("We currently don't handle conversion from " + format + " to TAR."); return null; } String tarPath = templatePath + File.separator + templateName + "." + ImageFormat.TAR.getFileExtension(); if (!_storage.exists(tarPath)) { - s_logger.debug("Unable to find the tar file: " + tarPath); + logger.debug("Unable to find the tar file: " + tarPath); return null; } diff --git a/core/src/main/java/com/cloud/storage/template/TemplateDownloader.java b/core/src/main/java/com/cloud/storage/template/TemplateDownloader.java index 5db3d2425a5..9fb1ca42442 100644 --- a/core/src/main/java/com/cloud/storage/template/TemplateDownloader.java +++ b/core/src/main/java/com/cloud/storage/template/TemplateDownloader.java @@ -92,4 +92,6 @@ public interface TemplateDownloader extends Runnable { boolean isInited(); long getMaxTemplateSizeInBytes(); + + void setFollowRedirects(boolean followRedirects); } diff --git a/core/src/main/java/com/cloud/storage/template/TemplateDownloaderBase.java b/core/src/main/java/com/cloud/storage/template/TemplateDownloaderBase.java index f56e4911ca7..f1cb21a1815 100644 --- a/core/src/main/java/com/cloud/storage/template/TemplateDownloaderBase.java +++ b/core/src/main/java/com/cloud/storage/template/TemplateDownloaderBase.java @@ -21,14 +21,12 @@ package com.cloud.storage.template; import java.io.File; -import org.apache.log4j.Logger; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import com.cloud.storage.StorageLayer; public abstract class TemplateDownloaderBase extends ManagedContextRunnable implements TemplateDownloader { - private static final Logger s_logger = Logger.getLogger(TemplateDownloaderBase.class); protected String _downloadUrl; protected String _toFile; @@ -43,6 +41,7 @@ public abstract class TemplateDownloaderBase extends ManagedContextRunnable impl protected long _start; protected StorageLayer _storage; protected boolean _inited = false; + protected boolean followRedirects = false; private long maxTemplateSizeInBytes; public TemplateDownloaderBase(StorageLayer storage, String downloadUrl, String toDir, long maxTemplateSizeInBytes, DownloadCompleteCallback callback) { @@ -133,7 +132,7 @@ public abstract class TemplateDownloaderBase extends ManagedContextRunnable impl try { download(_resume, _callback); } catch (Exception e) { - s_logger.warn("Unable to complete download due to ", e); + logger.warn("Unable to complete download due to ", e); _errorString = "Failed to install: " + e.getMessage(); _status = TemplateDownloader.Status.UNRECOVERABLE_ERROR; } @@ -149,4 +148,9 @@ public abstract class TemplateDownloaderBase extends ManagedContextRunnable impl public boolean isInited() { return _inited; } + + @Override + public void setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + } } diff --git a/core/src/main/java/com/cloud/storage/template/TemplateLocation.java b/core/src/main/java/com/cloud/storage/template/TemplateLocation.java index 99360eea72c..563c642f292 100644 --- a/core/src/main/java/com/cloud/storage/template/TemplateLocation.java +++ b/core/src/main/java/com/cloud/storage/template/TemplateLocation.java @@ -19,16 +19,16 @@ package com.cloud.storage.template; +import static com.cloud.utils.NumbersUtil.toHumanReadableSize; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.Properties; -import java.util.Arrays; - -import org.apache.log4j.Logger; import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType; @@ -36,11 +36,11 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageLayer; import com.cloud.storage.template.Processor.FormatInfo; import com.cloud.utils.NumbersUtil; - -import static com.cloud.utils.NumbersUtil.toHumanReadableSize; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; public class TemplateLocation { - private static final Logger s_logger = Logger.getLogger(TemplateLocation.class); + protected Logger logger = LogManager.getLogger(getClass()); public final static String Filename = "template.properties"; StorageLayer _storage; @@ -65,6 +65,9 @@ public class TemplateLocation { if (_templatePath.matches(".*" + "volumes" + ".*")) { _file = _storage.getFile(_templatePath + "volume.properties"); _resourceType = ResourceType.VOLUME; + } else if (_templatePath.matches(".*" + "snapshots" + ".*")) { + _file = _storage.getFile(_templatePath + "snapshot.properties"); + _resourceType = ResourceType.SNAPSHOT; } else { _file = _storage.getFile(_templatePath + Filename); } @@ -88,8 +91,8 @@ public class TemplateLocation { if (!isRemoved) { purged = false; } - if (s_logger.isDebugEnabled()) { - s_logger.debug((isRemoved ? "Removed " : "Unable to remove") + file); + if (logger.isDebugEnabled()) { + logger.debug((isRemoved ? "Removed " : "Unable to remove") + file); } } @@ -100,27 +103,27 @@ public class TemplateLocation { try (FileInputStream strm = new FileInputStream(_file);) { _props.load(strm); } catch (IOException e) { - s_logger.warn("Unable to load the template properties for '" + _file + "': ", e); + logger.warn("Unable to load the template properties for '" + _file + "': ", e); } for (ImageFormat format : ImageFormat.values()) { String currentExtension = format.getFileExtension(); String ext = _props.getProperty(currentExtension); if (ext != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("File extension '" + currentExtension + "' was found in '" + _file + "'."); + if (logger.isDebugEnabled()) { + logger.debug("File extension '" + currentExtension + "' was found in '" + _file + "'."); } FormatInfo info = new FormatInfo(); info.format = format; info.filename = _props.getProperty(currentExtension + ".filename"); if (info.filename == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Property '" + currentExtension + ".filename' was not found in '" + _file + "'. Current format is ignored."); + if (logger.isDebugEnabled()) { + logger.debug("Property '" + currentExtension + ".filename' was not found in '" + _file + "'. Current format is ignored."); } continue; } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Property '" + currentExtension + ".filename' was found in '" + _file + "'. Current format will be parsed."); + if (logger.isDebugEnabled()) { + logger.debug("Property '" + currentExtension + ".filename' was found in '" + _file + "'. Current format will be parsed."); } info.size = NumbersUtil.parseLong(_props.getProperty(currentExtension + ".size"), -1); _props.setProperty("physicalSize", Long.toString(info.size)); @@ -129,18 +132,18 @@ public class TemplateLocation { if (!checkFormatValidity(info)) { _isCorrupted = true; - s_logger.warn("Cleaning up inconsistent information for " + format); + logger.warn("Cleaning up inconsistent information for " + format); } } else { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Format extension '" + currentExtension + "' wasn't found in '" + _file + "'."); + if (logger.isDebugEnabled()) { + logger.debug("Format extension '" + currentExtension + "' wasn't found in '" + _file + "'."); } } } if (_props.getProperty("uniquename") == null || _props.getProperty("virtualsize") == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Property 'uniquename' or 'virtualsize' weren't found in '" + _file + "'. Loading failed."); + if (logger.isDebugEnabled()) { + logger.debug("Property 'uniquename' or 'virtualsize' weren't found in '" + _file + "'. Loading failed."); } return false; } @@ -158,7 +161,7 @@ public class TemplateLocation { try (FileOutputStream strm = new FileOutputStream(_file);) { _props.store(strm, ""); } catch (IOException e) { - s_logger.warn("Unable to save the template properties ", e); + logger.warn("Unable to save the template properties ", e); return false; } return true; @@ -170,6 +173,8 @@ public class TemplateLocation { tmplInfo.installPath = _templatePath + _props.getProperty("filename"); // _templatePath endsWith / if (_resourceType == ResourceType.VOLUME) { tmplInfo.installPath = tmplInfo.installPath.substring(tmplInfo.installPath.indexOf("volumes")); + } else if (_resourceType == ResourceType.SNAPSHOT) { + tmplInfo.installPath = tmplInfo.installPath.substring(tmplInfo.installPath.indexOf("snapshots")); } else { tmplInfo.installPath = tmplInfo.installPath.substring(tmplInfo.installPath.indexOf("template")); } @@ -200,9 +205,9 @@ public class TemplateLocation { deleteFormat(newInfo.format); if (!checkFormatValidity(newInfo)) { - s_logger.warn("Format is invalid"); - s_logger.debug("Format: " + newInfo.format + " size: " + toHumanReadableSize(newInfo.size) + " virtualsize: " + toHumanReadableSize(newInfo.virtualSize) + " filename: " + newInfo.filename); - s_logger.debug("format, filename cannot be null and size, virtual size should be > 0 "); + logger.warn("Format is invalid"); + logger.debug("Format: " + newInfo.format + " size: " + toHumanReadableSize(newInfo.size) + " virtualsize: " + toHumanReadableSize(newInfo.virtualSize) + " filename: " + newInfo.filename); + logger.debug("format, filename cannot be null and size, virtual size should be > 0 "); return false; } diff --git a/core/src/main/java/com/cloud/storage/template/VhdProcessor.java b/core/src/main/java/com/cloud/storage/template/VhdProcessor.java index baea7bf0db5..9f18d782b42 100644 --- a/core/src/main/java/com/cloud/storage/template/VhdProcessor.java +++ b/core/src/main/java/com/cloud/storage/template/VhdProcessor.java @@ -27,7 +27,6 @@ import com.cloud.utils.component.AdapterBase; import org.apache.commons.compress.compressors.CompressorException; import org.apache.commons.compress.compressors.CompressorInputStream; import org.apache.commons.compress.compressors.CompressorStreamFactory; -import org.apache.log4j.Logger; import javax.naming.ConfigurationException; import java.io.BufferedInputStream; @@ -46,7 +45,6 @@ import java.util.Map; */ public class VhdProcessor extends AdapterBase implements Processor { - private static final Logger s_logger = Logger.getLogger(VhdProcessor.class); StorageLayer _storage; private int vhdFooterSize = 512; private int vhdCookieOffset = 8; @@ -64,13 +62,13 @@ public class VhdProcessor extends AdapterBase implements Processor { @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) throws InternalErrorException { if (format != null) { - s_logger.debug("We currently don't handle conversion from " + format + " to VHD."); + logger.debug("We currently don't handle conversion from " + format + " to VHD."); return null; } String vhdPath = templatePath + File.separator + templateName + "." + ImageFormat.VHD.getFileExtension(); if (!_storage.exists(vhdPath)) { - s_logger.debug("Unable to find the vhd file: " + vhdPath); + logger.debug("Unable to find the vhd file: " + vhdPath); return null; } @@ -84,7 +82,7 @@ public class VhdProcessor extends AdapterBase implements Processor { try { info.virtualSize = getTemplateVirtualSize(vhdFile); } catch (IOException e) { - s_logger.error("Unable to get the virtual size for " + vhdPath); + logger.error("Unable to get the virtual size for " + vhdPath); throw new InternalErrorException("unable to get virtual size from vhd file"); } @@ -97,7 +95,7 @@ public class VhdProcessor extends AdapterBase implements Processor { long size = getTemplateVirtualSize(file); return size; } catch (Exception e) { - s_logger.info("[ignored]" + "failed to get template virtual size for VHD: " + e.getLocalizedMessage()); + logger.info("[ignored]" + "failed to get template virtual size for VHD: " + e.getLocalizedMessage()); } return file.length(); } @@ -117,7 +115,7 @@ public class VhdProcessor extends AdapterBase implements Processor { try { strm = new CompressorStreamFactory().createCompressorInputStream(fileStream); } catch (CompressorException e) { - s_logger.info("error opening compressed VHD file " + file.getName()); + logger.info("error opening compressed VHD file " + file.getName()); return file.length(); } } try { @@ -146,7 +144,7 @@ public class VhdProcessor extends AdapterBase implements Processor { throw new IOException("Unexpected end-of-file"); } } catch (IOException e) { - s_logger.warn("Error reading virtual size from VHD file " + e.getMessage() + " VHD: " + file.getName()); + logger.warn("Error reading virtual size from VHD file " + e.getMessage() + " VHD: " + file.getName()); return file.length(); } finally { if (strm != null) { @@ -180,11 +178,11 @@ public class VhdProcessor extends AdapterBase implements Processor { cin = new CompressorStreamFactory().createCompressorInputStream(bin); } catch (CompressorException e) { - s_logger.warn(e.getMessage()); + logger.warn(e.getMessage()); return false; } catch (FileNotFoundException e) { - s_logger.warn(e.getMessage()); + logger.warn(e.getMessage()); return false; } finally { if (cin != null) diff --git a/core/src/main/java/com/cloud/storage/template/VmdkProcessor.java b/core/src/main/java/com/cloud/storage/template/VmdkProcessor.java index 927515f7544..4f53c556667 100644 --- a/core/src/main/java/com/cloud/storage/template/VmdkProcessor.java +++ b/core/src/main/java/com/cloud/storage/template/VmdkProcessor.java @@ -30,7 +30,6 @@ import java.util.regex.Pattern; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; import com.cloud.exception.InternalErrorException; import com.cloud.storage.Storage.ImageFormat; @@ -40,7 +39,6 @@ import com.cloud.utils.component.AdapterBase; import static com.cloud.utils.NumbersUtil.toHumanReadableSize; public class VmdkProcessor extends AdapterBase implements Processor { - private static final Logger s_logger = Logger.getLogger(VmdkProcessor.class); StorageLayer _storage; @@ -52,17 +50,17 @@ public class VmdkProcessor extends AdapterBase implements Processor { @Override public FormatInfo process(String templatePath, ImageFormat format, String templateName, long processTimeout) throws InternalErrorException { if (format != null) { - if (s_logger.isInfoEnabled()) { - s_logger.info("We currently don't handle conversion from " + format + " to VMDK."); + if (logger.isInfoEnabled()) { + logger.info("We currently don't handle conversion from " + format + " to VMDK."); } return null; } - s_logger.info("Template processing. templatePath: " + templatePath + ", templateName: " + templateName); + logger.info("Template processing. templatePath: " + templatePath + ", templateName: " + templateName); String templateFilePath = templatePath + File.separator + templateName + "." + ImageFormat.VMDK.getFileExtension(); if (!_storage.exists(templateFilePath)) { - if (s_logger.isInfoEnabled()) { - s_logger.info("Unable to find the vmware template file: " + templateFilePath); + if (logger.isInfoEnabled()) { + logger.info("Unable to find the vmware template file: " + templateFilePath); } return null; } @@ -82,7 +80,7 @@ public class VmdkProcessor extends AdapterBase implements Processor { long size = getTemplateVirtualSize(file.getParent(), file.getName()); return size; } catch (Exception e) { - s_logger.info("[ignored]" + logger.info("[ignored]" + "failed to get template virtual size for vmdk: " + e.getLocalizedMessage()); } return file.length(); @@ -108,15 +106,15 @@ public class VmdkProcessor extends AdapterBase implements Processor { } } catch(FileNotFoundException ex) { String msg = "Unable to open file '" + templateFileFullPath + "' " + ex.toString(); - s_logger.error(msg); + logger.error(msg); throw new InternalErrorException(msg); } catch(IOException ex) { String msg = "Unable read open file '" + templateFileFullPath + "' " + ex.toString(); - s_logger.error(msg); + logger.error(msg); throw new InternalErrorException(msg); } - s_logger.debug("vmdk file had size=" + toHumanReadableSize(virtualSize)); + logger.debug("vmdk file had size=" + toHumanReadableSize(virtualSize)); return virtualSize; } diff --git a/core/src/main/java/org/apache/cloudstack/agent/directdownload/CheckUrlCommand.java b/core/src/main/java/org/apache/cloudstack/agent/directdownload/CheckUrlCommand.java index e8618d54209..325f61427a9 100644 --- a/core/src/main/java/org/apache/cloudstack/agent/directdownload/CheckUrlCommand.java +++ b/core/src/main/java/org/apache/cloudstack/agent/directdownload/CheckUrlCommand.java @@ -25,6 +25,10 @@ public class CheckUrlCommand extends Command { private String format; private String url; + private Integer connectTimeout; + private Integer connectionRequestTimeout; + private Integer socketTimeout; + private boolean followRedirects; public String getFormat() { return format; @@ -34,10 +38,31 @@ public class CheckUrlCommand extends Command { return url; } - public CheckUrlCommand(final String format,final String url) { + public Integer getConnectTimeout() { return connectTimeout; } + + public Integer getConnectionRequestTimeout() { return connectionRequestTimeout; } + + public Integer getSocketTimeout() { return socketTimeout; } + + public boolean isFollowRedirects() { + return followRedirects; + } + + public CheckUrlCommand(final String format, final String url, final boolean followRedirects) { super(); this.format = format; this.url = url; + this.followRedirects = followRedirects; + } + + public CheckUrlCommand(final String format,final String url, Integer connectTimeout, Integer connectionRequestTimeout, Integer socketTimeout, final boolean followRedirects) { + super(); + this.format = format; + this.url = url; + this.connectTimeout = connectTimeout; + this.socketTimeout = socketTimeout; + this.connectionRequestTimeout = connectionRequestTimeout; + this.followRedirects = followRedirects; } @Override diff --git a/core/src/main/java/org/apache/cloudstack/agent/directdownload/DirectDownloadCommand.java b/core/src/main/java/org/apache/cloudstack/agent/directdownload/DirectDownloadCommand.java index 7e1ff0b34c4..b6748dca434 100644 --- a/core/src/main/java/org/apache/cloudstack/agent/directdownload/DirectDownloadCommand.java +++ b/core/src/main/java/org/apache/cloudstack/agent/directdownload/DirectDownloadCommand.java @@ -45,7 +45,11 @@ public abstract class DirectDownloadCommand extends StorageSubSystemCommand { private Long templateSize; private Storage.ImageFormat format; - protected DirectDownloadCommand (final String url, final Long templateId, final PrimaryDataStoreTO destPool, final String checksum, final Map headers, final Integer connectTimeout, final Integer soTimeout, final Integer connectionRequestTimeout) { + private boolean followRedirects; + + protected DirectDownloadCommand (final String url, final Long templateId, final PrimaryDataStoreTO destPool, + final String checksum, final Map headers, final Integer connectTimeout, + final Integer soTimeout, final Integer connectionRequestTimeout, final boolean followRedirects) { this.url = url; this.templateId = templateId; this.destData = destData; @@ -55,6 +59,7 @@ public abstract class DirectDownloadCommand extends StorageSubSystemCommand { this.connectTimeout = connectTimeout; this.soTimeout = soTimeout; this.connectionRequestTimeout = connectionRequestTimeout; + this.followRedirects = followRedirects; } public String getUrl() { @@ -137,4 +142,12 @@ public abstract class DirectDownloadCommand extends StorageSubSystemCommand { public int getWaitInMillSeconds() { return getWait() * 1000; } + + public boolean isFollowRedirects() { + return followRedirects; + } + + public void setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + } } diff --git a/core/src/main/java/org/apache/cloudstack/agent/directdownload/HttpDirectDownloadCommand.java b/core/src/main/java/org/apache/cloudstack/agent/directdownload/HttpDirectDownloadCommand.java index f131b3b0a7f..bdc00b3bc47 100644 --- a/core/src/main/java/org/apache/cloudstack/agent/directdownload/HttpDirectDownloadCommand.java +++ b/core/src/main/java/org/apache/cloudstack/agent/directdownload/HttpDirectDownloadCommand.java @@ -24,8 +24,10 @@ import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; public class HttpDirectDownloadCommand extends DirectDownloadCommand { - public HttpDirectDownloadCommand(String url, Long templateId, PrimaryDataStoreTO destPool, String checksum, Map headers, int connectTimeout, int soTimeout) { - super(url, templateId, destPool, checksum, headers, connectTimeout, soTimeout, null); + public HttpDirectDownloadCommand(String url, Long templateId, PrimaryDataStoreTO destPool, String checksum, + Map headers, int connectTimeout, int soTimeout, boolean followRedirects) { + super(url, templateId, destPool, checksum, headers, connectTimeout, soTimeout, + null, followRedirects); } } diff --git a/core/src/main/java/org/apache/cloudstack/agent/directdownload/HttpsDirectDownloadCommand.java b/core/src/main/java/org/apache/cloudstack/agent/directdownload/HttpsDirectDownloadCommand.java index dd88ad2a155..a7e16eac91a 100644 --- a/core/src/main/java/org/apache/cloudstack/agent/directdownload/HttpsDirectDownloadCommand.java +++ b/core/src/main/java/org/apache/cloudstack/agent/directdownload/HttpsDirectDownloadCommand.java @@ -25,7 +25,10 @@ import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; public class HttpsDirectDownloadCommand extends DirectDownloadCommand { - public HttpsDirectDownloadCommand(String url, Long templateId, PrimaryDataStoreTO destPool, String checksum, Map headers, int connectTimeout, int soTimeout, int connectionRequestTimeout) { - super(url, templateId, destPool, checksum, headers, connectTimeout, soTimeout, connectionRequestTimeout); + public HttpsDirectDownloadCommand(String url, Long templateId, PrimaryDataStoreTO destPool, String checksum, + Map headers, int connectTimeout, int soTimeout, int connectionRequestTimeout, + boolean followRedirects) { + super(url, templateId, destPool, checksum, headers, connectTimeout, soTimeout, + connectionRequestTimeout, followRedirects); } } diff --git a/core/src/main/java/org/apache/cloudstack/agent/directdownload/MetalinkDirectDownloadCommand.java b/core/src/main/java/org/apache/cloudstack/agent/directdownload/MetalinkDirectDownloadCommand.java index a3edcebe7de..7742994c76b 100644 --- a/core/src/main/java/org/apache/cloudstack/agent/directdownload/MetalinkDirectDownloadCommand.java +++ b/core/src/main/java/org/apache/cloudstack/agent/directdownload/MetalinkDirectDownloadCommand.java @@ -24,8 +24,9 @@ import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; public class MetalinkDirectDownloadCommand extends DirectDownloadCommand { - public MetalinkDirectDownloadCommand(String url, Long templateId, PrimaryDataStoreTO destPool, String checksum, Map headers, int connectTimeout, int soTimeout) { - super(url, templateId, destPool, checksum, headers, connectTimeout, soTimeout, null); + public MetalinkDirectDownloadCommand(String url, Long templateId, PrimaryDataStoreTO destPool, String checksum, + Map headers, int connectTimeout, int soTimeout, boolean followRedirects) { + super(url, templateId, destPool, checksum, headers, connectTimeout, soTimeout, null, followRedirects); } } diff --git a/core/src/main/java/org/apache/cloudstack/agent/directdownload/NfsDirectDownloadCommand.java b/core/src/main/java/org/apache/cloudstack/agent/directdownload/NfsDirectDownloadCommand.java index 0bf9c4d934b..0e51d786230 100644 --- a/core/src/main/java/org/apache/cloudstack/agent/directdownload/NfsDirectDownloadCommand.java +++ b/core/src/main/java/org/apache/cloudstack/agent/directdownload/NfsDirectDownloadCommand.java @@ -24,8 +24,9 @@ import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; public class NfsDirectDownloadCommand extends DirectDownloadCommand { - public NfsDirectDownloadCommand(final String url, final Long templateId, final PrimaryDataStoreTO destPool, final String checksum, final Map headers) { - super(url, templateId, destPool, checksum, headers, null, null, null); + public NfsDirectDownloadCommand(final String url, final Long templateId, final PrimaryDataStoreTO destPool, + final String checksum, final Map headers) { + super(url, templateId, destPool, checksum, headers, null, null, null, false); } } diff --git a/core/src/main/java/org/apache/cloudstack/agent/routing/ManageServiceCommand.java b/core/src/main/java/org/apache/cloudstack/agent/routing/ManageServiceCommand.java new file mode 100644 index 00000000000..c83a5b69574 --- /dev/null +++ b/core/src/main/java/org/apache/cloudstack/agent/routing/ManageServiceCommand.java @@ -0,0 +1,49 @@ +// +// 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.agent.routing; + +import com.cloud.agent.api.routing.NetworkElementCommand; + +public class ManageServiceCommand extends NetworkElementCommand { + + String serviceName; + String action; + + @Override + public boolean executeInSequence() { + return true; + } + + protected ManageServiceCommand() { + } + + public ManageServiceCommand(String serviceName, String action) { + this.serviceName = serviceName; + this.action = action; + } + + public String getServiceName() { + return serviceName; + } + + public String getAction() { + return action; + } +} diff --git a/core/src/main/java/org/apache/cloudstack/backup/PrepareForBackupRestorationCommand.java b/core/src/main/java/org/apache/cloudstack/backup/PrepareForBackupRestorationCommand.java new file mode 100644 index 00000000000..25306fb5f73 --- /dev/null +++ b/core/src/main/java/org/apache/cloudstack/backup/PrepareForBackupRestorationCommand.java @@ -0,0 +1,43 @@ +// +// 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.backup; + +import com.cloud.agent.api.Command; + +public class PrepareForBackupRestorationCommand extends Command { + + private String vmName; + + protected PrepareForBackupRestorationCommand() { + } + + public PrepareForBackupRestorationCommand(String vmName) { + this.vmName = vmName; + } + + public String getVmName() { + return vmName; + } + + @Override + public boolean executeInSequence() { + return true; + } +} diff --git a/core/src/main/java/org/apache/cloudstack/diagnostics/DiagnosticsAnswer.java b/core/src/main/java/org/apache/cloudstack/diagnostics/DiagnosticsAnswer.java index 7390e4fcdd2..6421f45ed0a 100644 --- a/core/src/main/java/org/apache/cloudstack/diagnostics/DiagnosticsAnswer.java +++ b/core/src/main/java/org/apache/cloudstack/diagnostics/DiagnosticsAnswer.java @@ -21,13 +21,11 @@ import com.cloud.agent.api.Answer; import com.cloud.utils.exception.CloudRuntimeException; import org.apache.commons.lang3.StringUtils; import org.apache.cloudstack.api.ApiConstants; -import org.apache.log4j.Logger; import java.util.HashMap; import java.util.Map; public class DiagnosticsAnswer extends Answer { - public static final Logger LOGGER = Logger.getLogger(DiagnosticsAnswer.class); public DiagnosticsAnswer(DiagnosticsCommand cmd, boolean result, String details) { super(cmd, result, details); diff --git a/core/src/main/java/org/apache/cloudstack/direct/download/DirectDownloadHelper.java b/core/src/main/java/org/apache/cloudstack/direct/download/DirectDownloadHelper.java index 80509b19b1b..0e0e2f0b57b 100644 --- a/core/src/main/java/org/apache/cloudstack/direct/download/DirectDownloadHelper.java +++ b/core/src/main/java/org/apache/cloudstack/direct/download/DirectDownloadHelper.java @@ -24,37 +24,41 @@ import org.apache.cloudstack.agent.directdownload.HttpDirectDownloadCommand; import org.apache.cloudstack.agent.directdownload.HttpsDirectDownloadCommand; import org.apache.cloudstack.agent.directdownload.MetalinkDirectDownloadCommand; import org.apache.cloudstack.agent.directdownload.NfsDirectDownloadCommand; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; public class DirectDownloadHelper { - public static final Logger LOGGER = Logger.getLogger(DirectDownloadHelper.class.getName()); + protected static Logger LOGGER = LogManager.getLogger(DirectDownloadHelper.class); /** * Get direct template downloader from direct download command and destination pool */ public static DirectTemplateDownloader getDirectTemplateDownloaderFromCommand(DirectDownloadCommand cmd, - String destPoolLocalPath, - String temporaryDownloadPath) { + String destPoolLocalPath, String temporaryDownloadPath) { if (cmd instanceof HttpDirectDownloadCommand) { - return new HttpDirectTemplateDownloader(cmd.getUrl(), cmd.getTemplateId(), destPoolLocalPath, cmd.getChecksum(), cmd.getHeaders(), - cmd.getConnectTimeout(), cmd.getSoTimeout(), temporaryDownloadPath); + return new HttpDirectTemplateDownloader(cmd.getUrl(), cmd.getTemplateId(), destPoolLocalPath, + cmd.getChecksum(), cmd.getHeaders(), cmd.getConnectTimeout(), cmd.getSoTimeout(), + temporaryDownloadPath, cmd.isFollowRedirects()); } else if (cmd instanceof HttpsDirectDownloadCommand) { - return new HttpsDirectTemplateDownloader(cmd.getUrl(), cmd.getTemplateId(), destPoolLocalPath, cmd.getChecksum(), cmd.getHeaders(), - cmd.getConnectTimeout(), cmd.getSoTimeout(), cmd.getConnectionRequestTimeout(), temporaryDownloadPath); + return new HttpsDirectTemplateDownloader(cmd.getUrl(), cmd.getTemplateId(), destPoolLocalPath, + cmd.getChecksum(), cmd.getHeaders(), cmd.getConnectTimeout(), cmd.getSoTimeout(), + cmd.getConnectionRequestTimeout(), temporaryDownloadPath, cmd.isFollowRedirects()); } else if (cmd instanceof NfsDirectDownloadCommand) { - return new NfsDirectTemplateDownloader(cmd.getUrl(), destPoolLocalPath, cmd.getTemplateId(), cmd.getChecksum(), temporaryDownloadPath); + return new NfsDirectTemplateDownloader(cmd.getUrl(), destPoolLocalPath, cmd.getTemplateId(), + cmd.getChecksum(), temporaryDownloadPath); } else if (cmd instanceof MetalinkDirectDownloadCommand) { - return new MetalinkDirectTemplateDownloader(cmd.getUrl(), destPoolLocalPath, cmd.getTemplateId(), cmd.getChecksum(), cmd.getHeaders(), - cmd.getConnectTimeout(), cmd.getSoTimeout(), temporaryDownloadPath); + return new MetalinkDirectTemplateDownloader(cmd.getUrl(), destPoolLocalPath, cmd.getTemplateId(), + cmd.getChecksum(), cmd.getHeaders(), cmd.getConnectTimeout(), cmd.getSoTimeout(), + temporaryDownloadPath, cmd.isFollowRedirects()); } else { throw new IllegalArgumentException("Unsupported protocol, please provide HTTP(S), NFS or a metalink"); } } - public static boolean checkUrlExistence(String url) { + public static boolean checkUrlExistence(String url, boolean followRedirects) { try { - DirectTemplateDownloader checker = getCheckerDownloader(url); + DirectTemplateDownloader checker = getCheckerDownloader(url, null, null, null, followRedirects); return checker.checkUrl(url); } catch (CloudRuntimeException e) { LOGGER.error(String.format("Cannot check URL %s is reachable due to: %s", url, e.getMessage()), e); @@ -62,22 +66,37 @@ public class DirectDownloadHelper { } } - private static DirectTemplateDownloader getCheckerDownloader(String url) { + public static boolean checkUrlExistence(String url, Integer connectTimeout, Integer connectionRequestTimeout, Integer socketTimeout, boolean followRedirects) { + try { + DirectTemplateDownloader checker = getCheckerDownloader(url, connectTimeout, connectionRequestTimeout, socketTimeout, followRedirects); + return checker.checkUrl(url); + } catch (CloudRuntimeException e) { + LOGGER.error(String.format("Cannot check URL %s is reachable due to: %s", url, e.getMessage()), e); + return false; + } + } + + private static DirectTemplateDownloader getCheckerDownloader(String url, Integer connectTimeout, Integer connectionRequestTimeout, Integer socketTimeout, boolean followRedirects) { if (url.toLowerCase().startsWith("https:")) { - return new HttpsDirectTemplateDownloader(url); + return new HttpsDirectTemplateDownloader(url, connectTimeout, connectionRequestTimeout, socketTimeout, followRedirects); } else if (url.toLowerCase().startsWith("http:")) { - return new HttpDirectTemplateDownloader(url); + return new HttpDirectTemplateDownloader(url, connectTimeout, socketTimeout, followRedirects); } else if (url.toLowerCase().startsWith("nfs:")) { return new NfsDirectTemplateDownloader(url); } else if (url.toLowerCase().endsWith(".metalink")) { - return new MetalinkDirectTemplateDownloader(url); + return new MetalinkDirectTemplateDownloader(url, connectTimeout, socketTimeout, followRedirects); } else { throw new CloudRuntimeException(String.format("Cannot find a download checker for url: %s", url)); } } - public static Long getFileSize(String url, String format) { - DirectTemplateDownloader checker = getCheckerDownloader(url); + public static Long getFileSize(String url, String format, boolean followRedirects) { + DirectTemplateDownloader checker = getCheckerDownloader(url, null, null, null, followRedirects); + return checker.getRemoteFileSize(url, format); + } + + public static Long getFileSize(String url, String format, Integer connectTimeout, Integer connectionRequestTimeout, Integer socketTimeout, boolean followRedirects) { + DirectTemplateDownloader checker = getCheckerDownloader(url, connectTimeout, connectionRequestTimeout, socketTimeout, followRedirects); return checker.getRemoteFileSize(url, format); } } diff --git a/core/src/main/java/org/apache/cloudstack/direct/download/DirectTemplateDownloaderImpl.java b/core/src/main/java/org/apache/cloudstack/direct/download/DirectTemplateDownloaderImpl.java index 9476dbaa5ce..d22c803818b 100644 --- a/core/src/main/java/org/apache/cloudstack/direct/download/DirectTemplateDownloaderImpl.java +++ b/core/src/main/java/org/apache/cloudstack/direct/download/DirectTemplateDownloaderImpl.java @@ -22,7 +22,8 @@ import com.cloud.utils.UriUtils; import com.cloud.utils.exception.CloudRuntimeException; import org.apache.cloudstack.utils.security.DigestHelper; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import java.io.File; import java.io.FileInputStream; @@ -42,16 +43,19 @@ public abstract class DirectTemplateDownloaderImpl implements DirectTemplateDown private String checksum; private boolean redownload = false; protected String temporaryDownloadPath; + private boolean followRedirects; - public static final Logger s_logger = Logger.getLogger(DirectTemplateDownloaderImpl.class.getName()); + protected Logger logger = LogManager.getLogger(getClass()); protected DirectTemplateDownloaderImpl(final String url, final String destPoolPath, final Long templateId, - final String checksum, final String temporaryDownloadPath) { + final String checksum, final String temporaryDownloadPath, + final boolean followRedirects) { this.url = url; this.destPoolPath = destPoolPath; this.templateId = templateId; this.checksum = checksum; this.temporaryDownloadPath = temporaryDownloadPath; + this.followRedirects = followRedirects; } private static String directDownloadDir = "template"; @@ -111,6 +115,14 @@ public abstract class DirectTemplateDownloaderImpl implements DirectTemplateDown return redownload; } + public boolean isFollowRedirects() { + return followRedirects; + } + + public void setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + } + /** * Create download directory (if it does not exist) */ @@ -135,16 +147,16 @@ public abstract class DirectTemplateDownloaderImpl implements DirectTemplateDown try { while (!valid && retry > 0) { retry--; - s_logger.info("Performing checksum validation for downloaded template " + templateId + " using " + checksum + ", retries left: " + retry); + logger.info("Performing checksum validation for downloaded template " + templateId + " using " + checksum + ", retries left: " + retry); valid = DigestHelper.check(checksum, new FileInputStream(downloadedFilePath)); if (!valid && retry > 0) { - s_logger.info("Checksum validation failed, re-downloading template"); + logger.info("Checksum validation failed, re-downloading template"); redownload = true; resetDownloadFile(); downloadTemplate(); } } - s_logger.info("Checksum validation for template " + templateId + ": " + (valid ? "succeeded" : "failed")); + logger.info("Checksum validation for template " + templateId + ": " + (valid ? "succeeded" : "failed")); return valid; } catch (IOException e) { throw new CloudRuntimeException("could not check sum for file: " + downloadedFilePath, e); @@ -152,7 +164,7 @@ public abstract class DirectTemplateDownloaderImpl implements DirectTemplateDown throw new CloudRuntimeException("Unknown checksum algorithm: " + checksum, e); } } - s_logger.info("No checksum provided, skipping checksum validation"); + logger.info("No checksum provided, skipping checksum validation"); return true; } @@ -161,14 +173,14 @@ public abstract class DirectTemplateDownloaderImpl implements DirectTemplateDown */ private void resetDownloadFile() { File f = new File(getDownloadedFilePath()); - s_logger.info("Resetting download file: " + getDownloadedFilePath() + ", in order to re-download and persist template " + templateId + " on it"); + logger.info("Resetting download file: " + getDownloadedFilePath() + ", in order to re-download and persist template " + templateId + " on it"); try { if (f.exists()) { f.delete(); } f.createNewFile(); } catch (IOException e) { - s_logger.error("Error creating file to download on: " + getDownloadedFilePath() + " due to: " + e.getMessage()); + logger.error("Error creating file to download on: " + getDownloadedFilePath() + " due to: " + e.getMessage()); throw new CloudRuntimeException("Failed to create download file for direct download"); } } diff --git a/core/src/main/java/org/apache/cloudstack/direct/download/HttpDirectTemplateDownloader.java b/core/src/main/java/org/apache/cloudstack/direct/download/HttpDirectTemplateDownloader.java index 093f0604a44..8c4147fad60 100644 --- a/core/src/main/java/org/apache/cloudstack/direct/download/HttpDirectTemplateDownloader.java +++ b/core/src/main/java/org/apache/cloudstack/direct/download/HttpDirectTemplateDownloader.java @@ -40,23 +40,22 @@ import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.HeadMethod; import org.apache.commons.io.IOUtils; -import org.apache.log4j.Logger; public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl { protected HttpClient client; private static final MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager(); - public static final Logger s_logger = Logger.getLogger(HttpDirectTemplateDownloader.class.getName()); protected GetMethod request; protected Map reqHeaders = new HashMap<>(); - protected HttpDirectTemplateDownloader(String url) { - this(url, null, null, null, null, null, null, null); + protected HttpDirectTemplateDownloader(String url, Integer connectTimeout, Integer socketTimeout, boolean followRedirects) { + this(url, null, null, null, null, connectTimeout, socketTimeout, null, followRedirects); } public HttpDirectTemplateDownloader(String url, Long templateId, String destPoolPath, String checksum, - Map headers, Integer connectTimeout, Integer soTimeout, String downloadPath) { - super(url, destPoolPath, templateId, checksum, downloadPath); + Map headers, Integer connectTimeout, Integer soTimeout, String downloadPath, + boolean followRedirects) { + super(url, destPoolPath, templateId, checksum, downloadPath, followRedirects); s_httpClientManager.getParams().setConnectionTimeout(connectTimeout == null ? 5000 : connectTimeout); s_httpClientManager.getParams().setSoTimeout(soTimeout == null ? 5000 : soTimeout); client = new HttpClient(s_httpClientManager); @@ -68,7 +67,7 @@ public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl { protected GetMethod createRequest(String downloadUrl, Map headers) { GetMethod request = new GetMethod(downloadUrl); - request.setFollowRedirects(true); + request.setFollowRedirects(this.isFollowRedirects()); if (MapUtils.isNotEmpty(headers)) { for (String key : headers.keySet()) { request.setRequestHeader(key, headers.get(key)); @@ -83,7 +82,7 @@ public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl { try { int status = client.executeMethod(request); if (status != HttpStatus.SC_OK) { - s_logger.warn("Not able to download template, status code: " + status); + logger.warn("Not able to download template, status code: " + status); return new Pair<>(false, null); } return performDownload(); @@ -95,14 +94,14 @@ public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl { } protected Pair performDownload() { - s_logger.info("Downloading template " + getTemplateId() + " from " + getUrl() + " to: " + getDownloadedFilePath()); + logger.info("Downloading template " + getTemplateId() + " from " + getUrl() + " to: " + getDownloadedFilePath()); try ( InputStream in = request.getResponseBodyAsStream(); OutputStream out = new FileOutputStream(getDownloadedFilePath()) ) { IOUtils.copy(in, out); } catch (IOException e) { - s_logger.error("Error downloading template " + getTemplateId() + " due to: " + e.getMessage()); + logger.error("Error downloading template " + getTemplateId() + " due to: " + e.getMessage()); return new Pair<>(false, null); } return new Pair<>(true, getDownloadedFilePath()); @@ -111,14 +110,16 @@ public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl { @Override public boolean checkUrl(String url) { HeadMethod httpHead = new HeadMethod(url); + httpHead.setFollowRedirects(this.isFollowRedirects()); try { - if (client.executeMethod(httpHead) != HttpStatus.SC_OK) { - s_logger.error(String.format("Invalid URL: %s", url)); + int responseCode = client.executeMethod(httpHead); + if (responseCode != HttpStatus.SC_OK) { + logger.error(String.format("HTTP HEAD request to URL: %s failed, response code: %d", url, responseCode)); return false; } return true; } catch (IOException e) { - s_logger.error(String.format("Cannot reach URL: %s due to: %s", url, e.getMessage()), e); + logger.error(String.format("Cannot reach URL: %s due to: %s", url, e.getMessage()), e); return false; } finally { httpHead.releaseConnection(); @@ -128,9 +129,9 @@ public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl { @Override public Long getRemoteFileSize(String url, String format) { if ("qcow2".equalsIgnoreCase(format)) { - return QCOW2Utils.getVirtualSize(url); + return QCOW2Utils.getVirtualSizeFromUrl(url, this.isFollowRedirects()); } else { - return UriUtils.getRemoteSize(url); + return UriUtils.getRemoteSize(url, this.isFollowRedirects()); } } @@ -142,7 +143,7 @@ public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl { try { status = client.executeMethod(getMethod); } catch (IOException e) { - s_logger.error("Error retrieving urls form metalink: " + metalinkUrl); + logger.error("Error retrieving urls form metalink: " + metalinkUrl); getMethod.releaseConnection(); return null; } @@ -152,7 +153,7 @@ public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl { addMetalinkUrlsToListFromInputStream(is, urls); } } catch (IOException e) { - s_logger.warn(e.getMessage()); + logger.warn(e.getMessage()); } finally { getMethod.releaseConnection(); } @@ -168,7 +169,7 @@ public class HttpDirectTemplateDownloader extends DirectTemplateDownloaderImpl { return generateChecksumListFromInputStream(is); } } catch (IOException e) { - s_logger.error(String.format("Error obtaining metalink checksums on URL %s: %s", metalinkUrl, e.getMessage()), e); + logger.error(String.format("Error obtaining metalink checksums on URL %s: %s", metalinkUrl, e.getMessage()), e); } finally { getMethod.releaseConnection(); } diff --git a/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java b/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java index 2035aab2aca..b8a25a11b5c 100644 --- a/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java +++ b/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java @@ -19,29 +19,6 @@ package org.apache.cloudstack.direct.download; -import com.cloud.utils.Pair; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.script.Script; -import com.cloud.utils.storage.QCOW2Utils; -import org.apache.cloudstack.utils.security.SSLUtils; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.io.IOUtils; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.commons.collections.MapUtils; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; - -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; @@ -60,25 +37,57 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; + +import org.apache.cloudstack.utils.security.SSLUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.io.IOUtils; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import com.cloud.utils.Pair; +import com.cloud.utils.UriUtils; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import com.cloud.utils.storage.QCOW2Utils; + public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl { protected CloseableHttpClient httpsClient; private HttpUriRequest req; - protected HttpsDirectTemplateDownloader(String url) { - this(url, null, null, null, null, null, null, null, null); + protected HttpsDirectTemplateDownloader(String url, Integer connectTimeout, Integer connectionRequestTimeout, Integer socketTimeout, boolean followRedirects) { + this(url, null, null, null, null, connectTimeout, socketTimeout, connectionRequestTimeout, null, followRedirects); } - public HttpsDirectTemplateDownloader(String url, Long templateId, String destPoolPath, String checksum, Map headers, - Integer connectTimeout, Integer soTimeout, Integer connectionRequestTimeout, String temporaryDownloadPath) { - super(url, destPoolPath, templateId, checksum, temporaryDownloadPath); + public HttpsDirectTemplateDownloader(String url, Long templateId, String destPoolPath, String checksum, + Map headers, Integer connectTimeout, Integer soTimeout, + Integer connectionRequestTimeout, String temporaryDownloadPath, boolean followRedirects) { + super(url, destPoolPath, templateId, checksum, temporaryDownloadPath, followRedirects); SSLContext sslcontext = getSSLContext(); SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); RequestConfig config = RequestConfig.custom() .setConnectTimeout(connectTimeout == null ? 5000 : connectTimeout) .setConnectionRequestTimeout(connectionRequestTimeout == null ? 5000 : connectionRequestTimeout) - .setSocketTimeout(soTimeout == null ? 5000 : soTimeout).build(); - httpsClient = HttpClients.custom().setSSLSocketFactory(factory).setDefaultRequestConfig(config).build(); + .setSocketTimeout(soTimeout == null ? 5000 : soTimeout) + .setRedirectsEnabled(followRedirects) + .build(); + httpsClient = HttpClients.custom() + .setSSLSocketFactory(factory) + .setDefaultRequestConfig(config) + .build(); createUriRequest(url, headers); String downloadDir = getDirectDownloadTempPath(templateId); File tempFile = createTemporaryDirectoryAndFile(downloadDir); @@ -87,6 +96,7 @@ public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl protected void createUriRequest(String downloadUrl, Map headers) { req = new HttpGet(downloadUrl); + setFollowRedirects(this.isFollowRedirects()); if (MapUtils.isNotEmpty(headers)) { for (String headerKey: headers.keySet()) { req.setHeader(headerKey, headers.get(headerKey)); @@ -115,7 +125,7 @@ public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl sslContext.init(null, tm, null); return sslContext; } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | KeyManagementException e) { - s_logger.error(String.format("Failure getting SSL context for HTTPS downloader, using default SSL context: %s", e.getMessage()), e); + logger.error(String.format("Failure getting SSL context for HTTPS downloader, using default SSL context: %s", e.getMessage()), e); try { return SSLContext.getDefault(); } catch (NoSuchAlgorithmException ex) { @@ -140,7 +150,7 @@ public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl * Consume response and persist it on getDownloadedFilePath() file */ protected Pair consumeResponse(CloseableHttpResponse response) { - s_logger.info("Downloading template " + getTemplateId() + " from " + getUrl() + " to: " + getDownloadedFilePath()); + logger.info("Downloading template " + getTemplateId() + " from " + getUrl() + " to: " + getDownloadedFilePath()); if (response.getStatusLine().getStatusCode() != 200) { throw new CloudRuntimeException("Error on HTTPS response"); } @@ -150,7 +160,7 @@ public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl OutputStream out = new FileOutputStream(getDownloadedFilePath()); IOUtils.copy(in, out); } catch (Exception e) { - s_logger.error("Error parsing response for template " + getTemplateId() + " due to: " + e.getMessage()); + logger.error("Error parsing response for template " + getTemplateId() + " due to: " + e.getMessage()); return new Pair<>(false, null); } return new Pair<>(true, getDownloadedFilePath()); @@ -161,13 +171,14 @@ public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl HttpHead httpHead = new HttpHead(url); try { CloseableHttpResponse response = httpsClient.execute(httpHead); - if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { - s_logger.error(String.format("Invalid URL: %s", url)); + int responseCode = response.getStatusLine().getStatusCode(); + if (responseCode != HttpStatus.SC_OK) { + logger.error(String.format("HTTP HEAD request to URL: %s failed, response code: %d", url, responseCode)); return false; } return true; } catch (IOException e) { - s_logger.error(String.format("Cannot reach URL: %s due to: %s", url, e.getMessage()), e); + logger.error(String.format("Cannot reach URL: %s due to: %s", url, e.getMessage()), e); return false; } finally { httpHead.releaseConnection(); @@ -183,8 +194,7 @@ public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl SSLContext context = getSSLContext(); urlConnection.setSSLSocketFactory(context.getSocketFactory()); urlConnection.connect(); - boolean isCompressed = !url.endsWith("qcow2"); - return QCOW2Utils.getVirtualSize(urlObj.openStream(), isCompressed); + return QCOW2Utils.getVirtualSize(urlObj.openStream(), UriUtils.isUrlForCompressedFile(url)); } catch (IOException e) { throw new CloudRuntimeException(String.format("Cannot obtain qcow2 virtual size due to: %s", e.getMessage()), e); } @@ -213,11 +223,11 @@ public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl response = httpsClient.execute(getMethod); if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { String msg = String.format("Cannot access metalink content on URL %s", metalinkUrl); - s_logger.error(msg); + logger.error(msg); throw new IOException(msg); } } catch (IOException e) { - s_logger.error(String.format("Error retrieving urls form metalink URL %s: %s", metalinkUrl, e.getMessage()), e); + logger.error(String.format("Error retrieving urls form metalink URL %s: %s", metalinkUrl, e.getMessage()), e); getMethod.releaseConnection(); return null; } @@ -227,7 +237,7 @@ public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl ByteArrayInputStream inputStream = new ByteArrayInputStream(responseStr.getBytes(StandardCharsets.UTF_8)); addMetalinkUrlsToListFromInputStream(inputStream, urls); } catch (IOException e) { - s_logger.warn(e.getMessage(), e); + logger.warn(e.getMessage(), e); } finally { getMethod.releaseConnection(); } @@ -244,7 +254,7 @@ public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl return generateChecksumListFromInputStream(is); } } catch (IOException e) { - s_logger.error(String.format("Error obtaining metalink checksums on URL %s: %s", metalinkUrl, e.getMessage()), e); + logger.error(String.format("Error obtaining metalink checksums on URL %s: %s", metalinkUrl, e.getMessage()), e); } finally { getMethod.releaseConnection(); } diff --git a/core/src/main/java/org/apache/cloudstack/direct/download/MetalinkDirectTemplateDownloader.java b/core/src/main/java/org/apache/cloudstack/direct/download/MetalinkDirectTemplateDownloader.java index 83802064cdf..5335da99150 100644 --- a/core/src/main/java/org/apache/cloudstack/direct/download/MetalinkDirectTemplateDownloader.java +++ b/core/src/main/java/org/apache/cloudstack/direct/download/MetalinkDirectTemplateDownloader.java @@ -23,7 +23,6 @@ import com.cloud.utils.exception.CloudRuntimeException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.log4j.Logger; import java.io.File; import java.util.List; @@ -39,34 +38,32 @@ public class MetalinkDirectTemplateDownloader extends DirectTemplateDownloaderIm private Integer connectTimeout; private Integer soTimeout; - private static final Logger s_logger = Logger.getLogger(MetalinkDirectTemplateDownloader.class.getName()); - protected DirectTemplateDownloader createDownloaderForMetalinks(String url, Long templateId, - String destPoolPath, String checksum, - Map headers, - Integer connectTimeout, Integer soTimeout, - Integer connectionRequestTimeout, String temporaryDownloadPath) { + String destPoolPath, String checksum, Map headers, Integer connectTimeout, + Integer soTimeout, Integer connectionRequestTimeout, String temporaryDownloadPath) { if (url.toLowerCase().startsWith("https:")) { return new HttpsDirectTemplateDownloader(url, templateId, destPoolPath, checksum, headers, - connectTimeout, soTimeout, connectionRequestTimeout, temporaryDownloadPath); + connectTimeout, soTimeout, connectionRequestTimeout, temporaryDownloadPath, + this.isFollowRedirects()); } else if (url.toLowerCase().startsWith("http:")) { return new HttpDirectTemplateDownloader(url, templateId, destPoolPath, checksum, headers, - connectTimeout, soTimeout, temporaryDownloadPath); + connectTimeout, soTimeout, temporaryDownloadPath, this.isFollowRedirects()); } else if (url.toLowerCase().startsWith("nfs:")) { return new NfsDirectTemplateDownloader(url); } else { - s_logger.error(String.format("Cannot find a suitable downloader to handle the metalink URL %s", url)); + logger.error(String.format("Cannot find a suitable downloader to handle the metalink URL %s", url)); return null; } } - protected MetalinkDirectTemplateDownloader(String url) { - this(url, null, null, null, null, null, null, null); + protected MetalinkDirectTemplateDownloader(String url, Integer connectTimeout, Integer socketTimeout, boolean followRedirects) { + this(url, null, null, null, null, connectTimeout, socketTimeout, null, followRedirects); } public MetalinkDirectTemplateDownloader(String url, String destPoolPath, Long templateId, String checksum, - Map headers, Integer connectTimeout, Integer soTimeout, String downloadPath) { - super(url, destPoolPath, templateId, checksum, downloadPath); + Map headers, Integer connectTimeout, Integer soTimeout, String downloadPath, + boolean followRedirects) { + super(url, destPoolPath, templateId, checksum, downloadPath, followRedirects); this.headers = headers; this.connectTimeout = connectTimeout; this.soTimeout = soTimeout; @@ -75,10 +72,10 @@ public class MetalinkDirectTemplateDownloader extends DirectTemplateDownloaderIm metalinkUrls = downloader.getMetalinkUrls(url); metalinkChecksums = downloader.getMetalinkChecksums(url); if (CollectionUtils.isEmpty(metalinkUrls)) { - s_logger.error(String.format("No urls found on metalink file: %s. Not possible to download template %s ", url, templateId)); + logger.error(String.format("No urls found on metalink file: %s. Not possible to download template %s ", url, templateId)); } else { setUrl(metalinkUrls.get(0)); - s_logger.info("Metalink downloader created, metalink url: " + url + " parsed - " + + logger.info("Metalink downloader created, metalink url: " + url + " parsed - " + metalinkUrls.size() + " urls and " + (CollectionUtils.isNotEmpty(metalinkChecksums) ? metalinkChecksums.size() : "0") + " checksums found"); } @@ -96,7 +93,7 @@ public class MetalinkDirectTemplateDownloader extends DirectTemplateDownloaderIm if (!isRedownload()) { setUrl(metalinkUrls.get(i)); } - s_logger.info("Trying to download template from url: " + getUrl()); + logger.info("Trying to download template from url: " + getUrl()); DirectTemplateDownloader urlDownloader = createDownloaderForMetalinks(getUrl(), getTemplateId(), getDestPoolPath(), getChecksum(), headers, connectTimeout, soTimeout, null, temporaryDownloadPath); try { @@ -109,10 +106,10 @@ public class MetalinkDirectTemplateDownloader extends DirectTemplateDownloaderIm Pair downloadResult = urlDownloader.downloadTemplate(); downloaded = downloadResult.first(); if (downloaded) { - s_logger.info("Successfully downloaded template from url: " + getUrl()); + logger.info("Successfully downloaded template from url: " + getUrl()); } } catch (Exception e) { - s_logger.error(String.format("Error downloading template: %s from URL: %s due to: %s", getTemplateId(), getUrl(), e.getMessage()), e); + logger.error(String.format("Error downloading template: %s from URL: %s due to: %s", getTemplateId(), getUrl(), e.getMessage()), e); } i++; } @@ -125,7 +122,7 @@ public class MetalinkDirectTemplateDownloader extends DirectTemplateDownloaderIm if (StringUtils.isBlank(getChecksum()) && CollectionUtils.isNotEmpty(metalinkChecksums)) { String chk = metalinkChecksums.get(random.nextInt(metalinkChecksums.size())); setChecksum(chk); - s_logger.info("Checksum not provided but " + metalinkChecksums.size() + " found on metalink file, performing checksum using one of them: " + chk); + logger.info("Checksum not provided but " + metalinkChecksums.size() + " found on metalink file, performing checksum using one of them: " + chk); } return super.validateChecksum(); } @@ -133,7 +130,7 @@ public class MetalinkDirectTemplateDownloader extends DirectTemplateDownloaderIm @Override public boolean checkUrl(String metalinkUrl) { if (!downloader.checkUrl(metalinkUrl)) { - s_logger.error(String.format("Metalink URL check failed for: %s", metalinkUrl)); + logger.error(String.format("Metalink URL check failed for: %s", metalinkUrl)); return false; } diff --git a/core/src/main/java/org/apache/cloudstack/direct/download/NfsDirectTemplateDownloader.java b/core/src/main/java/org/apache/cloudstack/direct/download/NfsDirectTemplateDownloader.java index d606136e297..21184ef07fe 100644 --- a/core/src/main/java/org/apache/cloudstack/direct/download/NfsDirectTemplateDownloader.java +++ b/core/src/main/java/org/apache/cloudstack/direct/download/NfsDirectTemplateDownloader.java @@ -57,8 +57,9 @@ public class NfsDirectTemplateDownloader extends DirectTemplateDownloaderImpl { this(url, null, null, null, null); } - public NfsDirectTemplateDownloader(String url, String destPool, Long templateId, String checksum, String downloadPath) { - super(url, destPool, templateId, checksum, downloadPath); + public NfsDirectTemplateDownloader(String url, String destPool, Long templateId, String checksum, + String downloadPath) { + super(url, destPool, templateId, checksum, downloadPath, false); parseUrl(); } @@ -80,7 +81,7 @@ public class NfsDirectTemplateDownloader extends DirectTemplateDownloaderImpl { parseUrl(); return true; } catch (CloudRuntimeException e) { - s_logger.error(String.format("Cannot check URL %s is reachable due to: %s", url, e.getMessage()), e); + logger.error(String.format("Cannot check URL %s is reachable due to: %s", url, e.getMessage()), e); return false; } } diff --git a/core/src/main/java/org/apache/cloudstack/storage/command/DownloadCommand.java b/core/src/main/java/org/apache/cloudstack/storage/command/DownloadCommand.java index 29d737fcce9..f44220f31d0 100644 --- a/core/src/main/java/org/apache/cloudstack/storage/command/DownloadCommand.java +++ b/core/src/main/java/org/apache/cloudstack/storage/command/DownloadCommand.java @@ -20,6 +20,7 @@ package org.apache.cloudstack.storage.command; import org.apache.cloudstack.api.InternalIdentity; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; @@ -33,7 +34,7 @@ import com.cloud.storage.Storage.ImageFormat; public class DownloadCommand extends AbstractDownloadCommand implements InternalIdentity { public static enum ResourceType { - VOLUME, TEMPLATE + VOLUME, TEMPLATE, SNAPSHOT } private boolean hvm; @@ -48,6 +49,8 @@ public class DownloadCommand extends AbstractDownloadCommand implements Internal private DataStoreTO _store; private DataStoreTO cacheStore; + private boolean followRedirects = false; + protected DownloadCommand() { } @@ -64,6 +67,7 @@ public class DownloadCommand extends AbstractDownloadCommand implements Internal installPath = that.installPath; _store = that._store; _proxy = that._proxy; + followRedirects = that.followRedirects; } public DownloadCommand(TemplateObjectTO template, Long maxDownloadSizeInBytes) { @@ -79,6 +83,7 @@ public class DownloadCommand extends AbstractDownloadCommand implements Internal setSecUrl(((NfsTO)_store).getUrl()); } this.maxDownloadSizeInBytes = maxDownloadSizeInBytes; + this.followRedirects = template.isFollowRedirects(); } public DownloadCommand(TemplateObjectTO template, String user, String passwd, Long maxDownloadSizeInBytes) { @@ -94,6 +99,19 @@ public class DownloadCommand extends AbstractDownloadCommand implements Internal _store = volume.getDataStore(); this.maxDownloadSizeInBytes = maxDownloadSizeInBytes; resourceType = ResourceType.VOLUME; + this.followRedirects = volume.isFollowRedirects(); + } + + public DownloadCommand(SnapshotObjectTO snapshot, Long maxDownloadSizeInBytes, String url) { + super(snapshot.getName(), url, null, snapshot.getAccountId()); + _store = snapshot.getDataStore(); + installPath = snapshot.getPath(); + id = snapshot.getId(); + if (_store instanceof NfsTO) { + setSecUrl(((NfsTO)_store).getUrl()); + } + this.maxDownloadSizeInBytes = maxDownloadSizeInBytes; + this.resourceType = ResourceType.SNAPSHOT; } @Override @@ -181,4 +199,12 @@ public class DownloadCommand extends AbstractDownloadCommand implements Internal public DataStoreTO getCacheStore() { return cacheStore; } + + public boolean isFollowRedirects() { + return followRedirects; + } + + public void setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + } } diff --git a/core/src/main/java/org/apache/cloudstack/storage/command/QuerySnapshotZoneCopyAnswer.java b/core/src/main/java/org/apache/cloudstack/storage/command/QuerySnapshotZoneCopyAnswer.java new file mode 100644 index 00000000000..7c96225ce54 --- /dev/null +++ b/core/src/main/java/org/apache/cloudstack/storage/command/QuerySnapshotZoneCopyAnswer.java @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.storage.command; + +import java.util.List; + +import com.cloud.agent.api.Answer; + +public class QuerySnapshotZoneCopyAnswer extends Answer { + private List files; + + public QuerySnapshotZoneCopyAnswer(QuerySnapshotZoneCopyCommand cmd, List files) { + super(cmd); + this.files = files; + } + + public QuerySnapshotZoneCopyAnswer(QuerySnapshotZoneCopyCommand cmd, String errMsg) { + super(null, false, errMsg); + } + + public List getFiles() { + return files; + } +} diff --git a/core/src/main/java/org/apache/cloudstack/storage/command/QuerySnapshotZoneCopyCommand.java b/core/src/main/java/org/apache/cloudstack/storage/command/QuerySnapshotZoneCopyCommand.java new file mode 100644 index 00000000000..5bca52484eb --- /dev/null +++ b/core/src/main/java/org/apache/cloudstack/storage/command/QuerySnapshotZoneCopyCommand.java @@ -0,0 +1,50 @@ +// 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.storage.command; + +import org.apache.cloudstack.storage.to.SnapshotObjectTO; + +/* +Command to get the list of snapshot files for copying a snapshot to a different zone + */ + +public class QuerySnapshotZoneCopyCommand extends StorageSubSystemCommand { + + private SnapshotObjectTO snapshot; + + public QuerySnapshotZoneCopyCommand(final SnapshotObjectTO snapshot) { + super(); + this.snapshot = snapshot; + } + + public SnapshotObjectTO getSnapshot() { + return snapshot; + } + + public void setSnapshot(final SnapshotObjectTO snapshot) { + this.snapshot = snapshot; + } + + @Override + public boolean executeInSequence() { + return false; + } + + @Override + public void setExecuteInSequence(boolean inSeq) {} +} diff --git a/core/src/main/java/org/apache/cloudstack/storage/command/browser/ListDataStoreObjectsAnswer.java b/core/src/main/java/org/apache/cloudstack/storage/command/browser/ListDataStoreObjectsAnswer.java new file mode 100644 index 00000000000..eb8d0991c5c --- /dev/null +++ b/core/src/main/java/org/apache/cloudstack/storage/command/browser/ListDataStoreObjectsAnswer.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.cloudstack.storage.command.browser; + +import com.cloud.agent.api.Answer; + +import java.util.Collections; +import java.util.List; + +public class ListDataStoreObjectsAnswer extends Answer { + + private boolean pathExists; + + private int count; + + private List names; + + private List paths; + + private List absPaths; + + private List isDirs; + + private List sizes; + + private List lastModified; + + public ListDataStoreObjectsAnswer() { + super(); + } + + public ListDataStoreObjectsAnswer(boolean pathExists, int count, List names, List paths, + List absPaths, List isDirs, + List sizes, + List lastModified) { + super(); + this.pathExists = pathExists; + this.count = count; + this.names = names; + this.paths = paths; + this.absPaths = absPaths; + this.isDirs = isDirs; + this.sizes = sizes; + this.lastModified = lastModified; + } + + public boolean isPathExists() { + return pathExists; + } + + public int getCount() { + return count; + } + + public List getNames() { + if (names == null) { + return Collections.emptyList(); + } + return names; + } + + public List getPaths() { + if (paths == null) { + return Collections.emptyList(); + } + return paths; + } + + public List getAbsPaths() { + if (absPaths == null) { + return Collections.emptyList(); + } + return absPaths; + } + + public List getIsDirs() { + if (isDirs == null) { + return Collections.emptyList(); + } + return isDirs; + } + + public List getSizes() { + if (sizes == null) { + return Collections.emptyList(); + } + return sizes; + } + + public List getLastModified() { + if (lastModified == null) { + return Collections.emptyList(); + } + return lastModified; + } +} diff --git a/core/src/main/java/org/apache/cloudstack/storage/command/browser/ListDataStoreObjectsCommand.java b/core/src/main/java/org/apache/cloudstack/storage/command/browser/ListDataStoreObjectsCommand.java new file mode 100644 index 00000000000..c5c0dc508ba --- /dev/null +++ b/core/src/main/java/org/apache/cloudstack/storage/command/browser/ListDataStoreObjectsCommand.java @@ -0,0 +1,66 @@ +/* + * 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.storage.command.browser; + +import com.cloud.agent.api.storage.StorageCommand; +import com.cloud.agent.api.to.DataStoreTO; + +public class ListDataStoreObjectsCommand extends StorageCommand { + + private DataStoreTO store; + + private String path; + + private int startIndex; + + private int pageSize; + + public ListDataStoreObjectsCommand() { + } + + public ListDataStoreObjectsCommand(DataStoreTO store, String path, int startIndex, int pageSize) { + super(); + this.store = store; + this.path = path; + this.startIndex = startIndex; + this.pageSize = pageSize; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public String getPath() { + return path; + } + + public DataStoreTO getStore() { + return store; + } + + public int getStartIndex() { + return startIndex; + } + + public int getPageSize() { + return pageSize; + } +} diff --git a/core/src/main/java/org/apache/cloudstack/storage/to/DownloadableObjectTO.java b/core/src/main/java/org/apache/cloudstack/storage/to/DownloadableObjectTO.java new file mode 100644 index 00000000000..70db8fafffc --- /dev/null +++ b/core/src/main/java/org/apache/cloudstack/storage/to/DownloadableObjectTO.java @@ -0,0 +1,30 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.storage.to; + +public class DownloadableObjectTO { + protected boolean followRedirects = false; + + public boolean isFollowRedirects() { + return followRedirects; + } + + public void setFollowRedirects(boolean followRedirects) { + this.followRedirects = followRedirects; + } +} diff --git a/core/src/main/java/org/apache/cloudstack/storage/to/SnapshotObjectTO.java b/core/src/main/java/org/apache/cloudstack/storage/to/SnapshotObjectTO.java index c62110b179e..76b93909b8c 100644 --- a/core/src/main/java/org/apache/cloudstack/storage/to/SnapshotObjectTO.java +++ b/core/src/main/java/org/apache/cloudstack/storage/to/SnapshotObjectTO.java @@ -30,7 +30,7 @@ import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.DataTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; -public class SnapshotObjectTO implements DataTO { +public class SnapshotObjectTO extends DownloadableObjectTO implements DataTO { private String path; private VolumeObjectTO volume; private String parentSnapshotPath; @@ -42,6 +42,7 @@ public class SnapshotObjectTO implements DataTO { private boolean quiescevm; private String[] parents; private Long physicalSize = (long) 0; + private long accountId; public SnapshotObjectTO() { @@ -51,6 +52,7 @@ public class SnapshotObjectTO implements DataTO { public SnapshotObjectTO(SnapshotInfo snapshot) { this.path = snapshot.getPath(); this.setId(snapshot.getId()); + this.accountId = snapshot.getAccountId(); VolumeInfo vol = snapshot.getBaseVolume(); if (vol != null) { this.volume = (VolumeObjectTO)vol.getTO(); @@ -168,6 +170,14 @@ public class SnapshotObjectTO implements DataTO { return parents; } + public long getAccountId() { + return accountId; + } + + public void setAccountId(long accountId) { + this.accountId = accountId; + } + @Override public String toString() { return new StringBuilder("SnapshotTO[datastore=").append(dataStore).append("|volume=").append(volume).append("|path").append(path).append("]").toString(); diff --git a/core/src/main/java/org/apache/cloudstack/storage/to/TemplateObjectTO.java b/core/src/main/java/org/apache/cloudstack/storage/to/TemplateObjectTO.java index a405785bf64..eafe8f83269 100644 --- a/core/src/main/java/org/apache/cloudstack/storage/to/TemplateObjectTO.java +++ b/core/src/main/java/org/apache/cloudstack/storage/to/TemplateObjectTO.java @@ -28,7 +28,7 @@ import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.Storage.ImageFormat; import com.cloud.template.VirtualMachineTemplate; -public class TemplateObjectTO implements DataTO { +public class TemplateObjectTO extends DownloadableObjectTO implements DataTO { private String path; private String origUrl; private String uuid; @@ -87,6 +87,7 @@ public class TemplateObjectTO implements DataTO { this.deployAsIs = template.isDeployAsIs(); this.deployAsIsConfiguration = template.getDeployAsIsConfiguration(); this.directDownload = template.isDirectDownload(); + this.followRedirects = template.isFollowRedirects(); } @Override diff --git a/core/src/main/java/org/apache/cloudstack/storage/to/VolumeObjectTO.java b/core/src/main/java/org/apache/cloudstack/storage/to/VolumeObjectTO.java index 8473ea7a49e..6514038ac62 100644 --- a/core/src/main/java/org/apache/cloudstack/storage/to/VolumeObjectTO.java +++ b/core/src/main/java/org/apache/cloudstack/storage/to/VolumeObjectTO.java @@ -33,12 +33,13 @@ import com.cloud.storage.Volume; import java.util.Arrays; -public class VolumeObjectTO implements DataTO { +public class VolumeObjectTO extends DownloadableObjectTO implements DataTO { private String uuid; private Volume.Type volumeType; private DataStoreTO dataStore; private String name; private Long size; + private Long usableSize; private String path; private Long volumeId; private String vmName; @@ -119,6 +120,7 @@ public class VolumeObjectTO implements DataTO { this.vSphereStoragePolicyId = volume.getvSphereStoragePolicyId(); this.passphrase = volume.getPassphrase(); this.encryptFormat = volume.getEncryptFormat(); + this.followRedirects = volume.isFollowRedirects(); } public String getUuid() { @@ -160,6 +162,10 @@ public class VolumeObjectTO implements DataTO { return size; } + public Long getUsableSize() { + return usableSize; + } + @Override public DataObjectType getObjectType() { return DataObjectType.VOLUME; @@ -177,6 +183,10 @@ public class VolumeObjectTO implements DataTO { this.size = size; } + public void setUsableSize(Long usableSize) { + this.usableSize = usableSize; + } + public void setPath(String path) { this.path = path; } diff --git a/core/src/main/java/org/apache/cloudstack/transport/HypervisorTypeAdaptor.java b/core/src/main/java/org/apache/cloudstack/transport/HypervisorTypeAdaptor.java new file mode 100644 index 00000000000..bc4d3c3a6e3 --- /dev/null +++ b/core/src/main/java/org/apache/cloudstack/transport/HypervisorTypeAdaptor.java @@ -0,0 +1,53 @@ +// 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.transport; + +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import java.lang.reflect.Type; + +/** + * {@link HypervisorType} acts as extendable set of singleton objects and should return same result when used "==" + * or {@link Object#equals(Object)}. + * To support that, need to return existing object for a given name instead of creating new. + */ +public class HypervisorTypeAdaptor implements JsonDeserializer, JsonSerializer { + @Override + public HypervisorType deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json instanceof JsonPrimitive && ((JsonPrimitive) json).isString()) { + return HypervisorType.valueOf(json.getAsString()); + } + return null; + } + + @Override + public JsonElement serialize(HypervisorType src, Type typeOfSrc, JsonSerializationContext context) { + String name = src.name(); + if (name == null) { + return new JsonNull(); + } + return new JsonPrimitive(name); + } +} diff --git a/core/src/main/resources/META-INF/cloudstack/allocator/spring-core-allocator-context.xml b/core/src/main/resources/META-INF/cloudstack/allocator/spring-core-allocator-context.xml index a0d1b4cfd43..9f04a7fb618 100644 --- a/core/src/main/resources/META-INF/cloudstack/allocator/spring-core-allocator-context.xml +++ b/core/src/main/resources/META-INF/cloudstack/allocator/spring-core-allocator-context.xml @@ -27,7 +27,7 @@ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" - > + > diff --git a/core/src/main/resources/META-INF/cloudstack/allocator/spring-core-lifecycle-allocator-context-inheritable.xml b/core/src/main/resources/META-INF/cloudstack/allocator/spring-core-lifecycle-allocator-context-inheritable.xml index ec3bb63aeb6..6d05f858303 100644 --- a/core/src/main/resources/META-INF/cloudstack/allocator/spring-core-lifecycle-allocator-context-inheritable.xml +++ b/core/src/main/resources/META-INF/cloudstack/allocator/spring-core-lifecycle-allocator-context-inheritable.xml @@ -27,7 +27,7 @@ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" - > + > diff --git a/core/src/main/resources/META-INF/cloudstack/api/spring-core-lifecycle-api-context-inheritable.xml b/core/src/main/resources/META-INF/cloudstack/api/spring-core-lifecycle-api-context-inheritable.xml index 91a35f18a89..995ed30eb5e 100644 --- a/core/src/main/resources/META-INF/cloudstack/api/spring-core-lifecycle-api-context-inheritable.xml +++ b/core/src/main/resources/META-INF/cloudstack/api/spring-core-lifecycle-api-context-inheritable.xml @@ -62,12 +62,12 @@ - + - + diff --git a/systemvm/agent/scripts/secstorage.sh b/core/src/main/resources/META-INF/cloudstack/cluster/module.properties old mode 100755 new mode 100644 similarity index 69% rename from systemvm/agent/scripts/secstorage.sh rename to core/src/main/resources/META-INF/cloudstack/cluster/module.properties index f210bb79615..e1b7a0e6eb2 --- a/systemvm/agent/scripts/secstorage.sh +++ b/core/src/main/resources/META-INF/cloudstack/cluster/module.properties @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +# # 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 @@ -15,19 +15,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +# - - -#runs the secondary storage service as a standalone server -#i.e., not in the system vm - -CP=./:./conf -for file in *.jar -do - CP=${CP}:$file -done -keyvalues= -#LOGHOME=/var/log/cloud/ -LOGHOME=$PWD/ - -java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore -Dlog.home=$LOGHOME -cp $CP com.cloud.agent.AgentShell $keyvalues $@ +name=cluster +parent=core diff --git a/core/src/main/resources/META-INF/cloudstack/cluster/spring-core-lifecycle-cluster-context-inheritable.xml b/core/src/main/resources/META-INF/cloudstack/cluster/spring-core-lifecycle-cluster-context-inheritable.xml new file mode 100644 index 00000000000..6278c0fc816 --- /dev/null +++ b/core/src/main/resources/META-INF/cloudstack/cluster/spring-core-lifecycle-cluster-context-inheritable.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/core/src/main/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml b/core/src/main/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml index a7f384c76a9..84d1b80b3b6 100644 --- a/core/src/main/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml +++ b/core/src/main/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml @@ -33,7 +33,7 @@ class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry"> - + - + - + @@ -276,11 +276,11 @@ class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry"> - + - + @@ -288,10 +288,10 @@ + class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry"> - + @@ -339,11 +339,28 @@ class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry"> - + + + + + + + + + + + + + + + diff --git a/core/src/main/resources/META-INF/cloudstack/event/module.properties b/core/src/main/resources/META-INF/cloudstack/event/module.properties new file mode 100644 index 00000000000..ab1f88e9844 --- /dev/null +++ b/core/src/main/resources/META-INF/cloudstack/event/module.properties @@ -0,0 +1,21 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +name=event +parent=core diff --git a/core/src/main/resources/META-INF/cloudstack/event/spring-core-lifecycle-event-context-inheritable.xml b/core/src/main/resources/META-INF/cloudstack/event/spring-core-lifecycle-event-context-inheritable.xml new file mode 100644 index 00000000000..63d11c65bac --- /dev/null +++ b/core/src/main/resources/META-INF/cloudstack/event/spring-core-lifecycle-event-context-inheritable.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/core/src/main/resources/META-INF/cloudstack/kubernetes/spring-core-lifecycle-kubernetes-context-inheritable.xml b/core/src/main/resources/META-INF/cloudstack/kubernetes/spring-core-lifecycle-kubernetes-context-inheritable.xml index df1a4b5c229..96a9a634bae 100644 --- a/core/src/main/resources/META-INF/cloudstack/kubernetes/spring-core-lifecycle-kubernetes-context-inheritable.xml +++ b/core/src/main/resources/META-INF/cloudstack/kubernetes/spring-core-lifecycle-kubernetes-context-inheritable.xml @@ -25,8 +25,8 @@ > - - + + diff --git a/core/src/main/resources/META-INF/cloudstack/network/spring-core-lifecycle-network-context-inheritable.xml b/core/src/main/resources/META-INF/cloudstack/network/spring-core-lifecycle-network-context-inheritable.xml index 8dbaf610581..e5c232267ae 100644 --- a/core/src/main/resources/META-INF/cloudstack/network/spring-core-lifecycle-network-context-inheritable.xml +++ b/core/src/main/resources/META-INF/cloudstack/network/spring-core-lifecycle-network-context-inheritable.xml @@ -92,7 +92,7 @@ - + + + + + + diff --git a/core/src/main/resources/META-INF/cloudstack/storage/spring-lifecycle-storage-context-inheritable.xml b/core/src/main/resources/META-INF/cloudstack/storage/spring-lifecycle-storage-context-inheritable.xml index 2771dfe415f..3a47cad2598 100644 --- a/core/src/main/resources/META-INF/cloudstack/storage/spring-lifecycle-storage-context-inheritable.xml +++ b/core/src/main/resources/META-INF/cloudstack/storage/spring-lifecycle-storage-context-inheritable.xml @@ -52,7 +52,7 @@ - + - - + + diff --git a/core/src/main/resources/META-INF/cloudstack/system/spring-core-system-context-inheritable.xml b/core/src/main/resources/META-INF/cloudstack/system/spring-core-system-context-inheritable.xml index 4a59e95de35..89442fc12b4 100644 --- a/core/src/main/resources/META-INF/cloudstack/system/spring-core-system-context-inheritable.xml +++ b/core/src/main/resources/META-INF/cloudstack/system/spring-core-system-context-inheritable.xml @@ -27,7 +27,7 @@ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" - > + > @@ -44,8 +44,8 @@ - - diff --git a/core/src/test/java/com/cloud/agent/api/GetVolumesOnStorageAnswerTest.java b/core/src/test/java/com/cloud/agent/api/GetVolumesOnStorageAnswerTest.java new file mode 100644 index 00000000000..26948f2b823 --- /dev/null +++ b/core/src/test/java/com/cloud/agent/api/GetVolumesOnStorageAnswerTest.java @@ -0,0 +1,73 @@ +// 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; + +import com.cloud.hypervisor.Hypervisor; +import org.apache.cloudstack.storage.volume.VolumeOnStorageTO; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.List; + +public class GetVolumesOnStorageAnswerTest { + + private static String path = "path"; + private static String name = "name"; + private static String fullPath = "fullPath"; + private static String format = "qcow2"; + private static long size = 10; + private static long virtualSize = 20; + private static String encryptFormat = "LUKS"; + + private static GetVolumesOnStorageCommand command = Mockito.mock(GetVolumesOnStorageCommand.class); + + @Test + public void testGetVolumesOnStorageAnswer() { + VolumeOnStorageTO volumeOnStorageTO = new VolumeOnStorageTO(Hypervisor.HypervisorType.KVM, path, name, fullPath, + format, size, virtualSize); + volumeOnStorageTO.setQemuEncryptFormat(encryptFormat); + + List volumesOnStorageTO = new ArrayList<>(); + volumesOnStorageTO.add(volumeOnStorageTO); + + GetVolumesOnStorageAnswer answer = new GetVolumesOnStorageAnswer(command, volumesOnStorageTO); + List volumes = answer.getVolumes(); + + Assert.assertEquals(1, volumes.size()); + VolumeOnStorageTO volume = volumes.get(0); + + Assert.assertEquals(Hypervisor.HypervisorType.KVM, volume.getHypervisorType()); + Assert.assertEquals(path, volume.getPath()); + Assert.assertEquals(name, volume.getName()); + Assert.assertEquals(fullPath, volume.getFullPath()); + Assert.assertEquals(format, volume.getFormat()); + Assert.assertEquals(size, volume.getSize()); + Assert.assertEquals(virtualSize, volume.getVirtualSize()); + Assert.assertEquals(encryptFormat, volume.getQemuEncryptFormat()); + Assert.assertEquals(path, volume.getPath()); + } + + @Test + public void testGetVolumesOnStorageAnswer2() { + String details = "details"; + GetVolumesOnStorageAnswer answer = new GetVolumesOnStorageAnswer(command, false, details); + Assert.assertFalse(answer.getResult()); + Assert.assertEquals(details, answer.getDetails()); + } +} diff --git a/core/src/test/java/com/cloud/agent/api/GetVolumesOnStorageCommandTest.java b/core/src/test/java/com/cloud/agent/api/GetVolumesOnStorageCommandTest.java new file mode 100644 index 00000000000..7b8a9114571 --- /dev/null +++ b/core/src/test/java/com/cloud/agent/api/GetVolumesOnStorageCommandTest.java @@ -0,0 +1,41 @@ +// 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; + +import com.cloud.agent.api.to.StorageFilerTO; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +public class GetVolumesOnStorageCommandTest { + + final StorageFilerTO pool = Mockito.mock(StorageFilerTO.class); + + final String localPath = "localPath"; + final String volumePath = "volumePath"; + final String keyword = "keyword"; + + @Test + public void testGetVolumesOnStorageCommand() { + GetVolumesOnStorageCommand command = new GetVolumesOnStorageCommand(pool, volumePath, keyword); + + Assert.assertEquals(pool, command.getPool()); + Assert.assertEquals(volumePath, command.getVolumePath()); + Assert.assertEquals(keyword, command.getKeyword()); + Assert.assertFalse(command.executeInSequence()); + } +} diff --git a/core/src/test/java/com/cloud/agent/api/SecurityGroupRulesCmdTest.java b/core/src/test/java/com/cloud/agent/api/SecurityGroupRulesCmdTest.java index 50c82a76455..1ce3cfb06b9 100644 --- a/core/src/test/java/com/cloud/agent/api/SecurityGroupRulesCmdTest.java +++ b/core/src/test/java/com/cloud/agent/api/SecurityGroupRulesCmdTest.java @@ -27,7 +27,7 @@ import java.util.Vector; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; import com.cloud.agent.api.SecurityGroupRulesCmd.IpPortAndProto; diff --git a/core/src/test/java/com/cloud/agent/transport/LoggingExclusionStrategyTest.java b/core/src/test/java/com/cloud/agent/transport/LoggingExclusionStrategyTest.java new file mode 100644 index 00000000000..e02fe4516ab --- /dev/null +++ b/core/src/test/java/com/cloud/agent/transport/LoggingExclusionStrategyTest.java @@ -0,0 +1,83 @@ +// 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.transport; + +import com.cloud.agent.api.BadCommand; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.GetStorageStatsCommand; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(MockitoJUnitRunner.class) +public class LoggingExclusionStrategyTest { + + @Mock + Logger loggerMock; + @Spy + @InjectMocks + LoggingExclusionStrategy loggingExclusionStrategySpy; + + @Test + public void shouldSkipClassTestArrayClazz() { + List array = new ArrayList<>(); + + boolean result = loggingExclusionStrategySpy.shouldSkipClass(array.getClass()); + + Assert.assertFalse(result); + } + + @Test + public void shouldSkipClassTestNotSubclassOfCommand() { + Integer integer = 1; + + boolean result = loggingExclusionStrategySpy.shouldSkipClass(integer.getClass()); + + Assert.assertFalse(result); + } + + @Test + public void shouldSkipClassTestNullClassAnnotation() { + Command cmd = new BadCommand(); + Mockito.doReturn(true).when(loggerMock).isEnabled(Level.DEBUG); + + boolean result = loggingExclusionStrategySpy.shouldSkipClass(cmd.getClass()); + + Assert.assertFalse(result); + } + + @Test + public void shouldSkipClassTestWithClassAnnotation() { + Command cmd = new GetStorageStatsCommand(); + Mockito.doReturn(true).when(loggerMock).isEnabled(Level.TRACE); + + boolean result = loggingExclusionStrategySpy.shouldSkipClass(cmd.getClass()); + + Assert.assertFalse(result); + } + +} diff --git a/core/src/test/java/com/cloud/agent/transport/RequestTest.java b/core/src/test/java/com/cloud/agent/transport/RequestTest.java index 21766ba038f..0fe42c7cede 100644 --- a/core/src/test/java/com/cloud/agent/transport/RequestTest.java +++ b/core/src/test/java/com/cloud/agent/transport/RequestTest.java @@ -22,8 +22,8 @@ package com.cloud.agent.transport; import java.nio.ByteBuffer; import junit.framework.TestCase; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import org.junit.Assert; import org.mockito.Mockito; @@ -43,7 +43,6 @@ import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.transport.Request.Version; import com.cloud.exception.UnsupportedVersionException; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.serializer.GsonHelper; import com.cloud.storage.DataStoreRole; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; @@ -58,47 +57,22 @@ import com.cloud.template.VirtualMachineTemplate; */ public class RequestTest extends TestCase { - private static final Logger s_logger = Logger.getLogger(RequestTest.class); + protected Logger logger = LogManager.getLogger(getClass()); public void testSerDeser() { - s_logger.info("Testing serializing and deserializing works as expected"); + logger.info("Testing serializing and deserializing works as expected"); - s_logger.info("UpdateHostPasswordCommand should have two parameters that doesn't show in logging"); + logger.info("UpdateHostPasswordCommand should have two parameters that doesn't show in logging"); UpdateHostPasswordCommand cmd1 = new UpdateHostPasswordCommand("abc", "def"); - s_logger.info("SecStorageFirewallCfgCommand has a context map that shouldn't show up in debug level"); + logger.info("SecStorageFirewallCfgCommand has a context map that shouldn't show up in debug level"); SecStorageFirewallCfgCommand cmd2 = new SecStorageFirewallCfgCommand(); - s_logger.info("GetHostStatsCommand should not show up at all in debug level"); + logger.info("GetHostStatsCommand should not show up at all in debug level"); GetHostStatsCommand cmd3 = new GetHostStatsCommand("hostguid", "hostname", 101); cmd2.addPortConfig("abc", "24", true, "eth0"); cmd2.addPortConfig("127.0.0.1", "44", false, "eth1"); Request sreq = new Request(2, 3, new Command[] {cmd1, cmd2, cmd3}, true, true); sreq.setSequence(892403717); - Logger logger = Logger.getLogger(GsonHelper.class); - Level level = logger.getLevel(); - - logger.setLevel(Level.DEBUG); - String log = sreq.log("Debug", true, Level.DEBUG); - assert (log.contains(UpdateHostPasswordCommand.class.getSimpleName())); - assert (log.contains(SecStorageFirewallCfgCommand.class.getSimpleName())); - assert (!log.contains(GetHostStatsCommand.class.getSimpleName())); - assert (!log.contains("username")); - assert (!log.contains("password")); - - logger.setLevel(Level.TRACE); - log = sreq.log("Trace", true, Level.TRACE); - assert (log.contains(UpdateHostPasswordCommand.class.getSimpleName())); - assert (log.contains(SecStorageFirewallCfgCommand.class.getSimpleName())); - assert (log.contains(GetHostStatsCommand.class.getSimpleName())); - assert (!log.contains("username")); - assert (!log.contains("password")); - - logger.setLevel(Level.INFO); - log = sreq.log("Info", true, Level.INFO); - assert (log == null); - - logger.setLevel(level); - byte[] bytes = sreq.getBytes(); assert Request.getSequence(bytes) == 892403717; @@ -109,9 +83,9 @@ public class RequestTest extends TestCase { try { creq = Request.parse(bytes); } catch (ClassNotFoundException e) { - s_logger.error("Unable to parse bytes: ", e); + logger.error("Unable to parse bytes: ", e); } catch (UnsupportedVersionException e) { - s_logger.error("Unable to parse bytes: ", e); + logger.error("Unable to parse bytes: ", e); } assert creq != null : "Couldn't get the request back"; @@ -127,9 +101,9 @@ public class RequestTest extends TestCase { try { sresp = Response.parse(bytes); } catch (ClassNotFoundException e) { - s_logger.error("Unable to parse bytes: ", e); + logger.error("Unable to parse bytes: ", e); } catch (UnsupportedVersionException e) { - s_logger.error("Unable to parse bytes: ", e); + logger.error("Unable to parse bytes: ", e); } assert sresp != null : "Couldn't get the response back"; @@ -138,7 +112,7 @@ public class RequestTest extends TestCase { } public void testSerDeserTO() { - s_logger.info("Testing serializing and deserializing interface TO works as expected"); + logger.info("Testing serializing and deserializing interface TO works as expected"); NfsTO nfs = new NfsTO("nfs://192.168.56.10/opt/storage/secondary", DataStoreRole.Image); // SecStorageSetupCommand cmd = new SecStorageSetupCommand(nfs, "nfs://192.168.56.10/opt/storage/secondary", null); @@ -156,9 +130,9 @@ public class RequestTest extends TestCase { try { creq = Request.parse(bytes); } catch (ClassNotFoundException e) { - s_logger.error("Unable to parse bytes: ", e); + logger.error("Unable to parse bytes: ", e); } catch (UnsupportedVersionException e) { - s_logger.error("Unable to parse bytes: ", e); + logger.error("Unable to parse bytes: ", e); } assert creq != null : "Couldn't get the request back"; @@ -168,7 +142,7 @@ public class RequestTest extends TestCase { } public void testDownload() { - s_logger.info("Testing Download answer"); + logger.info("Testing Download answer"); VirtualMachineTemplate template = Mockito.mock(VirtualMachineTemplate.class); Mockito.when(template.getId()).thenReturn(1L); Mockito.when(template.getFormat()).thenReturn(ImageFormat.QCOW2); @@ -193,7 +167,7 @@ public class RequestTest extends TestCase { } public void testCompress() { - s_logger.info("testCompress"); + logger.info("testCompress"); int len = 800000; ByteBuffer inputBuffer = ByteBuffer.allocate(len); for (int i = 0; i < len; i++) { @@ -202,7 +176,7 @@ public class RequestTest extends TestCase { inputBuffer.limit(len); ByteBuffer compressedBuffer = ByteBuffer.allocate(len); compressedBuffer = Request.doCompress(inputBuffer, len); - s_logger.info("compressed length: " + compressedBuffer.limit()); + logger.info("compressed length: " + compressedBuffer.limit()); ByteBuffer decompressedBuffer = ByteBuffer.allocate(len); decompressedBuffer = Request.doDecompress(compressedBuffer, len); for (int i = 0; i < len; i++) { @@ -212,29 +186,6 @@ public class RequestTest extends TestCase { } } - public void testLogging() { - s_logger.info("Testing Logging"); - GetHostStatsCommand cmd3 = new GetHostStatsCommand("hostguid", "hostname", 101); - Request sreq = new Request(2, 3, new Command[] {cmd3}, true, true); - sreq.setSequence(1); - Logger logger = Logger.getLogger(GsonHelper.class); - Level level = logger.getLevel(); - - logger.setLevel(Level.DEBUG); - String log = sreq.log("Debug", true, Level.DEBUG); - assert (log == null); - - log = sreq.log("Debug", false, Level.DEBUG); - assert (log != null); - - logger.setLevel(Level.TRACE); - log = sreq.log("Trace", true, Level.TRACE); - assert (log.contains(GetHostStatsCommand.class.getSimpleName())); - s_logger.debug(log); - - logger.setLevel(level); - } - protected void compareRequest(Request req1, Request req2) { assert req1.getSequence() == req2.getSequence(); assert req1.getAgentId() == req2.getAgentId(); @@ -253,24 +204,24 @@ public class RequestTest extends TestCase { } public void testGoodCommand() { - s_logger.info("Testing good Command"); + logger.info("Testing good Command"); String content = "[{\"com.cloud.agent.api.GetVolumeStatsCommand\":{\"volumeUuids\":[\"dcc860ac-4a20-498f-9cb3-bab4d57aa676\"]," - + "\"poolType\":\"NetworkFilesystem\",\"poolUuid\":\"e007c270-2b1b-3ce9-ae92-a98b94eef7eb\",\"contextMap\":{},\"wait\":5}}]"; + + "\"poolType\":{\"name\":\"NetworkFilesystem\"},\"poolUuid\":\"e007c270-2b1b-3ce9-ae92-a98b94eef7eb\",\"contextMap\":{},\"wait\":5}}]"; Request sreq = new Request(Version.v2, 1L, 2L, 3L, 1L, (short)1, content); sreq.setSequence(1); Command cmds[] = sreq.getCommands(); - s_logger.debug("Command class = " + cmds[0].getClass().getSimpleName()); + logger.debug("Command class = " + cmds[0].getClass().getSimpleName()); assert cmds[0].getClass().equals(GetVolumeStatsCommand.class); } public void testBadCommand() { - s_logger.info("Testing Bad Command"); + logger.info("Testing Bad Command"); String content = "[{\"com.cloud.agent.api.SomeJunkCommand\":{\"volumeUuids\":[\"dcc860ac-4a20-498f-9cb3-bab4d57aa676\"]," - + "\"poolType\":\"NetworkFilesystem\",\"poolUuid\":\"e007c270-2b1b-3ce9-ae92-a98b94eef7eb\",\"contextMap\":{},\"wait\":5}}]"; + + "\"poolType\":{\"name\":\"NetworkFilesystem\"},\"poolUuid\":\"e007c270-2b1b-3ce9-ae92-a98b94eef7eb\",\"contextMap\":{},\"wait\":5}}]"; Request sreq = new Request(Version.v2, 1L, 2L, 3L, 1L, (short)1, content); sreq.setSequence(1); Command cmds[] = sreq.getCommands(); - s_logger.debug("Command class = " + cmds[0].getClass().getSimpleName()); + logger.debug("Command class = " + cmds[0].getClass().getSimpleName()); assert cmds[0].getClass().equals(BadCommand.class); } diff --git a/core/src/test/java/com/cloud/resource/ServerResourceBaseTest.java b/core/src/test/java/com/cloud/resource/ServerResourceBaseTest.java index d9df73fb9b1..ed64e1482a6 100644 --- a/core/src/test/java/com/cloud/resource/ServerResourceBaseTest.java +++ b/core/src/test/java/com/cloud/resource/ServerResourceBaseTest.java @@ -17,18 +17,21 @@ package com.cloud.resource; import com.cloud.utils.net.NetUtils; +import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsAnswer; +import org.apache.commons.collections.CollectionUtils; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; +import org.mockito.MockedStatic; import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; import javax.naming.ConfigurationException; +import java.io.File; +import java.io.IOException; import java.net.NetworkInterface; import java.net.SocketException; import java.util.ArrayList; @@ -40,7 +43,7 @@ import java.util.List; import java.util.Map; -@RunWith(PowerMockRunner.class) +@RunWith(MockitoJUnitRunner.class) public class ServerResourceBaseTest { private static final String[] NIC_NAME_STARTS_TO_AVOID = {"vnif", "vnbr", "peth", "vif", "virbr"}; @@ -54,165 +57,162 @@ public class ServerResourceBaseTest { @Before public void setup() { - networkInterfaceMock1 = PowerMockito.mock(NetworkInterface.class); - networkInterfaceMock2 = PowerMockito.mock(NetworkInterface.class); - networkInterfaceMock3 = PowerMockito.mock(NetworkInterface.class); - networkInterfaceMock4 = PowerMockito.mock(NetworkInterface.class); + networkInterfaceMock1 = Mockito.mock(NetworkInterface.class); + networkInterfaceMock2 = Mockito.mock(NetworkInterface.class); + networkInterfaceMock3 = Mockito.mock(NetworkInterface.class); + networkInterfaceMock4 = Mockito.mock(NetworkInterface.class); } @Test - @PrepareForTest(ServerResourceBase.class) public void isValidNicToUseAsPrivateNicTestReturnFalseWhenNicIsVirtual() { - NetworkInterface networkInterfaceMock = PowerMockito.mock(NetworkInterface.class); - PowerMockito.when(networkInterfaceMock.isVirtual()).thenReturn(true); + NetworkInterface networkInterfaceMock = Mockito.mock(NetworkInterface.class); + Mockito.when(networkInterfaceMock.isVirtual()).thenReturn(true); Assert.assertFalse(serverResourceBaseSpy.isValidNicToUseAsPrivateNic(networkInterfaceMock)); } @Test - @PrepareForTest(ServerResourceBase.class) public void isValidNicToUseAsPrivateNicTestReturnFalseWhenNicNameStartsWithOneOfTheAvoidList() { - NetworkInterface networkInterfaceMock = PowerMockito.mock(NetworkInterface.class); - PowerMockito.when(networkInterfaceMock.isVirtual()).thenReturn(false); - PowerMockito.when(networkInterfaceMock.getName()).thenReturn("vniftest", "vnbrtest", "pethtest", "viftest", "virbrtest"); + NetworkInterface networkInterfaceMock = Mockito.mock(NetworkInterface.class); + Mockito.when(networkInterfaceMock.isVirtual()).thenReturn(false); + Mockito.when(networkInterfaceMock.getName()).thenReturn("vniftest", "vnbrtest", "pethtest", "viftest", "virbrtest"); Arrays.asList(NIC_NAME_STARTS_TO_AVOID).forEach(type -> Assert.assertFalse(serverResourceBaseSpy.isValidNicToUseAsPrivateNic(networkInterfaceMock))); } @Test - @PrepareForTest(ServerResourceBase.class) public void isValidNicToUseAsPrivateNicTestReturnFalseWhenNicNameContainsColon() { - NetworkInterface networkInterfaceMock = PowerMockito.mock(NetworkInterface.class); - PowerMockito.when(networkInterfaceMock.isVirtual()).thenReturn(false); - PowerMockito.when(networkInterfaceMock.getName()).thenReturn("te:st"); + NetworkInterface networkInterfaceMock = Mockito.mock(NetworkInterface.class); + Mockito.when(networkInterfaceMock.isVirtual()).thenReturn(false); + Mockito.when(networkInterfaceMock.getName()).thenReturn("te:st"); Assert.assertFalse(serverResourceBaseSpy.isValidNicToUseAsPrivateNic(networkInterfaceMock)); } @Test - @PrepareForTest({ServerResourceBase.class, NetUtils.class}) public void isValidNicToUseAsPrivateNicTestReturnFalseWhenNetUtilsGetNicParamsReturnsNull() { - NetworkInterface networkInterfaceMock = PowerMockito.mock(NetworkInterface.class); - PowerMockito.when(networkInterfaceMock.isVirtual()).thenReturn(false); - PowerMockito.when(networkInterfaceMock.getName()).thenReturn("testvnif", "testvnbr", "testpeth", "testvif", "testvirbr"); + NetworkInterface networkInterfaceMock = Mockito.mock(NetworkInterface.class); + Mockito.when(networkInterfaceMock.isVirtual()).thenReturn(false); + Mockito.when(networkInterfaceMock.getName()).thenReturn("testvnif", "testvnbr", "testpeth", "testvif", "testvirbr"); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.getNicParams(Mockito.anyString())).thenReturn(null); + try (MockedStatic ignored = Mockito.mockStatic(NetUtils.class)) { + Mockito.when(NetUtils.getNicParams(Mockito.anyString())).thenReturn(null); - Arrays.asList(NIC_NAME_STARTS_TO_AVOID).forEach(type -> { - Assert.assertFalse(serverResourceBaseSpy.isValidNicToUseAsPrivateNic(networkInterfaceMock)); - }); + Arrays.asList(NIC_NAME_STARTS_TO_AVOID).forEach(type -> { + Assert.assertFalse(serverResourceBaseSpy.isValidNicToUseAsPrivateNic(networkInterfaceMock)); + }); + } } @Test - @PrepareForTest({ServerResourceBase.class, NetUtils.class}) public void isValidNicToUseAsPrivateNicTestReturnFalseWhenNetUtilsGetNicParamsReturnsFirstElementNull() { - NetworkInterface networkInterfaceMock = PowerMockito.mock(NetworkInterface.class); - PowerMockito.when(networkInterfaceMock.isVirtual()).thenReturn(false); - PowerMockito.when(networkInterfaceMock.getName()).thenReturn("testvnif", "testvnbr", "testpeth", "testvif", "testvirbr"); + NetworkInterface networkInterfaceMock = Mockito.mock(NetworkInterface.class); + Mockito.when(networkInterfaceMock.isVirtual()).thenReturn(false); + Mockito.when(networkInterfaceMock.getName()).thenReturn("testvnif", "testvnbr", "testpeth", "testvif", "testvirbr"); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.getNicParams(Mockito.anyString())).thenReturn(new String[]{null}); + try (MockedStatic ignored = Mockito.mockStatic(NetUtils.class)) { + Mockito.when(NetUtils.getNicParams(Mockito.anyString())).thenReturn(new String[]{null}); - Arrays.asList(NIC_NAME_STARTS_TO_AVOID).forEach(type -> { - Assert.assertFalse(serverResourceBaseSpy.isValidNicToUseAsPrivateNic(networkInterfaceMock)); - }); + Arrays.asList(NIC_NAME_STARTS_TO_AVOID).forEach(type -> { + Assert.assertFalse(serverResourceBaseSpy.isValidNicToUseAsPrivateNic(networkInterfaceMock)); + }); + } } @Test - @PrepareForTest({ServerResourceBase.class, NetUtils.class}) public void isValidNicToUseAsPrivateNicTestReturnTrueWhenNetUtilsGetNicParamsReturnsAValidFirstElement() { - NetworkInterface networkInterfaceMock = PowerMockito.mock(NetworkInterface.class); - PowerMockito.when(networkInterfaceMock.isVirtual()).thenReturn(false); - PowerMockito.when(networkInterfaceMock.getName()).thenReturn("testvnif", "testvnbr", "testpeth", "testvif", "testvirbr"); + NetworkInterface networkInterfaceMock = Mockito.mock(NetworkInterface.class); + Mockito.when(networkInterfaceMock.isVirtual()).thenReturn(false); + Mockito.when(networkInterfaceMock.getName()).thenReturn("testvnif", "testvnbr", "testpeth", "testvif", "testvirbr"); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.getNicParams(Mockito.anyString())).thenReturn(new String[]{"test"}); + try (MockedStatic ignored = Mockito.mockStatic(NetUtils.class)) { + Mockito.when(NetUtils.getNicParams(Mockito.anyString())).thenReturn(new String[]{"test"}); - Arrays.asList(NIC_NAME_STARTS_TO_AVOID).forEach(type -> { - Assert.assertTrue(serverResourceBaseSpy.isValidNicToUseAsPrivateNic(networkInterfaceMock)); - }); + Arrays.asList(NIC_NAME_STARTS_TO_AVOID).forEach(type -> { + Assert.assertTrue(serverResourceBaseSpy.isValidNicToUseAsPrivateNic(networkInterfaceMock)); + }); + } } @Test(expected = ConfigurationException.class) - @PrepareForTest(ServerResourceBase.class) public void tryToAutoDiscoverResourcePrivateNetworkInterfaceTestThrowConfigurationExceptionWhenNicsDoesNotHaveMoreElements() throws SocketException, ConfigurationException { - PowerMockito.mockStatic(NetworkInterface.class); - PowerMockito.when(NetworkInterface.getNetworkInterfaces()).thenReturn(Collections.enumeration(new ArrayList<>())); + try (MockedStatic ignored = Mockito.mockStatic(NetworkInterface.class)) { + Mockito.when(NetworkInterface.getNetworkInterfaces()).thenReturn(Collections.enumeration(new ArrayList<>())); - serverResourceBaseSpy.tryToAutoDiscoverResourcePrivateNetworkInterface(); + serverResourceBaseSpy.tryToAutoDiscoverResourcePrivateNetworkInterface(); + } } @Test(expected = ConfigurationException.class) - @PrepareForTest(ServerResourceBase.class) public void tryToAutoDiscoverResourcePrivateNetworkInterfaceTestThrowConfigurationExceptionWhenNicsGetNetworkInterfacesThrowsSocketException() throws SocketException, ConfigurationException { - PowerMockito.mockStatic(NetworkInterface.class); - PowerMockito.when(NetworkInterface.getNetworkInterfaces()).thenThrow(SocketException.class); + try (MockedStatic ignored = Mockito.mockStatic(NetworkInterface.class)) { + Mockito.when(NetworkInterface.getNetworkInterfaces()).thenThrow(SocketException.class); - serverResourceBaseSpy.tryToAutoDiscoverResourcePrivateNetworkInterface(); + serverResourceBaseSpy.tryToAutoDiscoverResourcePrivateNetworkInterface(); + } } @Test(expected = ConfigurationException.class) - @PrepareForTest(ServerResourceBase.class) public void tryToAutoDiscoverResourcePrivateNetworkInterfaceTestThrowConfigurationExceptionWhenThereIsNoValidNics() throws SocketException, ConfigurationException { - PowerMockito.mockStatic(NetworkInterface.class); - PowerMockito.when(NetworkInterface.getNetworkInterfaces()).thenReturn(Collections.enumeration(Arrays.asList(networkInterfaceMock1, networkInterfaceMock2))); - Mockito.doReturn(false).when(serverResourceBaseSpy).isValidNicToUseAsPrivateNic(Mockito.any()); + try (MockedStatic ignored = Mockito.mockStatic(NetworkInterface.class)) { + Mockito.when(NetworkInterface.getNetworkInterfaces()).thenReturn(Collections.enumeration(Arrays.asList(networkInterfaceMock1, networkInterfaceMock2))); + Mockito.doReturn(false).when(serverResourceBaseSpy).isValidNicToUseAsPrivateNic(Mockito.any()); - serverResourceBaseSpy.tryToAutoDiscoverResourcePrivateNetworkInterface(); + serverResourceBaseSpy.tryToAutoDiscoverResourcePrivateNetworkInterface(); - Mockito.verify(serverResourceBaseSpy, Mockito.times(2)).isValidNicToUseAsPrivateNic(Mockito.any()); + Mockito.verify(serverResourceBaseSpy, Mockito.times(2)).isValidNicToUseAsPrivateNic(Mockito.any()); + } } @Test - @PrepareForTest(ServerResourceBase.class) public void tryToAutoDiscoverResourcePrivateNetworkInterfaceTestReturnNic() throws SocketException, ConfigurationException { Enumeration interfaces = Collections.enumeration(Arrays.asList(networkInterfaceMock1, networkInterfaceMock2)); - PowerMockito.mockStatic(NetworkInterface.class); - PowerMockito.when(NetworkInterface.getNetworkInterfaces()).thenReturn(interfaces); - Mockito.doReturn(false, true).when(serverResourceBaseSpy).isValidNicToUseAsPrivateNic(Mockito.any()); + try (MockedStatic ignored = Mockito.mockStatic(NetworkInterface.class)) { + Mockito.when(NetworkInterface.getNetworkInterfaces()).thenReturn(interfaces); + Mockito.doReturn(false, true).when(serverResourceBaseSpy).isValidNicToUseAsPrivateNic(Mockito.any()); - serverResourceBaseSpy.tryToAutoDiscoverResourcePrivateNetworkInterface(); + serverResourceBaseSpy.tryToAutoDiscoverResourcePrivateNetworkInterface(); - Assert.assertEquals(networkInterfaceMock2, serverResourceBaseSpy._privateNic); - Mockito.verify(serverResourceBaseSpy, Mockito.times(2)).isValidNicToUseAsPrivateNic(Mockito.any()); + Assert.assertEquals(networkInterfaceMock2, serverResourceBaseSpy.privateNic); + Mockito.verify(serverResourceBaseSpy, Mockito.times(2)).isValidNicToUseAsPrivateNic(Mockito.any()); + } } @Test - @PrepareForTest(NetUtils.class) public void defineResourceNetworkInterfacesTestUseXenbr0WhenPrivateNetworkInterfaceNotConfigured() { Map params = createParamsMap(null, "cloudbr1", "cloudbr2", "cloudbr3"); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.getNetworkInterface(Mockito.anyString())).thenReturn(networkInterfaceMock1, networkInterfaceMock2, networkInterfaceMock3, networkInterfaceMock4); + try (MockedStatic ignored = Mockito.mockStatic(NetUtils.class)) { + Mockito.when(NetUtils.getNetworkInterface(Mockito.anyString())).thenReturn(networkInterfaceMock1, networkInterfaceMock2, networkInterfaceMock3, networkInterfaceMock4); - serverResourceBaseSpy.defineResourceNetworkInterfaces(params); + serverResourceBaseSpy.defineResourceNetworkInterfaces(params); - verifyAndAssertNetworkInterfaces("xenbr0", "cloudbr1", "cloudbr2", "cloudbr3"); + verifyAndAssertNetworkInterfaces("xenbr0", "cloudbr1", "cloudbr2", "cloudbr3"); + } } @Test - @PrepareForTest(NetUtils.class) public void defineResourceNetworkInterfacesTestUseXenbr1WhenPublicNetworkInterfaceNotConfigured() { Map params = createParamsMap("cloudbr0", null, "cloudbr2", "cloudbr3"); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.getNetworkInterface(Mockito.anyString())).thenReturn(networkInterfaceMock1, networkInterfaceMock2, networkInterfaceMock3, networkInterfaceMock4); + try (MockedStatic ignored = Mockito.mockStatic(NetUtils.class)) { + Mockito.when(NetUtils.getNetworkInterface(Mockito.anyString())).thenReturn(networkInterfaceMock1, networkInterfaceMock2, networkInterfaceMock3, networkInterfaceMock4); - serverResourceBaseSpy.defineResourceNetworkInterfaces(params); + serverResourceBaseSpy.defineResourceNetworkInterfaces(params); - verifyAndAssertNetworkInterfaces("cloudbr0", "xenbr1", "cloudbr2", "cloudbr3"); + verifyAndAssertNetworkInterfaces("cloudbr0", "xenbr1", "cloudbr2", "cloudbr3"); + } } @Test - @PrepareForTest(NetUtils.class) public void defineResourceNetworkInterfacesTestUseConfiguredNetworkInterfaces() { Map params = createParamsMap("cloudbr0", "cloudbr1", "cloudbr2", "cloudbr3"); - PowerMockito.mockStatic(NetUtils.class); - PowerMockito.when(NetUtils.getNetworkInterface(Mockito.anyString())).thenReturn(networkInterfaceMock1, networkInterfaceMock2, networkInterfaceMock3, networkInterfaceMock4); + try (MockedStatic ignored = Mockito.mockStatic(NetUtils.class)) { + Mockito.when(NetUtils.getNetworkInterface(Mockito.anyString())).thenReturn(networkInterfaceMock1, networkInterfaceMock2, networkInterfaceMock3, networkInterfaceMock4); - serverResourceBaseSpy.defineResourceNetworkInterfaces(params); + serverResourceBaseSpy.defineResourceNetworkInterfaces(params); - verifyAndAssertNetworkInterfaces("cloudbr0", "cloudbr1", "cloudbr2", "cloudbr3"); + verifyAndAssertNetworkInterfaces("cloudbr0", "cloudbr1", "cloudbr2", "cloudbr3"); + } } private Map createParamsMap(String... params) { @@ -225,7 +225,7 @@ public class ServerResourceBaseTest { } private void verifyAndAssertNetworkInterfaces(String... expectedResults) { - PowerMockito.verifyStatic(NetUtils.class, Mockito.times(4)); + Mockito.verify(NetUtils.class, Mockito.times(4)); NetUtils.getNetworkInterface(keyCaptor.capture()); List keys = keyCaptor.getAllValues(); @@ -233,9 +233,42 @@ public class ServerResourceBaseTest { Assert.assertEquals(expectedResults[i], keys.get(i)); } - Assert.assertEquals(networkInterfaceMock1, serverResourceBaseSpy._privateNic); - Assert.assertEquals(networkInterfaceMock2, serverResourceBaseSpy._publicNic); - Assert.assertEquals(networkInterfaceMock3, serverResourceBaseSpy._storageNic); - Assert.assertEquals(networkInterfaceMock4, serverResourceBaseSpy._storageNic2); + Assert.assertEquals(networkInterfaceMock1, serverResourceBaseSpy.privateNic); + Assert.assertEquals(networkInterfaceMock2, serverResourceBaseSpy.publicNic); + Assert.assertEquals(networkInterfaceMock3, serverResourceBaseSpy.storageNic); + Assert.assertEquals(networkInterfaceMock4, serverResourceBaseSpy.storageNic2); + } + + @Test + public void testListFilesAtPath() throws IOException { + String nfsMountPoint = "/tmp/nfs"; + String relativePath = "test"; + int startIndex = 0; + int pageSize = 10; + + // create a test directory with some files + File testDir = new File(nfsMountPoint, relativePath); + testDir.mkdirs(); + File file1 = new File(testDir, "file1.txt"); + File file2 = new File(testDir, "file2.txt"); + file1.createNewFile(); + file2.createNewFile(); + + ListDataStoreObjectsAnswer result = (ListDataStoreObjectsAnswer) serverResourceBaseSpy.listFilesAtPath(nfsMountPoint, relativePath, startIndex, pageSize); + + Assert.assertTrue(result.getResult()); + Assert.assertEquals(2, result.getCount()); + List expectedNames = Arrays.asList("file1.txt", "file2.txt"); + List expectedPaths = Arrays.asList("/test/file1.txt", "/test/file2.txt"); + List expectedAbsPaths = Arrays.asList(nfsMountPoint + "/test/file1.txt", nfsMountPoint + "/test/file2.txt"); + List expectedIsDirs = Arrays.asList(false, false); + List expectedSizes = Arrays.asList(file2.length(), file1.length()); + List expectedModifiedList = Arrays.asList(file2.lastModified(), file1.lastModified()); + Assert.assertTrue(CollectionUtils.isEqualCollection(expectedNames, result.getNames())); + Assert.assertTrue(CollectionUtils.isEqualCollection(expectedPaths, result.getPaths())); + Assert.assertTrue(CollectionUtils.isEqualCollection(expectedAbsPaths, result.getAbsPaths())); + Assert.assertTrue(CollectionUtils.isEqualCollection(expectedIsDirs, result.getIsDirs())); + Assert.assertTrue(CollectionUtils.isEqualCollection(expectedSizes, result.getSizes())); + Assert.assertTrue(CollectionUtils.isEqualCollection(expectedModifiedList, result.getLastModified())); } } diff --git a/core/src/test/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBaseTest.java b/core/src/test/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBaseTest.java new file mode 100644 index 00000000000..104c6521676 --- /dev/null +++ b/core/src/test/java/com/cloud/storage/resource/StorageSubsystemCommandHandlerBaseTest.java @@ -0,0 +1,43 @@ +// 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.storage.resource; + +import org.apache.cloudstack.storage.command.QuerySnapshotZoneCopyAnswer; +import org.apache.cloudstack.storage.command.QuerySnapshotZoneCopyCommand; +import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import com.cloud.agent.api.Answer; + +@RunWith(MockitoJUnitRunner.class) +public class StorageSubsystemCommandHandlerBaseTest { + + @Test + public void testHandleQuerySnapshotCommand() { + StorageSubsystemCommandHandlerBase storageSubsystemCommandHandlerBase = new StorageSubsystemCommandHandlerBase(Mockito.mock(StorageProcessor.class)); + QuerySnapshotZoneCopyCommand querySnapshotZoneCopyCommand = new QuerySnapshotZoneCopyCommand(Mockito.mock(SnapshotObjectTO.class)); + Answer answer = storageSubsystemCommandHandlerBase.handleStorageCommands(querySnapshotZoneCopyCommand); + Assert.assertTrue(answer instanceof QuerySnapshotZoneCopyAnswer); + QuerySnapshotZoneCopyAnswer querySnapshotZoneCopyAnswer = (QuerySnapshotZoneCopyAnswer)answer; + Assert.assertFalse(querySnapshotZoneCopyAnswer.getResult()); + Assert.assertEquals("Unsupported command", querySnapshotZoneCopyAnswer.getDetails()); + } +} diff --git a/core/src/test/java/com/cloud/storage/template/OVAProcessorTest.java b/core/src/test/java/com/cloud/storage/template/OVAProcessorTest.java index 2387842fe33..8ab54644718 100644 --- a/core/src/test/java/com/cloud/storage/template/OVAProcessorTest.java +++ b/core/src/test/java/com/cloud/storage/template/OVAProcessorTest.java @@ -28,19 +28,15 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.MockedConstruction; import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import org.mockito.junit.MockitoJUnitRunner; import java.io.File; import java.util.HashMap; import java.util.Map; -@RunWith(PowerMockRunner.class) -@PowerMockIgnore({"javax.xml.*", "java.xml.*", "javax.management.*", "org.apache.xerces.*"}) -@PrepareForTest(OVAProcessor.class) +@RunWith(MockitoJUnitRunner.class) public class OVAProcessorTest { OVAProcessor processor; @@ -49,7 +45,7 @@ public class OVAProcessorTest { @Before public void setUp() throws Exception { - processor = PowerMockito.spy(new OVAProcessor()); + processor = Mockito.spy(new OVAProcessor()); Map params = new HashMap(); params.put(StorageLayer.InstanceConfigKey, mockStorageLayer); processor.configure("OVA Processor", params); @@ -62,11 +58,11 @@ public class OVAProcessorTest { Mockito.when(mockStorageLayer.exists(Mockito.anyString())).thenReturn(true); - Script mockScript = Mockito.mock(Script.class); - PowerMockito.whenNew(Script.class).withAnyArguments().thenReturn(mockScript); - PowerMockito.when(mockScript.execute()).thenReturn("error while untaring the file"); - - processor.process(templatePath, null, templateName); + try (MockedConstruction @@ -72,8 +72,8 @@ under the License. 180 - - + + createStoragePool @@ -99,5 +99,5 @@ under the License. - + diff --git a/test/conf/deploy.properties b/test/conf/deploy.properties index 640ccfce844..321f970cae1 100644 --- a/test/conf/deploy.properties +++ b/test/conf/deploy.properties @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/test/conf/deploy.xml b/test/conf/deploy.xml index 7f4047a7a01..29dcbf146fc 100644 --- a/test/conf/deploy.xml +++ b/test/conf/deploy.xml @@ -30,7 +30,7 @@ under the License. - + deleteZone @@ -70,7 +70,7 @@ under the License. - + createVlanIpRange @@ -104,7 +104,7 @@ under the License. - + createPod @@ -166,7 +166,7 @@ under the License. - + updateConfiguration diff --git a/test/conf/log4j-stdout.properties b/test/conf/log4j-stdout.properties index 51c90854fb3..a5a16af9dcb 100644 --- a/test/conf/log4j-stdout.properties +++ b/test/conf/log4j-stdout.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/test/conf/log4j.properties b/test/conf/log4j.properties index 2c8eae6d6b7..4bc91563394 100644 --- a/test/conf/log4j.properties +++ b/test/conf/log4j.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/test/conf/tool.properties b/test/conf/tool.properties index 942d92af400..c23550c925a 100644 --- a/test/conf/tool.properties +++ b/test/conf/tool.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/test/integration/component/maint/test_host_high_availability.py b/test/integration/component/maint/test_host_high_availability.py index c95b5db89b6..c335c66b481 100644 --- a/test/integration/component/maint/test_host_high_availability.py +++ b/test/integration/component/maint/test_host_high_availability.py @@ -483,7 +483,7 @@ class TestHostHighAvailability(cloudstackTestCase): self.assertEqual( vm_response.id, vm.id, - "The virtual machine id and the the virtual machine from listVirtualMachines is not matching." + "The virtual machine id and the virtual machine from listVirtualMachines is not matching." ) self.assertEqual( diff --git a/test/integration/component/maint/test_primary_storage_nfsmountopts_kvm.py b/test/integration/component/maint/test_primary_storage_nfsmountopts_kvm.py new file mode 100644 index 00000000000..f2ad18188ca --- /dev/null +++ b/test/integration/component/maint/test_primary_storage_nfsmountopts_kvm.py @@ -0,0 +1,184 @@ +# 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. + +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.cloudstackAPI import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import (list_clusters, list_hosts, list_storage_pools) +import xml.etree.ElementTree as ET +from lxml import etree +from nose.plugins.attrib import attr + +class TestNFSMountOptsKVM(cloudstackTestCase): + """ Test cases for host HA using KVM host(s) + """ + + @classmethod + def setUpClass(cls): + testClient = super(TestNFSMountOptsKVM, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + + cls.cluster = list_clusters(cls.apiclient)[0] + cls.host = cls.getHost(cls) + cls.storage_pool = cls.getPrimaryStorage(cls, cls.cluster.id) + cls.hostConfig = cls.config.__dict__["zones"][0].__dict__["pods"][0].__dict__["clusters"][0].__dict__["hosts"][0].__dict__ + cls.cluster_id = cls.host.clusterid + cls.sshClient = SshClient( + host=cls.host.ipaddress, + port=22, + user=cls.hostConfig['username'], + passwd=cls.hostConfig['password']) + cls.version = cls.getNFSMountOptionForPool(cls, "vers", cls.storage_pool.id) + if (cls.version == None): + raise cls.skipTest("Storage pool not associated with the host") + + def tearDown(self): + nfsMountOpts = "vers=" + self.version + details = [{'nfsmountopts': nfsMountOpts}] + self.changeNFSOptions(details) + pass + + def getHost(self): + response = list_hosts( + self.apiclient, + type='Routing', + hypervisor='kvm', + state='Up', + id=None + ) + + if response and len(response) > 0: + self.host = response[0] + return self.host + raise self.skipTest("Not enough KVM hosts found, skipping NFS options test") + + def getPrimaryStorage(self, clusterId): + response = list_storage_pools( + self.apiclient, + clusterid=clusterId, + type='NetworkFilesystem', + state='Up', + id=None, + ) + if response and len(response) > 0: + return response[0] + raise self.skipTest("Not enough KVM hosts found, skipping NFS options test") + + def getNFSMountOptionsFromVirsh(self, poolId): + virsh_cmd = "virsh pool-dumpxml %s" % poolId + xml_res = self.sshClient.execute(virsh_cmd) + xml_as_str = ''.join(xml_res) + self.debug(xml_as_str) + parser = etree.XMLParser(remove_blank_text=True) + root = ET.fromstring(xml_as_str, parser=parser) + mount_opts = root.findall("{http://libvirt.org/schemas/storagepool/fs/1.0}mount_opts")[0] + + options_map = {} + for child in mount_opts: + option = child.get('name').split("=") + options_map[option[0]] = option[1] + return options_map + + def getUnusedNFSVersions(self, filter): + nfsstat_cmd = "nfsstat -m | sed -n '/%s/{ n; p }'" % filter + nfsstats = self.sshClient.execute(nfsstat_cmd) + versions = {"4.1": 0, "4.2": 0, "3": 0} + for stat in nfsstats: + vers = stat[stat.find("vers"):].split("=")[1].split(",")[0] + versions[vers] += 1 + + for key in versions: + if versions[key] == 0: + return key + return None + + def getNFSMountOptionForPool(self, option, poolId): + nfsstat_cmd = "nfsstat -m | sed -n '/%s/{ n; p }'" % poolId + nfsstat = self.sshClient.execute(nfsstat_cmd) + if (nfsstat == None): + return None + stat = nfsstat[0] + vers = stat[stat.find(option):].split("=")[1].split(",")[0] + return vers + + def changeNFSOptions(self, details): + maint_cmd = enableStorageMaintenance.enableStorageMaintenanceCmd() + maint_cmd.id = self.storage_pool.id + + storage = StoragePool.list(self.apiclient, + id=self.storage_pool.id + )[0] + if storage.state != "Maintenance": + self.apiclient.enableStorageMaintenance(maint_cmd) + + StoragePool.update(self.apiclient, + id=self.storage_pool.id, + details=details + ) + + store_maint_cmd = cancelStorageMaintenance.cancelStorageMaintenanceCmd() + store_maint_cmd.id = self.storage_pool.id + resp = self.apiclient.cancelStorageMaintenance(store_maint_cmd) + return resp + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true") + def test_primary_storage_nfs_options_kvm(self): + """ + Tests that NFS mount options configured on the primary storage are set correctly on the KVM hypervisor host + """ + version = self.getUnusedNFSVersions(self.storage_pool.ipaddress) + nconnect = None + if version == None: + self.debug("skipping nconnect mount option as there are multiple mounts already present from the nfs server for all versions") + version = self.getUnusedNFSVersions(self.storage_pool.id) + nfsMountOpts = "vers=" + version + else: + nconnect='4' + nfsMountOpts = "vers=" + version + ",nconnect=" + nconnect + + details = [{'nfsmountopts': nfsMountOpts}] + + resp = self.changeNFSOptions(details) + + storage = StoragePool.list(self.apiclient, + id=self.storage_pool.id + )[0] + self.assertEqual(storage.nfsmountopts, nfsMountOpts) + + options = self.getNFSMountOptionsFromVirsh(self.storage_pool.id) + self.assertEqual(options["vers"], version) + if (nconnect != None): + self.assertEqual(options["nconnect"], nconnect) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true") + def test_primary_storage_incorrect_nfs_options_kvm(self): + """ + Tests that incorrect NFS mount options leads to exception when maintenance mode is cancelled + """ + nfsMountOpts = "version=4.1" + details = [{'nfsmountopts': nfsMountOpts}] + + try: + resp = self.changeNFSOptions(details) + except Exception: + storage = StoragePool.list(self.apiclient, + id=self.storage_pool.id + )[0] + self.assertEqual(storage.state, "Maintenance") + else: + self.fail("Incorrect NFS mount option should throw error while mounting") diff --git a/test/integration/component/maint/testpath_disable_enable_zone.py b/test/integration/component/maint/testpath_disable_enable_zone.py index 216161f1c6b..63642c0fd25 100644 --- a/test/integration/component/maint/testpath_disable_enable_zone.py +++ b/test/integration/component/maint/testpath_disable_enable_zone.py @@ -1273,7 +1273,7 @@ class TestDisableEnableCluster(cloudstackTestCase): self.assertEqual(len(exception_list), 0, - "Check if vm's are accesible" + "Check if vm's are accessible" ) # non-admin user should fail to create vm, snap, temp etc diff --git a/test/integration/component/maint/testpath_vMotion_vmware.py b/test/integration/component/maint/testpath_vMotion_vmware.py index b37db8aa09a..06facdd9212 100644 --- a/test/integration/component/maint/testpath_vMotion_vmware.py +++ b/test/integration/component/maint/testpath_vMotion_vmware.py @@ -1190,7 +1190,7 @@ class TestStorageLiveMigrationVmware(cloudstackTestCase): a) Create VM snapshots to check data integrity - @method used : VmSnapshotToCheckDataIntegrity(self, vm) c) Check for VM accessibility by sshing to the VM - @method used : check_for_vm_access_by_ssh_using_nat(self, virtual_machine_1) """ - if not self.zone.localstorageenabled: + if not self.zone.localstorageenabled: raise self.skipTest("The setup doesn't have local storage enabled") scope = first_value ostype = second_value diff --git a/test/integration/component/test_acl_isolatednetwork.py b/test/integration/component/test_acl_isolatednetwork.py index 5126aff06d4..038fd358972 100644 --- a/test/integration/component/test_acl_isolatednetwork.py +++ b/test/integration/component/test_acl_isolatednetwork.py @@ -427,7 +427,7 @@ class TestIsolatedNetwork(cloudstackTestCase): self.cleanup.append(network) self.assertEqual(network.state.lower() == ALLOCATED.lower(), True, - "Admin User is not able to create a network for for other users in other domain") + "Admin User is not able to create a network for other users in other domain") ## Test cases relating to createNetwork as domain admin user @@ -575,7 +575,7 @@ class TestIsolatedNetwork(cloudstackTestCase): except Exception as e: self.debug("When user tries to create network for users in their domain %s" % e) if not CloudstackAclException.verifyMsginException(e, CloudstackAclException.UNABLE_TO_LIST_NETWORK_ACCOUNT): - self.fail("Error message validation failed when when User tries to create network for other users in their domain ") + self.fail("Error message validation failed when User tries to create network for other users in their domain ") @attr("simulator_only", tags=["advanced"], required_hardware="false") def test_10_createNetwork_user_foruserinotherdomain(self): @@ -674,7 +674,7 @@ class TestIsolatedNetwork(cloudstackTestCase): self.cleanup.append(vm) self.assertEqual(vm.state.lower() == RUNNING.lower() and vm.account == self.account_d2a.name and vm.domainid == self.account_d2a.domainid, True, - "Admin User is not able to deploy VM for users users in other domain") + "Admin User is not able to deploy VM for users in other domain") @attr("simulator_only", tags=["advanced"], required_hardware="false") def test_13_1_deployvm_admin_foruserinotherdomain_crossnetwork(self): diff --git a/test/integration/component/test_acl_sharednetwork.py b/test/integration/component/test_acl_sharednetwork.py index 42f4a899e12..52209a378ab 100644 --- a/test/integration/component/test_acl_sharednetwork.py +++ b/test/integration/component/test_acl_sharednetwork.py @@ -949,7 +949,7 @@ class TestSharedNetwork(cloudstackTestCase): Validate that any other user in same domain is NOT allowed to deploy VM in a shared network created with scope="account" for an account """ - # deploy VM as user under the same domain but belonging to a different account from the acount that has a shared network with scope=account + # deploy VM as user under the same domain but belonging to a different account from the account that has a shared network with scope=account self.apiclient.connection.apiKey = self.user_d111b_apikey self.apiclient.connection.securityKey = self.user_d111b_secretkey diff --git a/test/integration/component/test_acl_sharednetwork_deployVM-impersonation.py b/test/integration/component/test_acl_sharednetwork_deployVM-impersonation.py index 1cb445b96fe..609af80b66c 100644 --- a/test/integration/component/test_acl_sharednetwork_deployVM-impersonation.py +++ b/test/integration/component/test_acl_sharednetwork_deployVM-impersonation.py @@ -1613,7 +1613,7 @@ class TestSharedNetworkImpersonation(cloudstackTestCase): Valiate that Domain admin is NOT able to deploy a VM for user in the same domain but belonging to a different account in a shared network with scope=account """ - # Deploy VM as user in a domain under the same domain but different account from the acount that has a shared network with scope=account + # Deploy VM as user in a domain under the same domain but different account from the account that has a shared network with scope=account self.apiclient.connection.apiKey = self.user_d1_apikey self.apiclient.connection.securityKey = self.user_d1_secretkey self.vmdata["name"] = self.acldata["vmD111B"]["name"] + "-shared-scope-domain-withsubdomainaccess-domain-admin" @@ -1714,7 +1714,7 @@ class TestSharedNetworkImpersonation(cloudstackTestCase): accountid=self.account_d2a.name, domainid=self.account_d2a.domainid ) - self.fail("Domain admin is able able to deploy a VM for an regular user from a differnt domain in a shared network with scope=account") + self.fail("Domain admin is able to deploy a VM for an regular user from a differnt domain in a shared network with scope=account") except Exception as e: self.debug("When a user from different domain deploys a VM in a shared network with scope=account %s" % e) if not CloudstackAclException.verifyMsginException(e, CloudstackAclException.NO_PERMISSION_TO_OPERATE_DOMAIN): diff --git a/test/integration/component/test_advancedsg_networks.py b/test/integration/component/test_advancedsg_networks.py index 4b3b8a32fa1..60567ae82fd 100644 --- a/test/integration/component/test_advancedsg_networks.py +++ b/test/integration/component/test_advancedsg_networks.py @@ -611,7 +611,7 @@ class TestNetworksInAdvancedSG(cloudstackTestCase): with same subnet and vlan""" # Steps, - # 1. create two different accouts + # 1. create two different accounts # 2. create account specific shared networks in both accounts with same subnet and vlan id # Validations, diff --git a/test/integration/component/test_affinity_groups_projects.py b/test/integration/component/test_affinity_groups_projects.py index 1c0b4c2bdd8..07811e79fde 100644 --- a/test/integration/component/test_affinity_groups_projects.py +++ b/test/integration/component/test_affinity_groups_projects.py @@ -1065,7 +1065,7 @@ class TestDeployVMAffinityGroups(cloudstackTestCase): """ test DeployVM in anti-affinity groups with more vms than hosts. """ - hosts = list_hosts(self.api_client, type="routing") + hosts = list_hosts(self.api_client, type="routing", zoneid=self.zone.id) aff_grp = self.create_aff_grp(self.account_api_client) vms = [] for host in hosts: diff --git a/test/integration/component/test_assign_vm.py b/test/integration/component/test_assign_vm.py index c2ee442e32e..e01f6fbc686 100644 --- a/test/integration/component/test_assign_vm.py +++ b/test/integration/component/test_assign_vm.py @@ -18,9 +18,9 @@ """ """ #Import Local Modules -from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.lib.base import (Account, +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import (Account, Domain, User, Project, diff --git a/test/integration/component/test_base_image_updation.py b/test/integration/component/test_base_image_updation.py index 234a86e1ce8..bd78082be3e 100644 --- a/test/integration/component/test_base_image_updation.py +++ b/test/integration/component/test_base_image_updation.py @@ -331,7 +331,7 @@ class TestBaseImageUpdate(cloudstackTestCase): except Exception as e: self.fail("Failed to reboot the virtual machines, %s" % e) - # Check if the the root disk was destroyed and recreated for isVolatile=True + # Check if the root disk was destroyed and recreated for isVolatile=True self.debug("Checking root disk of VM with isVolatile=True") vms = VirtualMachine.list( self.apiclient, @@ -358,7 +358,7 @@ class TestBaseImageUpdate(cloudstackTestCase): %(vm_with_reset.nic[0].ipaddress, self.vm_with_reset.nic[0].ipaddress) ) - # Check if the the root disk was not destroyed for isVolatile=False + # Check if the root disk was not destroyed for isVolatile=False self.debug("Checking root disk of VM with isVolatile=False") vms = VirtualMachine.list( self.apiclient, @@ -473,7 +473,7 @@ class TestBaseImageUpdate(cloudstackTestCase): %(vm_with_reset.nic[0].ipaddress, self.vm_with_reset.nic[0].ipaddress) ) - # Check if the the root disk was not destroyed for isVolatile=False + # Check if the root disk was not destroyed for isVolatile=False self.debug("Checking template id of VM with isVolatile=False") vms = VirtualMachine.list( self.apiclient, @@ -606,7 +606,7 @@ class TestBaseImageUpdate(cloudstackTestCase): except Exception as e: self.fail("Failed to reboot the virtual machine. Error: %s" % e) - # Check if the the root disk was destroyed and recreated for isVolatile=True + # Check if the root disk was destroyed and recreated for isVolatile=True self.debug("Checking whether root disk of VM with isVolatile=True was destroyed") vms = VirtualMachine.list( self.apiclient, diff --git a/test/integration/component/test_browse_volumes.py b/test/integration/component/test_browse_volumes.py index a1ee938bb28..1cf3bacfc93 100644 --- a/test/integration/component/test_browse_volumes.py +++ b/test/integration/component/test_browse_volumes.py @@ -2083,9 +2083,9 @@ class TestBrowseUploadVolume(cloudstackTestCase): vm4details = self.deploy_vm() - newvolumetodestoy_VM = self.browse_upload_volume() + newvolumetodestroy_VM = self.browse_upload_volume() - self.attach_volume(vm4details, newvolumetodestoy_VM.id) + self.attach_volume(vm4details, newvolumetodestroy_VM.id) self.destroy_vm(vm4details) @@ -2095,7 +2095,7 @@ class TestBrowseUploadVolume(cloudstackTestCase): self.expunge_vm(vm4details) cmd = deleteVolume.deleteVolumeCmd() - cmd.id = newvolumetodestoy_VM.id + cmd.id = newvolumetodestroy_VM.id self.apiclient.deleteVolume(cmd) self.debug( diff --git a/test/integration/component/test_configdrive.py b/test/integration/component/test_configdrive.py index 38e753480db..b092273cd5f 100644 --- a/test/integration/component/test_configdrive.py +++ b/test/integration/component/test_configdrive.py @@ -366,7 +366,7 @@ class ConfigDriveUtils: return None def _get_config_drive_data(self, ssh, file, name, fail_on_missing=True): - """Fetches the content of a file file on the config drive + """Fetches the content of a file on the config drive :param ssh: SSH connection to the VM :param file: path to the file to fetch @@ -1613,7 +1613,7 @@ class TestConfigDrive(cloudstackTestCase, ConfigDriveUtils): "List network should return a valid list" ) self.assertEqual(network.name, networks[0].name, - "Name of the network should match with with the " + "Name of the network should match with the " "returned list data" ) if state: @@ -1777,11 +1777,11 @@ class TestConfigDrive(cloudstackTestCase, ConfigDriveUtils): # And the VM is successfully deployed and is in the "Running" state # And there is no VR is deployed. # 4. And the user data in the ConfigDrive device is as expected - # 5. And the the vm password in the ConfigDrive device is as expected + # 5. And the vm password in the ConfigDrive device is as expected # 6. When I stop, reset the password, and start the VM # 7. Then I can login into the VM using the new password. - # 8. And the the vm password in the ConfigDrive device is the new one + # 8. And the vm password in the ConfigDrive device is the new one # 9. Verify various scenarios and check the data in configdriveIso # 10. Delete all the created objects (cleanup). @@ -2000,11 +2000,11 @@ class TestConfigDrive(cloudstackTestCase, ConfigDriveUtils): # And the VM is successfully deployed and is in the "Running" state # 4. And the user data in the ConfigDrive device is as expected - # 5. And the the vm password in the ConfigDrive device is as expected + # 5. And the vm password in the ConfigDrive device is as expected # 6. When I stop, reset the password, and start the VM # 7. Then I can login into the VM using the new password. - # 8. And the the vm password in the ConfigDrive device is the new one + # 8. And the vm password in the ConfigDrive device is the new one # 9. Verify various scenarios and check the data in configdriveIso # 10. Delete all the created objects (cleanup). diff --git a/test/integration/component/test_deploy_vm_userdata_multi_nic.py b/test/integration/component/test_deploy_vm_userdata_multi_nic.py index 766c96ac119..8743e9972f1 100644 --- a/test/integration/component/test_deploy_vm_userdata_multi_nic.py +++ b/test/integration/component/test_deploy_vm_userdata_multi_nic.py @@ -79,7 +79,7 @@ class TestDeployVmWithUserDataMultiNic(cloudstackTestCase): # Enable Network offering cls.network_offering_nouserdata.update(cls.api_client, state='Enabled') - # Create Network Offering with all the serices + # Create Network Offering with all the services cls.network_offering_all = NetworkOffering.create( cls.api_client, cls.test_data["isolated_network_offering"] diff --git a/test/integration/component/test_egress_fw_rules.py b/test/integration/component/test_egress_fw_rules.py index 7e045a6f845..780f9f2615d 100644 --- a/test/integration/component/test_egress_fw_rules.py +++ b/test/integration/component/test_egress_fw_rules.py @@ -18,10 +18,10 @@ """ """ #Import Local Modules -from nose.plugins.attrib import attr -from marvin.cloudstackTestCase import cloudstackTestCase +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase import unittest -from marvin.lib.base import (Account, +from marvin.lib.base import (Account, Domain, Router, Network, diff --git a/test/integration/component/test_escalations_instances.py b/test/integration/component/test_escalations_instances.py index 0004cce0b35..89c4f4ce2a6 100644 --- a/test/integration/component/test_escalations_instances.py +++ b/test/integration/component/test_escalations_instances.py @@ -1244,7 +1244,7 @@ class TestListInstances(cloudstackTestCase): status[0], "Listing VM's by name and zone failed" ) - # Verifying Verifying that the size of the list is 1 + # Verifying that the size of the list is 1 self.assertEqual( 1, len(list_vms), @@ -1404,7 +1404,7 @@ class TestListInstances(cloudstackTestCase): status[0], "Listing VM's by name and zone failed" ) - # Verifying Verifying that the size of the list is 1 + # Verifying that the size of the list is 1 self.assertEqual( 1, len(list_vms), @@ -1474,7 +1474,7 @@ class TestListInstances(cloudstackTestCase): status[0], "Listing VM's by name, account and zone failed" ) - # Verifying Verifying that the size of the list is 1 + # Verifying that the size of the list is 1 self.assertEqual( 1, len(list_vms), diff --git a/test/integration/component/test_interop_xd_ccp.py b/test/integration/component/test_interop_xd_ccp.py index ae5a9ae9ae7..dc579336590 100644 --- a/test/integration/component/test_interop_xd_ccp.py +++ b/test/integration/component/test_interop_xd_ccp.py @@ -571,7 +571,7 @@ class TestXDCCPInterop(cloudstackTestCase): id=self.volume.id ) - if list_volume_response1[0].virtualmachineid is None: + if list_volume_response1[0].virtualmachineid is None: self.skipTest("Check if volume is attached to the VM before detach") self.virtual_machine.detach_volume(self.user_api_client, self.volume) @@ -618,7 +618,7 @@ class TestXDCCPInterop(cloudstackTestCase): id=self.volume.id ) - if list_volume_response1[0].virtualmachineid is not None: + if list_volume_response1[0].virtualmachineid is not None: self.skipTest("Check if volume is detached before deleting") cmd = deleteVolume.deleteVolumeCmd() diff --git a/test/integration/component/test_ip_reservation.py b/test/integration/component/test_ip_reservation.py index 0ea01be4799..838aa30f7d0 100644 --- a/test/integration/component/test_ip_reservation.py +++ b/test/integration/component/test_ip_reservation.py @@ -1069,7 +1069,7 @@ class TestFailureScnarios(cloudstackTestCase): # 1. update guestvmcidr of isolated network (non persistent) # # validation - # should throw exception as network is not in implemented state as no vm is created + # should succeed although network is not in implemented state networkOffering = self.isolated_network_offering resultSet = createIsolatedNetwork(self, networkOffering.id) @@ -1078,9 +1078,7 @@ class TestFailureScnarios(cloudstackTestCase): else: isolated_network = resultSet[1] - with self.assertRaises(Exception): - isolated_network.update(self.apiclient, guestvmcidr="10.1.1.0/26") - return + isolated_network.update(self.apiclient, guestvmcidr="10.1.1.0/26") @attr(tags=["advanced"], required_hardware="false") def test_vm_create_after_reservation(self): diff --git a/test/integration/component/test_ldap.py b/test/integration/component/test_ldap.py index 56f844ac21a..8a9fd4cf5e6 100644 --- a/test/integration/component/test_ldap.py +++ b/test/integration/component/test_ldap.py @@ -52,12 +52,7 @@ class TestLdap(cloudstackTestCase): @classmethod def tearDownClass(cls): - try: - cleanup_resources(cls.api_client, cls._cleanup) - - except Exception as tde: - raise Exception("Warning: Exception during cleanup : %s" % tde) - return + super(TestLdap, cls).tearDownClass() def setUp(self): @@ -105,7 +100,7 @@ class TestLdap(cloudstackTestCase): self.apiClient.deleteAccount(deleteAcct) self.debug( - "Deleted the the following account name %s:" % + "Deleted the following account name %s:" % acct_name) if self.ldapconfRes == 1: diff --git a/test/integration/component/test_ldap_auto_import.py b/test/integration/component/test_ldap_auto_import.py index c2cc6b5a23c..c397386a3b7 100644 --- a/test/integration/component/test_ldap_auto_import.py +++ b/test/integration/component/test_ldap_auto_import.py @@ -379,7 +379,7 @@ class TestLdap(cloudstackTestCase): self.apiClient.deleteAccount(deleteAcct2) self.debug( - "Deleted the the following account name %s:" % + "Deleted the following account name %s:" % acct_name) except Exception as e: diff --git a/test/integration/component/test_multiple_ips_per_nic.py b/test/integration/component/test_multiple_ips_per_nic.py index 6c24ec1a78b..a9e1ca9a182 100644 --- a/test/integration/component/test_multiple_ips_per_nic.py +++ b/test/integration/component/test_multiple_ips_per_nic.py @@ -297,7 +297,7 @@ class TestBasicOperations(cloudstackTestCase): # Validations: # 1. Step 3 should succeed # 2. Step 4 should fail - # 3. Step 5 should should fail + # 3. Step 5 should fail # 4. Step 6 should fail self.account = Account.create( diff --git a/test/integration/component/test_multiple_nic_support.py b/test/integration/component/test_multiple_nic_support.py index cba1c4e24dc..7eb18ed59b7 100644 --- a/test/integration/component/test_multiple_nic_support.py +++ b/test/integration/component/test_multiple_nic_support.py @@ -14,7 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -""" tests for supporting multiple NIC's in advanced zone with security groups in cloudstack 4.14.0.0 +"""tests for supporting multiple NIC's in advanced zone with security groups in cloudstack 4.14.0.0 """ # Import Local Modules @@ -117,7 +117,7 @@ class TestMultipleNicSupport(cloudstackTestCase): cls.testdata["virtual_machine"]["template"] = cls.template.id if cls.zone.securitygroupsenabled: - # Enable networking for reaching to VM thorugh SSH + # Enable networking for reaching to VM through SSH security_group = SecurityGroup.create( cls.apiclient, cls.testdata["security_group"], @@ -302,9 +302,9 @@ class TestMultipleNicSupport(cloudstackTestCase): Steps: # 1. Create more than 1 isolated or shared network - # 2. Create a vm and select more than 1 network while deploying - # 3. Vm is deployed successfully with 1 nic from each network - # 4. All the vm's should be pingable + # 2. Create a VM and select more than 1 network while deploying + # 3. VM is deployed successfully with 1 NIC from each network + # 4. All the VM's should be pingable :return: """ virtual_machine = VirtualMachine.list( @@ -330,8 +330,8 @@ class TestMultipleNicSupport(cloudstackTestCase): Steps: # 1. Create a VM by selecting one default NIC # 2. Create few more isolated or shared networks - # 3. Add extra NIC's to the vm from the newly created networks - # 4. The deployed VM should have extra nic's added in the above + # 3. Add extra NIC's to the VM from the newly created networks + # 4. The deployed VM should have extra NIC's added in the above # step without any fail # 5. The IP's of the extra NIC's should be pingable :return: @@ -355,8 +355,8 @@ class TestMultipleNicSupport(cloudstackTestCase): Steps: # 1. Create a VM with more than 1 NIC # 2) Navigate to Instances->NIC->Edit Secondary IP's - # ->Aquire new Secondary IP" - # 3) Add as many secondary Ip as possible to the VM + # ->Acquire new Secondary IP" + # 3) Add as many secondary IP as possible to the VM # 4) Configure the secondary IP's by referring to "Configure # the secondary IP's" in the "Action Item" section :return: @@ -381,7 +381,7 @@ class TestMultipleNicSupport(cloudstackTestCase): # 2)Navigate to Instances-NIC's->Edit Secondary IP's # ->Acquire new Secondary IP # 3) Add secondary IP to all the NIC's of the VM - # 4) Confiugre the secondary IP's by referring to "Configure the + # 4) Configure the secondary IP's by referring to "Configure the # secondary IP's" in the "Action Item" section :return: """ @@ -441,10 +441,10 @@ class TestMultipleNicSupport(cloudstackTestCase): """ Stop and Start a VM with Multple NIC Steps: - # 1) Create a Vm with multiple NIC's + # 1) Create a VM with multiple NIC's # 2) Configure secondary IP's on the VM # 3) Try to stop/start the VM - # 4) Ping the IP's of the vm + # 4) Ping the IP's of the VM # 5) Remove Secondary IP from one of the NIC :return: """ @@ -484,16 +484,16 @@ class TestMultipleNicSupport(cloudstackTestCase): @attr(tags=["advancedsg"], required_hardware="false") def test_06_migrate_vm_with_multiple_nic(self): - """ Migrate a VM with Multple NIC + """ Migrate a VM with Multiple NIC Steps: - # 1) Create a Vm with multiple NIC's + # 1) Create a VM with multiple NIC's # 2) Configure secondary IP's on the VM # 3) Try to stop/start the VM - # 4) Ping the IP's of the vm + # 4) Ping the IP's of the VM :return: """ - # Skipping adding Secondary IP to NIC since its already + # Skipping adding Secondary IP to NIC since it's already # done in the previous test cases virtual_machine = VirtualMachine.list( @@ -543,7 +543,7 @@ class TestMultipleNicSupport(cloudstackTestCase): """ Remove secondary IP from any NIC Steps: # 1) Navigate to Instances - # 2) Select any vm + # 2) Select any VM # 3) NIC's ->Edit secondary IP's->Release IP # 4) The secondary IP should be successfully removed """ @@ -572,7 +572,7 @@ class TestMultipleNicSupport(cloudstackTestCase): def test_08_remove_nic_from_vm(self): """ Remove NIC from VM Steps: - # 1) Navigate to Instances->select any vm->NIC's->NIC 2 + # 1) Navigate to Instances->select any VM->NIC's->NIC 2 # ->Click on "X" button to remove the second NIC # 2) Remove other NIC's as well from the VM # 3) All the NIC's should be successfully removed from the VM @@ -599,16 +599,16 @@ class TestMultipleNicSupport(cloudstackTestCase): @attr(tags=["advancedsg"], required_hardware="false") def test_09_reboot_vm_with_multiple_nic(self): - """ Reboot a VM with Multple NIC + """ Reboot a VM with Multiple NIC Steps: - # 1) Create a Vm with multiple NIC's + # 1) Create a VM with multiple NIC's # 2) Configure secondary IP's on the VM # 3) Try to reboot the VM - # 4) Ping the IP's of the vm + # 4) Ping the IP's of the VM :return: """ - # Skipping adding Secondary IP to NIC since its already + # Skipping adding Secondary IP to NIC since it's already # done in the previous test cases virtual_machine = VirtualMachine.list( diff --git a/test/integration/component/test_project_limits.py b/test/integration/component/test_project_limits.py index 87bbcf70784..74c231e6b8e 100644 --- a/test/integration/component/test_project_limits.py +++ b/test/integration/component/test_project_limits.py @@ -1066,7 +1066,7 @@ class TestMaxProjectNetworks(cloudstackTestCase): # Steps for validation # 1. Fetch max.account.networks from configurations - # 2. Create an account. Create account more that max.accout.network + # 2. Create an account. Create account more that max.account.network # 3. Create network should fail self.debug("Creating project with '%s' as admin" % diff --git a/test/integration/component/test_project_resources.py b/test/integration/component/test_project_resources.py index f767af1788b..16d21dfd7cb 100644 --- a/test/integration/component/test_project_resources.py +++ b/test/integration/component/test_project_resources.py @@ -551,66 +551,59 @@ class TestTemplates(cloudstackTestCase): cls.hypervisor = cls.testClient.getHypervisorInfo() if cls.hypervisor.lower() in ['lxc']: raise unittest.SkipTest("create template from volume is not supported on %s" % cls.hypervisor.lower()) + cls._cleanup = [] cls.template = get_template( - cls.api_client, - cls.zone.id, - cls.services["ostype"] - ) + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) cls.services["server"]["zoneid"] = cls.zone.id # Create Domains, Account etc cls.domain = Domain.create( - cls.api_client, - cls.services["domain"] - ) + cls.api_client, + cls.services["domain"] + ) + cls._cleanup.append(cls.domain) cls.account = Account.create( - cls.api_client, - cls.services["account"], - domainid=cls.domain.id - ) + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup.append(cls.account) cls.user = Account.create( - cls.api_client, - cls.services["account"], - domainid=cls.domain.id - ) + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup.append(cls.user) # Create project as a domain admin cls.project = Project.create( - cls.api_client, - cls.services["project"], - account=cls.account.name, - domainid=cls.account.domainid - ) + cls.api_client, + cls.services["project"], + account=cls.account.name, + domainid=cls.account.domainid + ) + cls._cleanup.append(cls.project) cls.services["account"] = cls.account.name # Create Service offering and disk offerings etc cls.service_offering = ServiceOffering.create( - cls.api_client, - cls.services["service_offering"] - ) + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup.append(cls.service_offering) cls.userapiclient = cls.testClient.getUserApiClient( - UserName=cls.account.name, - DomainName=cls.domain.name - ) - - cls._cleanup = [ - cls.project, - cls.service_offering, - cls.account, - cls.user, - cls.domain - ] + UserName=cls.account.name, + DomainName=cls.domain.name + ) return @classmethod def tearDownClass(cls): - try: - #Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) - except Exception as e: - raise Exception("Warning: Exception during cleanup : %s" % e) - return + super(TestTemplates, cls).tearDownClass() def setUp(self): self.apiclient = self.testClient.getApiClient() @@ -619,12 +612,7 @@ class TestTemplates(cloudstackTestCase): return def tearDown(self): - try: - #Clean up, terminate the created instance, volumes and snapshots - cleanup_resources(self.apiclient, self.cleanup) - except Exception as e: - raise Exception("Warning: Exception during cleanup : %s" % e) - return + super(TestTemplates, self).tearDown() @attr(tags=["advanced", "basic", "sg", "eip", "advancedns"], required_hardware="false") def test_04_public_private_template_use_in_project(self): diff --git a/test/integration/component/test_ps_resize_volume.py b/test/integration/component/test_ps_resize_volume.py index 4c8b0ef82a6..29adfb48c3b 100644 --- a/test/integration/component/test_ps_resize_volume.py +++ b/test/integration/component/test_ps_resize_volume.py @@ -16,7 +16,7 @@ # under the License. """ P1 tests for testing resize volume functionality with primary storage - imit constraints on account/domain + limit constraints on account/domain Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/ Limit+Resources+to+domain+or+accounts @@ -254,7 +254,7 @@ class TestResizeVolume(cloudstackTestCase): # 3. Deploy a VM without any disk offering (only root disk) # 4. Create a volume of 5 GB in the account and attach it to the VM # 5. Try to (resize) the volume to 20 GB - # 6. Resize opearation should fail""" + # 6. Resize operation should fail""" # Setting up account and domain hierarchy result = self.setupAccounts() @@ -318,7 +318,7 @@ class TestResizeVolume(cloudstackTestCase): # 3. Deploy a VM without any disk offering (only root disk) # 4. Create a volume of 5 GB in the account and attach it to the VM # 5. Try to (resize) the volume to 20 GB - # 6. Resize opearation should fail""" + # 6. Resize operation should fail""" # Setting up account and domain hierarchy result = self.setupAccounts() diff --git a/test/integration/component/test_resource_limit_tags.py b/test/integration/component/test_resource_limit_tags.py new file mode 100644 index 00000000000..916abff4db8 --- /dev/null +++ b/test/integration/component/test_resource_limit_tags.py @@ -0,0 +1,692 @@ +# 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. +""" BVT tests for resource limit tags functionalities +""" +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.cloudstackAPI import (listCapacity, + listResourceLimits, + updateResourceLimit, + updateResourceCount) +from marvin.lib.base import (Host, + StoragePool, + Account, + Domain, + Zone, + ServiceOffering, + Template, + DiskOffering, + VirtualMachine, + Volume, + Configurations) +from marvin.lib.common import (get_domain, + get_zone, + get_template) +from marvin.codes import FAILED +from marvin.cloudstackException import CloudstackAPIException +from nose.plugins.attrib import attr +import logging +# Import System modules +import math +import random + + +_multiprocess_shared_ = True +MAX_VM_LIMIT = 2 +MAX_RAM_VM_LIMIT = 3 +MAX_DATA_VOLUME_LIMIT = 3 +MAX_PS_DATA_VOLUME_LIMIT = 2 + +class TestResourceLimitTags(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestResourceLimitTags, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.hypervisor = testClient.getHypervisorInfo() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + + cls._cleanup = [] + cls.logger = logging.getLogger('TestResourceLimitTags') + + template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"]) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + + # Set Zones and disk offerings + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["small"]["template"] = template.id + + cls.host_tags = ['htag1', 'htag2', 'htag3'] + cls.host_tags_supporting_types = [0, 8, 9] + Configurations.update(cls.apiclient, + "resource.limit.host.tags", + value=','.join(cls.host_tags) + ) + cls.storage_tags = ['stag1', 'stag2', 'stag3'] + cls.storage_tags_supporting_types = [2, 10] + Configurations.update(cls.apiclient, + "resource.limit.storage.tags", + value=','.join(cls.storage_tags) + ) + + hosts = Host.list(cls.apiclient, type='Routing') + cls.original_host_tag_map = {} + for idx, host in enumerate(hosts): + cls.original_host_tag_map[host.id] = host.hosttags + if idx % 2 == 0: + Host.update(cls.apiclient, id=host.id, hosttags=cls.host_tags[1]) + else: + Host.update(cls.apiclient, id=host.id, hosttags='') + + pools = StoragePool.list(cls.apiclient) + cls.original_storage_pool_tag_map = {} + for idx, pool in enumerate(pools): + cls.original_storage_pool_tag_map[pool.id] = pool.tags + if idx % 2 == 0: + StoragePool.update(cls.apiclient, id=pool.id, tags=cls.storage_tags[1]) + else: + StoragePool.update(cls.apiclient, id=pool.id, tags='') + + + cls.untagged_compute_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["tiny"]) + cls._cleanup.append(cls.untagged_compute_offering) + + host_tagged_compute_offering_service = cls.services["service_offerings"]["tiny"].copy() + host_tagged_compute_offering_service["hosttags"] = cls.host_tags[1] + cls.host_tagged_compute_offering = ServiceOffering.create( + cls.apiclient, + host_tagged_compute_offering_service) + cls._cleanup.append(cls.host_tagged_compute_offering) + + host_storage_tagged_compute_offering_service = cls.services["service_offerings"]["tiny"].copy() + host_storage_tagged_compute_offering_service["hosttags"] = cls.host_tags[1] + host_storage_tagged_compute_offering_service["tags"] = cls.storage_tags[1] + cls.host_storage_tagged_compute_offering = ServiceOffering.create( + cls.apiclient, + host_storage_tagged_compute_offering_service) + cls._cleanup.append(cls.host_storage_tagged_compute_offering) + + cls.untagged_disk_offering = DiskOffering.create( + cls.apiclient, + cls.services["disk_offering"] + ) + cls._cleanup.append(cls.untagged_disk_offering) + + tagged_disk_offering_service = cls.services["disk_offering"].copy() + tagged_disk_offering_service["tags"] = cls.storage_tags[1] + cls.tagged_disk_offering = DiskOffering.create( + cls.apiclient, + tagged_disk_offering_service + ) + cls._cleanup.append(cls.tagged_disk_offering) + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + @classmethod + def tearDownClass(cls): + for host_id in cls.original_host_tag_map: + tag = cls.original_host_tag_map[host_id] + if tag is None: + tag = '' + Host.update(cls.apiclient, id=host_id, hosttags=tag) + for pool_id in cls.original_storage_pool_tag_map: + tag = cls.original_storage_pool_tag_map[pool_id] + if tag is None: + tag = '' + StoragePool.update(cls.apiclient, id=pool_id, tags=tag) + super(TestResourceLimitTags, cls).tearDownClass() + + def setUp(self): + self.cleanup = [] + self.tag_type = random.choice(['host', 'storage']) + self.domain1 = Domain.create( + self.apiclient, + self.services["domain"]) + self.cleanup.append(self.domain1) + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain1.id) + self.cleanup.append(self.account) + self.userapiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain + ) + + def tearDown(self): + super(TestResourceLimitTags, self).tearDown() + + def check_entity_tagged_resource_count(self, taggedresources): + self.assertNotEqual( + taggedresources, + None, + "Check tagged resources list" + ) + for type in self.host_tags_supporting_types: + filtered_limits = list(filter(lambda x: x.resourcetype == type, taggedresources)) + self.assertEqual( + len(filtered_limits), + len(self.host_tags) + ) + for limit in filtered_limits: + self.assertTrue(limit.tag in self.host_tags) + for type in self.storage_tags_supporting_types: + filtered_limits = list(filter(lambda x: x.resourcetype == type, taggedresources)) + self.assertEqual( + len(filtered_limits), + len(self.storage_tags) + ) + for limit in filtered_limits: + self.assertTrue(limit.tag in self.storage_tags) + + def verify_entity_resource_limits(self, limits, resource_type, tag, max): + if type(limits) is list: + if len(limits) == 0: + self.fail("Empty limits list") + limits = limits[0] + self.assertNotEqual( + limits, + None, + "Check tagged limits list" + ) + self.assertEqual(max, + limits.max, + "Max value not equal" + ) + self.assertEqual(tag, + limits.tag, + "Tag value not equal" + ) + self.assertEqual(str(resource_type), + limits.resourcetype, + "Resource type value not equal" + ) + + def update_domain_account_tagged_limit(self, resource_type, tag, max, for_account=False): + cmd = updateResourceLimit.updateResourceLimitCmd() + cmd.domainid = self.domain1.id + if for_account: + cmd.account = self.account.name + cmd.resourcetype = resource_type + cmd.tag = tag + cmd.max = max + response = self.apiclient.updateResourceLimit(cmd) + return response + + def list_domain_account_tagged_limit(self, resource_type, tag, for_account=False): + cmd = listResourceLimits.listResourceLimitsCmd() + cmd.domainid = self.domain1.id + if for_account: + cmd.account = self.account.name + cmd.resourcetype = resource_type + cmd.tag = tag + response = self.apiclient.listResourceLimits(cmd) + return response + + def run_test_update_domain_account_tagged_limit(self, for_account=False): + tags = self.host_tags + resource_types = self.host_tags_supporting_types + if self.tag_type == 'storage': + tags = self.storage_tags + resource_types = self.storage_tags_supporting_types + tag = random.choice(tags) + resource_type = random.choice(resource_types) + max = random.randrange(5, 10) + + response = self.update_domain_account_tagged_limit(resource_type, tag, max, for_account) + self.verify_entity_resource_limits(response, resource_type, tag, max) + + response = self.list_domain_account_tagged_limit(resource_type, tag, for_account) + self.verify_entity_resource_limits(response, resource_type, tag, max) + + def run_test_domain_account_tagged_vm_limit(self, resource_type, max): + counter = 0 + increment = 1 + if resource_type == 8: + increment = 100 + elif resource_type == 9: + increment = 128 + vm_to_delete = None + while counter < max: + self.vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.host_tagged_compute_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.vm) + counter = counter + increment + if vm_to_delete is None: + vm_to_delete = self.vm + # Tagged VM shouldn't be deployed + try: + self.vm2 = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.host_tagged_compute_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.vm2) + self.fail("VM deployed over tagged limit for domain/account") + except CloudstackAPIException as e: + self.logger.debug("Over tagged limit VM for domain/account deployment failed with : %s" % e) + # Untagged VM should be deployed fine + self.vm3 = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.untagged_compute_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.vm3) + # Delete one of the tagged VMs and check if a new tagged VM is deployed + vm_to_delete.delete(self.apiclient, expunge=True) + for idx, x in enumerate(self.cleanup): + if x.id == vm_to_delete.id: + self.cleanup.pop(idx) + break + self.vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.host_tagged_compute_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.vm) + + def run_test_domain_account_tagged_volume_limit(self, resource_type, max): + increment = 1 + if resource_type == 10: + increment = 1*1024*1024*1024 + volume_to_delete = None + self.vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.host_storage_tagged_compute_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.vm) + counter = 1 + if resource_type == 10: + counter = self.root_volume_size + while counter < max: + self.volume = Volume.create( + self.userapiclient, + self.services["volume"], + diskofferingid=self.tagged_disk_offering.id, + zoneid=self.zone.id + ) + self.cleanup.append(self.volume) + counter = counter + increment + if volume_to_delete is None: + volume_to_delete = self.volume + # Tagged VM shouldn't be deployed + try: + self.volume2 = Volume.create( + self.userapiclient, + self.services["volume"], + diskofferingid=self.tagged_disk_offering.id, + zoneid=self.zone.id + ) + self.cleanup.append(self.volume2) + self.fail("Volume created over tagged limit for domain/account") + except CloudstackAPIException as e: + self.logger.debug("Over tagged limit volume for domain/account deployment failed with : %s" % e) + # Untagged VM should be deployed fine + self.volume3 = Volume.create( + self.userapiclient, + self.services["volume"], + diskofferingid=self.untagged_disk_offering.id, + zoneid=self.zone.id + ) + self.cleanup.append(self.volume3) + # Delete one of the tagged volumes and check if a new tagged volume is deployed + volume_to_delete.delete(self.apiclient) + for idx, x in enumerate(self.cleanup): + if x.id == volume_to_delete.id: + self.cleanup.pop(idx) + break + self.volume = Volume.create( + self.userapiclient, + self.services["volume"], + diskofferingid=self.tagged_disk_offering.id, + zoneid=self.zone.id + ) + self.cleanup.append(self.volume) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_01_check_list_capacity(self): + """Test to verify listing capacity with tags + """ + # Validate the following: + # 1. List capacity with a valid tag + # 2. Verify + + cmd = listCapacity.listCapacityCmd() + cmd.tag = self.host_tags[1] + response = self.apiclient.listCapacity(cmd) + self.assertNotEqual( + response, + None, + "Check capacity is listed" + ) + self.assertTrue(len(response) > 0) + cmd.tag = "INVALID" + response = self.apiclient.listCapacity(cmd) + self.assertEqual( + response, + None, + "Check capacity is listed incorrectly" + ) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_02_check_list_domain_tagged_limit(self): + """Test to verify listing domain tagged resource counts + """ + + domain = Domain.list( + self.apiclient, + id = self.domain1.id + )[0] + self.check_entity_tagged_resource_count(domain.taggedresources) + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_03_check_list_account_tagged_limit(self): + """Test to verify listing account tagged resource counts + """ + + account = Account.list( + self.apiclient, + id = self.account.id + )[0] + self.check_entity_tagged_resource_count(account.taggedresources) + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_04_check_update_domain_tagged_limit(self): + """Test to verify listing domain tagged resource limits + """ + self.run_test_update_domain_account_tagged_limit() + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_05_check_update_account_tagged_limit(self): + """Test to verify listing domain tagged resource limits + """ + self.run_test_update_domain_account_tagged_limit(True) + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_06_verify_domain_tagged_vm_limit(self): + """Test to verify domain tagged resource limits working + 1. Check if VM(s) can be deployed within tagged limits for domain + 2. Check if VM(s) can not be deployed over tagged limits for domain + 3. Check if VM(s) can be deployed without tag for domain + """ + resource_type = 0 + tag = self.host_tags[1] + max = MAX_VM_LIMIT + self.update_domain_account_tagged_limit(resource_type, tag, max) + self.run_test_domain_account_tagged_vm_limit(resource_type, max) + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_07_verify_account_tagged_vm_limit(self): + """Test to verify account tagged resource limits working + 1. Check if VM(s) can be deployed within tagged limits for account + 2. Check if VM(s) can not be deployed over tagged limits for account + 3. Check if VM(s) can be deployed without tag for account + """ + resource_type = 9 + tag = self.host_tags[1] + max = self.host_tagged_compute_offering.memory * MAX_RAM_VM_LIMIT + self.update_domain_account_tagged_limit(resource_type, tag, max) + self.run_test_domain_account_tagged_vm_limit(resource_type, max) + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_08_verify_domain_tagged_volume_limit(self): + """Test to verify domain tagged resource limits working + 1. Check if volume(s) can be deployed within tagged limits for domain + 2. Check if volume(s) can not be deployed over tagged limits for domain + 3. Check if volume(s) can be deployed without tag for domain + """ + resource_type = 2 + tag = self.storage_tags[1] + max = MAX_DATA_VOLUME_LIMIT + self.update_domain_account_tagged_limit(resource_type, tag, max) + self.run_test_domain_account_tagged_volume_limit(resource_type, max) + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_09_verify_account_tagged_volume_limit(self): + """Test to verify account tagged resource limits working + 1. Check if volume(s) can be deployed within tagged limits for domain + 2. Check if volume(s) can not be deployed over tagged limits for domain + 3. Check if volume(s) can be deployed without tag for domain + """ + self.test_vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.untagged_compute_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.test_vm) + volume = Volume.list( + self.userapiclient, + virtualmachineid=self.test_vm.id, + listall=True, + type='ROOT' + )[0] + self.root_volume_size = volume['size'] + resource_type = 10 + tag = self.storage_tags[1] + max = math.ceil(self.root_volume_size/(1024*1024*1024)) + MAX_PS_DATA_VOLUME_LIMIT + self.update_domain_account_tagged_limit(resource_type, tag, max, True) + self.run_test_domain_account_tagged_volume_limit(resource_type, (max*1024*1024*1024)) + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_10_verify_assign_vm_limit(self): + """Test to verify limits are updated on changing VM owner + """ + self.donor_account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain1.id) + self.cleanup.append(self.donor_account) + # Pass mode=basic to avoid creation of PF rules for the VM + self.vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.host_storage_tagged_compute_offering.id, + mode='basic' + ) + self.cleanup.append(self.vm) + self.vm.stop(self.userapiclient) + acc = Account.list( + self.userapiclient, + id=self.account.id + )[0] + tags = [self.host_storage_tagged_compute_offering.hosttags, self.host_storage_tagged_compute_offering.storagetags] + source_account_usage_before = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + self.vm.assign_virtual_machine(self.apiclient, self.donor_account.name ,self.domain1.id) + acc = Account.list( + self.userapiclient, + id=self.account.id + )[0] + source_account_usage_after = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + for usage in source_account_usage_after: + self.assertTrue(usage.total == 0, "Usage for %s with tag %s is not zero for source account" % (usage.resourcetypename, usage.tag)) + acc = Account.list( + self.apiclient, + id=self.donor_account.id + )[0] + target_account_usage = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + for idx, usage in enumerate(target_account_usage): + expected_usage = source_account_usage_before[idx] + self.assertTrue(usage.total == expected_usage.total, "Usage for %s with tag %s is not matching for target account" % (usage.resourcetypename, usage.tag)) + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_11_verify_scale_vm_limit(self): + """Test to verify limits are updated on scaling VM + """ + scale_compute_offering_service = self.services["service_offerings"]["tiny"].copy() + scale_compute_offering_service["cpunumber"] = 2 * self.host_tagged_compute_offering.cpunumber + scale_compute_offering_service["memory"] = 2 * self.host_tagged_compute_offering.memory + scale_compute_offering_service["hosttags"] = self.host_tagged_compute_offering.hosttags + self.scale_compute_offering = ServiceOffering.create( + self.apiclient, + scale_compute_offering_service) + self.cleanup.append(self.scale_compute_offering) + + self.vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.host_tagged_compute_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.vm) + self.vm.stop(self.userapiclient) + acc = Account.list( + self.userapiclient, + id=self.account.id + )[0] + tags = [self.host_tagged_compute_offering.hosttags] + account_usage_before = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + self.vm.scale(self.userapiclient, self.scale_compute_offering.id) + acc = Account.list( + self.userapiclient, + id=self.account.id + )[0] + account_usage_after = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + for idx, usage in enumerate(account_usage_after): + expected_usage_total = account_usage_before[idx].total + if usage.resourcetype in [8, 9]: + expected_usage_total = 2 * expected_usage_total + self.assertTrue(usage.total == expected_usage_total, "Usage for %s with tag %s is not matching for target account" % (usage.resourcetypename, usage.tag)) + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_12_verify_scale_volume_limit(self): + """Test to verify limits are updated on scaling volume + """ + scale_disk_offering_service = self.services["disk_offering"].copy() + scale_disk_offering_service["tags"] = self.tagged_disk_offering.tags + scale_disk_offering_service["disksize"] = 2 * self.tagged_disk_offering.disksize + self.scale_disk_offering = DiskOffering.create( + self.apiclient, + scale_disk_offering_service + ) + self.cleanup.append(self.scale_disk_offering) + + self.vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.host_tagged_compute_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.vm) + self.volume = Volume.create( + self.userapiclient, + self.services["volume"], + diskofferingid=self.tagged_disk_offering.id, + zoneid=self.zone.id + ) + self.vm.attach_volume( + self.userapiclient, + volume=self.volume + ) + self.vm.detach_volume( + self.userapiclient, + volume=self.volume + ) + acc = Account.list( + self.userapiclient, + id=self.account.id + )[0] + tags = [self.tagged_disk_offering.tags] + account_usage_before = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + self.volume.resize( + self.userapiclient, + diskofferingid=self.scale_disk_offering.id + ) + acc = Account.list( + self.userapiclient, + id=self.account.id + )[0] + account_usage_after = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + for idx, usage in enumerate(account_usage_after): + expected_usage_total = account_usage_before[idx].total + if usage.resourcetype in [10]: + expected_usage_total = 2 * expected_usage_total + self.assertTrue(usage.total == expected_usage_total, "Usage for %s with tag %s is not matching for target account" % (usage.resourcetypename, usage.tag)) + return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_13_verify_restore_vm_limit(self): + """Test to verify limits are updated on restoring VM + """ + hypervisor = self.hypervisor.lower() + restore_template_service = self.services["test_templates"][ + hypervisor if hypervisor != 'simulator' else 'xenserver'].copy() + restore_template = Template.register(self.apiclient, restore_template_service, zoneid=self.zone.id, hypervisor=hypervisor, templatetag=self.host_tags[1]) + restore_template.download(self.apiclient) + self.cleanup.append(restore_template) + + self.vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + templateid=restore_template.id, + serviceofferingid=self.host_storage_tagged_compute_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.vm) + old_root_vol = Volume.list(self.userapiclient, virtualmachineid=self.vm.id)[0] + + acc = Account.list( + self.userapiclient, + id=self.account.id + )[0] + tags = [self.host_storage_tagged_compute_offering.hosttags, self.host_storage_tagged_compute_offering.storagetags] + account_usage_before = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + + self.vm.restore(self.userapiclient, restore_template.id, rootdisksize=16, expunge=True) + acc = Account.list( + self.userapiclient, + id=self.account.id + )[0] + + account_usage_after = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + for idx, usage in enumerate(account_usage_after): + expected_usage_total = account_usage_before[idx].total + if usage.resourcetype in [10]: + expected_usage_total = expected_usage_total - old_root_vol.size + 16 * 1024 * 1024 * 1024 + self.assertTrue(usage.total == expected_usage_total, "Usage for %s with tag %s is not matching for target account" % (usage.resourcetypename, usage.tag)) + return diff --git a/test/integration/component/test_resource_limits.py b/test/integration/component/test_resource_limits.py index e2efc4344a9..25518257a33 100644 --- a/test/integration/component/test_resource_limits.py +++ b/test/integration/component/test_resource_limits.py @@ -1435,7 +1435,7 @@ class TestMaxAccountNetworks(cloudstackTestCase): # Steps for validation # 1. Fetch max.account.networks from configurations - # 2. Create an account. Create account more that max.accout.network + # 2. Create an account. Create account more that max.account.network # 3. Create network should fail config = Configurations.list( diff --git a/test/integration/component/test_rootvolume_resize.py b/test/integration/component/test_rootvolume_resize.py index 7e58d1e3f42..fa2d4a018cd 100644 --- a/test/integration/component/test_rootvolume_resize.py +++ b/test/integration/component/test_rootvolume_resize.py @@ -647,7 +647,7 @@ class TestResizeVolume(cloudstackTestCase): self.assertEqual(virtualmachine_snapshot.id, virtulmachine_snapshot_list[0].id, "Virtual Machine Snapshot id do not match") - except Exception as e: + except Exception as e: raise Exception("Issue CLOUDSTACK-10080: Exception while performing" " vmsnapshot: %s" % e) else: diff --git a/test/integration/component/test_snapshot_copy.py b/test/integration/component/test_snapshot_copy.py new file mode 100644 index 00000000000..7b9531a3433 --- /dev/null +++ b/test/integration/component/test_snapshot_copy.py @@ -0,0 +1,351 @@ +# 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. +""" BVT tests for volume snapshot copy functionality +""" +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.cloudstackAPI import (createSnapshot, + deleteSnapshot, + copySnapshot, + createVolume, + createTemplate, + listOsTypes) +from marvin.lib.utils import (cleanup_resources, + random_gen) +from marvin.lib.base import (Account, + Zone, + ServiceOffering, + DiskOffering, + VirtualMachine, + Volume, + Snapshot, + Template) +from marvin.lib.common import (get_domain, + get_zone, + get_template) +from marvin.lib.decoratorGenerators import skipTestIf +from marvin.codes import FAILED, PASS +from nose.plugins.attrib import attr +import logging +# Import System modules +import math + + +_multiprocess_shared_ = True + + +class TestSnapshotCopy(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestSnapshotCopy, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + + cls._cleanup = [] + cls.logger = logging.getLogger('TestSnapshotCopy') + cls.testsNotSupported = False + cls.zones = Zone.list(cls.apiclient) + enabled_core_zones = [] + if not isinstance(cls.zones, list): + cls.testsNotSupported = True + elif len(cls.zones) < 2: + cls.testsNotSupported = True + else: + for z in cls.zones: + if z.type == 'Core' and z.allocationstate == 'Enabled': + enabled_core_zones.append(z) + if len(enabled_core_zones) < 2: + cls.testsNotSupported = True + + if cls.testsNotSupported == True: + self.logger.info("Unsupported") + return + + cls.additional_zone = None + for z in enabled_core_zones: + if z.id != cls.zone.id: + cls.additional_zone = z + + template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"]) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + + # Set Zones and disk offerings + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["small"]["template"] = template.id + cls.services["iso"]["zoneid"] = cls.zone.id + + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + domainid=cls.domain.id) + cls._cleanup.append(cls.account) + + compute_offering_service = cls.services["service_offerings"]["tiny"].copy() + cls.service_offering = ServiceOffering.create( + cls.apiclient, + compute_offering_service) + cls._cleanup.append(cls.service_offering) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + cls.virtual_machine = VirtualMachine.create( + cls.apiclient, + cls.services["virtual_machine"], + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.service_offering.id, + mode=cls.services["mode"] + ) + cls._cleanup.append(cls.virtual_machine) + cls.volume = Volume.list( + cls.apiclient, + virtualmachineid=cls.virtual_machine.id, + type='ROOT', + listall=True + )[0] + + @classmethod + def tearDownClass(cls): + super(TestSnapshotCopy, cls).tearDownClass() + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.userapiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain + ) + self.dbclient = self.testClient.getDbConnection() + self.snapshot_id = None + self.cleanup = [] + + def tearDown(self): + super(TestSnapshotCopy, self).tearDown() + + def create_snapshot(self, apiclient, zoneids): + cmd = createSnapshot.createSnapshotCmd() + cmd.volumeid = self.volume.id + cmd.account = self.account.name + cmd.domainid = self.account.domainid + if zoneids: + cmd.zoneids = zoneids + snapshot = Snapshot(apiclient.createSnapshot(cmd).__dict__) + self.cleanup.append(snapshot) + return snapshot + + def delete_snapshot(self, apiclient, snapshot_id, zone_id=None): + cmd = deleteSnapshot.deleteSnapshotCmd() + cmd.id = snapshot_id + if zone_id: + cmd.zoneid = zone_id + apiclient.deleteSnapshot(cmd) + + def copy_snapshot(self, apiclient, snapshot_id, zone_ids, source_zone_id=None): + cmd = copySnapshot.copySnapshotCmd() + cmd.id = snapshot_id + cmd.destzoneids = zone_ids + if source_zone_id: + cmd.sourcezoneid = source_zone_id + return apiclient.copySnapshot(cmd) + + def create_snapshot_volume(self, apiclient, snapshot_id, zone_id=None, disk_offering_id=None): + cmd = createVolume.createVolumeCmd() + cmd.name = "-".join(["VolumeFromSnap", random_gen()]) + cmd.snapshotid = snapshot_id + if zone_id: + cmd.zoneid = zone_id + if disk_offering_id: + cmd.diskofferingid = disk_offering_id + volume_from_snapshot = Volume(apiclient.createVolume(cmd).__dict__) + self.cleanup.append(volume_from_snapshot) + return volume_from_snapshot + + def create_snapshot_template(self, apiclient, services, snapshot_id, zone_id): + cmd = createTemplate.createTemplateCmd() + cmd.displaytext = "TemplateFromSnap" + name = "-".join([cmd.displaytext, random_gen()]) + cmd.name = name + if "ostypeid" in services: + cmd.ostypeid = services["ostypeid"] + elif "ostype" in services: + # Find OSTypeId from Os type + sub_cmd = listOsTypes.listOsTypesCmd() + sub_cmd.description = services["ostype"] + ostypes = apiclient.listOsTypes(sub_cmd) + + if not isinstance(ostypes, list): + self.fail("Unable to find Ostype id with desc: %s" % + services["ostype"]) + cmd.ostypeid = ostypes[0].id + else: + self.fail("Unable to find Ostype is required for creating template") + + cmd.isfeatured = True + cmd.ispublic = True + cmd.isextractable = False + + cmd.snapshotid = snapshot_id + cmd.zoneid = zone_id + apiclient.createTemplate(cmd) + templates = Template.list(apiclient, name=name, templatefilter="self") + if not isinstance(templates, list) and len(templates) < 0: + self.fail("Unable to find created template with name %s" % name) + template = Template(templates[0].__dict__) + self.cleanup.append(template) + return template + + def verify_snapshot_copies(self, snapshot_id, zone_ids): + snapshot_entries = Snapshot.list(self.userapiclient, id=snapshot_id, showunique=False, locationtype="Secondary") + if not isinstance(snapshot_entries, list): + self.fail("Unable to list snapshot for multiple zones") + elif len(snapshot_entries) != len(zone_ids): + self.fail("Undesired list snapshot size for multiple zones") + for zone_id in zone_ids: + zone_found = False + for entry in snapshot_entries: + if entry.zoneid == zone_id: + zone_found = True + break + if zone_found == False: + self.fail("Unable to find snapshot entry for the zone ID: %s" % zone_id) + + @skipTestIf("testsNotSupported") + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_01_take_snapshot_multi_zone(self): + """Test to take volume snapshot in multiple zones + """ + # Validate the following: + # 1. Take snapshot in multiple zone + # 2. Verify + + snapshot = self.create_snapshot(self.userapiclient, [str(self.additional_zone.id)]) + self.snapshot_id = snapshot.id + self.verify_snapshot_copies(self.snapshot_id, [self.zone.id, self.additional_zone.id]) + return + + @skipTestIf("testsNotSupported") + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_02_copy_snapshot_multi_zone(self): + """Test to take volume snapshot in a zone and then copy + """ + # Validate the following: + # 1. Take snapshot in the native zone + # 2. Copy snapshot in the additional zone + # 3. Verify + + snapshot = self.create_snapshot(self.userapiclient, None) + self.snapshot_id = snapshot.id + self.copy_snapshot(self.userapiclient, self.snapshot_id, [str(self.additional_zone.id)], self.zone.id) + self.verify_snapshot_copies(self.snapshot_id, [self.zone.id, self.additional_zone.id]) + return + + @skipTestIf("testsNotSupported") + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_03_take_snapshot_multi_zone_delete_single_zone(self): + """Test to take volume snapshot in multiple zones and delete from one zone + """ + # Validate the following: + # 1. Take snapshot in multiple zone + # 2. Verify + # 3. Delete from one zone + # 4. Verify + + snapshot = self.create_snapshot(self.userapiclient, [str(self.additional_zone.id)]) + self.snapshot_id = snapshot.id + self.verify_snapshot_copies(self.snapshot_id, [self.zone.id, self.additional_zone.id]) + self.delete_snapshot(self.userapiclient, self.snapshot_id, self.zone.id) + self.verify_snapshot_copies(self.snapshot_id, [self.additional_zone.id]) + return + + @skipTestIf("testsNotSupported") + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_04_copy_snapshot_multi_zone_delete_all(self): + """Test to take volume snapshot in a zone, copy in another zone and delete for all + """ + # Validate the following: + # 1. Take snapshot in the native zone + # 2. Copy snapshot in the additional zone + # 3. Verify + # 4. Delete for all zones + # 5. Verify + + snapshot = self.create_snapshot(self.userapiclient, None) + self.snapshot_id = snapshot.id + self.copy_snapshot(self.userapiclient, self.snapshot_id, [str(self.additional_zone.id)], self.zone.id) + self.verify_snapshot_copies(self.snapshot_id, [self.zone.id, self.additional_zone.id]) + self.delete_snapshot(self.userapiclient, self.snapshot_id) + snapshot_entries = Snapshot.list(self.userapiclient, id=snapshot.id) + if snapshot_entries and isinstance(snapshot_entries, list) and len(snapshot_entries) > 0: + self.fail("Snapshot delete for all zones failed") + self.cleanup.remove(snapshot) + return + + @skipTestIf("testsNotSupported") + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_05_take_snapshot_multi_zone_create_volume_additional_zone(self): + """Test to take volume snapshot in multiple zones and create a volume in one of the additional zones + """ + # Validate the following: + # 1. Take snapshot in multiple zone + # 2. Verify + # 3. Create volume in the additional zone + # 4. Verify volume zone + + snapshot = self.create_snapshot(self.userapiclient, [str(self.additional_zone.id)]) + self.snapshot_id = snapshot.id + self.verify_snapshot_copies(self.snapshot_id, [self.zone.id, self.additional_zone.id]) + disk_offering_id = None + if snapshot.volumetype == 'ROOT': + service = self.services["disk_offering"] + service["disksize"] = math.ceil(snapshot.virtualsize/(1024*1024*1024)) + self.disk_offering = DiskOffering.create( + self.apiclient, + service + ) + self.cleanup.append(self.disk_offering) + disk_offering_id = self.disk_offering.id + self.volume = self.create_snapshot_volume(self.userapiclient, self.snapshot_id, self.additional_zone.id, disk_offering_id) + if self.additional_zone.id != self.volume.zoneid: + self.fail("Volume from snapshot not created in the additional zone") + return + + @skipTestIf("testsNotSupported") + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_06_take_snapshot_multi_zone_create_template_additional_zone(self): + """Test to take volume snapshot in multiple zones and create a volume in one of the additional zones + """ + # Validate the following: + # 1. Take snapshot in multiple zone + # 2. Verify + # 3. Create template in the additional zone + # 4. Verify template zone + + snapshot = self.create_snapshot(self.userapiclient, [str(self.additional_zone.id)]) + self.snapshot_id = snapshot.id + self.verify_snapshot_copies(self.snapshot_id, [self.zone.id, self.additional_zone.id]) + self.template = self.create_snapshot_template(self.userapiclient, self.services, self.snapshot_id, self.additional_zone.id) + if self.additional_zone.id != self.template.zoneid: + self.fail("Template from snapshot not created in the additional zone") + return diff --git a/test/integration/component/test_snapshots_improvement.py b/test/integration/component/test_snapshots_improvement.py index c95d8205ee7..fde81025bca 100644 --- a/test/integration/component/test_snapshots_improvement.py +++ b/test/integration/component/test_snapshots_improvement.py @@ -542,7 +542,7 @@ class TestCreateSnapshot(cloudstackTestCase): def verify_Snapshots(self): try: - self.debug("Listing snapshots for accout : %s" % self.account.name) + self.debug("Listing snapshots for account : %s" % self.account.name) snapshots = self.get_Snapshots_For_Account( self.account.name, self.account.domainid) diff --git a/test/integration/component/test_tags.py b/test/integration/component/test_tags.py index 2141384eaf7..6ee5d3c6ea9 100644 --- a/test/integration/component/test_tags.py +++ b/test/integration/component/test_tags.py @@ -2426,7 +2426,7 @@ class TestResourceTags(cloudstackTestCase): hosts.pop(0) host_ids = [host.id for host in hosts] for id in host_ids: - if not id in host_ids_for_migration: + if id not in host_ids_for_migration: self.fail("Not all hosts are available for vm migration") return diff --git a/test/integration/component/test_vpc_network.py b/test/integration/component/test_vpc_network.py index 9a313e23094..db436bbd398 100644 --- a/test/integration/component/test_vpc_network.py +++ b/test/integration/component/test_vpc_network.py @@ -1001,23 +1001,23 @@ class TestVPCNetwork(cloudstackTestCase): # 1. Create a network offering with guest type=Isolated that has all # supported Services(Vpn,dhcpdns,UserData, SourceNat,Static NAT,LB # and PF,LB,NetworkAcl ) provided by VPCVR and conserve mode is ON - # 2. Create offering fails since Conserve mode ON isn't allowed within - # VPC + # 2. Create offering should succeed since Conserve mode ON is allowed within + # VPC since https://github.com/apache/cloudstack/pull/8309 # 3. Repeat test for offering which has Netscaler as external LB # provider """ self.debug("Creating network offering with conserve mode = ON") - with self.assertRaises(Exception): + try: nw = NetworkOffering.create( self.apiclient, self.services[value], conservemode=True ) self.cleanup.append(nw) - self.debug( - "Network creation failed as VPC support nw with conserve mode OFF") + except Exception as e: + self.warn("Network creation failed in VPC with conserve mode ON") return diff --git a/test/integration/component/test_vpc_vm_life_cycle.py b/test/integration/component/test_vpc_vm_life_cycle.py index 3d41dcadb48..abe6d194a54 100644 --- a/test/integration/component/test_vpc_vm_life_cycle.py +++ b/test/integration/component/test_vpc_vm_life_cycle.py @@ -627,7 +627,7 @@ class TestVMLifeCycleVPC(cloudstackTestCase): """ # Validate the following - # 1. Destory the virtual machines. + # 1. Destroy the virtual machines. # 2. Rules should be still configured on virtual router. # 3. Recover the virtual machines. # 4. Vm should be in stopped state. State both the instances @@ -1751,7 +1751,7 @@ class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): """ # Validate the following - # 1. Destory the virtual machines. + # 1. Destroy the virtual machines. # 2. Rules should be still configured on virtual router. # 3. Recover the virtual machines. # 4. Vm should be in stopped state. State both the instances @@ -2466,7 +2466,7 @@ class TestVMLifeCycleDiffHosts(cloudstackTestCase): """ # Validate the following - # 1. Destory the virtual machines. + # 1. Destroy the virtual machines. # 2. Rules should be still configured on virtual router. # 3. Recover the virtual machines. # 4. Vm should be in stopped state. State both the instances diff --git a/test/integration/plugins/ldap/test_ldap.py b/test/integration/plugins/ldap/test_ldap.py index fd0aecfab45..6746f3289f7 100644 --- a/test/integration/plugins/ldap/test_ldap.py +++ b/test/integration/plugins/ldap/test_ldap.py @@ -101,11 +101,13 @@ class TestLDAP(cloudstackTestCase): def tearDownClass(cls): cls.logger.info("Tearing Down Class") try: - cleanup_resources(cls.apiclient, reversed(cls._cleanup)) - cls.remove_ldap_configuration_for_domains() - cls.logger.debug("done cleaning up resources in tearDownClass(cls) %s") - except Exception as e: - cls.logger.debug("Exception in tearDownClass(cls): %s" % e) + super(TestLDAP, cls).tearDownClass() + finally: + try: + cls.remove_ldap_configuration_for_domains() + cls.logger.debug("done cleaning up resources in tearDownClass(cls) %s") + except Exception as e: + cls.logger.debug("Exception in tearDownClass(cls): %s" % e) def setUp(self): self.cleanup = [] @@ -116,11 +118,7 @@ class TestLDAP(cloudstackTestCase): return def tearDown(self): - try: - cleanup_resources(self.apiclient, self.cleanup) - except Exception as e: - raise Exception("Warning: Exception during cleanup : %s" % e) - return + super(TestLDAP, self).tearDown() @attr(tags=["smoke", "advanced"], required_hardware="false") def test_01_manual(self): @@ -349,8 +347,8 @@ class TestLDAP(cloudstackTestCase): if parent_domain: domain_to_create["parentdomainid"] = parent_domain tmpDomain = Domain.create(cls.apiclient, domain_to_create) - cls.logger.debug("Created domain %s with id %s " % (tmpDomain.name, tmpDomain.id)) cls._cleanup.append(tmpDomain) + cls.logger.debug("Created domain %s with id %s " % (tmpDomain.name, tmpDomain.id)) return tmpDomain @classmethod diff --git a/test/integration/plugins/linstor/README.md b/test/integration/plugins/linstor/README.md index a0a559c9da4..717f4e24e70 100644 --- a/test/integration/plugins/linstor/README.md +++ b/test/integration/plugins/linstor/README.md @@ -6,26 +6,26 @@ This directory contains the basic VM, Volume life cycle tests for Linstor storag =============== To run the basic volume tests, first update the below test data of the CloudStack environment -```` +``` TestData.zoneId: TestData.clusterId: TestData.domainId: TestData.url: TestData.primaryStorage "url": -```` +``` and to enable and run volume migration tests, update the below test data -```` +``` TestData.migrationTests: True TestData.primaryStorageSameInstance "url": TestData.primaryStorageDistinctInstance "url": -```` +``` Then run the tests using python unittest runner: nosetests -```` +``` nosetests --with-marvin --marvin-config= /test/integration/plugins/linstor/test_linstor_volumes.py --zone= --hypervisor=kvm -```` +``` You can also run these tests out of the box with PyDev or PyCharm or whatever. diff --git a/test/integration/plugins/quota/test_quota_balance.py b/test/integration/plugins/quota/test_quota_balance.py new file mode 100644 index 00000000000..f5c1c75d7b2 --- /dev/null +++ b/test/integration/plugins/quota/test_quota_balance.py @@ -0,0 +1,191 @@ +# 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. +""" +Test cases for validating the Quota balance of accounts +""" + +from marvin.cloudstackTestCase import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +from nose.plugins.attrib import attr + + +class TestQuotaBalance(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestQuotaBalance, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls.mgtSvrDetails = cls.config.__dict__["mgtSvr"][0].__dict__ + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.zone + + # Create Account + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup = [ + cls.account, + ] + + cls.services["account"] = cls.account.name + + if not is_config_suitable(apiclient=cls.apiclient, name='quota.enable.service', value='true'): + cls.debug("Quota service is not enabled, therefore the configuration `quota.enable.service` will be set to `true` and the management server will be restarted.") + Configurations.update(cls.apiclient, "quota.enable.service", "true") + cls.restartServer() + + return + + @classmethod + def restartServer(cls): + """Restart management server""" + + cls.debug("Restarting management server") + sshClient = SshClient( + cls.mgtSvrDetails["mgtSvrIp"], + 22, + cls.mgtSvrDetails["user"], + cls.mgtSvrDetails["passwd"] + ) + + command = "service cloudstack-management restart" + sshClient.execute(command) + + # Waits for management to come up in 5 mins, when it's up it will continue + timeout = time.time() + 300 + while time.time() < timeout: + if cls.isManagementUp() is True: + time.sleep(30) + return + time.sleep(5) + return cls.fail("Management server did not come up, failing") + + @classmethod + def isManagementUp(cls): + try: + cls.apiclient.listInfrastructure(listInfrastructure.listInfrastructureCmd()) + return True + except Exception: + return False + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.apiclient, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + self.tariffs = [] + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + self.delete_tariffs() + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def delete_tariffs(self): + for tariff in self.tariffs: + cmd = quotaTariffDelete.quotaTariffDeleteCmd() + cmd.id = tariff.uuid + self.apiclient.quotaTariffDelete(cmd) + + @attr(tags=["advanced", "smoke", "quota"], required_hardware="false") + def test_quota_balance(self): + """ + Test Quota balance + + Validate the following + 1. Add credits to an account + 2. Create Quota tariff for the usage type 21 (VM_DISK_IO_READ) + 3. Simulate quota usage by inserting a row in the `cloud_usage` table + 4. Update the balance of the account by calling the API quotaUpdate + 5. Verify the balance of the account according to the tariff created + """ + + # Create quota tariff for the usage type 21 (VM_DISK_IO_READ) + cmd = quotaTariffCreate.quotaTariffCreateCmd() + cmd.name = 'Tariff' + cmd.value = '10' + cmd.usagetype = '21' + self.tariffs.append(self.apiclient.quotaTariffCreate(cmd)) + + # Add credits to the account + cmd = quotaCredits.quotaCreditsCmd() + cmd.account = self.account.name + cmd.domainid = self.domain.id + cmd.value = 100 + self.apiclient.quotaCredits(cmd) + + # Fetch account ID from account_uuid + account_id_select = f"SELECT id FROM account WHERE uuid = '{self.account.id}';" + self.debug(account_id_select) + qresultset = self.dbclient.execute(account_id_select) + account_id = qresultset[0][0] + + # Fetch domain ID from domain_uuid + domain_id_select = f"SELECT id FROM `domain` d WHERE uuid = '{self.domain.id}';" + self.debug(domain_id_select) + qresultset = self.dbclient.execute(domain_id_select) + domain_id = qresultset[0][0] + + # Fetch zone ID from zone_uuid + zone_id_select = f"SELECT id from data_center dc where dc.uuid = '{self.zone.id}';" + self.debug(zone_id_select) + qresultset = self.dbclient.execute(zone_id_select) + zone_id = qresultset[0][0] + + start_date = datetime.datetime.now() + datetime.timedelta(seconds=1) + end_date = datetime.datetime.now() + datetime.timedelta(hours=1) + + # Manually insert a usage regarding the usage type 21 (VM_DISK_IO_READ) + sql_query = (f"INSERT INTO cloud_usage.cloud_usage (zone_id,account_id,domain_id,description,usage_display,usage_type,raw_usage,vm_instance_id,vm_name,offering_id,template_id," + f"usage_id,`type`,`size`,network_id,start_date,end_date,virtual_size,cpu_speed,cpu_cores,memory,quota_calculated,is_hidden,state)" + f" VALUES ('{zone_id}','{account_id}','{domain_id}','Test','1 Hrs',21,1,NULL,NULL,NULL,NULL,NULL,'VirtualMachine',NULL,NULL,'{start_date}','{end_date}',NULL,NULL,NULL,NULL,0,0,NULL);") + self.debug(sql_query) + self.dbclient.execute(sql_query) + + # Update quota to calculate the balance of the account + cmd = quotaUpdate.quotaUpdateCmd() + self.apiclient.quotaUpdate(cmd) + + # Retrieve the quota balance of the account + cmd = quotaBalance.quotaBalanceCmd() + cmd.domainid = self.account.domainid + cmd.account = self.account.name + response = self.apiclient.quotaBalance(cmd) + + self.debug(f"The quota balance for the account {self.account.name} is {response.balance}.") + self.assertEqual(response.balance.startquota, 90, f"The `startQuota` response field is supposed to be 90 but was {response.balance.startquota}.") + + return diff --git a/test/integration/plugins/scaleio/README.md b/test/integration/plugins/scaleio/README.md index 0e48fc15b46..6e1212ecb3a 100644 --- a/test/integration/plugins/scaleio/README.md +++ b/test/integration/plugins/scaleio/README.md @@ -6,25 +6,25 @@ This directory contains the basic VM, Volume life cycle tests for PowerFlex/Scal =============== To run the basic volume tests, first update the below test data of the CloudStack environment -```` +``` TestData.zoneId: TestData.clusterId: TestData.domainId: TestData.url: TestData.primaryStorage "url": -```` +``` and to enable and run volume migration tests, update the below test data -```` +``` TestData.migrationTests: True TestData.primaryStorageSameInstance "url": TestData.primaryStorageDistinctInstance "url": -```` +``` PowerFlex/ScaleIO storage pool url format: -```` +``` powerflex://:@/ where, @@ -35,12 +35,12 @@ powerflex://:@/ For example: "powerflex://admin:P%40ssword123@10.10.2.130/cspool" -```` +``` Then run the tests using python unittest runner: nosetests -```` +``` nosetests --with-marvin --marvin-config= /test/integration/plugins/scaleio/test_scaleio_volumes.py --zone= --hypervisor=kvm -```` +``` You can also run these tests out of the box with PyDev or PyCharm or whatever. diff --git a/test/integration/plugins/storpool/TestStorPoolVolumes.py b/test/integration/plugins/storpool/TestStorPoolVolumes.py index 640a2f9d2bc..70f8900df58 100644 --- a/test/integration/plugins/storpool/TestStorPoolVolumes.py +++ b/test/integration/plugins/storpool/TestStorPoolVolumes.py @@ -2073,7 +2073,7 @@ class TestStoragePool(cloudstackTestCase): clusterid = c.id ) for conf in configuration: - if conf.name == 'sp.cluster.id' and (conf.value in clusterid[1]): + if conf.name == 'sp.cluster.id' and (conf.value in clusterid[1]): return c @classmethod @@ -2088,7 +2088,7 @@ class TestStoragePool(cloudstackTestCase): clusterid = c.id ) for conf in configuration: - if conf.name == 'sp.cluster.id' and (conf.value not in clusterid[1]): + if conf.name == 'sp.cluster.id' and (conf.value not in clusterid[1]): return c @classmethod diff --git a/test/integration/plugins/storpool/TestTagsOnStorPool.py b/test/integration/plugins/storpool/TestTagsOnStorPool.py index 6d13e2081d9..a66fb3570f4 100644 --- a/test/integration/plugins/storpool/TestTagsOnStorPool.py +++ b/test/integration/plugins/storpool/TestTagsOnStorPool.py @@ -218,6 +218,19 @@ class TestStoragePool(cloudstackTestCase): hypervisor=cls.hypervisor, rootdisksize=10 ) + cls.virtual_machine3 = VirtualMachine.create( + cls.apiclient, + {"name":"StorPool-%s" % uuid.uuid4() }, + zoneid=cls.zone.id, + templateid=template.id, + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.service_offering.id, + hypervisor=cls.hypervisor, + diskofferingid=cls.disk_offerings.id, + size=2, + rootdisksize=10 + ) cls.template = template cls.random_data_0 = random_gen(size=100) cls.test_dir = "/tmp" @@ -270,7 +283,7 @@ class TestStoragePool(cloudstackTestCase): virtualmachineid = self.virtual_machine.id, listall=True ) - self.vc_policy_tags(volumes, vm_tags, vm) + self.vc_policy_tags(volumes, vm_tags, vm, True) @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true") @@ -310,7 +323,7 @@ class TestStoragePool(cloudstackTestCase): vm = list_virtual_machines(self.apiclient,id = self.virtual_machine.id, listall=True) vm_tags = vm[0].tags - self.vc_policy_tags(volumes, vm_tags, vm) + self.vc_policy_tags(volumes, vm_tags, vm, True) self.assertEqual(volume_attached.id, self.volume.id, "Is not the same volume ") @@ -442,7 +455,7 @@ class TestStoragePool(cloudstackTestCase): vm = list_virtual_machines(self.apiclient,id = self.virtual_machine.id, listall=True) vm_tags = vm[0].tags - self.vc_policy_tags(volumes, vm_tags, vm) + self.vc_policy_tags(volumes, vm_tags, vm, True) self.assertEqual( self.random_data_0, @@ -490,18 +503,17 @@ class TestStoragePool(cloudstackTestCase): def test_06_remove_vcpolicy_tag_when_disk_detached(self): """ Test remove vc-policy tag to disk detached from VM""" time.sleep(60) - volume_detached = self.virtual_machine.detach_volume( - self.apiclient, - self.volume_2 - ) vm = list_virtual_machines(self.apiclient,id = self.virtual_machine.id, listall=True) vm_tags = vm[0].tags volumes = list_volumes( self.apiclient, - virtualmachineid = self.virtual_machine.id, listall=True + id= self.volume_2.id, listall=True, ) - - self.vc_policy_tags( volumes, vm_tags, vm) + volume_detached = self.virtual_machine.detach_volume( + self.apiclient, + self.volume_2 + ) + self.vc_policy_tags( volumes, vm_tags, vm, False) @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true") def test_07_delete_vcpolicy_tag(self): @@ -538,7 +550,7 @@ class TestStoragePool(cloudstackTestCase): virtualmachineid = self.virtual_machine2.id, listall=True, type = "ROOT" ) - self.vc_policy_tags(volume, vm_tags, vm) + self.vc_policy_tags(volume, vm_tags, vm, True) snapshot = Snapshot.create( self.apiclient, @@ -560,11 +572,36 @@ class TestStoragePool(cloudstackTestCase): vm_tags = vm[0].tags vol = list_volumes(self.apiclient, id = snapshot.volumeid, listall=True) - self.vc_policy_tags(vol, vm_tags, vm) + self.vc_policy_tags(vol, vm_tags, vm, True) + @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true") + def test_09_remove_vm_tags_on_datadisks_attached_to_destroyed_vm(self): + tag = Tag.create( + self.apiclient, + resourceIds=self.virtual_machine3.id, + resourceType='UserVm', + tags={'vc-policy': 'testing_vc-policy'} + ) + vm = list_virtual_machines(self.apiclient,id = self.virtual_machine3.id, listall=True) + vm_tags = vm[0].tags + volumes = list_volumes( + self.apiclient, + virtualmachineid = self.virtual_machine3.id, listall=True + ) - def vc_policy_tags(self, volumes, vm_tags, vm): - flag = False + self.vc_policy_tags(volumes, vm_tags, vm, True) + + volumes = list_volumes( + self.apiclient, + virtualmachineid = self.virtual_machine3.id, listall=True, type="DATADISK" + ) + self.virtual_machine3.delete(self.apiclient, expunge=True) + + self.vc_policy_tags(volumes, vm_tags, vm, False) + + def vc_policy_tags(self, volumes, vm_tags, vm, should_tags_exists=None): + vcPolicyTag = False + cvmTag = False for v in volumes: name = v.path.split("/")[3] spvolume = self.spapi.volumeList(volumeName="~" + name) @@ -572,9 +609,15 @@ class TestStoragePool(cloudstackTestCase): for t in tags: for vm_tag in vm_tags: if t == vm_tag.key: - flag = True + vcPolicyTag = True self.assertEqual(tags[t], vm_tag.value, "Tags are not equal") if t == 'cvm': + cvmTag = True self.assertEqual(tags[t], vm[0].id, "CVM tag is not the same as vm UUID") #self.assertEqual(tag.tags., second, msg) - self.assertTrue(flag, "There aren't volumes with vm tags") + if should_tags_exists: + self.assertTrue(vcPolicyTag, "There aren't volumes with vm tags") + self.assertTrue(cvmTag, "There aren't volumes with vm tags") + else: + self.assertFalse(vcPolicyTag, "The tags should be removed") + self.assertFalse(cvmTag, "The tags should be removed") diff --git a/test/integration/plugins/storpool/sp_util.py b/test/integration/plugins/storpool/sp_util.py index 569aa4a2539..eaea3d4934d 100644 --- a/test/integration/plugins/storpool/sp_util.py +++ b/test/integration/plugins/storpool/sp_util.py @@ -384,7 +384,7 @@ class StorPoolHelper(): clusterid = c.id ) for conf in configuration: - if conf.name == 'sp.cluster.id' and (conf.value in clusterid[1]): + if conf.name == 'sp.cluster.id' and (conf.value in clusterid[1]): return c @classmethod @@ -399,7 +399,7 @@ class StorPoolHelper(): clusterid = c.id ) for conf in configuration: - if conf.name == 'sp.cluster.id' and (conf.value not in clusterid[1]): + if conf.name == 'sp.cluster.id' and (conf.value not in clusterid[1]): return c @classmethod diff --git a/test/integration/plugins/test_quota_tariff_order.py b/test/integration/plugins/test_quota_tariff_order.py new file mode 100644 index 00000000000..3236c6c3c18 --- /dev/null +++ b/test/integration/plugins/test_quota_tariff_order.py @@ -0,0 +1,175 @@ +# 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. +""" Test cases for checking quota API +""" + +# Import Local Modules +import tools.marvin.marvin +from tools.marvin.marvin.cloudstackTestCase import * +from tools.marvin.marvin.cloudstackAPI import * +from tools.marvin.marvin.lib.utils import * +from tools.marvin.marvin.lib.base import * +from tools.marvin.marvin.lib.common import * +from nose.plugins.attrib import attr + +# Import System modules +import time + + +class TestQuotaTariffOrder(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestQuotaTariffOrder, cls).getClsTestClient() + cls.api_client = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client) + cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests()) + + cls._cleanup = [] + # Create Account + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup.append(cls.account) + + cls.services["account"] = cls.account.name + + return + + @classmethod + def tearDownClass(cls): + super(TestQuotaTariffOrder, cls).tearDownClass() + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + self.tariffs = [] + return + + def tearDown(self): + self.delete_tariffs() + super(TestQuotaTariffOrder, self).tearDown() + + def delete_tariffs(self): + for tariff in self.tariffs: + cmd = quotaTariffDelete.quotaTariffDeleteCmd() + cmd.id = tariff.uuid + self.api_client.quotaTariffDelete(cmd) + + @attr( + tags=[ + "advanced", + "smoke"], + required_hardware="false") + def test_01_quota_tariff_order(self): + """Test Quota Tariff Order + """ + + cmd = quotaTariffCreate.quotaTariffCreateCmd() + cmd.name = 'tf1' + cmd.value = '1' + cmd.activationrule = '10' + cmd.usagetype = '22' + cmd.position = '2' + self.tariffs.append(self.api_client.quotaTariffCreate(cmd)) + + cmd = quotaTariffCreate.quotaTariffCreateCmd() + cmd.name = 'tf2' + cmd.value = '1' + cmd.activationrule = 'lastTariffs[lastTariffs.length -1].value + 7' + cmd.usagetype = '22' + cmd.position = '3' + self.tariffs.append(self.api_client.quotaTariffCreate(cmd)) + + cmd = quotaTariffCreate.quotaTariffCreateCmd() + cmd.name = 'tf3' + cmd.value = '1' + cmd.activationrule = 'lastTariffs[lastTariffs.length -2].value + lastTariffs[lastTariffs.length -1].value' + cmd.usagetype = '22' + cmd.position = '4' + self.tariffs.append(self.api_client.quotaTariffCreate(cmd)) + + cmd = quotaCredits.quotaCreditsCmd() + cmd.account = self.account.name + cmd.domainid = self.domain.id + cmd.value = 54 + self.api_client.quotaCredits(cmd) + + # Fetch account ID from account_uuid + self.debug("select id from account where uuid = '%s';" + % self.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" + % self.account.id + ) + + account_id = qresultset[0][0] + + self.debug("SELECT id from `domain` d WHERE uuid = '%s';" + % self.domain.id) + + qresultset = self.dbclient.execute( + "SELECT id from `domain` d WHERE uuid = '%s';" + % self.domain.id + ) + + domain_id = qresultset[0][0] + + self.debug("SELECT id from data_center dc where dc.uuid = '%s';" + % self.zone.id) + + qresultset = self.dbclient.execute( + "SELECT id from data_center dc where dc.uuid = '%s';" + % self.zone.id + ) + + zone_id = qresultset[0][0] + + start = datetime.datetime.now() + datetime.timedelta(seconds=1) + end = datetime.datetime.now() + datetime.timedelta(hours=1) + + query = "INSERT INTO cloud_usage.cloud_usage (zone_id,account_id,domain_id,description,usage_display," + "usage_type,raw_usage,vm_instance_id,vm_name,offering_id,template_id,usage_id,`type`,`size`," + "network_id,start_date,end_date,virtual_size,cpu_speed,cpu_cores,memory,quota_calculated," + "is_hidden,state) VALUES ('{}','{}','{}','Test','1 Hrs',22,1,NULL,NULL,NULL,NULL,NULL," + "'VirtualMachine',NULL,NULL,'{}','{}',NULL,NULL,NULL,NULL,0,0,NULL);".format(zone_id, account_id, domain_id, start, end) + + self.debug(query) + + self.dbclient.execute( + query) + + cmd = quotaUpdate.quotaUpdateCmd() + self.api_client.quotaUpdate(cmd) + + cmd = quotaBalance.quotaBalanceCmd() + cmd.domainid = self.account.domainid + cmd.account = self.account.name + response = self.apiclient.quotaBalance(cmd) + + self.debug(f"Quota Balance: {response.balance}") + + self.assertEqual(response.balance.startquota, 0, f"startQuota is supposed to be 0 but was {response.balance.startquota}") + + return diff --git a/test/integration/smoke/test_attach_multiple_volumes.py b/test/integration/smoke/test_attach_multiple_volumes.py index 939764dc010..81199bcfdfa 100644 --- a/test/integration/smoke/test_attach_multiple_volumes.py +++ b/test/integration/smoke/test_attach_multiple_volumes.py @@ -211,7 +211,7 @@ class TestMultipleVolumeAttach(cloudstackTestCase): clusterid = host.clusterid storage_pools = StoragePool.list(self.apiClient, clusterid=clusterid) if len(storage_pools) < 2: - self.skipTest("at least two accesible primary storage pools needed for the vm to perform this test") + self.skipTest("at least two accessible primary storage pools needed for the vm to perform this test") return storage_pools diff --git a/test/integration/smoke/test_backup_recovery_veeam.py b/test/integration/smoke/test_backup_recovery_veeam.py new file mode 100644 index 00000000000..f99b3db17d4 --- /dev/null +++ b/test/integration/smoke/test_backup_recovery_veeam.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python +# 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. + +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.utils import wait_until +from marvin.lib.base import (Account, ServiceOffering, DiskOffering, Volume, VirtualMachine, + BackupOffering, Configurations, Backup, BackupSchedule) +from marvin.lib.common import (get_domain, get_zone, get_template) +from nose.plugins.attrib import attr +from marvin.codes import FAILED + +import time + +class TestVeeamBackupAndRecovery(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + # Setup + + cls.testClient = super(TestVeeamBackupAndRecovery, cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.services["mode"] = cls.zone.networktype + cls.hypervisor = cls.testClient.getHypervisorInfo() + cls.domain = get_domain(cls.apiclient) + cls.template = get_template(cls.apiclient, cls.zone.id, cls.services["ostype"]) + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["small"]["template"] = cls.template.id + cls._cleanup = [] + + # Check backup configuration values, set them to enable the veeam provider + backup_enabled_cfg = Configurations.list(cls.apiclient, name='backup.framework.enabled', zoneid=cls.zone.id) + backup_provider_cfg = Configurations.list(cls.apiclient, name='backup.framework.provider.plugin', zoneid=cls.zone.id) + cls.backup_enabled = backup_enabled_cfg[0].value + cls.backup_provider = backup_provider_cfg[0].value + + if cls.backup_enabled == "false": + Configurations.update(cls.apiclient, 'backup.framework.enabled', value='true', zoneid=cls.zone.id) + if cls.backup_provider != "veeam": + return + + if cls.hypervisor.lower() != 'vmware': + return + + cls.service_offering = ServiceOffering.create(cls.apiclient, cls.services["service_offerings"]["small"]) + cls._cleanup.append(cls.service_offering) + cls.disk_offering = DiskOffering.create(cls.apiclient, cls.services["disk_offering"]) + cls._cleanup.append(cls.disk_offering) + + @classmethod + def isBackupOfferingUsed(cls, existing_offerings, provider_offering): + if not existing_offerings: + return False + for existing_offering in existing_offerings: + if existing_offering.externalid == provider_offering.externalid: + return True + return False + + def waitForBackUp(self, vm): + def checkBackUp(): + backups = Backup.list(self.user_apiclient, vm.id) + if isinstance(backups, list) and len(backups) != 0: + return True, None + return False, None + + res, _ = wait_until(10, 60, checkBackUp) + if not res: + self.fail("Failed to wait for backup of VM %s to be Up" % vm.id) + + @classmethod + def tearDownClass(cls): + if cls.backup_enabled == "false": + Configurations.update(cls.apiclient, 'backup.framework.enabled', value=cls.backup_enabled, zoneid=cls.zone.id) + super(TestVeeamBackupAndRecovery, cls).tearDownClass() + + def setUp(self): + if self.backup_provider != "veeam": + raise self.skipTest("Skipping test cases which must only run for veeam") + if self.hypervisor.lower() != 'vmware': + raise self.skipTest("Skipping test cases which must only run for VMware") + self.cleanup = [] + + # Import backup offering + self.offering = None + existing_offerings = BackupOffering.listByZone(self.apiclient, self.zone.id) + provider_offerings = BackupOffering.listExternal(self.apiclient, self.zone.id) + if not provider_offerings: + self.skipTest("Skipping test cases as the provider offering is None") + for provider_offering in provider_offerings: + if not self.isBackupOfferingUsed(existing_offerings, provider_offering): + self.debug("Importing backup offering %s - %s" % (provider_offering.externalid, provider_offering.name)) + self.offering = BackupOffering.importExisting(self.apiclient, self.zone.id, provider_offering.externalid, + provider_offering.name, provider_offering.description) + if not self.offering: + self.fail("Failed to import backup offering %s" % provider_offering.name) + break + if not self.offering: + self.skipTest("Skipping test cases as there is no available provider offerings to import") + + # Create user account + self.account = Account.create(self.apiclient, self.services["account"], domainid=self.domain.id) + self.user_user = self.account.user[0] + self.user_apiclient = self.testClient.getUserApiClient( + self.user_user.username, self.domain.name + ) + self.cleanup.append(self.account) + + def tearDown(self): + super(TestVeeamBackupAndRecovery, self).tearDown() + + @attr(tags=["advanced", "backup"], required_hardware="false") + def test_01_import_list_delete_backup_offering(self): + """ + Import provider backup offering from Veeam Backup and Recovery Provider + """ + + # Verify offering is listed by user + imported_offering = BackupOffering.listByZone(self.user_apiclient, self.zone.id) + self.assertIsInstance(imported_offering, list, "List Backup Offerings should return a valid response") + self.assertNotEqual(len(imported_offering), 0, "Check if the list API returns a non-empty response") + matching_offerings = [x for x in imported_offering if x.id == self.offering.id] + self.assertNotEqual(len(matching_offerings), 0, "Check if there is a matching offering") + + # Delete backup offering + self.debug("Deleting backup offering %s" % self.offering.id) + self.offering.delete(self.apiclient) + + # Verify offering is not listed by user + imported_offering = BackupOffering.listByZone(self.user_apiclient, self.zone.id) + if imported_offering: + self.assertIsInstance(imported_offering, list, "List Backup Offerings should return a valid response") + matching_offerings = [x for x in imported_offering if x.id == self.offering.id] + self.assertEqual(len(matching_offerings), 0, "Check there is not a matching offering") + + @attr(tags=["advanced", "backup"], required_hardware="false") + def test_02_vm_backup_lifecycle(self): + """ + Test VM backup lifecycle + """ + + if self.offering: + self.cleanup.insert(0, self.offering) + + self.vm = VirtualMachine.create(self.user_apiclient, self.services["small"], accountid=self.account.name, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, + diskofferingid=self.disk_offering.id) + + # Verify there are no backups for the VM + backups = Backup.list(self.user_apiclient, self.vm.id) + self.assertEqual(backups, None, "There should not exist any backup for the VM") + + # Assign VM to offering and create ad-hoc backup + self.offering.assignOffering(self.user_apiclient, self.vm.id) + vms = VirtualMachine.list( + self.user_apiclient, + id=self.vm.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List virtual machines should return a valid list" + ) + self.assertEqual(1, len(vms), "List of the virtual machines should have 1 vm") + self.assertEqual(self.offering.id, vms[0].backupofferingid, "The virtual machine should have backup offering %s" % self.offering.id) + + # Create backup schedule on 01:00AM every Sunday + BackupSchedule.create(self.user_apiclient, self.vm.id, intervaltype="WEEKLY", timezone="CET", schedule="00:01:1") + backupSchedule = BackupSchedule.list(self.user_apiclient, self.vm.id) + self.assertIsNotNone(backupSchedule) + self.assertEqual("WEEKLY", backupSchedule.intervaltype) + self.assertEqual("00:01:1", backupSchedule.schedule) + self.assertEqual("CET", backupSchedule.timezone) + self.assertEqual(self.vm.id, backupSchedule.virtualmachineid) + self.assertEqual(self.vm.name, backupSchedule.virtualmachinename) + + # Update backup schedule on 02:00AM every 20th + BackupSchedule.update(self.user_apiclient, self.vm.id, intervaltype="MONTHLY", timezone="CET", schedule="00:02:20") + backupSchedule = BackupSchedule.list(self.user_apiclient, self.vm.id) + self.assertIsNotNone(backupSchedule) + self.assertEqual("MONTHLY", backupSchedule.intervaltype) + self.assertEqual("00:02:20", backupSchedule.schedule) + + # Delete backup schedule + BackupSchedule.delete(self.user_apiclient, self.vm.id) + + # Create backup + Backup.create(self.user_apiclient, self.vm.id) + + # Verify backup is created for the VM + self.waitForBackUp(self.vm) + backups = Backup.list(self.user_apiclient, self.vm.id) + self.assertEqual(len(backups), 1, "There should exist only one backup for the VM") + backup = backups[0] + + # Stop VM + self.vm.stop(self.user_apiclient, forced=True) + # Restore backup + Backup.restoreVM(self.user_apiclient, backup.id) + + # Delete backup + Backup.delete(self.user_apiclient, backup.id, forced=True) + + # Verify backup is deleted + backups = Backup.list(self.user_apiclient, self.vm.id) + self.assertEqual(backups, None, "There should not exist any backup for the VM") + + # Remove VM from offering + self.offering.removeOffering(self.user_apiclient, self.vm.id) + + @attr(tags=["advanced", "backup"], required_hardware="false") + def test_03_restore_volume_attach_vm(self): + """ + Test Volume Restore from Backup and Attach to VM + """ + + if self.offering: + self.cleanup.insert(0, self.offering) + + self.vm_with_datadisk = VirtualMachine.create(self.user_apiclient, self.services["small"], accountid=self.account.name, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, + diskofferingid=self.disk_offering.id) + + self.vm = VirtualMachine.create(self.user_apiclient, self.services["small"], accountid=self.account.name, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id) + + # Assign VM to offering and create ad-hoc backup + self.offering.assignOffering(self.user_apiclient, self.vm_with_datadisk.id) + + # Create backup + Backup.create(self.user_apiclient, self.vm_with_datadisk.id) + + # Verify backup is created for the VM with datadisk + self.waitForBackUp(self.vm_with_datadisk) + backups = Backup.list(self.user_apiclient, self.vm_with_datadisk.id) + self.assertEqual(len(backups), 1, "There should exist only one backup for the VM with datadisk") + backup = backups[0] + + try: + volumes = Volume.list( + self.user_apiclient, + virtualmachineid=self.vm_with_datadisk.id, + listall=True + ) + rootDiskId = None + dataDiskId = None + for volume in volumes: + if volume.type == 'ROOT': + rootDiskId = volume.id + elif volume.type == 'DATADISK': + dataDiskId = volume.id + if rootDiskId: + # Restore ROOT volume of vm_with_datadisk and attach to vm + Backup.restoreVolumeFromBackupAndAttachToVM( + self.user_apiclient, + backupid=backup.id, + volumeid=rootDiskId, + virtualmachineid=self.vm.id + ) + vm_volumes = Volume.list( + self.user_apiclient, + virtualmachineid=self.vm.id, + listall=True + ) + self.assertTrue(isinstance(vm_volumes, list), "List volumes should return a valid list") + self.assertEqual(2, len(vm_volumes), "The number of volumes should be 2") + if dataDiskId: + # Restore DATADISK volume of vm_with_datadisk and attach to vm + Backup.restoreVolumeFromBackupAndAttachToVM( + self.user_apiclient, + backupid=backup.id, + volumeid=dataDiskId, + virtualmachineid=self.vm.id + ) + vm_volumes = Volume.list( + self.user_apiclient, + virtualmachineid=self.vm.id, + listall=True + ) + self.assertTrue(isinstance(vm_volumes, list), "List volumes should return a valid list") + self.assertEqual(3, len(vm_volumes), "The number of volumes should be 3") + finally: + # Delete backup + Backup.delete(self.user_apiclient, backup.id, forced=True) + # Remove VM from offering + self.offering.removeOffering(self.user_apiclient, self.vm_with_datadisk.id) + # Delete vm + self.vm.delete(self.apiclient) + # Delete vm with datadisk + self.vm_with_datadisk.delete(self.apiclient) diff --git a/test/integration/smoke/test_bucket.py b/test/integration/smoke/test_bucket.py new file mode 100644 index 00000000000..7d92ea98b07 --- /dev/null +++ b/test/integration/smoke/test_bucket.py @@ -0,0 +1,111 @@ +# 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. +""" BVT tests for Bucket Operations""" + +#Import Local Modules +from marvin.cloudstackTestCase import * +from nose.plugins.attrib import attr +from marvin.lib.base import (ObjectStoragePool, Bucket) +from marvin.lib.utils import (cleanup_resources) + +_multiprocess_shared_ = True + +class TestObjectStore(cloudstackTestCase): + + def setUp(self): + self.services = self.testClient.getParsedTestDataConfig() + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created resources + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["smoke"], required_hardware="false") + def test_01_create_bucket(self): + """Test to create bucket in object store + + """ + + object_store = ObjectStoragePool.create( + self.apiclient, + "testOS-9", + "http://192.168.0.1", + "Simulator", + None + ) + + self.debug("Created Object Store with ID: %s" % object_store.id) + + bucket = Bucket.create( + self.apiclient, + "mybucket", + object_store.id + ) + + list_buckets_response = Bucket.list( + self.apiclient, + id=bucket.id + ) + + self.assertNotEqual( + len(list_buckets_response), + 0, + "Check List Bucket response" + ) + + bucket_response = list_buckets_response[0] + self.assertEqual( + object_store.id, + bucket_response.objectstorageid, + "Check object store id of the created Bucket" + ) + self.assertEqual( + "mybucket", + bucket_response.name, + "Check Name of the created Bucket" + ) + + bucket.update( + self.apiclient, + quota=100 + ) + + list_buckets_response_updated = Bucket.list( + self.apiclient, + id=bucket.id + ) + + bucket_response_updated = list_buckets_response_updated[0] + + self.assertEqual( + 100, + bucket_response_updated.quota, + "Check quota of the updated bucket" + ) + + self.cleanup.append(bucket) + self.cleanup.append(object_store) + + return diff --git a/test/integration/smoke/test_cluster_drs.py b/test/integration/smoke/test_cluster_drs.py new file mode 100644 index 00000000000..f1eb48f92f5 --- /dev/null +++ b/test/integration/smoke/test_cluster_drs.py @@ -0,0 +1,310 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" +Tests DRS on a cluster +""" + +import logging +import time +from collections.abc import Iterable + +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.cloudstackAPI import (migrateSystemVm, listRouters, listSystemVms) +from marvin.lib.base import (Cluster, Configurations, Host, Network, NetworkOffering, ServiceOffering, VirtualMachine, + Zone) +from marvin.lib.common import (get_domain, get_zone, get_template) +from marvin.lib.utils import wait_until +from marvin import jsonHelper +from nose.plugins.attrib import attr + + +class TestClusterDRS(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.testClient = super(TestClusterDRS, cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + + zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.zone = Zone(zone.__dict__) + cls.template = get_template(cls.apiclient, cls.zone.id) + cls._cleanup = [] + + cls.logger = logging.getLogger("TestClusterDRS") + cls.stream_handler = logging.StreamHandler() + cls.logger.setLevel(logging.DEBUG) + cls.logger.addHandler(cls.stream_handler) + + cls.skipTests = False + clusters = Cluster.list(cls.apiclient, zoneid=cls.zone.id, allocationstate='Enabled') + + if not clusters or not isinstance(clusters, list) or len(clusters) < 1: + cls.logger.debug("This test requires at least 1 (Up and Enabled) cluster in the zone") + cls.skipTests = True + return + + for cluster in clusters: + cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, clusterid=cluster.id, state='Up', + resourcestate='Enabled') + if not cls.hosts or not isinstance(cls.hosts, list) or len(cls.hosts) < 2: + cls.logger.debug("This test requires at least two (Up and Enabled) hosts in the zone") + cls.skipTests = True + return + else: + cls.cluster = Cluster(jsonHelper.jsonDump.dump(cluster)) + break + + cls.domain = get_domain(cls.apiclient) + + # 1. Create large service offering + cls.service_offering = ServiceOffering.create(cls.apiclient, cls.services["service_offerings"]["large"]) + cls._cleanup.append(cls.service_offering) + + # 2. Create a network + cls.services["network"]["name"] = "Test Network" + cls.network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["l2-network_offering"] + ) + cls._cleanup.append(cls.network_offering) + NetworkOffering.update( + cls.network_offering, + cls.apiclient, + id=cls.network_offering.id, + state="enabled" + ) + + cls.network = Network.create( + cls.apiclient, + cls.services["l2-network"], + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id, + accountid="admin", + domainid=cls.domain.id, + ) + cls._cleanup.append(cls.network) + + cls.hypervisor = cls.testClient.getHypervisorInfo() + if cls.hypervisor.lower() not in ['simulator']: + cls.migrateSvms(cls.cluster) + + @classmethod + def migrateSvms(cls, cluster): + """ + for testing the balanced algorithm we must make sure there is at least as more free memory on host[1] than on + host[0]. As a grude measure we migrate any and all system vms to host[0] before the testing commences + + :param cluster: the cluser to check + :return: None + """ + + systemVmIds = [] + cmds = listSystemVms.listSystemVmsCmd() + responseS = cls.apiclient.listSystemVms(cmds) + if isinstance(responseS, Iterable): + for svm in responseS: + if svm.hostid != cls.hosts[0].id: + systemVmIds.append(svm.id) + cmdv = listRouters.listRoutersCmd() + responseR = cls.apiclient.listRouters(cmdv) + if isinstance(responseR, Iterable): + for svm in responseR: + if svm.hostid != cls.hosts[0].id: + systemVmIds.append(svm.id) + numToMigrate = len(systemVmIds) + cls.logger.debug(f'system vms and routers to migrate -- {numToMigrate}') + cmdM = migrateSystemVm.migrateSystemVmCmd() + cmdM.hostId=cls.hosts[0].id + for id in systemVmIds: + cmdM.virtualmachineid=id + responseM = cls.apiclient.migrateSystemVm(cmdM) + cls.logger.debug(f'migrated {responseM}') + + + @classmethod + def tearDownClass(cls): + super(TestClusterDRS, cls).tearDownClass() + + def setUp(self): + if self.skipTests: + self.skipTest("This test requires at least two (Up and Enabled) hosts in the zone") + self.apiclient = self.testClient.getApiClient() + self.cleanup = [] + + def tearDown(self): + super(TestClusterDRS, self).tearDown() + + def get_vm_host_id(cls, vm_id): + list_vms = VirtualMachine.list(cls.apiclient, id=vm_id) + vm = list_vms[0] + return vm.hostid + + def wait_for_vm_start(self, vm): + """ Wait until vm is Running """ + def check_vm_state(): + vms = VirtualMachine.list( + self.apiclient, + id=vm.id, + listall=True + ) + if isinstance(vms, list): + if vms[0].state == 'Running': + return True, vms[0].state + return False, vms[0].state + + res = wait_until(10, 30, check_vm_state) + if not res: + raise Exception("Failed to wait for VM %s (%s) to be Running" % (vm.name, vm.id)) + return res + + def wait_for_plan_completion(self, plan): + """ Wait until plan is completed """ + def check_plan_status(): + plans = self.cluster.listDrsPlans(self.apiclient, id=plan.id) + if isinstance(plans, list): + if plans[0].status == 'COMPLETED': + return True, plans[0].status + return False, plans[0].status + + res = wait_until(10, 30, check_plan_status) + if not res: + raise Exception("Failed to wait for completion of plan %s" % (plan.id)) + return res + + def get_migrations(self): + """ Wait until migrations are generated. Sometimes it takes a little bit of time for stats to get updated. We generate migrations + until we get at least one migration """ + def generate_migrations(): + drs_plan = self.cluster.generateDrsPlan(self.apiclient, migrations=4) + if len(drs_plan["migrations"]) > 0: + return True, drs_plan["migrations"] + return False, drs_plan["migrations"] + + res, migrations = wait_until(10, 30, generate_migrations) + if not res: + raise Exception("Failed to generate drs migrations") + return migrations + + @attr(tags=["advanced"], required_hardware="false") + def test_01_condensed_drs_algorithm(self): + """ Verify DRS algorithm - condensed""" + # 1. Deploy vm-1 on host 1 + # 2. Deploy vm-2 on host 2 + # 3. Execute DRS to move all VMs on the same host + self.logger.debug("=== Running test_01_condensed_drs_algorithm ===") + + # 1. Deploy vm-1 on host 1 + self.services["virtual_machine"]["name"] = "virtual-machine-1" + self.services["virtual_machine"]["displayname"] = "virtual-machine-1" + self.virtual_machine_1 = VirtualMachine.create(self.apiclient, self.services["virtual_machine"], + serviceofferingid=self.service_offering.id, + templateid=self.template.id, zoneid=self.zone.id, + networkids=self.network.id, hostid=self.hosts[0].id) + self.cleanup.append(self.virtual_machine_1) + vm_1_host_id = self.get_vm_host_id(self.virtual_machine_1.id) + + # 2. Deploy vm-2 on host 2 + self.services["virtual_machine"]["name"] = "virtual-machine-2" + self.services["virtual_machine"]["displayname"] = "virtual-machine-2" + self.virtual_machine_2 = VirtualMachine.create(self.apiclient, self.services["virtual_machine"], + serviceofferingid=self.service_offering.id, + templateid=self.template.id, zoneid=self.zone.id, + networkids=self.network.id, hostid=self.hosts[1].id) + self.cleanup.append(self.virtual_machine_2) + vm_2_host_id = self.get_vm_host_id(self.virtual_machine_2.id) + + self.assertNotEqual(vm_1_host_id, vm_2_host_id, msg="Both VMs should be on different hosts") + self.wait_for_vm_start(self.virtual_machine_1) + self.wait_for_vm_start(self.virtual_machine_2) + + # 3. Generate & execute DRS to move all VMs on the same host + Configurations.update(self.apiclient, "drs.algorithm", "condensed", clusterid=self.cluster.id) + Configurations.update(self.apiclient, "drs.imbalance", "1.0", clusterid=self.cluster.id) + + migrations = self.get_migrations() + vm_to_dest_host_map = { + migration["virtualmachineid"]: migration["destinationhostid"] for migration in migrations + } + + self.assertEqual(len(vm_to_dest_host_map), 1, msg="DRS plan should have 1 migrations") + + executed_plan = self.cluster.executeDrsPlan(self.apiclient, vm_to_dest_host_map) + self.wait_for_plan_completion(executed_plan) + + vm_1_host_id = self.get_vm_host_id(self.virtual_machine_1.id) + vm_2_host_id = self.get_vm_host_id(self.virtual_machine_2.id) + + self.assertEqual(vm_1_host_id, vm_2_host_id, msg="Both VMs should be on the same host") + + @attr(tags=["advanced"], required_hardware="false") + def test_02_balanced_drs_algorithm(self): + """ + Verify DRS algorithm - balanced + + # 1. Deploy vm-1 on host 1 + # 2. Deploy vm-2 on host 2 + # 3. Execute DRS to move all VMs on different hosts + """ + self.logger.debug("=== Running test_02_balanced_drs_algorithm ===") + + # 1. Deploy vm-1 on host 1 + self.services["virtual_machine"]["name"] = "virtual-machine-1" + self.services["virtual_machine"]["displayname"] = "virtual-machine-1" + self.virtual_machine_1 = VirtualMachine.create(self.apiclient, self.services["virtual_machine"], + serviceofferingid=self.service_offering.id, + templateid=self.template.id, zoneid=self.zone.id, + networkids=self.network.id, hostid=self.hosts[0].id) + self.cleanup.append(self.virtual_machine_1) + vm_1_host_id = self.get_vm_host_id(self.virtual_machine_1.id) + + # 2. Deploy vm-2 on host 1 + self.services["virtual_machine"]["name"] = "virtual-machine-2" + self.services["virtual_machine"]["displayname"] = "virtual-machine-2" + self.virtual_machine_2 = VirtualMachine.create(self.apiclient, self.services["virtual_machine"], + serviceofferingid=self.service_offering.id, + templateid=self.template.id, zoneid=self.zone.id, + networkids=self.network.id, hostid=self.hosts[0].id) + self.cleanup.append(self.virtual_machine_2) + vm_2_host_id = self.get_vm_host_id(self.virtual_machine_2.id) + + self.assertEqual(vm_1_host_id, vm_2_host_id, msg="Both VMs should be on same hosts") + self.wait_for_vm_start(self.virtual_machine_1) + self.wait_for_vm_start(self.virtual_machine_2) + + # 3. Execute DRS to move all VMs on different hosts + Configurations.update(self.apiclient, "drs.algorithm", "balanced", clusterid=self.cluster.id) + Configurations.update(self.apiclient, "drs.imbalance", "1.0", clusterid=self.cluster.id) + + migrations = self.get_migrations() + vm_to_dest_host_map = { + migration["virtualmachineid"]: migration["destinationhostid"] for migration in migrations + } + + # this is one if no svm is considered to be migrated, it might be higher + self.assertTrue(len(vm_to_dest_host_map) >= 1, msg="DRS plan should have at least 1 migrations") + + executed_plan = self.cluster.executeDrsPlan(self.apiclient, vm_to_dest_host_map) + self.wait_for_plan_completion(executed_plan) + + vm_1_host_id = self.get_vm_host_id(self.virtual_machine_1.id) + vm_2_host_id = self.get_vm_host_id(self.virtual_machine_2.id) + + self.assertTrue( + vm_1_host_id != self.virtual_machine_1.hostid or vm_2_host_id != self.virtual_machine_2.hostid, + msg="At least one VM should have been migrated to a different host") diff --git a/test/integration/smoke/test_enable_account_settings_for_domain.py b/test/integration/smoke/test_enable_account_settings_for_domain.py index 09550ed1e27..fea80ee1297 100644 --- a/test/integration/smoke/test_enable_account_settings_for_domain.py +++ b/test/integration/smoke/test_enable_account_settings_for_domain.py @@ -391,7 +391,7 @@ class TestDedicatePublicIPRange(cloudstackTestCase): # (8) change domain setting (3) to original +30 # (9) list domain settings with name=(3), value should be same as (8) # (10) list account settings with name=(3), value should be same as (9)=(8) - # (11) change acount setting (3) to original +50 + # (11) change account setting (3) to original +50 # (12) list account settings with name=(3), value should be same as (10) """ @@ -484,7 +484,7 @@ class TestDedicatePublicIPRange(cloudstackTestCase): account_value = int(configs[0].value) self.assertEqual(new_domain_value, account_value, "Account setting is not equal to new value of global setting") - # (11) change acount setting (3) to original +50 + # (11) change account setting (3) to original +50 new_account_value = account_value + 50 Configurations.update( self.apiclient, diff --git a/test/integration/smoke/test_events_resource.py b/test/integration/smoke/test_events_resource.py index 660cbd37bce..79443110950 100644 --- a/test/integration/smoke/test_events_resource.py +++ b/test/integration/smoke/test_events_resource.py @@ -116,6 +116,7 @@ class TestEventsResource(cloudstackTestCase): self.services["domain"], parentdomainid=self.domain.id ) + self.cleanup.append(domain1) self.services["domainid"] = domain1.id account = Account.create( @@ -123,6 +124,7 @@ class TestEventsResource(cloudstackTestCase): self.services["account"], domainid=domain1.id ) + self.cleanup.append(account) account_network = Network.create( self.apiclient, @@ -130,6 +132,7 @@ class TestEventsResource(cloudstackTestCase): account.name, account.domainid ) + self.cleanup.append(account_network) virtual_machine = VirtualMachine.create( self.apiclient, self.services, @@ -138,6 +141,7 @@ class TestEventsResource(cloudstackTestCase): networkids=account_network.id, serviceofferingid=self.service_offering.id ) + self.cleanup.append(virtual_machine) volume = Volume.create( self.apiclient, self.services, @@ -146,6 +150,7 @@ class TestEventsResource(cloudstackTestCase): domainid=account.domainid, diskofferingid=self.disk_offering.id ) + self.cleanup.append(volume) virtual_machine.attach_volume( self.apiclient, volume @@ -157,15 +162,20 @@ class TestEventsResource(cloudstackTestCase): time.sleep(self.services["sleep"]) virtual_machine.detach_volume(self.apiclient, volume) volume.delete(self.apiclient) + self.cleanup.remove(volume) ts = str(time.time()) virtual_machine.update(self.apiclient, displayname=ts) virtual_machine.delete(self.apiclient) + self.cleanup.remove(virtual_machine) account_network.update(self.apiclient, name=account_network.name + ts) account_network.delete(self.apiclient) + self.cleanup.remove(account_network) account.update(self.apiclient, newname=account.name + ts) account.disable(self.apiclient) account.delete(self.apiclient) + self.cleanup.remove(account) domain1.delete(self.apiclient) + self.cleanup.remove(domain1) cmd = listEvents.listEventsCmd() cmd.startdate = start_time @@ -185,8 +195,9 @@ class TestEventsResource(cloudstackTestCase): for event in events: if event.type.startswith("VM.") or (event.type.startswith("NETWORK.") and not event.type.startswith("NETWORK.ELEMENT")) or event.type.startswith("VOLUME.") or event.type.startswith("ACCOUNT.") or event.type.startswith("DOMAIN.") or event.type.startswith("TEMPLATE."): if event.resourceid is None or event.resourcetype is None: - self.debug("Failed event:: %s" % json.dumps(event, indent=2)) - self.fail("resourceid or resourcetype for the event not found!") + event_json = json.dumps(event.__dict__, indent=2) + self.debug("Failed event:: %s" % event_json) + self.fail("resourceid or resourcetype not found for the event: %s" % event_json) else: self.debug("Event %s at %s:: Resource Type: %s, Resource ID: %s" % (event.type, event.created, event.resourcetype, event.resourceid)) diff --git a/test/integration/smoke/test_global_acls.py b/test/integration/smoke/test_global_acls.py new file mode 100644 index 00000000000..47db858c121 --- /dev/null +++ b/test/integration/smoke/test_global_acls.py @@ -0,0 +1,245 @@ +# 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. +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.utils import cleanup_resources +from marvin.lib.base import (Network, NetworkACLList, NetworkOffering, VpcOffering, VPC, NetworkACL) +from marvin.lib.common import (get_domain, get_zone) +from nose.plugins.attrib import attr +from marvin.cloudstackException import CloudstackAPIException + + +class Services: + """Test Global ACLs + """ + + def __init__(self): + self.services = { + "root_domain": { + "name": "ROOT", + }, + "domain": { + "name": "Domain", + }, + "user": { + "username": "user", + "roletype": 0, + }, + "domain_admin": { + "username": "Domain admin", + "roletype": 2, + }, + "root_admin": { + "username": "Root admin", + "roletype": 1, + }, + "vpc": { + "name": "vpc-networkacl", + "displaytext": "vpc-networkacl", + "cidr": "10.1.1.0/24", + }, + "vpcnetwork": { + "name": "vpcnetwork", + "displaytext": "vpcnetwork", + }, + "rule": { + "protocol": "all", + "traffictype": "ingress", + } + } + + +class TestGlobalACLs(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.testClient = super(TestGlobalACLs, cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + + cls.services = Services().services + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + return + + def setUp(self): + self.user_apiclient = self.testClient.getUserApiClient(self.services["user"]["username"], + self.services["domain"]["name"], + self.services["user"]["roletype"]) + + self.domain_admin_apiclient = self.testClient.getUserApiClient(self.services["domain_admin"]["username"], + self.services["domain"]["name"], + self.services["domain_admin"]["roletype"]) + + self.admin_apiclient = self.testClient.getUserApiClient(self.services["root_admin"]["username"], + self.services["root_domain"]["name"], + self.services["root_admin"]["roletype"]) + + self.cleanup = [] + return + + def tearDown(self): + super(TestGlobalACLs, self).tearDown() + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_create_global_acl(self): + """ Test create global ACL as a normal user, domain admin and root admin users. + """ + + self.debug("Creating ACL list as a normal user, should raise exception.") + self.assertRaisesRegex(CloudstackAPIException, "Only Root Admin can create global ACLs.", + NetworkACLList.create, apiclient=self.user_apiclient, services={}, + name="acl", description="acl") + + self.debug("Creating ACL list as a domain admin, should raise exception.") + self.assertRaisesRegex(CloudstackAPIException, "Only Root Admin can create global ACLs.", + NetworkACLList.create, apiclient=self.domain_admin_apiclient, services={}, + name="acl", description="acl") + + self.debug("Creating ACL list as a root admin, should work.") + acl = NetworkACLList.create(apiclient=self.admin_apiclient, services={}, name="acl", description="acl") + self.cleanup.append(acl) + self.assertIsNotNone(acl, "A root admin user should be able to create a global ACL.") + + return + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_replace_acl_of_network(self): + """ Test to replace ACL of a VPC as a normal user, domain admin and root admin users. + """ + # Get network offering + networkOffering = NetworkOffering.list(self.apiclient, name="DefaultIsolatedNetworkOfferingForVpcNetworks") + self.assertTrue(networkOffering is not None and len(networkOffering) > 0, "No VPC network offering") + + # Getting VPC offering + vpcOffering = VpcOffering.list(self.apiclient, name="Default VPC offering") + self.assertTrue(vpcOffering is not None and len(vpcOffering) > 0, "No VPC offerings found") + + # Creating VPC + vpc = VPC.create( + apiclient=self.apiclient, + services=self.services["vpc"], + networkDomain="vpc.networkacl", + vpcofferingid=vpcOffering[0].id, + zoneid=self.zone.id, + domainid=self.domain.id + ) + self.cleanup.append(vpc) + self.assertTrue(vpc is not None, "VPC creation failed") + + # Creating ACL list + acl = NetworkACLList.create(apiclient=self.apiclient, services={}, name="acl", description="acl") + + # Creating tier on VPC with ACL list + network = Network.create( + apiclient=self.apiclient, + services=self.services["vpcnetwork"], + accountid="Admin", + domainid=self.domain.id, + networkofferingid=networkOffering[0].id, + zoneid=self.zone.id, + vpcid=vpc.id, + aclid=acl.id, + gateway="10.1.1.1", + netmask="255.255.255.192" + ) + self.cleanup.append(network) + + # User should be able to replace ACL + network.replaceACLList(apiclient=self.user_apiclient, aclid=acl.id) + # Domain Admin should be able to replace ACL + network.replaceACLList(apiclient=self.domain_admin_apiclient, aclid=acl.id) + # Admin should be able to replace ACL + network.replaceACLList(apiclient=self.admin_apiclient, aclid=acl.id) + + return + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_create_acl_rule(self): + """ Test to create ACL rule as a normal user, domain admin and root admin users. + """ + # Creating ACL list + acl = NetworkACLList.create(apiclient=self.admin_apiclient, services={}, name="acl", description="acl") + self.cleanup.append(acl) + + self.debug("Creating ACL rule as a user, should raise exception.") + self.assertRaisesRegex(CloudstackAPIException, "Only Root Admins can create rules for a global ACL.", + NetworkACL.create, self.user_apiclient, services=self.services["rule"], aclid=acl.id) + self.debug("Creating ACL rule as a domain admin, should raise exception.") + self.assertRaisesRegex(CloudstackAPIException, "Only Root Admins can create rules for a global ACL.", + NetworkACL.create, self.domain_admin_apiclient, services=self.services["rule"], aclid=acl.id) + self.debug("Creating ACL rule as a root admin, should work.") + acl_rule = NetworkACL.create(self.admin_apiclient, services=self.services["rule"], aclid=acl.id) + self.cleanup.append(acl_rule) + + return + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_delete_acl_rule(self): + """ Test to delete ACL rule as a normal user, domain admin and root admin users. + """ + # Creating ACL list + acl = NetworkACLList.create(apiclient=self.apiclient, services={}, name="acl", description="acl") + self.cleanup.append(acl) + + # Creating ACL rule + acl_rule = NetworkACL.create(self.apiclient, services=self.services["rule"], aclid=acl.id) + self.cleanup.append(acl_rule) + + self.debug("Deleting ACL rule as a user, should raise exception.") + self.assertRaisesRegex(Exception, "Only Root Admin can delete global ACL rules.", + NetworkACL.delete, acl_rule, self.user_apiclient) + self.debug("Deleting ACL rule as a domain admin, should raise exception.") + self.assertRaisesRegex(Exception, "Only Root Admin can delete global ACL rules.", + NetworkACL.delete, acl_rule, self.domain_admin_apiclient) + + self.debug("Deleting ACL rule as a root admin, should work.") + NetworkACL.delete(acl_rule, self.admin_apiclient) + self.cleanup.remove(acl_rule) + + # Verify if the number of ACL rules is equal to four, i.e. the number of rules + # for the default ACLs `default_allow` (2 rules) and `default_deny` (2 rules) ACLs + number_of_acl_rules = acl_rule.list(apiclient=self.admin_apiclient) + self.assertEqual(len(number_of_acl_rules), 4) + + return + + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_delete_global_acl(self): + """ Test delete global ACL as a normal user, domain admin and root admin users. + """ + + # Creating ACL list. Not adding to cleanup as it will be deleted in this method + acl = NetworkACLList.create(apiclient=self.apiclient, services={}, name="acl", description="acl") + self.cleanup.append(acl) + + self.debug("Deleting ACL list as a normal user, should raise exception.") + self.assertRaisesRegex(Exception, "Only Root Admin can delete global ACLs.", + NetworkACLList.delete, acl, apiclient=self.user_apiclient) + + self.debug("Deleting ACL list as a domain admin, should raise exception.") + self.assertRaisesRegex(Exception, "Only Root Admin can delete global ACLs.", + NetworkACLList.delete, acl, apiclient=self.domain_admin_apiclient) + + self.debug("Deleting ACL list as a root admin, should work.") + acl.delete(apiclient=self.admin_apiclient) + self.cleanup.remove(acl) + + # Verify if number of ACLs is equal to two, i.e. the number of default ACLs `default_allow` and `default_deny` + number_of_acls = NetworkACLList.list(apiclient=self.admin_apiclient) + self.assertEqual(len(number_of_acls), 2) + + return diff --git a/test/integration/smoke/test_guest_os.py b/test/integration/smoke/test_guest_os.py index 01fe34395e0..c9d50a7c523 100644 --- a/test/integration/smoke/test_guest_os.py +++ b/test/integration/smoke/test_guest_os.py @@ -181,7 +181,7 @@ class TestGuestOS(cloudstackTestCase): raise unittest.SkipTest("OS name check with hypervisor is supported only on XenServer and VMware") if self.hypervisor.hypervisor.lower() == "xenserver": - testosname="Debian Squeeze 6.0 (32-bit)" + testosname="Debian Jessie 8.0" else: testosname="debian4_64Guest" diff --git a/test/integration/smoke/test_host_ping.py b/test/integration/smoke/test_host_ping.py new file mode 100644 index 00000000000..6414553543a --- /dev/null +++ b/test/integration/smoke/test_host_ping.py @@ -0,0 +1,108 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" Check state transition of host from Alert to Up on Ping +""" + +# Import Local Modules +from marvin.cloudstackTestCase import * +from marvin.lib.common import * +from marvin.lib.utils import * +from nose.plugins.attrib import attr + +_multiprocess_shared_ = False + + +class TestHostPing(cloudstackTestCase): + + def setUp(self, handler=logging.StreamHandler()): + self.logger = logging.getLogger('TestHM') + self.stream_handler = handler + self.logger.setLevel(logging.DEBUG) + self.logger.addHandler(self.stream_handler) + self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() + self.mgtSvrDetails = self.config.__dict__["mgtSvr"][0].__dict__ + self.dbConnection = self.testClient.getDbConnection() + self.services = self.testClient.getParsedTestDataConfig() + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.pod = get_pod(self.apiclient, self.zone.id) + self.original_host_state_map = {} + self.cleanup = [] + + def tearDown(self): + for host_id in self.original_host_state_map: + state = self.original_host_state_map[host_id] + sql_query = "UPDATE host SET status = '" + state + "' WHERE uuid = '" + host_id + "'" + self.dbConnection.execute(sql_query) + super(TestHostPing, self).tearDown() + + def checkHostStateInCloudstack(self, state, host_id): + try: + listHost = Host.list( + self.apiclient, + type='Routing', + zoneid=self.zone.id, + podid=self.pod.id, + id=host_id + ) + self.assertEqual( + isinstance(listHost, list), + True, + "Check if listHost returns a valid response" + ) + + self.assertEqual( + len(listHost), + 1, + "Check if listHost returns a host" + ) + self.logger.debug(" Host state is %s " % listHost[0].state) + if listHost[0].state == state: + return True, 1 + else: + return False, 1 + except Exception as e: + self.logger.debug("Got exception %s" % e) + return False, 1 + + @attr( + tags=[ + "advanced", + "advancedns", + "smoke", + "basic"], + required_hardware="true") + def test_01_host_ping_on_alert(self): + listHost = Host.list( + self.apiclient, + type='Routing', + zoneid=self.zone.id, + podid=self.pod.id, + ) + for host in listHost: + self.logger.debug('Hypervisor = {}'.format(host.id)) + + hostToTest = listHost[0] + self.original_host_state_map[hostToTest.id] = hostToTest.state + sql_query = "UPDATE host SET status = 'Alert' WHERE uuid = '" + hostToTest.id + "'" + self.dbConnection.execute(sql_query) + + hostUpInCloudstack = wait_until(30, 8, self.checkHostStateInCloudstack, "Up", hostToTest.id) + + if not (hostUpInCloudstack): + raise self.fail("Host is not up %s, in cloudstack so failing test " % (hostToTest.ipaddress)) + return diff --git a/test/integration/smoke/test_host_tags.py b/test/integration/smoke/test_host_tags.py new file mode 100644 index 00000000000..b6bfe79148d --- /dev/null +++ b/test/integration/smoke/test_host_tags.py @@ -0,0 +1,160 @@ +# 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. +""" Tests for importVolume and unmanageVolume APIs +""" +# Import Local Modules +from marvin.cloudstackAPI import updateHost +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.lib.base import Host +from marvin.lib.utils import is_server_ssh_ready, wait_until + +# Import System modules +from nose.plugins.attrib import attr + +import logging + +class TestHostTags(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestHostTags, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.hypervisor = testClient.getHypervisorInfo() + if cls.testClient.getHypervisorInfo().lower() != "kvm": + raise unittest.SkipTest("This is only available for KVM") + + cls.hostConfig = cls.config.__dict__["zones"][0].__dict__["pods"][0].__dict__["clusters"][0].__dict__["hosts"][0].__dict__ + + hosts = Host.list( + cls.apiclient, + type = "Routing", + hypervisor = cls.hypervisor + ) + if isinstance(hosts, list) and len(hosts) > 0: + cls.host = hosts[0] + else: + raise unittest.SkipTest("No available host for this test") + + cls.logger = logging.getLogger("TestHostTags") + cls.stream_handler = logging.StreamHandler() + cls.logger.setLevel(logging.DEBUG) + cls.logger.addHandler(cls.stream_handler) + + @classmethod + def tearDownClass(cls): + cls.update_host_tags_via_api(cls.host.hosttags) + cls.update_implicit_host_tags_via_agent_properties(cls.host.implicithosttags) + + @classmethod + def update_host_tags_via_api(cls, hosttags): + cmd = updateHost.updateHostCmd() + cmd.id = cls.host.id + cmd.hosttags = hosttags + cls.apiclient.updateHost(cmd) + + @classmethod + def update_implicit_host_tags_via_agent_properties(cls, implicithosttags): + ssh_client = is_server_ssh_ready( + cls.host.ipaddress, + 22, + cls.hostConfig["username"], + cls.hostConfig["password"], + ) + if implicithosttags: + command = "sed -i '/host.tags=/d' /etc/cloudstack/agent/agent.properties \ + && echo 'host.tags=%s' >> /etc/cloudstack/agent/agent.properties \ + && systemctl restart cloudstack-agent" % implicithosttags + else: + command = "sed -i '/host.tags=/d' /etc/cloudstack/agent/agent.properties \ + && systemctl restart cloudstack-agent" + + ssh_client.execute(command) + + def wait_until_host_is_up_and_verify_hosttags(self, explicithosttags, implicithosttags, interval=3, retries=20): + def check_host_state(): + hosts = Host.list( + self.apiclient, + id=self.host.id + ) + if isinstance(hosts, list) and len(hosts) > 0: + host = hosts[0] + if host.state == "Up": + self.logger.debug("Host %s is in Up state" % host.name) + self.logger.debug("Host explicithosttags is %s, implicit hosttags is %s" % (host.explicithosttags, host.implicithosttags)) + if explicithosttags: + self.assertEquals(explicithosttags, host.explicithosttags) + else: + self.assertIsNone(host.explicithosttags) + if implicithosttags: + self.assertEquals(implicithosttags, host.implicithosttags) + else: + self.assertIsNone(host.implicithosttags) + return True, None + else: + self.logger.debug("Waiting for host %s to be Up state, current state is %s" % (host.name, host.state)) + return False, None + + done, _ = wait_until(interval, retries, check_host_state) + if not done: + raise Exception("Failed to wait for host %s to be Up" % self.host.name) + return True + + @attr(tags=['advanced', 'basic', 'sg'], required_hardware=False) + def test_01_host_tags(self): + """Test implicit/explicit host tags + """ + + # update explicit host tags to "s1,s2" + explicithosttags="s1,s2" + implicithosttags=self.host.implicithosttags + self.update_host_tags_via_api(explicithosttags) + self.wait_until_host_is_up_and_verify_hosttags(explicithosttags, implicithosttags) + + # update implicit host tags to "d1,d2" + implicithosttags="d1,d2" + self.update_implicit_host_tags_via_agent_properties(implicithosttags) + self.wait_until_host_is_up_and_verify_hosttags(explicithosttags, implicithosttags) + + # update explicit host tags to "s3,s4" + explicithosttags="s3,s4" + self.update_host_tags_via_api(explicithosttags) + self.wait_until_host_is_up_and_verify_hosttags(explicithosttags, implicithosttags) + + # update implicit host tags to "d3,d4" + implicithosttags="d3,d4" + self.update_implicit_host_tags_via_agent_properties(implicithosttags) + self.wait_until_host_is_up_and_verify_hosttags(explicithosttags, implicithosttags) + + # update hosttags to "" + explicithosttags="" + self.update_host_tags_via_api(explicithosttags) + self.wait_until_host_is_up_and_verify_hosttags(explicithosttags, implicithosttags) + + # update implicit host tags to "" + implicithosttags="" + self.update_implicit_host_tags_via_agent_properties(implicithosttags) + self.wait_until_host_is_up_and_verify_hosttags(explicithosttags, implicithosttags) + + # update explicit host tags to "s1,s2" + explicithosttags="s1,s2" + self.update_host_tags_via_api(explicithosttags) + self.wait_until_host_is_up_and_verify_hosttags(explicithosttags, implicithosttags) + + # update implicit host tags to "d1,d2" + implicithosttags="d1,d2" + self.update_implicit_host_tags_via_agent_properties(implicithosttags) + self.wait_until_host_is_up_and_verify_hosttags(explicithosttags, implicithosttags) diff --git a/test/integration/smoke/test_image_store_object_migration.py b/test/integration/smoke/test_image_store_object_migration.py new file mode 100644 index 00000000000..fcd10d70e2e --- /dev/null +++ b/test/integration/smoke/test_image_store_object_migration.py @@ -0,0 +1,233 @@ +# 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. + +""" Image store object migration test +""" +import logging + +#Import Local Modules +from marvin.cloudstackException import * +from marvin.cloudstackAPI import * +from marvin.codes import FAILED +from marvin.cloudstackTestCase import cloudstackTestCase +import unittest +from marvin.cloudstackAPI import listZones +from marvin.lib.utils import random_gen, cleanup_resources +from marvin.lib.base import (Template, + ImageStore) +from marvin.lib.common import (get_domain, + get_zone, + get_template) +from nose.plugins.attrib import attr +import urllib.request, urllib.parse, urllib.error +#Import System modules +import time +from marvin.cloudstackAPI import (createTemplate, listOsTypes) + +_multiprocess_shared_ = True + +class TestImageStoreObjectMigration(cloudstackTestCase): + """Test Image Store Object migration + """ + def setUp(self): + self.testClient = super(TestImageStoreObjectMigration, self).getClsTestClient() + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + self.services = self.testClient.getParsedTestDataConfig() + self.unsupportedHypervisor = False + self.hypervisor = self.testClient.getHypervisorInfo() + if self.hypervisor.lower() in ['lxc']: + # Template creation from root volume is not supported in LXC + self.unsupportedHypervisor = True + return + + # Get Zone, Domain and templates + self.domain = get_domain(self.apiclient) + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + + if "kvm" in self.hypervisor.lower(): + self.test_template = registerTemplate.registerTemplateCmd() + self.test_template = registerTemplate.registerTemplateCmd() + self.test_template.checksum = "{SHA-1}" + "6952e58f39b470bd166ace11ffd20bf479bed936" + self.test_template.hypervisor = self.hypervisor + self.test_template.zoneid = self.zone.id + self.test_template.name = 'test sha-2333' + self.test_template.displaytext = 'test sha-1' + self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-kvm.qcow2.bz2" + self.test_template.format = "QCOW2" + self.test_template.ostypeid = self.getOsType("Other Linux (64-bit)") + self.md5 = "88c60fd500ce7ced985cf845df0db9da" + self.sha256 = "bc4cc040bbab843000fab78db6cb4a33f3a06ae1ced2cf563d36b38c7fee3049" + + if "vmware" in self.hypervisor.lower(): + self.test_template = registerTemplate.registerTemplateCmd() + self.test_template = registerTemplate.registerTemplateCmd() + self.test_template.checksum = "{SHA-1}" + "8b82224fd3c6429b6914f32d8339e650770c7526" + self.test_template.hypervisor = self.hypervisor + self.test_template.zoneid = self.zone.id + self.test_template.name = 'test sha-2333' + self.test_template.displaytext = 'test sha-1' + self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-vmware.ova" + self.test_template.format = "OVA" + self.test_template.ostypeid = self.getOsType("Other Linux (64-bit)") + self.md5 = "b4e8bff3882b23175974e692533b4381" + self.sha256 = "e1dffca3c3ab545a753cb42d838a341624cf25841d1bcf3d1e45556c9fce7cf3" + + if "xen" in self.hypervisor.lower(): + self.test_template = registerTemplate.registerTemplateCmd() + self.test_template = registerTemplate.registerTemplateCmd() + self.test_template.checksum = "{SHA-1}" + "80af2c18f96e94273188808c3d56e561a1cda717" + self.test_template.hypervisor = self.hypervisor + self.test_template.zoneid = self.zone.id + self.test_template.name = 'test sha-2333' + self.test_template.displaytext = 'test sha-1' + self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-xen.vhd.bz2" + self.test_template.format = "VHD" + self.test_template.ostypeid = self.getOsType("Other Linux (64-bit)") + self.md5 = "1662bbf224e41bb62b1dee043d785731" + self.sha256 = "80fba5a7a83842ec4e5f67cc6755d61d4fca46ae170d59b0c6ed47ebf7162722" + + if self.unsupportedHypervisor: + self.skipTest("Skipping test because unsupported hypervisor\ + %s" % self.hypervisor) + return + + def tearDown(self): + try: + # Clean up the created templates + for temp in self.cleanup: + cmd = deleteTemplate.deleteTemplateCmd() + cmd.id = temp.id + cmd.zoneid = self.zone.id + self.apiclient.deleteTemplate(cmd) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advanced", "basic", "smoke"], required_hardware="true") + def test_01_browser_migrate_template(self): + """ + Test storage browser and template migration to another secondary storage + """ + template = self.registerTemplate(self.test_template) + self.download(self.apiclient, template.id) + + list_template_response=Template.list( + self.apiclient, + id=template.id, + templatefilter="all", + zoneid=self.zone.id) + + datastoreid = list_template_response[0].downloaddetails[0].datastoreId + + qresultset = self.dbclient.execute( + "select account_id, id from vm_template where uuid = '%s';" + % template.id + ) + + account_id = qresultset[0][0] + template_id = qresultset[0][1] + + originalSecondaryStore = ImageStore({"id": datastoreid}) + + storeObjects = originalSecondaryStore.listObjects(self.apiclient, path="template/tmpl/" + str(account_id) + "/" + str(template_id)) + + self.assertGreaterEqual(len(storeObjects), 2, "Check template is uploaded on secondary storage") + + # Migrate template to another secondary storage + secondaryStores = ImageStore.list(self.apiclient, zoneid=self.zone.id) + + if len(secondaryStores) < 2: + self.skipTest("Only one secondary storage available hence skipping") + + for store in secondaryStores: + if store.id != datastoreid: + destSecondaryStore = ImageStore({"id": store.id}) + break + + originalSecondaryStore.migrateResources(self.apiclient, destSecondaryStore.id, templateIdList=[template.id]) + + try: + originalSecondaryStore.listObjects(self.apiclient, path="template/tmpl/" + str(account_id) + "/" + str(template_id)) + except Exception as exc: + self.assertTrue("template/tmpl/" + str(account_id) + "/" + str(template_id) + " doesn't exist in store" in str(exc), + "Check template is deleted from original secondary storage") + else: + self.fail("Template is not deleted from original secondary storage") + + storeObjects = destSecondaryStore.listObjects(self.apiclient, path="template/tmpl/" + str(account_id) + "/" + str(template_id)) + + self.assertGreaterEqual(len(storeObjects), 2, "Check template is uploaded on destination secondary storage") + + def registerTemplate(self, cmd): + temp = self.apiclient.registerTemplate(cmd)[0] + if not temp: + self.cleanup.append(temp) + return temp + + def getOsType(self, param): + cmd = listOsTypes.listOsTypesCmd() + cmd.description = param + return self.apiclient.listOsTypes(cmd)[0].id + + def download(self, apiclient, template_id, retries=12, interval=5): + """Check if template download will finish in 1 minute""" + while retries > -1: + time.sleep(interval) + template_response = Template.list( + apiclient, + id=template_id, + zoneid=self.zone.id, + templatefilter='self' + ) + + if isinstance(template_response, list): + template = template_response[0] + if not hasattr(template, 'status') or not template or not template.status: + retries = retries - 1 + continue + + # If template is ready, + # template.status = Download Complete + # Downloading - x% Downloaded + # if Failed + # Error - Any other string + if 'Failed' in template.status: + raise Exception( + "Failed to download template: status - %s" % + template.status) + + elif template.status == 'Download Complete' and template.isready: + return + + elif 'Downloaded' in template.status: + retries = retries - 1 + continue + + elif 'Installing' not in template.status: + if retries >= 0: + retries = retries - 1 + continue + raise Exception( + "Error in downloading template: status - %s" % + template.status) + + else: + retries = retries - 1 + raise Exception("Template download failed exception.") diff --git a/test/integration/smoke/test_import_unmanage_volumes.py b/test/integration/smoke/test_import_unmanage_volumes.py new file mode 100644 index 00000000000..9001e97a79e --- /dev/null +++ b/test/integration/smoke/test_import_unmanage_volumes.py @@ -0,0 +1,167 @@ +# 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. +""" Tests for importVolume and unmanageVolume APIs +""" +# Import Local Modules +from marvin.cloudstackAPI import unmanageVolume, listVolumesForImport, importVolume +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.codes import FAILED +from marvin.lib.base import (Account, + Domain, + Volume, + ServiceOffering, + DiskOffering, + VirtualMachine) +from marvin.lib.common import (get_domain, get_zone, get_suitable_test_template) + +# Import System modules +from nose.plugins.attrib import attr + +_multiprocess_shared_ = True + + +class TestImportAndUnmanageVolumes(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestImportAndUnmanageVolumes, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.testdata = cls.testClient.getParsedTestDataConfig() + + cls.services = testClient.getParsedTestDataConfig() + cls.hypervisor = testClient.getHypervisorInfo() + if cls.testClient.getHypervisorInfo().lower() != "kvm": + raise unittest.SkipTest("This is only available for KVM") + + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient) + cls._cleanup = [] + + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["tiny"] + ) + cls._cleanup.append(cls.service_offering) + + template = get_suitable_test_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"], + cls.hypervisor + ) + if template == FAILED: + assert False, "get_test_template() failed to return template" + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["mode"] = cls.zone.networktype + + cls.disk_offering = DiskOffering.create(cls.apiclient, + cls.services["disk_offering"]) + cls._cleanup.append(cls.disk_offering) + + cls.test_domain = Domain.create( + cls.apiclient, + cls.services["domain"]) + cls._cleanup.append(cls.test_domain) + + cls.test_account = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.test_domain.id) + cls._cleanup.append(cls.test_account) + + # Create VM + cls.virtual_machine = VirtualMachine.create( + cls.apiclient, + cls.services["virtual_machine"], + templateid=template.id, + accountid=cls.test_account.name, + domainid=cls.test_account.domainid, + serviceofferingid=cls.service_offering.id, + mode=cls.services["mode"] + ) + cls._cleanup.append(cls.virtual_machine) + + cls.virtual_machine.stop(cls.apiclient, forced=True) + + @classmethod + def tearDownClass(cls): + super(TestImportAndUnmanageVolumes, cls).tearDownClass() + + @attr(tags=['advanced', 'basic', 'sg'], required_hardware=False) + def test_01_detach_unmanage_import_volume(self): + """Test attach/detach/unmanage/import volume + """ + # Create DATA volume + volume = Volume.create( + self.apiclient, + self.testdata["volume"], + zoneid=self.zone.id, + account=self.test_account.name, + domainid=self.test_account.domainid, + diskofferingid=self.disk_offering.id + ) + + # Attach and Detach volume + try: + self.virtual_machine.attach_volume(self.apiclient, volume) + except Exception as e: + self.fail("Attach volume failed with Exception: %s" % e) + + self.virtual_machine.detach_volume(self.apiclient, volume) + + # List volume by id + volumes = Volume.list(self.apiclient, + id = volume.id) + self.assertTrue(isinstance(volumes, list), + "listVolumes response should return a valid list" + ) + self.assertTrue(len(volumes) > 0, + "listVolumes response should return a non-empty list" + ) + volume = volumes[0] + + # Unmanage volume + cmd = unmanageVolume.unmanageVolumeCmd() + cmd.id = volume.id + self.apiclient.unmanageVolume(cmd) + + # List VMs for import + cmd = listVolumesForImport.listVolumesForImportCmd() + cmd.storageid = volume.storageid + volumesForImport = self.apiclient.listVolumesForImport(cmd) + self.assertTrue(isinstance(volumesForImport, list), + "Check listVolumesForImport response returns a valid list" + ) + + # Import volume + cmd = importVolume.importVolumeCmd() + cmd.storageid = volume.storageid + cmd.path = volume.path + self.apiclient.importVolume(cmd) + + # List volume by name + volumes = Volume.list(self.apiclient, + storageid = volume.storageid, + name=volume.path) + self.assertTrue(isinstance(volumes, list), + "listVolumes response should return a valid list" + ) + self.assertTrue(len(volumes) > 0, + "listVolumes response should return a non-empty list" + ) diff --git a/test/integration/smoke/test_kubernetes_clusters.py b/test/integration/smoke/test_kubernetes_clusters.py index c18711e7dde..20f1cb3224a 100644 --- a/test/integration/smoke/test_kubernetes_clusters.py +++ b/test/integration/smoke/test_kubernetes_clusters.py @@ -283,13 +283,15 @@ class TestKubernetesCluster(cloudstackTestCase): cls.apiclient.deleteKubernetesSupportedVersion(deleteKubernetesSupportedVersionCmd) @classmethod - def listKubernetesCluster(cls, cluster_id = None): + def listKubernetesCluster(cls, cluster_id = None, cluster_name = None): listKubernetesClustersCmd = listKubernetesClusters.listKubernetesClustersCmd() listKubernetesClustersCmd.listall = True if cluster_id != None: listKubernetesClustersCmd.id = cluster_id + if cluster_name != None: + listKubernetesClustersCmd.name = cluster_name clusterResponse = cls.apiclient.listKubernetesClusters(listKubernetesClustersCmd) - if cluster_id != None and clusterResponse != None: + if (cluster_id != None or cluster_name != None) and clusterResponse != None: return clusterResponse[0] return clusterResponse @@ -528,28 +530,10 @@ class TestKubernetesCluster(cloudstackTestCase): return - @attr(tags=["advanced", "smoke"], required_hardware="true") - @skipTestIf("hypervisorNotSupported") - def test_07_deploy_kubernetes_ha_cluster(self): - """Test to deploy a new Kubernetes cluster - - # Validate the following: - # 1. createKubernetesCluster should return valid info for new cluster - # 2. The Cloud Database contains the valid information - """ - if self.setup_failed == True: - self.fail("Setup incomplete") - if self.default_network: - self.skipTest("HA cluster on shared network requires external ip address, skipping it") - global k8s_cluster - k8s_cluster = self.getValidKubernetesCluster(1, 2) - self.debug("HA Kubernetes cluster with ID: %s successfully deployed" % k8s_cluster.id) - return - @attr(tags=["advanced", "smoke"], required_hardware="true") @skipTestIf("hypervisorNotSupported") def test_08_upgrade_kubernetes_ha_cluster(self): - """Test to upgrade a Kubernetes cluster to newer version + """Test to upgrade a HA Kubernetes cluster to newer version # Validate the following: # 1. upgradeKubernetesCluster should return valid info for the cluster @@ -559,7 +543,7 @@ class TestKubernetesCluster(cloudstackTestCase): if self.default_network: self.skipTest("HA cluster on shared network requires external ip address, skipping it") global k8s_cluster - k8s_cluster = self.getValidKubernetesCluster(1, 2, version=self.kubernetes_version_v1) + k8s_cluster = self.getValidKubernetesCluster(1, 3, version=self.kubernetes_version_v1) time.sleep(self.services["sleep"]) self.debug("Upgrading HA Kubernetes cluster with ID: %s" % k8s_cluster.id) @@ -573,24 +557,6 @@ class TestKubernetesCluster(cloudstackTestCase): self.debug("Kubernetes cluster with ID: %s successfully upgraded" % k8s_cluster.id) return - @attr(tags=["advanced", "smoke"], required_hardware="true") - @skipTestIf("hypervisorNotSupported") - def test_09_delete_kubernetes_ha_cluster(self): - """Test to delete a HA Kubernetes cluster - - # Validate the following: - # 1. deleteKubernetesCluster should delete an existing HA Kubernetes cluster - """ - if self.setup_failed == True: - self.fail("Setup incomplete") - if self.default_network: - self.skipTest("HA cluster on shared network requires external ip address, skipping it") - global k8s_cluster - k8s_cluster = self.getValidKubernetesCluster(1, 2) - - self.debug("Deleting Kubernetes cluster with ID: %s" % k8s_cluster.id) - return - @attr(tags=["advanced", "smoke"], required_hardware="true") @skipTestIf("hypervisorNotSupported") def test_10_vpc_tier_kubernetes_cluster(self): @@ -800,7 +766,7 @@ class TestKubernetesCluster(cloudstackTestCase): self.verifyKubernetesCluster(cluster, cluster.name, None, size, control_nodes) self.debug("Existing Kubernetes cluster available with name %s" % cluster.name) return cluster - except AssertionError as error: + except AssertionError as error: self.debug("Existing cluster failed verification due to %s, need to deploy a new one" % error) self.deleteKubernetesClusterAndVerify(cluster.id, False, True) @@ -818,8 +784,14 @@ class TestKubernetesCluster(cloudstackTestCase): cluster = self.createKubernetesCluster(name, version.id, size, control_nodes) self.verifyKubernetesCluster(cluster, name, version.id, size, control_nodes) except Exception as ex: + cluster = self.listKubernetesCluster(cluster_name = name) + if cluster != None: + self.deleteKubernetesClusterAndVerify(cluster.id, False, True) self.fail("Kubernetes cluster deployment failed: %s" % ex) except AssertionError as err: + cluster = self.listKubernetesCluster(cluster_name = name) + if cluster != None: + self.deleteKubernetesClusterAndVerify(cluster.id, False, True) self.fail("Kubernetes cluster deployment failed during cluster verification: %s" % err) return cluster diff --git a/test/integration/smoke/test_list_accounts.py b/test/integration/smoke/test_list_accounts.py new file mode 100644 index 00000000000..1cce3cef170 --- /dev/null +++ b/test/integration/smoke/test_list_accounts.py @@ -0,0 +1,379 @@ +# 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. +""" Tests for API listing of accounts with different filters +""" + +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import (Account, + Domain) +from marvin.lib.common import (get_domain, list_accounts) +# Import System modules +from nose.plugins.attrib import attr + +_multiprocess_shared_ = True + + +class TestListAccounts(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestListAccounts, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls.domain = get_domain(cls.apiclient) + cls.account = list_accounts(cls.apiclient, name="admin")[0] + cls._cleanup = [] + cls.accounts = list_accounts(cls.apiclient, listall=True) + + cls.child_domain_1 = Domain.create( + cls.apiclient, + cls.services["domain"], + parentdomainid=cls.domain.id + ) + cls._cleanup.append(cls.child_domain_1) + + cls.services["account"]["username"] = "child_account_admin" + cls.child_account_admin = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.child_domain_1.id + ) + cls._cleanup.append(cls.child_account_admin) + + cls.services["username"] = "child_account_user" + cls.child_account_user = Account.create( + cls.apiclient, + cls.services["account"], + admin=0, + domainid=cls.child_domain_1.id + ) + cls.child_account_user.disable(cls.apiclient) + cls._cleanup.append(cls.child_account_user) + + cls.child_domain_2 = Domain.create( + cls.apiclient, + cls.services["domain"], + parentdomainid=cls.domain.id + ) + cls._cleanup.append(cls.child_domain_2) + + @classmethod + def tearDownClass(cls): + super(TestListAccounts, cls).tearDownClass() + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_01_list_accounts_accounttype_filter(self): + """Test listing accounts with accounttype filter + """ + list_account_response = Account.list( + self.apiclient, + accounttype=0, + domainid=self.child_domain_1.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + len(list_account_response), + 1, + "List Account response has incorrect length" + ) + self.assertEqual( + list_account_response[0].name, + self.child_account_user.name, + "Check for list response return valid data" + ) + self.assertEqual( + list_account_response[0].accounttype, + 0, + "Check for list response return valid data" + ) + + list_account_response = Account.list( + self.apiclient, + accounttype=2, + domainid=self.child_domain_1.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + len(list_account_response), + 1, + "List Account response has incorrect length" + ) + self.assertEqual( + list_account_response[0].name, + self.child_account_admin.name, + "Check for list response return valid data" + ) + self.assertEqual( + list_account_response[0].accounttype, + 2, + "Check for list response return valid data" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_02_list_accounts_domainid_filter(self): + """Test listing accounts with domainid filter + """ + list_account_response = Account.list( + self.apiclient, + domainid=self.child_domain_1.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + len(list_account_response), + 2, + "List Account response has incorrect length" + ) + self.assertEqual( + self.child_domain_1.id, + list_account_response[0].domainid, + "Check for list response return valid data" + ) + self.assertEqual( + self.child_domain_1.id, + list_account_response[1].domainid, + "Check for list response return valid data" + ) + + list_account_response = Account.list( + self.apiclient, + domainid=self.child_domain_2.id + ) + self.assertIsNone(list_account_response, "Check for list response return valid data") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_03_list_accounts_id_filter(self): + """Test listing accounts with id filter + """ + list_account_response = Account.list( + self.apiclient, + id=self.child_account_user.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + len(list_account_response), + 1, + "List Account response has incorrect length" + ) + self.assertEqual( + list_account_response[0].name, + self.child_account_user.name, + "Expected account name and actual account name should be same" + ) + + list_account_response = Account.list( + self.apiclient, + id=self.child_account_admin.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + len(list_account_response), + 1, + "List Account response has incorrect length" + ) + self.assertEqual( + list_account_response[0].name, + self.child_account_admin.name, + "Expected account name and actual account name should be same" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_04_list_accounts_name_filter(self): + """Test listing accounts with name filter + """ + list_account_response = Account.list( + self.apiclient, + name=self.child_account_user.name, + domainid=self.child_domain_1.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + len(list_account_response), + 1, + "List Account response has incorrect length" + ) + self.assertEqual( + list_account_response[0].name, + self.child_account_user.name, + "Expected account name and actual account name should be same" + ) + + list_account_response = Account.list( + self.apiclient, + name=self.child_account_admin.name, + domainid=self.child_domain_1.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + len(list_account_response), + 1, + "List Account response has incorrect length" + ) + self.assertEqual( + list_account_response[0].name, + self.child_account_admin.name, + "Expected account name and actual account name should be same" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_05_list_accounts_state_filter(self): + """Test listing accounts with state filter + """ + list_account_response = Account.list( + self.apiclient, + state="enabled", + domainid=self.child_domain_1.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + len(list_account_response), + 1, + "List Account response has incorrect length" + ) + self.assertEqual( + list_account_response[0].name, + self.child_account_admin.name, + "Expected account name and actual account name should be same" + ) + + list_account_response = Account.list( + self.apiclient, + state="disabled", + domainid=self.child_domain_1.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + len(list_account_response), + 1, + "List Account response has incorrect length" + ) + self.assertEqual( + list_account_response[0].name, + self.child_account_user.name, + "Expected account name and actual account name should be same" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_06_list_accounts_keyword_filter(self): + """Test listing accounts with keyword filter + """ + list_account_response = Account.list( + self.apiclient, + keyword=self.child_account_user.name, + domainid=self.child_domain_1.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + self.child_account_user.name, + list_account_response[0].name, + "Expected account name and actual account name should be same" + ) + + list_account_response = Account.list( + self.apiclient, + keyword=self.child_account_admin.name, + domainid=self.child_domain_1.id + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + self.child_account_admin.name, + list_account_response[0].name, + "Expected account name and actual account name should be same" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_07_list_accounts_with_listall_filters(self): + """Test listing accounts with listall filters + """ + list_account_response = Account.list( + self.apiclient, + listall=False + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + 1, + len(list_account_response), + "List Account response has incorrect length" + ) + + list_account_response = Account.list( + self.apiclient, + listall=True + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + 2, + len(list_account_response) - len(self.accounts), + "List Account response has incorrect length" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_08_list_accounts_with_no_filters(self): + """Test listing accounts with no filters + """ + list_account_response = Account.list( + self.apiclient + ) + self.assertTrue( + isinstance(list_account_response, list), + "List Account response is not a valid list" + ) + self.assertEqual( + 1, + len(list_account_response), + "List Account response has incorrect length" + ) diff --git a/test/integration/smoke/test_list_disk_offerings.py b/test/integration/smoke/test_list_disk_offerings.py new file mode 100644 index 00000000000..6319ea338ad --- /dev/null +++ b/test/integration/smoke/test_list_disk_offerings.py @@ -0,0 +1,319 @@ +# 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. +""" Tests for API listing of disk offerings with different filters +""" +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.codes import FAILED +from marvin.lib.base import (Account, + Domain, + Volume, + ServiceOffering, + DiskOffering, + VirtualMachine) +from marvin.lib.common import (get_domain, list_accounts, + list_zones, list_clusters, list_hosts) +# Import System modules +from nose.plugins.attrib import attr + +_multiprocess_shared_ = True + + +class TestListDiskOfferings(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestListDiskOfferings, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls.hypervisor = testClient.getHypervisorInfo() + cls.domain = get_domain(cls.apiclient) + cls.zones = list_zones(cls.apiclient) + cls.zone = cls.zones[0] + cls.clusters = list_clusters(cls.apiclient) + cls.cluster = cls.clusters[0] + cls.hosts = list_hosts(cls.apiclient) + cls.account = list_accounts(cls.apiclient, name="admin")[0] + cls._cleanup = [] + cls.disk_offerings = DiskOffering.list(cls.apiclient, listall=True) + + cls.disk_offering = DiskOffering.create(cls.apiclient, + cls.services["disk_offering"], + domainid=cls.domain.id) + cls._cleanup.append(cls.disk_offering) + + cls.child_domain_1 = Domain.create( + cls.apiclient, + cls.services["domain"], + parentdomainid=cls.domain.id + ) + cls._cleanup.append(cls.child_domain_1) + + cls.account_1 = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls._cleanup.append(cls.account_1) + + cls.domainadmin_api_client = testClient.getUserApiClient( + UserName=cls.account_1.user[0].username, + DomainName=cls.domain.name, + type=2 + ) + + cls.disk_offering_child_domain = DiskOffering.create(cls.apiclient, + cls.services["disk_offering"], + domainid=cls.child_domain_1.id, + zoneid=cls.zone.id, + encrypt=True) + cls._cleanup.append(cls.disk_offering_child_domain) + + @classmethod + def tearDownClass(cls): + super(TestListDiskOfferings, cls).tearDownClass() + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_01_list_disk_offerings_id_filter(self): + """ Test list disk offerings with id filter + """ + # List all disk offerings + disk_offerings = DiskOffering.list(self.apiclient, id=self.disk_offering.id) + self.assertTrue( + isinstance(disk_offerings, list), + "List disk offerings response is not a valid list" + ) + self.assertEqual( + len(disk_offerings), + 1, + "List disk offerings response has incorrect length" + ) + # Verify the id of the disk offering returned is the same as the one requested + self.assertEqual( + disk_offerings[0].id, + self.disk_offering.id, + "List disk offerings should return the disk offering requested" + ) + + disk_offerings = DiskOffering.list(self.apiclient, id=-1) + self.assertIsNone(disk_offerings, "List disk offerings response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_02_list_disk_offerings_name_filter(self): + """ Test list disk offerings with name filter + """ + disk_offerings = DiskOffering.list(self.apiclient, name=self.services["disk_offering"]["name"]) + self.assertTrue( + isinstance(disk_offerings, list), + "List disk offerings response is not a valid list" + ) + self.assertEqual( + len(disk_offerings), + 2, + "List disk offerings response has incorrect length" + ) + # Verify the name of the disk offering returned is the same as the one requested + self.assertEqual( + disk_offerings[0].name, + self.services["disk_offering"]["name"], + "List disk offerings should return the disk offering requested" + ) + self.assertEqual( + disk_offerings[1].name, + self.services["disk_offering"]["name"], + "List disk offerings should return the disk offering requested" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_03_list_disk_offerings_zoneid_filter(self): + """ Test list disk offerings with zoneid filter + """ + disk_offerings_zone_1 = DiskOffering.list(self.apiclient, zoneid=self.zone.id) + self.assertTrue( + isinstance(disk_offerings_zone_1, list), + "List disk offerings response is not a valid list" + ) + self.assertEqual( + len(disk_offerings_zone_1) - len(self.disk_offerings), + 2, + "List disk offerings response has incorrect length" + ) + + for disk_offering in disk_offerings_zone_1: + self.assertTrue( + disk_offering.zoneid is None or disk_offering.zoneid == self.zone.id, + "List disk offerings should return the disk offering requested" + ) + + if len(self.zones) > 1: + disk_offerings_zone_2 = DiskOffering.list(self.apiclient, zoneid=self.zones[1].id) + self.assertTrue( + isinstance(disk_offerings_zone_2, list), + "List disk offerings response is not a valid list" + ) + for disk_offering in disk_offerings_zone_2: + self.assertTrue( + disk_offering.zoneid is None or disk_offering.zoneid == self.zones[1].id, + "List disk offerings should return the disk offering requested" + ) + + self.assertEqual(len(disk_offerings_zone_1) - len(disk_offerings_zone_2), 1) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_04_list_disk_offerings_domainid_filter(self): + """ Test list disk offerings with domainid filter + """ + disk_offerings = DiskOffering.list(self.apiclient, domainid=self.domain.id) + self.assertTrue( + isinstance(disk_offerings, list), + "List disk offerings response is not a valid list" + ) + self.assertEqual( + len(disk_offerings), + 1, + "List disk offerings response has incorrect length" + ) + self.assertEqual( + disk_offerings[0].domainid, + self.domain.id, + "List disk offerings should return the disk offering requested" + ) + + disk_offerings = DiskOffering.list(self.apiclient, domainid=self.child_domain_1.id) + self.assertTrue( + isinstance(disk_offerings, list), + "List disk offerings response is not a valid list" + ) + self.assertEqual( + len(disk_offerings), + 1, + "List disk offerings response has incorrect length" + ) + self.assertEqual( + disk_offerings[0].domainid, + self.child_domain_1.id, + "List disk offerings should return the disk offering requested" + ) + + disk_offerings = DiskOffering.list(self.apiclient, domainid=-1) + self.assertIsNone(disk_offerings, "List disk offerings response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_05_list_disk_offerings_encrypted_filter(self): + """ Test list disk offerings with encrypted filter + """ + disk_offerings = DiskOffering.list(self.apiclient, encrypt=True) + self.assertTrue( + isinstance(disk_offerings, list), + "List disk offerings response is not a valid list" + ) + + self.assertEqual( + len(disk_offerings), + 1, + "List disk offerings response has incorrect length" + ) + self.assertTrue( + disk_offerings[0].encrypt, + "List disk offerings should return the disk offering requested" + ) + + disk_offerings = DiskOffering.list(self.apiclient, encrypt=False) + self.assertTrue( + isinstance(disk_offerings, list), + "List disk offerings response is not a valid list" + ) + self.assertEqual( + len(disk_offerings) - len(self.disk_offerings), + 1, + "List disk offerings response has incorrect length" + ) + for disk_offering in disk_offerings: + self.assertFalse( + disk_offering.encrypt, + "List disk offerings should return the disk offering requested" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_06_list_disk_offerings_keyword_filter(self): + """ Test list disk offerings with keyword filter + """ + disk_offerings = DiskOffering.list(self.apiclient, keyword=self.disk_offering.name) + self.assertTrue( + isinstance(disk_offerings, list), + "List disk offerings response is not a valid list" + ) + self.assertEqual( + len(disk_offerings), + 2, + "List disk offerings response has incorrect length" + ) + self.assertEqual( + disk_offerings[0].name, + self.disk_offering.name, + "List disk offerings should return the disk offering requested" + ) + self.assertEqual( + disk_offerings[1].name, + self.disk_offering.name, + "List disk offerings should return the disk offering requested" + ) + + disk_offerings = DiskOffering.list(self.apiclient, keyword="random") + self.assertIsNone(disk_offerings, "List disk offerings response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_07_list_disk_offering_isrecursive_filter(self): + """ Test list disk offerings with isrecursive parameter + """ + disk_offerings = DiskOffering.list(self.domainadmin_api_client, isrecursive=True) + self.assertTrue( + isinstance(disk_offerings, list), + "List disk offerings response is not a valid list" + ) + self.assertEqual( + len(disk_offerings) - len(self.disk_offerings), + 2, + "List disk offerings response has incorrect length" + ) + + disk_offerings = DiskOffering.list(self.domainadmin_api_client, isrecursive=False) + self.assertTrue( + isinstance(disk_offerings, list), + "List disk offerings response is not a valid list" + ) + self.assertEqual( + len(disk_offerings) - len(self.disk_offerings), + 1, + "List disk offerings response has incorrect length" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_08_list_disk_offering_no_filter(self): + """ Test list disk offerings with no filters + """ + disk_offerings = DiskOffering.list(self.apiclient) + self.assertTrue( + isinstance(disk_offerings, list), + "List disk offerings response is not a valid list" + ) + self.assertEqual( + len(disk_offerings) - len(self.disk_offerings), + 2, + "List disk offerings response has incorrect length" + ) diff --git a/test/integration/smoke/test_list_domains.py b/test/integration/smoke/test_list_domains.py new file mode 100644 index 00000000000..546ffbbf1e3 --- /dev/null +++ b/test/integration/smoke/test_list_domains.py @@ -0,0 +1,216 @@ +# 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. +""" Tests for API listing of domains with different filters +""" + +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import (Account, + Domain) +from marvin.lib.common import (get_domain, list_accounts) +# Import System modules +from nose.plugins.attrib import attr + +_multiprocess_shared_ = True + + +class TestListDomains(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestListDomains, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls.domain = get_domain(cls.apiclient) + cls.account = list_accounts(cls.apiclient, name="admin")[0] + cls._cleanup = [] + + cls.child_domain_1 = Domain.create( + cls.apiclient, + cls.services["domain"], + parentdomainid=cls.domain.id + ) + cls._cleanup.append(cls.child_domain_1) + + cls.child_account_1 = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.child_domain_1.id + ) + cls._cleanup.append(cls.child_account_1) + + cls.child_account_apiclient = testClient.getUserApiClient(cls.child_account_1.user[0]['username'], cls.child_domain_1.name, type=2) + + cls.child_domain_2 = Domain.create( + cls.apiclient, + cls.services["domain"], + parentdomainid=cls.child_domain_1.id + ) + cls._cleanup.append(cls.child_domain_2) + + @classmethod + def tearDownClass(cls): + super(TestListDomains, cls).tearDownClass() + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_01_list_domains_id_filter(self): + """ Test list domains with id filter + """ + # List all domains + domains = Domain.list(self.apiclient, id=self.domain.id) + self.assertEqual( + isinstance(domains, list), + True, + "List Domain response is not a valid list" + ) + self.assertEqual( + len(domains), + 1, + "List Domain response has incorrect length" + ) + self.assertEqual( + domains[0].id, + self.domain.id, + "Check if list domains returns valid domain" + ) + + # List all domains with a non-existent id + with self.assertRaises(Exception): + Domain.list(self.apiclient, id=-1) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_02_list_domains_name_filter(self): + """ Test list domains with name filter + """ + # List all domains + domains = Domain.list(self.apiclient, name=self.domain.name) + self.assertEqual( + isinstance(domains, list), + True, + "List Domain response is not a valid list" + ) + self.assertEqual( + len(domains), + 1, + "List Domain response has incorrect length" + ) + self.assertEqual( + domains[0].name, + self.domain.name, + "Check if list domains returns valid domain" + ) + + domains = Domain.list(self.apiclient, name="non-existent-domain") + self.assertIsNone(domains, "List Domain response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_03_list_domains_listall_filter(self): + """ Test list domains with listall parameter + """ + # List all domains + domains = Domain.list(self.child_account_apiclient, listall=True) + self.assertEqual( + isinstance(domains, list), + True, + "List Domain response is not a valid list" + ) + self.assertEqual( + len(domains), + 2, + "List Domain response has incorrect length" + ) + + domains = Domain.list(self.child_account_apiclient, listall=False) + self.assertEqual( + isinstance(domains, list), + True, + "List Domain response is not a valid list" + ) + self.assertEqual( + len(domains), + 1, + "List Domain response has incorrect length" + ) + self.assertEqual( + domains[0].id, + self.child_domain_1.id, + "Check if list domains returns valid domain" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_04_list_domains_level_filter(self): + """ Test list domains with level filter + """ + # List all domains + domains = Domain.list(self.apiclient, level=0) + self.assertEqual( + isinstance(domains, list), + True, + "List Domain response is not a valid list" + ) + self.assertEqual( + len(domains), + 1, + "List Domain response has incorrect length" + ) + self.assertEqual( + domains[0].id, + self.domain.id, + "Check if list domains returns valid domain" + ) + + domains = Domain.list(self.apiclient, level=1) + self.assertEqual( + isinstance(domains, list), + True, + "List Domain response is not a valid list" + ) + self.assertEqual( + len(domains), + 1, + "List Domain response has incorrect length" + ) + + domains = Domain.list(self.apiclient, level=2) + self.assertEqual( + isinstance(domains, list), + True, + "List Domain response is not a valid list" + ) + self.assertEqual( + len(domains), + 1, + "List Domain response has incorrect length" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_05_list_domains_no_filter(self): + """ Test list domains with no filter + """ + # List all domains + domains = Domain.list(self.apiclient) + self.assertEqual( + isinstance(domains, list), + True, + "List Domain response is not a valid list" + ) + self.assertEqual( + len(domains), + 3, + "List Domain response has incorrect length" + ) diff --git a/test/integration/smoke/test_list_hosts.py b/test/integration/smoke/test_list_hosts.py new file mode 100644 index 00000000000..7bae216d51d --- /dev/null +++ b/test/integration/smoke/test_list_hosts.py @@ -0,0 +1,372 @@ +# 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. +""" Tests for API listing of hosts with different filters +""" +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.codes import FAILED +from marvin.lib.base import (Configurations, Host) +from marvin.lib.common import (get_domain, list_accounts, + list_zones, list_clusters) +# Import System modules +from nose.plugins.attrib import attr + +_multiprocess_shared_ = True + + +class TestListHosts(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestListHosts, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls.hypervisor = testClient.getHypervisorInfo() + cls.zones = list_zones(cls.apiclient) + cls.zone = cls.zones[0] + cls.clusters = list_clusters(cls.apiclient) + cls.cluster = cls.clusters[0] + cls.hosts = Host.list(cls.apiclient) + + + @classmethod + def tearDownClass(cls): + super(TestListHosts, cls).tearDownClass() + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_01_list_hosts_no_filter(self): + """Test list hosts with no filter""" + hosts = Host.list(self.apiclient) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should greater than 0" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_02_list_hosts_clusterid_filter(self): + """Test list hosts with clusterid filter""" + hosts = Host.list(self.apiclient, clusterid=self.cluster.id) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should greater than 0" + ) + for host in hosts: + self.assertEqual( + host.clusterid, + self.cluster.id, + "Host should be in the cluster %s" % self.cluster.id + ) + with self.assertRaises(Exception): + hosts = Host.list(self.apiclient, clusterid="invalidclusterid") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_03_list_hosts_hahost_filter(self): + """Test list hosts with hahost filter""" + configs = Configurations.list( + self.apiclient, + name='ha.tag' + ) + if isinstance(configs, list) and configs[0].value != "" and configs[0].value is not None: + hosts = Host.list(self.apiclient, hahost=True) + if hosts is not None: + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should greater than 0" + ) + for host in hosts: + self.assertEqual( + host.hahost, + True, + "Host should be a HA host" + ) + + hosts = Host.list(self.apiclient, hahost=False) + if hosts is not None: + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should greater than 0" + ) + for host in hosts: + self.assertTrue( + host.hahost is None or host.hahost is False, + "Host should not be a HA host" + ) + else: + self.debug("HA is not enabled in the setup") + hosts = Host.list(self.apiclient, hahost="invalidvalue") + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should greater than 0" + ) + self.assertEqual( + len(hosts), + len(self.hosts), + "Length of host response should be equal to the length of hosts" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_04_list_hosts_hypervisor_filter(self): + """Test list hosts with hypervisor filter""" + hosts = Host.list(self.apiclient, hypervisor=self.hypervisor) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should greater than 0" + ) + for host in hosts: + self.assertEqual( + host.hypervisor.lower(), + self.hypervisor.lower(), + "Host should be a %s hypervisor" % self.hypervisor + ) + + hosts = Host.list(self.apiclient, hypervisor="invalidhypervisor") + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertEqual( + len(hosts), + len(self.hosts), + "Length of host response should be equal to the length of hosts" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_05_list_hosts_id_filter(self): + """Test list hosts with id filter""" + hosts = Host.list(self.apiclient, id=self.hosts[0].id) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertEqual( + len(hosts), + 1, + "Length of host response should be 1" + ) + self.assertEqual( + hosts[0].id, + self.hosts[0].id, + "Host id should match with the host id in the list" + ) + + with self.assertRaises(Exception): + hosts = Host.list(self.apiclient, id="invalidid") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_06_list_hosts_keyword_filter(self): + """Test list hosts with keyword filter""" + hosts = Host.list(self.apiclient, keyword=self.hosts[0].name) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should be greater than 0" + ) + for host in hosts: + self.assertIn( + host.name, + self.hosts[0].name, + "Host name should match with the host name in the list" + ) + + hosts = Host.list(self.apiclient, keyword="invalidkeyword") + self.assertIsNone( + hosts, + "Host response should be None" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_07_list_hosts_name_filter(self): + """Test list hosts with name filter""" + hosts = Host.list(self.apiclient, name=self.hosts[0].name) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should be greater than 0" + ) + for host in hosts: + self.assertIn( + host.name, + self.hosts[0].name, + "Host name should match with the host name in the list" + ) + + hosts = Host.list(self.apiclient, name="invalidname") + self.assertIsNone( + hosts, + "Host response should be None" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_08_list_hosts_podid_filter(self): + """Test list hosts with podid filter""" + hosts = Host.list(self.apiclient, podid=self.hosts[0].podid) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should be greater than 0" + ) + for host in hosts: + self.assertEqual( + host.podid, + self.hosts[0].podid, + "Host podid should match with the host podid in the list" + ) + with self.assertRaises(Exception): + hosts = Host.list(self.apiclient, podid="invalidpodid") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_09_list_hosts_resourcestate_filter(self): + """Test list hosts with resourcestate filter""" + hosts = Host.list(self.apiclient, resourcestate=self.hosts[0].resourcestate) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should be greater than 0" + ) + for host in hosts: + self.assertEqual( + host.resourcestate, + self.hosts[0].resourcestate, + "Host resourcestate should match with the host resourcestate in the list" + ) + + hosts = Host.list(self.apiclient, resourcestate="invalidresourcestate") + self.assertIsNone( + hosts, + "Host response should be None" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_10_list_hosts_state_filter(self): + """Test list hosts with state filter""" + hosts = Host.list(self.apiclient, state=self.hosts[0].state) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should be greater than 0" + ) + for host in hosts: + self.assertEqual( + host.state, + self.hosts[0].state, + "Host state should match with the host state in the list" + ) + + hosts = Host.list(self.apiclient, state="invalidstate") + self.assertIsNone( + hosts, + "Host response should be None" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_11_list_hosts_type_filter(self): + """Test list hosts with type filter""" + hosts = Host.list(self.apiclient, type=self.hosts[0].type) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should be greater than 0" + ) + for host in hosts: + self.assertEqual( + host.type, + self.hosts[0].type, + "Host type should match with the host type in the list" + ) + + hosts = Host.list(self.apiclient, type="invalidtype") + self.assertIsNone( + hosts, + "Host response should be None" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_12_list_hosts_zoneid_filter(self): + """Test list hosts with zoneid filter""" + hosts = Host.list(self.apiclient, zoneid=self.zone.id) + self.assertTrue( + isinstance(hosts, list), + "Host response type should be a valid list" + ) + self.assertGreater( + len(hosts), + 0, + "Length of host response should be greater than 0" + ) + for host in hosts: + self.assertEqual( + host.zoneid, + self.zone.id, + "Host zoneid should match with the host zoneid in the list" + ) + + with self.assertRaises(Exception): + hosts = Host.list(self.apiclient, zoneid="invalidzoneid") diff --git a/test/integration/smoke/test_list_service_offerings.py b/test/integration/smoke/test_list_service_offerings.py new file mode 100644 index 00000000000..319675419dd --- /dev/null +++ b/test/integration/smoke/test_list_service_offerings.py @@ -0,0 +1,559 @@ +# 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. +""" Tests for API listing of service offerings with different filters +""" +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.codes import FAILED +from marvin.lib.base import (Account, + Domain, + Volume, + ServiceOffering, + DiskOffering, + VirtualMachine) +from marvin.lib.common import (get_domain, list_accounts, + list_zones, list_clusters, list_hosts) +# Import System modules +from nose.plugins.attrib import attr + +_multiprocess_shared_ = True + + +class TestListServiceOfferings(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestListServiceOfferings, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls.hypervisor = testClient.getHypervisorInfo() + cls.domain = get_domain(cls.apiclient) + cls.zones = list_zones(cls.apiclient) + cls.zone = cls.zones[0] + cls.clusters = list_clusters(cls.apiclient) + cls.cluster = cls.clusters[0] + cls.hosts = list_hosts(cls.apiclient) + cls.account = list_accounts(cls.apiclient, name="admin")[0] + cls._cleanup = [] + cls.service_offerings = ServiceOffering.list(cls.apiclient) + cls.system_service_offerings = ServiceOffering.list(cls.apiclient, issystem=True) + + cls.child_domain_1 = Domain.create( + cls.apiclient, + cls.services["domain"], + parentdomainid=cls.domain.id + ) + cls._cleanup.append(cls.child_domain_1) + + cls.account_1 = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls._cleanup.append(cls.account_1) + + cls.domainadmin_api_client = testClient.getUserApiClient( + UserName=cls.account_1.user[0].username, + DomainName=cls.domain.name, + type=2 + ) + + cls.system_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["tiny"], + issystem=True, + name="custom_system_offering", + systemvmtype="domainrouter" + ) + cls._cleanup.append(cls.system_offering) + + cls.service_offering_1 = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["small"], + cpunumber=2, + cpuspeed=2000, + domainid=cls.child_domain_1.id, + encryptroot=True, + name="custom_offering_1", + zoneid=cls.zone.id + ) + cls._cleanup.append(cls.service_offering_1) + + + @classmethod + def tearDownClass(cls): + super(TestListServiceOfferings, cls).tearDownClass() + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_01_list_service_offerings_cpunumber_filter(self): + """Test list service offerings with cpunumber filter + """ + # List all service offerings with cpunumber 1 + service_offerings = ServiceOffering.list( + self.apiclient, + cpunumber=1 + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings) - len(self.service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + for service_offering in service_offerings: + self.assertGreaterEqual( + service_offering.cpunumber, + 1, + "List ServiceOfferings response has incorrect cpunumber" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + cpunumber=99999 + ) + self.assertIsNone(service_offerings, "List ServiceOfferings response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_02_list_service_offerings_cpuspeed_filter(self): + """Test list service offerings with cpuspeed filter + """ + # List all service offerings with cpuspeed 1000 + service_offerings = ServiceOffering.list( + self.apiclient, + cpuspeed=1000 + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertGreaterEqual( + len(service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + for service_offering in service_offerings: + self.assertGreaterEqual( + service_offering.cpuspeed, + 1000, + "List ServiceOfferings response has incorrect cpuspeed" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + cpuspeed=99999 + ) + self.assertIsNone(service_offerings, "List ServiceOfferings response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_03_list_service_offerings_memory_filter(self): + """Test list service offerings with memory filter + """ + # List all service offerings with memory 256 + service_offerings = ServiceOffering.list( + self.apiclient, + memory=256 + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertGreaterEqual( + len(service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + for service_offering in service_offerings: + self.assertGreaterEqual( + service_offering.memory, + 256, + "List ServiceOfferings response has incorrect memory" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + memory=99999 + ) + self.assertIsNone(service_offerings, "List ServiceOfferings response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_04_list_service_offerings_domainid_filter(self): + """Test list service offerings with domainid filter + """ + # List all service offerings with domainid + service_offerings = ServiceOffering.list( + self.apiclient, + domainid=self.domain.id + ) + self.assertIsNone( + service_offerings, + "List ServiceOfferings response is not None" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + domainid=self.child_domain_1.id + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + for service_offering in service_offerings: + self.assertEqual( + service_offering.domainid, + self.child_domain_1.id, + "List ServiceOfferings response has incorrect domainid" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_05_list_service_offerings_encryptroot_filter(self): + """Test list service offerings with encryptroot filter + """ + # List all service offerings with encryptroot True + service_offerings = ServiceOffering.list( + self.apiclient, + encryptroot=True + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertGreaterEqual( + len(service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + for service_offering in service_offerings: + self.assertTrue( + service_offering.encryptroot, + "List ServiceOfferings response has incorrect encryptroot" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + encryptroot=False + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertGreaterEqual( + len(service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + for service_offering in service_offerings: + self.assertFalse( + service_offering.encryptroot, + "List ServiceOfferings response has incorrect encryptroot" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_06_list_service_offerings_id_filter(self): + """Test list service offerings with id filter + """ + # List all service offerings with id + service_offerings = ServiceOffering.list( + self.apiclient, + id=self.system_offering.id + ) + self.assertIsNone( + service_offerings, + "List ServiceOfferings response is not None" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + id=self.service_offering_1.id + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + self.assertEqual( + service_offerings[0].id, + self.service_offering_1.id, + "List ServiceOfferings response has incorrect id" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + id=-1 + ) + self.assertIsNone(service_offerings, "List ServiceOfferings response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_07_list_service_offerings_isrecursive_filter(self): + """Test list service offerings with isrecursive filter + """ + # List all service offerings with listall True + service_offerings = ServiceOffering.list( + self.domainadmin_api_client, + isrecursive=True + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings), + len(self.service_offerings) + 1, + "List ServiceOfferings response is empty" + ) + + # List all service offerings with isrecursive False + service_offerings = ServiceOffering.list( + self.domainadmin_api_client, + isrecursive=False + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertGreaterEqual( + len(service_offerings), + len(self.service_offerings), + "List ServiceOfferings response is empty" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_08_list_service_offerings_issystem_filter(self): + """Test list service offerings with issystem filter + """ + # List all service offerings with issystem True + service_offerings = ServiceOffering.list( + self.apiclient, + issystem=True + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings), + len(self.system_service_offerings) + 1, + "List ServiceOfferings response is empty" + ) + for service_offering in service_offerings: + self.assertTrue( + service_offering.issystem, + "List ServiceOfferings response has incorrect issystem" + ) + + # List all service offerings with issystem False + service_offerings = ServiceOffering.list( + self.apiclient, + issystem=False + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings), + len(self.service_offerings) + 1, + "List ServiceOfferings response is empty" + ) + for service_offering in service_offerings: + self.assertFalse( + service_offering.issystem, + "List ServiceOfferings response has incorrect issystem" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_09_list_service_offerings_keyword_filter(self): + """Test list service offerings with keyword filter + """ + # List all service offerings with keyword + service_offerings = ServiceOffering.list( + self.apiclient, + keyword=self.system_offering.name + ) + self.assertIsNone( + service_offerings, + "List ServiceOfferings response is not None" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + keyword=self.service_offering_1.name + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + self.assertEqual( + service_offerings[0].name, + self.service_offering_1.name, + "List ServiceOfferings response has incorrect name" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + keyword="invalid" + ) + self.assertIsNone(service_offerings, "List ServiceOfferings response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_10_list_service_offerings_name_filter(self): + """Test list service offerings with name filter + """ + # List all service offerings with name + service_offerings = ServiceOffering.list( + self.apiclient, + name=self.system_offering.name + ) + self.assertIsNone( + service_offerings, + "List ServiceOfferings response is not None" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + name=self.system_offering.name, + issystem=True + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + self.assertEqual( + service_offerings[0].name, + self.system_offering.name, + "List ServiceOfferings response has incorrect name" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + name=self.service_offering_1.name + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + self.assertEqual( + service_offerings[0].name, + self.service_offering_1.name, + "List ServiceOfferings response has incorrect name" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + name="invalid" + ) + self.assertIsNone(service_offerings, "List ServiceOfferings response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_11_list_service_offerings_systemvmtype_filter(self): + """Test list service offerings with systemvmtype filter + """ + # List all service offerings with systemvmtype domainrouter + service_offerings = ServiceOffering.list( + self.apiclient, + systemvmtype="domainrouter" + ) + self.assertIsNone( + service_offerings, + "List ServiceOfferings response is not None" + ) + + service_offerings = ServiceOffering.list( + self.apiclient, + systemvmtype="domainrouter", + issystem=True + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertGreaterEqual( + len(service_offerings), + 1, + "List ServiceOfferings response is empty" + ) + for service_offering in service_offerings: + self.assertEqual( + service_offering.systemvmtype, + "domainrouter", + "List ServiceOfferings response has incorrect systemvmtype" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_12_list_service_offerings_zoneid_filter(self): + """Test list service offerings with zoneid filter + """ + service_offerings = ServiceOffering.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings), + len(self.service_offerings) + 1, + "List ServiceOfferings response is empty" + ) + for service_offering in service_offerings: + self.assertTrue( + service_offering.zoneid is None or service_offering.zoneid == self.zone.id, + "List ServiceOfferings response has incorrect zoneid" + ) + + if len(self.zones) > 1: + service_offerings = ServiceOffering.list( + self.apiclient, + zoneid=self.zones[1].id + ) + if service_offerings is not None: + self.assertTrue( + isinstance(service_offerings, list), + "List ServiceOfferings response is not a valid list" + ) + self.assertEqual( + len(service_offerings), + len(self.service_offerings), + "List ServiceOfferings response is empty" + ) diff --git a/test/integration/smoke/test_list_storage_pools.py b/test/integration/smoke/test_list_storage_pools.py new file mode 100644 index 00000000000..c2c075da65a --- /dev/null +++ b/test/integration/smoke/test_list_storage_pools.py @@ -0,0 +1,396 @@ +# 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. +""" Tests for API listing of storage pools with different filters +""" +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.codes import FAILED +from marvin.lib.base import (StoragePool) +from marvin.lib.common import (get_domain, list_accounts, + list_zones, list_clusters, list_hosts) +# Import System modules +from nose.plugins.attrib import attr + +_multiprocess_shared_ = True + + +class TestListStoragePools(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestListStoragePools, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls.hypervisor = testClient.getHypervisorInfo() + cls.domain = get_domain(cls.apiclient) + cls.zones = list_zones(cls.apiclient) + cls.zone = cls.zones[0] + cls.clusters = list_clusters(cls.apiclient) + cls.cluster = cls.clusters[0] + cls.hosts = list_hosts(cls.apiclient) + cls.account = list_accounts(cls.apiclient, name="admin")[0] + cls.storage_pools = StoragePool.list(cls.apiclient) + + + @classmethod + def tearDownClass(cls): + super(TestListStoragePools, cls).tearDownClass() + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_01_list_storage_pools_clusterid_filter(self): + """ Test list storage pools by clusterid filter + """ + storage_pools = StoragePool.list( + self.apiclient, + clusterid=self.cluster.id + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertGreater( + len(storage_pools), + 0, + "Length of storage pools should greater than 0" + ) + for storage_pool in storage_pools: + self.assertEqual( + storage_pool.clusterid, + self.cluster.id, + "Cluster id should be equal to the cluster id passed in the filter" + ) + + storage_pools = StoragePool.list( + self.apiclient, + clusterid="-1" + ) + self.assertIsNone( + storage_pools, + "Response should be empty when invalid cluster id is passed" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_02_list_storage_pools_id_filter(self): + """ Test list storage pools by id filter + """ + valid_id = self.storage_pools[0].id + storage_pools = StoragePool.list( + self.apiclient, + id=valid_id + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertEqual( + len(storage_pools), + 1, + "Length of storage pools should be equal to 1" + ) + self.assertEqual( + storage_pools[0].id, + valid_id, + "Cluster id should be equal to the cluster id passed in the filter" + ) + + storage_pools = StoragePool.list( + self.apiclient, + id="-1" + ) + self.assertIsNone( + storage_pools, + "Response should be empty when invalid cluster id is passed" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_03_list_storage_pools_ipaddress_filter(self): + """ Test list storage pools by ipaddress filter + """ + valid_ipaddress = self.storage_pools[0].ipaddress + storage_pools = StoragePool.list( + self.apiclient, + ipaddress=valid_ipaddress + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertGreater( + len(storage_pools), + 0, + "Length of storage pools should greater than 0" + ) + for storage_pool in storage_pools: + self.assertEqual( + storage_pool.ipaddress, + valid_ipaddress, + "IP address should be equal to the ip address passed in the filter" + ) + + storage_pools = StoragePool.list( + self.apiclient, + ipaddress="1.1.1.1" + ) + self.assertIsNone( + storage_pools, + "Response should be empty when invalid ip address is passed" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_04_list_storage_pools_keyword_filter(self): + """ Test list storage pools by keyword filter + """ + valid_keyword = self.storage_pools[0].name + storage_pools = StoragePool.list( + self.apiclient, + keyword=valid_keyword + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertGreater( + len(storage_pools), + 0, + "Length of storage pools should greater than 0" + ) + for storage_pool in storage_pools: + self.assertIn( + valid_keyword, + storage_pool.name, + "Keyword should be present in the storage pool name" + ) + + storage_pools = StoragePool.list( + self.apiclient, + keyword="invalid" + ) + self.assertIsNone( + storage_pools, + "Response should be empty when invalid keyword is passed" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_05_list_storage_pools_name_filter(self): + """ Test list storage pools by name filter + """ + valid_name = self.storage_pools[0].name + storage_pools = StoragePool.list( + self.apiclient, + name=valid_name + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertGreater( + len(storage_pools), + 0, + "Length of storage pools should greater than 0" + ) + for storage_pool in storage_pools: + self.assertEqual( + storage_pool.name, + valid_name, + "Name should be equal to the name passed in the filter" + ) + + storage_pools = StoragePool.list( + self.apiclient, + name="invalid" + ) + self.assertIsNone( + storage_pools, + "Response should be empty when invalid name is passed" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_06_list_storage_pools_path_filter(self): + """ Test list storage pools by path filter + """ + valid_path = self.storage_pools[0].path + storage_pools = StoragePool.list( + self.apiclient, + path=valid_path + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertGreater( + len(storage_pools), + 0, + "Length of storage pools should greater than 0" + ) + for storage_pool in storage_pools: + self.assertEqual( + storage_pool.path, + valid_path, + "Path should be equal to the path passed in the filter" + ) + + storage_pools = StoragePool.list( + self.apiclient, + path="invalid" + ) + self.assertIsNone( + storage_pools, + "Response should be empty when invalid path is passed" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_07_list_storage_pools_podid_filter(self): + """ Test list storage pools by podid filter + """ + storage_pools = StoragePool.list( + self.apiclient, + podid=self.cluster.podid + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertGreater( + len(storage_pools), + 0, + "Length of storage pools should greater than 0" + ) + for storage_pool in storage_pools: + self.assertEqual( + storage_pool.podid, + self.cluster.podid, + "Pod id should be equal to the pod id passed in the filter" + ) + + storage_pools = StoragePool.list( + self.apiclient, + podid="-1" + ) + self.assertIsNone( + storage_pools, + "Response should be empty when invalid pod id is passed" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_08_list_storage_pools_scope_filter(self): + """ Test list storage pools by scope filter + """ + valid_scope = self.storage_pools[0].scope + storage_pools = StoragePool.list( + self.apiclient, + scope=valid_scope + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertGreater( + len(storage_pools), + 0, + "Length of storage pools should greater than 0" + ) + for storage_pool in storage_pools: + self.assertEqual( + storage_pool.scope, + valid_scope, + "Scope should be equal to the scope passed in the filter" + ) + with self.assertRaises(Exception): + storage_pools = StoragePool.list( + self.apiclient, + scope="invalid" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_09_list_storage_pools_status_filter(self): + """ Test list storage pools by status filter + """ + valid_status = self.storage_pools[0].status + storage_pools = StoragePool.list( + self.apiclient, + status=valid_status + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertGreater( + len(storage_pools), + 0, + "Length of storage pools should greater than 0" + ) + for storage_pool in storage_pools: + self.assertEqual( + storage_pool.status, + valid_status, + "State should be equal to the status passed in the filter" + ) + with self.assertRaises(Exception): + storage_pools = StoragePool.list( + self.apiclient, + status="invalid" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_10_list_storage_pools_zoneid_filter(self): + """ Test list storage pools by zoneid filter + """ + storage_pools = StoragePool.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertGreater( + len(storage_pools), + 0, + "Length of storage pools should greater than 0" + ) + for storage_pool in storage_pools: + self.assertEqual( + storage_pool.zoneid, + self.zone.id, + "Zone id should be equal to the zone id passed in the filter" + ) + + storage_pools = StoragePool.list( + self.apiclient, + zoneid="-1" + ) + self.assertIsNone( + storage_pools, + "Response should be empty when invalid zone id is passed" + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_11_list_storage_pools_no_filter(self): + """ Test list storage pools with no filter + """ + storage_pools = StoragePool.list( + self.apiclient + ) + self.assertTrue( + isinstance(storage_pools, list), + "Storage pool response type should be a list" + ) + self.assertGreater( + len(storage_pools), + 0, + "Length of storage pools should greater than 0" + ) diff --git a/test/integration/smoke/test_list_volumes.py b/test/integration/smoke/test_list_volumes.py new file mode 100644 index 00000000000..d21ce5d2ee6 --- /dev/null +++ b/test/integration/smoke/test_list_volumes.py @@ -0,0 +1,615 @@ +# 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. +""" Tests for API listing of volumes with different filters +""" +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.codes import FAILED +from marvin.lib.base import (Account, + Domain, + Volume, + ServiceOffering, + Tag, + DiskOffering, + VirtualMachine) +from marvin.lib.common import (get_domain, list_accounts, + list_zones, list_clusters, list_hosts, get_suitable_test_template) +# Import System modules +from nose.plugins.attrib import attr + +_multiprocess_shared_ = True + + +class TestListVolumes(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestListVolumes, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls.hypervisor = testClient.getHypervisorInfo() + cls.domain = get_domain(cls.apiclient) + cls.zones = list_zones(cls.apiclient) + cls.zone = cls.zones[0] + cls.clusters = list_clusters(cls.apiclient) + cls.cluster = cls.clusters[0] + cls.hosts = list_hosts(cls.apiclient) + cls.account = list_accounts(cls.apiclient, name="admin")[0] + cls._cleanup = [] + + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["tiny"] + ) + cls._cleanup.append(cls.service_offering) + + template = get_suitable_test_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"], + cls.hypervisor + ) + if template == FAILED: + assert False, "get_test_template() failed to return template" + + cls.services["template"]["ostypeid"] = template.ostypeid + cls.services["template_2"]["ostypeid"] = template.ostypeid + cls.services["ostypeid"] = template.ostypeid + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["mode"] = cls.zone.networktype + + cls.disk_offering = DiskOffering.create(cls.apiclient, + cls.services["disk_offering"]) + cls._cleanup.append(cls.disk_offering) + + # Create VM + cls.virtual_machine = VirtualMachine.create( + cls.apiclient, + cls.services["virtual_machine"], + templateid=template.id, + accountid=cls.account.name, + domainid=cls.account.domainid, + clusterid=cls.cluster.id, + serviceofferingid=cls.service_offering.id, + mode=cls.services["mode"] + ) + + cls.child_domain = Domain.create( + cls.apiclient, + cls.services["domain"]) + cls._cleanup.append(cls.child_domain) + + cls.child_account = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.child_domain.id) + cls._cleanup.append(cls.child_account) + + cls.vol_1 = Volume.create(cls.apiclient, + cls.services["volume"], + zoneid=cls.zone.id, + account=cls.account.name, + domainid=cls.account.domainid, + diskofferingid=cls.disk_offering.id) + cls._cleanup.append(cls.vol_1) + + cls.vol_1 = cls.virtual_machine.attach_volume( + cls.apiclient, + cls.vol_1 + ) + cls._cleanup.append(cls.virtual_machine) + + Tag.create(cls.apiclient, cls.vol_1.id, "Volume", {"abc": "xyz"}) + + cls.vol_2 = Volume.create(cls.apiclient, + cls.services["volume"], + zoneid=cls.zone.id, + account=cls.account.name, + domainid=cls.account.domainid, + diskofferingid=cls.disk_offering.id) + + cls._cleanup.append(cls.vol_2) + + cls.vol_3 = Volume.create(cls.apiclient, + cls.services["volume"], + zoneid=cls.zone.id, + account=cls.child_account.name, + domainid=cls.child_account.domainid, + diskofferingid=cls.disk_offering.id) + cls._cleanup.append(cls.vol_3) + + @classmethod + def tearDownClass(cls): + super(TestListVolumes, cls).tearDownClass() + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_01_list_volumes_account_domain_filter(self): + """Test listing Volumes with account & domain filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 3, + "ListVolumes response expected 3 Volumes, received %s" % len(list_volume_response) + ) + + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + account=self.child_account.name, + domainid=self.child_account.domainid + ) + + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 1, + "ListVolumes response expected 1 Volume, received %s" % len(list_volume_response) + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_02_list_volumes_diskofferingid_filter(self): + """Test listing Volumes with diskofferingid filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 2, + "ListVolumes response expected 2 Volumes, received %s" % len(list_volume_response) + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_03_list_volumes_id_filter(self): + """Test listing Volumes with id filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + id=self.vol_1.id + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 1, + "ListVolumes response expected 1 Volume, received %s" % len(list_volume_response) + ) + self.assertEqual( + list_volume_response[0].id, + self.vol_1.id, + "ListVolumes response expected Volume with id %s, received %s" % (self.vol_1.id, list_volume_response[0].id) + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_04_list_volumes_ids_filter(self): + """Test listing Volumes with ids filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + ids=[self.vol_1.id, self.vol_2.id, self.vol_3.id] + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 2, + "ListVolumes response expected 2 Volumes, received %s" % len(list_volume_response) + ) + self.assertIn(list_volume_response[0].id, [self.vol_1.id, self.vol_2.id], + "ListVolumes response Volume 1 not in list") + self.assertIn(list_volume_response[1].id, [self.vol_1.id, self.vol_2.id], + "ListVolumes response Volume 2 not in list") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_05_list_volumes_isrecursive(self): + """Test listing Volumes with isrecursive filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + isrecursive=True, + domainid=self.account.domainid + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len([v for v in list_volume_response if v.state != "Destroy"]), + 4, + "ListVolumes response expected 4 Volumes, received %s" % len(list_volume_response) + ) + + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + isrecursive=False, + domainid=self.account.domainid + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len([v for v in list_volume_response if v.state != "Destroy"]), + 3, + "ListVolumes response expected 3 Volumes, received %s" % len(list_volume_response) + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_06_list_volumes_keyword_filter(self): + """Test listing Volumes with keyword filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + keyword=self.services["volume"]["diskname"] + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 2, + "ListVolumes response expected 2 Volumes, received %s" % len(list_volume_response) + ) + self.assertIn( + list_volume_response[0].id, [self.vol_1.id, self.vol_2.id], + "ListVolumes response Volume 1 not in list") + self.assertIn(list_volume_response[1].id, [self.vol_1.id, self.vol_2.id], + "ListVolumes response Volume 2 not in list") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_07_list_volumes_listall(self): + """Test listing Volumes with listall filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len([v for v in list_volume_response if v.state != "Destroy"]), + 4, + "ListVolumes response expected 4 Volumes, received %s" % len(list_volume_response) + ) + + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + listall=False + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len([v for v in list_volume_response if v.state != "Destroy"]), + 3, + "ListVolumes response expected 3 Volumes, received %s" % len(list_volume_response) + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_08_listsystemvms(self): + list_volumes_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + listsystemvms=True + ) + self.assertEqual( + isinstance(list_volumes_response, list), + True, + "List Volume response is not a valid list" + ) + self.assertGreater( + len(list_volumes_response), + 3, + "ListVolumes response expected more than 3 Volumes, received %s" % len(list_volumes_response) + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_09_list_volumes_name_filter(self): + """Test listing Volumes with name filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + name=self.vol_1.name + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 1, + "ListVolumes response expected 1 Volumes, received %s" % len(list_volume_response) + ) + self.assertEqual( + list_volume_response[0].id, + self.vol_1.id, + "ListVolumes response expected Volume with id %s, received %s" % (self.vol_1.id, list_volume_response[0].id) + ) + self.assertEqual( + list_volume_response[0].name, + self.vol_1.name, + "ListVolumes response expected Volume with name %s, received %s" % ( + self.vol_1.name, list_volume_response[0].name) + ) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_10_list_volumes_podid_filter(self): + """Test listing Volumes with podid filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + podid=self.vol_1.podid + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertGreater( + len(list_volume_response), + 1, + "ListVolumes response expected more than 1 Volume, received %s" % len(list_volume_response) + ) + self.assertIn(self.vol_1.id, [volume.id for volume in list_volume_response], + "ListVolumes response expected Volume with id %s" % self.vol_1.id) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_11_list_volumes_state_filter(self): + """Test listing Volumes with state filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + state="Ready" + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 2, + "ListVolumes response expected 2 Volumes, received %s" % len(list_volume_response) + ) + self.assertIn(self.vol_1.id, [volume.id for volume in list_volume_response], + "ListVolumes response expected Volume with id %s" % self.vol_1.id) + + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + state="Allocated" + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 1, + "ListVolumes response expected 1 Volumes, received %s" % len(list_volume_response) + ) + self.assertEqual(self.vol_2.id, list_volume_response[0].id, + "ListVolumes response expected Volume with id %s" % self.vol_3.id) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_12_list_volumes_storageid_filter(self): + """Test listing Volumes with storageid filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + storageid=self.vol_1.storageid + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertGreaterEqual( + len(list_volume_response), + 1, + "ListVolumes response expected 1 or more Volumes, received %s" % len(list_volume_response) + ) + self.assertIn(self.vol_1.id, [volume.id for volume in list_volume_response], + "ListVolumes response expected Volume with id %s" % self.vol_1.id) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_13_list_volumes_type_filter(self): + """Test listing Volumes with type filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + type="DATADISK" + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 2, + "ListVolumes response expected 2 Volumes, received %s" % len(list_volume_response) + ) + self.assertIn(self.vol_1.id, [volume.id for volume in list_volume_response], + "ListVolumes response expected Volume with id %s" % self.vol_1.id) + + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + type="ROOT" + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 1, + "ListVolumes response expected 1 Volumes, received %s" % len(list_volume_response) + ) + self.assertNotIn(list_volume_response[0].id, [self.vol_1.id, self.vol_2.id], + "ListVolumes response expected ROOT Volume") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_14_list_volumes_virtualmachineid_filter(self): + """Test listing Volumes with virtualmachineid filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id, + virtualmachineid=self.vol_1.virtualmachineid + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 2, + "ListVolumes response expected 2 Volumes, received %s" % len(list_volume_response) + ) + self.assertIn(self.vol_1.id, [volume.id for volume in list_volume_response], + "ListVolumes response expected Volume with id %s" % self.vol_1.id) + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_15_list_volumes_zoneid_filter(self): + """Test listing Volumes with zoneid filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zones[0].id + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 3, + "ListVolumes response expected 3 Volumes, received %s" % len(list_volume_response) + ) + + if len(self.zones) > 1: + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zones[1].id + ) + self.assertIsNone(list_volume_response, "List Volume response is not None") + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_16_list_volumes_tags_filter(self): + """Test listing Volumes with tags filter + """ + list_volume_response = Volume.list( + self.apiclient, + tags=[{"key": "abc", "value": "xyz"}] + ) + + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertEqual( + len(list_volume_response), + 1, + "ListVolumes response expected 1 or more Volumes, received %s" % len(list_volume_response) + ) + self.assertEqual( + list_volume_response[0].id, + self.vol_1.id, + "ListVolumes response expected Volume with id %s, received %s" % (self.vol_1.id, list_volume_response[0].id) + ) + self.assertEqual( + list_volume_response[0].tags[0]["key"], + "abc", + "ListVolumes response expected Volume with tag key abc, received %s" % list_volume_response[0].tags[0]["key"] + ) + self.assertEqual( + list_volume_response[0].tags[0]["value"], + "xyz", + "ListVolumes response expected Volume with tag value xyz, received %s" % list_volume_response[0].tags[0]["value"] + ) + + list_volume_response = Volume.list( + self.apiclient, + tags=[{"key": "abc", "value": "xyz1"}] + ) + self.assertIsNone(list_volume_response, "List Volume response is not None") + with self.assertRaises(Exception): + list_volume_response = Volume.list( + self.apiclient, + tags=[{"key": None, "value": None}] + ) + + + @attr(tags=["advanced", "advancedns", "smoke", "basic"], required_hardware="false") + def test_17_list_volumes_no_filter(self): + """Test listing Volumes with no filter + """ + list_volume_response = Volume.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertTrue( + isinstance(list_volume_response, list), + "List Volume response is not a valid list" + ) + self.assertGreaterEqual( + len(list_volume_response), + 3, + "ListVolumes response expected 3 or more Volumes, received %s" % len(list_volume_response) + ) + self.assertIn(self.vol_1.id, [volume.id for volume in list_volume_response], + "ListVolumes response expected Volume with id %s" % self.vol_1.id) diff --git a/test/integration/smoke/test_metrics_api.py b/test/integration/smoke/test_metrics_api.py index d5ad559fad0..ab2644fc1aa 100644 --- a/test/integration/smoke/test_metrics_api.py +++ b/test/integration/smoke/test_metrics_api.py @@ -289,7 +289,6 @@ class TestMetrics(cloudstackTestCase): self.assertTrue(hasattr(li, 'hosts')) self.assertEqual(li.hosts, len(list_hosts(self.apiclient, - zoneid=self.zone.id, type='Routing'))) self.assertTrue(hasattr(li, 'imagestores')) @@ -518,7 +517,7 @@ class TestMetrics(cloudstackTestCase): self.cleanup.append(self.small_virtual_machine) currentHost = Host.list(self.apiclient, id=self.small_virtual_machine.hostid)[0] - if currentHost.hypervisor.lower() == "xenserver" and currentHost.hypervisorversion == "7.1.0": + if currentHost.hypervisor.lower() == "xenserver": # Skip tests as volume metrics doesn't see to work self.skipTest("Skipping test because volume metrics doesn't work on hypervisor\ %s, %s" % (currentHost.hypervisor, currentHost.hypervisorversion)) diff --git a/test/integration/smoke/test_migration.py b/test/integration/smoke/test_migration.py index 3b21a0b3936..cadb50692a9 100644 --- a/test/integration/smoke/test_migration.py +++ b/test/integration/smoke/test_migration.py @@ -119,7 +119,7 @@ class TestNetworkMigration(cloudstackTestCase): cls.network_offering_nouserdata.update(cls.api_client, state='Enabled') - # Create Network Offering with all the serices + # Create Network Offering with all the services cls.network_offering_all = NetworkOffering.create( cls.api_client, cls.test_data["isolated_network_offering"] diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index 56b434f3241..8f3f4f533dd 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -871,7 +871,7 @@ class TestReleaseIP(cloudstackTestCase): @attr(tags=["advanced", "advancedns", "smoke", "dvs"], required_hardware="false") def test_releaseIP(self): - """Test for release public IP address""" + """Test for release public IP address using the ID""" logger.debug("Deleting Public IP : %s" % self.ip_addr.id) @@ -930,6 +930,66 @@ class TestReleaseIP(cloudstackTestCase): ) return + @attr(tags=["advanced", "advancedns", "smoke", "dvs"], required_hardware="false") + def test_releaseIP_using_IP(self): + """Test for release public IP address using the address""" + + logger.debug("Deleting Public IP : %s" % self.ip_addr.ipaddress) + self.ip_address.delete_by_ip(self.apiclient) + + retriesCount = 10 + isIpAddressDisassociated = False + while retriesCount > 0: + listResponse = list_publicIP( + self.apiclient, + id=self.ip_addr.id, + state="Allocated" + ) + if listResponse is None: + isIpAddressDisassociated = True + break + retriesCount -= 1 + time.sleep(60) + # End while + + self.assertTrue( + isIpAddressDisassociated, + "Failed to disassociate IP address") + + # ListPortForwardingRules should not list + # associated rules with Public IP address + try: + list_nat_rule = list_nat_rules( + self.apiclient, + id=self.nat_rule.id + ) + logger.debug("List NAT Rule response" + str(list_nat_rule)) + except CloudstackAPIException: + logger.debug("Port Forwarding Rule is deleted") + + # listLoadBalancerRules should not list + # associated rules with Public IP address + try: + list_lb_rule = list_lb_rules( + self.apiclient, + id=self.lb_rule.id + ) + logger.debug("List LB Rule response" + str(list_lb_rule)) + except CloudstackAPIException: + logger.debug("Port Forwarding Rule is deleted") + + # SSH Attempt though public IP should fail + with self.assertRaises(Exception): + SshClient( + self.ip_addr.ipaddress, + self.services["natrule"]["publicport"], + self.virtual_machine.username, + self.virtual_machine.password, + retries=2, + delay=0 + ) + return + class TestDeleteAccount(cloudstackTestCase): diff --git a/test/integration/smoke/test_network_ipv6.py b/test/integration/smoke/test_network_ipv6.py index 720f14e64da..2c369f28300 100644 --- a/test/integration/smoke/test_network_ipv6.py +++ b/test/integration/smoke/test_network_ipv6.py @@ -697,15 +697,16 @@ class TestIpv6Network(cloudstackTestCase): "IPv6 firewall rule ICMP code mismatch %d, %d" % (rule.icmpcode, icmp_code)) routerCmd = "nft list chain ip6 %s %s" % (FIREWALL_TABLE, FIREWALL_CHAINS[traffic_type]) res = self.getRouterProcessStatus(self.getNetworkRouter(self.network), routerCmd) - self.assertTrue(parsed_rule in res, - "Listing firewall rule with nft list chain failure for rule: %s" % parsed_rule) + parsed_rule_new = parsed_rule.replace("{ ", "").replace(" }", "") + self.assertTrue(parsed_rule in res or parsed_rule_new in res, + "Listing firewall rule with nft list chain failure for rule: '%s' is not in '%s'" % (parsed_rule, res)) if delete == True: cmd = deleteIpv6FirewallRule.deleteIpv6FirewallRuleCmd() cmd.id = fw_rule.id self.userapiclient.deleteIpv6FirewallRule(cmd) res = self.getRouterProcessStatus(self.getNetworkRouter(self.network), routerCmd) - self.assertFalse(parsed_rule in res, - "Firewall rule present in nft list chain failure despite delete for rule: %s" % parsed_rule) + self.assertFalse(parsed_rule in res or parsed_rule_new in res, + "Firewall rule present in nft list chain failure despite delete for rule: '%s' is in '%s'" % (parsed_rule, res)) def checkIpv6FirewallRule(self): traffic_type = "Ingress" diff --git a/test/integration/smoke/test_object_stores.py b/test/integration/smoke/test_object_stores.py new file mode 100644 index 00000000000..710fce646e1 --- /dev/null +++ b/test/integration/smoke/test_object_stores.py @@ -0,0 +1,108 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" BVT tests for Object Storage Pool""" + +#Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from nose.plugins.attrib import attr +from marvin.lib.base import (ObjectStoragePool) +from marvin.lib.utils import (cleanup_resources) + +_multiprocess_shared_ = True + +class TestObjectStore(cloudstackTestCase): + + def setUp(self): + self.services = self.testClient.getParsedTestDataConfig() + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created resources + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["smoke"], required_hardware="false") + def test_01_create_object_store(self): + """Test to create object store + """ + + object_store = ObjectStoragePool.create( + self.apiclient, + "testOS-10", + "http://192.168.0.1", + "Simulator", + None + ) + + self.debug("Created Object Store with ID: %s" % object_store.id) + + list_object_stores_response = ObjectStoragePool.list( + self.apiclient, + id=object_store.id + ) + + self.assertNotEqual( + len(list_object_stores_response), + 0, + "Check List Object Store response" + ) + + object_store_response = list_object_stores_response[0] + self.assertEqual( + "Simulator", + object_store_response.providername, + "Check Provider of the created Object Store" + ) + self.assertEqual( + "testOS-10", + object_store_response.name, + "Check Name of the created Object Store" + ) + self.assertEqual( + "http://192.168.0.1", + object_store_response.url, + "Check URL of the created Object Store" + ) + + object_store.update( + self.apiclient, + name="updated_name" + ) + + list_object_stores_response_updated = ObjectStoragePool.list( + self.apiclient, + id=object_store.id + ) + + object_store_response_updated = list_object_stores_response_updated[0] + + self.assertEqual( + "updated_name", + object_store_response_updated.name, + "Check Name of the updated Object Store name" + ) + + self.cleanup.append(object_store) + + return diff --git a/test/integration/smoke/test_primary_storage_scope.py b/test/integration/smoke/test_primary_storage_scope.py new file mode 100644 index 00000000000..db2cd09b616 --- /dev/null +++ b/test/integration/smoke/test_primary_storage_scope.py @@ -0,0 +1,178 @@ +# 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. +""" BVT tests for Primary Storage +""" + +# Import System modules +# Import Local Modules +from marvin.cloudstackTestCase import * +from marvin.lib.base import (Host, StoragePool, Cluster, updateStoragePool, changeStoragePoolScope) +from marvin.lib.common import (get_zone, get_pod, list_clusters) +from marvin.lib.utils import cleanup_resources +from nose.plugins.attrib import attr + +class TestPrimaryStorageScope(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.services = self.testClient.getParsedTestDataConfig() + self.cleanup = [] + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.pod = get_pod(self.apiclient, self.zone.id) + self.debug(self.services) + self.cluster1 = list_clusters(self.apiclient)[0] + self.debug(self.cluster1) + if (self.cluster1 == None): + cloudstackTestCase.skipTest(self, "Cluster not found. Skipping test.") + if (self.cluster1.hypervisortype not in ['KVM', 'VMware', 'Simulator']): + cloudstackTestCase.skipTest(self, "Supported hypervisors (KVM, VMware, Simulator) not found. Skipping test.") + self.cluster = { + 'clustername': 'C0_testScope', + 'clustertype': 'CloudManaged' + } + return + + def tearDown(self): + super(TestPrimaryStorageScope, self).tearDown() + + @attr(tags=["advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="true") + def test_01_primary_storage_scope_change(self): + """Test primary storage pool scope change + """ + + # Create cluster + self.cluster2 = Cluster.create(self.apiclient, + self.cluster, + zoneid=self.zone.id, + podid=self.pod.id, + hypervisor=self.cluster1.hypervisortype + ) + self.cleanup.append(self.cluster2) + + # Create zone-wide storage pool + self.storage = StoragePool.create(self.apiclient, + self.services["nfs"], + scope = 'ZONE', + zoneid=self.zone.id, + hypervisor=self.cluster1.hypervisortype + ) + self.cleanup.append(self.storage) + self.debug("Created storage pool %s in zone scope", self.storage.id) + + # Disable storage pool + cmd = updateStoragePool.updateStoragePoolCmd() + cmd.id = self.storage.id + cmd.enabled = False + self.apiclient.updateStoragePool(cmd) + + self.debug("Disabled storage pool : %s" % self.storage.id) + + # Change storage pool scope to Cluster2 + cmd = changeStoragePoolScope.changeStoragePoolScopeCmd() + cmd.id = self.storage.id + cmd.scope = "CLUSTER" + cmd.clusterid = self.cluster2.id + self.apiclient.changeStoragePoolScope(cmd) + + self.debug("Changed scope of storage pool %s to cluster" % self.storage.id) + + pool_id = self.dbclient.execute("select id from storage_pool where uuid=\"" + self.storage.id + "\"")[0][0] + host1 = Host.list(self.apiclient, clusterid=self.cluster1.id, listall=True)[0] + host1_id = self.dbclient.execute("select id from host where uuid=\"" + host1.id + "\"")[0][0] + + pool_row = self.dbclient.execute("select cluster_id, pod_id, scope from storage_pool where id=" + str(pool_id))[0] + capacity_row = self.dbclient.execute("select cluster_id, pod_id from op_host_capacity where capacity_type=3 and host_id=" + str(pool_id))[0] + pool_host_rows = self.dbclient.execute("select id from storage_pool_host_ref where host_id=" + str(host1_id) + " and pool_id=" + str(pool_id)) + + self.assertIsNotNone( + pool_row[0], + "Cluster id should not be NULL for cluster scope" + ) + self.assertIsNotNone( + pool_row[1], + "Pod id should not be NULL for cluster scope" + ) + self.assertEqual( + pool_row[2], + "CLUSTER", + "Storage pool scope not changed to Cluster" + ) + self.assertIsNotNone( + capacity_row[0], + "Cluster id should not be NULL in the op_host_capacity table" + ) + self.assertIsNotNone( + capacity_row[1], + "Pod id set should not be NULL in the op_host_capacity table" + ) + self.assertEqual( + len(pool_host_rows), + 0, + "Storage pool not removed from the storage_pool_host_ref table for host on another cluster" + ) + + # Change storage pool scope to Zone + cmd = changeStoragePoolScope.changeStoragePoolScopeCmd() + cmd.id = self.storage.id + cmd.scope = "ZONE" + self.apiclient.changeStoragePoolScope(cmd) + + self.debug("Changed scope of storage pool %s to zone" % self.storage.id) + + pool_row = self.dbclient.execute("select cluster_id, pod_id, scope from storage_pool where id=" + str(pool_id))[0] + capacity_row = self.dbclient.execute("select cluster_id, pod_id from op_host_capacity where capacity_type=3 and host_id=" + str(pool_id))[0] + pool_host_rows = self.dbclient.execute("select id from storage_pool_host_ref where host_id=" + str(host1_id) + " and pool_id=" + str(pool_id)) + + self.assertIsNone( + pool_row[0], + "Cluster id not set to NULL for zone scope" + ) + self.assertIsNone( + pool_row[1], + "Pod id not set to NULL for zone scope" + ) + self.assertEqual( + pool_row[2], + "ZONE", + "Storage pool scope not changed to ZONE" + ) + self.assertIsNone( + capacity_row[0], + "Cluster id not set to NULL in the op_host_capacity table" + ) + self.assertIsNone( + capacity_row[1], + "Pod id not set to NULL in the op_host_capacity table" + ) + self.assertEqual( + len(pool_host_rows), + 1, + "Storage pool not added to the storage_pool_host_ref table for host on another cluster" + ) + + # Enable storage pool + cmd = updateStoragePool.updateStoragePoolCmd() + cmd.id = self.storage.id + cmd.enabled = True + response = self.apiclient.updateStoragePool(cmd) + self.assertEqual( + response.state, + "Up", + "Storage pool couldn't be enabled" + ) diff --git a/test/integration/smoke/test_privategw_acl.py b/test/integration/smoke/test_privategw_acl.py index da0ae6a0020..b0553241dc2 100644 --- a/test/integration/smoke/test_privategw_acl.py +++ b/test/integration/smoke/test_privategw_acl.py @@ -850,7 +850,7 @@ class TestPrivateGwACL(cloudstackTestCase): self.assertTrue(check_state == 0, "Routers private gateway interface should not be on the same state!") self.assertTrue(check_mac == 0, "Routers private gateway interface should not have the same mac address!") else: - self.assertTrue(check_state == 1, "Routers private gateway interface should should have been removed!") + self.assertTrue(check_state == 1, "Routers private gateway interface should have been removed!") def check_routers_state(self, status_to_check="PRIMARY", expected_count=1): routers = self.query_routers() @@ -920,6 +920,6 @@ class TestPrivateGwACL(cloudstackTestCase): (select id from physical_network where uuid='%s');" % physical_network.id ) for traffic_type in traffic_type_list: - if "Guest" in str(traffic_type[0]): + if "Guest" in str(traffic_type[0]): return physical_network return None diff --git a/test/integration/smoke/test_privategw_acl_ovs_gre.py b/test/integration/smoke/test_privategw_acl_ovs_gre.py index 94e5c3c839a..89e20af914e 100644 --- a/test/integration/smoke/test_privategw_acl_ovs_gre.py +++ b/test/integration/smoke/test_privategw_acl_ovs_gre.py @@ -683,7 +683,7 @@ class TestPrivateGwACLOvsGRE(cloudstackTestCase): (select id from physical_network where uuid='%s');" % physical_network.id ) for traffic_type in traffic_type_list: - if "Guest" in str(traffic_type[0]): + if "Guest" in str(traffic_type[0]): return physical_network return None diff --git a/test/integration/smoke/test_purge_expunged_vms.py b/test/integration/smoke/test_purge_expunged_vms.py new file mode 100644 index 00000000000..0fe55991059 --- /dev/null +++ b/test/integration/smoke/test_purge_expunged_vms.py @@ -0,0 +1,371 @@ +# 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. +""" BVT tests for purging expunged VMs and their resources +""" +# Import Local Modules +from marvin.codes import FAILED +from marvin.cloudstackAPI import (purgeExpungedResources, + listInfrastructure, + listManagementServers) +from marvin.cloudstackException import CloudstackAPIException +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import (Account, + Domain, + ServiceOffering, + DiskOffering, + NetworkOffering, + Network, + VirtualMachine, + Configurations) +from marvin.lib.common import (get_domain, + get_zone, + get_template) +from marvin.lib.utils import (random_gen) +from marvin.lib.decoratorGenerators import skipTestIf +from marvin.sshClient import SshClient +from nose.plugins.attrib import attr +import logging +# Import System modules +import time +from datetime import datetime, timedelta +import pytz +import threading + + +_multiprocess_shared_ = True +DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S" + +class TestPurgeExpungedVms(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.testClient = super(TestPurgeExpungedVms, cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + cls.dbConnection = cls.testClient.getDbConnection() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + + cls.mgtSvrDetails = cls.config.__dict__["mgtSvr"][0].__dict__ + + + cls.hypervisor = cls.testClient.getHypervisorInfo().lower() + cls.hypervisorIsSimulator = False + if cls.hypervisor == 'simulator': + cls.hypervisorIsSimulator = True + + cls._cleanup = [] + cls.logger = logging.getLogger('TestPurgeExpungedVms') + cls.logger.setLevel(logging.DEBUG) + + template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"]) + if template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + + # Set Zones and disk offerings + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["small"]["template"] = template.id + + cls.compute_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["tiny"]) + cls._cleanup.append(cls.compute_offering) + + cls.purge_resource_compute_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["tiny"], + purgeresources=True) + cls._cleanup.append(cls.purge_resource_compute_offering) + + cls.disk_offering = DiskOffering.create( + cls.apiclient, + cls.services["disk_offering"] + ) + cls._cleanup.append(cls.disk_offering) + + cls.network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["l2-network_offering"], + ) + cls._cleanup.append(cls.network_offering) + cls.network_offering.update(cls.apiclient, state='Enabled') + cls.services["network"]["networkoffering"] = cls.network_offering.id + + cls.domain1 = Domain.create( + cls.apiclient, + cls.services["domain"]) + cls._cleanup.append(cls.domain1) + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + domainid=cls.domain1.id) + cls._cleanup.append(cls.account) + cls.userapiclient = cls.testClient.getUserApiClient( + UserName=cls.account.name, + DomainName=cls.account.domain + ) + cls.l2_network = Network.create( + cls.userapiclient, + cls.services["l2-network"], + zoneid=cls.zone.id, + networkofferingid=cls.network_offering.id + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + @classmethod + def tearDownClass(cls): + super(TestPurgeExpungedVms, cls).tearDownClass() + + def updateVmCreatedRemovedInDb(self, vm_id, timestamp): + # Assuming DB is UTC + utc_timestamp = datetime.strptime(timestamp, DATETIME_FORMAT).astimezone(pytz.utc).strftime(DATETIME_FORMAT) + logging.info("Updating VM: %s created and removed in DB with timestamp: %s" % (vm_id, timestamp)) + query = "UPDATE cloud.vm_instance SET created='%s', removed='%s' WHERE uuid='%s'" % (utc_timestamp, utc_timestamp, vm_id) + self.dbConnection.execute(query) + + def setupExpungedVm(self, timestamp): + logging.info("Setting up expunged VM with timestamp: %s" % timestamp) + vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.compute_offering.id, + networkids=self.l2_network.id + ) + self.cleanup.append(vm) + vm_id = vm.id + self.vm_ids[timestamp] = vm_id + vm.delete(self.apiclient, expunge=True) + self.cleanup.remove(vm) + self.updateVmCreatedRemovedInDb(vm_id, timestamp) + + def setupExpungedVms(self): + logging.info("Setup VMs") + self.vm_ids = {} + self.threads = [] + days = 3 + for i in range(days): + logging.info("Setting up expunged VMs for day: %d" % (i + 1)) + thread = threading.Thread(target=self.setupExpungedVm, args=(self.timestamps[i],)) + self.threads.append(thread) + thread.start() + + for index, thread in enumerate(self.threads): + logging.info("Before joining thread %d." % index) + thread.join() + logging.info("Thread %d done" % index) + + def setUp(self): + self.cleanup = [] + self.changedConfigurations = {} + self.staticConfigurations = [] + if 'service_offering' in self._testMethodName: + return + if 'background_task' in self._testMethodName and self.hypervisorIsSimulator: + return + self.days = 3 + self.timestamps = [] + for i in range(self.days): + days_ago = (self.days - i) * 2 + now = (datetime.now() - timedelta(days = days_ago)) + timestamp = now.strftime(DATETIME_FORMAT) + self.timestamps.append(timestamp) + self.setupExpungedVms() + + def tearDown(self): + restartServer = False + for config in self.changedConfigurations: + value = self.changedConfigurations[config] + logging.info("Reverting value of config: %s to %s" % (config, value)) + Configurations.update(self.apiclient, + config, + value=value) + if config in self.staticConfigurations: + restartServer = True + if restartServer: + self.restartAllManagementServers() + super(TestPurgeExpungedVms, self).tearDown() + + def executePurgeExpungedResources(self, start_date, end_date): + cmd = purgeExpungedResources.purgeExpungedResourcesCmd() + if start_date is not None: + cmd.startdate = start_date + if end_date is not None: + cmd.enddate = end_date + self.apiclient.purgeExpungedResources(cmd) + + def getVmsInDb(self, vm_ids): + vm_id_str = "','".join(vm_ids) + vm_id_str = "'" + vm_id_str + "'" + query = "SELECT * FROM cloud.vm_instance WHERE uuid IN (%s)" % vm_id_str + response = self.dbConnection.execute(query) + logging.info("DB response from VM: %s:: %s" % (vm_id_str, response)) + return response + + def validatePurgedVmEntriesInDb(self, purged, not_purged): + if purged is not None: + response = self.getVmsInDb(purged) + self.assertTrue(response is None or len(response) == 0, + "Purged VMs still present in DB") + if not_purged is not None: + response = self.getVmsInDb(not_purged) + self.assertTrue(response is not None or len(response) == len(not_purged), + "Not purged VM not present in DB") + + def changeConfiguration(self, name, value): + current_config = Configurations.list(self.apiclient, name=name)[0] + if current_config.value == value: + return + logging.info("Current value for config: %s is %s, changing it to %s" % (name, current_config.value, value)) + self.changedConfigurations[name] = current_config.value + if current_config.isdynamic == False: + self.staticConfigurations.append(name) + Configurations.update(self.apiclient, + name, + value=value) + + def isManagementUp(self): + try: + self.apiclient.listInfrastructure(listInfrastructure.listInfrastructureCmd()) + return True + except Exception: + return False + + def getManagementServerIps(self): + if self.mgtSvrDetails["mgtSvrIp"] == 'localhost': + return None + cmd = listManagementServers.listManagementServersCmd() + servers = self.apiclient.listManagementServers(cmd) + active_server_ips = [] + active_server_ips.append(self.mgtSvrDetails["mgtSvrIp"]) + for idx, server in enumerate(servers): + if server.state == 'Up' and server.serviceip != self.mgtSvrDetails["mgtSvrIp"]: + active_server_ips.append(server.serviceip) + return active_server_ips + + def restartAllManagementServers(self): + """Restart all management servers + Assumes all servers have same username and password""" + server_ips = self.getManagementServerIps() + if server_ips is None: + self.staticConfigurations.clear() + self.fail("MS restarts cannot be done on %s" % self.mgtSvrDetails["mgtSvrIp"]) + return False + self.debug("Restarting all management server") + for idx, server_ip in enumerate(server_ips): + self.debug(f"Restarting management server #{idx} with IP {server_ip}") + sshClient = SshClient( + server_ip, + 22, + self.mgtSvrDetails["user"], + self.mgtSvrDetails["passwd"] + ) + command = "service cloudstack-management stop" + sshClient.execute(command) + command = "service cloudstack-management start" + sshClient.execute(command) + if idx == 0: + # Wait before restarting other management servers to make the first as oldest running + time.sleep(10) + + # Waits for management to come up in 10 mins, when it's up it will continue + timeout = time.time() + (10 * 60) + while time.time() < timeout: + if self.isManagementUp() is True: return True + time.sleep(5) + self.debug("Management server did not come up, failing") + return False + + @attr(tags=["advanced"], required_hardware="true") + def test_01_purge_expunged_api_vm_start_date(self): + self.executePurgeExpungedResources(self.timestamps[1], None) + self.validatePurgedVmEntriesInDb( + [self.vm_ids[self.timestamps[1]], self.vm_ids[self.timestamps[2]]], + [self.vm_ids[self.timestamps[0]]] + ) + + @attr(tags=["advanced"], required_hardware="true") + def test_02_purge_expunged_api_vm_end_date(self): + self.executePurgeExpungedResources(None, self.timestamps[1]) + self.validatePurgedVmEntriesInDb( + [self.vm_ids[self.timestamps[0]], self.vm_ids[self.timestamps[1]]], + [self.vm_ids[self.timestamps[2]]] + ) + + @attr(tags=["advanced"], required_hardware="true") + def test_03_purge_expunged_api_vm_start_end_date(self): + self.executePurgeExpungedResources(self.timestamps[0], self.timestamps[2]) + self.validatePurgedVmEntriesInDb( + [self.vm_ids[self.timestamps[0]], self.vm_ids[self.timestamps[1]], self.vm_ids[self.timestamps[2]]], + None + ) + + @attr(tags=["advanced"], required_hardware="true") + def test_04_purge_expunged_api_vm_no_date(self): + self.executePurgeExpungedResources(None, None) + self.validatePurgedVmEntriesInDb( + [self.vm_ids[self.timestamps[0]], self.vm_ids[self.timestamps[1]], self.vm_ids[self.timestamps[2]]], + None + ) + + @attr(tags=["advanced", "skip_setup_vms"], required_hardware="true") + def test_05_purge_expunged_vm_service_offering(self): + purge_delay = 181 + self.changeConfiguration('expunged.resource.purge.job.delay', purge_delay) + vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.purge_resource_compute_offering.id, + networkids=self.l2_network.id + ) + self.cleanup.append(vm) + vm_id = vm.id + vm.delete(self.apiclient, expunge=True) + self.cleanup.remove(vm) + wait = 1.25 * purge_delay + logging.info("Waiting for 1.25x%d = %d seconds for VM to get purged" % (purge_delay, wait)) + time.sleep(wait) + self.validatePurgedVmEntriesInDb( + [vm_id], + None + ) + + @skipTestIf("hypervisorIsSimulator") + @attr(tags=["advanced"], required_hardware="true") + def test_06_purge_expunged_vm_background_task(self): + purge_task_delay = 120 + self.changeConfiguration('expunged.resources.purge.enabled', 'true') + self.changeConfiguration('expunged.resources.purge.delay', purge_task_delay) + self.changeConfiguration('expunged.resources.purge.interval', int(purge_task_delay/2)) + self.changeConfiguration('expunged.resources.purge.keep.past.days', 1) + if len(self.staticConfigurations) > 0: + self.restartAllManagementServers() + wait_multiple = 2 + wait = wait_multiple * purge_task_delay + logging.info(f"Waiting for {wait_multiple}x{purge_task_delay} = {wait} seconds for background task to execute") + time.sleep(wait) + logging.debug("Validating expunged VMs") + self.validatePurgedVmEntriesInDb( + [self.vm_ids[self.timestamps[0]], self.vm_ids[self.timestamps[1]], self.vm_ids[self.timestamps[2]]], + None + ) diff --git a/test/integration/smoke/test_quarantined_ips.py b/test/integration/smoke/test_quarantined_ips.py new file mode 100644 index 00000000000..42349fd2a53 --- /dev/null +++ b/test/integration/smoke/test_quarantined_ips.py @@ -0,0 +1,329 @@ +# 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. +import time + +from nose.plugins.attrib import attr + +from marvin.cloudstackAPI import updateConfiguration +from marvin.cloudstackException import CloudstackAPIException +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import Network, NetworkOffering, VpcOffering, VPC, PublicIPAddress +from marvin.lib.common import get_domain, get_zone + + +class Services: + """ Test Quarantine for public IPs + """ + + def __init__(self): + self.services = { + "root_domain": { + "name": "ROOT", + }, + "domain_admin": { + "username": "Domain admin", + "roletype": 2, + }, + "root_admin": { + "username": "Root admin", + "roletype": 1, + }, + "domain_vpc": { + "name": "domain-vpc", + "displaytext": "domain-vpc", + "cidr": "10.1.1.0/24", + }, + "domain_network": { + "name": "domain-network", + "displaytext": "domain-network", + }, + "root_vpc": { + "name": "root-vpc", + "displaytext": "root-vpc", + "cidr": "10.2.1.0/24", + }, + "root_network": { + "name": "root-network", + "displaytext": "root-network", + } + } + + +class TestQuarantineIPs(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.testClient = super(TestQuarantineIPs, cls).getClsTestClient() + cls.apiclient = cls.testClient.getApiClient() + + cls.services = Services().services + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + return + + def setUp(self): + self.domain_admin_apiclient = self.testClient.getUserApiClient(self.services["domain_admin"]["username"], + self.services["root_domain"]["name"], + self.services["domain_admin"]["roletype"]) + + self.admin_apiclient = self.testClient.getUserApiClient(self.services["root_admin"]["username"], + self.services["root_domain"]["name"], + self.services["root_admin"]["roletype"]) + + """ + Set public.ip.address.quarantine.duration to 60 minutes + """ + update_configuration_cmd = updateConfiguration.updateConfigurationCmd() + update_configuration_cmd.name = "public.ip.address.quarantine.duration" + update_configuration_cmd.value = "1" + self.apiclient.updateConfiguration(update_configuration_cmd) + + self.cleanup = [] + return + + def tearDown(self): + """ + Reset public.ip.address.quarantine.duration to 0 minutes + """ + update_configuration_cmd = updateConfiguration.updateConfigurationCmd() + update_configuration_cmd.name = "public.ip.address.quarantine.duration" + update_configuration_cmd.value = "0" + self.apiclient.updateConfiguration(update_configuration_cmd) + + super(TestQuarantineIPs, self).tearDown() + + def create_vpc(self, api_client, services): + # Get network offering + network_offering = NetworkOffering.list(api_client, name="DefaultIsolatedNetworkOfferingForVpcNetworks") + self.assertTrue(network_offering is not None and len(network_offering) > 0, "No VPC network offering") + + # Getting VPC offering + vpc_offering = VpcOffering.list(api_client, name="Default VPC offering") + self.assertTrue(vpc_offering is not None and len(vpc_offering) > 0, "No VPC offerings found") + + # Creating VPC + vpc = VPC.create( + apiclient=api_client, + services=services, + networkDomain="vpc.networkacl", + vpcofferingid=vpc_offering[0].id, + zoneid=self.zone.id, + domainid=self.domain.id, + start=False + ) + + self.cleanup.append(vpc) + self.assertTrue(vpc is not None, "VPC creation failed") + return vpc + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_only_owner_can_allocate_ip_in_quarantine_vpc(self): + """ Test allocate IP in quarantine to VPC. + """ + # Creating Domain Admin VPC + domain_vpc = self.create_vpc(self.domain_admin_apiclient, self.services["domain_vpc"]) + + # Allocating source nat first + PublicIPAddress.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + vpcid=domain_vpc.id) + + # Getting available public IP address + ip_address = PublicIPAddress.list(self.domain_admin_apiclient, state="Free", listall=True)[0].ipaddress + + self.debug( + f"creating public address with zone {self.zone.id} and vpc id {domain_vpc.id} and ip address {ip_address}.") + # Associating public IP address to Domain Admin account + public_ip = PublicIPAddress.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + vpcid=domain_vpc.id, + ipaddress=ip_address) + self.assertIsNotNone(public_ip, "Failed to Associate IP Address") + self.assertEqual(public_ip.ipaddress.ipaddress, ip_address, "Associated IP is not same as specified") + + self.debug(f"Disassociating public IP {public_ip.ipaddress.ipaddress}.") + public_ip.delete(self.domain_admin_apiclient) + + # Creating Root Admin VPC + root_vpc = self.create_vpc(self.admin_apiclient, self.services["root_vpc"]) + + self.debug(f"Trying to allocate the same IP address {ip_address} that is still in quarantine.") + + with self.assertRaises(CloudstackAPIException) as exception: + PublicIPAddress.create(self.admin_apiclient, + zoneid=self.zone.id, + vpcid=root_vpc.id, + ipaddress=ip_address) + self.assertIn(f"Failed to allocate public IP address [{ip_address}] as it is in quarantine.", + exception.exception.errorMsg) + + # Owner should be able to allocate its IP in quarantine + public_ip = PublicIPAddress.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + vpcid=domain_vpc.id, + ipaddress=ip_address) + self.assertIsNotNone(public_ip, "Failed to Associate IP Address") + self.assertEqual(public_ip.ipaddress.ipaddress, ip_address, "Associated IP is not same as specified") + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_another_user_can_allocate_ip_after_quarantined_has_ended_vpc(self): + """ Test allocate IP to VPC after quarantine has ended. + """ + # Creating Domain Admin VPC + domain_vpc = self.create_vpc(self.domain_admin_apiclient, self.services["domain_vpc"]) + + # Allocating source nat first + PublicIPAddress.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + vpcid=domain_vpc.id) + + # Getting available public IP address + ip_address = PublicIPAddress.list(self.domain_admin_apiclient, state="Free", listall=True)[0].ipaddress + + self.debug( + f"creating public address with zone {self.zone.id} and vpc id {domain_vpc.id} and ip address {ip_address}.") + # Associating public IP address to Domain Admin account + public_ip = PublicIPAddress.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + vpcid=domain_vpc.id, + ipaddress=ip_address) + self.assertIsNotNone(public_ip, "Failed to Associate IP Address") + self.assertEqual(public_ip.ipaddress.ipaddress, ip_address, "Associated IP is not same as specified") + + self.debug(f"Disassociating public IP {public_ip.ipaddress.ipaddress}.") + public_ip.delete(self.domain_admin_apiclient) + + # Creating Root Admin VPC + root_vpc = self.create_vpc(self.admin_apiclient, self.services["root_vpc"]) + + self.debug(f"Trying to allocate the same IP address {ip_address} after the quarantine duration.") + + time.sleep(60) + + public_ip_2 = PublicIPAddress.create(self.admin_apiclient, + zoneid=self.zone.id, + vpcid=root_vpc.id, + ipaddress=ip_address) + self.assertIsNotNone(public_ip_2, "Failed to Associate IP Address") + self.assertEqual(public_ip_2.ipaddress.ipaddress, ip_address, "Associated IP is not same as specified") + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_only_owner_can_allocate_ip_in_quarantine_network(self): + """ Test allocate IP in quarantine to network. + """ + network_offering = NetworkOffering.list(self.domain_admin_apiclient, + name="DefaultIsolatedNetworkOfferingWithSourceNatService") + domain_network = Network.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + services=self.services["domain_network"], + networkofferingid=network_offering[0].id) + self.cleanup.append(domain_network) + + # Allocating source nat first + PublicIPAddress.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + networkid=domain_network.id) + + # Getting available public IP address + ip_address = PublicIPAddress.list(self.domain_admin_apiclient, state="Free", listall=True)[0].ipaddress + + self.debug( + f"creating public address with zone {self.zone.id} and network id {domain_network.id} and ip address {ip_address}.") + # Associating public IP address to Domain Admin account + public_ip = PublicIPAddress.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + networkid=domain_network.id, + ipaddress=ip_address) + self.assertIsNotNone(public_ip, "Failed to Associate IP Address") + self.assertEqual(public_ip.ipaddress.ipaddress, ip_address, "Associated IP is not same as specified") + + self.debug(f"Disassociating public IP {public_ip.ipaddress.ipaddress}.") + public_ip.delete(self.domain_admin_apiclient) + + # Creating Root Admin network + root_network = Network.create(self.admin_apiclient, + zoneid=self.zone.id, + services=self.services["root_network"], + networkofferingid=network_offering[0].id) + self.cleanup.append(root_network) + self.debug(f"Trying to allocate the same IP address {ip_address} that is still in quarantine.") + + with self.assertRaises(CloudstackAPIException) as exception: + PublicIPAddress.create(self.admin_apiclient, + zoneid=self.zone.id, + networkid=root_network.id, + ipaddress=ip_address) + self.assertIn(f"Failed to allocate public IP address [{ip_address}] as it is in quarantine.", + exception.exception.errorMsg) + + # Owner should be able to allocate its IP in quarantine + public_ip = PublicIPAddress.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + networkid=domain_network.id, + ipaddress=ip_address) + self.assertIsNotNone(public_ip, "Failed to Associate IP Address") + self.assertEqual(public_ip.ipaddress.ipaddress, ip_address, "Associated IP is not same as specified") + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_another_user_can_allocate_ip_after_quarantined_has_ended_network(self): + """ Test allocate IP to network after quarantine has ended. + """ + network_offering = NetworkOffering.list(self.domain_admin_apiclient, + name="DefaultIsolatedNetworkOfferingWithSourceNatService") + domain_network = Network.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + services=self.services["domain_network"], + networkofferingid=network_offering[0].id) + self.cleanup.append(domain_network) + # Allocating source nat first + PublicIPAddress.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + networkid=domain_network.id) + + # Getting available public IP address + ip_address = PublicIPAddress.list(self.domain_admin_apiclient, state="Free", listall=True)[0].ipaddress + + self.debug( + f"creating public address with zone {self.zone.id} and network id {domain_network.id} and ip address {ip_address}.") + # Associating public IP address to Domain Admin account + public_ip = PublicIPAddress.create(self.domain_admin_apiclient, + zoneid=self.zone.id, + networkid=domain_network.id, + ipaddress=ip_address) + self.assertIsNotNone(public_ip, "Failed to Associate IP Address") + self.assertEqual(public_ip.ipaddress.ipaddress, ip_address, "Associated IP is not same as specified") + + self.debug(f"Disassociating public IP {public_ip.ipaddress.ipaddress}.") + public_ip.delete(self.domain_admin_apiclient) + + # Creating Root Admin VPC + root_network = Network.create(self.admin_apiclient, + zoneid=self.zone.id, + services=self.services["root_network"], + networkofferingid=network_offering[0].id) + self.cleanup.append(root_network) + + self.debug(f"Trying to allocate the same IP address {ip_address} after the quarantine duration.") + + time.sleep(60) + + public_ip_2 = PublicIPAddress.create(self.admin_apiclient, + zoneid=self.zone.id, + networkid=domain_network.id, + ipaddress=ip_address) + self.assertIsNotNone(public_ip_2, "Failed to Associate IP Address") + self.assertEqual(public_ip_2.ipaddress.ipaddress, ip_address, "Associated IP is not same as specified") diff --git a/test/integration/smoke/test_register_userdata.py b/test/integration/smoke/test_register_userdata.py index c89d08e63e8..f19b5abc9cf 100644 --- a/test/integration/smoke/test_register_userdata.py +++ b/test/integration/smoke/test_register_userdata.py @@ -28,7 +28,7 @@ from marvin.lib.base import (ServiceOffering, NATRule, Template) from marvin.lib.common import get_test_template, get_zone, list_virtual_machines -from marvin.lib.utils import (validateList, cleanup_resources) +from marvin.lib.utils import validateList from nose.plugins.attrib import attr from marvin.codes import PASS,FAIL import base64 @@ -87,6 +87,7 @@ class TestRegisteredUserdata(cloudstackTestCase): # Get Zone, Domain and Default Built-in template self.domain = get_domain(self.apiclient) self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.hypervisor = self.testClient.getHypervisorInfo() #create a user account self.account = Account.create( @@ -96,7 +97,7 @@ class TestRegisteredUserdata(cloudstackTestCase): ) self.testdata["mode"] = self.zone.networktype - self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) + self.template = get_test_template(self.apiclient, self.zone.id, self.hypervisor) #create a service offering small_service_offering = self.testdata["service_offerings"]["small"] @@ -115,25 +116,21 @@ class TestRegisteredUserdata(cloudstackTestCase): self.testdata["network"], networkofferingid=self.no_isolate.id, zoneid=self.zone.id, - accountid="admin", - domainid=1 + accountid=self.account.name, + domainid=self.account.domainid ) #build cleanup list self.cleanup = [ + self.account, + self.no_isolate, self.service_offering, self.isolated_network, - self.no_isolate, - self.account, ] def tearDown(self): - try: - cleanup_resources(self.apiclient, self.cleanup) - except Exception as e: - self.debug("Warning! Exception in tearDown: %s" % e) - + super(TestRegisteredUserdata, self).tearDown() @attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False) def test_CRUD_operations_userdata(self): @@ -192,22 +189,21 @@ class TestRegisteredUserdata(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, - accountid="admin", - domainid=1, + accountid=self.account.name, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, templateid=self.template.id, networkids=[self.isolated_network.id], userdataid=self.userdata2.userdata.id ) self.cleanup.append(self.virtual_machine) - self.cleanup.append(self.userdata2) networkid = self.virtual_machine.nic[0].networkid src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=networkid, - account="admin", - domainid=1, + account=self.account.name, + domainid=self.account.domainid, listall=True, issourcenat=True, ) @@ -320,8 +316,8 @@ class TestRegisteredUserdata(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, - accountid="admin", - domainid=1, + accountid=self.account.name, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, templateid=self.template.id, networkids=[self.isolated_network.id], @@ -329,14 +325,13 @@ class TestRegisteredUserdata(cloudstackTestCase): userdatadetails=[{"key1": "value1"}] ) self.cleanup.append(self.virtual_machine) - self.cleanup.append(self.userdata2) networkid = self.virtual_machine.nic[0].networkid src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=networkid, - account="admin", - domainid=1, + account=self.account.name, + domainid=self.account.domainid, listall=True, issourcenat=True, ) @@ -493,15 +488,14 @@ class TestRegisteredUserdata(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, - accountid="admin", - domainid=1, + accountid=self.account.name, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, templateid=self.template.id, networkids=[self.isolated_network.id], userdataid=self.apiUserdata.userdata.id ) self.cleanup.append(self.virtual_machine) - self.cleanup.append(self.apiUserdata) self.template = Template.linkUserDataToTemplate( self.apiclient, @@ -512,8 +506,8 @@ class TestRegisteredUserdata(cloudstackTestCase): src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=networkid, - account="admin", - domainid=1, + account=self.account.name, + domainid=self.account.domainid, listall=True, issourcenat=True, ) @@ -623,16 +617,14 @@ class TestRegisteredUserdata(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, - accountid="admin", - domainid=1, + accountid=self.account.name, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, templateid=self.template.id, networkids=[self.isolated_network.id], userdataid=self.apiUserdata.userdata.id ) self.cleanup.append(self.virtual_machine) - self.cleanup.append(self.apiUserdata) - self.cleanup.append(self.templateUserdata) self.template = Template.linkUserDataToTemplate( self.apiclient, @@ -643,8 +635,8 @@ class TestRegisteredUserdata(cloudstackTestCase): src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=networkid, - account="admin", - domainid=1, + account=self.account.name, + domainid=self.account.domainid, listall=True, issourcenat=True, ) @@ -770,8 +762,8 @@ class TestRegisteredUserdata(cloudstackTestCase): self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, - accountid="admin", - domainid=1, + accountid=self.account.name, + domainid=self.account.domainid, serviceofferingid=self.service_offering.id, templateid=self.template.id, networkids=[self.isolated_network.id], @@ -781,9 +773,6 @@ class TestRegisteredUserdata(cloudstackTestCase): self.debug("Deploy VM with userdata passed during deployment failed as expected because template userdata override policy is deny. Exception here is : %s" % e.exception) - self.cleanup.append(self.apiUserdata) - self.cleanup.append(self.templateUserdata) - self.template = Template.linkUserDataToTemplate( self.apiclient, templateid=self.template.id @@ -809,7 +798,6 @@ class TestRegisteredUserdata(cloudstackTestCase): account=self.account.name, domainid=self.account.domainid ) - self.cleanup.append(self.userdata) list_userdata = UserData.list(self.apiclient, id=self.userdata.userdata.id, listall=True) self.assertNotEqual( @@ -853,4 +841,3 @@ class TestRegisteredUserdata(cloudstackTestCase): self.userapiclient, id=self.userdata.userdata.id ) - self.cleanup.remove(self.userdata) diff --git a/test/integration/smoke/test_restore_vm.py b/test/integration/smoke/test_restore_vm.py new file mode 100644 index 00000000000..aac33460da1 --- /dev/null +++ b/test/integration/smoke/test_restore_vm.py @@ -0,0 +1,183 @@ +# 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. +""" P1 tests for Scaling up Vm +""" +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import (VirtualMachine, Volume, DiskOffering, ServiceOffering, Template) +from marvin.lib.common import (get_zone, get_domain) +from nose.plugins.attrib import attr + +_multiprocess_shared_ = True + + +class TestRestoreVM(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestRestoreVM, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls._cleanup = [] + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.hypervisor = testClient.getHypervisorInfo() + cls.services['mode'] = cls.zone.networktype + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + cls.service_offering = ServiceOffering.create(cls.apiclient, cls.services["service_offering"]) + cls._cleanup.append(cls.service_offering) + + cls.disk_offering = DiskOffering.create(cls.apiclient, cls.services["disk_offering"], disksize='8') + cls._cleanup.append(cls.disk_offering) + + template_t1 = Template.register(cls.apiclient, cls.services["test_templates"][ + cls.hypervisor.lower() if cls.hypervisor.lower() != 'simulator' else 'xenserver'], + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower()) + cls._cleanup.append(template_t1) + template_t1.download(cls.apiclient) + cls.template_t1 = Template.list(cls.apiclient, templatefilter='all', id=template_t1.id)[0] + + template_t2 = Template.register(cls.apiclient, cls.services["test_templates"][ + cls.hypervisor.lower() if cls.hypervisor.lower() != 'simulator' else 'xenserver'], + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower()) + cls._cleanup.append(template_t2) + template_t2.download(cls.apiclient) + cls.template_t2 = Template.list(cls.apiclient, templatefilter='all', id=template_t2.id)[0] + + @classmethod + def tearDownClass(cls): + super(TestRestoreVM, cls).tearDownClass() + return + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_01_restore_vm(self): + """Test restore virtual machine + """ + # create a virtual machine + virtual_machine = VirtualMachine.create(self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, + templateid=self.template_t1.id, + serviceofferingid=self.service_offering.id) + self._cleanup.append(virtual_machine) + + old_root_vol = Volume.list(self.apiclient, virtualmachineid=virtual_machine.id)[0] + self.assertEqual(old_root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(old_root_vol.size, self.template_t1.size, "Size of volume and template should match") + + virtual_machine.restore(self.apiclient, self.template_t2.id, expunge=True) + + restored_vm = VirtualMachine.list(self.apiclient, id=virtual_machine.id)[0] + self.assertEqual(restored_vm.state, 'Running', "VM should be in a running state") + self.assertEqual(restored_vm.templateid, self.template_t2.id, "VM's template after restore is incorrect") + + root_vol = Volume.list(self.apiclient, virtualmachineid=restored_vm.id)[0] + self.assertEqual(root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(root_vol.size, self.template_t2.size, "Size of volume and template should match") + + old_root_vol = Volume.list(self.apiclient, id=old_root_vol.id) + self.assertEqual(old_root_vol, None, "Old volume should be deleted") + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_02_restore_vm_with_disk_offering(self): + """Test restore virtual machine + """ + # create a virtual machine + virtual_machine = VirtualMachine.create(self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, + templateid=self.template_t1.id, + serviceofferingid=self.service_offering.id) + self._cleanup.append(virtual_machine) + + old_root_vol = Volume.list(self.apiclient, virtualmachineid=virtual_machine.id)[0] + self.assertEqual(old_root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(old_root_vol.size, self.template_t1.size, "Size of volume and template should match") + + virtual_machine.restore(self.apiclient, self.template_t2.id, self.disk_offering.id, expunge=True) + + restored_vm = VirtualMachine.list(self.apiclient, id=virtual_machine.id)[0] + self.assertEqual(restored_vm.state, 'Running', "VM should be in a running state") + self.assertEqual(restored_vm.templateid, self.template_t2.id, "VM's template after restore is incorrect") + + root_vol = Volume.list(self.apiclient, virtualmachineid=restored_vm.id)[0] + self.assertEqual(root_vol.diskofferingid, self.disk_offering.id, "Disk offering id should match") + self.assertEqual(root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(root_vol.size, self.disk_offering.disksize * 1024 * 1024 * 1024, + "Size of volume and disk offering should match") + + old_root_vol = Volume.list(self.apiclient, id=old_root_vol.id) + self.assertEqual(old_root_vol, None, "Old volume should be deleted") + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_03_restore_vm_with_disk_offering_custom_size(self): + """Test restore virtual machine + """ + # create a virtual machine + virtual_machine = VirtualMachine.create(self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, + templateid=self.template_t1.id, + serviceofferingid=self.service_offering.id) + self._cleanup.append(virtual_machine) + + old_root_vol = Volume.list(self.apiclient, virtualmachineid=virtual_machine.id)[0] + self.assertEqual(old_root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(old_root_vol.size, self.template_t1.size, "Size of volume and template should match") + + virtual_machine.restore(self.apiclient, self.template_t2.id, self.disk_offering.id, rootdisksize=16) + + restored_vm = VirtualMachine.list(self.apiclient, id=virtual_machine.id)[0] + self.assertEqual(restored_vm.state, 'Running', "VM should be in a running state") + self.assertEqual(restored_vm.templateid, self.template_t2.id, "VM's template after restore is incorrect") + + root_vol = Volume.list(self.apiclient, virtualmachineid=restored_vm.id)[0] + self.assertEqual(root_vol.diskofferingid, self.disk_offering.id, "Disk offering id should match") + self.assertEqual(root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(root_vol.size, 16 * 1024 * 1024 * 1024, "Size of volume and custom disk size should match") + + old_root_vol = Volume.list(self.apiclient, id=old_root_vol.id)[0] + self.assertEqual(old_root_vol.state, "Destroy", "Old volume should be in Destroy state") + Volume.delete(old_root_vol, self.apiclient) + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_04_restore_vm_allocated_root(self): + """Test restore virtual machine with root disk in allocated state + """ + # create a virtual machine with allocated root disk by setting startvm=False + virtual_machine = VirtualMachine.create(self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, + templateid=self.template_t1.id, + serviceofferingid=self.service_offering.id, + startvm=False) + self._cleanup.append(virtual_machine) + old_root_vol = Volume.list(self.apiclient, virtualmachineid=virtual_machine.id)[0] + self.assertEqual(old_root_vol.state, 'Allocated', "Volume should be in Allocated state") + self.assertEqual(old_root_vol.size, self.template_t1.size, "Size of volume and template should match") + + virtual_machine.restore(self.apiclient, self.template_t2.id) + restored_vm = VirtualMachine.list(self.apiclient, id=virtual_machine.id)[0] + self.assertEqual(restored_vm.state, 'Stopped', "Check the state of VM") + self.assertEqual(restored_vm.templateid, self.template_t2.id, "Check the template of VM") + + root_vol = Volume.list(self.apiclient, virtualmachineid=restored_vm.id)[0] + self.assertEqual(root_vol.state, 'Allocated', "Volume should be in Allocated state") + self.assertEqual(root_vol.size, self.template_t2.size, "Size of volume and template should match") + + virtual_machine.start(self.apiclient) + root_vol = Volume.list(self.apiclient, virtualmachineid=restored_vm.id)[0] + self.assertEqual(root_vol.state, 'Ready', "Volume should be in Ready state") + + old_root_vol = Volume.list(self.apiclient, id=old_root_vol.id) + self.assertEqual(old_root_vol, None, "Old volume should be deleted") diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index 356bd213cfc..64bad11f240 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -22,7 +22,8 @@ from marvin.cloudstackTestCase import cloudstackTestCase from marvin.cloudstackAPI import (stopRouter, restartNetwork, startRouter, - rebootRouter) + rebootRouter, + getRouterHealthCheckResults) from marvin.lib.utils import (cleanup_resources, get_process_status, get_host_credentials) @@ -303,7 +304,81 @@ class TestRouterServices(cloudstackTestCase): "Check haproxy service is running or not" ) self.debug("Haproxy process status: %s" % res) - return + + routers = list_routers( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid, + fetchhealthcheckresults=True + ) + + self.assertEqual(isinstance(routers, list), True, + "Check for list routers response return valid data" + ) + self.assertNotEqual( + len(routers), 0, + "Check list router response" + ) + + router = routers[0] + self.info("Router ID: %s & Router state: %s" % ( + router.id, router.state + )) + + self.assertEqual(isinstance(router.healthcheckresults, list), True, + "Router response should contain it's health check result as list" + ) + + cmd = getRouterHealthCheckResults.getRouterHealthCheckResultsCmd() + cmd.routerid = router.id + cmd.performfreshchecks = True # Perform fresh checks as a newly created router may not have results + healthData = self.apiclient.getRouterHealthCheckResults(cmd) + self.info("Router ID: %s & Router state: %s" % ( + router.id, router.state + )) + + self.assertEqual(router.id, healthData.routerid, + "Router response should contain it's health check result so id should match" + ) + self.assertEqual(isinstance(healthData.healthchecks, list), True, + "Router response should contain it's health check result as list" + ) + + self.verifyCheckTypes(healthData.healthchecks) + self.verifyCheckNames(healthData.healthchecks) + self.verifyCheckResults(healthData.healthchecks) + + def verifyCheckTypes(self, healthChecks): + for checkType in ["basic", "advanced"]: + foundType = False + for check in healthChecks: + if check.checktype == checkType: + foundType = True + break + self.assertTrue(foundType, + "Router should contain health check results info for type: " + checkType + ) + + def verifyCheckNames(self, healthChecks): + for checkName in ["dns_check.py", "dhcp_check.py", "haproxy_check.py", "disk_space_check.py", "iptables_check.py", "gateways_check.py", "router_version_check.py"]: + foundCheck = False + for check in healthChecks: + if check.checkname == checkName: + foundCheck = True + break + self.assertTrue(foundCheck, + "Router should contain health check results info for check name: " + checkName + ) + + def verifyCheckResults(self, healthChecks): + failedCheck = 0 + for check in healthChecks: + if check.success: + print("check %s is good" % check.checkname) + else: + print("check %s failed due to %s" % (check.checkname, check.details)) + failedCheck = failedCheck + 1 + self.assertEquals(failedCheck, 0) @attr( tags=[ diff --git a/test/integration/smoke/test_routers_network_ops.py b/test/integration/smoke/test_routers_network_ops.py index a133e9aed98..ac51d3736ad 100644 --- a/test/integration/smoke/test_routers_network_ops.py +++ b/test/integration/smoke/test_routers_network_ops.py @@ -287,8 +287,8 @@ class TestRedundantIsolateNetworks(cloudstackTestCase): ) expected = 1 - ssh_command = "wget -t 1 -T 5 www.google.com" - check_string = "HTTP request sent, awaiting response... 200 OK" + ssh_command = "curl -v -m 1 -o index.html -sL www.google.com" + check_string = "200 OK" result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self) self.assertEqual( @@ -307,8 +307,8 @@ class TestRedundantIsolateNetworks(cloudstackTestCase): ) expected = 0 - ssh_command = "wget -t 1 -T 1 www.google.com" - check_string = "HTTP request sent, awaiting response... 200 OK" + ssh_command = "curl -v -m 1 -o index.html -sL www.google.com" + check_string = "200 OK" result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self) self.assertEqual( @@ -451,8 +451,8 @@ class TestRedundantIsolateNetworks(cloudstackTestCase): ) expected = 0 - ssh_command = "wget -t 1 -T 1 www.google.com" - check_string = "HTTP request sent, awaiting response... 200 OK" + ssh_command = "curl -v -m 1 -o index.html -sL www.google.com" + check_string = "200 OK" result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self) self.assertEqual( @@ -480,8 +480,8 @@ class TestRedundantIsolateNetworks(cloudstackTestCase): ) expected = 1 - ssh_command = "wget -t 1 -T 5 www.google.com" - check_string = "HTTP request sent, awaiting response... 200 OK" + ssh_command = "curl -v -m 1 -o index.html -sL www.google.com" + check_string = "200 OK" result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self) self.assertEqual( @@ -840,8 +840,8 @@ class TestIsolatedNetworks(cloudstackTestCase): ) expected = 1 - ssh_command = "wget -t 1 -T 5 www.google.com" - check_string = "HTTP request sent, awaiting response... 200 OK" + ssh_command = "curl -v -m 1 -o index.html -sL www.google.com" + check_string = "200 OK" result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self) self.assertEqual( @@ -860,8 +860,8 @@ class TestIsolatedNetworks(cloudstackTestCase): ) expected = 0 - ssh_command = "wget -t 1 -T 1 www.google.com" - check_string = "HTTP request sent, awaiting response... 200 OK" + ssh_command = "curl -v -m 1 -o index.html -sL www.google.com" + check_string = "200 OK" result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self) self.assertEqual( @@ -995,8 +995,8 @@ class TestIsolatedNetworks(cloudstackTestCase): ) expected = 0 - ssh_command = "wget -t 1 -T 1 www.google.com" - check_string = "HTTP request sent, awaiting response... 200 OK" + ssh_command = "curl -v -m 1 -o index.html -sL www.google.com" + check_string = "200 OK" result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self) self.assertEqual( @@ -1015,8 +1015,8 @@ class TestIsolatedNetworks(cloudstackTestCase): ) expected = 1 - ssh_command = "wget -t 1 -T 5 www.google.com" - check_string = "HTTP request sent, awaiting response... 200 OK" + ssh_command = "curl -v -m 1 -o index.html -sL www.google.com" + check_string = "200 OK" result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self) self.assertEqual( diff --git a/test/integration/smoke/test_scale_vm.py b/test/integration/smoke/test_scale_vm.py index 7f8b65b8465..c2ae85df3b2 100644 --- a/test/integration/smoke/test_scale_vm.py +++ b/test/integration/smoke/test_scale_vm.py @@ -221,7 +221,7 @@ class TestScaleVm(cloudstackTestCase): result = str( sshClient.execute("service vmware-tools status")).lower() self.debug("and result is: %s" % result) - if not "running" in result: + if "running" not in result: self.skipTest("Skipping scale VM operation because\ VMware tools are not installed on the VM") res = None @@ -355,7 +355,7 @@ class TestScaleVm(cloudstackTestCase): result = str( sshClient.execute("service vmware-tools status")).lower() self.debug("and result is: %s" % result) - if not "running" in result: + if "running" not in result: self.skipTest("Skipping scale VM operation because\ VMware tools are not installed on the VM") @@ -464,7 +464,7 @@ class TestScaleVm(cloudstackTestCase): result = str( sshClient.execute("service vmware-tools status")).lower() self.debug("and result is: %s" % result) - if not "running" in result: + if "running" not in result: self.skipTest("Skipping scale VM operation because\ VMware tools are not installed on the VM") @@ -555,7 +555,7 @@ class TestScaleVm(cloudstackTestCase): result = str( sshClient.execute("service vmware-tools status")).lower() self.debug("and result is: %s" % result) - if not "running" in result: + if "running" not in result: self.skipTest("Skipping scale VM operation because\ VMware tools are not installed on the VM") res = None @@ -700,7 +700,7 @@ class TestScaleVm(cloudstackTestCase): result = str( sshClient.execute("service vmware-tools status")).lower() self.debug("and result is: %s" % result) - if not "running" in result: + if "running" not in result: self.skipTest("Skipping scale VM operation because\ VMware tools are not installed on the VM") res = None diff --git a/test/integration/smoke/test_secondary_storage.py b/test/integration/smoke/test_secondary_storage.py index 5b339ae67b9..4b26950ea64 100644 --- a/test/integration/smoke/test_secondary_storage.py +++ b/test/integration/smoke/test_secondary_storage.py @@ -340,7 +340,7 @@ class TestSecStorageServices(cloudstackTestCase): # 1. Try complete migration from a storage with more (or equal) free space - migration should be refused storages = self.list_secondary_storages(self.apiclient) - if (len(storages)) < 2: + if (len(storages)) < 2 or (storages[0]['zoneid'] != storages[1]['zoneid']): self.skipTest( "This test requires more than one secondary storage") diff --git a/test/integration/smoke/test_service_offerings.py b/test/integration/smoke/test_service_offerings.py index 62e39e195c2..c6a14a64471 100644 --- a/test/integration/smoke/test_service_offerings.py +++ b/test/integration/smoke/test_service_offerings.py @@ -1043,7 +1043,7 @@ class TestCpuCapServiceOfferings(cloudstackTestCase): #Get host CPU usage from top command before and after VM consuming 100% CPU find_pid_cmd = "ps -ax | grep '%s' | head -1 | awk '{print $1}'" % self.vm.id pid = ssh_host.execute(find_pid_cmd)[0] - cpu_usage_cmd = "top -b n 1 p %s | tail -1 | awk '{print $9}'" % pid + cpu_usage_cmd = "top -b -n 1 -p %s | tail -1 | awk '{print $9}'" % pid host_cpu_usage_before_str = ssh_host.execute(cpu_usage_cmd)[0] host_cpu_usage_before = round(float(host_cpu_usage_before_str)) diff --git a/test/integration/smoke/test_snapshots.py b/test/integration/smoke/test_snapshots.py index f49534238b6..f8346093c64 100644 --- a/test/integration/smoke/test_snapshots.py +++ b/test/integration/smoke/test_snapshots.py @@ -374,3 +374,159 @@ class TestSnapshotRootDisk(cloudstackTestCase): ) return + + +class TestSnapshotStandaloneBackup(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestSnapshotStandaloneBackup, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + + cls.hypervisorNotSupported = False + cls.hypervisor = cls.testClient.getHypervisorInfo() + if cls.hypervisor.lower() in ['hyperv', 'lxc'] or 'kvm-centos6' in cls.testClient.getZoneForTests(): + cls.hypervisorNotSupported = True + + cls._cleanup = [] + if not cls.hypervisorNotSupported: + cls.services["domainid"] = cls.domain.id + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["zoneid"] = cls.zone.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup.append(cls.account) + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["tiny"] + ) + cls._cleanup.append(cls.service_offering) + cls.userapiclient = cls.testClient.getUserApiClient( + UserName=cls.account.name, + DomainName=cls.account.domain + ) + cls.template = Template.register( + cls.userapiclient, + cls.services["test_templates"][cls.hypervisor.lower()], + zoneid=cls.zone.id, + hypervisor=cls.hypervisor + ) + cls._cleanup.append(cls.template) + cls.template.download(cls.apiclient) + cls.ostypeid = cls.template.ostypeid + cls.virtual_machine = VirtualMachine.create( + cls.userapiclient, + cls.services["small"], + templateid=cls.template.id, + accountid=cls.account.name, + domainid=cls.account.domainid, + zoneid=cls.zone.id, + serviceofferingid=cls.service_offering.id, + mode=cls.services["mode"] + ) + cls._cleanup.append(cls.virtual_machine) + + volumes =Volume.list( + cls.userapiclient, + virtualmachineid=cls.virtual_machine.id, + type='ROOT', + listall=True + ) + cls.snapshot = Snapshot.create( + cls.userapiclient, + volumes[0].id, + account=cls.account.name, + domainid=cls.account.domainid + ) + cls._cleanup.append(cls.snapshot) + + cls.virtual_machine.delete(cls.apiclient, expunge=True) + cls._cleanup.remove(cls.virtual_machine) + cls.template.delete(cls.userapiclient) + cls._cleanup.remove(cls.template) + + return + + @classmethod + def tearDownClass(cls): + super(TestSnapshotStandaloneBackup, cls).tearDownClass() + + def setUp(self): + self.cleanup = [] + return + + def tearDown(self): + super(TestSnapshotStandaloneBackup, self).tearDown() + + @skipTestIf("hypervisorNotSupported") + @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true") + def test_01_snapshot_to_volume(self): + """Test creating volume from snapshot + """ + self.services['volume_from_snapshot']['zoneid'] = self.zone.id + self.volume_from_snap = Volume.create_from_snapshot( + self.userapiclient, + snapshot_id=self.snapshot.id, + services=self.services["volume_from_snapshot"], + account=self.account.name, + domainid=self.account.domainid + ) + self.cleanup.append(self.volume_from_snap) + + self.assertEqual( + self.volume_from_snap.state, + 'Ready', + "Check state of the volume created from snapshot" + ) + + @skipTestIf("hypervisorNotSupported") + @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true") + def test_02_snapshot_to_template(self): + """Test creating volume from snapshot + """ + + + services = {"displaytext": "Template-1", "name": "Template-1-name", "ostypeid": self.ostypeid, "ispublic": "true"} + self.template_from_snap = Template.create_from_snapshot( + self.userapiclient, + self.snapshot, + services + ) + self.cleanup.append(self.template_from_snap) + + self.assertEqual( + self.template_from_snap.isready, + True, + "Check state of the template created from snapshot" + ) + + self.virtual_machine1 = VirtualMachine.create( + self.userapiclient, + self.services["small"], + templateid=self.template_from_snap.id, + accountid=self.account.name, + domainid=self.account.domainid, + zoneid=self.zone.id, + serviceofferingid=self.service_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.virtual_machine1) + + self.assertEqual( + self.virtual_machine1.state, + 'Running', + "Check state of the VM deployed using the template created from snapshot" + ) + + return diff --git a/test/integration/smoke/test_ssvm.py b/test/integration/smoke/test_ssvm.py index cdbc7d2f58e..ad03c3d46e1 100644 --- a/test/integration/smoke/test_ssvm.py +++ b/test/integration/smoke/test_ssvm.py @@ -121,7 +121,7 @@ class TestSSVMs(cloudstackTestCase): # should return only ONE SSVM per zone # 2. The returned SSVM should be in Running state # 3. listSystemVM for secondarystoragevm should list publicip, - # privateip and link-localip + # privateip, link-localip and service offering id/name # 4. The gateway programmed on the ssvm by listSystemVm should be # the same as the gateway returned by listVlanIpRanges # 5. DNS entries must match those given for the zone @@ -188,6 +188,18 @@ class TestSSVMs(cloudstackTestCase): "Check whether SSVM has public IP field" ) + self.assertEqual( + hasattr(ssvm, 'serviceofferingid'), + True, + "Check whether SSVM has service offering id field" + ) + + self.assertEqual( + hasattr(ssvm, 'serviceofferingname'), + True, + "Check whether SSVM has service offering name field" + ) + # Fetch corresponding ip ranges information from listVlanIpRanges ipranges_response = list_vlan_ipranges( self.apiclient, @@ -261,8 +273,8 @@ class TestSSVMs(cloudstackTestCase): # 1. listSystemVM (systemvmtype=consoleproxy) should return # at least ONE CPVM per zone # 2. The returned ConsoleProxyVM should be in Running state - # 3. listSystemVM for console proxy should list publicip, privateip - # and link-localip + # 3. listSystemVM for console proxy should list publicip, privateip, + # link-localip and service offering id/name # 4. The gateway programmed on the console proxy should be the same # as the gateway returned by listZones # 5. DNS entries must match those given for the zone @@ -327,6 +339,18 @@ class TestSSVMs(cloudstackTestCase): True, "Check whether CPVM has public IP field" ) + + self.assertEqual( + hasattr(cpvm, 'serviceofferingid'), + True, + "Check whether CPVM has service offering id field" + ) + + self.assertEqual( + hasattr(cpvm, 'serviceofferingname'), + True, + "Check whether CPVM has service offering name field" + ) # Fetch corresponding ip ranges information from listVlanIpRanges ipranges_response = list_vlan_ipranges( self.apiclient, diff --git a/test/integration/smoke/test_templates.py b/test/integration/smoke/test_templates.py index 00ad2201b44..2696db8f96b 100644 --- a/test/integration/smoke/test_templates.py +++ b/test/integration/smoke/test_templates.py @@ -115,6 +115,7 @@ class TestCreateTemplateWithChecksum(cloudstackTestCase): cmd = deleteTemplate.deleteTemplateCmd() cmd.id = temp.id cmd.zoneid = self.zone.id + cmd.forced = True self.apiclient.deleteTemplate(cmd) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -988,6 +989,8 @@ class TestTemplates(cloudstackTestCase): ) for template in list_template_response: + if template.directdownload == True: + continue self.assertNotEqual( len(template.downloaddetails), 0, @@ -1021,17 +1024,17 @@ class TestCopyAndDeleteTemplatesAcrossZones(cloudstackTestCase): cls.services["disk_offering"] ) cls._cleanup.append(cls.disk_offering) - template = get_template( + cls.template = get_template( cls.apiclient, cls.zone.id, cls.services["ostype"] ) - if template == FAILED: + if cls.template == FAILED: assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] - cls.services["template"]["ostypeid"] = template.ostypeid - cls.services["template_2"]["ostypeid"] = template.ostypeid - cls.services["ostypeid"] = template.ostypeid + cls.services["template"]["ostypeid"] = cls.template.ostypeid + cls.services["template_2"]["ostypeid"] = cls.template.ostypeid + cls.services["ostypeid"] = cls.template.ostypeid cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["volume"]["diskoffering"] = cls.disk_offering.id @@ -1052,7 +1055,7 @@ class TestCopyAndDeleteTemplatesAcrossZones(cloudstackTestCase): cls.virtual_machine = VirtualMachine.create( cls.apiclient, cls.services["virtual_machine"], - templateid=template.id, + templateid=cls.template.id, accountid=cls.account.name, domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, @@ -1101,7 +1104,7 @@ class TestCopyAndDeleteTemplatesAcrossZones(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns"], required_hardware="false") + @attr(tags=["advanced", "advancedns"], required_hardware="true") def test_09_copy_delete_template(self): cmd = listZones.listZonesCmd() zones = self.apiclient.listZones(cmd) @@ -1153,7 +1156,7 @@ class TestCopyAndDeleteTemplatesAcrossZones(cloudstackTestCase): list_template_response = Template.list( self.apiclient, - templatefilter=self.services["template"]["templatefilter"], + templatefilter=self.services["templatefilter"], id=self.template.id, zoneid=self.destZone.id ) @@ -1247,11 +1250,7 @@ class TestCreateTemplateWithDirectDownload(cloudstackTestCase): @classmethod def tearDownClass(cls): - try: - cleanup_resources(cls.apiclient, cls._cleanup) - except Exception as e: - raise Exception("Warning: Exception during cleanup : %s" % e) - return + super(TestCreateTemplateWithDirectDownload, cls).tearDownClass() def setUp(self): self.apiclient = self.testClient.getApiClient() @@ -1263,13 +1262,7 @@ class TestCreateTemplateWithDirectDownload(cloudstackTestCase): return def tearDown(self): - try: - #Clean up, terminate the created templates - cleanup_resources(self.apiclient, self.cleanup) - - except Exception as e: - raise Exception("Warning: Exception during cleanup : %s" % e) - return + super(TestCreateTemplateWithDirectDownload, self).tearDown() @attr(tags=["advanced", "smoke"], required_hardware="true") def test_01_register_template_direct_download_flag(self): @@ -1322,10 +1315,11 @@ class TestCreateTemplateWithDirectDownload(cloudstackTestCase): """ Deploy a VM from a Direct Download registered template with wrong checksum """ - self.template["checksum"]="{MD5}XXXXXXX" + self.template["checksum"]="{MD5}" + ("X" * 32) tmpl = Template.register(self.apiclient, self.template, zoneid=self.zone.id, hypervisor=self.hypervisor, randomize_name=False) self.cleanup.append(tmpl) + failed = False try: virtual_machine = VirtualMachine.create( self.apiclient, @@ -1336,8 +1330,19 @@ class TestCreateTemplateWithDirectDownload(cloudstackTestCase): serviceofferingid=self.service_offering.id ) self.cleanup.append(virtual_machine) - self.fail("Expected to fail deployment") + failed = True except Exception as e: self.debug("Expected exception") + list_virtual_machine_response = VirtualMachine.list( + self.apiclient, + templateid=tmpl.id, + listall=True + ) + if type(list_virtual_machine_response) == list and len(list_virtual_machine_response) > 0: + for virtual_machine_response in list_virtual_machine_response: + VirtualMachine.delete(virtual_machine_response, self.apiclient, expunge=True) + + if failed == True: + self.fail("Expected to fail VM deployment with wrong checksum template") return diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index a9a554e19ad..aaffa63978a 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -1011,8 +1011,37 @@ class TestSecuredVmMigration(cloudstackTestCase): @classmethod def tearDownClass(cls): + if cls.hypervisor.lower() in ["kvm"]: + cls.ensure_all_hosts_are_up() super(TestSecuredVmMigration, cls).tearDownClass() + @classmethod + def ensure_all_hosts_are_up(cls): + hosts = Host.list( + cls.apiclient, + zoneid=cls.zone.id, + type='Routing', + hypervisor='KVM' + ) + for host in hosts: + if host.state != "Up": + SshClient(host.ipaddress, port=22, user=cls.hostConfig["username"], passwd=cls.hostConfig["password"]) \ + .execute("service cloudstack-agent stop ; \ + sleep 10 ; \ + service cloudstack-agent start") + interval = 5 + retries = 10 + while retries > -1: + time.sleep(interval) + restarted_host = Host.list( + cls.apiclient, + id=host.id, + type='Routing' + )[0] + if restarted_host.state == "Up": + break + retries = retries - 1 + def setUp(self): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() @@ -1071,7 +1100,7 @@ class TestSecuredVmMigration(cloudstackTestCase): time.sleep(interval) host = Host.list( self.apiclient, - hostid=hostId, + id=hostId, type='Routing' )[0] if host.state != state: @@ -1131,7 +1160,7 @@ class TestSecuredVmMigration(cloudstackTestCase): host = Host.list( self.apiclient, zoneid=self.zone.id, - hostid=host.id, + id=host.id, type='Routing' )[0] if host.details.secured != secured: diff --git a/test/integration/smoke/test_vm_schedule.py b/test/integration/smoke/test_vm_schedule.py index e66470dff73..ee1354ff80e 100644 --- a/test/integration/smoke/test_vm_schedule.py +++ b/test/integration/smoke/test_vm_schedule.py @@ -571,7 +571,7 @@ class TestVMSchedule(cloudstackTestCase): stop_vmschedule.delete(self.apiclient) # To ensure that all vm schedules have been deleted and all of their jobs have been completed - time.sleep(15) + time.sleep(60) # Verify VM Schedule is deleted self.assertEqual( @@ -596,6 +596,10 @@ class TestVMSchedule(cloudstackTestCase): time.sleep(30) current_state = self.virtual_machine.update(self.apiclient).state if previous_state != current_state: + # Add these checks because VMs can take some time to start or stop + if (previous_state == 'Starting' and current_state in ('Starting', 'Running')) or ( + previous_state == 'Stopping' and current_state in ('Stopping', 'Stopped')): + continue self.debug( "VM changed state from %s to %s" % (previous_state, current_state) ) diff --git a/test/integration/smoke/test_vm_strict_host_tags.py b/test/integration/smoke/test_vm_strict_host_tags.py new file mode 100644 index 00000000000..163869c8fae --- /dev/null +++ b/test/integration/smoke/test_vm_strict_host_tags.py @@ -0,0 +1,552 @@ +# 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. + +# Import Local Modules +from marvin.cloudstackAPI import (expungeVirtualMachine, updateConfiguration) +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import (Account, ServiceOffering, Template, Host, VirtualMachine) +from marvin.lib.common import (get_domain, get_zone) +from nose.plugins.attrib import attr + + +class TestVMDeploymentPlannerStrictTags(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + testClient = super(TestVMDeploymentPlannerStrictTags, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.hypervisor = testClient.getHypervisorInfo() + cls.services['mode'] = cls.zone.networktype + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + # Create an account, network, VM and IP addresses + cls.account = Account.create(cls.apiclient, cls.services["account"], domainid=cls.domain.id) + cls.service_offering_h1 = ServiceOffering.create(cls.apiclient, cls.services["service_offering_h1"]) + cls.service_offering_h2 = ServiceOffering.create(cls.apiclient, cls.services["service_offering_h2"]) + + cls.template_t1 = Template.register(cls.apiclient, cls.services["test_templates"][cls.hypervisor.lower()], + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower(), templatetag="t1") + cls.template_t1.download(cls.apiclient) + + cls.template_t2 = Template.register(cls.apiclient, cls.services["test_templates"][cls.hypervisor.lower()], + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower(), templatetag="t2") + cls.template_t2.download(cls.apiclient) + + hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing') + cls.host_h1 = hosts[0] if len(hosts) >= 1 else None + + cls._cleanup = [cls.account, cls.service_offering_h1, cls.service_offering_h2, cls.template_t1, cls.template_t2] + + @classmethod + def tearDownClass(cls): + if cls.host_h1: + Host.update(cls.apiclient, id=cls.host_h1.id, hosttags="") + cls.updateConfiguration("vm.strict.host.tags", "") + cls.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + cls.updateConfiguration("resource.limit.host.tags", "") + super(TestVMDeploymentPlannerStrictTags, cls).tearDownClass() + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + if self.host_h1: + Host.update(self.apiclient, id=self.host_h1.id, hosttags="h1,t1,v1") + self.updateConfiguration("vm.strict.host.tags", "") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "") + self.cleanup = [] + + def tearDown(self): + self.cleanup_vm_for_template(self.template_t1.id) + self.cleanup_vm_for_template(self.template_t2.id) + super(TestVMDeploymentPlannerStrictTags, self).tearDown() + + def cleanup_vm_for_template(self, templateid): + vm_list = VirtualMachine.list(self.apiclient, listall=True, templateid=templateid) + if type(vm_list) is list: + for vm in vm_list: + self.expunge_vm(vm) + + def expunge_vm(self, vm): + try: + cmd = expungeVirtualMachine.expungeVirtualMachineCmd() + cmd.id = vm.id + self.apiclient.expungeVirtualMachine(cmd) + except Exception as e: + self.debug("Failed to expunge VM: %s" % e) + + @classmethod + def updateConfiguration(self, name, value): + cmd = updateConfiguration.updateConfigurationCmd() + cmd.name = name + cmd.value = value + self.apiclient.updateConfiguration(cmd) + + def deploy_vm(self, destination_id, template_id, service_offering_id): + return VirtualMachine.create(self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, + templateid=template_id, serviceofferingid=service_offering_id, + hostid=destination_id) + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_01_deploy_vm_on_specific_host_without_strict_tags(self): + self.updateConfiguration("vm.strict.host.tags", "") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "") + + vm = self.deploy_vm(self.host_h1.id, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.assertEqual(self.host_h1.id, vm.hostid, "VM instance was not deployed on target host ID") + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_02_deploy_vm_on_any_host_without_strict_tags(self): + self.updateConfiguration("vm.strict.host.tags", "") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "") + + vm = self.deploy_vm(None, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.assertIsNotNone(vm, "VM instance was not deployed") + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_03_deploy_vm_on_specific_host_with_strict_tags_success(self): + self.updateConfiguration("vm.strict.host.tags", "v1,v2") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "false") + self.updateConfiguration("resource.limit.host.tags", "h1,h2,t1,t2") + + vm = self.deploy_vm(self.host_h1.id, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.assertEqual(self.host_h1.id, vm.hostid, "VM instance was not deployed on target host ID") + + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + + vm = self.deploy_vm(self.host_h1.id, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.assertEqual(self.host_h1.id, vm.hostid, "VM instance was not deployed on target host ID") + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_04_deploy_vm_on_any_host_with_strict_tags_success(self): + self.updateConfiguration("vm.strict.host.tags", "v1,v2") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "false") + self.updateConfiguration("resource.limit.host.tags", "h1,h2,t1,t2") + + vm = self.deploy_vm(None, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.assertIsNotNone(vm, "VM instance was not deployed") + + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + + vm = self.deploy_vm(None, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.assertEqual(self.host_h1.id, vm.hostid, "VM instance was not deployed on target host ID") + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_05_deploy_vm_on_specific_host_with_strict_tags_failure(self): + self.updateConfiguration("vm.strict.host.tags", "v1,v2") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "h1,h2,t1,t2") + + try: + vm = self.deploy_vm(self.host_h1.id, self.template_t2.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.fail("VM should not be deployed") + except Exception as e: + self.assertTrue("Cannot deploy VM, destination host" in str(e)) + + try: + vm = self.deploy_vm(self.host_h1.id, self.template_t2.id, self.service_offering_h2.id) + self.cleanup.append(vm) + self.fail("VM should not be deployed") + except Exception as e: + self.assertTrue("Cannot deploy VM, destination host" in str(e)) + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_06_deploy_vm_on_any_host_with_strict_tags_failure(self): + self.updateConfiguration("vm.strict.host.tags", "v1,v2") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "h1,h2,t1,t2") + + try: + vm = self.deploy_vm(None, self.template_t2.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.fail("VM should not be deployed") + except Exception as e: + self.assertTrue("No suitable host found for vm " in str(e)) + + +class TestScaleVMStrictTags(cloudstackTestCase): + @classmethod + def setUpClass(cls): + testClient = super(TestScaleVMStrictTags, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.hypervisor = testClient.getHypervisorInfo() + cls.services['mode'] = cls.zone.networktype + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + # Create an account, network, VM and IP addresses + cls.account = Account.create(cls.apiclient, cls.services["account"], domainid=cls.domain.id) + cls.service_offering_h1 = ServiceOffering.create(cls.apiclient, cls.services["service_offering_h1"]) + cls.service_offering_h2 = ServiceOffering.create(cls.apiclient, cls.services["service_offering_h2"]) + + cls.template_t1 = Template.register(cls.apiclient, cls.services["test_templates"][cls.hypervisor.lower()], + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower(), templatetag="t1") + cls.template_t1.download(cls.apiclient) + + cls.template_t2 = Template.register(cls.apiclient, cls.services["test_templates"][cls.hypervisor.lower()], + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower(), templatetag="t2") + cls.template_t2.download(cls.apiclient) + + hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing') + cls.host_h1 = hosts[0] if len(hosts) >= 1 else None + + cls._cleanup = [cls.account, cls.service_offering_h1, cls.service_offering_h2, cls.template_t1, cls.template_t2] + + @classmethod + def tearDownClass(cls): + if cls.host_h1: + Host.update(cls.apiclient, id=cls.host_h1.id, hosttags="") + cls.updateConfiguration("vm.strict.host.tags", "") + cls.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + cls.updateConfiguration("resource.limit.host.tags", "") + super(TestScaleVMStrictTags, cls).tearDownClass() + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + if self.host_h1: + Host.update(self.apiclient, id=self.host_h1.id, hosttags="h1,t1,v1,h2,t2,v2") + self.updateConfiguration("vm.strict.host.tags", "") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "") + self.cleanup = [] + + def tearDown(self): + self.cleanup_vm_for_template(self.template_t1.id) + self.cleanup_vm_for_template(self.template_t2.id) + super(TestScaleVMStrictTags, self).tearDown() + + def cleanup_vm_for_template(self, templateid): + vm_list = VirtualMachine.list(self.apiclient, listall=True, templateid=templateid) + if type(vm_list) is list: + for vm in vm_list: + self.expunge_vm(vm) + + def expunge_vm(self, vm): + try: + cmd = expungeVirtualMachine.expungeVirtualMachineCmd() + cmd.id = vm.id + self.apiclient.expungeVirtualMachine(cmd) + except Exception as e: + self.debug("Failed to expunge VM: %s" % e) + + @classmethod + def updateConfiguration(self, name, value): + cmd = updateConfiguration.updateConfigurationCmd() + cmd.name = name + cmd.value = value + self.apiclient.updateConfiguration(cmd) + + def deploy_vm(self, destination_id, template_id, service_offering_id): + return VirtualMachine.create(self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, + templateid=template_id, serviceofferingid=service_offering_id, + hostid=destination_id) + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_01_scale_vm_strict_tags_success(self): + self.updateConfiguration("vm.strict.host.tags", "v1,v2") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "h1,h2,t1,t2") + + vm = self.deploy_vm(self.host_h1.id, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.assertEqual(self.host_h1.id, vm.hostid, "VM instance was not deployed on target host ID") + vm.stop(self.apiclient) + vm.scale(self.apiclient, serviceOfferingId=self.service_offering_h2.id) + vm.start(self.apiclient) + scaled_vm = VirtualMachine.list(self.apiclient, id=vm.id, listall=True)[0] + self.assertEqual(scaled_vm.serviceofferingid, self.service_offering_h2.id, "VM was not scaled") + self.assertEqual(self.host_h1.id, scaled_vm.hostid, "VM was not scaled") + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_02_scale_vm_strict_tags_failure(self): + if self.host_h1: + Host.update(self.apiclient, id=self.host_h1.id, hosttags="h1,t1,v1") + + self.updateConfiguration("vm.strict.host.tags", "v1,v2") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "h1,h2,t1,t2") + + vm = self.deploy_vm(self.host_h1.id, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + + self.assertEqual(self.host_h1.id, vm.hostid, "VM instance was not deployed on target host ID") + try: + vm.stop(self.apiclient) + vm.scale(self.apiclient, serviceOfferingId=self.service_offering_h2.id) + vm.start(self.apiclient) + self.fail("VM should not be be able scale and start") + except Exception as e: + self.assertTrue("No suitable host found for vm " in str(e)) + + +class TestRestoreVMStrictTags(cloudstackTestCase): + @classmethod + def setUpClass(cls): + testClient = super(TestRestoreVMStrictTags, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.hypervisor = testClient.getHypervisorInfo() + cls.services['mode'] = cls.zone.networktype + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + # Create an account, network, VM and IP addresses + cls.account = Account.create(cls.apiclient, cls.services["account"], domainid=cls.domain.id) + cls.service_offering_h1 = ServiceOffering.create(cls.apiclient, cls.services["service_offering_h1"]) + cls.service_offering_h2 = ServiceOffering.create(cls.apiclient, cls.services["service_offering_h2"]) + + cls.template_t1 = Template.register(cls.apiclient, cls.services["test_templates"][cls.hypervisor.lower()], + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower(), templatetag="t1") + cls.template_t1.download(cls.apiclient) + + cls.template_t2 = Template.register(cls.apiclient, cls.services["test_templates"][cls.hypervisor.lower()], + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower(), templatetag="t2") + cls.template_t2.download(cls.apiclient) + + hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing') + cls.host_h1 = hosts[0] if len(hosts) >= 1 else None + + cls._cleanup = [cls.account, cls.service_offering_h1, cls.service_offering_h2, cls.template_t1, cls.template_t2] + + @classmethod + def tearDownClass(cls): + if cls.host_h1: + Host.update(cls.apiclient, id=cls.host_h1.id, hosttags="") + cls.updateConfiguration("vm.strict.host.tags", "") + cls.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + cls.updateConfiguration("resource.limit.host.tags", "") + super(TestRestoreVMStrictTags, cls).tearDownClass() + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + if self.host_h1: + Host.update(self.apiclient, id=self.host_h1.id, hosttags="h1,t1,v1") + self.updateConfiguration("vm.strict.host.tags", "") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "") + self.cleanup = [] + + def tearDown(self): + self.cleanup_vm_for_template(self.template_t1.id) + self.cleanup_vm_for_template(self.template_t2.id) + super(TestRestoreVMStrictTags, self).tearDown() + + def cleanup_vm_for_template(self, templateid): + vm_list = VirtualMachine.list(self.apiclient, listall=True, templateid=templateid) + if type(vm_list) is list: + for vm in vm_list: + self.expunge_vm(vm) + + def expunge_vm(self, vm): + try: + cmd = expungeVirtualMachine.expungeVirtualMachineCmd() + cmd.id = vm.id + self.apiclient.expungeVirtualMachine(cmd) + except Exception as e: + self.debug("Failed to expunge VM: %s" % e) + + @classmethod + def updateConfiguration(self, name, value): + cmd = updateConfiguration.updateConfigurationCmd() + cmd.name = name + cmd.value = value + self.apiclient.updateConfiguration(cmd) + + def deploy_vm(self, destination_id, template_id, service_offering_id): + return VirtualMachine.create(self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, + templateid=template_id, serviceofferingid=service_offering_id, + hostid=destination_id) + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_01_restore_vm_strict_tags_success(self): + self.updateConfiguration("vm.strict.host.tags", "v1,v2") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "h1,h2") + + vm = self.deploy_vm(self.host_h1.id, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.assertEqual(self.host_h1.id, vm.hostid, "VM instance was not deployed on target host ID") + + vm.restore(self.apiclient, templateid=self.template_t2.id, expunge=True) + restored_vm = VirtualMachine.list(self.apiclient, id=vm.id, listall=True)[0] + self.assertEqual(restored_vm.templateid, self.template_t2.id, "VM was not restored") + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_02_restore_vm_strict_tags_failure(self): + self.updateConfiguration("vm.strict.host.tags", "v1,v2") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "h1,h2,t1,t2") + + vm = self.deploy_vm(self.host_h1.id, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + + self.assertEqual(self.host_h1.id, vm.hostid, "VM instance was not deployed on target host ID") + try: + vm.restore(self.apiclient, templateid=self.template_t2.id, expunge=True) + self.fail("VM should not be restored") + except Exception as e: + self.assertTrue("No suitable host found for vm " in str(e)) + + +class TestMigrateVMStrictTags(cloudstackTestCase): + @classmethod + def setUpClass(cls): + testClient = super(TestMigrateVMStrictTags, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.hypervisor = testClient.getHypervisorInfo() + cls.services['mode'] = cls.zone.networktype + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing') + cls.host_h1 = hosts[0] if len(hosts) >= 1 else None + cls.host_h2 = None + if len(hosts) >= 2: + for host in hosts[1:]: + if host.clusterid == cls.host_h1.clusterid: + cls.host_h2 = host + break + + if not cls.host_h2: + cls.skipTest("There are not enough hosts to run this test") + + # Create an account, network, VM and IP addresses + cls.account = Account.create(cls.apiclient, cls.services["account"], domainid=cls.domain.id) + cls.service_offering_h1 = ServiceOffering.create(cls.apiclient, cls.services["service_offering_h1"]) + cls.service_offering_h2 = ServiceOffering.create(cls.apiclient, cls.services["service_offering_h2"]) + + cls.template_t1 = Template.register(cls.apiclient, cls.services["test_templates"][cls.hypervisor.lower()], + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower(), templatetag="t1") + cls.template_t1.download(cls.apiclient) + + cls.template_t2 = Template.register(cls.apiclient, cls.services["test_templates"][cls.hypervisor.lower()], + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower(), templatetag="t2") + cls.template_t2.download(cls.apiclient) + + cls._cleanup = [cls.account, cls.service_offering_h1, cls.service_offering_h2, cls.template_t1, cls.template_t2] + + @classmethod + def tearDownClass(cls): + if cls.host_h1: + Host.update(cls.apiclient, id=cls.host_h1.id, hosttags="") + if cls.host_h2: + Host.update(cls.apiclient, id=cls.host_h2.id, hosttags="") + cls.updateConfiguration("vm.strict.host.tags", "") + cls.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + cls.updateConfiguration("resource.limit.host.tags", "") + super(TestMigrateVMStrictTags, cls).tearDownClass() + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + if self.host_h1: + Host.update(self.apiclient, id=self.host_h1.id, hosttags="h1,t1,v1") + self.updateConfiguration("vm.strict.host.tags", "") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "") + self.cleanup = [] + + def tearDown(self): + self.cleanup_vm_for_template(self.template_t1.id) + self.cleanup_vm_for_template(self.template_t2.id) + super(TestMigrateVMStrictTags, self).tearDown() + + def cleanup_vm_for_template(self, templateid): + vm_list = VirtualMachine.list(self.apiclient, listall=True, templateid=templateid) + if type(vm_list) is list: + for vm in vm_list: + self.expunge_vm(vm) + + def expunge_vm(self, vm): + try: + cmd = expungeVirtualMachine.expungeVirtualMachineCmd() + cmd.id = vm.id + self.apiclient.expungeVirtualMachine(cmd) + except Exception as e: + self.debug("Failed to expunge VM: %s" % e) + + @classmethod + def updateConfiguration(self, name, value): + cmd = updateConfiguration.updateConfigurationCmd() + cmd.name = name + cmd.value = value + self.apiclient.updateConfiguration(cmd) + + def deploy_vm(self, destination_id, template_id, service_offering_id): + return VirtualMachine.create(self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, + templateid=template_id, serviceofferingid=service_offering_id, + hostid=destination_id) + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_01_migrate_vm_strict_tags_success(self): + self.updateConfiguration("vm.strict.host.tags", "v1,v2") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "h1,h2,t1,t2") + + vm = self.deploy_vm(self.host_h1.id, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + self.assertEqual(self.host_h1.id, vm.hostid, "VM instance was not deployed on target host ID") + Host.update(self.apiclient, id=self.host_h2.id, hosttags="h1,t1,v1") + vm.migrate(self.apiclient, self.host_h2.id) + migrated_vm = VirtualMachine.list(self.apiclient, id=vm.id, listall=True)[0] + self.assertEqual(migrated_vm.hostid, self.host_h2.id, "VM was not migratd") + + @attr(tags=["advanced", "advancedns", "ssh", "smoke"], required_hardware="false") + def test_02_migrate_vm_strict_tags_failure(self): + self.updateConfiguration("vm.strict.host.tags", "v1,v2") + self.updateConfiguration("vm.strict.resource.limit.host.tag.check", "true") + self.updateConfiguration("resource.limit.host.tags", "h1,h2,t1,t2") + + vm = self.deploy_vm(self.host_h1.id, self.template_t1.id, self.service_offering_h1.id) + self.cleanup.append(vm) + + self.assertEqual(self.host_h1.id, vm.hostid, "VM instance was not deployed on target host ID") + Host.update(self.apiclient, id=self.host_h2.id, hosttags="h2,t2,v2") + try: + vm.migrate(self.apiclient, self.host_h2.id) + VirtualMachine.list(self.apiclient, id=vm.id, listall=True)[0] + self.fail("VM should not be migrated") + except Exception as e: + self.assertTrue("Cannot deploy VM, destination host:" in str(e)) diff --git a/test/integration/smoke/test_vnf_templates.py b/test/integration/smoke/test_vnf_templates.py new file mode 100644 index 00000000000..f963ce41b38 --- /dev/null +++ b/test/integration/smoke/test_vnf_templates.py @@ -0,0 +1,341 @@ +# 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. + +""" Smoke tests for VNF templates/appliances +""" +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import (Account, + Domain, + Configurations, + ServiceOffering, + VirtualMachine, + Network, + NetworkOffering, + VnfAppliance, + VnfTemplate, + Zone) +from marvin.lib.common import get_zone, get_template +from nose.plugins.attrib import attr + +import time + +VNF_NICS = [{"deviceid": "0", "name": "WAN", "required": "true", "description": "Public WAN"}, + {"deviceid": "1", "name": "LAN-1", "required": "true", "description": "Private LAN-1"}] +NEW_VNF_NICS = [{"deviceid": "0", "name": "WAN", "required": "true", "description": "Public WAN"}, + {"deviceid": "1", "name": "LAN-1", "required": "true", "description": "Private LAN-1"}, + {"deviceid": "2", "name": "LAN-2", "required": "false", "description": "Private LAN-2"}] +VNF_DETAILS = [{"access_methods": "console,https,http", "username": "root"}] +NEW_VNF_DETAILS = [{"access_methods": "console,https,http", "username": "root", "password": "cloudstack"}] + +class TestVnfTemplates(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + testClient = super(TestVnfTemplates, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls._cleanup = [] + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.hypervisor = cls.testClient.getHypervisorInfo() + zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + cls.zone = Zone(zone.__dict__) + cls.template = get_template(cls.apiclient, cls.zone.id) + + cls.domain = Domain.create( + cls.apiclient, + cls.services["domain"] + ) + cls._cleanup.append(cls.domain) + + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls._cleanup.append(cls.account) + + cls.user = cls.account.user[0] + cls.user_apiclient = cls.testClient.getUserApiClient( + cls.user.username, cls.domain.name + ) + + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["big"] + ) + cls._cleanup.append(cls.service_offering) + + cls.vnf_template_config = { + "name": "pfsense", + "displaytext": "pfsense", + "format": cls.template.format, + "url": cls.template.url, + "requireshvm": "True", + "ispublic": "True", + "isextractable": "True", + "hypervisor": cls.hypervisor, + "zoneid": cls.zone.id, + "ostype": "FreeBSD 12 (64-bit)", + "directdownload": False + } + + cls.initial_setting = Configurations.list( + cls.apiclient, + name="vnf.template.appliance.enabled")[0].value + + Configurations.update(cls.apiclient, "vnf.template.appliance.enabled", "true") + + cls.vnf_templates = [] + + @classmethod + def tearDownClass(cls): + Configurations.update(cls.apiclient, "vnf.template.appliance.enabled", cls.initial_setting) + if len(cls.vnf_templates) > 0: + for vnf_template in cls.vnf_templates: + vnf_template.delete(cls.user_apiclient) + super(TestVnfTemplates, cls).tearDownClass() + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + def tearDown(self): + super(TestVnfTemplates, self).tearDown() + + def ensureVnfTemplateExists(self): + if len(self.vnf_templates) == 0: + self.vnf_template = VnfTemplate.register(self.user_apiclient, + self.vnf_template_config, + zoneid=self.zone.id, + hypervisor=self.hypervisor, + vnfnics=VNF_NICS, + vnfdetails=VNF_DETAILS) + self.vnf_templates.append(self.vnf_template) + else: + self.vnf_template = self.vnf_templates[0] + + def ensureVnfTemplateDownloaded(self): + """Check if template download will finish in 5 minutes""" + retries = 30 + interval = 10 + while retries > -1: + time.sleep(interval) + templates_response = VnfTemplate.list( + self.user_apiclient, + id=self.vnf_template.id, + zoneid=self.zone.id, + templatefilter='self' + ) + template = templates_response[0] + + if not hasattr(template, 'status') or not template or not template.status: + retries = retries - 1 + continue + + if 'Failed' in template.status: + raise Exception( + "Failed to download template: status - %s" % + template.status) + elif template.status == 'Download Complete' and template.isready: + return + elif 'Downloaded' in template.status: + retries = retries - 1 + continue + elif 'Installing' not in template.status: + if retries >= 0: + retries = retries - 1 + continue + raise Exception( + "Error in downloading template: status - %s" % + template.status) + else: + retries = retries - 1 + raise Exception("Template download failed exception.") + + @attr(tags=["advanced"], required_hardware="false") + def test_01_register_vnf_template(self): + """Test register VNF template + """ + self.ensureVnfTemplateExists() + + @attr(tags=["advanced"], required_hardware="false") + def test_02_list_vnf_template(self): + """Test list VNF template + """ + self.ensureVnfTemplateExists() + + templates_response = VnfTemplate.list( + self.user_apiclient, + id=self.vnf_template.id, + zoneid=self.zone.id, + templatefilter='self' + ) + + if isinstance(templates_response, list) and len(templates_response) > 0: + template = templates_response[0] + self.assertEqual("VNF", template.templatetype, + "The template type of VNF template should be VNF but actually it is %s" % template.templatetype) + self.assertTrue(isinstance(template.vnfnics, list), "The template vnfnics must be a list") + self.assertEqual(2, len(template.vnfnics), "The VNF template should have 2 VNF nics") + self.assertEqual(2, len(template.vnfdetails.__dict__), "The VNF template should have 2 VNF details") + else: + self.fail("Failed to get VNF templates by listVnfTemplates API") + + @attr(tags=["advanced"], required_hardware="false") + def test_03_edit_vnf_template(self): + """Test edit VNF template + """ + self.ensureVnfTemplateExists() + + self.vnf_template.update( + self.user_apiclient, + id=self.vnf_template.id, + vnfnics=NEW_VNF_NICS, + vnfdetails=NEW_VNF_DETAILS + ) + + templates_response = VnfTemplate.list( + self.user_apiclient, + id=self.vnf_template.id, + zoneid=self.zone.id, + templatefilter='self' + ) + + if isinstance(templates_response, list) and len(templates_response) > 0: + template = templates_response[0] + self.assertEqual("VNF", template.templatetype, + "The template type of VNF template should be VNF but actually it is %s" % template.templatetype) + self.assertEqual(3, len(template.vnfnics), "The VNF template should have 2 VNF nics") + self.assertEqual(3, len(template.vnfdetails.__dict__), "The VNF template should have 3 VNF details") + else: + self.fail("Failed to get VNF templates by listVnfTemplates API") + + @attr(tags=["advanced"], required_hardware="false") + def test_04_deploy_vnf_appliance(self): + """Test deploy VNF appliance + """ + self.ensureVnfTemplateExists() + self.ensureVnfTemplateDownloaded() + + templates_response = VnfTemplate.list( + self.user_apiclient, + id=self.vnf_template.id, + zoneid=self.zone.id, + templatefilter='self' + ) + + if isinstance(templates_response, list) and len(templates_response) > 0: + template = templates_response[0] + if not template.isready: + self.fail("VNF template is not Ready") + else: + self.fail("Failed to find VNF template") + + # Create network offerings + self.isolated_network_offering = NetworkOffering.create( + self.apiclient, + self.services["isolated_network_offering"]) + self.cleanup.append(self.isolated_network_offering) + self.isolated_network_offering.update( + self.apiclient, + state='Enabled') + + self.l2_network_offering = NetworkOffering.create( + self.apiclient, + self.services["l2-network_offering"]) + self.cleanup.append(self.l2_network_offering) + self.l2_network_offering.update( + self.apiclient, + state='Enabled') + + # Create networks + isolated_network = Network.create( + self.user_apiclient, + self.services["network"], + networkofferingid=self.isolated_network_offering.id, + zoneid=self.zone.id + ) + self.cleanup.append(isolated_network) + + l2_network_1 = Network.create( + self.user_apiclient, + self.services["l2-network"], + networkofferingid=self.l2_network_offering.id, + zoneid=self.zone.id + ) + self.cleanup.append(l2_network_1) + + l2_network_2 = Network.create( + self.user_apiclient, + self.services["l2-network"], + networkofferingid=self.l2_network_offering.id, + zoneid=self.zone.id + ) + self.cleanup.append(l2_network_2) + + # failed deployment + try: + self.virtual_machine = VirtualMachine.create( + self.user_apiclient, + self.services["virtual_machine"], + zoneid=self.zone.id, + templateid=self.vnf_template.id, + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[isolated_network.id] + ) + self.cleanup.append(self.virtual_machine) + self.fail("The deployment should fail") + except Exception as e: + pass + + # success deployment + self.vnf_appliance = VnfAppliance.create( + self.user_apiclient, + self.services["virtual_machine"], + zoneid=self.zone.id, + templateid=self.vnf_template.id, + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[isolated_network.id, l2_network_1.id, l2_network_2.id], + vnfconfiguremanagement='true' + ) + self.cleanup.append(self.vnf_appliance) + + @attr(tags=["advanced"], required_hardware="false") + def test_05_delete_vnf_template(self): + """Test delete VNF template + """ + self.ensureVnfTemplateExists() + + self.vnf_template.delete(self.user_apiclient) + + templates_response = VnfTemplate.list( + self.user_apiclient, + id=self.vnf_template.id, + zoneid=self.zone.id, + templatefilter='self' + ) + self.assertIsNone(templates_response, "The VNF template should be removed") + + self.vnf_templates.remove(self.vnf_template) diff --git a/test/integration/smoke/test_vpc_ipv6.py b/test/integration/smoke/test_vpc_ipv6.py index ce4d466acf0..efec43add7c 100644 --- a/test/integration/smoke/test_vpc_ipv6.py +++ b/test/integration/smoke/test_vpc_ipv6.py @@ -761,8 +761,9 @@ class TestIpv6Vpc(cloudstackTestCase): acl_chain = nic + ACL_CHAINS_SUFFIX[rule["traffictype"]] routerCmd = "nft list chain ip6 %s %s" % (ACL_TABLE, acl_chain) res = self.getRouterProcessStatus(router, routerCmd) - self.assertTrue(rule["parsedrule"] in res, - "Listing firewall rule with nft list chain failure for rule: %s" % rule["parsedrule"]) + parsed_rule_new = rule["parsedrule"].replace("{ ", "").replace(" }", "") + self.assertTrue(rule["parsedrule"] in res or parsed_rule_new in res, + "Listing firewall rule with nft list chain failure for rule: '%s' is not in '%s'" % (rule["parsedrule"], res)) def checkIpv6AclRule(self): router = self.getVpcRouter(self.vpc) diff --git a/test/integration/smoke/test_vpc_vpn.py b/test/integration/smoke/test_vpc_vpn.py index 63846cf10ff..bcee37a06c7 100644 --- a/test/integration/smoke/test_vpc_vpn.py +++ b/test/integration/smoke/test_vpc_vpn.py @@ -592,7 +592,7 @@ class TestVpcSite2SiteVpn(cloudstackTestCase): time.sleep(20) # setup ssh connection to vm2 - ssh_client = self._get_ssh_client(vm2, self.services, 10) + ssh_client = self._get_ssh_client(vm2, self.services, 30) if ssh_client: # run ping test diff --git a/test/integration/smoke/test_webhook_delivery.py b/test/integration/smoke/test_webhook_delivery.py new file mode 100644 index 00000000000..00178bd03ff --- /dev/null +++ b/test/integration/smoke/test_webhook_delivery.py @@ -0,0 +1,212 @@ +# 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. +""" BVT tests for webhooks delivery with a basic server +""" +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import (Account, + Domain, + Webhook, + SSHKeyPair) +from marvin.lib.common import (get_domain, + get_zone) +from marvin.lib.utils import (random_gen) +from marvin.cloudstackException import CloudstackAPIException +from nose.plugins.attrib import attr +from http.server import BaseHTTPRequestHandler, HTTPServer +import logging +# Import System modules +import time +import json +import socket +import _thread + + +_multiprocess_shared_ = True +deliveries_received = [] + +class WebhookReceiver(BaseHTTPRequestHandler): + """ + WebhookReceiver class to receive webhook events + """ + def _set_response(self): + self.send_response(200) + self.send_header('Content-type', 'text/html') + self.end_headers() + + def do_POST(self): + content_length = int(self.headers['Content-Length']) + post_data = self.rfile.read(content_length) + post_data = post_data.decode('utf-8') + event_id = self.headers.get('X-CS-Event-ID') + print("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n" % + (str(self.path), str(self.headers), post_data)) + self._set_response() + global deliveries_received + if deliveries_received is None: + deliveries_received = [] + deliveries_received.append({'event': event_id, 'payload': post_data}) + if event_id != None: + self.wfile.write("Event with ID: {} successfully processed!".format(str(event_id)).encode('utf-8')) + else: + self.wfile.write("POST request for {}".format(self.path).encode('utf-8')) + +class TestWebhookDelivery(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestWebhookDelivery, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls.mgtSvrDetails = cls.config.__dict__["mgtSvr"][0].__dict__ + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.logger = logging.getLogger('TestWebhookDelivery') + cls.logger.setLevel(logging.DEBUG) + + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect((cls.mgtSvrDetails["mgtSvrIp"], cls.mgtSvrDetails["port"])) + cls.server_ip = s.getsockname()[0] + s.close() + if cls.server_ip == "127.0.0.1": + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(("8.8.8.8", 80)) + cls.server_ip = s.getsockname()[0] + s.close() + # use random port for webhookreceiver server + s = socket.socket() + s.bind(('', 0)) + cls.server_port = s.getsockname()[1] + s.close() + cls.webhook_receiver_url = "http://" + cls.server_ip + ":" + str(cls.server_port) + cls.logger.debug("Running Webhook receiver @ %s" % cls.webhook_receiver_url) + def startMgmtServer(tname, server): + cls.logger.debug("Starting WebhookReceiver") + try: + server.serve_forever() + except Exception: pass + cls.server = HTTPServer(('0.0.0.0', cls.server_port), WebhookReceiver) + _thread.start_new_thread(startMgmtServer, ("webhook-receiver", cls.server,)) + + cls._cleanup = [] + + @classmethod + def tearDownClass(cls): + if cls.server: + cls.server.socket.close() + global deliveries_received + deliveries_received = [] + super(TestWebhookDelivery, cls).tearDownClass() + + def setUp(self): + self.cleanup = [] + self.domain1 = Domain.create( + self.apiclient, + self.services["domain"]) + self.cleanup.append(self.domain1) + + def tearDown(self): + super(TestWebhookDelivery, self).tearDown() + + def popItemFromCleanup(self, item_id): + for idx, x in enumerate(self.cleanup): + if x.id == item_id: + self.cleanup.pop(idx) + break + + def createDomainAccount(self, isDomainAdmin=False): + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=isDomainAdmin, + domainid=self.domain1.id) + self.cleanup.append(self.account) + self.userapiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain + ) + + def createWebhook(self, apiclient, scope=None, domainid=None, account=None, payloadurl=None, description=None, sslverification=None, secretkey=None, state=None): + name = "Test-" + random_gen() + if payloadurl is None: + payloadurl = self.webhook_receiver_url + self.webhook = Webhook.create( + apiclient, + name=name, + payloadurl=payloadurl, + description=description, + scope=scope, + sslverification=sslverification, + secretkey=secretkey, + state=state, + domainid=domainid, + account=account + ) + self.cleanup.append(self.webhook) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_01_webhook_deliveries(self): + global deliveries_received + self.createDomainAccount() + self.createWebhook(self.userapiclient) + self.keypair = SSHKeyPair.register( + self.userapiclient, + name="Test-" + random_gen(), + publickey="ssh-rsa: e6:9a:1e:b5:98:75:88:5d:56:bc:92:7b:43:48:05:b2" + ) + self.logger.debug("Registered sshkeypair: %s" % str(self.keypair.__dict__)) + time.sleep(2) + list_deliveries = self.webhook.list_deliveries( + self.userapiclient, + page=1, + pagesize=20 + ) + self.assertNotEqual( + list_deliveries, + None, + "Check webhook deliveries list" + ) + self.assertTrue( + len(list_deliveries) > 0, + "Check webhook deliveries list length" + ) + for delivery in list_deliveries: + self.assertEqual( + delivery.success, + True, + "Check webhook delivery success" + ) + self.assertEqual( + delivery.response, + ("Event with ID: %s successfully processed!" % delivery.eventid), + "Check webhook delivery response" + ) + delivery_matched = False + for received in deliveries_received: + if received['event'] == delivery.eventid: + self.assertEqual( + delivery.payload, + received['payload'], + "Check webhook delivery payload" + ) + delivery_matched = True + self.assertTrue( + delivery_matched, + "Delivery for %s did not match with server" % delivery.id + ) diff --git a/test/integration/smoke/test_webhook_lifecycle.py b/test/integration/smoke/test_webhook_lifecycle.py new file mode 100644 index 00000000000..2d1f322be6b --- /dev/null +++ b/test/integration/smoke/test_webhook_lifecycle.py @@ -0,0 +1,392 @@ +# 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. +""" BVT tests for webhooks lifecycle functionalities +""" +# Import Local Modules +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.cloudstackAPI import (listEvents) +from marvin.lib.base import (Account, + Domain, + Webhook, + SSHKeyPair) +from marvin.lib.common import (get_domain, + get_zone) +from marvin.lib.utils import (random_gen) +from marvin.cloudstackException import CloudstackAPIException +from nose.plugins.attrib import attr +import logging +# Import System modules +import time +from datetime import datetime + + +_multiprocess_shared_ = True +HTTP_PAYLOAD_URL = "http://smee.io/C9LPa7Ei3iB6Qj2" +HTTPS_PAYLOAD_URL = "https://smee.io/C9LPa7Ei3iB6Qj2" + +class TestWebhooks(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestWebhooks, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + + cls._cleanup = [] + cls.logger = logging.getLogger('TestWebhooks') + cls.logger.setLevel(logging.DEBUG) + + @classmethod + def tearDownClass(cls): + super(TestWebhooks, cls).tearDownClass() + + def setUp(self): + self.cleanup = [] + self.domain1 = Domain.create( + self.apiclient, + self.services["domain"]) + self.cleanup.append(self.domain1) + + def tearDown(self): + super(TestWebhooks, self).tearDown() + + def popItemFromCleanup(self, item_id): + for idx, x in enumerate(self.cleanup): + if x.id == item_id: + self.cleanup.pop(idx) + break + + def createDomainAccount(self, isDomainAdmin=False): + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=isDomainAdmin, + domainid=self.domain1.id) + self.cleanup.append(self.account) + self.userapiclient = self.testClient.getUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain + ) + + def runWebhookLifecycleTest(self, apiclient, scope=None, domainid=None, account=None, normaluser=None, payloadurl=None, description=None, sslverification=None, secretkey=None, state=None, isdelete=True): + name = "Test-" + random_gen() + if payloadurl is None: + payloadurl = HTTP_PAYLOAD_URL + self.webhook = Webhook.create( + apiclient, + name=name, + payloadurl=payloadurl, + description=description, + scope=scope, + sslverification=sslverification, + secretkey=secretkey, + state=state, + domainid=domainid, + account=account + ) + self.cleanup.append(self.webhook) + self.assertNotEqual( + self.webhook, + None, + "Check webhook created" + ) + webhook_id = self.webhook.id + self.logger.debug("Created webhook: %s" % str(self.webhook.__dict__)) + self.assertEqual( + name, + self.webhook.name, + "Check webhook name" + ) + self.assertEqual( + payloadurl, + self.webhook.payloadurl, + "Check webhook payloadurl" + ) + if state is None: + state = 'Enabled' + self.assertEqual( + state, + self.webhook.state, + "Check webhook state" + ) + if scope is None or normaluser is not None: + scope = 'Local' + self.assertEqual( + scope, + self.webhook.scope, + "Check webhook scope" + ) + if sslverification is None: + sslverification = False + self.assertEqual( + sslverification, + self.webhook.sslverification, + "Check webhook sslverification" + ) + if domainid is not None: + if normaluser is not None: + domainid = normaluser.domainid + self.assertEqual( + domainid, + self.webhook.domainid, + "Check webhook domainid" + ) + if account is not None: + self.assertEqual( + account, + self.webhook.account, + "Check webhook account" + ) + if description is not None: + self.assertEqual( + description, + self.webhook.description, + "Check webhook description" + ) + if secretkey is not None: + self.assertEqual( + secretkey, + self.webhook.secretkey, + "Check webhook secretkey" + ) + list_webhook = Webhook.list( + apiclient, + id=webhook_id + ) + self.assertNotEqual( + list_webhook, + None, + "Check webhook list" + ) + self.assertEqual( + len(list_webhook), + 1, + "Check webhook list length" + ) + self.assertEqual( + list_webhook[0].id, + webhook_id, + "Check webhook list item" + ) + if isdelete == False: + return + self.webhook.delete(apiclient) + self.popItemFromCleanup(webhook_id) + list_webhook = Webhook.list( + apiclient, + id=webhook_id + ) + self.assertTrue( + list_webhook is None or len(list_webhook) == 0, + "Check webhook list after delete" + ) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_01_create_webhook_admin_local(self): + self.runWebhookLifecycleTest(self.apiclient) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_02_create_webhook_admin_domain(self): + self.runWebhookLifecycleTest(self.apiclient, 'Domain', self.domain1.id) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_03_create_webhook_admin_global(self): + self.runWebhookLifecycleTest(self.apiclient, 'Global') + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_04_create_webhook_domainadmin_local(self): + self.createDomainAccount(True) + self.runWebhookLifecycleTest(self.userapiclient) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_05_create_webhook_domainadmin_subdomain(self): + self.createDomainAccount(True) + self.domain11 = Domain.create( + self.apiclient, + self.services["domain"], + parentdomainid=self.domain1.id) + self.cleanup.append(self.domain11) + self.runWebhookLifecycleTest(self.userapiclient, 'Domain', self.domain11.id) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_06_create_webhook_domainadmin_global_negative(self): + self.createDomainAccount(True) + try: + self.runWebhookLifecycleTest(self.userapiclient, 'Global') + except CloudstackAPIException as e: + self.assertTrue( + "errorText:Scope Global can not be specified for owner" in str(e), + "Check Global scope error check" + ) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_07_create_webhook_user_local(self): + self.createDomainAccount() + self.runWebhookLifecycleTest(self.userapiclient) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_08_create_webhook_user_domain(self): + """For normal user scope will always be Local irrespective of the passed value + """ + self.createDomainAccount() + self.runWebhookLifecycleTest(self.userapiclient, 'Domain', self.domain1.id, normaluser=self.account) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_09_create_webhook_user_gloabl(self): + """For normal user scope will always be Local irrespective of the passed value + """ + self.createDomainAccount() + self.runWebhookLifecycleTest(self.userapiclient, 'Global', normaluser=self.account) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_10_create_webhook_admin_advanced(self): + self.createDomainAccount() + self.runWebhookLifecycleTest( + self.apiclient, + payloadurl=HTTPS_PAYLOAD_URL, + scope="Local", + description="Webhook", + sslverification=True, + secretkey="webhook", + state="Disabled", + domainid=self.domain1.id, + account=self.account.name + ) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_11_update_webhook(self): + self.createDomainAccount() + self.runWebhookLifecycleTest(self.userapiclient, isdelete=False) + description = "Desc-" + random_gen() + secretkey = random_gen() + state = 'Disabled' + updated_webhook = self.webhook.update( + self.userapiclient, + description=description, + secretkey=secretkey, + state=state + )['webhook'] + self.assertNotEqual( + updated_webhook, + None, + "Check updated webhook" + ) + self.assertEqual( + description, + updated_webhook.description, + "Check webhook description" + ) + self.assertEqual( + secretkey, + updated_webhook.secretkey, + "Check webhook secretkey" + ) + self.assertEqual( + state, + updated_webhook.state, + "Check webhook state" + ) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_12_list_user_webhook_deliveries(self): + self.createDomainAccount() + self.runWebhookLifecycleTest(self.userapiclient, isdelete=False) + now = datetime.now() # current date and time + start_time = now.strftime("%Y-%m-%d %H:%M:%S") + self.keypair = SSHKeyPair.register( + self.userapiclient, + name="Test-" + random_gen(), + publickey="ssh-rsa: e6:9a:1e:b5:98:75:88:5d:56:bc:92:7b:43:48:05:b2" + ) + self.logger.debug("Registered sshkeypair: %s" % str(self.keypair.__dict__)) + cmd = listEvents.listEventsCmd() + cmd.startdate = start_time + cmd.listall = True + events = self.apiclient.listEvents(cmd) + register_sshkeypair_event_count = 0 + if events is not None: + for event in events: + if event.type == "REGISTER.SSH.KEYPAIR": + register_sshkeypair_event_count = register_sshkeypair_event_count + 1 + time.sleep(5) + list_deliveries = self.webhook.list_deliveries( + self.userapiclient, + page=1, + pagesize=20 + ) + self.assertNotEqual( + list_deliveries, + None, + "Check webhook deliveries list" + ) + self.assertTrue( + len(list_deliveries) > 0, + "Check webhook deliveries list length" + ) + register_sshkeypair_delivery_count = 0 + for delivery in list_deliveries: + if delivery.eventtype == "REGISTER.SSH.KEYPAIR": + register_sshkeypair_delivery_count = register_sshkeypair_delivery_count + 1 + self.assertEqual( + register_sshkeypair_event_count, + register_sshkeypair_delivery_count, + "Check sshkeypair webhook deliveries count" + ) + self.webhook.delete_deliveries( + self.userapiclient + ) + list_deliveries = self.webhook.list_deliveries( + self.userapiclient + ) + self.assertTrue( + list_deliveries is None or len(list_deliveries) == 0, + "Check webhook deliveries list after delete" + ) + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_13_webhook_execute_delivery(self): + self.createDomainAccount() + self.runWebhookLifecycleTest(self.userapiclient, isdelete=False) + payload = "{ \"CloudStack\": \"Integration Test\" }" + delivery = self.webhook.execute_delivery( + self.userapiclient, + payload=payload + ) + self.assertNotEqual( + delivery, + None, + "Check test webhook delivery" + ) + self.assertEqual( + self.webhook.id, + delivery.webhookid, + "Check test webhook delivery webhook" + ) + self.assertEqual( + payload, + delivery.payload, + "Check test webhook delivery payload" + ) + self.assertEqual( + self.webhook.id, + delivery.webhookid, + "Check test webhook delivery webhook" + ) diff --git a/test/integration/testpaths/testpath_multiple_snapshot.py b/test/integration/testpaths/testpath_multiple_snapshot.py index 50cccff61e5..f4bc4148611 100644 --- a/test/integration/testpaths/testpath_multiple_snapshot.py +++ b/test/integration/testpaths/testpath_multiple_snapshot.py @@ -157,7 +157,7 @@ class TestMultipleVolumeSnapshots(cloudstackTestCase): storage pools available in the setup") if len(list(storagePool for storagePool in self.pools if storagePool.scope == "CLUSTER")) < 2: - self.skipTest("There must be at at least two cluster wide\ + self.skipTest("There must be at least two cluster wide\ storage pools available in the setup") except Exception as e: self.skipTest(e) diff --git a/test/integration/testpaths/testpath_restore_vm.py b/test/integration/testpaths/testpath_restore_vm.py index 32ac214a739..956e41183bc 100644 --- a/test/integration/testpaths/testpath_restore_vm.py +++ b/test/integration/testpaths/testpath_restore_vm.py @@ -141,7 +141,7 @@ class TestRestoreVM(cloudstackTestCase): "Check: Failed to list cluster wide storage pools") if len(self.pools) < 2: - self.skipTest("There must be at at least two cluster wide\ + self.skipTest("There must be at least two cluster wide\ storage pools available in the setup") except Exception as e: diff --git a/test/integration/testpaths/testpath_usage.py b/test/integration/testpaths/testpath_usage.py index 3774bf8471c..e68bbaf56f2 100644 --- a/test/integration/testpaths/testpath_usage.py +++ b/test/integration/testpaths/testpath_usage.py @@ -112,7 +112,7 @@ class TestUsage(cloudstackTestCase): if cls.zone.localstorageenable: cls.testdata["service_offering"]["storagetype"] = 'local' - # Create 2 service offerings with different values for + # Create 2 service offerings with different values # for cpunumber, cpuspeed, and memory cls.testdata["service_offering"]["cpunumber"] = "1" @@ -215,7 +215,7 @@ class TestUsage(cloudstackTestCase): @classmethod def setUsageConfiguration(cls): """ Set the configuration parameters so that usage job runs - every 10 miuntes """ + every 10 minutes """ Configurations.update( cls.apiclient, @@ -432,9 +432,9 @@ class TestUsage(cloudstackTestCase): def test_01_positive_tests_usage(self): """ Positive test for usage test path - # 1. Register a template and verify that usage usage is generated + # 1. Register a template and verify that usage is generated for correct size of template - # 2. Register an ISO, verify usage is generate for the correct size + # 2. Register an ISO, verify usage is generated for the correct size of ISO # 3. Deploy a VM from the template and verify usage is generated for the VM with correct Service Offering and template id @@ -442,8 +442,8 @@ class TestUsage(cloudstackTestCase): # 5. Stop and start the VM # 6. Verify that allocated VM usage should be greater than running VM usage - # 7. Destroy the Vm and recover it - # 8. Verify that the running VM usage stays the same after delete and + # 7. Destroy the VM and recover it + # 8. Verify that the running VM usage stays the same after delete and after recover operation # 9. Verify that allocated VM usage should be greater after recover operation than after destroy operation @@ -453,7 +453,7 @@ class TestUsage(cloudstackTestCase): # 12. Start the VM # 13. Verify that the running VM usage after start operation is less than the allocated VM usage - # 14. Verify that the running VM usage after start vm opearation + # 14. Verify that the running VM usage after start VM operation is greater running VM usage after recover VM operation """ @@ -551,7 +551,7 @@ class TestUsage(cloudstackTestCase): "Iso list validation failed" ) - # Checking usage for Iso + # Checking usage for ISO response = self.listUsageRecords(usagetype=8) self.assertEqual(response[0], PASS, response[1]) isoUsageRecords = [record for record in response[1] @@ -824,7 +824,7 @@ class TestUsage(cloudstackTestCase): self.assertEqual(response[0], PASS, response[1]) vmAllocatedUsageRecord = response[1][-1] - # Step 11: Veriying vm usage for new service offering + # Step 11: Verifying VM usage for new service offering self.assertEqual(vmAllocatedUsageRecord.offeringid, self.service_offering_2.id, "The service offering id in the usage record\ @@ -884,7 +884,7 @@ class TestUsage(cloudstackTestCase): generated for template with correct size # 7. Delete the template and verify that usage is stopped for template - # 8. Create volume from snaopshot and verify correct disk usage + # 8. Create volume from snapshot and verify correct disk usage is generated # 9. Delete the volume and verify that the usage is stopped # 10. Create template from snapshot and verify correct usage @@ -1230,7 +1230,7 @@ class TestUsage(cloudstackTestCase): # Step 7 templateFromVolume.delete(self.userapiclient) - # Verifying usage for Template is stoppd after deleting it - START + # Verifying usage for Template is stopped after deleting it - START response = self.listUsageRecords(usagetype=7) self.assertEqual(response[0], PASS, response[1]) templateUsageRecords = response[1] @@ -1256,7 +1256,7 @@ class TestUsage(cloudstackTestCase): "usage for template after deletion should remain the same\ after specific intervals of time") - # Verifying usage for Template is stoppd after deleting it - END + # Verifying usage for Template is stopped after deleting it - END # Step 8 self.testdata["volume_from_snapshot"]["zoneid"] = self.zone.id @@ -1489,7 +1489,7 @@ class TestUsage(cloudstackTestCase): usage is generated for account Also verify that IP usage is generated for source NAT IP of network - # 2. Enabled VPN on source nat IP of default network of VM + # 2. Enabled VPN on source NAT IP of default network of VM # 3. Add two VPN users and check that usage is generated for VPN users # 4. Acquire public IP in the network and verify that IP usage is generated for the acquired IP @@ -1532,7 +1532,7 @@ class TestUsage(cloudstackTestCase): # Usages for steps are checked together in batch after the operations are done # to avoid waiting for usage job to run for each operation separately - # Listing source nat ip of newly added network + # Listing source NAT IP of newly added network ipAddresses = PublicIPAddress.list( self.apiclient, associatednetworkid=isolated_network.id, @@ -1548,7 +1548,7 @@ class TestUsage(cloudstackTestCase): sourceNatIPDefaultNetwork = ipAddressesDefaultNetwork[0] # Step 2 - # Create VPN for source NAT ip + # Create VPN for source NAT IP Vpn.create(self.apiclient, sourceNatIPDefaultNetwork.id, account=self.account.name, @@ -1625,7 +1625,7 @@ class TestUsage(cloudstackTestCase): # Usages for above operations are checked here together - # Checking usage for source nat IP of added network + # Checking usage for source NAT IP of added network response = self.listUsageRecords(usagetype=13) self.assertEqual(response[0], PASS, response[1]) usageRecords = response[1] @@ -1639,7 +1639,7 @@ class TestUsage(cloudstackTestCase): self.assertTrue(float(nwOfferingUsageRecords[0].rawusage) > 0, "Raw usage not started for source NAT ip") - # Checking usage for source nat IP of default VM network + # Checking usage for source NAT IP of default VM network response = self.listUsageRecords(usagetype=3, sleep=False) self.assertEqual(response[0], PASS, response[1]) usageRecords = response[1] @@ -1775,7 +1775,7 @@ class TestUsage(cloudstackTestCase): ) # Step 6 - # Enabling static Nat for Ip Address associated + # Enabling static NAT for IP Address associated StaticNATRule.enable( self.userapiclient, ipaddressid=public_ip_2.ipaddress.id, @@ -1933,7 +1933,7 @@ class TestUsage(cloudstackTestCase): natRule_1_Usage_t1 == natRule_1_Usage_t2, "NAT rule usage should be stopped once the rule is deleted") - # Also verify that usage for other nat rule is running + # Also verify that usage for other NAT rule is running natRule_2_Usage_t1 = sum(float(record.rawusage) for record in [record for record in usageRecords if nat_rule_2.id == record.usageid]) @@ -1962,7 +1962,6 @@ class TestUsage(cloudstackTestCase): is generated for the account # 4. Create another LB rule with different ports and verify separate usage is generated for new LB rule - # 5. Create egress firewall rule for VM and SSH to VM # 6. Ping external network from the VM and verify that network byte usage is generated correctly @@ -1972,12 +1971,11 @@ class TestUsage(cloudstackTestCase): # Verify iptables counters are reset when domR stops # Verify current_bytes in user_statistics table are moved to net_bytes - # Verify currnt_bytes becomes zero + # Verify current_bytes becomes zero # 9. Start the router and # Verify iptables counters are reset when domR starts # Verify a diff of total (current_bytes + net_bytes) in previous aggregation period and current period will give the network usage - """ # Step 1 @@ -2253,7 +2251,7 @@ class TestUsage(cloudstackTestCase): """ Positive test for usage test path T61 - T62 Steps: # 1. Deploy a VM - # 2. Take Vm snapshot and verify usage is generated for VM snapshot + # 2. Take VM snapshot and verify usage is generated for VM snapshot # 3. Delete VM snapshot and verify that usage stops """ @@ -2315,14 +2313,14 @@ class TestUsage(cloudstackTestCase): @attr(tags=["advanced"], required_hardware="true") def test_06_positive_tests_usage(self): - """Migrate VM and verify usage""" + """Migrate VM and verify usage # Validate the following # 1. Create a VM, and verify that usage is generated for it # with correct service offering and template id # 2. Migrate the VM to suitable host # 3. Verify that after migration, VM usage continues to be running - + """ if self.hypervisor.lower() in ['lxc']: self.skipTest( "vm migrate feature is not supported on %s" % @@ -2394,26 +2392,26 @@ class TestUsage(cloudstackTestCase): """ Steps: # 1. Add VM in VPC network, verify that - # usage is generated for source nat ip pf network in vpc - # 2. Acquire a public ip in VPC network and verify - usage is generated for the public ip - # 3. Create multiple PF rule on this ip in VPC network, - and verify that usage is generated for both pf rules - # 4. Enable vpn on source nat ip in vpc network - # 5. Add 2 vpn user - And verify that usage is generated for both the vpn users - # 6. Delete one VPn user, and verify that usage is stopped + # usage is generated for source NAT IP pf network in VPC + # 2. Acquire a public IP in VPC network and verify + usage is generated for the public IP + # 3. Create multiple PF rule on this IP in VPC network, + and verify that usage is generated for both PF rules + # 4. Enable VPN on source NAT IP in VPC network + # 5. Add 2 VPN user + And verify that usage is generated for both the VPN users + # 6. Delete one VPN user, and verify that usage is stopped for deleted user # 7. Open Egress rules on this VPC network # 8. Create network traffic on this network ping www.google.com, and verify that usage is generated for network traffic - # 9. Delete onePF rule in VPC network - And verify that usage is stopped for the pf rule - # 10. Stop router for VPC network + # 9. Delete one PF rule in VPC network + And verify that usage is stopped for the PF rule + # 10. Stop router for VPC network Verify iptables counters are reset when domR stops # Verify current_bytes in user_statistics table are moved to net_bytes - # Verify currnt_bytes becomes zero + # Verify current_bytes becomes zero # 11. Start router for VPC network Verify iptables counters are reset when domR starts # Verify a diff of total (current_bytes + net_bytes) in previous @@ -2534,7 +2532,7 @@ class TestUsage(cloudstackTestCase): sourceNatIP = ipAddresses[0] # Usage verification section - # Checking source nat IP usage + # Checking source NAT IP usage response = self.listUsageRecords(usagetype=3) self.assertEqual(response[0], PASS, response[1]) usageRecords = response[1] @@ -2582,7 +2580,7 @@ class TestUsage(cloudstackTestCase): "Raw usage not started for nat rule") # Step 4: - # Create VPN for source NAT ip + # Create VPN for source NAT IP Vpn.create(self.apiclient, sourceNatIP.id, account=self.account.name, @@ -2884,7 +2882,7 @@ class TestUsage(cloudstackTestCase): @attr(tags=["advanced", "basic"], required_hardware="false") def test_08_checkNewVolumein_listUsageRecords(self): - """ Test case to check if new volume crated after + """ Test case to check if new volume created after restore VM is listed in listUsageRecords # 1. Launch a VM # 2. Restore the VM @@ -3063,7 +3061,7 @@ class TestUsageDirectMeteringBasicZone(cloudstackTestCase): if cls.zone.localstorageenable: cls.testdata["service_offering"]["storagetype"] = 'local' - # Create 2 service offerings with different values for + # Create 2 service offerings with different values # for cpunumber, cpuspeed, and memory cls.testdata["service_offering"]["cpunumber"] = "1" @@ -3110,7 +3108,7 @@ class TestUsageDirectMeteringBasicZone(cloudstackTestCase): domainid=self.domain.id ) self.cleanup.append(self.account) - # Create user api client of the account + # Create user API client of the account self.userapiclient = self.testClient.getUserApiClient( UserName=self.account.name, DomainName=self.account.domain @@ -3261,7 +3259,7 @@ class TestUsageDirectMeteringBasicZone(cloudstackTestCase): return def getLatestUsageJobExecutionTime(self): - """ Get the end time of latest usage job that has run successfully""" + """Get the end time of latest usage job that has run successfully""" try: qresultset = self.dbclient.execute( diff --git a/test/integration/testpaths/testpath_vmlc.py b/test/integration/testpaths/testpath_vmlc.py index 0ae70c8e4bd..8384a472a0b 100755 --- a/test/integration/testpaths/testpath_vmlc.py +++ b/test/integration/testpaths/testpath_vmlc.py @@ -338,7 +338,7 @@ class TestPathVMLC(cloudstackTestCase): # 13. Find suitable host for VM to migrate and migrate the VM # 14. Verify VM accessibility on new host """ - if self.hypervisor.lower() in ['hyperv', 'lxc'] and value == VPC_NETWORK: + if self.hypervisor.lower() in ['hyperv', 'lxc'] and value == VPC_NETWORK: self.skipTest("can't be run for {} hypervisor".format(self.hypervisor)) # List created service offering in setUpClass by name diff --git a/test/integration/testpaths/testpath_volumelifecycle.py b/test/integration/testpaths/testpath_volumelifecycle.py index 42dd7c05e93..3b8350c164f 100644 --- a/test/integration/testpaths/testpath_volumelifecycle.py +++ b/test/integration/testpaths/testpath_volumelifecycle.py @@ -732,7 +732,7 @@ class TestPathVolume(cloudstackTestCase): self.assertGreater( len(list_pool), 0, - "Check the list list storagepoolresponse for vm id: %s" % + "Check the list storagepoolresponse for vm id: %s" % list_volume[0].storageid) list_pools = StoragePool.list(self.apiclient, scope=list_pool[0].scope diff --git a/test/metadata/adapter.xml b/test/metadata/adapter.xml index 84eeaa0adee..3de39d58d72 100644 --- a/test/metadata/adapter.xml +++ b/test/metadata/adapter.xml @@ -18,9 +18,9 @@ under the License. --> - + - + 192.168.131.168 hostip @@ -53,7 +53,7 @@ under the License. 204 globalnetworkid - + 192.168.131.168 @@ -152,19 +152,19 @@ under the License. flatnetworkdiskofferingid - + ../metadata/func/sanity.xml SANITY TEST - + com.cloud.test.regression.SanityTest ../metadata/func/regression.xml REGRESSION TEST - + ../metadata/func/templatedwnldstress.xml TEMPLATE DOWNLOAD STRESS TEST @@ -173,8 +173,8 @@ under the License. - - + + @@ -272,7 +272,7 @@ under the License. - + - + diff --git a/test/metadata/delegatedAdmin/delegated_admin_cleanup.xml b/test/metadata/delegatedAdmin/delegated_admin_cleanup.xml index 734fe667b4b..ac0f390ba90 100644 --- a/test/metadata/delegatedAdmin/delegated_admin_cleanup.xml +++ b/test/metadata/delegatedAdmin/delegated_admin_cleanup.xml @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. --> - + registerUserKeys @@ -37,7 +37,7 @@ under the License. secretkey - + listDomains @@ -55,8 +55,8 @@ under the License. - - + + listDomains true @@ -73,7 +73,7 @@ under the License. - + deleteUser @@ -83,7 +83,7 @@ under the License. - + deleteUser @@ -93,7 +93,7 @@ under the License. - + deleteDomain @@ -123,4 +123,4 @@ under the License. - + diff --git a/test/metadata/delegatedAdmin/delegated_admin_createusers.xml b/test/metadata/delegatedAdmin/delegated_admin_createusers.xml index 8ea7dd81696..27ce77f6cf7 100644 --- a/test/metadata/delegatedAdmin/delegated_admin_createusers.xml +++ b/test/metadata/delegatedAdmin/delegated_admin_createusers.xml @@ -36,7 +36,7 @@ under the License. - + createDomain @@ -51,8 +51,8 @@ under the License. level1domain2id - - + + createDomain @@ -72,7 +72,7 @@ under the License. - + createDomain @@ -173,8 +173,8 @@ under the License. - - + + createUser @@ -218,8 +218,8 @@ under the License. - - + + createUser @@ -262,8 +262,8 @@ under the License. domain12adminaccount - - + + createUser @@ -307,6 +307,6 @@ under the License. - + diff --git a/test/metadata/delegatedAdmin/delegated_admin_verify_part1.xml b/test/metadata/delegatedAdmin/delegated_admin_verify_part1.xml index 60815928df6..1ce18187d52 100644 --- a/test/metadata/delegatedAdmin/delegated_admin_verify_part1.xml +++ b/test/metadata/delegatedAdmin/delegated_admin_verify_part1.xml @@ -36,7 +36,7 @@ under the License. secretkey - + @@ -58,7 +58,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -67,8 +67,8 @@ under the License. - - + + createVolume @@ -84,7 +84,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -92,9 +92,9 @@ under the License. volumeid - - - + + + createTemplate @@ -123,8 +123,8 @@ under the License. - - + + registerTemplate Register template @@ -159,9 +159,9 @@ under the License. registeredtemplateid - - - + + + registerIso @@ -193,8 +193,8 @@ under the License. isoid - - + + createSnapshot @@ -211,8 +211,8 @@ under the License. snapshotid - - + + createSnapshotPolicy true @@ -244,8 +244,8 @@ under the License. snapshotpolicyid - - + + @@ -258,14 +258,14 @@ under the License. globalzoneid - + ipaddress ipaddress - + @@ -287,8 +287,8 @@ under the License. pfgroupid - - + + createPortForwardingService Create port forwarding service @@ -308,8 +308,8 @@ under the License. pfgroupid1 - - + + createPortForwardingServiceRule Create port forwarding service rule @@ -334,7 +334,7 @@ under the License. pfruleid - + @@ -367,9 +367,9 @@ under the License. lbid - - - + + + createLoadBalancerRule Create load balancer rule @@ -399,10 +399,10 @@ under the License. lbid1 - - + + - assignToLoadBalancerRule + assignToLoadBalancerRule Assign to load balancer true @@ -415,6 +415,6 @@ under the License. vmid - - - + + + diff --git a/test/metadata/delegatedAdmin/delegated_admin_verify_part2.xml b/test/metadata/delegatedAdmin/delegated_admin_verify_part2.xml index e36f27887d3..9f875054439 100644 --- a/test/metadata/delegatedAdmin/delegated_admin_verify_part2.xml +++ b/test/metadata/delegatedAdmin/delegated_admin_verify_part2.xml @@ -37,9 +37,9 @@ under the License. - - - + + + rebootVirtualMachine Reboot virtual machine @@ -51,7 +51,7 @@ under the License. - + startVirtualMachine Start virtual machine @@ -63,7 +63,7 @@ under the License. - + stopVirtualMachine Stop virtual machine @@ -75,7 +75,7 @@ under the License. - + resetPasswordForVirtualMachine Reset password for virtual machine @@ -87,7 +87,7 @@ under the License. - + changeServiceForVirtualMachine Change service offering for virtual machine @@ -103,7 +103,7 @@ under the License. - + updateVirtualMachine Update virtual machine @@ -119,7 +119,7 @@ under the License. - + listVirtualMachines List virtual machines @@ -131,7 +131,7 @@ under the License. - + deployVirtualMachine true @@ -151,7 +151,7 @@ under the License. diskofferingid globaldiskofferingid - + domainid domainid1 @@ -162,8 +162,8 @@ under the License. - - + + listVolumes @@ -175,8 +175,8 @@ under the License. volumeid - - + + attachVolume Attach volume @@ -192,7 +192,7 @@ under the License. - + detachVolume Detach volume @@ -204,7 +204,7 @@ under the License. - + createVolume Creating volume @@ -220,7 +220,7 @@ under the License. diskofferingid globaldiskofferingid - + domainid domainid1 @@ -230,8 +230,8 @@ under the License. account1 - - + + @@ -245,7 +245,7 @@ under the License. - + createSnapshot Creating snapshot @@ -265,7 +265,7 @@ under the License. - + listSnapshotPolicies Listing snapshot policies @@ -277,7 +277,7 @@ under the License. - + createSnapshotPolicy true @@ -312,7 +312,7 @@ under the License. - + updateTemplate @@ -329,7 +329,7 @@ under the License. - + updateTemplatePermissions Update template permissions @@ -345,7 +345,7 @@ under the License. - + copyTemplate Copy template @@ -365,7 +365,7 @@ under the License. - + listTemplates List templates @@ -377,7 +377,7 @@ under the License. - + listTemplatePermissions List template permissions @@ -389,7 +389,7 @@ under the License. - + createTemplate Create template @@ -419,9 +419,9 @@ under the License. account1 - - - + + + updateTemplate @@ -438,7 +438,7 @@ under the License. - + updateTemplatePermissions Update template permissions @@ -454,7 +454,7 @@ under the License. - + copyTemplate Copy template @@ -474,7 +474,7 @@ under the License. - + listTemplates List templates @@ -486,7 +486,7 @@ under the License. - + listTemplatePermissions List template permissions @@ -498,7 +498,7 @@ under the License. - + @@ -517,7 +517,7 @@ under the License. - + listIsos List isos @@ -529,7 +529,7 @@ under the License. - + copyIso Copy iso @@ -548,8 +548,8 @@ under the License. globalzoneid1 - - + + attachIso true @@ -564,8 +564,8 @@ under the License. isoid - - + + detachIso true @@ -576,12 +576,12 @@ under the License. vmid - - + + listPublicIpAddresses - true + true List public ip addresses @@ -590,7 +590,7 @@ under the License. - + associateIpAddress true @@ -610,7 +610,7 @@ under the License. - + @@ -623,8 +623,8 @@ under the License. pfgroupid - - + + listPortForwardingServiceRules List port forwarding service rule @@ -635,8 +635,8 @@ under the License. pfgroupid - - + + listPortForwardingServicesByVm List port forwarding services by vm @@ -647,7 +647,7 @@ under the License. vmid - + removePortForwardingService @@ -667,8 +667,8 @@ under the License. ipaddress - - + + assignPortForwardingService true @@ -687,8 +687,8 @@ under the License. ipaddress - - + + createPortForwardingService Create port forwarding service @@ -710,8 +710,8 @@ under the License. account1 - - + + createPortForwardingServiceRule Create port forwarding service rule @@ -730,8 +730,8 @@ under the License. pfgroupid - - + + deletePortForwardingServiceRule Delete port forwarding service rule @@ -743,8 +743,8 @@ under the License. - - + + deletePortForwardingService true @@ -756,8 +756,8 @@ under the License. - - + + listLoadBalancerRules @@ -769,8 +769,8 @@ under the License. lbid - - + + listLoadBalancerRuleInstances List load balancer rule instances @@ -781,8 +781,8 @@ under the License. lbid - - + + removeFromLoadBalancerRule Remove from load balancer @@ -797,8 +797,8 @@ under the License. vmid - - + + assignToLoadBalancerRule Assign to load balancer @@ -813,8 +813,8 @@ under the License. vmid - - + + deleteLoadBalancerRule Delete load balancer rule @@ -825,8 +825,8 @@ under the License. lbid - - + + createLoadBalancerRule Create load balancer rule @@ -850,13 +850,13 @@ under the License. roundrobin - - - + + + disassociateIpAddress - true + true Disassociate ip address @@ -876,7 +876,7 @@ under the License. - + deleteSnapshotPolicies Deleting snapshot policy @@ -888,7 +888,7 @@ under the License. - + deleteTemplate Delete template @@ -900,7 +900,7 @@ under the License. - + deleteTemplate Delete template @@ -912,7 +912,7 @@ under the License. - + deleteVolume Deleting volume @@ -924,7 +924,7 @@ under the License. - + deleteIso Delete iso @@ -935,8 +935,8 @@ under the License. isoid - - + + destroyVirtualMachine Destroy virtual machine @@ -947,6 +947,6 @@ under the License. vmid - + - + diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel1_domainlevel2.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel1_domainlevel2.xml index 42eb498ec35..6b66d9aad33 100644 --- a/test/metadata/delegatedAdmin/pickuser_domainlevel1_domainlevel2.xml +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel1_domainlevel2.xml @@ -47,8 +47,8 @@ under the License. account1 - - + + listDomains @@ -67,10 +67,10 @@ under the License. domainlevel1 - - + - + + listUsers @@ -98,7 +98,7 @@ under the License. - + listDomains @@ -118,5 +118,5 @@ under the License. - + diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_domainlevel1admin.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_domainlevel1admin.xml index b0cd1614fd0..f283affe292 100644 --- a/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_domainlevel1admin.xml +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_domainlevel1admin.xml @@ -47,8 +47,8 @@ under the License. account1 - - + + listDomains @@ -67,10 +67,10 @@ under the License. domainlevel1 - - + - + + listUsers @@ -98,7 +98,7 @@ under the License. - + listDomains @@ -118,5 +118,5 @@ under the License. - + diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_rootadmin.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_rootadmin.xml index 87cb933bd00..29c4a5ac01e 100644 --- a/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_rootadmin.xml +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel1admin_rootadmin.xml @@ -47,8 +47,8 @@ under the License. account1 - - + + listDomains @@ -67,10 +67,10 @@ under the License. domainlevel1 - - + - + + listUsers @@ -98,7 +98,7 @@ under the License. - + listDomains @@ -118,5 +118,5 @@ under the License. - + diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel2_child_domainlevel1.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel2_child_domainlevel1.xml index 5e77ca95932..662fe0f25c1 100644 --- a/test/metadata/delegatedAdmin/pickuser_domainlevel2_child_domainlevel1.xml +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel2_child_domainlevel1.xml @@ -47,8 +47,8 @@ under the License. account1 - - + + listDomains @@ -67,10 +67,10 @@ under the License. domainlevel1 - - + - + + listUsers @@ -98,7 +98,7 @@ under the License. - + listDomains @@ -118,5 +118,5 @@ under the License. - + diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel2_nonchild_domainlevel1.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel2_nonchild_domainlevel1.xml index b2192a2f03d..18a7b421343 100644 --- a/test/metadata/delegatedAdmin/pickuser_domainlevel2_nonchild_domainlevel1.xml +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel2_nonchild_domainlevel1.xml @@ -47,8 +47,8 @@ under the License. account1 - - + + listDomains @@ -67,10 +67,10 @@ under the License. domainlevel1 - - + - + + listUsers @@ -98,7 +98,7 @@ under the License. - + listDomains @@ -118,5 +118,5 @@ under the License. - + diff --git a/test/metadata/delegatedAdmin/pickuser_domainlevel2_rootadmin1.xml b/test/metadata/delegatedAdmin/pickuser_domainlevel2_rootadmin1.xml index ecf06af098f..c1b91351cbb 100644 --- a/test/metadata/delegatedAdmin/pickuser_domainlevel2_rootadmin1.xml +++ b/test/metadata/delegatedAdmin/pickuser_domainlevel2_rootadmin1.xml @@ -47,8 +47,8 @@ under the License. account1 - - + + listDomains @@ -67,10 +67,10 @@ under the License. domainlevel1 - - + - + + listUsers @@ -98,7 +98,7 @@ under the License. - + listDomains @@ -118,5 +118,5 @@ under the License. - + diff --git a/test/metadata/delegatedAdmin/pickuser_rootadmin1_rootadmin2.xml b/test/metadata/delegatedAdmin/pickuser_rootadmin1_rootadmin2.xml index d7c7a03d676..aa85730890a 100644 --- a/test/metadata/delegatedAdmin/pickuser_rootadmin1_rootadmin2.xml +++ b/test/metadata/delegatedAdmin/pickuser_rootadmin1_rootadmin2.xml @@ -47,8 +47,8 @@ under the License. account1 - - + + listDomains @@ -67,10 +67,10 @@ under the License. domainlevel1 - - + - + + listUsers @@ -98,7 +98,7 @@ under the License. - + listDomains @@ -118,5 +118,5 @@ under the License. - + diff --git a/test/metadata/delegatedAdmin/pickuser_rootadmin_vs_domainlevel1admin.xml b/test/metadata/delegatedAdmin/pickuser_rootadmin_vs_domainlevel1admin.xml index 361b934eee5..79da605f363 100644 --- a/test/metadata/delegatedAdmin/pickuser_rootadmin_vs_domainlevel1admin.xml +++ b/test/metadata/delegatedAdmin/pickuser_rootadmin_vs_domainlevel1admin.xml @@ -47,8 +47,8 @@ under the License. account1 - - + + listDomains @@ -67,10 +67,10 @@ under the License. domainlevel1 - - + - + + listUsers @@ -98,7 +98,7 @@ under the License. - + listDomains @@ -118,5 +118,5 @@ under the License. - + diff --git a/test/metadata/func/commands b/test/metadata/func/commands index 86754ebdd0b..53bebedc4c3 100644 --- a/test/metadata/func/commands +++ b/test/metadata/func/commands @@ -1,191 +1,191 @@ -# 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. - -updateAccount=no -listAccounts=no - -createUser=no -updateUser=no -deleteUser=no -listUsers=no -disableUser=yes -enableUser=no -disableAccount=yes -enableAccount=no -lockUser=no -lockAccount=no -deleteAccount=yes - -createDomain=no -updateDomain=no -deleteDomain=yes -listDomains=no -listDomainChildren=no - -updateResourceLimit=no -deleteResourceLimit=no -listResourceLimits=no - -deployVirtualMachine=yes -destroyVirtualMachine=yes -rebootVirtualMachine=yes -startVirtualMachine=yes -stopVirtualMachine=yes -resetPasswordForVirtualMachine=yes -changeServiceForVirtualMachine=no -updateVirtualMachine=no -recoverVirtualMachine=no -listVirtualMachines=no - -createSnapshot=yes -deleteSnapshot=yes -listSnapshots=no -listRecurringSnapshotSchedule=no -createVolumeFromSnapshot=yes -createSnapshotPolicy=no -deleteSnapshotPolicies=no -listSnapshotPolicies=no - -createTemplate=yes -registerTemplate=no -updateTemplate=no -deleteTemplate=no -listTemplates=no -updateTemplatePermissions=no -listTemplatePermissions=no -copyTemplate=yes - -attachIso=yes -detachIso=yes -listIsos=no -registerIso=no -updateIso=no -deleteIso=yes -copyIso=yes - -listOSTypes=no - -createServiceOffering=no -deleteServiceOffering=no -updateServiceOffering=no -listServiceOfferings=no - -createDiskOffering=no -updateDiskOffering=no -deleteDiskOffering=no -listDiskOfferings=no - -createVlan=no -deleteVlan=no - -createVlanIpRange=no -deleteVlanIpRange=no -listVlanIpRanges=no - -createVlanRange=no -deleteVlanRange=no -listVlanRanges=no - -associateIpAddress=yes -disassociateIpAddress=yes -listPublicIpAddresses=no -listPrivateIpAddresses=no -updatePublicIpRange=no -updatePrivateIpRange=no - -createPortForwardingServiceRule=yes -deletePortForwardingServiceRule=yes -listPortForwardingServiceRules=no -createPortForwardingService=no -deletePortForwardingService=yes -assignPortForwardingService=yes -removePortForwardingService=yes -listPortForwardingServices=no -listPortForwardingServicesByVm=no -createPortForwardingRule=no -deletePortForwardingRule=no -listPortForwardingRules=no -updatePortForwardingRule=no - -createIpForwardingRule=yes -deleteIpForwardingRule=yes -listIpForwardingRules=no - -createLoadBalancerRule=no -deleteLoadBalancerRule=yes -removeFromLoadBalancerRule=yes -assignToLoadBalancerRule=yes -listLoadBalancerRules=no -listLoadBalancerRuleInstances=no - -startRouter=yes -rebootRouter=yes -stopRouter=yes -listRouters=no - -startSystemVm=yes -rebootSystemVm=yes -stopSystemVm=yes -listSystemVms=no - -updateConfiguration=no -listConfigurations=no - -createPod=no -updatePod=no -deletePod=no -listPods=no - -createZone=no -updateZone=no -deleteZone=no -listZones=no - -listEvents=no - -listAlerts=no - -listCapacity=no - -addHost=no -reconnectHost=yes -deleteHost=no -prepareHostForMaintenance=yes -cancelHostMaintenance=yes -listHosts=no -addSecondaryStorage=no - -attachVolume=yes -detachVolume=yes -createVolume=yes -deleteVolume=no -listVolumes=no - -registerUserKeys=no - -queryAsyncJobResult=no - -listStoragePools=no -listStoragePoolsAndHosts=no -createStoragePool=no - - -createNetworkGroup=no -revokeNetworkGroupIngress=yes -authorizeNetworkGroupIngress=yes - -createNetwork=no +# 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. + +updateAccount=no +listAccounts=no + +createUser=no +updateUser=no +deleteUser=no +listUsers=no +disableUser=yes +enableUser=no +disableAccount=yes +enableAccount=no +lockUser=no +lockAccount=no +deleteAccount=yes + +createDomain=no +updateDomain=no +deleteDomain=yes +listDomains=no +listDomainChildren=no + +updateResourceLimit=no +deleteResourceLimit=no +listResourceLimits=no + +deployVirtualMachine=yes +destroyVirtualMachine=yes +rebootVirtualMachine=yes +startVirtualMachine=yes +stopVirtualMachine=yes +resetPasswordForVirtualMachine=yes +changeServiceForVirtualMachine=no +updateVirtualMachine=no +recoverVirtualMachine=no +listVirtualMachines=no + +createSnapshot=yes +deleteSnapshot=yes +listSnapshots=no +listRecurringSnapshotSchedule=no +createVolumeFromSnapshot=yes +createSnapshotPolicy=no +deleteSnapshotPolicies=no +listSnapshotPolicies=no + +createTemplate=yes +registerTemplate=no +updateTemplate=no +deleteTemplate=no +listTemplates=no +updateTemplatePermissions=no +listTemplatePermissions=no +copyTemplate=yes + +attachIso=yes +detachIso=yes +listIsos=no +registerIso=no +updateIso=no +deleteIso=yes +copyIso=yes + +listOSTypes=no + +createServiceOffering=no +deleteServiceOffering=no +updateServiceOffering=no +listServiceOfferings=no + +createDiskOffering=no +updateDiskOffering=no +deleteDiskOffering=no +listDiskOfferings=no + +createVlan=no +deleteVlan=no + +createVlanIpRange=no +deleteVlanIpRange=no +listVlanIpRanges=no + +createVlanRange=no +deleteVlanRange=no +listVlanRanges=no + +associateIpAddress=yes +disassociateIpAddress=yes +listPublicIpAddresses=no +listPrivateIpAddresses=no +updatePublicIpRange=no +updatePrivateIpRange=no + +createPortForwardingServiceRule=yes +deletePortForwardingServiceRule=yes +listPortForwardingServiceRules=no +createPortForwardingService=no +deletePortForwardingService=yes +assignPortForwardingService=yes +removePortForwardingService=yes +listPortForwardingServices=no +listPortForwardingServicesByVm=no +createPortForwardingRule=no +deletePortForwardingRule=no +listPortForwardingRules=no +updatePortForwardingRule=no + +createIpForwardingRule=yes +deleteIpForwardingRule=yes +listIpForwardingRules=no + +createLoadBalancerRule=no +deleteLoadBalancerRule=yes +removeFromLoadBalancerRule=yes +assignToLoadBalancerRule=yes +listLoadBalancerRules=no +listLoadBalancerRuleInstances=no + +startRouter=yes +rebootRouter=yes +stopRouter=yes +listRouters=no + +startSystemVm=yes +rebootSystemVm=yes +stopSystemVm=yes +listSystemVms=no + +updateConfiguration=no +listConfigurations=no + +createPod=no +updatePod=no +deletePod=no +listPods=no + +createZone=no +updateZone=no +deleteZone=no +listZones=no + +listEvents=no + +listAlerts=no + +listCapacity=no + +addHost=no +reconnectHost=yes +deleteHost=no +prepareHostForMaintenance=yes +cancelHostMaintenance=yes +listHosts=no +addSecondaryStorage=no + +attachVolume=yes +detachVolume=yes +createVolume=yes +deleteVolume=no +listVolumes=no + +registerUserKeys=no + +queryAsyncJobResult=no + +listStoragePools=no +listStoragePoolsAndHosts=no +createStoragePool=no + + +createNetworkGroup=no +revokeNetworkGroupIngress=yes +authorizeNetworkGroupIngress=yes + +createNetwork=no diff --git a/test/metadata/func/directnw_regression.xml b/test/metadata/func/directnw_regression.xml index 944ee3c314f..3cce8b1f869 100644 --- a/test/metadata/func/directnw_regression.xml +++ b/test/metadata/func/directnw_regression.xml @@ -18,10 +18,10 @@ under the License. --> - - + + - + createAccount [Create the Account and a User for the account] @@ -59,7 +59,7 @@ under the License. password - + id @@ -164,11 +164,11 @@ under the License. - + - + listUsers 5 [List the Created User in (3)] @@ -177,7 +177,7 @@ under the License. accountname - + id @@ -222,14 +222,14 @@ under the License. domain ROOT - + - - - + + + - + createUser 3 [Create User Command] @@ -261,9 +261,9 @@ under the License. email nimbus-user@gmail.com - + - + id @@ -312,7 +312,7 @@ under the License. - + @@ -324,7 +324,7 @@ under the License. accountname - + id @@ -429,7 +429,7 @@ under the License. - + @@ -473,7 +473,7 @@ under the License. usersecretkey - + id @@ -534,7 +534,7 @@ under the License. - + @@ -606,11 +606,11 @@ under the License. - + - - + @@ -753,7 +753,7 @@ under the License. - + @@ -825,7 +825,7 @@ under the License. - + @@ -945,7 +945,7 @@ under the License. state locked - + @@ -963,7 +963,7 @@ under the License. domainid 1 - + @@ -1065,7 +1065,7 @@ under the License. state enabled - + @@ -1189,7 +1189,7 @@ under the License. state disabled - + @@ -1207,7 +1207,7 @@ under the License. domainid 1 - + @@ -1309,7 +1309,7 @@ under the License. state enabled - + @@ -1325,7 +1325,7 @@ under the License. domainname - + name @@ -1366,7 +1366,7 @@ under the License. domainname - + id @@ -1414,7 +1414,7 @@ under the License. newdomainname - + id @@ -1456,7 +1456,7 @@ under the License. 1 - + domain 0 @@ -1486,8 +1486,8 @@ under the License. - - + + @@ -1503,7 +1503,7 @@ under the License. true - + success @@ -1528,7 +1528,7 @@ under the License. 1 - + template 0 @@ -1586,7 +1586,7 @@ under the License. size - debian50templatesize + debian50templatesize account @@ -1619,7 +1619,7 @@ under the License. domainid 1 - + @@ -1829,7 +1829,7 @@ under the License. offerha false - + @@ -1867,7 +1867,7 @@ under the License. vlan - guestcidraddress + guestcidraddress networktype diff --git a/test/metadata/func/error_events.properties b/test/metadata/func/error_events.properties index a7c7633baa2..e6909b42ec5 100644 --- a/test/metadata/func/error_events.properties +++ b/test/metadata/func/error_events.properties @@ -1,32 +1,32 @@ -# 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. - -# All the ERROR level events that need to be checked in EventsApiTest - -VM.CREATE=1 -VM.START=1 -VM.STOP=1 -VM.REBOOT=1 -VM.UPGRADE=1 -VM.RESETPASSWORD=1 -ROUTER.CREATE=1 -ROUTER.START=1 -ROUTER.STOP=1 -ROUTER.REBOOT=1 -NET.IPASSIGN=1 -NET.RULEADD=2 -NET.RULEDELETE=2 +# 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. + +# All the ERROR level events that need to be checked in EventsApiTest + +VM.CREATE=1 +VM.START=1 +VM.STOP=1 +VM.REBOOT=1 +VM.UPGRADE=1 +VM.RESETPASSWORD=1 +ROUTER.CREATE=1 +ROUTER.START=1 +ROUTER.STOP=1 +ROUTER.REBOOT=1 +NET.IPASSIGN=1 +NET.RULEADD=2 +NET.RULEDELETE=2 diff --git a/test/metadata/func/expunge.xml b/test/metadata/func/expunge.xml index 72ccb2afb6e..d008dc3319f 100644 --- a/test/metadata/func/expunge.xml +++ b/test/metadata/func/expunge.xml @@ -19,7 +19,7 @@ under the License. - + + --> createAccount [Create the Account and a User for the account] @@ -95,7 +95,7 @@ under the License. accountname - + id @@ -104,7 +104,7 @@ under the License. - - + registerUserKeys Registering the user @@ -205,7 +205,7 @@ under the License. - + deployVirtualMachine true @@ -222,7 +222,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -259,7 +259,7 @@ under the License. - + listVirtualMachines List virtual machines @@ -276,7 +276,7 @@ under the License. - + listHosts List host where vm is running @@ -293,7 +293,7 @@ under the License. - + listRouters List Routers @@ -326,7 +326,7 @@ under the License. - + listHosts List host where domR is running @@ -342,8 +342,8 @@ under the License. routerhost_ipaddress - - + + listVolumes List data disk vm volume @@ -368,7 +368,7 @@ under the License. - + select path from volumes true @@ -386,7 +386,7 @@ under the License. - + listVolumes List root disk vm volume @@ -411,7 +411,7 @@ under the License. - + select path from volumes true @@ -429,7 +429,7 @@ under the License. - + select path from volumes true @@ -463,7 +463,7 @@ under the License. - + listvdi.sh @@ -478,8 +478,8 @@ under the License. vm_rootvolumepath - - + + listvdi.sh @@ -494,7 +494,7 @@ under the License. router_rootvolumepath - + @@ -507,7 +507,7 @@ under the License. - + listConfigurations Getting expunge interval value @@ -524,7 +524,7 @@ under the License. - + sleep.sh @@ -535,9 +535,9 @@ under the License. expunge.interval - - - + + + sleep.sh @@ -548,9 +548,9 @@ under the License. expunge.interval - - - + + + listvdi.sh true @@ -567,7 +567,7 @@ under the License. - + listvdi.sh true @@ -584,8 +584,8 @@ under the License. - - + + createVolume @@ -602,7 +602,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -611,7 +611,7 @@ under the License. - + attachVolume true @@ -627,7 +627,7 @@ under the License. - + detachVolume true @@ -639,7 +639,7 @@ under the License. - + createSnapshot true @@ -661,7 +661,7 @@ under the License. - + select path from volumes true @@ -679,7 +679,7 @@ under the License. - + listvdi.sh @@ -694,8 +694,8 @@ under the License. detached_volumepath - - + + deleteVolume Delete detached volume @@ -707,7 +707,7 @@ under the License. - + sleep.sh @@ -718,9 +718,9 @@ under the License. expunge.interval - - - + + + sleep.sh @@ -731,8 +731,8 @@ under the License. expunge.interval - - + + listvdi.sh true @@ -749,7 +749,7 @@ under the License. - + listvdi.sh @@ -765,9 +765,9 @@ under the License. snapshotpath - - - + + + stopRouter @@ -778,8 +778,8 @@ under the License. router_id - - + + deleteUser Deleting the user @@ -789,8 +789,8 @@ under the License. userid - - + + listvdi.sh true @@ -807,7 +807,7 @@ under the License. - + listvdi.sh true @@ -823,10 +823,10 @@ under the License. snapshotpath - - - - + + + + @@ -843,7 +843,7 @@ under the License. - + ms.sh @@ -876,8 +876,8 @@ under the License. - - + + deployVirtualMachine true @@ -894,7 +894,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -927,7 +927,7 @@ under the License. - + listVolumes @@ -947,7 +947,7 @@ under the License. - + stopVirtualMachine Stop virtual machine @@ -958,7 +958,7 @@ under the License. - + createTemplate Create template from root volume @@ -986,8 +986,8 @@ under the License. - - + + deployVirtualMachine Deploying virtual machine from the private template @@ -1003,7 +1003,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid privatetemplateid @@ -1040,7 +1040,7 @@ under the License. - + listHosts List host where vm is running @@ -1057,7 +1057,7 @@ under the License. - + select install_path from template_spool_ref true @@ -1075,7 +1075,7 @@ under the License. - + listvdi.sh @@ -1091,7 +1091,7 @@ under the License. - + destroyVirtualMachine Destroy virtual machine created from the private template @@ -1102,7 +1102,7 @@ under the License. - + sleep.sh @@ -1113,8 +1113,8 @@ under the License. 240 - - + + listvdi.sh true @@ -1144,7 +1144,7 @@ under the License. - + deleteTemplate Delete private template @@ -1155,7 +1155,7 @@ under the License. - + updateConfiguration Updating storage.cleanup.interval @@ -1170,7 +1170,7 @@ under the License. - + ms.sh @@ -1202,6 +1202,6 @@ under the License. - - + + diff --git a/test/metadata/func/external_firewall.xml b/test/metadata/func/external_firewall.xml index afb92446bed..d0f7efb7062 100644 --- a/test/metadata/func/external_firewall.xml +++ b/test/metadata/func/external_firewall.xml @@ -61,7 +61,7 @@ under the License. - + createNetwork @@ -99,7 +99,7 @@ under the License. - + deployVirtualMachine deploying virtual machine @@ -144,10 +144,10 @@ under the License. - - - - + + + + associateIpAddress Associating first public ip address @@ -169,14 +169,14 @@ under the License. id nonsourcenatpublicip1id - + ipaddress nonsourcenatpublicip1 - + associateIpAddress Associating second public ip address @@ -198,15 +198,15 @@ under the License. id nonsourcenatpublicip2id - + ipaddress nonsourcenatpublicip2 - - + + enableStaticNat Enable Static NAT - 1 @@ -214,11 +214,11 @@ under the License. ipaddressid nonsourcenatpublicip1id - + virtualmachineid vmid - + @@ -250,7 +250,7 @@ under the License. - + sleep.sh @@ -261,8 +261,8 @@ under the License. 120 - - + + ssh.sh @@ -282,9 +282,9 @@ under the License. - - - + + + createLoadBalancerRule Creating load balancer rule @@ -324,8 +324,8 @@ under the License. lbid - - + + assignToLoadBalancerRule Assigning vm to the load balancer @@ -339,8 +339,8 @@ under the License. vmid - - + + deleteLoadBalancerRule Deleting the load balancer @@ -350,8 +350,8 @@ under the License. lbid - - + + disassociateIpAddress Dissociating first public ip address @@ -362,7 +362,7 @@ under the License. - + disassociateIpAddress Dissociating second public ip address @@ -373,7 +373,7 @@ under the License. - + deleteAccount Delete account @@ -383,7 +383,7 @@ under the License. accountid - - - + + + diff --git a/test/metadata/func/flatnetwork.xml b/test/metadata/func/flatnetwork.xml index 60866537b01..70648b312d3 100644 --- a/test/metadata/func/flatnetwork.xml +++ b/test/metadata/func/flatnetwork.xml @@ -56,7 +56,7 @@ under the License. - + registerUserKeys Registering the user @@ -77,7 +77,7 @@ under the License. - + createNetworkGroup true @@ -89,7 +89,7 @@ under the License. - + authorizeNetworkGroupIngress Authorizing network group ingress @@ -124,7 +124,7 @@ under the License. - + deployVirtualMachine true @@ -158,7 +158,7 @@ under the License. - + deployVirtualMachine true @@ -187,8 +187,8 @@ under the License. vmid1 - - + + createVolume true @@ -213,8 +213,8 @@ under the License. - - + + attachVolume true @@ -230,7 +230,7 @@ under the License. - + sleep.sh @@ -241,8 +241,8 @@ under the License. 120 - - + + ssh.sh @@ -258,7 +258,7 @@ under the License. - + sleep.sh @@ -269,8 +269,8 @@ under the License. 60 - - + + stopVirtualMachine true @@ -282,7 +282,7 @@ under the License. - + startVirtualMachine true @@ -294,7 +294,7 @@ under the License. - + rebootVirtualMachine true @@ -318,7 +318,7 @@ under the License. - + attachVolume true @@ -334,8 +334,8 @@ under the License. - - + + stopVirtualMachine true @@ -347,7 +347,7 @@ under the License. - + startVirtualMachine true @@ -359,7 +359,7 @@ under the License. - + rebootVirtualMachine true @@ -383,8 +383,8 @@ under the License. - - + + deleteVolume true @@ -396,7 +396,7 @@ under the License. - + createVolume true @@ -421,8 +421,8 @@ under the License. - - + + attachVolume true @@ -438,8 +438,8 @@ under the License. - - + + revokeNetworkGroupIngress Revoking network group igress @@ -474,8 +474,8 @@ under the License. - - + + ssh.sh @@ -492,7 +492,7 @@ under the License. - + destroyVirtualMachine true @@ -504,7 +504,7 @@ under the License. - + sleep.sh @@ -515,10 +515,10 @@ under the License. 120 - - - - + + + + deleteUser Deleting the user @@ -528,6 +528,6 @@ under the License. userid - + diff --git a/test/metadata/func/ha.xml b/test/metadata/func/ha.xml index fa2ccb4b631..32ad2c22a51 100644 --- a/test/metadata/func/ha.xml +++ b/test/metadata/func/ha.xml @@ -33,7 +33,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -74,7 +74,7 @@ under the License. - + deployVirtualMachine Deploy ha enabled vm @@ -90,7 +90,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -131,8 +131,8 @@ under the License. - - + + updateVirtualMachine Update virtual machine @@ -147,7 +147,7 @@ under the License. - + listHosts @@ -165,7 +165,7 @@ under the License. - + listHosts List host with ha enabled machine @@ -201,8 +201,8 @@ under the License. instance_name - - + + select instance_name from vm_instance true @@ -219,7 +219,7 @@ under the License. instance_name_ha - + @@ -236,8 +236,8 @@ under the License. instance_name - - + + killvm.sh @@ -252,7 +252,7 @@ under the License. instance_name_ha - + @@ -265,7 +265,7 @@ under the License. 300 - + @@ -283,8 +283,8 @@ under the License. Stopped - - + + listVirtualMachines List virtual machine with ha enabled @@ -305,7 +305,7 @@ under the License. - + listHosts List host with ha enabled machine @@ -322,7 +322,7 @@ under the License. - + listvm.sh @@ -337,9 +337,9 @@ under the License. instance_name_ha - - - + + + @@ -352,7 +352,7 @@ under the License. - + destroyVirtualMachine Destroy ha enabled vm as a part of cleanup @@ -363,5 +363,5 @@ under the License. - - + + diff --git a/test/metadata/func/iso.xml b/test/metadata/func/iso.xml index 8e4c1c1c904..aa6d361e96c 100644 --- a/test/metadata/func/iso.xml +++ b/test/metadata/func/iso.xml @@ -37,8 +37,8 @@ under the License. secretkey - - + + deployVirtualMachine true @@ -54,7 +54,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -87,7 +87,7 @@ under the License. - + attachIso true @@ -103,7 +103,7 @@ under the License. - + listVirtualMachines 869-2 @@ -120,10 +120,10 @@ under the License. - - + + - + createAccount [Create the Account and a User for the account] @@ -186,8 +186,8 @@ under the License. - - +--> registerUserKeys @@ -249,8 +249,8 @@ under the License. secretkey - - + + attachIso true @@ -267,8 +267,8 @@ under the License. - - + + registerUserKeys @@ -288,8 +288,8 @@ under the License. secretkey - - + + destroyVirtualMachine @@ -299,7 +299,7 @@ under the License. - + attachIso 871 @@ -315,8 +315,8 @@ under the License. - - + + attachIso @@ -333,7 +333,7 @@ under the License. - + @@ -351,7 +351,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -384,7 +384,7 @@ under the License. - + attachIso true @@ -399,7 +399,7 @@ under the License. - + rebootVirtualMachine true @@ -411,7 +411,7 @@ under the License. - + listVirtualMachines 1073-2 @@ -428,7 +428,7 @@ under the License. - + stopVirtualMachine @@ -441,7 +441,7 @@ under the License. - + listVirtualMachines 1074-2 @@ -458,7 +458,7 @@ under the License. - + startVirtualMachine true @@ -470,7 +470,7 @@ under the License. - + listVirtualMachines 1074-4 @@ -487,8 +487,8 @@ under the License. - - + + listRouters @@ -515,8 +515,8 @@ under the License. routerid - - + + attachIso 1075 @@ -532,7 +532,7 @@ under the License. - + detachIso @@ -545,8 +545,8 @@ under the License. - - + + attachIso @@ -562,7 +562,7 @@ under the License. - + stopVirtualMachine true @@ -573,7 +573,7 @@ under the License. - + detachIso true @@ -585,8 +585,8 @@ under the License. - - + + destroyVirtualMachine @@ -598,7 +598,7 @@ under the License. - + deployVirtualMachine true @@ -615,7 +615,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globalisoid @@ -652,7 +652,7 @@ under the License. - + destroyVirtualMachine @@ -664,7 +664,7 @@ under the License. - + deployVirtualMachine true @@ -681,7 +681,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globalisoid @@ -718,7 +718,7 @@ under the License. - + detachIso true @@ -730,7 +730,7 @@ under the License. - + rebootVirtualMachine true @@ -742,7 +742,7 @@ under the License. - + listVirtualMachines 1079-4 @@ -759,9 +759,9 @@ under the License. - - - + + + destroyVirtualMachine @@ -789,7 +789,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globalisoid @@ -826,7 +826,7 @@ under the License. - + detachIso true @@ -838,7 +838,7 @@ under the License. - + stopVirtualMachine true @@ -850,7 +850,7 @@ under the License. - + startVirtualMachine true @@ -862,7 +862,7 @@ under the License. - + listVirtualMachines 1080-4 @@ -879,8 +879,8 @@ under the License. - - + + deleteUser @@ -892,7 +892,7 @@ under the License. - + destroyVirtualMachine Destroying vm as a part of cleanup @@ -902,6 +902,6 @@ under the License. vmid - - + + diff --git a/test/metadata/func/loadbalancers.xml b/test/metadata/func/loadbalancers.xml index 781d30eab9d..87f2a0f9899 100644 --- a/test/metadata/func/loadbalancers.xml +++ b/test/metadata/func/loadbalancers.xml @@ -34,7 +34,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -58,7 +58,7 @@ under the License. networkids globalnetworkid - + @@ -67,7 +67,7 @@ under the License. - + associateIpAddress [Acquire a non-Source NAT IP Address for the Admin Account] @@ -85,14 +85,14 @@ under the License. 1 - + ipaddress nonsourcenatpublicip - + createLoadBalancerRule [Create Load Balancing Rule -ve test (Private Port 0)] @@ -127,8 +127,8 @@ under the License. 1 - - + + createLoadBalancerRule [Create Load Balancing Rule -ve test (Private Port 65536)] @@ -163,8 +163,8 @@ under the License. 1 - - + + createLoadBalancerRule [Create Load Balancing Rule -ve test (Private Port 65536)] @@ -199,8 +199,8 @@ under the License. 1 - - + + createLoadBalancerRule [Create Load Balancing Rule -ve test (Public Port 65536)] @@ -235,8 +235,8 @@ under the License. 1 - - + + createLoadBalancerRule @@ -270,8 +270,8 @@ under the License. 1 - - + + createLoadBalancerRule 919-1 [Create Load Balancing Rule - 2] @@ -304,8 +304,8 @@ under the License. 1 - - + + createLoadBalancerRule 919-2 [Create Load Balancing Rule - 3] @@ -338,8 +338,8 @@ under the License. 1 - - + + createLoadBalancerRule true @@ -373,7 +373,7 @@ under the License. 1 - + @@ -411,8 +411,8 @@ under the License. 1 - - + + createLoadBalancerRule 920-2 [Create a Load Balancer Rule with the Same Name] @@ -446,7 +446,7 @@ under the License. 1 - + @@ -483,7 +483,7 @@ under the License. 1 - + createAccount @@ -543,16 +543,16 @@ under the License. account accountvar - + id userid - + - +--> registerUserKeys [Register User Keys] @@ -615,8 +615,8 @@ under the License. secretkey - - + + createNetwork [Creating default network] @@ -653,7 +653,7 @@ under the License. - + deployVirtualMachine [Deploy Virtual Machine in that Account] @@ -670,7 +670,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -686,7 +686,7 @@ under the License. account accountvar - + domainid 1 @@ -694,7 +694,7 @@ under the License. networkids networkid - + @@ -703,7 +703,7 @@ under the License. - + associateIpAddress [Acquire a Non-Source NAT IP Address] @@ -722,14 +722,14 @@ under the License. 1 - + ipaddress nonsourcenatpublicip1 - + createLoadBalancerRule [Creating a LB Rule with the same name of a rule in another account] @@ -765,7 +765,7 @@ under the License. 1 - + @@ -803,8 +803,8 @@ under the License. - - + + createLoadBalancerRule @@ -840,8 +840,8 @@ under the License. admin - - + + associateIpAddress @@ -860,14 +860,14 @@ under the License. 1 - + ipaddress nonsourcenatpublicip - + createLoadBalancerRule 924 [Create Load Balancer Rule from non-Source NAT IP Address] @@ -900,8 +900,8 @@ under the License. 1 - - + + deleteLoadBalancerRule @@ -914,7 +914,7 @@ under the License. 10000 - + @@ -926,7 +926,7 @@ under the License. accountid - + createAccount @@ -987,16 +987,16 @@ under the License. account accountvar - + id userid - + - +--> registerUserKeys [Register User Keys] @@ -1059,8 +1059,8 @@ under the License. secretkey - - + + createNetwork [Creating default network] @@ -1097,7 +1097,7 @@ under the License. - + deployVirtualMachine [Deploy Virtual Machine in the account created] @@ -1114,7 +1114,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -1137,7 +1137,7 @@ under the License. - + associateIpAddress [Acquire a non-Source NAT IP Address for that account] @@ -1156,14 +1156,14 @@ under the License. 1 - + ipaddress nonsourcenatpublicip1 - + createLoadBalancerRule [Create Load Balancer Rule with the acquired Ip address] @@ -1204,8 +1204,8 @@ under the License. lbid1 - - + + createLoadBalancerRule [Create a Second Load Balancer Rule with the Acquired Ip Address] @@ -1238,7 +1238,7 @@ under the License. domainid 1 - + @@ -1246,8 +1246,8 @@ under the License. lbid2 - - + + createLoadBalancerRule [Create a Third Load Balancer Rule with the Acquired Ip Address] @@ -1288,8 +1288,8 @@ under the License. lbid3 - - + + deleteLoadBalancerRule 926 [Admin allowed to Delete Load Balancer Rule of another account via 8096 port] @@ -1312,7 +1312,7 @@ under the License. accountid - + createAccount @@ -1373,16 +1373,16 @@ under the License. account accountvar - + id userid - + - +--> registerUserKeys [Register User Keys] @@ -1445,8 +1445,8 @@ under the License. secretkey - - + + deleteLoadBalancerRule [Admin allowed to Delete Load Balancer Rule of another account via 8080 port] @@ -1459,8 +1459,8 @@ under the License. - - + + deleteAccount @@ -1471,8 +1471,8 @@ under the License. accountid - - + + createAccount [Create the Account and a User for the account] @@ -1486,7 +1486,7 @@ under the License. 0 - domainid + domainid 1 @@ -1532,16 +1532,16 @@ under the License. account accountvar - + id userid - + - +--> registerUserKeys [Register User Keys] @@ -1609,7 +1609,7 @@ under the License. - + createNetwork [Creating default network] @@ -1646,7 +1646,7 @@ under the License. - + deleteLoadBalancerRule true @@ -1659,8 +1659,8 @@ under the License. - - + + deployVirtualMachine [Deploy a Virtual Machine-1 to check multiple VMs - LB assignment] @@ -1676,7 +1676,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -1709,7 +1709,7 @@ under the License. - + deployVirtualMachine [Deploy a Virtual Machine-2 to check multiple VMs - LB assignment] @@ -1725,7 +1725,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -1758,7 +1758,7 @@ under the License. - + associateIpAddress [Acquire a non-Source NAT IP address] @@ -1776,14 +1776,14 @@ under the License. 1 - + ipaddress nonsourcenatpublicip - + createLoadBalancerRule [Create a Load Balancer Rule] @@ -1822,8 +1822,8 @@ under the License. lbid - - + + assignToLoadBalancerRule 939 [Assign the First VM to the Load Balancing Rule] @@ -1837,8 +1837,8 @@ under the License. vmid1 - - + + assignToLoadBalancerRule 939 [Assign the Second VM to the Load Balancing Rule] @@ -1852,8 +1852,8 @@ under the License. vmid2 - - + + createLoadBalancerRule @@ -1887,8 +1887,8 @@ under the License. 1 - - + + createLoadBalancerRule 978 [Creation of Second LoadBalancer Rule should Fail] @@ -1922,8 +1922,8 @@ under the License. 1 - - + + listRouters @@ -1950,8 +1950,8 @@ under the License. sourcenatpublicip - - + + createLoadBalancerRule 1017 [Create Load Balancer Rule with Source NAT IP Address] @@ -1984,9 +1984,9 @@ under the License. 1 - - - + + + destroyVirtualMachine @@ -1997,8 +1997,8 @@ under the License. vmid1 - - + + destroyVirtualMachine [Destroy vm as a part of cleanup] @@ -2009,7 +2009,7 @@ under the License. - + destroyVirtualMachine [Destroy vm as a part of cleanup] @@ -2020,7 +2020,7 @@ under the License. - + deleteAccount [Deleting Account as a part of cleanup] @@ -2030,7 +2030,7 @@ under the License. accountid - - - + + + diff --git a/test/metadata/func/localstorage_volume_test.xml b/test/metadata/func/localstorage_volume_test.xml index f268495b171..aa1bbcb4292 100644 --- a/test/metadata/func/localstorage_volume_test.xml +++ b/test/metadata/func/localstorage_volume_test.xml @@ -48,7 +48,7 @@ under the License. - + createVolume @@ -73,11 +73,11 @@ under the License. diskofferingid globaldiskofferingid - + - - + + listVolumes @@ -98,7 +98,7 @@ under the License. - + detachVolume 1032 @@ -110,9 +110,9 @@ under the License. - - - + + + listVolumes @@ -133,7 +133,7 @@ under the License. - + detachVolume 1034 @@ -145,9 +145,9 @@ under the License. - - - - - + + + + + diff --git a/test/metadata/func/mgmtvmsync.xml b/test/metadata/func/mgmtvmsync.xml index 9972b5555dd..f2b884e8a21 100644 --- a/test/metadata/func/mgmtvmsync.xml +++ b/test/metadata/func/mgmtvmsync.xml @@ -22,12 +22,12 @@ under the License. deployVirtualMachine deploy First VM test case - + diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -39,7 +39,7 @@ under the License. zoneid globalzoneid - + displayname FirstVM @@ -80,12 +80,12 @@ under the License. deployVirtualMachine deploy Second VM test case - + diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -97,7 +97,7 @@ under the License. zoneid globalzoneid - + displayname SecondVM @@ -172,7 +172,7 @@ under the License. haenable false - + @@ -194,7 +194,7 @@ under the License. - + @@ -231,8 +231,8 @@ under the License. instance_name_1st - - + + select instance_name from vm_instance true @@ -269,7 +269,7 @@ under the License. - + @@ -277,13 +277,13 @@ under the License. killvm.sh Kill the First HA disabled VM - + n instance_name_1st - + h ipaddress_1st @@ -295,13 +295,13 @@ under the License. killvm.sh Kill the Second HA disabled VM - + n instance_name_2nd - + h ipaddress_2nd @@ -320,7 +320,7 @@ under the License. 100 - + @@ -352,7 +352,7 @@ under the License. 100 - + @@ -369,10 +369,10 @@ under the License. state Stopped - + - - + + listVirtualMachines Check the stopped status of Second virtual machine with ha disabled @@ -387,7 +387,7 @@ under the License. state Stopped - + @@ -403,7 +403,7 @@ under the License. - + destroyVirtualMachine Destroy the Second vm as a part of cleanup @@ -421,12 +421,12 @@ under the License. deployVirtualMachine deploy VM test case - + diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -438,7 +438,7 @@ under the License. zoneid globalzoneid - + displayname FirstVM @@ -493,7 +493,7 @@ under the License. - + @@ -513,7 +513,7 @@ under the License. - + ms.sh @@ -537,13 +537,13 @@ under the License. shutdown.sh Shut down the VM Test Case - + n instance_name_1st - + h ipaddress_1st @@ -562,7 +562,7 @@ under the License. 60 - + @@ -593,7 +593,7 @@ under the License. 60 - + @@ -613,7 +613,7 @@ under the License. - + listHosts List host that is presumed to have the VM Test Case @@ -630,7 +630,7 @@ under the License. - + listvm.sh @@ -646,6 +646,6 @@ under the License. instance_name_1st - + diff --git a/test/metadata/func/portforwarding.xml b/test/metadata/func/portforwarding.xml index e591c0fdeeb..2c077a60cb5 100644 --- a/test/metadata/func/portforwarding.xml +++ b/test/metadata/func/portforwarding.xml @@ -78,12 +78,12 @@ under the License. account accountname - + id userid - + @@ -166,7 +166,7 @@ under the License. ---> +--> deployVirtualMachine [Deploy Virtual Machine in the created Account] @@ -202,7 +202,7 @@ under the License. networkids networkid - + @@ -237,7 +237,7 @@ under the License. 1 - + id routerid @@ -247,8 +247,8 @@ under the License. sourcenatpublicip - - + + associateIpAddress [Acquire a new IP Address for the Account] @@ -266,14 +266,14 @@ under the License. 1 - + ipaddress nonsourcenatpublicip - + createPortForwardingRule @@ -313,7 +313,7 @@ under the License. - + createPortForwardingRule @@ -353,7 +353,7 @@ under the License. - + createPortForwardingRule @@ -393,7 +393,7 @@ under the License. - + createPortForwardingRule @@ -433,9 +433,9 @@ under the License. - + - +--> createPortForwardingRule @@ -514,7 +514,7 @@ under the License. - + createPortForwardingRule 328 [Create Port Forwarding Rule with same parameters with UDP protocol] @@ -553,7 +553,7 @@ under the License. - + associateIpAddress @@ -572,14 +572,14 @@ under the License. 1 - + ipaddress nonsourcenatpublicip1 - + createPortForwardingRule [Create Port Forwarding Rule with the acquired IP Address] @@ -617,14 +617,14 @@ under the License. 1 - + id portforwardingruleid1 - + deletePortForwardingRule 329 [Delete Port Forwarding Rule] @@ -643,7 +643,7 @@ under the License. - + listPortForwardingRules 329 [Try to list the Deleted Port Forwarding Rules (del pf rule exercise end)] @@ -696,14 +696,14 @@ under the License. 1 - + id portforwardingruleid1 - + disassociateIpAddress [Release the Non-Source NAT IP Address] @@ -722,7 +722,7 @@ under the License. - + listPortForwardingRules 331 [Try to List the Port Forwarding Rules created from Released IP Address(del ip exercise end)] @@ -736,13 +736,13 @@ under the License. - + createLoadBalancerRule [Create Load Balancing Rule Inorder to test PF-LBrule collision (pf-lb collision exercise begin)] - + privateip vmipaddress @@ -781,13 +781,13 @@ under the License. - - + + assignToLoadBalancerRule [Assign the Created LB Rule to the VM created in the Test] - + virtualmachineids vmid @@ -797,14 +797,14 @@ under the License. - + createPortForwardingRule [Create Port Forwarding Rule to test PF-LBrule collision (pf-lb rule collison exercise end)] 332 true - + privateip vmipaddress @@ -838,7 +838,7 @@ under the License. - + stopRouter @@ -850,12 +850,12 @@ under the License. - + createPortForwardingRule 336 [Create Port Forwarding Rule with the Source NAT IP Address] - + privateip vmipaddress @@ -889,7 +889,7 @@ under the License. - + startRouter [Start the DomR (add new pfrule when domR is stopped exercise end)] @@ -900,14 +900,14 @@ under the License. - + createPortForwardingRule 337 [Create Port Forwarding Rule with the Source NAT IP Address] - + privateip vmipaddress @@ -940,16 +940,16 @@ under the License. 1 - + id portforwardingruleid_forremove - - + stopRouter @@ -1041,7 +1041,7 @@ under the License. - + startRouter [Start the DomR (del pf rule exercise end)] @@ -1063,6 +1063,6 @@ under the License. accountid - + diff --git a/test/metadata/func/private_templates.xml b/test/metadata/func/private_templates.xml index d733c7e7f50..c56eec4a5dc 100644 --- a/test/metadata/func/private_templates.xml +++ b/test/metadata/func/private_templates.xml @@ -77,12 +77,12 @@ under the License. account accountvar - + id userid - + @@ -124,7 +124,7 @@ under the License. ---> +--> registerUserKeys @@ -143,8 +143,8 @@ under the License. secretkey - - + + createNetwork [Creating default network] @@ -181,7 +181,7 @@ under the License. - + deployVirtualMachine true @@ -197,7 +197,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -230,8 +230,8 @@ under the License. - - + + listVolumes @@ -251,8 +251,8 @@ under the License. - - + + stopVirtualMachine @@ -264,7 +264,7 @@ under the License. - + createTemplate true @@ -294,8 +294,8 @@ under the License. - - + + startVirtualMachine @@ -307,7 +307,7 @@ under the License. - + createTemplate true @@ -331,7 +331,7 @@ under the License. - + destroyVirtualMachine @@ -343,7 +343,7 @@ under the License. - + createTemplate true @@ -367,7 +367,7 @@ under the License. - + deployVirtualMachine @@ -385,7 +385,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid privatetemplateid @@ -422,7 +422,7 @@ under the License. - + listVolumes @@ -443,7 +443,7 @@ under the License. - + stopVirtualMachine true @@ -454,7 +454,7 @@ under the License. - + createTemplate true @@ -483,7 +483,7 @@ under the License. - + deployVirtualMachine true @@ -500,7 +500,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid privatetemplateid @@ -537,7 +537,7 @@ under the License. - + createTemplate @@ -567,7 +567,7 @@ under the License. - + createTemplate true @@ -591,8 +591,8 @@ under the License. - - + + @@ -654,12 +654,12 @@ under the License. account accountvar1 - + id userid1 - + @@ -697,7 +697,7 @@ under the License. ---> +--> registerUserKeys @@ -716,8 +716,8 @@ under the License. secretkey - - + + createNetwork [Creating default network] @@ -754,7 +754,7 @@ under the License. - + deployVirtualMachine true @@ -770,7 +770,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -803,7 +803,7 @@ under the License. - + stopVirtualMachine true @@ -814,7 +814,7 @@ under the License. - + listVolumes @@ -834,7 +834,7 @@ under the License. - + createTemplate true @@ -858,9 +858,9 @@ under the License. - - - + + + deleteAccount Deleting First Account as a part of cleanup @@ -871,7 +871,7 @@ under the License. - + deleteAccount Deleting Second Account as a part of cleanup @@ -882,8 +882,8 @@ under the License. - - - + diff --git a/test/metadata/func/regression.xml b/test/metadata/func/regression.xml index 2b47dadcfcf..eebf13ff74c 100644 --- a/test/metadata/func/regression.xml +++ b/test/metadata/func/regression.xml @@ -170,7 +170,7 @@ under the License. accountname - + id @@ -215,12 +215,12 @@ under the License. domain ROOT - + - - - + + + createUser @@ -257,9 +257,9 @@ under the License. domainid 1 - + - + id @@ -318,7 +318,7 @@ under the License. accountname - + id @@ -465,7 +465,7 @@ under the License. usersecretkey - + id @@ -596,11 +596,11 @@ under the License. - + - @@ -1480,7 +1480,7 @@ under the License. true - + success @@ -1505,7 +1505,7 @@ under the License. 1 - + template 0 @@ -1563,7 +1563,7 @@ under the License. size - debian50templatesize + debian50templatesize account @@ -1596,7 +1596,7 @@ under the License. domainid 1 - + @@ -1804,7 +1804,7 @@ under the License. offerha false - + @@ -1840,7 +1840,7 @@ under the License. vlan - guestcidraddress + guestcidraddress networktype @@ -1886,7 +1886,7 @@ under the License. - + deployVirtualMachine @@ -1903,7 +1903,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -1995,8 +1995,8 @@ under the License. - - + + listVirtualMachines @@ -2077,8 +2077,8 @@ under the License. group1 - - + + listRouters @@ -2169,9 +2169,9 @@ under the License. Running - - - + + + associateIpAddress 546 @@ -2189,7 +2189,7 @@ under the License. 1 - + id nonsourcenatpublicipid @@ -2215,9 +2215,9 @@ under the License. - + - + createLoadBalancerRule @@ -2286,9 +2286,9 @@ under the License. accountname - - - + + + listLoadBalancerRules @@ -2305,8 +2305,8 @@ under the License. - - + + assignToLoadBalancerRule @@ -2321,8 +2321,8 @@ under the License. vmid - - + + deleteLoadBalancerRule @@ -2333,17 +2333,17 @@ under the License. lbid - - + + listLoadBalancerRules true - + createLoadBalancerRule - + name lbname @@ -2406,8 +2406,8 @@ under the License. accountname - - + + assignToLoadBalancerRule @@ -2420,9 +2420,9 @@ under the License. vmid - - - + + + listLoadBalancerRuleInstances @@ -2434,8 +2434,8 @@ under the License. lbid - - + + removeFromLoadBalancerRule @@ -2454,8 +2454,8 @@ under the License. accountname - - + + listLoadBalancerRuleInstances true @@ -2465,13 +2465,13 @@ under the License. lbid - - + + - + - - + + rebootVirtualMachine @@ -2483,7 +2483,7 @@ under the License. - + listVirtualMachines @@ -2503,8 +2503,8 @@ under the License. - - + + stopVirtualMachine @@ -2516,7 +2516,7 @@ under the License. - + listVirtualMachines @@ -2536,9 +2536,9 @@ under the License. - - - + + + @@ -2560,7 +2560,7 @@ under the License. - + listVolumes @@ -2580,7 +2580,7 @@ under the License. - + detachVolume @@ -2591,7 +2591,7 @@ under the License. - + listVolumes true @@ -2606,8 +2606,8 @@ under the License. - - + + createVolume @@ -2631,7 +2631,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -2639,9 +2639,9 @@ under the License. datavolumeid - - - + + + attachVolume @@ -2656,7 +2656,7 @@ under the License. - + listVolumes false @@ -2671,8 +2671,8 @@ under the License. - - + + createVolume @@ -2695,7 +2695,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -2703,8 +2703,8 @@ under the License. datavolumeid1 - - + + deleteVolume @@ -2713,8 +2713,8 @@ under the License. datavolumeid1 - - + + listVolumes true @@ -2724,10 +2724,10 @@ under the License. datavolumeid1 - - + - + + createSnapshot @@ -2758,7 +2758,7 @@ under the License. - + listSnapshots false @@ -2769,7 +2769,7 @@ under the License. - + deleteSnapshot @@ -2781,7 +2781,7 @@ under the License. - + listSnapshots @@ -2794,7 +2794,7 @@ under the License. - + createSnapshot @@ -2811,7 +2811,7 @@ under the License. - + createTemplate 958 @@ -2859,7 +2859,7 @@ under the License. - + listTemplates @@ -2900,7 +2900,7 @@ under the License. - + updateTemplate @@ -2920,7 +2920,7 @@ under the License. - + listTemplates List updated template @@ -2941,8 +2941,8 @@ under the License. - - + + listTemplatePermissions @@ -2964,8 +2964,8 @@ under the License. - - + + updateTemplatePermissions @@ -2981,7 +2981,7 @@ under the License. - + listTemplates List template with updated permission @@ -3002,8 +3002,8 @@ under the License. - - + + deleteTemplate @@ -3015,7 +3015,7 @@ under the License. - + listTemplates true @@ -3030,9 +3030,9 @@ under the License. - - + + changeServiceForVirtualMachine @@ -3048,7 +3048,7 @@ under the License. - + listVirtualMachines @@ -3072,8 +3072,8 @@ under the License. - - + + resetPasswordForVirtualMachine @@ -3094,7 +3094,7 @@ under the License. - + listVirtualMachines @@ -3114,7 +3114,7 @@ under the License. - + listVirtualMachines @@ -3135,7 +3135,7 @@ under the License. - + startVirtualMachine 18 @@ -3191,7 +3191,7 @@ under the License. - + listVirtualMachines @@ -3211,7 +3211,7 @@ under the License. - + updateVirtualMachine @@ -3226,7 +3226,7 @@ under the License. - + listVirtualMachines 21 @@ -3247,7 +3247,7 @@ under the License. - + updateVirtualMachine @@ -3261,7 +3261,7 @@ under the License. - + listVirtualMachines 21 @@ -3282,9 +3282,9 @@ under the License. - - - + + + listPublicIpAddresses @@ -3298,8 +3298,8 @@ under the License. - - + + disassociateIpAddress @@ -3315,7 +3315,7 @@ under the License. - + rebootRouter @@ -3327,7 +3327,7 @@ under the License. - + stopRouter @@ -3339,7 +3339,7 @@ under the License. - + startRouter @@ -3414,7 +3414,7 @@ under the License. - + listEvents @@ -3426,7 +3426,7 @@ under the License. - + destroyVirtualMachine @@ -3438,7 +3438,7 @@ under the License. - + listVirtualMachines @@ -3454,7 +3454,7 @@ under the License. - + recoverVirtualMachine @@ -3466,7 +3466,7 @@ under the License. - + listVirtualMachines @@ -3486,14 +3486,14 @@ under the License. - + listConfigurations 549 false - - + + listConfigurations @@ -3506,8 +3506,8 @@ under the License. - - + + updateConfiguration @@ -3523,7 +3523,7 @@ under the License. - + listConfigurations @@ -3538,9 +3538,9 @@ under the License. 35 - - - + + + listPods @@ -3549,9 +3549,9 @@ under the License. - - - + + + createAccount @@ -3591,7 +3591,7 @@ under the License. - + listAccounts @@ -3606,8 +3606,8 @@ under the License. accountid1 - - + + updateAccount 951 @@ -3626,7 +3626,7 @@ under the License. - + listAccounts @@ -3645,8 +3645,8 @@ under the License. updatedname - - + + disableAccount @@ -3664,10 +3664,10 @@ under the License. lock true - + - - + + @@ -3683,10 +3683,10 @@ under the License. 1 - - - - + + + + updateResourceLimit 953 @@ -3722,9 +3722,9 @@ under the License. 300 - - - + + + listResourceLimits true @@ -3745,9 +3745,9 @@ under the License. 300 - - - + + + updateResourceLimit 954 @@ -3765,8 +3765,8 @@ under the License. 65 - - + + listResourceLimits @@ -3785,9 +3785,9 @@ under the License. 65 - - - + + + createDiskOffering @@ -3833,9 +3833,9 @@ under the License. - - - + + + listDiskOfferings @@ -3851,9 +3851,9 @@ under the License. newdisk - - - + + + updateDiskOffering @@ -3867,8 +3867,8 @@ under the License. newdiskname - - + + listDiskOfferings @@ -3887,9 +3887,9 @@ under the License. newdiskname - + + - deleteDiskOffering @@ -3900,8 +3900,8 @@ under the License. diskid - - + + listDiskOfferings true @@ -3915,7 +3915,7 @@ under the License. diskid - + @@ -3923,29 +3923,29 @@ under the License. 750 false - + listCapacity 974 false - + listHosts false 975 - - + + listIsos 960 true - + createServiceOffering @@ -3978,7 +3978,7 @@ under the License. - + listServiceOfferings @@ -4013,8 +4013,8 @@ under the License. - - + + updateServiceOffering @@ -4033,8 +4033,8 @@ under the License. - - + + listServiceOfferings @@ -4069,8 +4069,8 @@ under the License. - - + + deleteServiceOffering @@ -4082,7 +4082,7 @@ under the License. - + listServiceOfferings 963-2 @@ -4094,9 +4094,9 @@ under the License. - - - + + + registerIso Register iso @@ -4164,8 +4164,8 @@ under the License. - - + + listIsos List isos @@ -4177,7 +4177,7 @@ under the License. - + registerTemplate @@ -4258,8 +4258,8 @@ under the License. - - + + listSystemVms @@ -4337,7 +4337,7 @@ under the License. - + rebootSystemVm @@ -4349,7 +4349,7 @@ under the License. - + stopSystemVm @@ -4360,8 +4360,8 @@ under the License. consoleid - - + + startSystemVm @@ -4372,9 +4372,9 @@ under the License. consoleid - - - + + + deleteIso @@ -4398,7 +4398,7 @@ under the License. - + deleteTemplate @@ -4437,7 +4437,7 @@ under the License. accountid - - - + + + diff --git a/test/metadata/func/regression_events.properties b/test/metadata/func/regression_events.properties index 456574c982d..800248fb99f 100644 --- a/test/metadata/func/regression_events.properties +++ b/test/metadata/func/regression_events.properties @@ -1,43 +1,43 @@ -# 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. - -# All the events that need to be created as a result of execution of Regression test -VM.CREATE=2 -VM.DESTROY=2 -VM.START=2 -VM.STOP=2 -VM.REBOOT=1 -VM.UPGRADE=1 -VM.RESETPASSWORD=1 -ROUTER.CREATE=1 -ROUTER.DESTROY=1 -ROUTER.START=2 -ROUTER.STOP=2 -ROUTER.REBOOT=1 -NET.IPASSIGN=2 -NET.IPRELEASE=2 -SNAPSHOT.CREATE=1 -SNAPSHOT.DELETE=1 -PF.SERVICE.APPLY=1 -PF.SERVICE.REMOVE=1 -TEMPLATE.CREATE=2 -NET.RULEADD=4 -NET.RULEDELETE=4 -VOLUME.CREATE=6 -VOLUME.DELETE=6 -VOLUME.ATTACH=1 -VOLUME.DETACH=1 +# 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. + +# All the events that need to be created as a result of execution of Regression test +VM.CREATE=2 +VM.DESTROY=2 +VM.START=2 +VM.STOP=2 +VM.REBOOT=1 +VM.UPGRADE=1 +VM.RESETPASSWORD=1 +ROUTER.CREATE=1 +ROUTER.DESTROY=1 +ROUTER.START=2 +ROUTER.STOP=2 +ROUTER.REBOOT=1 +NET.IPASSIGN=2 +NET.IPRELEASE=2 +SNAPSHOT.CREATE=1 +SNAPSHOT.DELETE=1 +PF.SERVICE.APPLY=1 +PF.SERVICE.REMOVE=1 +TEMPLATE.CREATE=2 +NET.RULEADD=4 +NET.RULEDELETE=4 +VOLUME.CREATE=6 +VOLUME.DELETE=6 +VOLUME.ATTACH=1 +VOLUME.DETACH=1 diff --git a/test/metadata/func/regression_new.xml b/test/metadata/func/regression_new.xml index 8db3593c0cd..3554e6e45a3 100644 --- a/test/metadata/func/regression_new.xml +++ b/test/metadata/func/regression_new.xml @@ -836,7 +836,7 @@ under the License. size - debian50templatesize + debian50templatesize account @@ -869,7 +869,7 @@ under the License. domainid 1 - + @@ -1269,7 +1269,7 @@ under the License. - + sleep.sh @@ -1280,7 +1280,7 @@ under the License. 60 - + @@ -2686,7 +2686,7 @@ under the License. serviceofferingid - globalserviceofferingid + globalserviceofferingid serviceofferingname @@ -2694,7 +2694,7 @@ under the License. serviceofferingdisplaytext - + @@ -2807,7 +2807,7 @@ under the License. destroyed false - + @@ -2902,7 +2902,7 @@ under the License. state Created - + account accountname @@ -3018,7 +3018,7 @@ under the License. state Created - + account accountname @@ -3066,7 +3066,7 @@ under the License. destroyed false - + @@ -3210,7 +3210,7 @@ under the License. intervaltype MANUAL - + @@ -3320,7 +3320,7 @@ under the License. - + createTemplate 958 [Create Template from Snapshot] @@ -3373,7 +3373,7 @@ under the License. isready true - + passwordenabled false @@ -3411,7 +3411,7 @@ under the License. domainid 1 - + @@ -3458,7 +3458,7 @@ under the License. hypervisor XenServer - + @@ -3539,11 +3539,11 @@ under the License. isextractable true - + - - + + sleep.sh @@ -3554,8 +3554,8 @@ under the License. 300 - - + + listTemplates @@ -3601,7 +3601,7 @@ under the License. format VHD - + isfeatured false @@ -3648,7 +3648,7 @@ under the License. domain ROOT - + @@ -3762,7 +3762,7 @@ under the License. 240 - + listTemplates @@ -3965,7 +3965,7 @@ under the License. - + - @@ -7355,7 +7355,7 @@ under the License. state Running - + @@ -7444,7 +7444,7 @@ under the License. state Running - + @@ -7466,7 +7466,7 @@ under the License. systemvmtype consoleproxy - + zoneid globalzoneid @@ -7524,7 +7524,7 @@ under the License. state Stopped - + @@ -7612,7 +7612,7 @@ under the License. state Running - + @@ -7638,7 +7638,7 @@ under the License. privateisoid - + diff --git a/test/metadata/func/regression_test.xml b/test/metadata/func/regression_test.xml index 18dc7856d9c..53baea191b2 100644 --- a/test/metadata/func/regression_test.xml +++ b/test/metadata/func/regression_test.xml @@ -93,7 +93,7 @@ under the License. - + listAccounts @@ -200,8 +200,8 @@ under the License. false - - + + updateUser @@ -216,8 +216,8 @@ under the License. newuser - - + + listUsers @@ -271,10 +271,10 @@ under the License. created - + - - + + lockUser @@ -285,8 +285,8 @@ under the License. userid - - + + disableUser @@ -298,9 +298,9 @@ under the License. - - + + enableUser @@ -311,8 +311,8 @@ under the License. userid - - + + createDomain @@ -333,9 +333,9 @@ under the License. newdomainid - + + - listDomains @@ -356,8 +356,8 @@ under the License. domainname - - + + updateDomain @@ -372,8 +372,8 @@ under the License. newdomainname - - + + listDomains false @@ -383,8 +383,8 @@ under the License. newdomainname - - + + deleteDomain @@ -395,8 +395,8 @@ under the License. newdomainid - - + + listTemplates @@ -440,7 +440,7 @@ under the License. - + listTemplates @@ -484,7 +484,7 @@ under the License. - + listServiceOfferings @@ -508,7 +508,7 @@ under the License. - + listServiceOfferings 876 @@ -552,13 +552,13 @@ under the License. - - + + listZones 39 - + 0 zone @@ -571,7 +571,7 @@ under the License. - + deployVirtualMachine @@ -588,7 +588,7 @@ under the License. diskofferingid 5 - + templateid globaltemplateid @@ -676,8 +676,8 @@ under the License. - - + + listVirtualMachines @@ -758,8 +758,8 @@ under the License. group1 - - + + listRouters @@ -851,9 +851,9 @@ under the License. Running - - - + + + +--> - + + + +--> + + --> + + --> - + + --> + + + --> + + --> - + + + --> + + + --> + + --> - + + --> + + + --> - + + --> + + + --> + + --> + + --> - + + --> + listVirtualMachines @@ -1516,8 +1516,8 @@ under the License. - - + + rebootVirtualMachine @@ -1529,7 +1529,7 @@ under the License. - + listVirtualMachines @@ -1549,8 +1549,8 @@ under the License. - - + + stopVirtualMachine @@ -1562,7 +1562,7 @@ under the License. - + listVirtualMachines @@ -1582,9 +1582,9 @@ under the License. - - - + + + @@ -1606,7 +1606,7 @@ under the License. - + listVolumes @@ -1626,7 +1626,7 @@ under the License. - + detachVolume @@ -1637,7 +1637,7 @@ under the License. - + listVolumes true @@ -1652,8 +1652,8 @@ under the License. - - + + createVolume @@ -1685,9 +1685,9 @@ under the License. datavolumeid - - - + + + attachVolume @@ -1702,7 +1702,7 @@ under the License. - + listVolumes false @@ -1717,8 +1717,8 @@ under the License. - - + + createVolume @@ -1749,8 +1749,8 @@ under the License. datavolumeid1 - - + + deleteVolume @@ -1759,8 +1759,8 @@ under the License. datavolumeid1 - - + + listVolumes true @@ -1770,10 +1770,10 @@ under the License. datavolumeid1 - - + - + + createSnapshot @@ -1804,7 +1804,7 @@ under the License. - + listSnapshots false @@ -1815,7 +1815,7 @@ under the License. - + deleteSnapshot @@ -1827,7 +1827,7 @@ under the License. - + listSnapshots @@ -1840,7 +1840,7 @@ under the License. - + createTemplate @@ -1889,7 +1889,7 @@ under the License. - + listTemplates @@ -1930,7 +1930,7 @@ under the License. - + updateTemplate @@ -1950,7 +1950,7 @@ under the License. - + listTemplates List updated template @@ -1971,8 +1971,8 @@ under the License. - - + + listTemplatePermissions @@ -1994,8 +1994,8 @@ under the License. - - + + updateTemplatePermissions @@ -2011,7 +2011,7 @@ under the License. - + listTemplates List template with updated permission @@ -2032,8 +2032,8 @@ under the License. - - + + deleteTemplate @@ -2045,7 +2045,7 @@ under the License. - + listTemplates true @@ -2060,9 +2060,9 @@ under the License. - - + + changeServiceForVirtualMachine @@ -2078,7 +2078,7 @@ under the License. - + listVirtualMachines @@ -2102,8 +2102,8 @@ under the License. - - + + +--> listVirtualMachines @@ -2165,7 +2165,7 @@ under the License. - + startVirtualMachine 18 @@ -2221,7 +2221,7 @@ under the License. - + listVirtualMachines @@ -2241,7 +2241,7 @@ under the License. - + updateVirtualMachine @@ -2256,7 +2256,7 @@ under the License. - + listVirtualMachines 21 @@ -2277,7 +2277,7 @@ under the License. - + updateVirtualMachine @@ -2291,7 +2291,7 @@ under the License. - + listVirtualMachines 21 @@ -2312,9 +2312,9 @@ under the License. - - - + + + - + --> + + --> rebootRouter @@ -2357,7 +2357,7 @@ under the License. - + stopRouter @@ -2369,7 +2369,7 @@ under the License. - + startRouter @@ -2445,7 +2445,7 @@ under the License. - + listEvents @@ -2457,7 +2457,7 @@ under the License. - + destroyVirtualMachine @@ -2469,7 +2469,7 @@ under the License. - + listVirtualMachines @@ -2485,7 +2485,7 @@ under the License. - + recoverVirtualMachine @@ -2497,7 +2497,7 @@ under the License. - + listVirtualMachines @@ -2517,14 +2517,14 @@ under the License. - + listConfigurations 549 false - - + + listConfigurations @@ -2537,8 +2537,8 @@ under the License. - - + + updateConfiguration @@ -2554,7 +2554,7 @@ under the License. - + listConfigurations @@ -2569,9 +2569,9 @@ under the License. 35 - - - + + + listPods @@ -2580,9 +2580,9 @@ under the License. - - - + + + createUser @@ -2619,7 +2619,7 @@ under the License. - + listAccounts @@ -2634,8 +2634,8 @@ under the License. accountid1 - - + + updateAccount 951 @@ -2654,7 +2654,7 @@ under the License. - + listAccounts @@ -2673,8 +2673,8 @@ under the License. updatedname - - + + lockAccount @@ -2689,8 +2689,8 @@ under the License. 1 - - + + disableAccount @@ -2705,8 +2705,8 @@ under the License. 1 - - + + @@ -2722,10 +2722,10 @@ under the License. 1 - - - - + + + + updateResourceLimit 953 @@ -2761,9 +2761,9 @@ under the License. 300 - - - + + + listResourceLimits true @@ -2784,9 +2784,9 @@ under the License. 300 - - - + + + updateResourceLimit 954 @@ -2804,8 +2804,8 @@ under the License. 65 - - + + listResourceLimits @@ -2824,9 +2824,9 @@ under the License. 65 - - - + + + createDiskOffering @@ -2876,9 +2876,9 @@ under the License. - - - + + + listDiskOfferings @@ -2894,9 +2894,9 @@ under the License. newdisk - - - + + + updateDiskOffering @@ -2910,8 +2910,8 @@ under the License. newdiskname - - + + listDiskOfferings @@ -2930,9 +2930,9 @@ under the License. newdiskname - + + - deleteDiskOffering @@ -2943,8 +2943,8 @@ under the License. diskid - - + + listDiskOfferings true @@ -2958,9 +2958,9 @@ under the License. diskid - + + - deleteUser @@ -2971,37 +2971,37 @@ under the License. userid - - + + listAlerts 750 false - + listCapacity 974 false - + listHosts false 975 - - + + listIsos 960 true - + createServiceOffering @@ -3034,7 +3034,7 @@ under the License. - + listServiceOfferings @@ -3069,8 +3069,8 @@ under the License. - - + + updateServiceOffering @@ -3089,8 +3089,8 @@ under the License. - - + + listServiceOfferings @@ -3125,8 +3125,8 @@ under the License. - - + + deleteServiceOffering @@ -3138,7 +3138,7 @@ under the License. - + listServiceOfferings 963-2 @@ -3150,9 +3150,9 @@ under the License. - - - + + + registerIso Register iso @@ -3220,8 +3220,8 @@ under the License. - - + + listIsos List isos @@ -3233,7 +3233,7 @@ under the License. - + registerTemplate @@ -3310,8 +3310,8 @@ under the License. - - + + listSystemVms @@ -3389,7 +3389,7 @@ under the License. - + rebootSystemVm @@ -3401,7 +3401,7 @@ under the License. - + stopSystemVm @@ -3412,8 +3412,8 @@ under the License. consoleid - - + + startSystemVm @@ -3424,9 +3424,9 @@ under the License. consoleid - - - + + + deleteIso @@ -3450,7 +3450,7 @@ under the License. - + deleteTemplate @@ -3479,5 +3479,5 @@ under the License. - + diff --git a/test/metadata/func/regression_user.xml b/test/metadata/func/regression_user.xml index aac4d585f07..c58c848e9d5 100644 --- a/test/metadata/func/regression_user.xml +++ b/test/metadata/func/regression_user.xml @@ -170,7 +170,7 @@ under the License. accountname - + id @@ -215,7 +215,7 @@ under the License. domain ROOT - + @@ -295,7 +295,7 @@ under the License. ---> +--> registerUserKeys @@ -314,8 +314,8 @@ under the License. secretkey - - + + createNetwork [Creating default network] @@ -352,7 +352,7 @@ under the License. - + listAccounts @@ -446,9 +446,9 @@ under the License. templateavailable - + + - deployVirtualMachine @@ -466,7 +466,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -490,7 +490,7 @@ under the License. networkids networkid - + @@ -542,8 +542,8 @@ under the License. - - + + listVirtualMachines @@ -597,8 +597,8 @@ under the License. group1 - - + + listRouters @@ -690,9 +690,9 @@ under the License. Running - - - + + + associateIpAddress true @@ -703,7 +703,7 @@ under the License. globalzoneid - + id nonsourcenatpublicipid @@ -729,9 +729,9 @@ under the License. - + - + createLoadBalancerRule @@ -797,9 +797,9 @@ under the License. accountname - - - + + + listLoadBalancerRules @@ -807,8 +807,8 @@ under the License. 988 false - - + + assignToLoadBalancerRule @@ -824,8 +824,8 @@ under the License. vmid - - + + deleteLoadBalancerRule @@ -837,19 +837,19 @@ under the License. lbid - - + + listLoadBalancerRules true true - + createLoadBalancerRule true - + name lbname @@ -912,8 +912,8 @@ under the License. accountname - - + + assignToLoadBalancerRule true @@ -927,9 +927,9 @@ under the License. vmid - - - + + + listLoadBalancerRuleInstances @@ -942,8 +942,8 @@ under the License. lbid - - + + removeFromLoadBalancerRule @@ -963,8 +963,8 @@ under the License. accountname - - + + listLoadBalancerRuleInstances true @@ -975,13 +975,13 @@ under the License. lbid - - + + - + + +--> + + +--> + +--> - + +--> + + +--> - + +--> + + +--> + +--> + +--> - + +--> + listVirtualMachines @@ -1322,8 +1322,8 @@ under the License. - - + + rebootVirtualMachine @@ -1336,7 +1336,7 @@ under the License. - + listVirtualMachines true @@ -1353,8 +1353,8 @@ under the License. - - + + stopVirtualMachine @@ -1367,7 +1367,7 @@ under the License. - + listVirtualMachines true @@ -1384,9 +1384,9 @@ under the License. - - - + + + @@ -1408,7 +1408,7 @@ under the License. - + listVolumes @@ -1428,7 +1428,7 @@ under the License. - + detachVolume @@ -1440,7 +1440,7 @@ under the License. - + listVolumes true @@ -1455,8 +1455,8 @@ under the License. - - + + createVolume @@ -1473,7 +1473,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -1481,9 +1481,9 @@ under the License. datavolumeid - - - + + + attachVolume @@ -1499,7 +1499,7 @@ under the License. - + listVolumes true @@ -1515,8 +1515,8 @@ under the License. - - + + createVolume @@ -1532,7 +1532,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -1540,8 +1540,8 @@ under the License. datavolumeid1 - - + + deleteVolume true @@ -1551,8 +1551,8 @@ under the License. datavolumeid1 - - + + listVolumes true @@ -1562,10 +1562,10 @@ under the License. datavolumeid1 - - + - + + createSnapshot @@ -1597,7 +1597,7 @@ under the License. - + listSnapshots true @@ -1609,7 +1609,7 @@ under the License. - + deleteSnapshot @@ -1622,7 +1622,7 @@ under the License. - + listSnapshots @@ -1636,7 +1636,7 @@ under the License. - + createSnapshot @@ -1654,7 +1654,7 @@ under the License. - + createTemplate true @@ -1703,7 +1703,7 @@ under the License. - + listTemplates @@ -1745,7 +1745,7 @@ under the License. - + updateTemplate @@ -1766,7 +1766,7 @@ under the License. - + listTemplates true @@ -1788,8 +1788,8 @@ under the License. - - + + listTemplatePermissions @@ -1808,8 +1808,8 @@ under the License. - - + + updateTemplatePermissions @@ -1826,7 +1826,7 @@ under the License. - + listTemplates true @@ -1848,8 +1848,8 @@ under the License. - - + + deleteTemplate @@ -1862,7 +1862,7 @@ under the License. - + listTemplates true @@ -1878,7 +1878,7 @@ under the License. - + stopVirtualMachine true @@ -1890,7 +1890,7 @@ under the License. - + changeServiceForVirtualMachine @@ -1907,7 +1907,7 @@ under the License. - + listVirtualMachines true @@ -1928,8 +1928,8 @@ under the License. - - + + resetPasswordForVirtualMachine @@ -1951,7 +1951,7 @@ under the License. - + listVirtualMachines true @@ -1968,7 +1968,7 @@ under the License. - + listVirtualMachines @@ -1986,7 +1986,7 @@ under the License. - + startVirtualMachine true @@ -2039,7 +2039,7 @@ under the License. - + listVirtualMachines true @@ -2056,7 +2056,7 @@ under the License. - + updateVirtualMachine @@ -2072,7 +2072,7 @@ under the License. - + listVirtualMachines true @@ -2090,7 +2090,7 @@ under the License. - + updateVirtualMachine true @@ -2105,7 +2105,7 @@ under the License. - + listVirtualMachines true @@ -2123,17 +2123,17 @@ under the License. - - - + + + listPublicIpAddresses true 547 - - + + disassociateIpAddress @@ -2146,15 +2146,15 @@ under the License. - - + + listEvents true 40 - + destroyVirtualMachine @@ -2167,9 +2167,9 @@ under the License. - - - + + + registerIso true @@ -2236,8 +2236,8 @@ under the License. - - + + listIsos true @@ -2250,7 +2250,7 @@ under the License. - + registerTemplate @@ -2320,8 +2320,8 @@ under the License. - - + + deleteIso @@ -2347,7 +2347,7 @@ under the License. - + deleteTemplate @@ -2378,5 +2378,5 @@ under the License. - + diff --git a/test/metadata/func/regression_works.xml b/test/metadata/func/regression_works.xml index 731f498ccac..0b2f7543874 100644 --- a/test/metadata/func/regression_works.xml +++ b/test/metadata/func/regression_works.xml @@ -18,10 +18,10 @@ under the License. --> - - + + - + createAccount [Create the Account and a User for the account] @@ -59,7 +59,7 @@ under the License. password - + id @@ -164,11 +164,11 @@ under the License. - + - + listUsers 5 [List the Created User in (3)] @@ -177,7 +177,7 @@ under the License. accountname - + id @@ -222,14 +222,14 @@ under the License. domain ROOT - + - - - + + + - + createUser 3 [Create User Command] @@ -261,9 +261,9 @@ under the License. email nimbus-user@gmail.com - + - + id @@ -312,7 +312,7 @@ under the License. - + @@ -324,7 +324,7 @@ under the License. accountname - + id @@ -429,7 +429,7 @@ under the License. - + @@ -473,7 +473,7 @@ under the License. usersecretkey - + id @@ -534,7 +534,7 @@ under the License. - + @@ -606,11 +606,11 @@ under the License. - + - - + @@ -753,7 +753,7 @@ under the License. - + @@ -825,7 +825,7 @@ under the License. - + @@ -945,7 +945,7 @@ under the License. state locked - + @@ -963,7 +963,7 @@ under the License. domainid 1 - + @@ -1065,7 +1065,7 @@ under the License. state enabled - + @@ -1189,7 +1189,7 @@ under the License. state disabled - + @@ -1207,7 +1207,7 @@ under the License. domainid 1 - + @@ -1309,7 +1309,7 @@ under the License. state enabled - + @@ -1325,7 +1325,7 @@ under the License. domainname - + name @@ -1366,7 +1366,7 @@ under the License. domainname - + id @@ -1414,7 +1414,7 @@ under the License. newdomainname - + id @@ -1456,7 +1456,7 @@ under the License. 1 - + domain 0 @@ -1486,8 +1486,8 @@ under the License. - - + + @@ -1503,7 +1503,7 @@ under the License. true - + success @@ -1528,7 +1528,7 @@ under the License. 1 - + template 0 @@ -1586,7 +1586,7 @@ under the License. size - debian50templatesize + debian50templatesize account @@ -1619,7 +1619,7 @@ under the License. domainid 1 - + @@ -1829,7 +1829,7 @@ under the License. offerha false - + @@ -1867,7 +1867,7 @@ under the License. vlan - guestcidraddress + guestcidraddress networktype @@ -2015,7 +2015,7 @@ under the License. - + sleep.sh @@ -2026,7 +2026,7 @@ under the License. 60 - + @@ -3432,7 +3432,7 @@ under the License. serviceofferingid - globalserviceofferingid + globalserviceofferingid serviceofferingname @@ -3440,7 +3440,7 @@ under the License. serviceofferingdisplaytext - + @@ -3553,7 +3553,7 @@ under the License. destroyed false - + @@ -3648,7 +3648,7 @@ under the License. state Created - + account accountname @@ -3764,7 +3764,7 @@ under the License. state Created - + account accountname @@ -3812,7 +3812,7 @@ under the License. destroyed false - + @@ -3956,7 +3956,7 @@ under the License. intervaltype MANUAL - + @@ -4066,7 +4066,7 @@ under the License. - + createTemplate 958 [Create Template from Snapshot] @@ -4119,7 +4119,7 @@ under the License. isready true - + passwordenabled false @@ -4157,7 +4157,7 @@ under the License. domainid 1 - + @@ -4204,7 +4204,7 @@ under the License. hypervisor XenServer - + @@ -4285,11 +4285,11 @@ under the License. isextractable true - + - - + + sleep.sh @@ -4300,8 +4300,8 @@ under the License. 300 - - + + listTemplates @@ -4347,7 +4347,7 @@ under the License. format VHD - + isfeatured false @@ -4394,7 +4394,7 @@ under the License. domain ROOT - + @@ -4508,7 +4508,7 @@ under the License. 240 - + listTemplates @@ -4711,7 +4711,7 @@ under the License. - + - @@ -8101,7 +8101,7 @@ under the License. state Running - + @@ -8190,7 +8190,7 @@ under the License. state Running - + @@ -8212,7 +8212,7 @@ under the License. systemvmtype consoleproxy - + zoneid globalzoneid @@ -8270,7 +8270,7 @@ under the License. state Stopped - + @@ -8358,7 +8358,7 @@ under the License. state Running - + @@ -8384,7 +8384,7 @@ under the License. privateisoid - + diff --git a/test/metadata/func/resource_limits.xml b/test/metadata/func/resource_limits.xml index e503a03666d..838ec93144a 100644 --- a/test/metadata/func/resource_limits.xml +++ b/test/metadata/func/resource_limits.xml @@ -79,17 +79,17 @@ under the License. account accountname - + id userid - + - - + updateResourceLimit Setup VMs Limit for Account Test Case @@ -166,10 +166,10 @@ under the License. 2 - + - + updateResourceLimit Setup Public-Ips Limit for Account Test Case @@ -200,10 +200,10 @@ under the License. 1 - - + + - + updateResourceLimit Setup Volumes Limit for Account Test Case @@ -234,10 +234,10 @@ under the License. 6 - + - + updateResourceLimit Setup Snapshots Limit for Account Test Case @@ -268,7 +268,7 @@ under the License. 2 - + @@ -302,9 +302,9 @@ under the License. 2 - - - + + + registerUserKeys @@ -325,8 +325,8 @@ under the License. secretkey - - + + createNetwork [Creating default network] @@ -374,7 +374,7 @@ under the License. diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -386,11 +386,11 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 @@ -406,7 +406,7 @@ under the License. networkids networkid - + @@ -424,7 +424,7 @@ under the License. diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -436,15 +436,15 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 - + displayname ResourceLimits-VM-2 @@ -465,38 +465,38 @@ under the License. - + - associateIpAddress + associateIpAddress Associate second IP Test Case true - + zoneid globalzoneid - + account accountname - + domainid 1 - + - + ipaddress ipid - - - + + + @@ -504,7 +504,7 @@ under the License. createVolume Create Fifth Volume Test Case true - + name @@ -513,29 +513,29 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 - + diskofferingid globaldiskofferingid - + - + id volid1 - - + + attachVolume @@ -550,7 +550,7 @@ under the License. - + createVolume Create Sixth Volume Test Case @@ -563,19 +563,19 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 - + diskofferingid globaldiskofferingid - + @@ -583,7 +583,7 @@ under the License. volid2 - + @@ -599,7 +599,7 @@ under the License. - + createSnapshot @@ -635,7 +635,7 @@ under the License. snpid - + @@ -666,7 +666,7 @@ under the License. zoneid globalzoneid - + account accountname @@ -678,7 +678,7 @@ under the License. hypervisor globalhypervisortype - + @@ -716,7 +716,7 @@ under the License. zoneid globalzoneid - + account accountname @@ -728,7 +728,7 @@ under the License. hypervisor globalhypervisortype - + @@ -749,7 +749,7 @@ under the License. diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -761,11 +761,11 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 @@ -773,7 +773,7 @@ under the License. networkids network - + @@ -782,11 +782,11 @@ under the License. - + - associateIpAddress + associateIpAddress Associate Second IP Failure Test Case true true @@ -794,25 +794,25 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 - + - + ipaddress ipid - - + + @@ -829,29 +829,29 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 - + diskofferingid globaldiskofferingid - + - + id volid3 - - + + listVolumes @@ -873,7 +873,7 @@ under the License. - + createSnapshot Create Third Snapshot Failure Test Case @@ -924,7 +924,7 @@ under the License. zoneid globalzoneid - + account accountname @@ -936,7 +936,7 @@ under the License. hypervisor globalhypervisortype - + @@ -950,14 +950,14 @@ under the License. deleteAccount Clean up account test case - + id accountname - + @@ -1023,15 +1023,15 @@ under the License. account accountname - + id userid - + - - + updateResourceLimit Failure in Setting Up VMs Limit for Admin Account Test Case true @@ -1108,10 +1108,10 @@ under the License. 2 - + - + updateResourceLimit Failure in Setting Up Public-Ips Limit for Admin Account Test Case true @@ -1143,10 +1143,10 @@ under the License. 1 - - + + - + updateResourceLimit Failure in Setting Up Volumes Limit for Admin Account Test Case true @@ -1178,10 +1178,10 @@ under the License. 6 - + - + updateResourceLimit Failure in Setting up Snapshots Limit for Admin Account Test Case true @@ -1248,9 +1248,9 @@ under the License. 2 - - - + + + registerUserKeys @@ -1271,7 +1271,7 @@ under the License. secretkey - + createNetwork @@ -1309,7 +1309,7 @@ under the License. - + @@ -1320,7 +1320,7 @@ under the License. diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -1332,11 +1332,11 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 @@ -1352,7 +1352,7 @@ under the License. networkids networkid - + @@ -1370,7 +1370,7 @@ under the License. diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -1382,11 +1382,11 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 @@ -1402,7 +1402,7 @@ under the License. networkids networkid - + @@ -1411,43 +1411,43 @@ under the License. - + - associateIpAddress + associateIpAddress Associate second IP Test Case true - + zoneid globalzoneid - + account accountname - + domainid 1 - + - + ipaddress ipid - - + + createVolume Create Fifth Volume Test Case true - + name @@ -1456,30 +1456,30 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 - + diskofferingid globaldiskofferingid - + - + id volid1 - - - + + + attachVolume @@ -1492,8 +1492,8 @@ under the License. vmid1 - - + + createVolume Create Sixth Volume Test Case @@ -1506,19 +1506,19 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 - + diskofferingid globaldiskofferingid - + @@ -1526,7 +1526,7 @@ under the License. volid2 - + @@ -1542,7 +1542,7 @@ under the License. - + createSnapshot @@ -1609,7 +1609,7 @@ under the License. zoneid globalzoneid - + account accountname @@ -1621,7 +1621,7 @@ under the License. hypervisor globalhypervisortype - + @@ -1659,7 +1659,7 @@ under the License. zoneid globalzoneid - + account accountname @@ -1671,7 +1671,7 @@ under the License. hypervisor globalhypervisortype - + @@ -1687,12 +1687,12 @@ under the License. deployVirtualMachine Deploy VM3 Failure Avoidance test case true - + diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -1704,11 +1704,11 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 @@ -1724,7 +1724,7 @@ under the License. networkids networkid - + @@ -1733,37 +1733,37 @@ under the License. - + - associateIpAddress + associateIpAddress Associate Second IP Failure Avoidance Test Case true - + zoneid globalzoneid - + account accountname - + domainid 1 - + - + ipaddress ipid - - + + @@ -1771,7 +1771,7 @@ under the License. createVolume Create Seventh Volume Failure Avoidance Test Case true - + name @@ -1780,31 +1780,31 @@ under the License. zoneid globalzoneid - + account accountname - + domainid 1 - + diskofferingid globaldiskofferingid - + - + id volid3 - - - + + + createSnapshot Create Third Snapshot Failure Test Case @@ -1855,7 +1855,7 @@ under the License. zoneid globalzoneid - + account accountname @@ -1867,8 +1867,8 @@ under the License. hypervisor globalhypervisortype - - + + @@ -1882,13 +1882,13 @@ under the License. deleteAccount Clean up admin account test case - + id accountid - + diff --git a/test/metadata/func/roughflatstress.xml b/test/metadata/func/roughflatstress.xml index 841190c496f..291d434348a 100644 --- a/test/metadata/func/roughflatstress.xml +++ b/test/metadata/func/roughflatstress.xml @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. --> - + createAccount [Create the Account and a User for the account] @@ -66,7 +66,7 @@ under the License. - + listUsers [List the User of the account] @@ -99,7 +99,7 @@ under the License. - + registerUserKeys Registering the First User @@ -120,7 +120,7 @@ under the License. - + createSecurityGroup true @@ -149,7 +149,7 @@ under the License. - + authorizeSecurityGroupIngress true @@ -185,7 +185,7 @@ under the License. --> - + listSecurityGroups true @@ -211,7 +211,7 @@ under the License. - + deployVirtualMachine true @@ -244,7 +244,7 @@ under the License. domainid globaldomainid - + --> @@ -254,10 +254,10 @@ under the License. ipaddress getvmip1 - + - + sleep.sh @@ -268,8 +268,8 @@ under the License. 120 - - + + ssh.sh @@ -285,7 +285,7 @@ under the License. - + sleep.sh @@ -296,8 +296,8 @@ under the License. 60 - - + + revokeSecurityGroupIngress true @@ -309,7 +309,7 @@ under the License. - +--> - + createSecurityGroup true @@ -358,7 +358,7 @@ under the License. - + authorizeSecurityGroupIngress true @@ -375,7 +375,7 @@ under the License. usersecuritygrouplist[0].group getsecuritygroupname1 - + endport 22 @@ -398,8 +398,8 @@ under the License. --> - - + + authorizeSecurityGroupIngress true @@ -435,7 +435,7 @@ under the License. --> - + listSecurityGroups true @@ -461,7 +461,7 @@ under the License. - + deployVirtualMachine true @@ -494,7 +494,7 @@ under the License. domainid globaldomainid - + --> @@ -504,10 +504,10 @@ under the License. ipaddress getvmip2 - + - + sleep.sh @@ -518,8 +518,8 @@ under the License. 120 - - + + ssh.sh @@ -535,7 +535,7 @@ under the License. - + sleep.sh @@ -546,8 +546,8 @@ under the License. 60 - - + + revokeSecurityGroupIngress true @@ -559,7 +559,7 @@ under the License. - + listSecurityGroups true @@ -585,7 +585,7 @@ under the License. - + revokeSecurityGroupIngress true @@ -597,8 +597,8 @@ under the License. - - +--> destroyVirtualMachine true @@ -627,7 +627,7 @@ under the License. - + sleep.sh @@ -651,7 +651,7 @@ under the License. - + sleep.sh @@ -663,9 +663,9 @@ under the License. - - - + + + deleteUser Deleting the user @@ -675,8 +675,8 @@ under the License. getuserid1 - - + + deleteAccount Delete Account @@ -686,6 +686,6 @@ under the License. getaccountid - - + + diff --git a/test/metadata/func/roughregression.xml b/test/metadata/func/roughregression.xml index f6de2323557..64c120a8bd4 100644 --- a/test/metadata/func/roughregression.xml +++ b/test/metadata/func/roughregression.xml @@ -199,7 +199,7 @@ under the License. domain getdomainname1 - + @@ -243,7 +243,7 @@ under the License. - + @@ -380,7 +380,7 @@ under the License. - + createUser @@ -417,7 +417,7 @@ under the License. domainid globaldomainid - + @@ -794,7 +794,7 @@ under the License. state locked - + @@ -810,7 +810,7 @@ under the License. domainid globaldomainid - + @@ -912,7 +912,7 @@ under the License. state enabled - + @@ -974,7 +974,7 @@ under the License. vmavailable Unlimited - + ipavailable Unlimited @@ -1034,7 +1034,7 @@ under the License. state disabled - + @@ -1050,7 +1050,7 @@ under the License. domainid globaldomainid - + @@ -1152,7 +1152,7 @@ under the License. state enabled - + @@ -1189,7 +1189,7 @@ under the License. getdomainname2 - + id @@ -1261,8 +1261,8 @@ under the License. false - - + + @@ -1274,7 +1274,7 @@ under the License. globaldomainid - + domain 0 @@ -1304,7 +1304,7 @@ under the License. - + deleteDomain @@ -1319,7 +1319,7 @@ under the License. true - + success @@ -1342,7 +1342,7 @@ under the License. 1 - + template 0 @@ -1396,7 +1396,7 @@ under the License. size - debian50templatesize + debian50templatesize account @@ -1429,7 +1429,7 @@ under the License. domainid 1 - + @@ -1636,7 +1636,7 @@ under the License. offerha false - + @@ -1672,7 +1672,7 @@ under the License. vlan - guestcidraddress + guestcidraddress networktype @@ -1680,7 +1680,7 @@ under the License. - + @@ -1770,7 +1770,7 @@ under the License. - + deployVirtualMachine [2] deployVirtualMachine-TestCase @@ -1814,7 +1814,7 @@ under the License. domainid globaldomainid - + @@ -1823,7 +1823,7 @@ under the License. - + updateVirtualMachine [3] updateVirtualMachine-TestCase @@ -1850,9 +1850,9 @@ under the License. - + - + associateIpAddress [4] associateIpAddress-TestCase @@ -1881,7 +1881,7 @@ under the License. - + enableStaticNat [5] enableStaticNat-TestCase @@ -1896,7 +1896,7 @@ under the License. - + createIpForwardingRule [6] createIpForwardingRule-TestCase @@ -1922,10 +1922,10 @@ under the License. id getipfwdruleid1 - + - + sleep.sh @@ -1936,8 +1936,8 @@ under the License. 120 - - + + ssh.sh @@ -1953,7 +1953,7 @@ under the License. - + deleteIpForwardingRule [7] deleteIpForwardingRule-TestCase @@ -1964,7 +1964,7 @@ under the License. - + disableStaticNat [8] disableStaticNat-TestCase @@ -1975,7 +1975,7 @@ under the License. - + disassociateIpAddress [9] disassociateIpAddress-TestCase @@ -1986,7 +1986,7 @@ under the License. - + associateIpAddress [10] associateIpAddress-TestCase @@ -2015,7 +2015,7 @@ under the License. - + createPortForwardingRule [11] createPortForwardingRule-TestCase @@ -2058,7 +2058,7 @@ under the License. id getportfwdruleid1 - + @@ -2073,8 +2073,8 @@ under the License. 120 - - + + ssh.sh @@ -2090,7 +2090,7 @@ under the License. - + deletePortForwardingRule [12] deletePortForwardingRule-TestCase @@ -2101,7 +2101,7 @@ under the License. - + disassociateIpAddress [13] disassociateIpAddress-TestCase @@ -2112,7 +2112,7 @@ under the License. - + associateIpAddress [14] associateIpAddress-TestCase @@ -2141,7 +2141,7 @@ under the License. - + createLoadBalancerRule [15] createLoadBalancerRule-TestCase @@ -2174,7 +2174,7 @@ under the License. - + assignToLoadBalancerRule [16] assignToLoadBalancerRule-TestCase @@ -2189,7 +2189,7 @@ under the License. - + listVolumes @@ -2384,7 +2384,7 @@ under the License. - + createSnapshot [26] createSnapshotofROOTVolume-TestCase @@ -2409,7 +2409,7 @@ under the License. - + listSnapshots [27] listROOTVolumeSnapshot-TestCase @@ -2420,7 +2420,7 @@ under the License. - + listVolumes [26] listDATADISKVolumes-TestCase @@ -2466,7 +2466,7 @@ under the License. - + listSnapshots [29] listDATADISKVolumeSnapshot-TestCase @@ -2477,7 +2477,7 @@ under the License. - + createTemplate [30] createTemplateFromSnapshotTakenofROOTVolume-TestCase @@ -2518,7 +2518,7 @@ under the License. - + createTemplate [31] createTemplateFromSnapshotTakenofDATADISKVolume-TestCase @@ -2559,7 +2559,7 @@ under the License. - + createVolume [32] createVolumeFromSnapshotTakenofROOTVolume-TestCase @@ -2588,7 +2588,7 @@ under the License. - + createVolume [33] createVolumeFromSnapshotTakenofDATADISKVolume-TestCase @@ -2618,7 +2618,7 @@ under the License. - + attachVolume [34] attachVolume1-TestCase @@ -2633,7 +2633,7 @@ under the License. - + attachVolume [35] attachVolume2-TestCase @@ -2648,9 +2648,9 @@ under the License. - + - + detachVolume [36] detachVolume1-TestCase @@ -2661,7 +2661,7 @@ under the License. - + detachVolume [37] detachVolume2-TestCase @@ -2672,7 +2672,7 @@ under the License. - + attachVolume [34] attachVolume1-TestCase @@ -2687,7 +2687,7 @@ under the License. - + attachVolume [35] attachVolume2-TestCase @@ -2702,7 +2702,7 @@ under the License. - + stopVirtualMachine [40] stopVirtualMachine-TestCase @@ -2713,7 +2713,7 @@ under the License. - + updateVirtualMachine [41] updateVirtualMachine-TestCase @@ -2740,7 +2740,7 @@ under the License. - + detachVolume [36] detachVolume1-TestCase @@ -2751,7 +2751,7 @@ under the License. - + detachVolume [37] detachVolume2-TestCase @@ -2762,7 +2762,7 @@ under the License. - + createTemplate [44] createTemplateFromROOTVolume-TestCase @@ -2799,7 +2799,7 @@ under the License. - + startVirtualMachine [45] startVirtualMachine-TestCase @@ -2810,7 +2810,7 @@ under the License. - + rebootVirtualMachine [46] rebootVirtualMachine-TestCase @@ -2821,7 +2821,7 @@ under the License. - + createSnapshotPolicy [47] createHOURLYSnapshotPolicyForRootVolume-TestCase @@ -2848,7 +2848,7 @@ under the License. - + createSnapshotPolicy [48] createDAILYSnapshotPolicy-TestCase @@ -2875,7 +2875,7 @@ under the License. - + createSnapshotPolicy [49] createWEEKLYSnapshotPolicy-TestCase @@ -2902,7 +2902,7 @@ under the License. - + createSnapshotPolicy [50] createMONTHLYSnapshotPolicy-TestCase @@ -2935,7 +2935,7 @@ under the License. - + deleteSnapshotPolicies [51] deleteMONTHLYSnapshotPolicies-TestCase @@ -2946,7 +2946,7 @@ under the License. - + deleteVolume [52] deleteVolume1-TestCase @@ -2957,7 +2957,7 @@ under the License. - + deleteVolume [53] deleteVolume2-TestCase @@ -2970,7 +2970,7 @@ under the License. - + destroyVirtualMachine [54] destroyVirtualMachine-TestCase @@ -2981,7 +2981,7 @@ under the License. - + recoverVirtualMachine [55] recoverVirtualMachine-TestCase @@ -2992,7 +2992,7 @@ under the License. - + startVirtualMachine [56] startVirtualMachine-TestCase @@ -3003,7 +3003,7 @@ under the License. - + rebootVirtualMachine [57] rebootVirtualMachine-TestCase @@ -3014,7 +3014,7 @@ under the License. - + stopVirtualMachine [58] stopVirtualMachine-TestCase @@ -3025,7 +3025,7 @@ under the License. - + destroyVirtualMachine [59] destroyVirtualMachine-TestCase @@ -3036,7 +3036,7 @@ under the License. - + recoverVirtualMachine [60] recoverVirtualMachine-TestCase @@ -3047,7 +3047,7 @@ under the License. - + changeServiceForVirtualMachine [61] changeServiceForVirtualMachine-TestCase @@ -3062,7 +3062,7 @@ under the License. - + startVirtualMachine [62] startVirtualMachine-TestCase @@ -3073,7 +3073,7 @@ under the License. - + rebootVirtualMachine [63] rebootVirtualMachine-TestCase @@ -3084,7 +3084,7 @@ under the License. - + stopVirtualMachine [64] stopVirtualMachine-TestCase @@ -3095,7 +3095,7 @@ under the License. - + destroyVirtualMachine [65] destroyVirtualMachine-TestCase @@ -3106,7 +3106,7 @@ under the License. - + deployVirtualMachine [66] deployVirtualMachineFromTemplateCreatedFromSnapshotofROOTVolume-TestCase @@ -3166,7 +3166,7 @@ under the License. - + deleteTemplate [68] deleteTemplateofSnapshotTakenofDATAVolume-TestCase @@ -3181,7 +3181,7 @@ under the License. - + deleteTemplate [69] deleteTemplateCreatedFromROOTVolume-TestCase @@ -3196,7 +3196,7 @@ under the License. - + deleteSnapshot [70] deleteSnapshot-TestCase @@ -3207,7 +3207,7 @@ under the License. - + deleteSnapshot [71] deleteSnapshot-TestCase @@ -3248,9 +3248,9 @@ under the License. - + - + associateIpAddress [4] associateIpAddress-TestCase @@ -3279,7 +3279,7 @@ under the License. - + enableStaticNat [5] enableStaticNat-TestCase @@ -3294,7 +3294,7 @@ under the License. - + createIpForwardingRule [6] createIpForwardingRule-TestCase @@ -3320,10 +3320,10 @@ under the License. id getipfwdruleid1 - + - + sleep.sh @@ -3334,8 +3334,8 @@ under the License. 120 - - + + ssh.sh @@ -3351,7 +3351,7 @@ under the License. - + deleteIpForwardingRule [7] deleteIpForwardingRule-TestCase @@ -3362,7 +3362,7 @@ under the License. - + disableStaticNat [8] disableStaticNat-TestCase @@ -3373,7 +3373,7 @@ under the License. - + disassociateIpAddress [9] disassociateIpAddress-TestCase @@ -3384,7 +3384,7 @@ under the License. - + associateIpAddress [10] associateIpAddress-TestCase @@ -3413,7 +3413,7 @@ under the License. - + createPortForwardingRule [11] createPortForwardingRule-TestCase @@ -3456,7 +3456,7 @@ under the License. id getportfwdruleid1 - + @@ -3471,8 +3471,8 @@ under the License. 120 - - + + ssh.sh @@ -3488,7 +3488,7 @@ under the License. - + deletePortForwardingRule [12] deletePortForwardingRule-TestCase @@ -3499,7 +3499,7 @@ under the License. - + disassociateIpAddress [13] disassociateIpAddress-TestCase @@ -3510,7 +3510,7 @@ under the License. - + associateIpAddress [14] associateIpAddress-TestCase @@ -3539,7 +3539,7 @@ under the License. - + createLoadBalancerRule [15] createLoadBalancerRule-TestCase @@ -3572,7 +3572,7 @@ under the License. - + assignToLoadBalancerRule [16] assignToLoadBalancerRule-TestCase @@ -3587,7 +3587,7 @@ under the License. - + +--> deleteLoadBalancerRule [24] deleteLoadBalancerRule-TestCase @@ -3745,10 +3745,10 @@ under the License. id getldblcrule1 - + - + disassociateIpAddress [25] disassociateIpAddress-TestCase @@ -3759,7 +3759,7 @@ under the License. - + listVolumes @@ -3781,7 +3781,7 @@ under the License. - + createSnapshot [26] createSnapshotofROOTVolume-TestCase @@ -3806,7 +3806,7 @@ under the License. - + listSnapshots [27] listROOTVolumeSnapshot-TestCase @@ -3817,7 +3817,7 @@ under the License. - + listVolumes [26] listDATADISKVolumes-TestCase @@ -3863,7 +3863,7 @@ under the License. - + listSnapshots [29] listDATADISKVolumeSnapshot-TestCase @@ -3874,7 +3874,7 @@ under the License. - + createTemplate [30] createTemplateFromSnapshotTakenofROOTVolume-TestCase @@ -3915,7 +3915,7 @@ under the License. - + createTemplate [31] createTemplateFromSnapshotTakenofDATADISKVolume-TestCase @@ -3956,7 +3956,7 @@ under the License. - + createVolume [32] createVolumeFromSnapshotTakenofROOTVolume-TestCase @@ -3985,7 +3985,7 @@ under the License. - + createVolume [33] createVolumeFromSnapshotTakenofDATADISKVolume-TestCase @@ -4015,7 +4015,7 @@ under the License. - + attachVolume [34] attachVolume1-TestCase @@ -4030,7 +4030,7 @@ under the License. - + attachVolume [35] attachVolume2-TestCase @@ -4045,9 +4045,9 @@ under the License. - + - + detachVolume [36] detachVolume1-TestCase @@ -4058,7 +4058,7 @@ under the License. - + detachVolume [37] detachVolume2-TestCase @@ -4069,7 +4069,7 @@ under the License. - + attachVolume [34] attachVolume1-TestCase @@ -4084,7 +4084,7 @@ under the License. - + attachVolume [35] attachVolume2-TestCase @@ -4099,7 +4099,7 @@ under the License. - + stopVirtualMachine [40] stopVirtualMachine-TestCase @@ -4110,7 +4110,7 @@ under the License. - + updateVirtualMachine [41] updateVirtualMachine-TestCase @@ -4137,7 +4137,7 @@ under the License. - + detachVolume [36] detachVolume1-TestCase @@ -4148,7 +4148,7 @@ under the License. - + detachVolume [37] detachVolume2-TestCase @@ -4159,7 +4159,7 @@ under the License. - + createTemplate [44] createTemplateFromROOTVolume-TestCase @@ -4196,7 +4196,7 @@ under the License. - + startVirtualMachine [45] startVirtualMachine-TestCase @@ -4207,7 +4207,7 @@ under the License. - + rebootVirtualMachine [46] rebootVirtualMachine-TestCase @@ -4218,7 +4218,7 @@ under the License. - + createSnapshotPolicy [47] createHOURLYSnapshotPolicyForRootVolume-TestCase @@ -4245,7 +4245,7 @@ under the License. - + createSnapshotPolicy [48] createDAILYSnapshotPolicy-TestCase @@ -4272,7 +4272,7 @@ under the License. - + createSnapshotPolicy [49] createWEEKLYSnapshotPolicy-TestCase @@ -4299,7 +4299,7 @@ under the License. - + createSnapshotPolicy [50] createMONTHLYSnapshotPolicy-TestCase @@ -4332,7 +4332,7 @@ under the License. - + deleteSnapshotPolicies [51] deleteMONTHLYSnapshotPolicies-TestCase @@ -4343,7 +4343,7 @@ under the License. - + deleteVolume [52] deleteVolume1-TestCase @@ -4354,7 +4354,7 @@ under the License. - + deleteVolume [53] deleteVolume2-TestCase @@ -4367,7 +4367,7 @@ under the License. - + destroyVirtualMachine [54] destroyVirtualMachine-TestCase @@ -4378,7 +4378,7 @@ under the License. - + recoverVirtualMachine [55] recoverVirtualMachine-TestCase @@ -4389,7 +4389,7 @@ under the License. - + startVirtualMachine [56] startVirtualMachine-TestCase @@ -4400,7 +4400,7 @@ under the License. - + rebootVirtualMachine [57] rebootVirtualMachine-TestCase @@ -4411,7 +4411,7 @@ under the License. - + stopVirtualMachine [58] stopVirtualMachine-TestCase @@ -4422,7 +4422,7 @@ under the License. - + destroyVirtualMachine [59] destroyVirtualMachine-TestCase @@ -4433,7 +4433,7 @@ under the License. - + recoverVirtualMachine [60] recoverVirtualMachine-TestCase @@ -4444,7 +4444,7 @@ under the License. - + changeServiceForVirtualMachine [61] changeServiceForVirtualMachine-TestCase @@ -4459,7 +4459,7 @@ under the License. - + startVirtualMachine [62] startVirtualMachine-TestCase @@ -4470,7 +4470,7 @@ under the License. - + rebootVirtualMachine [63] rebootVirtualMachine-TestCase @@ -4481,7 +4481,7 @@ under the License. - + stopVirtualMachine [64] stopVirtualMachine-TestCase @@ -4492,7 +4492,7 @@ under the License. - + destroyVirtualMachine [65] destroyVirtualMachine-TestCase @@ -4503,7 +4503,7 @@ under the License. - + @@ -4511,7 +4511,7 @@ under the License. - + - + associateIpAddress [4] associateIpAddress-TestCase @@ -4623,7 +4623,7 @@ under the License. - + enableStaticNat [5] enableStaticNat-TestCase @@ -4638,7 +4638,7 @@ under the License. - + createIpForwardingRule [6] createIpForwardingRule-TestCase @@ -4664,10 +4664,10 @@ under the License. id getipfwdruleid1 - + - + sleep.sh @@ -4678,8 +4678,8 @@ under the License. 120 - - + + ssh.sh @@ -4695,7 +4695,7 @@ under the License. - + deleteIpForwardingRule [7] deleteIpForwardingRule-TestCase @@ -4706,7 +4706,7 @@ under the License. - + disableStaticNat [8] disableStaticNat-TestCase @@ -4717,7 +4717,7 @@ under the License. - + disassociateIpAddress [9] disassociateIpAddress-TestCase @@ -4728,7 +4728,7 @@ under the License. - + associateIpAddress [10] associateIpAddress-TestCase @@ -4757,7 +4757,7 @@ under the License. - + createPortForwardingRule [11] createPortForwardingRule-TestCase @@ -4800,7 +4800,7 @@ under the License. id getportfwdruleid1 - + @@ -4815,8 +4815,8 @@ under the License. 120 - - + + ssh.sh @@ -4832,7 +4832,7 @@ under the License. - + deletePortForwardingRule [12] deletePortForwardingRule-TestCase @@ -4843,7 +4843,7 @@ under the License. - + disassociateIpAddress [13] disassociateIpAddress-TestCase @@ -4854,7 +4854,7 @@ under the License. - + associateIpAddress [14] associateIpAddress-TestCase @@ -4883,7 +4883,7 @@ under the License. - + createLoadBalancerRule [15] createLoadBalancerRule-TestCase @@ -4916,7 +4916,7 @@ under the License. - + assignToLoadBalancerRule [16] assignToLoadBalancerRule-TestCase @@ -4931,7 +4931,7 @@ under the License. - + listVolumes @@ -5126,7 +5126,7 @@ under the License. - + createSnapshot [26] createSnapshotofROOTVolume-TestCase @@ -5151,7 +5151,7 @@ under the License. - + listSnapshots [27] listROOTVolumeSnapshot-TestCase @@ -5162,7 +5162,7 @@ under the License. - + listVolumes [26] listDATADISKVolumes-TestCase @@ -5208,7 +5208,7 @@ under the License. - + listSnapshots [29] listDATADISKVolumeSnapshot-TestCase @@ -5219,7 +5219,7 @@ under the License. - + createTemplate [30] createTemplateFromSnapshotTakenofROOTVolume-TestCase @@ -5260,7 +5260,7 @@ under the License. - + createTemplate [31] createTemplateFromSnapshotTakenofDATADISKVolume-TestCase @@ -5301,7 +5301,7 @@ under the License. - + createVolume [32] createVolumeFromSnapshotTakenofROOTVolume-TestCase @@ -5330,7 +5330,7 @@ under the License. - + createVolume [33] createVolumeFromSnapshotTakenofDATADISKVolume-TestCase @@ -5360,7 +5360,7 @@ under the License. - + attachVolume [34] attachVolume1-TestCase @@ -5375,7 +5375,7 @@ under the License. - + attachVolume [35] attachVolume2-TestCase @@ -5390,9 +5390,9 @@ under the License. - + - + detachVolume [36] detachVolume1-TestCase @@ -5403,7 +5403,7 @@ under the License. - + detachVolume [37] detachVolume2-TestCase @@ -5414,7 +5414,7 @@ under the License. - + attachVolume [34] attachVolume1-TestCase @@ -5429,7 +5429,7 @@ under the License. - + attachVolume [35] attachVolume2-TestCase @@ -5444,7 +5444,7 @@ under the License. - + stopVirtualMachine [40] stopVirtualMachine-TestCase @@ -5455,7 +5455,7 @@ under the License. - + updateVirtualMachine [41] updateVirtualMachine-TestCase @@ -5482,7 +5482,7 @@ under the License. - + detachVolume [36] detachVolume1-TestCase @@ -5493,7 +5493,7 @@ under the License. - + detachVolume [37] detachVolume2-TestCase @@ -5504,7 +5504,7 @@ under the License. - + createTemplate [44] createTemplateFromROOTVolume-TestCase @@ -5541,7 +5541,7 @@ under the License. - + startVirtualMachine [45] startVirtualMachine-TestCase @@ -5552,7 +5552,7 @@ under the License. - + rebootVirtualMachine [46] rebootVirtualMachine-TestCase @@ -5563,7 +5563,7 @@ under the License. - + createSnapshotPolicy [47] createHOURLYSnapshotPolicyForRootVolume-TestCase @@ -5590,7 +5590,7 @@ under the License. - + createSnapshotPolicy [48] createDAILYSnapshotPolicy-TestCase @@ -5617,7 +5617,7 @@ under the License. - + createSnapshotPolicy [49] createWEEKLYSnapshotPolicy-TestCase @@ -5644,7 +5644,7 @@ under the License. - + createSnapshotPolicy [50] createMONTHLYSnapshotPolicy-TestCase @@ -5677,7 +5677,7 @@ under the License. - + deleteSnapshotPolicies [51] deleteMONTHLYSnapshotPolicies-TestCase @@ -5688,7 +5688,7 @@ under the License. - + deleteVolume [52] deleteVolume1-TestCase @@ -5699,7 +5699,7 @@ under the License. - + deleteVolume [53] deleteVolume2-TestCase @@ -5712,7 +5712,7 @@ under the License. - + destroyVirtualMachine [54] destroyVirtualMachine-TestCase @@ -5723,7 +5723,7 @@ under the License. - + recoverVirtualMachine [55] recoverVirtualMachine-TestCase @@ -5734,7 +5734,7 @@ under the License. - + startVirtualMachine [56] startVirtualMachine-TestCase @@ -5745,7 +5745,7 @@ under the License. - + rebootVirtualMachine [57] rebootVirtualMachine-TestCase @@ -5756,7 +5756,7 @@ under the License. - + stopVirtualMachine [58] stopVirtualMachine-TestCase @@ -5767,7 +5767,7 @@ under the License. - + destroyVirtualMachine [59] destroyVirtualMachine-TestCase @@ -5778,7 +5778,7 @@ under the License. - + recoverVirtualMachine [60] recoverVirtualMachine-TestCase @@ -5789,7 +5789,7 @@ under the License. - + changeServiceForVirtualMachine [61] changeServiceForVirtualMachine-TestCase @@ -5804,7 +5804,7 @@ under the License. - + startVirtualMachine [62] startVirtualMachine-TestCase @@ -5815,7 +5815,7 @@ under the License. - + rebootVirtualMachine [63] rebootVirtualMachine-TestCase @@ -5826,7 +5826,7 @@ under the License. - + stopVirtualMachine [64] stopVirtualMachine-TestCase @@ -5837,7 +5837,7 @@ under the License. - + destroyVirtualMachine [65] destroyVirtualMachine-TestCase @@ -5848,7 +5848,7 @@ under the License. - + deployVirtualMachine [66] deployVirtualMachineFromTemplateCreatedFromSnapshotofROOTVolume-TestCase @@ -5908,7 +5908,7 @@ under the License. - + deleteTemplate [68] deleteTemplateofSnapshotTakenofDATAVolume-TestCase @@ -5923,7 +5923,7 @@ under the License. - + deleteTemplate [69] deleteTemplateCreatedFromROOTVolume-TestCase @@ -5938,7 +5938,7 @@ under the License. - + deleteSnapshot [70] deleteSnapshot-TestCase @@ -5949,7 +5949,7 @@ under the License. - + deleteSnapshot [71] deleteSnapshot-TestCase @@ -6008,5 +6008,5 @@ under the License. getaccountid - - + + diff --git a/test/metadata/func/sanity.xml b/test/metadata/func/sanity.xml index 3094abd136d..6316ed6d2ed 100644 --- a/test/metadata/func/sanity.xml +++ b/test/metadata/func/sanity.xml @@ -18,7 +18,7 @@ under the License. --> - @@ -84,7 +84,7 @@ under the License. - + createNetwork @@ -122,7 +122,7 @@ under the License. - + deployVirtualMachine [Deploy a Virtual Machine under the Account] @@ -167,8 +167,8 @@ under the License. - - + + associateIpAddress [Acquire an IP Address (Non-Source NAT*)] @@ -190,14 +190,14 @@ under the License. id nonsourcenatpublicipid - + ipaddress nonsourcenatpublicip - + disassociateIpAddress [Release the IP Address (Non-Source NAT*)] @@ -208,7 +208,7 @@ under the License. - + rebootVirtualMachine [Reboot Virtual Machine] @@ -219,7 +219,7 @@ under the License. - + stopVirtualMachine [Stop virtual machine] @@ -230,7 +230,7 @@ under the License. - + startVirtualMachine [Start virtual machine] @@ -247,8 +247,8 @@ under the License. - - + + listRouters [List Routers] @@ -272,9 +272,9 @@ under the License. routerid - - - + + + stopRouter [Stop router] @@ -313,7 +313,7 @@ under the License. - + listVirtualMachines [Verify that vm was destroyed] @@ -330,7 +330,7 @@ under the License. - + recoverVirtualMachine [Recover virtual machine] @@ -341,7 +341,7 @@ under the License. - + listVirtualMachines [Verify that machine was recovered] @@ -362,7 +362,7 @@ under the License. - + deleteAccount [Delete account] @@ -372,7 +372,7 @@ under the License. accountid - - - + + + diff --git a/test/metadata/func/securitygroups.xml b/test/metadata/func/securitygroups.xml index 3ecffbf8467..55fc32aa270 100644 --- a/test/metadata/func/securitygroups.xml +++ b/test/metadata/func/securitygroups.xml @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. --> - @@ -78,7 +78,7 @@ under the License. - + registerUserKeys Registering the User @@ -99,7 +99,7 @@ under the License. - + createNetworkGroup true @@ -113,7 +113,7 @@ under the License. - + authorizeNetworkGroupIngress Add the First Ingress Rule @@ -148,7 +148,7 @@ under the License. - + deployVirtualMachine true @@ -182,7 +182,7 @@ under the License. - + sleep.sh @@ -193,8 +193,8 @@ under the License. 120 - - + + ssh.sh @@ -210,7 +210,7 @@ under the License. - + sleep.sh @@ -221,8 +221,8 @@ under the License. 60 - - + + stopVirtualMachine true @@ -234,7 +234,7 @@ under the License. - + startVirtualMachine true @@ -246,7 +246,7 @@ under the License. - + rebootVirtualMachine true @@ -293,7 +293,7 @@ under the License. - + ssh.sh @@ -310,9 +310,9 @@ under the License. - + - + authorizeNetworkGroupIngress Add the Second Ingress Rule @@ -347,7 +347,7 @@ under the License. - + deployVirtualMachine true @@ -381,7 +381,7 @@ under the License. - + sleep.sh @@ -392,8 +392,8 @@ under the License. 120 - - + + ssh.sh @@ -410,7 +410,7 @@ under the License. - + revokeNetworkGroupIngress Revoke The Second Ingress Rule @@ -447,7 +447,7 @@ under the License. - + authorizeNetworkGroupIngress Add the Third Ingress Rule @@ -482,7 +482,7 @@ under the License. - + deployVirtualMachine true @@ -516,7 +516,7 @@ under the License. - + sleep.sh @@ -527,8 +527,8 @@ under the License. 120 - - + + ssh.sh @@ -545,7 +545,7 @@ under the License. - + revokeNetworkGroupIngress Revoke The Third Ingress Rule @@ -580,9 +580,9 @@ under the License. - + - + authorizeNetworkGroupIngress Add the Fourth Ingress Rule @@ -617,7 +617,7 @@ under the License. - + deployVirtualMachine true @@ -651,7 +651,7 @@ under the License. - + sleep.sh @@ -662,8 +662,8 @@ under the License. 120 - - + + ssh.sh @@ -680,7 +680,7 @@ under the License. - + revokeNetworkGroupIngress Revoke The Fourth Ingress Rule @@ -715,8 +715,8 @@ under the License. - - + + deleteNetworkGroup @@ -729,7 +729,7 @@ under the License. - + destroyVirtualMachine true @@ -741,7 +741,7 @@ under the License. - + sleep.sh @@ -752,10 +752,10 @@ under the License. 120 - - - - + + + + deleteUser Deleting the user @@ -765,6 +765,6 @@ under the License. userid - + diff --git a/test/metadata/func/sharedstorage_volume_test.xml b/test/metadata/func/sharedstorage_volume_test.xml index c34afc47baf..697887998ec 100644 --- a/test/metadata/func/sharedstorage_volume_test.xml +++ b/test/metadata/func/sharedstorage_volume_test.xml @@ -78,12 +78,12 @@ under the License. account accountvar - + id userid - + @@ -126,7 +126,7 @@ under the License. ---> +--> registerUserKeys @@ -145,7 +145,7 @@ under the License. secretkey - + createNetwork @@ -200,7 +200,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -208,7 +208,7 @@ under the License. account accountvar - + domainid 1 @@ -224,7 +224,7 @@ under the License. networkids networkid - + @@ -233,7 +233,7 @@ under the License. - + createVolume true @@ -248,7 +248,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -257,7 +257,7 @@ under the License. - + attachVolume true @@ -273,7 +273,7 @@ under the License. - + @@ -286,7 +286,7 @@ under the License. - + createVolume true @@ -301,7 +301,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -310,7 +310,7 @@ under the License. - + attachVolume true @@ -326,8 +326,8 @@ under the License. - - + + createVolume @@ -344,7 +344,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -352,9 +352,9 @@ under the License. DATADISK - - - + + + deployVirtualMachine @@ -371,7 +371,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -379,7 +379,7 @@ under the License. account accountvar - + domainid 1 @@ -395,7 +395,7 @@ under the License. networkids networkid - + @@ -404,7 +404,7 @@ under the License. - + listVolumes @@ -424,7 +424,7 @@ under the License. - + detachVolume true @@ -458,7 +458,7 @@ under the License. - + detachVolume true @@ -471,8 +471,8 @@ under the License. - - + + deployVirtualMachine @@ -489,7 +489,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -497,7 +497,7 @@ under the License. account accountvar - + domainid 1 @@ -513,7 +513,7 @@ under the License. networkids networkid - + @@ -522,7 +522,7 @@ under the License. - + createVolume true @@ -537,7 +537,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -546,7 +546,7 @@ under the License. - + createVolume true @@ -561,7 +561,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -570,7 +570,7 @@ under the License. - + createVolume true @@ -585,7 +585,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -594,7 +594,7 @@ under the License. - + createVolume true @@ -609,7 +609,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -618,7 +618,7 @@ under the License. - + createVolume true @@ -633,7 +633,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -642,7 +642,7 @@ under the License. - + attachVolume true @@ -657,7 +657,7 @@ under the License. - + attachVolume true @@ -672,7 +672,7 @@ under the License. - + attachVolume true @@ -687,7 +687,7 @@ under the License. - + attachVolume true @@ -702,7 +702,7 @@ under the License. - + attachVolume true @@ -732,7 +732,7 @@ under the License. - + stopVirtualMachine @@ -745,7 +745,7 @@ under the License. - + startVirtualMachine true @@ -757,8 +757,8 @@ under the License. - - + + createVolume @@ -774,7 +774,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -783,7 +783,7 @@ under the License. - + attachVolume true @@ -800,7 +800,7 @@ under the License. - + @@ -813,8 +813,8 @@ under the License. vmid - - + + listVolumes true @@ -830,8 +830,8 @@ under the License. - - + + deployVirtualMachine @@ -848,7 +848,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -856,7 +856,7 @@ under the License. account accountvar - + domainid 1 @@ -872,7 +872,7 @@ under the License. networkids networkid - + @@ -881,7 +881,7 @@ under the License. - + listVolumes @@ -901,7 +901,7 @@ under the License. - + detachVolume true @@ -912,7 +912,7 @@ under the License. - + rebootVirtualMachine true @@ -924,7 +924,7 @@ under the License. - + stopVirtualMachine @@ -936,7 +936,7 @@ under the License. - + startVirtualMachine true @@ -967,7 +967,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -975,7 +975,7 @@ under the License. account accountvar - + domainid 1 @@ -991,7 +991,7 @@ under the License. networkids networkid - + @@ -1000,7 +1000,7 @@ under the License. - + listVolumes @@ -1020,7 +1020,7 @@ under the License. - + detachVolume true @@ -1032,7 +1032,7 @@ under the License. - + listVolumes true @@ -1048,7 +1048,7 @@ under the License. - + attachVolume @@ -1064,7 +1064,7 @@ under the License. - + stopVirtualMachine true @@ -1075,7 +1075,7 @@ under the License. - + detachVolume true @@ -1087,7 +1087,7 @@ under the License. - + listVolumes true @@ -1103,7 +1103,7 @@ under the License. - + deployVirtualMachine @@ -1120,7 +1120,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -1128,7 +1128,7 @@ under the License. account accountvar - + domainid 1 @@ -1144,7 +1144,7 @@ under the License. networkids networkid - + @@ -1153,7 +1153,7 @@ under the License. - + deployVirtualMachine true @@ -1169,7 +1169,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -1177,7 +1177,7 @@ under the License. account accountvar - + domainid 1 @@ -1193,7 +1193,7 @@ under the License. networkids networkid - + @@ -1202,7 +1202,7 @@ under the License. - + createVolume true @@ -1217,7 +1217,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -1226,7 +1226,7 @@ under the License. - + attachVolume true @@ -1241,7 +1241,7 @@ under the License. - + attachVolume true @@ -1258,7 +1258,7 @@ under the License. - + destroyVirtualMachine @@ -1270,7 +1270,7 @@ under the License. - + createVolume true @@ -1285,7 +1285,7 @@ under the License. diskofferingid globaldiskofferingid - + @@ -1294,7 +1294,7 @@ under the License. - + attachVolume true @@ -1311,7 +1311,7 @@ under the License. - + listVolumes @@ -1332,7 +1332,7 @@ under the License. - + destroyVirtualMachine true @@ -1343,7 +1343,7 @@ under the License. - + detachVolume true @@ -1356,9 +1356,9 @@ under the License. - - - + + + deleteAccount Deleting Account as a part of cleanup diff --git a/test/metadata/func/snapshot_iso.xml b/test/metadata/func/snapshot_iso.xml index aabc8c113b4..6bddb393e71 100644 --- a/test/metadata/func/snapshot_iso.xml +++ b/test/metadata/func/snapshot_iso.xml @@ -18,38 +18,38 @@ under the License. --> - - + createUser Create a user - + username @@ -87,7 +87,7 @@ under the License. - + registerUserKeys Registering the user @@ -108,8 +108,8 @@ under the License. - - + + registerIso Register iso @@ -176,9 +176,9 @@ under the License. registerdisplay - - - + + + deployVirtualMachine Deploying VM from small diskOffering @@ -195,7 +195,7 @@ under the License. diskofferingid 5 - + templateid privateisoid @@ -224,7 +224,7 @@ under the License. - + listVolumes @@ -245,7 +245,7 @@ under the License. - + listVolumes @@ -265,7 +265,7 @@ under the License. - + sleep.sh @@ -277,7 +277,7 @@ under the License. 200 - + @@ -316,7 +316,7 @@ under the License. - + createTemplate @@ -346,7 +346,7 @@ under the License. - + deployVirtualMachine @@ -364,7 +364,7 @@ under the License. diskofferingid 5 - + templateid smalltemplateid @@ -394,7 +394,7 @@ under the License. - + createVolume Create a volume from smaller disk snapshot @@ -416,7 +416,7 @@ under the License. - + createVolume Create a volume from smaller disk snapshot @@ -456,7 +456,7 @@ under the License. - + attachVolume Attach small volume to a different VM @@ -472,7 +472,7 @@ under the License. - + listConfiguration Getting value of the expunge.delay configuration parameter @@ -489,8 +489,8 @@ under the License. - - + + rebootVirtualMachine @@ -502,7 +502,7 @@ under the License. - + stopVirtualMachine stop medium vm @@ -513,7 +513,7 @@ under the License. - + startVirtualMachine stop medium vm @@ -548,9 +548,9 @@ under the License. - - + + @@ -570,8 +570,8 @@ under the License. - - + + sleep.sh @@ -583,7 +583,7 @@ under the License. - + sleep.sh @@ -595,8 +595,8 @@ under the License. - - + + @@ -617,7 +617,7 @@ under the License. - + destroyVirtualMachine @@ -629,8 +629,8 @@ under the License. - - + + deleteUser @@ -642,5 +642,5 @@ under the License. - + diff --git a/test/metadata/func/snapshots.xml b/test/metadata/func/snapshots.xml index 578698ad67e..843b5dfe1c5 100644 --- a/test/metadata/func/snapshots.xml +++ b/test/metadata/func/snapshots.xml @@ -28,7 +28,7 @@ under the License. d.List the Data Disk of the Medium VM 5.Create a Snapshot from the root disk of the Small VM 6.Create a Snapshot from the data disk of the Small VM - 7.Create a Snapshot from the root disk of the Medium VM + 7.Create a Snapshot from the root disk of the Medium VM 8.Create a Snapshot from the data disk of the Medium VM 9.Create a Template from the snapshot taken of the root disk of the Small VM 10.Create a Template from the snapshot taken of the root disk of the Medium VM @@ -38,9 +38,9 @@ under the License. 14.Create a Volume from the snapshot taken of the root disk of the Medium VM 15.Attach the volume created from the snapshot taken of the root disk of the Small VM to the VM created from the template created from the snapshot taken of the root disk of the Small VM 16.Attach the volume created from the snapshot taken of the root disk of the Medium VM to the VM created from the template created from the snapshot taken of the root disk of the Medium VM - 17.Reboot,start,stop,destroy VM created from the template created from the snapshot taken of the root disk of the Small VM - 18.Reboot,start,stop,destroy VM created from the template created from the snapshot taken of the root disk of the Medium VM - 19.Clean Up + 17.Reboot,start,stop,destroy VM created from the template created from the snapshot taken of the root disk of the Small VM + 18.Reboot,start,stop,destroy VM created from the template created from the snapshot taken of the root disk of the Medium VM + 19.Clean Up --> @@ -103,20 +103,20 @@ under the License. account accountvar - + id userid - + - +--> registerUserKeys Registering the user @@ -173,8 +173,8 @@ under the License. secretkey - - + + createNetwork [Creating default network] @@ -211,7 +211,7 @@ under the License. - + deployVirtualMachine Deploying vm from small diskOffering @@ -228,7 +228,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -261,7 +261,7 @@ under the License. - + deployVirtualMachine Deploying vm from Medium disk offering @@ -278,7 +278,7 @@ under the License. diskofferingid mediumglobaldiskofferingid - + templateid globaltemplateid @@ -319,7 +319,7 @@ under the License. - + listVolumes @@ -339,7 +339,7 @@ under the License. - + listVolumes @@ -359,7 +359,7 @@ under the License. - + listVolumes @@ -379,7 +379,7 @@ under the License. - + listVolumes @@ -411,7 +411,7 @@ under the License. 200 - + @@ -431,7 +431,7 @@ under the License. - + createSnapshot Creating snapshot of Data disk of small vm @@ -449,7 +449,7 @@ under the License. - + createSnapshot Creating snapshot of ROOT disk of medium vm @@ -467,7 +467,7 @@ under the License. - + createSnapshot Creating snapshot of DATA disk of medium vm @@ -485,7 +485,7 @@ under the License. - + createTemplate @@ -515,7 +515,7 @@ under the License. - + createTemplate Creating template of ROOT snapshot of large vm @@ -544,7 +544,7 @@ under the License. - + deployVirtualMachine Deploy a vm from template created from snapshot of ROOT disk of small vm @@ -561,7 +561,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid smalltemplateid @@ -602,7 +602,7 @@ under the License. - + deployVirtualMachine Deploy a vm from template created from snapshot of ROOT disk of medium vm @@ -619,7 +619,7 @@ under the License. diskofferingid mediumglobaldiskofferinigid - + templateid largetemplateid @@ -703,8 +703,8 @@ under the License. largevolumeid - - + + attachVolume Attach small volume to the vm created from small snapshot @@ -720,7 +720,7 @@ under the License. - + attachVolume Attach medium volume to the vm created from medium snapshot @@ -736,8 +736,8 @@ under the License. - - + + rebootVirtualMachine @@ -749,7 +749,7 @@ under the License. - + stopVirtualMachine stop medium vm @@ -760,7 +760,7 @@ under the License. - + startVirtualMachine stop medium vm @@ -784,7 +784,7 @@ under the License. - + destroyVirtualMachine Destroy large vm @@ -796,7 +796,7 @@ under the License. - + @@ -808,9 +808,9 @@ under the License. accountid - + - - - + + diff --git a/test/metadata/func/snapshots_contd.xml b/test/metadata/func/snapshots_contd.xml index d0532cd89d2..c9b277cb696 100644 --- a/test/metadata/func/snapshots_contd.xml +++ b/test/metadata/func/snapshots_contd.xml @@ -18,14 +18,14 @@ under the License. --> - - + createUser Create a user - + username @@ -87,7 +87,7 @@ under the License. - + registerUserKeys Registering the user @@ -107,9 +107,9 @@ under the License. secretkey - - - + + + deployVirtualMachine Deploying VM from small diskOffering @@ -126,7 +126,7 @@ under the License. diskofferingid 5 - + templateid globaltemplateid @@ -155,7 +155,7 @@ under the License. - + listVolumes @@ -176,7 +176,7 @@ under the License. - + listVolumes @@ -196,7 +196,7 @@ under the License. - + sleep.sh @@ -208,7 +208,7 @@ under the License. 200 - + @@ -247,7 +247,7 @@ under the License. - + createTemplate @@ -277,7 +277,7 @@ under the License. - + deployVirtualMachine @@ -295,7 +295,7 @@ under the License. diskofferingid 5 - + templateid smalltemplateid @@ -325,7 +325,7 @@ under the License. - + createVolume Create a volume from smaller disk snapshot @@ -347,7 +347,7 @@ under the License. - + createVolume Create a volume from smaller disk snapshot @@ -369,7 +369,7 @@ under the License. - + createSnapshot Creating snapshot of Detached Volume @@ -406,7 +406,7 @@ under the License. - + attachVolume Attach small volume to a different VM @@ -422,9 +422,9 @@ under the License. - - - + + + rebootVirtualMachine @@ -436,7 +436,7 @@ under the License. - + stopVirtualMachine stop medium vm @@ -447,7 +447,7 @@ under the License. - + startVirtualMachine stop medium vm @@ -483,7 +483,7 @@ under the License. - + destroyVirtualMachine @@ -495,9 +495,9 @@ under the License. - - + + @@ -517,8 +517,8 @@ under the License. - - + + sleep.sh @@ -530,7 +530,7 @@ under the License. - + sleep.sh @@ -542,8 +542,8 @@ under the License. - - + + @@ -564,7 +564,7 @@ under the License. - + destroyVirtualMachine @@ -576,7 +576,7 @@ under the License. - + listConfiguration Getting value of the expunge.delay configuration parameter @@ -593,7 +593,7 @@ under the License. - + listConfiguration Getting value of the expunge.delay configuration parameter @@ -609,8 +609,8 @@ under the License. expunge.delay - - + + deleteUser @@ -622,5 +622,5 @@ under the License. - + diff --git a/test/metadata/func/static_nat.xml b/test/metadata/func/static_nat.xml index 144ad9d5ae0..7694affdab8 100644 --- a/test/metadata/func/static_nat.xml +++ b/test/metadata/func/static_nat.xml @@ -18,9 +18,9 @@ under the License. --> - + createUser - Create a regular user + Create a regular user username @@ -57,7 +57,7 @@ under the License. - + registerUserKeys Registering the user @@ -78,7 +78,7 @@ under the License. - + deployVirtualMachine Deploying virtual machine @@ -95,7 +95,7 @@ under the License. diskofferingid 5 - + templateid globaltemplateid @@ -127,9 +127,9 @@ under the License. vmipaddress - - - + + + deployVirtualMachine Deploying virtual machine @@ -146,7 +146,7 @@ under the License. diskofferingid 5 - + templateid globaltemplateid @@ -178,8 +178,8 @@ under the License. vmipaddress1 - - + + sleep.sh @@ -190,8 +190,8 @@ under the License. 60 - - + + listRouters 35 @@ -219,9 +219,9 @@ under the License. sourcenatpublicip - - - + + + associateIpAddress true @@ -231,15 +231,15 @@ under the License. globalzoneid - + ipaddress nonsourcenatpublicip - - + + createIpForwardingRule @@ -257,8 +257,8 @@ under the License. - - + + createIpForwardingRule @@ -274,14 +274,14 @@ under the License. vmid - + id ruleid - + ssh.sh @@ -297,8 +297,8 @@ under the License. - - + + deleteIpForwardingRule @@ -311,7 +311,7 @@ under the License. - + listIpForwardingRules true @@ -324,7 +324,7 @@ under the License. - + ssh.sh @@ -341,8 +341,8 @@ under the License. - - + + createIpForwardingRule @@ -358,14 +358,14 @@ under the License. vmid - + id ruleid - + listIpForwardingRules true @@ -378,7 +378,7 @@ under the License. - + listIpForwardingRules true @@ -391,8 +391,8 @@ under the License. - - + + listIpForwardingRules true @@ -405,7 +405,7 @@ under the License. - + disassociateIpAddress @@ -417,7 +417,7 @@ under the License. - + listIpForwardingRules true @@ -425,7 +425,7 @@ under the License. false - + associateIpAddress @@ -436,15 +436,15 @@ under the License. globalzoneid - + ipaddress nonsourcenatpublicip - - + + createIpForwardingRule true @@ -459,14 +459,14 @@ under the License. vmid - + id ruleid - + createIpForwardingRule true @@ -483,8 +483,8 @@ under the License. - - + + destroyVirtualMachine @@ -496,7 +496,7 @@ under the License. - + listConfigurations Getting expunge interval value @@ -513,7 +513,7 @@ under the License. - + sleep.sh @@ -524,15 +524,15 @@ under the License. expunge.interval - - + + listIpForwardingRules true true Test case 1140: static nat rules should be removed once corresponding vm is expunged - + @@ -544,14 +544,14 @@ under the License. globalzoneid - + ipaddress nonsourcenatpublicip1 - + associateIpAddress true @@ -561,14 +561,14 @@ under the License. globalzoneid - + ipaddress nonsourcenatpublicip2 - + createIpForwardingRule true @@ -584,7 +584,7 @@ under the License. - + createIpForwardingRule true @@ -600,8 +600,8 @@ under the License. - - + + ssh.sh @@ -617,8 +617,8 @@ under the License. - - + + ssh.sh @@ -634,8 +634,8 @@ under the License. - - + + rebootRouter @@ -647,7 +647,7 @@ under the License. - + ssh.sh @@ -675,8 +675,8 @@ under the License. routerid - - + + startRouter Starting router... @@ -686,8 +686,8 @@ under the License. routerid - - + + ssh.sh @@ -703,7 +703,7 @@ under the License. - + @@ -722,7 +722,7 @@ under the License. diskofferingid 5 - + templateid globaltemplateid @@ -754,8 +754,8 @@ under the License. vmipaddress1 - - + + sleep.sh @@ -766,8 +766,8 @@ under the License. 60 - - + + associateIpAddress true @@ -777,14 +777,14 @@ under the License. globalzoneid - + ipaddress nonsourcenatpublicip - - + + createPortForwardingRule true @@ -815,8 +815,8 @@ under the License. vmid - - + + ssh.sh @@ -832,7 +832,7 @@ under the License. - + createIpForwardingRule true @@ -847,14 +847,14 @@ under the License. vmid1 - + id ruleid - + ssh.sh @@ -870,7 +870,7 @@ under the License. - + deleteIpForwardingRule true @@ -882,7 +882,7 @@ under the License. - + ssh.sh @@ -898,9 +898,9 @@ under the License. - - - + + + deleteUser Deleting the user @@ -910,7 +910,7 @@ under the License. userid - + diff --git a/test/metadata/func/templatedwnldstress.xml b/test/metadata/func/templatedwnldstress.xml index 19d12a2d9ef..0edb82eb1fe 100644 --- a/test/metadata/func/templatedwnldstress.xml +++ b/test/metadata/func/templatedwnldstress.xml @@ -18,18 +18,18 @@ under the License. --> - @@ -76,7 +76,7 @@ under the License. - + createNetwork @@ -114,7 +114,7 @@ under the License. - + deployVirtualMachine [Deploy a Virtual Machine under the Account] @@ -159,7 +159,7 @@ under the License. - + listVolumes [List the ROOT Volume of the VM] @@ -180,7 +180,7 @@ under the License. - + stopVirtualMachine [Stop virtual machine] @@ -191,7 +191,7 @@ under the License. - + createTemplate [Create template from root volume] @@ -219,7 +219,7 @@ under the License. - + deployVirtualMachine [Deploying virtual machine from the Private Template] @@ -235,7 +235,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid privatetemplateid @@ -272,7 +272,7 @@ under the License. - + listHosts List host where vm is running @@ -289,7 +289,7 @@ under the License. - + select install_path from template_spool_ref true @@ -307,7 +307,7 @@ under the License. - + listvdi.sh @@ -323,7 +323,7 @@ under the License. - + destroyVirtualMachine Destroy virtual machine created from the private template @@ -333,9 +333,9 @@ under the License. vmid1 - - - + + + listConfigurations Getting expunge interval value @@ -352,7 +352,7 @@ under the License. - + updateConfiguration Updating storage.cleanup.interval @@ -367,7 +367,7 @@ under the License. - + listConfigurations Getting expunge interval value @@ -384,7 +384,7 @@ under the License. - + ms.sh @@ -411,9 +411,9 @@ under the License. expunge.interval - - - + + + sleep.sh @@ -424,8 +424,8 @@ under the License. expunge.interval - - + + sleep.sh @@ -436,8 +436,8 @@ under the License. storage.cleanup.interval - - + + sleep.sh @@ -448,10 +448,10 @@ under the License. storage.cleanup.interval - - + + - + listvdi.sh true @@ -470,7 +470,7 @@ under the License. - + deployVirtualMachine Deploying virtual machine from the private template @@ -486,7 +486,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid privatetemplateid @@ -523,7 +523,7 @@ under the License. - + listHosts List host where vm is running @@ -540,7 +540,7 @@ under the License. - + select install_path from template_spool_ref true @@ -558,7 +558,7 @@ under the License. - + listvdi.sh @@ -574,7 +574,7 @@ under the License. - + destroyVirtualMachine Destroy virtual machine created from the private template @@ -584,9 +584,9 @@ under the License. vmid1 - - - + + + listConfigurations Getting expunge interval value @@ -603,7 +603,7 @@ under the License. - + sleep.sh @@ -614,9 +614,9 @@ under the License. expunge.interval - - - + + + sleep.sh @@ -627,8 +627,8 @@ under the License. expunge.interval - - + + sleep.sh @@ -639,8 +639,8 @@ under the License. storage.cleanup.interval - - + + sleep.sh @@ -651,10 +651,10 @@ under the License. storage.cleanup.interval - - + + - + listvdi.sh true @@ -673,8 +673,8 @@ under the License. - - + + startVirtualMachine [Start virtual machine] @@ -691,7 +691,7 @@ under the License. - + rebootVirtualMachine [Reboot Virtual Machine] @@ -702,7 +702,7 @@ under the License. - + destroyVirtualMachine [Destroy virtual machine] @@ -713,7 +713,7 @@ under the License. - + listVirtualMachines [Verify that vm was destroyed] @@ -730,7 +730,7 @@ under the License. - + deleteTemplate Delete private template @@ -741,7 +741,7 @@ under the License. - + deleteAccount [Delete account] @@ -751,7 +751,7 @@ under the License. accountid - - - + + + diff --git a/test/metadata/func/userapi.xml b/test/metadata/func/userapi.xml index de03b9794da..67246cbb0bc 100644 --- a/test/metadata/func/userapi.xml +++ b/test/metadata/func/userapi.xml @@ -64,7 +64,7 @@ under the License. name accountname - + @@ -77,7 +77,7 @@ under the License. account accountname - + id @@ -86,10 +86,10 @@ under the License. username usernameparam - + - + createUser @@ -127,11 +127,11 @@ under the License. domainid 1 - + - - + + +--> @@ -243,7 +243,7 @@ under the License. password password - + +--> createUser @@ -296,7 +296,7 @@ under the License. 0 - username + username password @@ -317,7 +317,7 @@ under the License. domainid 1 - + @@ -326,7 +326,7 @@ under the License. seconduserid - + updateUser 593 @@ -356,7 +356,7 @@ under the License. - + deleteUser @@ -367,7 +367,7 @@ under the License. - + deleteUser 58 @@ -379,8 +379,8 @@ under the License. - - + + listUsers 59 @@ -392,7 +392,7 @@ under the License. - + listUsers @@ -405,7 +405,7 @@ under the License. - + updateUser @@ -421,7 +421,7 @@ under the License. - + updateUser @@ -437,7 +437,7 @@ under the License. - + createUser @@ -473,7 +473,7 @@ under the License. - + createUser @@ -512,8 +512,8 @@ under the License. - - + + createUser @@ -541,8 +541,8 @@ under the License. - - + + createUser 47 @@ -569,7 +569,7 @@ under the License. - + createUser 47 @@ -596,7 +596,7 @@ under the License. - + createUser 47 @@ -623,8 +623,8 @@ under the License. - - + + createDomain @@ -643,8 +643,8 @@ under the License. newdomainid - - + + createAccount [Create the Account and a User in the New Domain] @@ -690,7 +690,7 @@ under the License. name accountname1 - + @@ -703,7 +703,7 @@ under the License. account accountname1 - + id @@ -712,11 +712,11 @@ under the License. username usernameparam - + - - + +--> createUser 51 @@ -832,8 +832,8 @@ under the License. - - + + createUser @@ -871,7 +871,7 @@ under the License. - + createUser @@ -909,7 +909,7 @@ under the License. - + createDomain @@ -928,7 +928,7 @@ under the License. - + createDomain 64 @@ -940,9 +940,9 @@ under the License. - - + + deleteDomain @@ -952,7 +952,7 @@ under the License. - + listDomains 65 @@ -964,8 +964,8 @@ under the License. - - + + +--> deleteDomain 66 @@ -1032,7 +1032,7 @@ under the License. - + listDomains @@ -1045,8 +1045,8 @@ under the License. - - + + createUser @@ -1094,7 +1094,7 @@ under the License. - + deployVirtualMachine @@ -1109,7 +1109,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -1136,7 +1136,7 @@ under the License. - + deleteUser @@ -1146,7 +1146,7 @@ under the License. - + listEvents 601 @@ -1157,7 +1157,7 @@ under the License. - + @@ -1206,7 +1206,7 @@ under the License. - + registerUserKeys @@ -1225,8 +1225,8 @@ under the License. secretkey - - + + listVirtualMachines true @@ -1239,8 +1239,8 @@ under the License. - - + + deleteDomain @@ -1254,8 +1254,8 @@ under the License. true - - + + +--> deleteAccount id - accountid - - - - - - deleteAccount - - - id - accountid1 + accountid - + + + deleteAccount + + + id + accountid1 + + + + diff --git a/test/metadata/func/vmapi.xml b/test/metadata/func/vmapi.xml index 8c1263c7767..fbda66fe5d7 100644 --- a/test/metadata/func/vmapi.xml +++ b/test/metadata/func/vmapi.xml @@ -16,11 +16,11 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - + - @@ -80,7 +80,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -121,7 +121,7 @@ under the License. - + destroyVirtualMachine [Destroy Virtual Machine] @@ -132,7 +132,7 @@ under the License. - + listVirtualMachines 72 [List the Destroyed Virutal Machine] @@ -147,7 +147,7 @@ under the License. - + startVirtualMachine @@ -160,7 +160,7 @@ under the License. - + listVirtualMachines @@ -176,8 +176,8 @@ under the License. - - + + createAccount @@ -223,7 +223,7 @@ under the License. name accountname - + @@ -237,7 +237,7 @@ under the License. accountname - + id @@ -251,7 +251,7 @@ under the License. - +--> createNetwork @@ -328,7 +328,7 @@ under the License. - + deployVirtualMachine [Deploy Virtual Machine in the new Account] @@ -344,7 +344,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -385,7 +385,7 @@ under the License. - + deleteUser [Delete User] @@ -395,7 +395,7 @@ under the License. userid - + deleteAccount @@ -406,8 +406,8 @@ under the License. accountid - - + + listVirtualMachines 74 [Check that no VMs present under the Account(List VM for a Removed User exercise END)] @@ -423,7 +423,7 @@ under the License. - + updateVirtualMachine @@ -439,8 +439,8 @@ under the License. true - - + + updateVirtualMachine @@ -456,10 +456,10 @@ under the License. true - - + - + + recoverVirtualMachine [Recover the Destroyed VM] @@ -470,7 +470,7 @@ under the License. - + resetPasswordForVirtualMachine 79-1 [Verify that one can reset password for VM in stopped state] @@ -482,7 +482,7 @@ under the License. - + updateVirtualMachine @@ -497,10 +497,10 @@ under the License. true - + - + startVirtualMachine [Start Virtual Machine (reset password for VM in running state exercise BEGIN)] @@ -511,7 +511,7 @@ under the License. - + resetPasswordForVirtualMachine 79-2 [Verify that one can reset password for VM in running state] @@ -522,7 +522,7 @@ under the License. - + @@ -538,9 +538,9 @@ under the License. false - - - + + + destroyVirtualMachine @@ -552,7 +552,7 @@ under the License. - + resetPasswordForVirtualMachine 80 [Verify that one can't reset password for VM in destroyed state] @@ -564,8 +564,8 @@ under the License. - - + + rebootVirtualMachine 89 [Verify that one can't reboot destroyed VM] @@ -578,7 +578,7 @@ under the License. - + deployVirtualMachine @@ -595,7 +595,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -636,7 +636,7 @@ under the License. - + resetPasswordForVirtualMachine 81 [Check whether password can be reset on virtual machine made from password disabled VM] @@ -648,7 +648,7 @@ under the License. - + changeServiceForVirtualMachine @@ -677,7 +677,7 @@ under the License. - + changeServiceForVirtualMachine 83 [Try to change service offering to the one that VM already has -ve case] @@ -693,8 +693,8 @@ under the License. - - + + rebootVirtualMachine @@ -707,7 +707,7 @@ under the License. - + @@ -721,7 +721,7 @@ under the License. - + startVirtualMachine [Start virtual machine] @@ -732,7 +732,7 @@ under the License. - + recoverVirtualMachine 813 [Try to recover running virtual machine] @@ -763,7 +763,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -789,8 +789,8 @@ under the License. globalnetworkid - - + + deployVirtualMachine @@ -808,7 +808,7 @@ under the License. diskofferingid globaldiskofferingid - + templateid globaltemplateid @@ -834,8 +834,8 @@ under the License. networkid - - + + destroyVirtualMachine @@ -848,7 +848,7 @@ under the License. - + rebootVirtualMachine @@ -861,7 +861,7 @@ under the License. - + startVirtualMachine @@ -886,6 +886,6 @@ under the License. - - - + + + diff --git a/test/metadata/func/vmsync.xml b/test/metadata/func/vmsync.xml index 0e7a69749f9..c0b34c9c37a 100644 --- a/test/metadata/func/vmsync.xml +++ b/test/metadata/func/vmsync.xml @@ -23,12 +23,12 @@ under the License. deployVirtualMachine deploy HA enabled VM test case - + diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -40,7 +40,7 @@ under the License. zoneid globalzoneid - + displayname HAenabledVM @@ -60,7 +60,7 @@ under the License. networkids globalnetworkid - + @@ -82,12 +82,12 @@ under the License. deployVirtualMachine deploy HA disabled VM test case - + diskofferingid globaldiskofferingid - + serviceofferingid globalserviceofferingid @@ -99,7 +99,7 @@ under the License. zoneid globalzoneid - + displayname HAdisabledVM @@ -119,7 +119,7 @@ under the License. networkids globalnetworkid - + @@ -174,7 +174,7 @@ under the License. haenable false - + @@ -196,7 +196,7 @@ under the License. - + @@ -233,8 +233,8 @@ under the License. instance_name_db - - + + select instance_name from vm_instance true @@ -251,7 +251,7 @@ under the License. instance_name_en - + @@ -259,13 +259,13 @@ under the License. killvm.sh Kill the HA enabled VM - + n instance_name_en - + h ipaddress_en @@ -278,13 +278,13 @@ under the License. killvm.sh Kill the HA disabled VM - + n instance_name_db - + h ipaddress_db @@ -303,7 +303,7 @@ under the License. 300 - + @@ -321,10 +321,10 @@ under the License. state Stopped - + - - + + listVirtualMachines List virtual machine with ha enabled @@ -393,7 +393,7 @@ under the License. - + destroyVirtualMachine Destroy ha enabled vm as a part of cleanup diff --git a/test/pom.xml b/test/pom.xml index 1692a13a390..99efd5ef718 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -24,7 +24,7 @@ org.apache.cloudstack cloudstack - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT @@ -33,23 +33,17 @@ ${project.version} - ch.qos.reload4j - reload4j + org.apache.logging.log4j + log4j-core + + + org.apache.logging.log4j + log4j-api org.jenkins-ci trilead-ssh2 - - log4j - apache-log4j-extras - - - log4j - log4j - - - org.openqa.selenium.server selenium-server diff --git a/test/scripts/bootstrap-regression.sh b/test/scripts/bootstrap-regression.sh index ff219dd47cb..a8576c1e347 100755 --- a/test/scripts/bootstrap-regression.sh +++ b/test/scripts/bootstrap-regression.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + set -e diff --git a/test/scripts/build-env.sh b/test/scripts/build-env.sh index 299b6b6d097..4e455465438 100755 --- a/test/scripts/build-env.sh +++ b/test/scripts/build-env.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + PATHSEP=':' if [[ $OSTYPE == "cygwin" ]] ; then diff --git a/test/scripts/certDeleteEC2.sh b/test/scripts/certDeleteEC2.sh index ed4947ac5b4..59510358eea 100755 --- a/test/scripts/certDeleteEC2.sh +++ b/test/scripts/certDeleteEC2.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + set -e DST='src/' diff --git a/test/scripts/certSubmitEC2.sh b/test/scripts/certSubmitEC2.sh index 7ac915abf98..452ba0babab 100755 --- a/test/scripts/certSubmitEC2.sh +++ b/test/scripts/certSubmitEC2.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + set -e DST='src/' diff --git a/test/scripts/checkLog.sh b/test/scripts/checkLog.sh index 82619ffc9fb..4f9f1fd8317 100755 --- a/test/scripts/checkLog.sh +++ b/test/scripts/checkLog.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + #set -x diff --git a/test/scripts/checkOutOfMemory.sh b/test/scripts/checkOutOfMemory.sh index cb5b595df45..6b160402f5c 100755 --- a/test/scripts/checkOutOfMemory.sh +++ b/test/scripts/checkOutOfMemory.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + while true diff --git a/test/scripts/cleanparallel.sh b/test/scripts/cleanparallel.sh index 0ccb546dacf..03dd7224b02 100755 --- a/test/scripts/cleanparallel.sh +++ b/test/scripts/cleanparallel.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + . /etc/rc.d/init.d/functions diff --git a/test/scripts/deploy-and-run-regression.sh b/test/scripts/deploy-and-run-regression.sh index 691a93046e7..40d939d6aa3 100755 --- a/test/scripts/deploy-and-run-regression.sh +++ b/test/scripts/deploy-and-run-regression.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + set -e diff --git a/test/scripts/deploy.sh b/test/scripts/deploy.sh index 6b58e888a33..9d511298d92 100755 --- a/test/scripts/deploy.sh +++ b/test/scripts/deploy.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + . /etc/rc.d/init.d/functions diff --git a/test/scripts/deploycluster.sh b/test/scripts/deploycluster.sh index 91111d98ff1..dbd2c7b606c 100755 --- a/test/scripts/deploycluster.sh +++ b/test/scripts/deploycluster.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -49,7 +49,7 @@ deploy_server() { echo "Deploying management server software on remote machine $1" rsync -avzh -e ssh $path/cloudstack-oss root@$1:/root/ - if [ $? -gt 0 ]; then echo "failed to rsync software between $path/cloudstack-oss and and remote machine $1"; return 2; fi + if [ $? -gt 0 ]; then echo "failed to rsync software between $path/cloudstack-oss and remote machine $1"; return 2; fi ssh root@$1 "cd /root/cloudstack-oss && ant clean build-all deploy-server" if [ $? -gt 0 ]; then echo "failed to deploy cluster on $1"; return 2; fi diff --git a/test/scripts/executeUserAPI.sh b/test/scripts/executeUserAPI.sh index caf54b19f0f..7bfd6f49ce5 100755 --- a/test/scripts/executeUserAPI.sh +++ b/test/scripts/executeUserAPI.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + PATHSEP=':' if [[ $OSTYPE == "cygwin" ]] ; then diff --git a/test/scripts/invoke.sh b/test/scripts/invoke.sh index 2d8405f84a6..8b14d2abfe9 100755 --- a/test/scripts/invoke.sh +++ b/test/scripts/invoke.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + cd /root/test/scripts && ./cleanparallel.sh && ./deploy.sh -i -d -r if [ $? -ne 0 ]; then exit 2; fi; diff --git a/test/scripts/regression.sh b/test/scripts/regression.sh index 7a7c9e062aa..bae8c7ef202 100755 --- a/test/scripts/regression.sh +++ b/test/scripts/regression.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + set -e DST='../src/' diff --git a/test/scripts/run.sh b/test/scripts/run.sh index de1dc22b256..bbaac7abb03 100755 --- a/test/scripts/run.sh +++ b/test/scripts/run.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + PATHSEP=':' if [[ $OSTYPE == "cygwin" ]] ; then diff --git a/test/scripts/script_lock_test/test.sh b/test/scripts/script_lock_test/test.sh index f50b27bd605..c428206954d 100755 --- a/test/scripts/script_lock_test/test.sh +++ b/test/scripts/script_lock_test/test.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/test/scripts/script_lock_test/test_task.sh b/test/scripts/script_lock_test/test_task.sh index 21d722ed21f..c7f51a2271a 100755 --- a/test/scripts/script_lock_test/test_task.sh +++ b/test/scripts/script_lock_test/test_task.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/test/scripts/sign.sh b/test/scripts/sign.sh index db807c4122f..4052bb704a9 100755 --- a/test/scripts/sign.sh +++ b/test/scripts/sign.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + set -e DST='../src/' diff --git a/test/scripts/signEC2.sh b/test/scripts/signEC2.sh index 78ca108e5d7..a519f6549f4 100755 --- a/test/scripts/signEC2.sh +++ b/test/scripts/signEC2.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + set -e DST='../src/' diff --git a/test/scripts/usage/allocated.sh b/test/scripts/usage/allocated.sh index bb7fa1b44bc..c8d176308c6 100755 --- a/test/scripts/usage/allocated.sh +++ b/test/scripts/usage/allocated.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + #set -x iteration=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select count(*) from account;") diff --git a/test/scripts/usage/network.sh b/test/scripts/usage/network.sh index 81d6afdac2d..3523b1b4ae8 100755 --- a/test/scripts/usage/network.sh +++ b/test/scripts/usage/network.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + #set -x iteration=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select count(*) from user_statistics;") diff --git a/test/scripts/usage/running.sh b/test/scripts/usage/running.sh index bbb9f14eb8b..ba677443d71 100755 --- a/test/scripts/usage/running.sh +++ b/test/scripts/usage/running.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + #set -x iteration=$(mysql -h $1 --user=root --skip-column-names -U cloud_usage -e "select count(*) from account;") diff --git a/test/scripts/usage/volume_usage.sh b/test/scripts/usage/volume_usage.sh index a3b21d6e5a0..77842d33ac9 100755 --- a/test/scripts/usage/volume_usage.sh +++ b/test/scripts/usage/volume_usage.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + #set -x #Check first ROOT volume diff --git a/test/scripts/usercloud.properties b/test/scripts/usercloud.properties index 514e98058a6..e2b647e5de2 100644 --- a/test/scripts/usercloud.properties +++ b/test/scripts/usercloud.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/test/scripts/xen/corrupttemplate.sh b/test/scripts/xen/corrupttemplate.sh index d26097f73ba..75782491e9b 100755 --- a/test/scripts/xen/corrupttemplate.sh +++ b/test/scripts/xen/corrupttemplate.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + host="" diff --git a/test/scripts/xen/createfaketemplate.sh b/test/scripts/xen/createfaketemplate.sh index cc911228df6..4508a1ad959 100755 --- a/test/scripts/xen/createfaketemplate.sh +++ b/test/scripts/xen/createfaketemplate.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + host="" diff --git a/test/scripts/xen/killvm.sh b/test/scripts/xen/killvm.sh index 5aa9b1ed9be..8c3d5cb5665 100755 --- a/test/scripts/xen/killvm.sh +++ b/test/scripts/xen/killvm.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + uuid="" diff --git a/test/scripts/xen/listtemplate.sh b/test/scripts/xen/listtemplate.sh index 4b76b4aefd9..50f40263792 100755 --- a/test/scripts/xen/listtemplate.sh +++ b/test/scripts/xen/listtemplate.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + host="" diff --git a/test/scripts/xen/listvdi.sh b/test/scripts/xen/listvdi.sh index 9125b753d0f..25f210e5db2 100755 --- a/test/scripts/xen/listvdi.sh +++ b/test/scripts/xen/listvdi.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + uuid="" diff --git a/test/scripts/xen/listvm.sh b/test/scripts/xen/listvm.sh index 0a4e8b249fd..45be42c1118 100755 --- a/test/scripts/xen/listvm.sh +++ b/test/scripts/xen/listvm.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + uuid="" diff --git a/test/scripts/xen/ms.sh b/test/scripts/xen/ms.sh index d4a6cbce905..2a1a1480594 100755 --- a/test/scripts/xen/ms.sh +++ b/test/scripts/xen/ms.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + host="" diff --git a/test/scripts/xen/removetemplate.sh b/test/scripts/xen/removetemplate.sh index dd632cf70ef..39c91d03b1e 100755 --- a/test/scripts/xen/removetemplate.sh +++ b/test/scripts/xen/removetemplate.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + host="" @@ -37,7 +37,7 @@ do esac done -if [ $path != "" ] +if [ $path != "" ] then var=`ssh root@$host "cd $storage && rm -rf $path"` fi diff --git a/test/scripts/xen/shutdown.sh b/test/scripts/xen/shutdown.sh index c5621b1b0a7..7f422fbb941 100755 --- a/test/scripts/xen/shutdown.sh +++ b/test/scripts/xen/shutdown.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + uuid="" diff --git a/test/scripts/xen/sleep.sh b/test/scripts/xen/sleep.sh index 68bde07ac96..e5400a6a402 100755 --- a/test/scripts/xen/sleep.sh +++ b/test/scripts/xen/sleep.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + sleep=60 diff --git a/test/scripts/xen/ssh.sh b/test/scripts/xen/ssh.sh index b918c74ea3d..42abec94944 100755 --- a/test/scripts/xen/ssh.sh +++ b/test/scripts/xen/ssh.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -18,7 +18,7 @@ - + PATHSEP=':' diff --git a/test/src-not-used/main/java/com/cloud/sample/UserCloudAPIExecutor.java b/test/src-not-used/main/java/com/cloud/sample/UserCloudAPIExecutor.java deleted file mode 100644 index 6baadb8b035..00000000000 --- a/test/src-not-used/main/java/com/cloud/sample/UserCloudAPIExecutor.java +++ /dev/null @@ -1,188 +0,0 @@ -// 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.sample; - -import java.io.FileInputStream; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Properties; -import java.util.StringTokenizer; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; - -/** - * - * - * - * - * - * - * - * - * - */ - -/** - * Sample CloudStack Management User API Executor. - * - * Prerequisites: - Edit usercloud.properties to include your host, apiUrl, apiKey, and secretKey - Use ./executeUserAPI.sh to - * execute this test class - * - * - */ -public class UserCloudAPIExecutor { - public static void main(String[] args) { - // Host - String host = null; - - // Fully qualified URL with http(s)://host:port - String apiUrl = null; - - // ApiKey and secretKey as given by your CloudStack vendor - String apiKey = null; - String secretKey = null; - - try { - Properties prop = new Properties(); - prop.load(new FileInputStream("usercloud.properties")); - - // host - host = prop.getProperty("host"); - if (host == null) { - System.out.println("Please specify a valid host in the format of http(s)://:/client/api in your usercloud.properties file."); - } - - // apiUrl - apiUrl = prop.getProperty("apiUrl"); - if (apiUrl == null) { - System.out.println("Please specify a valid API URL in the format of command=¶m1=¶m2=... in your usercloud.properties file."); - } - - // apiKey - apiKey = prop.getProperty("apiKey"); - if (apiKey == null) { - System.out.println("Please specify your API Key as provided by your CloudStack vendor in your usercloud.properties file."); - } - - // secretKey - secretKey = prop.getProperty("secretKey"); - if (secretKey == null) { - System.out.println("Please specify your secret Key as provided by your CloudStack vendor in your usercloud.properties file."); - } - - if (apiUrl == null || apiKey == null || secretKey == null) { - return; - } - - System.out.println("Constructing API call to host = '" + host + "' with API command = '" + apiUrl + "' using apiKey = '" + apiKey + "' and secretKey = '" + - secretKey + "'"); - - // Step 1: Make sure your APIKey is URL encoded - String encodedApiKey = URLEncoder.encode(apiKey, "UTF-8"); - - // Step 2: URL encode each parameter value, then sort the parameters and apiKey in - // alphabetical order, and then toLowerCase all the parameters, parameter values and apiKey. - // Please note that if any parameters with a '&' as a value will cause this test client to fail since we are using - // '&' to delimit - // the string - List sortedParams = new ArrayList(); - sortedParams.add("apikey=" + encodedApiKey.toLowerCase()); - StringTokenizer st = new StringTokenizer(apiUrl, "&"); - String url = null; - boolean first = true; - while (st.hasMoreTokens()) { - String paramValue = st.nextToken(); - String param = paramValue.substring(0, paramValue.indexOf("=")); - String value = URLEncoder.encode(paramValue.substring(paramValue.indexOf("=") + 1, paramValue.length()), "UTF-8"); - if (first) { - url = param + "=" + value; - first = false; - } else { - url = url + "&" + param + "=" + value; - } - sortedParams.add(param.toLowerCase() + "=" + value.toLowerCase()); - } - Collections.sort(sortedParams); - - System.out.println("Sorted Parameters: " + sortedParams); - - // Step 3: Construct the sorted URL and sign and URL encode the sorted URL with your secret key - String sortedUrl = null; - first = true; - for (String param : sortedParams) { - if (first) { - sortedUrl = param; - first = false; - } else { - sortedUrl = sortedUrl + "&" + param; - } - } - System.out.println("sorted URL : " + sortedUrl); - String encodedSignature = signRequest(sortedUrl, secretKey); - - // Step 4: Construct the final URL we want to send to the CloudStack Management Server - // Final result should look like: - // http(s)://://client/api?&apiKey=&signature= - String finalUrl = host + "?" + url + "&apiKey=" + apiKey + "&signature=" + encodedSignature; - System.out.println("final URL : " + finalUrl); - - // Step 5: Perform a HTTP GET on this URL to execute the command - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(finalUrl); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - // SUCCESS! - System.out.println("Successfully executed command"); - } else { - // FAILED! - System.out.println("Unable to execute command with response code: " + responseCode); - } - - } catch (Throwable t) { - System.out.println(t); - } - } - - /** - * 1. Signs a string with a secret key using SHA-1 2. Base64 encode the result 3. URL encode the final result - * - * @param request - * @param key - * @return - */ - public static String signRequest(String request, String key) { - try { - Mac mac = Mac.getInstance("HmacSHA1"); - SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); - mac.init(keySpec); - mac.update(request.getBytes()); - byte[] encryptedBytes = mac.doFinal(); - return URLEncoder.encode(Base64.encodeBase64String(encryptedBytes), "UTF-8"); - } catch (Exception ex) { - System.out.println(ex); - } - return null; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/longrun/BuildGuestNetwork.java b/test/src-not-used/main/java/com/cloud/test/longrun/BuildGuestNetwork.java deleted file mode 100644 index 3a823ab9733..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/longrun/BuildGuestNetwork.java +++ /dev/null @@ -1,123 +0,0 @@ -// 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.test.longrun; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Random; - -import org.apache.log4j.Logger; - -public class BuildGuestNetwork { - - public static final Logger s_logger = Logger.getLogger(BuildGuestNetwork.class.getClass()); - private static final int ApiPort = 8096; - private static final int DeveloperPort = 8080; - private static final String ApiUrl = "/client/api"; - private static int numVM = 1; - private static long zoneId = -1L; - private static long templateId = 3; - private static long serviceOfferingId = 1; - - public static void main(String[] args) { - - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - String host = "http://localhost"; - int numThreads = 1; - - while (iter.hasNext()) { - String arg = iter.next(); - if (arg.equals("-h")) { - host = "http://" + iter.next(); - } - if (arg.equals("-t")) { - numThreads = Integer.parseInt(iter.next()); - } - if (arg.equals("-n")) { - numVM = Integer.parseInt(iter.next()); - } - if (arg.equals("-z")) { - zoneId = Integer.parseInt(iter.next()); - } - - if (arg.equals("-e")) { - templateId = Integer.parseInt(iter.next()); - } - - if (arg.equals("-s")) { - serviceOfferingId = Integer.parseInt(iter.next()); - } - } - - final String server = host + ":" + ApiPort + "/"; - final String developerServer = host + ":" + DeveloperPort + ApiUrl; - s_logger.info("Starting test in " + numThreads + " thread(s). Each thread is launching " + numVM + " VMs"); - - for (int i = 0; i < numThreads; i++) { - new Thread(new Runnable() { - @Override - public void run() { - try { - - String username = null; - String singlePrivateIp = null; - Random ran = new Random(); - username = Math.abs(ran.nextInt()) + "-user"; - - //Create User - User myUser = new User(username, username, server, developerServer); - try { - myUser.launchUser(); - myUser.registerUser(); - } catch (Exception e) { - s_logger.warn("Error code: ", e); - } - - if (myUser.getUserId() != null) { - s_logger.info("User " + myUser.getUserName() + " was created successfully, starting VM creation"); - //create VMs for the user - for (int i = 0; i < numVM; i++) { - //Create a new VM, add it to the list of user's VMs - VirtualMachine myVM = new VirtualMachine(myUser.getUserId()); - myVM.deployVM(zoneId, serviceOfferingId, templateId, myUser.getDeveloperServer(), myUser.getApiKey(), myUser.getSecretKey()); - myUser.getVirtualMachines().add(myVM); - singlePrivateIp = myVM.getPrivateIp(); - - if (singlePrivateIp != null) { - s_logger.info("VM with private Ip " + singlePrivateIp + " was successfully created"); - } else { - s_logger.info("Problems with VM creation for a user" + myUser.getUserName()); - s_logger.info("Deployment failed"); - break; - } - } - - s_logger.info("Deployment done..." + numVM + " VMs were created."); - } - - } catch (Exception e) { - s_logger.error(e); - } - } - }).start(); - - } - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/longrun/GuestNetwork.java b/test/src-not-used/main/java/com/cloud/test/longrun/GuestNetwork.java deleted file mode 100644 index 226e31ae4cc..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/longrun/GuestNetwork.java +++ /dev/null @@ -1,107 +0,0 @@ -// 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.test.longrun; - -import java.util.ArrayList; -import java.util.Random; - -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; - -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.Session; - -public class GuestNetwork implements Runnable { - public static final Logger s_logger = Logger.getLogger(GuestNetwork.class.getClass()); - - private String publicIp; - private ArrayList virtualMachines; - private int retryNum; - - public GuestNetwork(String publicIp, int retryNum) { - this.publicIp = publicIp; - this.retryNum = retryNum; - } - - public ArrayList getVirtualMachines() { - return virtualMachines; - } - - public void setVirtualMachines(ArrayList virtualMachines) { - this.virtualMachines = virtualMachines; - } - - @Override - public void run() { - NDC.push("Following thread has started" + Thread.currentThread().getName()); - int retry = 0; - - //Start copying files between machines in the network - s_logger.info("The size of the array is " + this.virtualMachines.size()); - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt"); - Thread.sleep(120000); - } - for (VirtualMachine vm : this.virtualMachines) { - - s_logger.info("Attempting to SSH into linux host " + this.publicIp + " with retry attempt: " + retry); - Connection conn = new Connection(this.publicIp); - conn.connect(null, 600000, 600000); - - s_logger.info("SSHed successfully into linux host " + this.publicIp); - - boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed"); - } - //execute copy command - Session sess = conn.openSession(); - String fileName; - Random ran = new Random(); - fileName = Math.abs(ran.nextInt()) + "-file"; - String copyCommand = new String("./scpScript " + vm.getPrivateIp() + " " + fileName); - s_logger.info("Executing " + copyCommand); - sess.execCommand(copyCommand); - Thread.sleep(120000); - sess.close(); - - //execute wget command - sess = conn.openSession(); - String downloadCommand = - new String("wget http://172.16.0.220/scripts/checkDiskSpace.sh; chmod +x *sh; ./checkDiskSpace.sh; rm -rf checkDiskSpace.sh"); - s_logger.info("Executing " + downloadCommand); - sess.execCommand(downloadCommand); - Thread.sleep(120000); - sess.close(); - - //close the connection - conn.close(); - } - } catch (Exception ex) { - s_logger.error(ex); - retry++; - if (retry == retryNum) { - s_logger.info("Performance Guest Network test failed with error " + ex.getMessage()); - } - } - } - - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/longrun/PerformanceWithAPI.java b/test/src-not-used/main/java/com/cloud/test/longrun/PerformanceWithAPI.java deleted file mode 100644 index f1a3725d01f..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/longrun/PerformanceWithAPI.java +++ /dev/null @@ -1,190 +0,0 @@ -// 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.test.longrun; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; - -import com.cloud.test.stress.TestClientWithAPI; - -public class PerformanceWithAPI { - - public static final Logger s_logger = Logger.getLogger(PerformanceWithAPI.class.getClass()); - private static final int Retry = 10; - private static final int ApiPort = 8096; - private static int s_numVM = 2; - private static final long ZoneId = -1L; - private static final long TemplateId = 3; - private static final long ServiceOfferingId = 1; - private static final String ApiUrl = "/client/api"; - private static final int DeveloperPort = 8080; - - public static void main(String[] args) { - - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - String host = "http://localhost"; - int numThreads = 1; - - while (iter.hasNext()) { - String arg = iter.next(); - if (arg.equals("-h")) { - host = "http://" + iter.next(); - } - if (arg.equals("-t")) { - numThreads = Integer.parseInt(iter.next()); - } - if (arg.equals("-n")) { - s_numVM = Integer.parseInt(iter.next()); - } - } - - final String server = host + ":" + ApiPort + "/"; - final String developerServer = host + ":" + DeveloperPort + ApiUrl; - - s_logger.info("Starting test in " + numThreads + " thread(s). Each thread is launching " + s_numVM + " VMs"); - - for (int i = 0; i < numThreads; i++) { - new Thread(new Runnable() { - @Override - public void run() { - try { - - String username = null; - String singlePrivateIp = null; - String singlePublicIp = null; - Random ran = new Random(); - username = Math.abs(ran.nextInt()) + "-user"; - - //Create User - User myUser = new User(username, username, server, developerServer); - try { - myUser.launchUser(); - myUser.registerUser(); - } catch (Exception e) { - s_logger.warn("Error code: ", e); - } - - if (myUser.getUserId() != null) { - s_logger.info("User " + myUser.getUserName() + " was created successfully, starting VM creation"); - //create VMs for the user - for (int i = 0; i < s_numVM; i++) { - //Create a new VM, add it to the list of user's VMs - VirtualMachine myVM = new VirtualMachine(myUser.getUserId()); - myVM.deployVM(ZoneId, ServiceOfferingId, TemplateId, myUser.getDeveloperServer(), myUser.getApiKey(), myUser.getSecretKey()); - myUser.getVirtualMachines().add(myVM); - singlePrivateIp = myVM.getPrivateIp(); - - if (singlePrivateIp != null) { - s_logger.info("VM with private Ip " + singlePrivateIp + " was successfully created"); - } else { - s_logger.info("Problems with VM creation for a user" + myUser.getUserName()); - break; - } - - //get public IP address for the User - myUser.retrievePublicIp(ZoneId); - singlePublicIp = myUser.getPublicIp().get(myUser.getPublicIp().size() - 1); - if (singlePublicIp != null) { - s_logger.info("Successfully got public Ip " + singlePublicIp + " for user " + myUser.getUserName()); - } else { - s_logger.info("Problems with getting public Ip address for user" + myUser.getUserName()); - break; - } - - //create ForwardProxy rules for user's VMs - int responseCode = CreateForwardingRule(myUser, singlePrivateIp, singlePublicIp, "22", "22"); - if (responseCode == 500) - break; - } - - s_logger.info("Deployment successful..." + s_numVM + " VMs were created. Waiting for 5 min before performance test"); - Thread.sleep(300000L); // Wait - - //Start performance test for the user - s_logger.info("Starting performance test for Guest network that has " + myUser.getPublicIp().size() + " public IP addresses"); - for (int j = 0; j < myUser.getPublicIp().size(); j++) { - s_logger.info("Starting test for user which has " + myUser.getVirtualMachines().size() + " vms. Public IP for the user is " + - myUser.getPublicIp().get(j) + " , number of retries is " + Retry + " , private IP address of the machine is" + - myUser.getVirtualMachines().get(j).getPrivateIp()); - GuestNetwork myNetwork = new GuestNetwork(myUser.getPublicIp().get(j), Retry); - myNetwork.setVirtualMachines(myUser.getVirtualMachines()); - new Thread(myNetwork).start(); - } - - } - } catch (Exception e) { - s_logger.error(e); - } - } - }).start(); - - } - } - - private static int CreateForwardingRule(User myUser, String privateIp, String publicIp, String publicPort, String privatePort) throws IOException { - String encodedPrivateIp = URLEncoder.encode("" + privateIp, "UTF-8"); - String encodedPublicIp = URLEncoder.encode("" + publicIp, "UTF-8"); - String encodedPrivatePort = URLEncoder.encode("" + privatePort, "UTF-8"); - String encodedPublicPort = URLEncoder.encode("" + publicPort, "UTF-8"); - String encodedApiKey = URLEncoder.encode(myUser.getApiKey(), "UTF-8"); - int responseCode = 500; - - String requestToSign = - "apiKey=" + encodedApiKey + "&command=createOrUpdateIpForwardingRule&privateIp=" + encodedPrivateIp + "&privatePort=" + encodedPrivatePort + - "&protocol=tcp&publicIp=" + encodedPublicIp + "&publicPort=" + encodedPublicPort; - - requestToSign = requestToSign.toLowerCase(); - s_logger.info("Request to sign is " + requestToSign); - - String signature = TestClientWithAPI.signRequest(requestToSign, myUser.getSecretKey()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - String url = - myUser.getDeveloperServer() + "?command=createOrUpdateIpForwardingRule" + "&publicIp=" + encodedPublicIp + "&publicPort=" + encodedPublicPort + - "&privateIp=" + encodedPrivateIp + "&privatePort=" + encodedPrivatePort + "&protocol=tcp&apiKey=" + encodedApiKey + "&signature=" + encodedSignature; - - s_logger.info("Trying to create IP forwarding rule: " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("create ip forwarding rule response code: " + responseCode); - if (responseCode == 200) { - s_logger.info("The rule is created successfully"); - } else if (responseCode == 500) { - InputStream is = method.getResponseBodyAsStream(); - Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"errorCode", "description"}); - s_logger.error("create ip forwarding rule (linux) test failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + - errorInfo.get("description")); - } else { - s_logger.error("internal error processing request: " + method.getStatusText()); - } - return responseCode; - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/longrun/User.java b/test/src-not-used/main/java/com/cloud/test/longrun/User.java deleted file mode 100644 index 06234c846ab..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/longrun/User.java +++ /dev/null @@ -1,202 +0,0 @@ -// 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.test.longrun; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Map; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; - -import com.cloud.test.stress.TestClientWithAPI; - -public class User { - public static final Logger s_logger = Logger.getLogger(User.class.getClass()); - - private ArrayList virtualMachines; - private ArrayList publicIp; - private String server; - private String developerServer; - private String userName; - private String userId; - private String apiKey; - private String secretKey; - private String password; - private String encryptedPassword; - - public User(String userName, String password, String server, String developerServer) { - this.server = server; - this.developerServer = developerServer; - this.userName = userName; - this.password = password; - this.virtualMachines = new ArrayList(); - this.publicIp = new ArrayList(); - } - - public ArrayList getVirtualMachines() { - return virtualMachines; - } - - public void setVirtualMachines(ArrayList virtualMachines) { - this.virtualMachines = virtualMachines; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public ArrayList getPublicIp() { - return publicIp; - } - - public void setPublicIp(ArrayList publicIp) { - this.publicIp = publicIp; - } - - public String getServer() { - return server; - } - - public void setServer(String server) { - this.server = server; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getApiKey() { - return apiKey; - } - - public void setApiKey(String apiKey) { - this.apiKey = apiKey; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getSecretKey() { - return secretKey; - } - - public void setSecretKey(String secretKey) { - this.secretKey = secretKey; - } - - public String getDeveloperServer() { - return developerServer; - } - - public void setDeveloperServer(String developerServer) { - this.developerServer = developerServer; - } - - public void launchUser() throws IOException { - String encodedUsername = URLEncoder.encode(this.getUserName(), "UTF-8"); - this.encryptedPassword = TestClientWithAPI.createMD5Password(this.getPassword()); - String encodedPassword = URLEncoder.encode(this.encryptedPassword, "UTF-8"); - String url = - this.server + "?command=createUser&username=" + encodedUsername + "&password=" + encodedPassword + - "&firstname=Test&lastname=Test&email=alena@vmops.com&domainId=1"; - String userIdStr = null; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userIdValues = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"id"}); - userIdStr = userIdValues.get("id"); - if ((userIdStr != null) && (Long.parseLong(userIdStr) != -1)) { - this.setUserId(userIdStr); - } - } - } - - public void retrievePublicIp(long zoneId) throws IOException { - - String encodedApiKey = URLEncoder.encode(this.apiKey, "UTF-8"); - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String requestToSign = "apiKey=" + encodedApiKey + "&command=associateIpAddress" + "&zoneId=" + encodedZoneId; - requestToSign = requestToSign.toLowerCase(); - String signature = TestClientWithAPI.signRequest(requestToSign, this.secretKey); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - String url = this.developerServer + "?command=associateIpAddress" + "&apiKey=" + encodedApiKey + "&zoneId=" + encodedZoneId + "&signature=" + encodedSignature; - - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map values = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"ipaddress"}); - this.getPublicIp().add(values.get("ipaddress")); - s_logger.info("Ip address is " + values.get("ipaddress")); - } else if (responseCode == 500) { - InputStream is = method.getResponseBodyAsStream(); - Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"errorcode", "description"}); - s_logger.error("associate ip test failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + errorInfo.get("description")); - } else { - s_logger.error("internal error processing request: " + method.getStatusText()); - } - - } - - public void registerUser() throws HttpException, IOException { - - String encodedUsername = URLEncoder.encode(this.userName, "UTF-8"); - String encodedPassword = URLEncoder.encode(this.password, "UTF-8"); - String url = server + "?command=register&username=" + encodedUsername + "&domainid=1"; - s_logger.info("registering: " + this.userName + " with url " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map requestKeyValues = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"apikey", "secretkey"}); - this.setApiKey(requestKeyValues.get("apikey")); - this.setSecretKey(requestKeyValues.get("secretkey")); - } else if (responseCode == 500) { - InputStream is = method.getResponseBodyAsStream(); - Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"errorcode", "description"}); - s_logger.error("registration failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + errorInfo.get("description")); - } else { - s_logger.error("internal error processing request: " + method.getStatusText()); - } - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/longrun/VirtualMachine.java b/test/src-not-used/main/java/com/cloud/test/longrun/VirtualMachine.java deleted file mode 100644 index eaed0a2bd12..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/longrun/VirtualMachine.java +++ /dev/null @@ -1,95 +0,0 @@ -// 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.test.longrun; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.util.Map; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; - -import com.cloud.test.stress.TestClientWithAPI; - -public class VirtualMachine { - public static final Logger s_logger = Logger.getLogger(VirtualMachine.class.getClass()); - - private String privateIp; - private String userId; - - public VirtualMachine(String userId) { - this.userId = userId; - } - - public String getPrivateIp() { - return privateIp; - } - - public void setPrivateIp(String privateIp) { - this.privateIp = privateIp; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public void deployVM(long zoneId, long serviceOfferingId, long templateId, String server, String apiKey, String secretKey) throws IOException { - - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); - String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); - String encodedApiKey = URLEncoder.encode(apiKey, "UTF-8"); - String requestToSign = - "apiKey=" + encodedApiKey + "&command=deployVirtualMachine&serviceOfferingId=" + encodedServiceOfferingId + "&templateId=" + encodedTemplateId + "&zoneId=" + - encodedZoneId; - - requestToSign = requestToSign.toLowerCase(); - String signature = TestClientWithAPI.signRequest(requestToSign, secretKey); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - String url = - server + "?command=deployVirtualMachine" + "&zoneId=" + encodedZoneId + "&serviceOfferingId=" + encodedServiceOfferingId + "&templateId=" + - encodedTemplateId + "&apiKey=" + encodedApiKey + "&signature=" + encodedSignature; - - s_logger.info("Sending this request to deploy a VM: " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("deploy linux vm response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map values = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"id", "ipaddress"}); - long linuxVMId = Long.parseLong(values.get("id")); - s_logger.info("got linux virtual machine id: " + linuxVMId); - this.setPrivateIp(values.get("ipaddress")); - - } else if (responseCode == 500) { - InputStream is = method.getResponseBodyAsStream(); - Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"errorcode", "description"}); - s_logger.error("deploy linux vm test failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + errorInfo.get("description")); - } else { - s_logger.error("internal error processing request: " + method.getStatusText()); - } - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/ApiCommand.java b/test/src-not-used/main/java/com/cloud/test/regression/ApiCommand.java deleted file mode 100644 index 9c9fc83bce9..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/ApiCommand.java +++ /dev/null @@ -1,848 +0,0 @@ -// 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.test.regression; - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.net.URLEncoder; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.Random; -import java.util.Set; -import java.util.TreeMap; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.utils.UtilsForTest; - -public class ApiCommand { - public static final Logger s_logger = Logger.getLogger(ApiCommand.class.getName()); - - public static enum CommandType { - HTTP, MYSQL, SCRIPT; - } - - public static enum ResponseType { - ERROR, EMPTY; - } - - private Element xmlCommand; - private String commandName; - private String testCaseInfo; - private boolean isUserCommand; - private boolean isAsync = false; - private CommandType commandType; - private ResponseType responseType; - - private TreeMap urlParam; - private HashMap verifyParam = new HashMap();; - private HashMap setParam = new HashMap();; - private int responseCode; - private Element responseBody; - - private String command; - private String host; - private boolean list; - private Element listName; - private Element listId; - private boolean required = false; - private ResultSet result; - - public ApiCommand(Element fstElmnt, HashMap param, HashMap commands) { - this.setXmlCommand(fstElmnt); - this.setCommandName(); - this.setResponseType(); - this.setUserCommand(); - this.setCommandType(); - this.setTestCaseInfo(); - this.setUrlParam(param); - this.setVerifyParam(param); - this.setHost("http://" + param.get("hostip")); - this.setCommand(param); - String async = commands.get(this.getName()); - if (async != null && async.equals("yes")) { - this.isAsync = true; - - } - } - - public Element getXmlCommand() { - return xmlCommand; - } - - public void setXmlCommand(Element xmlCommand) { - this.xmlCommand = xmlCommand; - } - - // ================FOLLOWING METHODS USE INPUT XML FILE=======================// - public void setCommandName() { - NodeList commandName = this.xmlCommand.getElementsByTagName("name"); - Element commandElmnt = (Element)commandName.item(0); - NodeList commandNm = commandElmnt.getChildNodes(); - this.commandName = (commandNm.item(0).getNodeValue()); - } - - public String getName() { - return commandName; - } - - public void setTestCaseInfo() { - this.testCaseInfo = getElementByName("testcase"); - } - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public void setResponseType() { - boolean result = verifyTagValue("error", "true"); - if (result) { - this.responseType = ResponseType.ERROR; - return; - } - result = verifyTagValue("empty", "true"); - if (result) { - this.responseType = ResponseType.EMPTY; - } - } - - public void setResponseType(ResponseType responseType) { - this.responseType = responseType; - } - - public ResponseType getResponseType() { - return responseType; - } - - public void setUserCommand() { - boolean result = verifyTagValue("usercommand", "true"); - this.isUserCommand = result; - } - - public void setCommandType() { - boolean result = verifyTagValue("mysql", "true"); - if (result) { - this.commandType = CommandType.MYSQL; - return; - } - result = verifyTagValue("script", "true"); - if (result) { - this.commandType = CommandType.SCRIPT; - return; - } - this.commandType = CommandType.HTTP; - } - - public CommandType getCommandType() { - return commandType; - } - - public String getTestCaseInfo() { - return testCaseInfo; - } - - public Boolean getRequired() { - return required; - } - - public void setUrlParam(HashMap param) { - this.urlParam = new TreeMap(); - NodeList parameterLst = this.xmlCommand.getElementsByTagName("parameters"); - if (parameterLst != null) { - for (int j = 0; j < parameterLst.getLength(); j++) { - Element parameterElement = (Element)parameterLst.item(j); - NodeList itemLst = parameterElement.getElementsByTagName("item"); - for (int k = 0; k < itemLst.getLength(); k++) { - Node item = itemLst.item(k); - if (item.getNodeType() == Node.ELEMENT_NODE) { - Element itemElement = (Element)item; - NodeList itemName = itemElement.getElementsByTagName("name"); - Element itemNameElement = (Element)itemName.item(0); - - // get value - Element itemValueElement = null; - if ((itemElement.getElementsByTagName("value") != null) && (itemElement.getElementsByTagName("value").getLength() != 0)) { - NodeList itemValue = itemElement.getElementsByTagName("value"); - itemValueElement = (Element)itemValue.item(0); - } - - Element itemParamElement = null; - // getparam - if ((itemElement.getElementsByTagName("param") != null) && (itemElement.getElementsByTagName("param").getLength() != 0)) { - NodeList itemParam = itemElement.getElementsByTagName("param"); - itemParamElement = (Element)itemParam.item(0); - } - - if ((itemElement.getAttribute("getparam").equals("true")) && (itemParamElement != null)) { - this.urlParam.put(itemNameElement.getTextContent(), param.get(itemParamElement.getTextContent())); - } else if (itemValueElement != null) { - this.urlParam.put(itemNameElement.getTextContent(), itemValueElement.getTextContent()); - } else if (itemElement.getAttribute("random").equals("true")) { - Random ran = new Random(); - String randomString = Math.abs(ran.nextInt()) + "-randomName"; - this.urlParam.put(itemNameElement.getTextContent(), randomString); - if ((itemElement.getAttribute("setparam").equals("true")) && (itemParamElement != null)) { - param.put(itemParamElement.getTextContent(), randomString); - } - } else if (itemElement.getAttribute("randomnumber").equals("true")) { - Random ran = new Random(); - Integer randomNumber = Math.abs(ran.nextInt(65535)); - this.urlParam.put(itemNameElement.getTextContent(), randomNumber.toString()); - if ((itemElement.getAttribute("setparam").equals("true")) && (itemParamElement != null)) { - param.put(itemParamElement.getTextContent(), randomNumber.toString()); - } - } - } - } - } - } - } - - // Set command URL - public void setCommand(HashMap param) { - - if (this.getCommandType() == CommandType.SCRIPT) { - String temp = "bash xen/" + this.commandName; - Set c = this.urlParam.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + " -" + key + " " + value; - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + key + " for the command " + this.getName()); - } - } - this.command = temp; - } else if (this.getCommandType() == CommandType.MYSQL) { - String temp = this.commandName + " where "; - Set c = this.urlParam.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + key + "=" + value; - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + key + " for the command " + this.getName()); - } - } - this.command = temp; - s_logger.info("The command is " + this.command); - - } else { - if ((param.get("apikey") == null) || (param.get("secretkey") == null) || (this.isUserCommand == false)) { - String temp = this.host + ":8096/?command=" + this.commandName; - Set c = this.urlParam.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + "&" + key + "=" + URLEncoder.encode(value, "UTF-8"); - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + key + " for the command " + this.getName()); - } - } - this.command = temp; - } else if (isUserCommand == true) { - String apiKey = param.get("apikey"); - String secretKey = param.get("secretkey"); - - String temp = ""; - this.urlParam.put("apikey", apiKey); - this.urlParam.put("command", this.commandName); - - // sort url hash map by key - Set c = this.urlParam.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + value + " for the command " + this.getName()); - } - - } - temp = temp.substring(0, temp.length() - 1); - String requestToSign = temp.toLowerCase(); - String signature = UtilsForTest.signRequest(requestToSign, secretKey); - String encodedSignature = ""; - try { - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - } catch (Exception ex) { - s_logger.error(ex); - } - this.command = this.host + ":8080/client/api/?" + temp + "&signature=" + encodedSignature; - } - } - } - - public void setVerifyParam(HashMap param) { - NodeList returnLst = this.xmlCommand.getElementsByTagName("returnvalue"); - if (returnLst != null) { - for (int m = 0; m < returnLst.getLength(); m++) { - Element returnElement = (Element)returnLst.item(m); - if (returnElement.getAttribute("list").equals("true")) { - this.list = true; - NodeList elementLst = returnElement.getElementsByTagName("element"); - this.listId = (Element)elementLst.item(0); - NodeList elementName = returnElement.getElementsByTagName("name"); - this.listName = (Element)elementName.item(0); - } else { - this.list = false; - } - - NodeList itemLst1 = returnElement.getElementsByTagName("item"); - if (itemLst1 != null) { - for (int n = 0; n < itemLst1.getLength(); n++) { - Node item = itemLst1.item(n); - if (item.getNodeType() == Node.ELEMENT_NODE) { - Element itemElement = (Element)item; - // get parameter name - NodeList itemName = itemElement.getElementsByTagName("name"); - Element itemNameElement = (Element)itemName.item(0); - - // Get parameters for future use - if (itemElement.getAttribute("setparam").equals("true")) { - NodeList itemVariable = itemElement.getElementsByTagName("param"); - Element itemVariableElement = (Element)itemVariable.item(0); - setParam.put(itemVariableElement.getTextContent(), itemNameElement.getTextContent()); - this.required = true; - } else if (itemElement.getAttribute("getparam").equals("true")) { - NodeList itemVariable = itemElement.getElementsByTagName("param"); - Element itemVariableElement = (Element)itemVariable.item(0); - this.verifyParam.put(itemNameElement.getTextContent(), param.get(itemVariableElement.getTextContent())); - } else if ((itemElement.getElementsByTagName("value") != null) && (itemElement.getElementsByTagName("value").getLength() != 0)) { - NodeList itemVariable = itemElement.getElementsByTagName("value"); - Element itemVariableElement = (Element)itemVariable.item(0); - this.verifyParam.put(itemNameElement.getTextContent(), itemVariableElement.getTextContent()); - } else { - this.verifyParam.put(itemNameElement.getTextContent(), "no value"); - } - } - } - } - } - } - } - - public int getResponseCode() { - return responseCode; - } - - // Send api command to the server - public void sendCommand(HttpClient client, Connection conn) { - if (TestCaseEngine.s_printUrl == true) { - s_logger.info("url is " + this.command); - } - - if (this.getCommandType() == CommandType.SCRIPT) { - try { - s_logger.info("Executing command " + this.command); - Runtime rtime = Runtime.getRuntime(); - Process child = rtime.exec(this.command); - Thread.sleep(10000); - int retCode = child.waitFor(); - if (retCode != 0) { - this.responseCode = retCode; - } else { - this.responseCode = 200; - } - - } catch (Exception ex) { - s_logger.error("Unable to execute a command " + this.command, ex); - } - } else if (this.getCommandType() == CommandType.MYSQL) { - try { - Statement stmt = conn.createStatement(); - this.result = stmt.executeQuery(this.command); - this.responseCode = 200; - } catch (Exception ex) { - this.responseCode = 400; - s_logger.error("Unable to execute mysql query " + this.command, ex); - } - } else { - HttpMethod method = new GetMethod(this.command); - try { - this.responseCode = client.executeMethod(method); - - if (this.responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(is); - doc.getDocumentElement().normalize(); - - if (!(this.isAsync)) { - this.responseBody = doc.getDocumentElement(); - } else { - // get async job result - Element jobTag = (Element)doc.getDocumentElement().getElementsByTagName("jobid").item(0); - String jobId = jobTag.getTextContent(); - Element responseBodyAsyncEl = queryAsyncJobResult(jobId); - if (responseBodyAsyncEl == null) { - s_logger.error("Can't get a async result"); - } else { - this.responseBody = responseBodyAsyncEl; - // get status of the job - Element jobStatusTag = (Element)responseBodyAsyncEl.getElementsByTagName("jobstatus").item(0); - String jobStatus = jobStatusTag.getTextContent(); - if (!jobStatus.equals("1")) { // Need to modify with different error codes for jobAsync -// results - // set fake response code by now - this.responseCode = 400; - } - } - } - } - - if (TestCaseEngine.s_printUrl == true) { - s_logger.info("Response code is " + this.responseCode); - } - } catch (Exception ex) { - s_logger.error("Command " + command + " failed with exception " + ex.getMessage()); - } finally { - method.releaseConnection(); - } - } - } - - // verify if response is empty (contains only root element) - public boolean isEmpty() { - boolean result = false; - if (!this.responseBody.hasChildNodes()) - result = true; - return result; - } - - // ================FOLLOWING METHODS USE RETURN XML FILE=======================// - - public boolean setParam(HashMap param) { - if ((this.responseBody == null) && (this.commandType == CommandType.HTTP)) { - s_logger.error("Response body is empty"); - return false; - } - Boolean result = true; - - if (this.getCommandType() == CommandType.MYSQL) { - Set set = this.setParam.entrySet(); - Iterator it = set.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - String itemName = null; - while (this.result.next()) { - itemName = this.result.getString(value); - } - if (itemName != null) { - param.put(key, itemName); - } else { - s_logger.error("Following return parameter is missing: " + value); - result = false; - } - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + value, ex); - } - } - } else if (this.getCommandType() == CommandType.HTTP) { - if (this.list == false) { - Set set = this.setParam.entrySet(); - Iterator it = set.iterator(); - - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - // set parameters needed for the future use - NodeList itemName = this.responseBody.getElementsByTagName(value); - if ((itemName != null) && (itemName.getLength() != 0)) { - for (int i = 0; i < itemName.getLength(); i++) { - Element itemNameElement = (Element)itemName.item(i); - if (itemNameElement.getChildNodes().getLength() <= 1) { - param.put(key, itemNameElement.getTextContent()); - break; - } - } - } else { - s_logger.error("Following return parameter is missing: " + value); - result = false; - } - } - } else { - Set set = this.setParam.entrySet(); - Iterator it = set.iterator(); - NodeList returnLst = this.responseBody.getElementsByTagName(this.listName.getTextContent()); - Node requiredNode = returnLst.item(Integer.parseInt(this.listId.getTextContent())); - - if (requiredNode.getNodeType() == Node.ELEMENT_NODE) { - Element fstElmnt = (Element)requiredNode; - - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - NodeList itemName = fstElmnt.getElementsByTagName(value); - if ((itemName != null) && (itemName.getLength() != 0)) { - Element itemNameElement = (Element)itemName.item(0); - if (itemNameElement.getChildNodes().getLength() <= 1) { - param.put(key, itemNameElement.getTextContent()); - } - } else { - s_logger.error("Following return parameter is missing: " + value); - result = false; - } - } - } - } - } - return result; - } - - public String getUrl() { - return command; - } - - public boolean verifyParam() { - boolean result = true; - if (this.getCommandType() == CommandType.HTTP) { - if (this.list == false) { - Set set = verifyParam.entrySet(); - Iterator it = set.iterator(); - - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - if (value == null) { - s_logger.error("Parameter " + key + " is missing in the list of global parameters"); - return false; - } - - NodeList itemName = this.responseBody.getElementsByTagName(key); - if ((itemName.getLength() != 0) && (itemName != null)) { - Element itemNameElement = (Element)itemName.item(0); - if (itemNameElement.hasChildNodes()) { - continue; - } - if (!(verifyParam.get(key).equals("no value")) && !(itemNameElement.getTextContent().equals(verifyParam.get(key)))) { - s_logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + " while actual value is " + - itemNameElement.getTextContent()); - result = false; - } - } else { - s_logger.error("Following xml element is missing in the response: " + key); - result = false; - } - } - } - // for multiple elements - else { - Set set = verifyParam.entrySet(); - Iterator it = set.iterator(); - // get list element specified by id - NodeList returnLst = this.responseBody.getElementsByTagName(this.listName.getTextContent()); - Node requiredNode = returnLst.item(Integer.parseInt(this.listId.getTextContent())); - - if (requiredNode.getNodeType() == Node.ELEMENT_NODE) { - Element fstElmnt = (Element)requiredNode; - - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - if (value == null) { - s_logger.error("Parameter " + key + " is missing in the list of global parameters"); - return false; - } - NodeList itemName = fstElmnt.getElementsByTagName(key); - if ((itemName.getLength() != 0) && (itemName != null)) { - Element itemNameElement = (Element)itemName.item(0); - if (!(verifyParam.get(key).equals("no value")) && !(itemNameElement.getTextContent().equals(verifyParam.get(key)))) { - s_logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + - " while actual value is " + itemNameElement.getTextContent()); - result = false; - } - } else { - s_logger.error("Following xml element is missing in the response: " + key); - result = false; - } - } - } - } - } else if (this.getCommandType() == CommandType.MYSQL) { - Set set = verifyParam.entrySet(); - Iterator it = set.iterator(); - - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - if (value == null) { - s_logger.error("Parameter " + key + " is missing in the list of global parameters"); - return false; - } - - String itemName = null; - try { - while (this.result.next()) { - itemName = this.result.getString(key); - } - } catch (Exception ex) { - s_logger.error("Unable to get element from result set " + key); - } - - if (!(value.equals("no value")) && !(itemName.equals(verifyParam.get(key)))) { - s_logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + " while actual value is " + itemName); - result = false; - } - } - } - return result; - } - - public static boolean verifyEvents(String fileName, String level, String host, String account) { - boolean result = false; - HashMap expectedEvents = new HashMap(); - HashMap actualEvents = new HashMap(); - String key = ""; - - File file = new File(fileName); - if (file.exists()) { - Properties pro = new Properties(); - try { - // get expected events - FileInputStream in = new FileInputStream(file); - pro.load(in); - Enumeration en = pro.propertyNames(); - while (en.hasMoreElements()) { - key = (String)en.nextElement(); - expectedEvents.put(key, Integer.parseInt(pro.getProperty(key))); - } - - // get actual events - String url = host + "/?command=listEvents&account=" + account + "&level=" + level + "&domainid=1&pagesize=100"; - s_logger.info("Getting events with the following url " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - ArrayList> eventValues = UtilsForTest.parseMulXML(is, new String[] {"event"}); - - for (int i = 0; i < eventValues.size(); i++) { - HashMap element = eventValues.get(i); - if (element.get("level").equals(level)) { - if (actualEvents.containsKey(element.get("type")) == true) { - actualEvents.put(element.get("type"), actualEvents.get(element.get("type")) + 1); - } else { - actualEvents.put(element.get("type"), 1); - } - } - } - } - method.releaseConnection(); - - // compare actual events with expected events - - // compare expected result and actual result - Iterator iterator = expectedEvents.keySet().iterator(); - Integer expected; - Integer actual; - int fail = 0; - while (iterator.hasNext()) { - expected = null; - actual = null; - String type = iterator.next().toString(); - expected = expectedEvents.get(type); - actual = actualEvents.get(type); - if (actual == null) { - s_logger.error("Event of type " + type + " and level " + level + " is missing in the listEvents response. Expected number of these events is " + - expected); - fail++; - } else if (expected.compareTo(actual) != 0) { - fail++; - s_logger.info("Amount of events of " + type + " type and level " + level + " is incorrect. Expected number of these events is " + expected + - ", actual number is " + actual); - } - } - if (fail == 0) { - result = true; - } - } catch (Exception ex) { - s_logger.error(ex); - } - } else { - s_logger.info("File " + fileName + " not found"); - } - return result; - } - - public static boolean verifyEvents(HashMap expectedEvents, String level, String host, String parameters) { - boolean result = false; - HashMap actualEvents = new HashMap(); - try { - // get actual events - String url = host + "/?command=listEvents&" + parameters; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - ArrayList> eventValues = UtilsForTest.parseMulXML(is, new String[] {"event"}); - - for (int i = 0; i < eventValues.size(); i++) { - HashMap element = eventValues.get(i); - if (element.get("level").equals(level)) { - if (actualEvents.containsKey(element.get("type")) == true) { - actualEvents.put(element.get("type"), actualEvents.get(element.get("type")) + 1); - } else { - actualEvents.put(element.get("type"), 1); - } - } - } - } - method.releaseConnection(); - } catch (Exception ex) { - s_logger.error(ex); - } - - // compare actual events with expected events - Iterator iterator = expectedEvents.keySet().iterator(); - Integer expected; - Integer actual; - int fail = 0; - while (iterator.hasNext()) { - expected = null; - actual = null; - String type = iterator.next().toString(); - expected = expectedEvents.get(type); - actual = actualEvents.get(type); - if (actual == null) { - s_logger.error("Event of type " + type + " and level " + level + " is missing in the listEvents response. Expected number of these events is " + expected); - fail++; - } else if (expected.compareTo(actual) != 0) { - fail++; - s_logger.info("Amount of events of " + type + " type and level " + level + " is incorrect. Expected number of these events is " + expected + - ", actual number is " + actual); - } - } - - if (fail == 0) { - result = true; - } - - return result; - } - - public Element queryAsyncJobResult(String jobId) { - Element returnBody = null; - int code = 400; - String resultUrl = this.host + ":8096/?command=queryAsyncJobResult&jobid=" + jobId; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(resultUrl); - while (true) { - try { - code = client.executeMethod(method); - if (code == 200) { - InputStream is = method.getResponseBodyAsStream(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(is); - doc.getDocumentElement().normalize(); - returnBody = doc.getDocumentElement(); - Element jobStatusTag = (Element)returnBody.getElementsByTagName("jobstatus").item(0); - String jobStatus = jobStatusTag.getTextContent(); - if (jobStatus.equals("0")) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - s_logger.debug("[ignored] interrupted while during async job result query."); - } - } else { - break; - } - method.releaseConnection(); - } else { - s_logger.error("Error during queryJobAsync. Error code is " + code); - this.responseCode = code; - return null; - } - } catch (Exception ex) { - s_logger.error(ex); - } - } - return returnBody; - } - - private String getElementByName(String elementName) { - NodeList commandName = this.xmlCommand.getElementsByTagName(elementName); - if (commandName.getLength() != 0) { - Element commandElmnt = (Element)commandName.item(0); - NodeList commandNm = commandElmnt.getChildNodes(); - return commandNm.item(0).getNodeValue(); - } else { - return null; - } - } - - private boolean verifyTagValue(String elementName, String expectedValue) { - NodeList tag = this.xmlCommand.getElementsByTagName(elementName); - if (tag.getLength() != 0) { - Element commandElmnt = (Element)tag.item(0); - NodeList commandNm = commandElmnt.getChildNodes(); - if (commandNm.item(0).getNodeValue().equals(expectedValue)) { - return true; - } else { - return false; - } - } else { - return false; - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/ConfigTest.java b/test/src-not-used/main/java/com/cloud/test/regression/ConfigTest.java deleted file mode 100644 index 8d5c3587a54..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/ConfigTest.java +++ /dev/null @@ -1,125 +0,0 @@ -// 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.test.regression; - -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.Session; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class ConfigTest extends TestCase { - public static final Logger s_logger = Logger.getLogger(ConfigTest.class.getName()); - - public ConfigTest() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - if (api.getName().equals("rebootManagementServer")) { - - s_logger.info("Attempting to SSH into management server " + this.getParam().get("hostip")); - try { - Connection conn = new Connection(this.getParam().get("hostip")); - conn.connect(null, 60000, 60000); - - s_logger.info("SSHed successfully into management server " + this.getParam().get("hostip")); - - boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password"); - return false; - } - - String restartCommand = "service cloud-management restart; service cloud-usage restart"; - Session sess = conn.openSession(); - s_logger.info("Executing : " + restartCommand); - sess.execCommand(restartCommand); - Thread.sleep(120000); - sess.close(); - conn.close(); - - } catch (Exception ex) { - s_logger.error(ex); - return false; - } - } else { - //send a command - api.sendCommand(this.getClient(), null); - - //verify the response of the command - if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200) && (api.getTestCaseInfo() != null)) { - s_logger.error("Test case " + api.getTestCaseInfo() + - "failed. Command that was supposed to fail, passed. The command was sent with the following url " + api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + - " didn't return parameters needed for the future use. The command was sent with url " + api.getUrl()); - return false; - } else { - //verify parameters - if (api.verifyParam() == false) { - s_logger.error("Command " + api.getName() + " failed. Verification for returned parameters failed. Command was sent with url " + api.getUrl()); - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed. Command was sent with the url " + api.getUrl()); - } - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Command " + api.getName() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + api.getUrl() + - " Required: " + api.getRequired()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed. Command that was supposed to fail, failed - test passed. Command was sent with url " + - api.getUrl()); - } - } - } - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/DelegatedAdminTest.java b/test/src-not-used/main/java/com/cloud/test/regression/DelegatedAdminTest.java deleted file mode 100644 index cad22db07e2..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/DelegatedAdminTest.java +++ /dev/null @@ -1,129 +0,0 @@ -// 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.test.regression; - -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class DelegatedAdminTest extends TestCase { - - public static final Logger s_logger = Logger.getLogger(DelegatedAdminTest.class.getName()); - - public DelegatedAdminTest() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - int error = 0; - - for (Document eachElement : this.getInputFile()) { - - Element rootElement = eachElement.getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - boolean verify = false; - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - if ((eachElement.getElementsByTagName("delegated_admin_verify_part2").getLength() != 0) && !(api.getName().equals("registerUserKeys"))) { - if (api.getName().startsWith("list")) { - - if (this.denyToExecute()) { - api.setResponseType(ResponseType.EMPTY); - } - verify = true; - } - - if (this.denyToExecute()) { - api.setResponseType(ResponseType.ERROR); - } - } - - //send a command - api.sendCommand(this.getClient(), null); - - //verify the response of the command - if ((verify == true) && !(api.getResponseType() == ResponseType.ERROR || api.getResponseType() == ResponseType.EMPTY)) { - s_logger.error("Test case " + api.getTestCaseInfo() + - " failed. Command that was supposed to fail, passed. The command was sent with the following url " + api.getUrl()); - error++; - } else if ((verify == true) && (api.getResponseType() == ResponseType.ERROR || api.getResponseType() == ResponseType.EMPTY)) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } else if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + - " failed. Command that was supposed to fail, passed. The command was sent with the following url " + api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + - " didn't return parameters needed for the future use. The command was sent with url " + api.getUrl()); - return false; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + - api.getUrl()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - - } - } - } - - if (error != 0) - return false; - else - return true; - } - - public boolean denyToExecute() { - boolean result = true; - Integer level1 = Integer.valueOf(this.getParam().get("domainlevel1")); - Integer level2 = Integer.valueOf(this.getParam().get("domainlevel2")); - String domain1 = this.getParam().get("domainname1"); - String domain2 = this.getParam().get("domainname2"); - - if (this.getParam().get("accounttype2").equals("1")) { - result = false; - } else if ((level2.compareTo(level1) < 0) && (domain1.startsWith(domain2)) && (this.getParam().get("accounttype2").equals("2"))) { - result = false; - } - - return result; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/Deploy.java b/test/src-not-used/main/java/com/cloud/test/regression/Deploy.java deleted file mode 100644 index 716e6277bec..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/Deploy.java +++ /dev/null @@ -1,109 +0,0 @@ -// 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.test.regression; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class Deploy extends TestCase { - public static final Logger s_logger = Logger.getLogger(Deploy.class.getName()); - - public Deploy() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), null); - - //verify the response of the command - if (api.getResponseCode() != 200) { - error++; - s_logger.error("The command " + api.getUrl() + " failed"); - } else { - s_logger.info("The command " + api.getUrl() + " passsed"); - } - } - if (error != 0) - return false; - else - return true; - } - - public static void main(String[] args) { - - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - String host = null; - String file = null; - - while (iter.hasNext()) { - String arg = iter.next(); - // management server host - if (arg.equals("-h")) { - host = iter.next(); - } - if (arg.equals("-f")) { - file = iter.next(); - } - } - - Deploy deploy = new Deploy(); - - ArrayList inputFile = new ArrayList(); - inputFile.add(file); - deploy.setInputFile(inputFile); - deploy.setTestCaseName("Management server deployment"); - deploy.getParam().put("hostip", host); - deploy.getParam().put("apicommands", "../metadata/func/commands"); - deploy.setCommands(); - - s_logger.info("Starting deployment against host " + host); - - boolean result = deploy.executeTest(); - if (result == false) { - s_logger.error("DEPLOYMENT FAILED"); - System.exit(1); - } else { - s_logger.info("DEPLOYMENT IS SUCCESSFUL"); - } - - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/EventsApiTest.java b/test/src-not-used/main/java/com/cloud/test/regression/EventsApiTest.java deleted file mode 100644 index 6d724c02587..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/EventsApiTest.java +++ /dev/null @@ -1,176 +0,0 @@ -// 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.test.regression; - -import java.sql.Statement; -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.Session; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class EventsApiTest extends TestCase { - public static final Logger s_logger = Logger.getLogger(EventsApiTest.class.getName()); - - public EventsApiTest() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //!!!check if we need to execute mySql command - NodeList commandName = fstElmnt.getElementsByTagName("name"); - Element commandElmnt = (Element)commandName.item(0); - NodeList commandNm = commandElmnt.getChildNodes(); - if (commandNm.item(0).getNodeValue().equals("mysqlupdate")) { - //establish connection to mysql server and execute an update command - NodeList mysqlList = fstElmnt.getElementsByTagName("mysqlcommand"); - for (int j = 0; j < mysqlList.getLength(); j++) { - Element itemVariableElement = (Element)mysqlList.item(j); - - s_logger.info("Executing mysql command " + itemVariableElement.getTextContent()); - try { - Statement st = this.getConn().createStatement(); - st.executeUpdate(itemVariableElement.getTextContent()); - } catch (Exception ex) { - s_logger.error(ex); - return false; - } - } - } - - else if (commandNm.item(0).getNodeValue().equals("agentcommand")) { - //connect to all the agents and execute agent command - NodeList commandList = fstElmnt.getElementsByTagName("commandname"); - Element commandElement = (Element)commandList.item(0); - NodeList ipList = fstElmnt.getElementsByTagName("ip"); - for (int j = 0; j < ipList.getLength(); j++) { - Element itemVariableElement = (Element)ipList.item(j); - - s_logger.info("Attempting to SSH into agent " + itemVariableElement.getTextContent()); - try { - Connection conn = new Connection(itemVariableElement.getTextContent()); - conn.connect(null, 60000, 60000); - - s_logger.info("SSHed successfully into agent " + itemVariableElement.getTextContent()); - - boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password"); - return false; - } - - Session sess = conn.openSession(); - s_logger.info("Executing : " + commandElement.getTextContent()); - sess.execCommand(commandElement.getTextContent()); - Thread.sleep(60000); - sess.close(); - conn.close(); - - } catch (Exception ex) { - s_logger.error(ex); - return false; - } - } - } - - else { - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), null); - - //verify the response of the command - if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + - " failed. Command that was supposed to fail, passed. The command was sent with the following url " + api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //verify if response is suppposed to be empty - if (api.getResponseType() == ResponseType.EMPTY) { - if (api.isEmpty() == true) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed. Empty response was returned as expected. Command was sent with url " + - api.getUrl()); - } else { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Empty response was expected. Command was sent with url " + api.getUrl()); - } - } else { - if (api.isEmpty() != false) - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Non-empty response was expected. Command was sent with url " + api.getUrl()); - else { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + - " didn't return parameters needed for the future use. The command was sent with url " + api.getUrl()); - return false; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed. Command was sent with the url " + api.getUrl()); - } - } - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Command " + api.getName() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + api.getUrl()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed. Command that was supposed to fail, failed. Command was sent with url " + api.getUrl()); - - } - } - } - - //verify events with userid parameter - test case 97 - HashMap expectedEvents = new HashMap(); - expectedEvents.put("VM.START", 1); - boolean eventResult = - ApiCommand.verifyEvents(expectedEvents, "INFO", "http://" + this.getParam().get("hostip") + ":8096", "userid=" + this.getParam().get("userid1") + - "&type=VM.START"); - s_logger.info("Test case 97 - listEvent command verification result is " + eventResult); - - //verify error events - eventResult = - ApiCommand.verifyEvents("../metadata/error_events.properties", "ERROR", "http://" + this.getParam().get("hostip") + ":8096", - this.getParam().get("erroruseraccount")); - s_logger.info("listEvent command verification result is " + eventResult); - - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/HA.java b/test/src-not-used/main/java/com/cloud/test/regression/HA.java deleted file mode 100644 index 0a17a5b7582..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/HA.java +++ /dev/null @@ -1,80 +0,0 @@ -// 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.test.regression; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class HA extends TestCase { - - public static final Logger s_logger = Logger.getLogger(HA.class.getName()); - - public HA() { - this.setClient(); - } - - @Override - public boolean executeTest() { - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), this.getConn()); - - //verify the response parameters - if ((api.getResponseCode() != 200) && (api.getRequired() == true)) { - s_logger.error("Exiting the test....Command " + api.getName() + " required for the future run, failed with an error code " + api.getResponseCode() + - ". Command was sent with the url " + api.getUrl()); - return false; - } else if ((api.getResponseCode() != 200) && (api.getResponseType() != ResponseType.ERROR)) { - error++; - s_logger.error("Command " + api.getTestCaseInfo() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + - api.getUrl()); - } else if ((api.getResponseCode() == 200) && (api.getResponseType() == ResponseType.ERROR)) { - error++; - s_logger.error("Command " + api.getTestCaseInfo() + " which was supposed to failed, passed. The command was sent with url " + api.getUrl()); - } else { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + " didn't return parameters needed for the future use. Command was sent with url " + - api.getUrl()); - return false; - } - s_logger.info("Command " + api.getTestCaseInfo() + " passed"); - } - } - - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/LoadBalancingTest.java b/test/src-not-used/main/java/com/cloud/test/regression/LoadBalancingTest.java deleted file mode 100644 index cdbc5364137..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/LoadBalancingTest.java +++ /dev/null @@ -1,142 +0,0 @@ -// 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.test.regression; - -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class LoadBalancingTest extends TestCase { - - public static final Logger s_logger = Logger.getLogger(LoadBalancingTest.class.getName()); - - public LoadBalancingTest() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), null); - - //verify the response of the command - if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Command that was supposed to fail, passed. The command was sent with the following url " + - api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //verify if response is suppposed to be empty - if (api.getResponseType() == ResponseType.EMPTY) { - if (api.isEmpty() == true) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } else { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Empty response was expected. Command was sent with url " + api.getUrl()); - } - } else { - if (api.isEmpty() != false) - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Non-empty response was expected. Command was sent with url " + api.getUrl()); - else { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + - " didn't return parameters needed for the future use. The command was sent with url " + api.getUrl()); - return false; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } - } - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Command was sent with url " + api.getUrl()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - - } - } - -// //Try to create portForwarding rule for all available private/public ports -// ArrayList port = new ArrayList(); -// for (int i=1; i<65536; i++){ -// port.add(Integer.toString(i)); -// } -// -// //try all public ports -// for (String portValue : port) { -// try { -// String url = this.getHost() + ":8096/?command=createOrUpdateLoadBalancerRule&account=" + this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + -// "&privateip=" + this.getParam().get("vmipaddress") + "&privateport=22&protocol=tcp&publicport=" + portValue; -// HttpClient client = new HttpClient(); -// HttpMethod method = new GetMethod(url); -// int responseCode = client.executeMethod(method); -// if (responseCode != 200 ) { -// error++; -// s_logger.error("Can't create LB rule for the public port " + portValue + ". Request was sent with url " + url); -// } -// }catch (Exception ex) { -// s_logger.error(ex); -// } -// } -// -// //try all private ports -// for (String portValue : port) { -// try { -// String url = this.getHost() + ":8096/?command=createOrUpdateLoadBalancerRule&account=" + this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + -// "&privateip=" + this.getParam().get("vmipaddress") + "&publicport=22&protocol=tcp&privateport=" + portValue; -// HttpClient client = new HttpClient(); -// HttpMethod method = new GetMethod(url); -// int responseCode = client.executeMethod(method); -// if (responseCode != 200 ) { -// error++; -// s_logger.error("Can't create LB rule for the private port " + portValue + ". Request was sent with url " + url); -// } -// }catch (Exception ex) { -// s_logger.error(ex); -// } -// } - - if (error != 0) - return false; - else - return true; - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/PortForwardingTest.java b/test/src-not-used/main/java/com/cloud/test/regression/PortForwardingTest.java deleted file mode 100644 index 24415fdc69a..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/PortForwardingTest.java +++ /dev/null @@ -1,143 +0,0 @@ -// 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.test.regression; - -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class PortForwardingTest extends TestCase { - public static final Logger s_logger = Logger.getLogger(PortForwardingTest.class.getName()); - - public PortForwardingTest() { - setClient(); - setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - - int error = 0; - Element rootElement = getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, getParam(), getCommands()); - - //send a command - api.sendCommand(getClient(), null); - - //verify the response of the command - if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Command that was supposed to fail, passed. The command was sent with the following url " + - api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //verify if response is suppposed to be empty - if (api.getResponseType() == ResponseType.EMPTY) { - if (api.isEmpty() == true) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } else { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Empty response was expected. Command was sent with url " + api.getUrl()); - } - } else { - if (api.isEmpty() != false) - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Non-empty response was expected. Command was sent with url " + api.getUrl()); - else { - //set parameters for the future use - if (api.setParam(getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + - " didn't return parameters needed for the future use. The command was sent with url " + api.getUrl()); - return false; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } - } - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed . Command was sent with url " + api.getUrl()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - - } - } - -// //Try to create portForwarding rule for all available private/public ports -// ArrayList port = new ArrayList(); -// for (int i=1; i<65536; i++){ -// port.add(Integer.toString(i)); -// } -// -// //try all public ports -// for (String portValue : port) { -// try { -// s_logger.info("public port is " + portValue); -// String url = this.getHost() + ":8096/?command=createOrUpdateIpForwardingRule&account=" + this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + -// "&privateip=" + this.getParam().get("vmipaddress") + "&privateport=22&protocol=tcp&publicport=" + portValue; -// HttpClient client = new HttpClient(); -// HttpMethod method = new GetMethod(url); -// int responseCode = client.executeMethod(method); -// if (responseCode != 200 ) { -// error++; -// s_logger.error("Can't create portForwarding rule for the public port " + portValue + ". Request was sent with url " + url); -// } -// }catch (Exception ex) { -// s_logger.error(ex); -// } -// } -// -// //try all private ports -// for (String portValue : port) { -// try { -// String url = this.getHost() + ":8096/?command=createOrUpdateIpForwardingRule&account=" + -// this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + -// "&privateip=" + this.getParam().get("vmipaddress") + "&publicport=22&protocol=tcp&privateport=" + portValue; -// HttpClient client = new HttpClient(); -// HttpMethod method = new GetMethod(url); -// int responseCode = client.executeMethod(method); -// if (responseCode != 200 ) { -// error++; -// s_logger.error("Can't create portForwarding rule for the private port " + portValue + ". Request was sent with url " + url); -// } -// }catch (Exception ex) { -// s_logger.error(ex); -// } -// } - - if (error != 0) - return false; - else - return true; - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/SanityTest.java b/test/src-not-used/main/java/com/cloud/test/regression/SanityTest.java deleted file mode 100644 index defb232b5af..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/SanityTest.java +++ /dev/null @@ -1,86 +0,0 @@ -// 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.test.regression; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class SanityTest extends TestCase { - - public static final Logger s_logger = Logger.getLogger(SanityTest.class.getName()); - - public SanityTest() { - this.setClient(); - } - - @Override - public boolean executeTest() { - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - api.sendCommand(this.getClient(), null); - - //verify the response parameters - if ((api.getResponseCode() != 200) && (api.getRequired() == true)) { - s_logger.error("Exiting the test....Command " + api.getName() + " required for the future run, failed with an error code " + api.getResponseCode() + - ". Command was sent with the url " + api.getUrl()); - return false; - } else if (api.getResponseCode() != 200) { - error++; - s_logger.error("Test " + api.getTestCaseInfo() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + api.getUrl()); - } else { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + " didn't return parameters needed for the future use. Command was sent with url " + - api.getUrl()); - return false; - } - - //verify parameters - if (api.verifyParam() == false) { - s_logger.error("Test " + api.getTestCaseInfo() + " failed. Verification for returned parameters failed. The command was sent with url " + - api.getUrl()); - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test " + api.getTestCaseInfo() + " passed"); - } - } - } - - //verify event - boolean eventResult = - ApiCommand.verifyEvents("../metadata/func/regression_events.properties", "INFO", "http://" + this.getParam().get("hostip") + ":8096", - this.getParam().get("accountname")); - s_logger.info("listEvent command verification result is " + eventResult); - - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/Test.java b/test/src-not-used/main/java/com/cloud/test/regression/Test.java deleted file mode 100644 index 5c6b336de9d..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/Test.java +++ /dev/null @@ -1,88 +0,0 @@ -// 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.test.regression; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class Test extends TestCase { - public static final Logger s_logger = Logger.getLogger(Test.class.getName()); - - public Test() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), null); - - } - - //Try to create portForwarding rule for all available private/public ports - ArrayList port = new ArrayList(); - for (int j = 1; j < 1000; j++) { - port.add(Integer.toString(j)); - } - - //try all public ports - for (String portValue : port) { - try { - s_logger.info("public port is " + portValue); - String url = - "http://" + this.getParam().get("hostip") + ":8096/?command=createNetworkRule&publicPort=" + portValue + - "&privatePort=22&protocol=tcp&isForward=true&securityGroupId=1&account=admin"; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode != 200) { - error++; - s_logger.error("Can't create portForwarding network rule for the public port " + portValue + ". Request was sent with url " + url); - } - } catch (Exception ex) { - s_logger.error(ex); - } - } - - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/TestCase.java b/test/src-not-used/main/java/com/cloud/test/regression/TestCase.java deleted file mode 100644 index cb7395c07bf..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/TestCase.java +++ /dev/null @@ -1,138 +0,0 @@ -// 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.test.regression; - -import java.io.File; -import java.io.FileInputStream; -import java.sql.Connection; -import java.sql.DriverManager; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Properties; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -public abstract class TestCase { - - public static Logger s_logger = Logger.getLogger(TestCase.class.getName()); - private Connection conn; - private ArrayList inputFile = new ArrayList(); - private HttpClient client; - private String testCaseName; - private HashMap param = new HashMap(); - private HashMap commands = new HashMap(); - - public HashMap getParam() { - return param; - } - - public void setParam(HashMap param) { - this.param = param; - } - - public HashMap getCommands() { - return commands; - } - - public void setCommands() { - File asyncCommands = null; - if (param.get("apicommands") == null) { - s_logger.info("Unable to get the list of commands, exiting"); - System.exit(1); - } else { - asyncCommands = new File(param.get("apicommands")); - } - try { - Properties pro = new Properties(); - FileInputStream in = new FileInputStream(asyncCommands); - pro.load(in); - Enumeration en = pro.propertyNames(); - while (en.hasMoreElements()) { - String key = (String)en.nextElement(); - commands.put(key, pro.getProperty(key)); - } - } catch (Exception ex) { - s_logger.info("Unable to find the file " + param.get("apicommands") + " due to following exception " + ex); - } - - } - - public Connection getConn() { - return conn; - } - - public void setConn(String dbPassword) { - this.conn = null; - try { - Class.forName("com.mysql.jdbc.Driver"); - this.conn = DriverManager.getConnection("jdbc:mysql://" + param.get("db") + "/cloud", "root", dbPassword); - if (!this.conn.isValid(0)) { - s_logger.error("Connection to DB failed to establish"); - } - - } catch (Exception ex) { - s_logger.error(ex); - } - } - - public void setInputFile(ArrayList fileNameInput) { - for (String fileName : fileNameInput) { - File file = new File(fileName); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - Document doc = null; - try { - DocumentBuilder builder = factory.newDocumentBuilder(); - doc = builder.parse(file); - doc.getDocumentElement().normalize(); - } catch (Exception ex) { - s_logger.error("Unable to load " + fileName + " due to ", ex); - } - this.inputFile.add(doc); - } - } - - public ArrayList getInputFile() { - return inputFile; - } - - public void setTestCaseName(String testCaseName) { - this.testCaseName = testCaseName; - } - - public String getTestCaseName() { - return this.testCaseName; - } - - public void setClient() { - HttpClient client = new HttpClient(); - this.client = client; - } - - public HttpClient getClient() { - return this.client; - } - - //abstract methods - public abstract boolean executeTest(); - -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/TestCaseEngine.java b/test/src-not-used/main/java/com/cloud/test/regression/TestCaseEngine.java deleted file mode 100644 index 4207e1786f5..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/TestCaseEngine.java +++ /dev/null @@ -1,275 +0,0 @@ -// 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.test.regression; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class TestCaseEngine { - - public static final Logger s_logger = Logger.getLogger(TestCaseEngine.class.getName()); - public static String s_fileName = "../metadata/adapter.xml"; - public static HashMap s_globalParameters = new HashMap(); - protected static HashMap s_componentMap = new HashMap(); - protected static HashMap> s_inputFile = new HashMap>(); - protected static String s_testCaseName = new String(); - protected static ArrayList s_keys = new ArrayList(); - private static ThreadLocal s_result = new ThreadLocal(); - public static int s_numThreads = 1; - public static boolean s_repeat = false; - public static boolean s_printUrl = false; - public static String s_type = "All"; - public static boolean s_isSanity = false; - public static boolean s_isRegression = false; - private static int s_failure = 0; - - public static void main(String args[]) { - - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - // is stress? - if (arg.equals("-t")) { - s_numThreads = Integer.parseInt(iter.next()); - } - // do you want to print url for all commands? - if (arg.equals("-p")) { - s_printUrl = true; - } - - //type of the test: sanity, regression, all (default) - if (arg.equals("-type")) { - s_type = iter.next(); - } - - if (arg.equals("-repeat")) { - s_repeat = Boolean.valueOf(iter.next()); - } - - if (arg.equals("-filename")) { - s_fileName = iter.next(); - } - } - - if (s_type.equalsIgnoreCase("sanity")) - s_isSanity = true; - else if (s_type.equalsIgnoreCase("regression")) - s_isRegression = true; - - try { - // parse adapter.xml file to get list of tests to execute - File file = new File(s_fileName); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(file); - doc.getDocumentElement().normalize(); - Element root = doc.getDocumentElement(); - - // set global parameters - setGlobalParams(root); - - // populate _componentMap - setComponent(root); - - // set error to 0 by default - - // execute test - for (int i = 0; i < s_numThreads; i++) { - if (s_numThreads > 1) { - s_logger.info("STARTING STRESS TEST IN " + s_numThreads + " THREADS"); - } else { - s_logger.info("STARTING FUNCTIONAL TEST"); - } - new Thread(new Runnable() { - @Override - public void run() { - do { - if (s_numThreads == 1) { - try { - for (String key : s_keys) { - Class c = Class.forName(s_componentMap.get(key)); - TestCase component = (TestCase)c.newInstance(); - executeTest(key, c, component); - } - } catch (Exception ex1) { - s_logger.error(ex1); - } finally { - if (s_failure > 0) { - System.exit(1); - } - } - } else { - Random ran = new Random(); - Integer randomNumber = Math.abs(ran.nextInt(s_keys.size())); - try { - String key = s_keys.get(randomNumber); - Class c = Class.forName(s_componentMap.get(key)); - TestCase component = (TestCase)c.newInstance(); - executeTest(key, c, component); - } catch (Exception e) { - s_logger.error("Error in thread ", e); - } - } - } while (s_repeat); - } - }).start(); - } - - } catch (Exception exc) { - s_logger.error(exc); - } - } - - public static void setGlobalParams(Element rootElement) { - NodeList globalParam = rootElement.getElementsByTagName("globalparam"); - Element parameter = (Element)globalParam.item(0); - NodeList paramLst = parameter.getElementsByTagName("param"); - - for (int i = 0; i < paramLst.getLength(); i++) { - Element paramElement = (Element)paramLst.item(i); - - if (paramElement.getNodeType() == Node.ELEMENT_NODE) { - Element itemElement = paramElement; - NodeList itemName = itemElement.getElementsByTagName("name"); - Element itemNameElement = (Element)itemName.item(0); - NodeList itemVariable = itemElement.getElementsByTagName("variable"); - Element itemVariableElement = (Element)itemVariable.item(0); - s_globalParameters.put(itemVariableElement.getTextContent(), itemNameElement.getTextContent()); - } - } - } - - public static void setComponent(Element rootElement) { - NodeList testLst = rootElement.getElementsByTagName("test"); - for (int j = 0; j < testLst.getLength(); j++) { - Element testElement = (Element)testLst.item(j); - - if (testElement.getNodeType() == Node.ELEMENT_NODE) { - Element itemElement = testElement; - - // get test case name - NodeList testCaseNameList = itemElement.getElementsByTagName("testname"); - if (testCaseNameList != null) { - s_testCaseName = ((Element)testCaseNameList.item(0)).getTextContent(); - } - - if (s_isSanity == true && !s_testCaseName.equals("SANITY TEST")) - continue; - else if (s_isRegression == true && !(s_testCaseName.equals("SANITY TEST") || s_testCaseName.equals("REGRESSION TEST"))) - continue; - - // set class name - NodeList className = itemElement.getElementsByTagName("class"); - if ((className.getLength() == 0) || (className == null)) { - s_componentMap.put(s_testCaseName, "com.cloud.test.regression.VMApiTest"); - } else { - String name = ((Element)className.item(0)).getTextContent(); - s_componentMap.put(s_testCaseName, name); - } - - // set input file name - NodeList inputFileNameLst = itemElement.getElementsByTagName("filename"); - s_inputFile.put(s_testCaseName, new ArrayList()); - for (int k = 0; k < inputFileNameLst.getLength(); k++) { - String inputFileName = ((Element)inputFileNameLst.item(k)).getTextContent(); - s_inputFile.get(s_testCaseName).add(inputFileName); - } - } - } - - //If sanity test required, make sure that SANITY TEST componennt got loaded - if (s_isSanity == true && s_componentMap.size() == 0) { - s_logger.error("FAILURE!!! Failed to load SANITY TEST component. Verify that the test is uncommented in adapter.xml"); - System.exit(1); - } - - if (s_isRegression == true && s_componentMap.size() != 2) { - s_logger.error("FAILURE!!! Failed to load SANITY TEST or REGRESSION TEST components. Verify that these tests are uncommented in adapter.xml"); - System.exit(1); - } - - // put all keys from _componentMap to the ArrayList - Set set = s_componentMap.entrySet(); - Iterator it = set.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - s_keys.add(key); - } - - } - - public static boolean executeTest(String key, Class c, TestCase component) { - boolean finalResult = false; - try { - s_logger.info("Starting \"" + key + "\" test...\n\n"); - - // set global parameters - HashMap updateParam = new HashMap(); - updateParam.putAll(s_globalParameters); - component.setParam(updateParam); - - // set DB ip address - component.setConn(s_globalParameters.get("dbPassword")); - - // set commands list - component.setCommands(); - - // set input file - if (s_inputFile.get(key) != null) { - component.setInputFile(s_inputFile.get(key)); - } - - // set test case name - if (key != null) { - component.setTestCaseName(s_testCaseName); - } - - // execute method - s_result.set(component.executeTest()); - if (s_result.get().toString().equals("false")) { - s_logger.error("FAILURE!!! Test \"" + key + "\" failed\n\n\n"); - s_failure++; - } else { - finalResult = true; - s_logger.info("SUCCESS!!! Test \"" + key + "\" passed\n\n\n"); - } - - } catch (Exception ex) { - s_logger.error("error during test execution ", ex); - } - return finalResult; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/VMApiTest.java b/test/src-not-used/main/java/com/cloud/test/regression/VMApiTest.java deleted file mode 100644 index 28877c59705..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/VMApiTest.java +++ /dev/null @@ -1,91 +0,0 @@ -// 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.test.regression; - -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class VMApiTest extends TestCase { - public static final Logger s_logger = Logger.getLogger(VMApiTest.class.getName()); - - public VMApiTest() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), this.getConn()); - - //verify the response of the command - if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Command that was supposed to fail, passed. The command was sent with the following url " + - api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + " didn't return parameters needed for the future use. The command was sent with url " + - api.getUrl()); - return false; - } - //verify parameters - if (api.verifyParam() == false) { - s_logger.error("Test " + api.getTestCaseInfo() + " failed. Verification for returned parameters failed. The command was sent with url " + - api.getUrl()); - error++; - } else { - s_logger.info("Test " + api.getTestCaseInfo() + " passed"); - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + - api.getUrl()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - - } - } - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/stress/SshTest.java b/test/src-not-used/main/java/com/cloud/test/stress/SshTest.java deleted file mode 100644 index a49dbadf1d5..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/stress/SshTest.java +++ /dev/null @@ -1,90 +0,0 @@ -// 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.test.stress; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import org.apache.log4j.Logger; - -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.Session; - -public class SshTest { - - public static final Logger s_logger = Logger.getLogger(SshTest.class.getName()); - public static String host = ""; - public static String password = "password"; - public static String url = "http://google.com"; - - public static void main(String[] args) { - - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - if (arg.equals("-h")) { - host = iter.next(); - } - if (arg.equals("-p")) { - password = iter.next(); - } - - if (arg.equals("-u")) { - url = iter.next(); - } - } - - if (host == null || host.equals("")) { - s_logger.info("Did not receive a host back from test, ignoring ssh test"); - System.exit(2); - } - - if (password == null) { - s_logger.info("Did not receive a password back from test, ignoring ssh test"); - System.exit(2); - } - - try { - s_logger.info("Attempting to SSH into host " + host); - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User + ssHed successfully into host " + host); - - boolean isAuthenticated = conn.authenticateWithPassword("root", password); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password" + password); - System.exit(2); - } - - String linuxCommand = "wget " + url; - Session sess = conn.openSession(); - sess.execCommand(linuxCommand); - sess.close(); - conn.close(); - - } catch (Exception e) { - s_logger.error("SSH test fail with error", e); - System.exit(2); - } - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/stress/StressTestDirectAttach.java b/test/src-not-used/main/java/com/cloud/test/stress/StressTestDirectAttach.java deleted file mode 100644 index 5625830b238..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/stress/StressTestDirectAttach.java +++ /dev/null @@ -1,1353 +0,0 @@ -// 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.test.stress; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.net.URLEncoder; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.trilead.ssh2.ChannelCondition; -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.SCPClient; -import com.trilead.ssh2.Session; - -import com.cloud.utils.exception.CloudRuntimeException; - -public class StressTestDirectAttach { - private static long sleepTime = 180000L; // default 0 - private static boolean cleanUp = true; - public static final Logger s_logger = Logger.getLogger(StressTestDirectAttach.class.getName()); - private static boolean repeat = true; - private static String[] users = null; - private static boolean internet = false; - private static ThreadLocal s_linuxIP = new ThreadLocal(); - private static ThreadLocal s_linuxVmId = new ThreadLocal(); - private static ThreadLocal s_linuxVmId1 = new ThreadLocal(); - private static ThreadLocal s_linuxPassword = new ThreadLocal(); - private static ThreadLocal s_windowsIP = new ThreadLocal(); - private static ThreadLocal s_secretKey = new ThreadLocal(); - private static ThreadLocal s_apiKey = new ThreadLocal(); - private static ThreadLocal s_userId = new ThreadLocal(); - private static ThreadLocal s_account = new ThreadLocal(); - private static ThreadLocal s_domainRouterId = new ThreadLocal(); - private static ThreadLocal s_newVolume = new ThreadLocal(); - private static ThreadLocal s_newVolume1 = new ThreadLocal(); - private static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - private static int usageIterator = 1; - private static int numThreads = 1; - private static int wait = 5000; - private static String accountName = null; - private static String zoneId = "1"; - private static String serviceOfferingId = "13"; - private static String diskOfferingId = "11"; - private static String diskOfferingId1 = "12"; - - private static final int MAX_RETRY_LINUX = 10; - private static final int MAX_RETRY_WIN = 10; - - public static void main(String[] args) { - String host = "http://localhost"; - String port = "8092"; - String devPort = "8080"; - String apiUrl = "/client/api"; - - try { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - // host - if (arg.equals("-h")) { - host = "http://" + iter.next(); - } - - if (arg.equals("-p")) { - port = iter.next(); - } - if (arg.equals("-dp")) { - devPort = iter.next(); - } - - if (arg.equals("-t")) { - numThreads = Integer.parseInt(iter.next()); - } - - if (arg.equals("-s")) { - sleepTime = Long.parseLong(iter.next()); - } - if (arg.equals("-a")) { - accountName = iter.next(); - } - - if (arg.equals("-c")) { - cleanUp = Boolean.parseBoolean(iter.next()); - if (!cleanUp) - sleepTime = 0L; // no need to wait if we don't ever - // cleanup - } - - if (arg.equals("-r")) { - repeat = Boolean.parseBoolean(iter.next()); - } - - if (arg.equals("-i")) { - internet = Boolean.parseBoolean(iter.next()); - } - - if (arg.equals("-w")) { - wait = Integer.parseInt(iter.next()); - } - - if (arg.equals("-z")) { - zoneId = iter.next(); - } - - if (arg.equals("-so")) { - serviceOfferingId = iter.next(); - } - - } - - final String server = host + ":" + port + "/"; - final String developerServer = host + ":" + devPort + apiUrl; - s_logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); - if (cleanUp) - s_logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up"); - - for (int i = 0; i < numThreads; i++) { - new Thread(new Runnable() { - @Override - public void run() { - do { - String username = null; - try { - long now = System.currentTimeMillis(); - Random ran = new Random(); - username = Math.abs(ran.nextInt()) + "-user"; - NDC.push(username); - - s_logger.info("Starting test for the user " + username); - int response = executeDeployment(server, developerServer, username); - boolean success = false; - String reason = null; - - if (response == 200) { - success = true; - if (internet) { - s_logger.info("Deploy successful...waiting 5 minute before SSH tests"); - Thread.sleep(300000L); // Wait 60 - // seconds so - // the windows VM - // can boot up and do a sys prep. - - s_logger.info("Begin Linux SSH test for account " + s_account.get()); - reason = sshTest(s_linuxIP.get(), s_linuxPassword.get()); - - if (reason == null) { - s_logger.info("Linux SSH test successful for account " + s_account.get()); - } - } - if (reason == null) { - if (internet) { - s_logger.info("Windows SSH test successful for account " + s_account.get()); - } else { - s_logger.info("deploy test successful....now cleaning up"); - if (cleanUp) { - s_logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); - Thread.sleep(sleepTime); - } else { - success = true; - } - } - - if (usageIterator >= numThreads) { - int eventsAndBillingResponseCode = executeEventsAndBilling(server, developerServer); - s_logger.info("events and usage records command finished with response code: " + eventsAndBillingResponseCode); - usageIterator = 1; - - } else { - s_logger.info("Skipping events and usage records for this user: usageIterator " + usageIterator + " and number of Threads " + - numThreads); - usageIterator++; - } - - if ((users == null) && (accountName == null)) { - s_logger.info("Sending cleanup command"); - int cleanupResponseCode = executeCleanup(server, developerServer, username); - s_logger.info("cleanup command finished with response code: " + cleanupResponseCode); - success = (cleanupResponseCode == 200); - } else { - s_logger.info("Sending stop DomR / destroy VM command"); - int stopResponseCode = executeStop(server, developerServer, username); - s_logger.info("stop(destroy) command finished with response code: " + stopResponseCode); - success = (stopResponseCode == 200); - } - - } else { - // Just stop but don't destroy the - // VMs/Routers - s_logger.info("SSH test failed for account " + s_account.get() + "with reason '" + reason + "', stopping VMs"); - int stopResponseCode = executeStop(server, developerServer, username); - s_logger.info("stop command finished with response code: " + stopResponseCode); - success = false; // since the SSH test - // failed, mark the - // whole test as - // failure - } - } else { - // Just stop but don't destroy the - // VMs/Routers - s_logger.info("Deploy test failed with reason '" + reason + "', stopping VMs"); - int stopResponseCode = executeStop(server, developerServer, username); - s_logger.info("stop command finished with response code: " + stopResponseCode); - success = false; // since the deploy test - // failed, mark the - // whole test as failure - } - - if (success) { - s_logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); - - } else { - s_logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + - " seconds with reason : " + reason); - } - s_logger.info("Sleeping for " + wait + " seconds before starting next iteration"); - Thread.sleep(wait); - } catch (Exception e) { - s_logger.warn("Error in thread", e); - try { - int stopResponseCode = executeStop(server, developerServer, username); - s_logger.info("stop response code: " + stopResponseCode); - } catch (Exception e1) { - s_logger.info("[ignored]" - + "error executing stop during stress test: " + e1.getLocalizedMessage()); - } - } finally { - NDC.clear(); - } - } while (repeat); - } - }).start(); - } - } catch (Exception e) { - s_logger.error(e); - } - } - - public static Map> getMultipleValuesFromXML(InputStream is, String[] tagNames) { - Map> returnValues = new HashMap>(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - List valueList = new ArrayList(); - for (int j = 0; j < targetNodes.getLength(); j++) { - Node node = targetNodes.item(j); - valueList.add(node.getTextContent()); - } - returnValues.put(tagNames[i], valueList); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - public static Map getSingleValueFromXML(InputStream is, String[] tagNames) { - Map returnValues = new HashMap(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - s_logger.error("error processing XML", ex); - } - return returnValues; - } - - public static Map getSingleValueFromXML(Element rootElement, String[] tagNames) { - Map returnValues = new HashMap(); - if (rootElement == null) { - s_logger.error("Root element is null, can't get single value from xml"); - return null; - } - try { - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - s_logger.error("error processing XML", ex); - } - return returnValues; - } - - private static List getNonSourceNatIPs(InputStream is) { - List returnValues = new ArrayList(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - NodeList allocatedIpAddrNodes = rootElement.getElementsByTagName("publicipaddress"); - for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { - Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); - NodeList childNodes = allocatedIpAddrNode.getChildNodes(); - String ipAddress = null; - boolean isSourceNat = true; // assume it's source nat until we - // find otherwise - for (int j = 0; j < childNodes.getLength(); j++) { - Node n = childNodes.item(j); - if ("ipaddress".equals(n.getNodeName())) { - ipAddress = n.getTextContent(); - } else if ("issourcenat".equals(n.getNodeName())) { - isSourceNat = Boolean.parseBoolean(n.getTextContent()); - } - } - if ((ipAddress != null) && !isSourceNat) { - returnValues.add(ipAddress); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - private static List getSourceNatIPs(InputStream is) { - List returnValues = new ArrayList(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - NodeList allocatedIpAddrNodes = rootElement.getElementsByTagName("publicipaddress"); - for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { - Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); - NodeList childNodes = allocatedIpAddrNode.getChildNodes(); - String ipAddress = null; - boolean isSourceNat = false; // assume it's *not* source nat until we find otherwise - for (int j = 0; j < childNodes.getLength(); j++) { - Node n = childNodes.item(j); - if ("ipaddress".equals(n.getNodeName())) { - ipAddress = n.getTextContent(); - } else if ("issourcenat".equals(n.getNodeName())) { - isSourceNat = Boolean.parseBoolean(n.getTextContent()); - } - } - if ((ipAddress != null) && isSourceNat) { - returnValues.add(ipAddress); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - private static String executeRegistration(String server, String username, String password) throws HttpException, IOException { - String url = server + "?command=registerUserKeys&id=" + s_userId.get().toString(); - s_logger.info("registering: " + username); - String returnValue = null; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map requestKeyValues = getSingleValueFromXML(is, new String[] {"apikey", "secretkey"}); - s_apiKey.set(requestKeyValues.get("apikey")); - returnValue = requestKeyValues.get("secretkey"); - } else { - s_logger.error("registration failed with error code: " + responseCode); - } - return returnValue; - } - - private static Integer executeDeployment(String server, String developerServer, String username) throws HttpException, IOException { - // test steps: - // - create user - // - deploy Windows VM - // - deploy Linux VM - // - associate IP address - // - create two IP forwarding rules - // - create load balancer rule - // - list IP forwarding rules - // - list load balancer rules - - // ----------------------------- - // CREATE USER - // ----------------------------- - String encodedUsername = URLEncoder.encode(username, "UTF-8"); - String encryptedPassword = createMD5Password(username); - String encodedPassword = URLEncoder.encode(encryptedPassword, "UTF-8"); - - String url = - server + "?command=createUser&username=" + encodedUsername + "&password=" + encodedPassword + - "&firstname=Test&lastname=Test&email=test@vmops.com&domainId=1&accounttype=0"; - if (accountName != null) { - url = - server + "?command=createUser&username=" + encodedUsername + "&password=" + encodedPassword + - "&firstname=Test&lastname=Test&email=test@vmops.com&domainId=1&accounttype=0&account=" + accountName; - } - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - long userId = -1; - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userIdValues = getSingleValueFromXML(is, new String[] {"id", "account"}); - String userIdStr = userIdValues.get("id"); - s_logger.info("created user " + username + " with id " + userIdStr); - if (userIdStr != null) { - userId = Long.parseLong(userIdStr); - s_userId.set(userId); - s_account.set(userIdValues.get("account")); - if (userId == -1) { - s_logger.error("create user (" + username + ") failed to retrieve a valid user id, aborting depolyment test"); - return -1; - } - } - } else { - s_logger.error("create user test failed for user " + username + " with error code :" + responseCode); - return responseCode; - } - - s_secretKey.set(executeRegistration(server, username, username)); - - if (s_secretKey.get() == null) { - s_logger.error("FAILED to retrieve secret key during registration, skipping user: " + username); - return -1; - } else { - s_logger.info("got secret key: " + s_secretKey.get()); - s_logger.info("got api key: " + s_apiKey.get()); - } - - // --------------------------------- - // CREATE NETWORK GROUP AND ADD INGRESS RULE TO IT - // --------------------------------- - String networkAccount = null; - if (accountName != null) { - networkAccount = accountName; - } else { - networkAccount = encodedUsername; - } - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=createSecurityGroup&name=" + encodedUsername; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - url = developerServer + "?command=createSecurityGroup&name=" + encodedUsername + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map values = getSingleValueFromXML(is, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("Create network rule response code: 401"); - return 401; - } else { - s_logger.info("Create security group response code: " + responseCode); - } - } else { - s_logger.error("Create security group failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - String encodedCidr = URLEncoder.encode("192.168.1.143/32", "UTF-8"); - url = - server + "?command=authorizeSecurityGroupIngress&cidrlist=" + encodedCidr + "&endport=22&" + "securitygroupname=" + encodedUsername + - "&protocol=tcp&startport=22&account=" + networkAccount + "&domainid=1"; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("Authorise security group ingress response code: 401"); - return 401; - } else { - s_logger.info("Authorise security group ingress response code: " + responseCode); - } - } else { - s_logger.error("Authorise security group ingress failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // --------------------------------- - // DEPLOY LINUX VM - // --------------------------------- - { - long templateId = 2; - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); - String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); - encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - requestToSign = - "apikey=" + encodedApiKey + "&command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&serviceofferingid=" + encodedServiceOfferingId + - "&templateid=" + encodedTemplateId + "&zoneid=" + encodedZoneId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - url = - developerServer + "?command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + - encodedServiceOfferingId + "&templateid=" + encodedTemplateId + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id", "ipaddress"}); - - if ((values.get("ipaddress") == null) || (values.get("id") == null)) { - s_logger.info("deploy linux vm response code: 401"); - return 401; - } else { - s_logger.info("deploy linux vm response code: " + responseCode); - long linuxVMId = Long.parseLong(values.get("id")); - s_logger.info("got linux virtual machine id: " + linuxVMId); - s_linuxVmId.set(values.get("id")); - s_linuxIP.set(values.get("ipaddress")); - s_linuxPassword.set("rs-ccb35ea5"); - } - } else { - s_logger.error("deploy linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //Create a new volume - { - url = server + "?command=createVolume&diskofferingid=" + diskOfferingId + "&zoneid=" + zoneId + "&name=newvolume&account=" + s_account.get() + "&domainid=1"; - s_logger.info("Creating volume...."); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("create volume response code: 401"); - return 401; - } else { - s_logger.info("create volume response code: " + responseCode); - String volumeId = values.get("id"); - s_logger.info("got volume id: " + volumeId); - s_newVolume.set(volumeId); - } - } else { - s_logger.error("create volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //attach a new volume to the vm - { - url = server + "?command=attachVolume&id=" + s_newVolume.get() + "&virtualmachineid=" + s_linuxVmId.get(); - s_logger.info("Attaching volume with id " + s_newVolume.get() + " to the vm " + s_linuxVmId.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Attach data volume response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("Attach volume response code: 401"); - return 401; - } else { - s_logger.info("Attach volume response code: " + responseCode); - } - } else { - s_logger.error("Attach volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //DEPLOY SECOND VM, ADD VOLUME TO IT - - // --------------------------------- - // DEPLOY another linux vm - // --------------------------------- - { - long templateId = 2; - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); - String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); - encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - requestToSign = - "apikey=" + encodedApiKey + "&command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&serviceofferingid=" + encodedServiceOfferingId + - "&templateid=" + encodedTemplateId + "&zoneid=" + encodedZoneId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - url = - developerServer + "?command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + - encodedServiceOfferingId + "&templateid=" + encodedTemplateId + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id", "ipaddress"}); - - if ((values.get("ipaddress") == null) || (values.get("id") == null)) { - s_logger.info("deploy linux vm response code: 401"); - return 401; - } else { - s_logger.info("deploy linux vm response code: " + responseCode); - long linuxVMId = Long.parseLong(values.get("id")); - s_logger.info("got linux virtual machine id: " + linuxVMId); - s_linuxVmId1.set(values.get("id")); - } - } else { - s_logger.error("deploy linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //Create a new volume - { - url = server + "?command=createVolume&diskofferingid=" + diskOfferingId1 + "&zoneid=" + zoneId + "&name=newvolume1&account=" + s_account.get() + "&domainid=1"; - s_logger.info("Creating volume...."); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("create volume response code: 401"); - return 401; - } else { - s_logger.info("create volume response code: " + responseCode); - String volumeId = values.get("id"); - s_logger.info("got volume id: " + volumeId); - s_newVolume1.set(volumeId); - } - } else { - s_logger.error("create volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //attach a new volume to the vm - { - url = server + "?command=attachVolume&id=" + s_newVolume1.get() + "&virtualmachineid=" + s_linuxVmId1.get(); - s_logger.info("Attaching volume with id " + s_newVolume1.get() + " to the vm " + s_linuxVmId1.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Attach data volume response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("Attach volume response code: 401"); - return 401; - } else { - s_logger.info("Attach volume response code: " + responseCode); - } - } else { - s_logger.error("Attach volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - return 200; - } - - private static int executeCleanup(String server, String developerServer, String username) throws HttpException, IOException { - // test steps: - // - get user - // - delete user - - // ----------------------------- - // GET USER - // ----------------------------- - String userId = s_userId.get().toString(); - String encodedUserId = URLEncoder.encode(userId, "UTF-8"); - String url = server + "?command=listUsers&id=" + encodedUserId; - s_logger.info("Cleaning up resources for user: " + userId + " with url " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userInfo = getSingleValueFromXML(is, new String[] {"username", "id", "account"}); - if (!username.equals(userInfo.get("username"))) { - s_logger.error("get user failed to retrieve requested user, aborting cleanup test" + ". Following URL was sent: " + url); - return -1; - } - - } else { - s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ----------------------------- - // UPDATE USER - // ----------------------------- - { - url = server + "?command=updateUser&id=" + userId + "&firstname=delete&lastname=me"; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("update user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"success"}); - s_logger.info("update user..success? " + success.get("success")); - } else { - s_logger.error("update user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // ----------------------------- - // Execute reboot/stop/start commands for the VMs before deleting the account - made to exercise xen - // ----------------------------- - - //Reboot centos VM - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=rebootVirtualMachine&id=" + s_linuxVmId.get(); - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=rebootVirtualMachine&id=" + s_linuxVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Reboot VM response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info("VM was rebooted with the status: " + success.get("success")); - } else { - s_logger.error(" VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - //Stop centos VM - requestToSign = "apikey=" + encodedApiKey + "&command=stopVirtualMachine&id=" + s_linuxVmId.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=stopVirtualMachine&id=" + s_linuxVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Stop VM response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info("VM was stopped with the status: " + success.get("success")); - } else { - s_logger.error("Stop VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - //Start centos VM - requestToSign = "apikey=" + encodedApiKey + "&command=startVirtualMachine&id=" + s_linuxVmId.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=startVirtualMachine&id=" + s_linuxVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Start VM response code: " + responseCode); - - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"id"}); - - if (success.get("id") == null) { - s_logger.info("Start linux vm response code: 401"); - return 401; - } else { - s_logger.info("Start vm response code: " + responseCode); - } - - s_logger.info("VM was started with the status: " + success.get("success")); - } else { - s_logger.error("Start VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - -//// // ----------------------------- -//// // DISABLE USER -//// // ----------------------------- -// { -// url = server + "?command=disableUser&id=" + userId; -// client = new HttpClient(); -// method = new GetMethod(url); -// responseCode = client.executeMethod(method); -// s_logger.info("disable user response code: " + responseCode); -// if (responseCode == 200) { -// InputStream input = method.getResponseBodyAsStream(); -// Element el = queryAsyncJobResult(server, input); -// s_logger -// .info("Disabled user successfully"); -// } else { -// s_logger.error("disable user failed with error code: " + responseCode + ". Following URL was sent: " + url); -// return responseCode; -// } -// } - - // ----------------------------- - // DELETE USER - // ----------------------------- - { - url = server + "?command=deleteUser&id=" + userId; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("delete user response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("Deleted user successfully"); - } else { - s_logger.error("delete user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - return responseCode; - } - - private static int executeEventsAndBilling(String server, String developerServer) throws HttpException, IOException { - // test steps: - // - get all the events in the system for all users in the system - // - generate all the usage records in the system - // - get all the usage records in the system - - // ----------------------------- - // GET EVENTS - // ----------------------------- - String url = server + "?command=listEvents&page=1&account=" + s_account.get(); - - s_logger.info("Getting events for the account " + s_account.get()); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get events response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> eventDescriptions = getMultipleValuesFromXML(is, new String[] {"description"}); - List descriptionText = eventDescriptions.get("description"); - if (descriptionText == null) { - s_logger.info("no events retrieved..."); - } else { - for (String text : descriptionText) { - s_logger.info("event: " + text); - } - } - } else { - s_logger.error("list events failed with error code: " + responseCode + ". Following URL was sent: " + url); - - return responseCode; - } - return responseCode; - } - - private static int executeStop(String server, String developerServer, String username) throws HttpException, IOException { - // test steps: - // - get userId for the given username - // - list virtual machines for the user - // - stop all virtual machines - // - get ip addresses for the user - // - release ip addresses - - // ----------------------------- - // GET USER - // ----------------------------- - String userId = s_userId.get().toString(); - String encodedUserId = URLEncoder.encode(userId, "UTF-8"); - - String url = server + "?command=listUsers&id=" + encodedUserId; - s_logger.info("Stopping resources for user: " + username); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userIdValues = getSingleValueFromXML(is, new String[] {"id"}); - String userIdStr = userIdValues.get("id"); - if (userIdStr != null) { - userId = userIdStr; - if (userId == null) { - s_logger.error("get user failed to retrieve a valid user id, aborting depolyment test" + ". Following URL was sent: " + url); - return -1; - } - } - } else { - s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - { - // ---------------------------------- - // LIST VIRTUAL MACHINES - // ---------------------------------- - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=listVirtualMachines"; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listVirtualMachines&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - - s_logger.info("Listing all virtual machines for the user with url " + url); - String[] vmIds = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list virtual machines response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> vmIdValues = getMultipleValuesFromXML(is, new String[] {"id"}); - if (vmIdValues.containsKey("id")) { - List vmIdList = vmIdValues.get("id"); - if (vmIdList != null) { - vmIds = new String[vmIdList.size()]; - vmIdList.toArray(vmIds); - String vmIdLogStr = ""; - if ((vmIds != null) && (vmIds.length > 0)) { - vmIdLogStr = vmIds[0]; - for (int i = 1; i < vmIds.length; i++) { - vmIdLogStr = vmIdLogStr + "," + vmIds[i]; - } - } - s_logger.info("got virtual machine ids: " + vmIdLogStr); - } - } - - } else { - s_logger.error("list virtual machines test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // STOP/DESTROY VIRTUAL MACHINES - // ---------------------------------- - if (vmIds != null) { - for (String vmId : vmIds) { - requestToSign = "apikey=" + encodedApiKey + "&command=stopVirtualMachine&id=" + vmId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=stopVirtualMachine&id=" + vmId + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("StopVirtualMachine" + " [" + vmId + "] response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info("StopVirtualMachine..success? " + success.get("success")); - } else { - s_logger.error("Stop virtual machine test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - } - -// { -// url = server + "?command=deleteUser&id=" + userId; -// client = new HttpClient(); -// method = new GetMethod(url); -// responseCode = client.executeMethod(method); -// s_logger.info("delete user response code: " + responseCode); -// if (responseCode == 200) { -// InputStream input = method.getResponseBodyAsStream(); -// Element el = queryAsyncJobResult(server, input); -// s_logger -// .info("Deleted user successfully"); -// } else { -// s_logger.error("delete user failed with error code: " + responseCode + ". Following URL was sent: " + url); -// return responseCode; -// } -// } - - } - - s_linuxIP.set(""); - s_linuxVmId.set(""); - s_linuxPassword.set(""); - s_windowsIP.set(""); - s_secretKey.set(""); - s_apiKey.set(""); - s_userId.set(Long.parseLong("0")); - s_account.set(""); - s_domainRouterId.set(""); - return responseCode; - } - - public static String signRequest(String request, String key) { - try { - Mac mac = Mac.getInstance("HmacSHA1"); - SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); - mac.init(keySpec); - mac.update(request.getBytes()); - byte[] encryptedBytes = mac.doFinal(); - return Base64.encodeBase64String(encryptedBytes); - } catch (Exception ex) { - s_logger.error("unable to sign request", ex); - } - return null; - } - - private static String sshWinTest(String host) { - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring win ssh test"); - return null; - } - - // We will retry 5 times before quitting - int retry = 1; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt. Account is " + s_account.get()); - Thread.sleep(300000); - } - - s_logger.info("Attempting to SSH into windows host " + host + " with retry attempt: " + retry + " for account " + s_account.get()); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User " + s_account.get() + " ssHed successfully into windows host " + host); - boolean success = false; - boolean isAuthenticated = conn.authenticateWithPassword("Administrator", "password"); - if (isAuthenticated == false) { - return "Authentication failed"; - } else { - s_logger.info("Authentication is successful"); - } - - try { - SCPClient scp = new SCPClient(conn); - scp.put("wget.exe", "wget.exe", "C:\\Users\\Administrator", "0777"); - s_logger.info("Successfully put wget.exe file"); - } catch (Exception ex) { - s_logger.error("Unable to put wget.exe " + ex); - } - - if (conn == null) { - s_logger.error("Connection is null"); - } - Session sess = conn.openSession(); - - s_logger.info("User + " + s_account.get() + " executing : wget http://192.168.1.250/dump.bin"); - sess.execCommand("wget http://192.168.1.250/dump.bin && dir dump.bin"); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - /* int len = */stderr.read(buffer); - } - } - sess.close(); - conn.close(); - - if (success) { - Thread.sleep(120000); - return null; - } else { - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail for account " + s_account.get(); - } - } - } catch (Exception e) { - s_logger.error(e); - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail with error " + e.getMessage(); - } - } - } - } - - private static String sshTest(String host, String password) { - int i = 0; - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring ssh test"); - return null; - } - - if (password == null) { - s_logger.info("Did not receive a password back from test, ignoring ssh test"); - return null; - } - - // We will retry 5 times before quitting - String result = null; - int retry = 0; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt. Account is " + s_account.get()); - Thread.sleep(120000); - } - - s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry + ". Account is " + s_account.get()); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User + " + s_account.get() + " ssHed successfully into linux host " + host); - - boolean isAuthenticated = conn.authenticateWithPassword("root", password); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password" + password); - return "Authentication failed"; - - } - - boolean success = false; - String linuxCommand = null; - - if (i % 10 == 0) - linuxCommand = "rm -rf *; wget http://192.168.1.250/dump.bin && ls -al dump.bin"; - else - linuxCommand = "wget http://192.168.1.250/dump.bin && ls -al dump.bin"; - - Session sess = conn.openSession(); - s_logger.info("User " + s_account.get() + " executing : " + linuxCommand); - sess.execCommand(linuxCommand); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - /* int len = */stderr.read(buffer); - } - } - - sess.close(); - conn.close(); - - if (!success) { - retry++; - if (retry == MAX_RETRY_LINUX) { - result = "SSH Linux Network test fail"; - } - } - - return result; - } catch (Exception e) { - retry++; - s_logger.error("SSH Linux Network test fail with error"); - if (retry == MAX_RETRY_LINUX) { - return "SSH Linux Network test fail with error " + e.getMessage(); - } - } - i++; - } - } - - public static String createMD5Password(String password) { - MessageDigest md5; - - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new CloudRuntimeException("Error", e); - } - - md5.reset(); - BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); - - // make sure our MD5 hash value is 32 digits long... - StringBuffer sb = new StringBuffer(); - String pwStr = pwInt.toString(16); - int padding = 32 - pwStr.length(); - for (int i = 0; i < padding; i++) { - sb.append('0'); - } - sb.append(pwStr); - return sb.toString(); - } - - public static Element queryAsyncJobResult(String host, InputStream inputStream) { - Element returnBody = null; - - Map values = getSingleValueFromXML(inputStream, new String[] {"jobid"}); - String jobId = values.get("jobid"); - - if (jobId == null) { - s_logger.error("Unable to get a jobId"); - return null; - } - - //s_logger.info("Job id is " + jobId); - String resultUrl = host + "?command=queryAsyncJobResult&jobid=" + jobId; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(resultUrl); - while (true) { - try { - client.executeMethod(method); - //s_logger.info("Method is executed successfully. Following url was sent " + resultUrl); - InputStream is = method.getResponseBodyAsStream(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(is); - returnBody = doc.getDocumentElement(); - doc.getDocumentElement().normalize(); - Element jobStatusTag = (Element)returnBody.getElementsByTagName("jobstatus").item(0); - String jobStatus = jobStatusTag.getTextContent(); - if (jobStatus.equals("0")) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - s_logger.debug("[ignored] interrupted while during async job result query."); - } - } else { - break; - } - - } catch (Exception ex) { - s_logger.error(ex); - } - } - return returnBody; - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/stress/TestClientWithAPI.java b/test/src-not-used/main/java/com/cloud/test/stress/TestClientWithAPI.java deleted file mode 100644 index 3d43a9440c7..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/stress/TestClientWithAPI.java +++ /dev/null @@ -1,2289 +0,0 @@ -// 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.test.stress; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.net.URLEncoder; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.trilead.ssh2.ChannelCondition; -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.SCPClient; -import com.trilead.ssh2.Session; - -import com.cloud.utils.exception.CloudRuntimeException; - -public class TestClientWithAPI { - private static long sleepTime = 180000L; // default 0 - private static boolean cleanUp = true; - public static final Logger s_logger = Logger.getLogger(TestClientWithAPI.class); - private static boolean repeat = true; - private static int numOfUsers = 0; - private static String[] users = null; - private static boolean internet = false; - private static ThreadLocal s_linuxIP = new ThreadLocal(); - private static ThreadLocal s_linuxIpId = new ThreadLocal(); - private static ThreadLocal s_linuxVmId = new ThreadLocal(); - private static ThreadLocal s_linuxPassword = new ThreadLocal(); - private static ThreadLocal s_windowsIP = new ThreadLocal(); - private static ThreadLocal s_windowsIpId = new ThreadLocal(); - private static ThreadLocal s_windowsVmId = new ThreadLocal(); - private static ThreadLocal s_secretKey = new ThreadLocal(); - private static ThreadLocal s_apiKey = new ThreadLocal(); - private static ThreadLocal s_userId = new ThreadLocal(); - private static ThreadLocal s_accountId = new ThreadLocal(); - private static ThreadLocal s_account = new ThreadLocal(); - private static ThreadLocal s_domainRouterId = new ThreadLocal(); - private static ThreadLocal s_pfGroupId = new ThreadLocal(); - private static ThreadLocal s_windowsLb = new ThreadLocal(); - private static ThreadLocal s_linuxLb = new ThreadLocal(); - private static ThreadLocal s_dataVolume = new ThreadLocal(); - private static ThreadLocal s_rootVolume = new ThreadLocal(); - private static ThreadLocal s_newVolume = new ThreadLocal(); - private static ThreadLocal s_snapshot = new ThreadLocal(); - private static ThreadLocal s_volumeFromSnapshot = new ThreadLocal(); - private static ThreadLocal s_networkId = new ThreadLocal(); - private static ThreadLocal s_publicIpId = new ThreadLocal(); - private static ThreadLocal s_winipfwdid = new ThreadLocal(); - private static ThreadLocal s_linipfwdid = new ThreadLocal(); - private static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - private static int usageIterator = 1; - private static int numThreads = 1; - private static int wait = 5000; - private static String accountName = null; - private static String zoneId = "1"; - private static String snapshotTest = "no"; - private static String serviceOfferingId = "1"; - private static String diskOfferingId = "4"; - private static String networkOfferingId = "6"; - private static String vmPassword = "rs-ccb35ea5"; - private static String downloadUrl = "192.168.1.250/dump.bin"; - - private static final int MAX_RETRY_LINUX = 10; - private static final int MAX_RETRY_WIN = 10; - - public static void main(String[] args) { - String host = "http://localhost"; - String port = "8092"; - String devPort = "8080"; - String apiUrl = "/client/api"; - - try { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - // host - if (arg.equals("-h")) { - host = "http://" + iter.next(); - } - - if (arg.equals("-p")) { - port = iter.next(); - } - if (arg.equals("-dp")) { - devPort = iter.next(); - } - - if (arg.equals("-t")) { - numThreads = Integer.parseInt(iter.next()); - } - - if (arg.equals("-s")) { - sleepTime = Long.parseLong(iter.next()); - } - if (arg.equals("-a")) { - accountName = iter.next(); - } - - if (arg.equals("-c")) { - cleanUp = Boolean.parseBoolean(iter.next()); - if (!cleanUp) - sleepTime = 0L; // no need to wait if we don't ever - // cleanup - } - - if (arg.equals("-r")) { - repeat = Boolean.parseBoolean(iter.next()); - } - - if (arg.equals("-u")) { - numOfUsers = Integer.parseInt(iter.next()); - } - - if (arg.equals("-i")) { - internet = Boolean.parseBoolean(iter.next()); - } - - if (arg.equals("-w")) { - wait = Integer.parseInt(iter.next()); - } - - if (arg.equals("-z")) { - zoneId = iter.next(); - } - - if (arg.equals("-snapshot")) { - snapshotTest = "yes"; - } - - if (arg.equals("-so")) { - serviceOfferingId = iter.next(); - } - - if (arg.equals("-do")) { - diskOfferingId = iter.next(); - } - - if (arg.equals("-no")) { - networkOfferingId = iter.next(); - } - - if (arg.equals("-pass")) { - vmPassword = iter.next(); - } - - if (arg.equals("-url")) { - downloadUrl = iter.next(); - } - - } - - final String server = host + ":" + port + "/"; - final String developerServer = host + ":" + devPort + apiUrl; - s_logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); - if (cleanUp) - s_logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up"); - - if (numOfUsers > 0) { - s_logger.info("Pre-generating users for test of size : " + numOfUsers); - users = new String[numOfUsers]; - Random ran = new Random(); - for (int i = 0; i < numOfUsers; i++) { - users[i] = Math.abs(ran.nextInt()) + "-user"; - } - } - - for (int i = 0; i < numThreads; i++) { - new Thread(new Runnable() { - @Override - public void run() { - do { - String username = null; - try { - long now = System.currentTimeMillis(); - Random ran = new Random(); - if (users != null) { - username = users[Math.abs(ran.nextInt()) % numOfUsers]; - } else { - username = Math.abs(ran.nextInt()) + "-user"; - } - NDC.push(username); - - s_logger.info("Starting test for the user " + username); - int response = executeDeployment(server, developerServer, username, snapshotTest); - boolean success = false; - String reason = null; - - if (response == 200) { - success = true; - if (internet) { - s_logger.info("Deploy successful...waiting 5 minute before SSH tests"); - Thread.sleep(300000L); // Wait 60 - // seconds so - // the windows VM - // can boot up and do a sys prep. - - if (accountName == null) { - s_logger.info("Begin Linux SSH test for account " + s_account.get()); - reason = sshTest(s_linuxIP.get(), s_linuxPassword.get(), snapshotTest); - } - - if (reason == null) { - s_logger.info("Linux SSH test successful for account " + s_account.get()); - s_logger.info("Begin WindowsSSH test for account " + s_account.get()); - - reason = sshTest(s_linuxIP.get(), s_linuxPassword.get(), snapshotTest); - // reason = sshWinTest(s_windowsIP.get()); - } - - // release the linux IP now... - s_linuxIP.set(null); - // release the Windows IP now - s_windowsIP.set(null); - } - - // sleep for 3 min before getting the latest network stat - // s_logger.info("Sleeping for 5 min before getting the lates network stat for the account"); - // Thread.sleep(300000); - // verify that network stat is correct for the user; if it's not - stop all the resources - // for the user - // if ((reason == null) && (getNetworkStat(server) == false) ) { - // s_logger.error("Stopping all the resources for the account " + s_account.get() + - // " as network stat is incorrect"); - // int stopResponseCode = executeStop( - // server, developerServer, - // username, false); - // s_logger - // .info("stop command finished with response code: " - // + stopResponseCode); - // success = false; // since the SSH test - // - // } else - if (reason == null) { - if (internet) { - s_logger.info("Windows SSH test successful for account " + s_account.get()); - } else { - s_logger.info("deploy test successful....now cleaning up"); - if (cleanUp) { - s_logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); - Thread.sleep(sleepTime); - } else { - success = true; - } - } - - if (usageIterator >= numThreads) { - int eventsAndBillingResponseCode = executeEventsAndBilling(server, developerServer); - s_logger.info("events and usage records command finished with response code: " + eventsAndBillingResponseCode); - usageIterator = 1; - - } else { - s_logger.info("Skipping events and usage records for this user: usageIterator " + usageIterator + " and number of Threads " + - numThreads); - usageIterator++; - } - - if ((users == null) && (accountName == null)) { - s_logger.info("Sending cleanup command"); - int cleanupResponseCode = executeCleanup(server, developerServer, username); - s_logger.info("cleanup command finished with response code: " + cleanupResponseCode); - success = (cleanupResponseCode == 200); - } else { - s_logger.info("Sending stop DomR / destroy VM command"); - int stopResponseCode = executeStop(server, developerServer, username, true); - s_logger.info("stop(destroy) command finished with response code: " + stopResponseCode); - success = (stopResponseCode == 200); - } - - } else { - // Just stop but don't destroy the - // VMs/Routers - s_logger.info("SSH test failed for account " + s_account.get() + "with reason '" + reason + "', stopping VMs"); - int stopResponseCode = executeStop(server, developerServer, username, false); - s_logger.info("stop command finished with response code: " + stopResponseCode); - success = false; // since the SSH test - // failed, mark the - // whole test as - // failure - } - } else { - // Just stop but don't destroy the - // VMs/Routers - s_logger.info("Deploy test failed with reason '" + reason + "', stopping VMs"); - int stopResponseCode = executeStop(server, developerServer, username, true); - s_logger.info("stop command finished with response code: " + stopResponseCode); - success = false; // since the deploy test - // failed, mark the - // whole test as failure - } - - if (success) { - s_logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); - - } else { - s_logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + - " seconds with reason : " + reason); - } - s_logger.info("Sleeping for " + wait + " seconds before starting next iteration"); - Thread.sleep(wait); - } catch (Exception e) { - s_logger.warn("Error in thread", e); - try { - int stopResponseCode = executeStop(server, developerServer, username, true); - s_logger.info("stop response code: " + stopResponseCode); - } catch (Exception e1) { - s_logger.info("[ignored]" - + "error executing stop during api test: " + e1.getLocalizedMessage()); - } - } finally { - NDC.clear(); - } - } while (repeat); - } - }).start(); - } - } catch (Exception e) { - s_logger.error(e); - } - } - - public static Map> getMultipleValuesFromXML(InputStream is, String[] tagNames) { - Map> returnValues = new HashMap>(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - List valueList = new ArrayList(); - for (int j = 0; j < targetNodes.getLength(); j++) { - Node node = targetNodes.item(j); - valueList.add(node.getTextContent()); - } - returnValues.put(tagNames[i], valueList); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - public static Map getSingleValueFromXML(InputStream is, String[] tagNames) { - Map returnValues = new HashMap(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - s_logger.error("error processing XML", ex); - } - return returnValues; - } - - public static Map getSingleValueFromXML(Element rootElement, String[] tagNames) { - Map returnValues = new HashMap(); - if (rootElement == null) { - s_logger.error("Root element is null, can't get single value from xml"); - return null; - } - try { - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - s_logger.error("error processing XML", ex); - } - return returnValues; - } - - private static List getNonSourceNatIPs(InputStream is) { - List returnValues = new ArrayList(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - NodeList allocatedIpAddrNodes = rootElement.getElementsByTagName("publicipaddress"); - for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { - Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); - NodeList childNodes = allocatedIpAddrNode.getChildNodes(); - String ipAddress = null; - boolean isSourceNat = true; // assume it's source nat until we - // find otherwise - for (int j = 0; j < childNodes.getLength(); j++) { - Node n = childNodes.item(j); - if ("id".equals(n.getNodeName())) { - // if ("ipaddress".equals(n.getNodeName())) { - ipAddress = n.getTextContent(); - } else if ("issourcenat".equals(n.getNodeName())) { - isSourceNat = Boolean.parseBoolean(n.getTextContent()); - } - } - if ((ipAddress != null) && !isSourceNat) { - returnValues.add(ipAddress); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - private static List getIPs(InputStream is, boolean sourceNat) { - List returnValues = new ArrayList(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - NodeList allocatedIpAddrNodes = rootElement.getElementsByTagName("publicipaddress"); - for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { - Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); - NodeList childNodes = allocatedIpAddrNode.getChildNodes(); - String ipAddress = null; - String ipAddressId = null; - boolean isSourceNat = false; // assume it's *not* source nat until we find otherwise - for (int j = 0; j < childNodes.getLength(); j++) { - Node n = childNodes.item(j); - //Id is being used instead of ipaddress. Changes need to done later to ipaddress variable - if ("id".equals(n.getNodeName())) { - ipAddressId = n.getTextContent(); - } else if ("ipaddress".equals(n.getNodeName())) { - ipAddress = n.getTextContent(); - } else if ("issourcenat".equals(n.getNodeName())) { - isSourceNat = Boolean.parseBoolean(n.getTextContent()); - } - } - if ((ipAddress != null) && isSourceNat == sourceNat) { - returnValues.add(ipAddressId); - returnValues.add(ipAddress); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - private static String executeRegistration(String server, String username, String password) throws HttpException, IOException { - String url = server + "?command=registerUserKeys&id=" + s_userId.get().toString(); - s_logger.info("registering: " + username); - String returnValue = null; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map requestKeyValues = getSingleValueFromXML(is, new String[] {"apikey", "secretkey"}); - s_apiKey.set(requestKeyValues.get("apikey")); - returnValue = requestKeyValues.get("secretkey"); - } else { - s_logger.error("registration failed with error code: " + responseCode); - } - return returnValue; - } - - private static Integer executeDeployment(String server, String developerServer, String username, String snapshotTest) throws HttpException, IOException { - // test steps: - // - create user - // - deploy Windows VM - // - deploy Linux VM - // - associate IP address - // - create two IP forwarding rules - // - create load balancer rule - // - list IP forwarding rules - // - list load balancer rules - - // ----------------------------- - // CREATE ACCOUNT - // ----------------------------- - String encodedUsername = URLEncoder.encode(username, "UTF-8"); - String encryptedPassword = createMD5Password(username); - String encodedPassword = URLEncoder.encode(encryptedPassword, "UTF-8"); - - String url = - server + "?command=createAccount&username=" + encodedUsername + "&account=" + encodedUsername + "&password=" + encodedPassword + - "&firstname=Test&lastname=Test&email=test@vmops.com&domainId=1&accounttype=0"; - - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - long accountId = -1; - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map accountValues = getSingleValueFromXML(is, new String[] {"id", "name"}); - String accountIdStr = accountValues.get("id"); - s_logger.info("created account " + username + " with id " + accountIdStr); - if (accountIdStr != null) { - accountId = Long.parseLong(accountIdStr); - s_accountId.set(accountId); - s_account.set(accountValues.get("name")); - if (accountId == -1) { - s_logger.error("create account (" + username + ") failed to retrieve a valid user id, aborting depolyment test"); - return -1; - } - } - } else { - s_logger.error("create account test failed for account " + username + " with error code :" + responseCode + - ", aborting deployment test. The command was sent with url " + url); - return -1; - } - - // LIST JUST CREATED USER TO GET THE USER ID - url = server + "?command=listUsers&username=" + encodedUsername + "&account=" + encodedUsername + "&domainId=1"; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - long userId = -1; - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userIdValues = getSingleValueFromXML(is, new String[] {"id"}); - String userIdStr = userIdValues.get("id"); - s_logger.info("listed user " + username + " with id " + userIdStr); - if (userIdStr != null) { - userId = Long.parseLong(userIdStr); - s_userId.set(userId); - if (userId == -1) { - s_logger.error("list user by username " + username + ") failed to retrieve a valid user id, aborting depolyment test"); - return -1; - } - } - } else { - s_logger.error("list user test failed for account " + username + " with error code :" + responseCode + - ", aborting deployment test. The command was sent with url " + url); - return -1; - } - - s_secretKey.set(executeRegistration(server, username, username)); - - if (s_secretKey.get() == null) { - s_logger.error("FAILED to retrieve secret key during registration, skipping user: " + username); - return -1; - } else { - s_logger.info("got secret key: " + s_secretKey.get()); - s_logger.info("got api key: " + s_apiKey.get()); - } - - // --------------------------------- - // CREATE VIRTUAL NETWORK - // --------------------------------- - url = - server + "?command=createNetwork&networkofferingid=" + networkOfferingId + "&account=" + encodedUsername + "&domainId=1" + "&zoneId=" + zoneId + - "&name=virtualnetwork-" + encodedUsername + "&displaytext=virtualnetwork-" + encodedUsername; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map networkValues = getSingleValueFromXML(is, new String[] {"id"}); - String networkIdStr = networkValues.get("id"); - s_logger.info("Created virtual network with name virtualnetwork-" + encodedUsername + " and id " + networkIdStr); - if (networkIdStr != null) { - s_networkId.set(networkIdStr); - } - } else { - s_logger.error("Create virtual network failed for account " + username + " with error code :" + responseCode + - ", aborting deployment test. The command was sent with url " + url); - return -1; - } - /* - // --------------------------------- - // CREATE DIRECT NETWORK - // --------------------------------- - url = server + "?command=createNetwork&networkofferingid=" + networkOfferingId_dir + "&account=" + encodedUsername + "&domainId=1" + "&zoneId=" + zoneId + "&name=directnetwork-" + encodedUsername + "&displaytext=directnetwork-" + encodedUsername; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map networkValues = getSingleValueFromXML(is, new String[] { "id" }); - String networkIdStr = networkValues.get("id"); - s_logger.info("Created direct network with name directnetwork-" + encodedUsername + " and id " + networkIdStr); - if (networkIdStr != null) { - s_networkId_dir.set(networkIdStr); - } - } else { - s_logger.error("Create direct network failed for account " + username + " with error code :" + responseCode + ", aborting deployment test. The command was sent with url " + url); - return -1; - } - */ - - // --------------------------------- - // DEPLOY LINUX VM - // --------------------------------- - String linuxVMPrivateIP = null; - { - // long templateId = 3; - long templateId = 4; - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); - String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String encodedNetworkIds = URLEncoder.encode(s_networkId.get() + ",206", "UTF-8"); - String requestToSign = - "apikey=" + encodedApiKey + "&command=deployVirtualMachine&diskofferingid=" + diskOfferingId + "&networkids=" + encodedNetworkIds + - "&serviceofferingid=" + encodedServiceOfferingId + "&templateid=" + encodedTemplateId + "&zoneid=" + encodedZoneId; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - url = - developerServer + "?command=deployVirtualMachine" + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + encodedServiceOfferingId + "&diskofferingid=" + - diskOfferingId + "&networkids=" + encodedNetworkIds + "&templateid=" + encodedTemplateId + "&apikey=" + encodedApiKey + "&signature=" + - encodedSignature; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id", "ipaddress"}); - - if ((values.get("ipaddress") == null) || (values.get("id") == null)) { - s_logger.info("deploy linux vm response code: 401, the command was sent with url " + url); - return 401; - } else { - s_logger.info("deploy linux vm response code: " + responseCode); - long linuxVMId = Long.parseLong(values.get("id")); - s_logger.info("got linux virtual machine id: " + linuxVMId); - s_linuxVmId.set(values.get("id")); - linuxVMPrivateIP = values.get("ipaddress"); - // s_linuxPassword.set(values.get("password")); - s_linuxPassword.set(vmPassword); - s_logger.info("got linux virtual machine password: " + s_linuxPassword.get()); - } - } else { - s_logger.error("deploy linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - { - // --------------------------------- - // ASSOCIATE IP for windows - // --------------------------------- - String ipAddr = null; - - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=associateIpAddress" + "&zoneid=" + zoneId; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=associateIpAddress" + "&apikey=" + encodedApiKey + "&zoneid=" + zoneId + "&signature=" + encodedSignature; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - /*Asynchronous Job - Corresponding Changes Made*/ - Element associpel = queryAsyncJobResult(server, is); - Map values = getSingleValueFromXML(associpel, new String[] {"id", "ipaddress"}); - - if ((values.get("ipaddress") == null) || (values.get("id") == null)) { - s_logger.info("associate ip for Windows response code: 401, the command was sent with url " + url); - return 401; - } else { - s_logger.info("Associate IP Address response code: " + responseCode); - long publicIpId = Long.parseLong(values.get("id")); - s_logger.info("Associate IP's Id: " + publicIpId); - s_publicIpId.set(values.get("id")); - } - } else { - s_logger.error("associate ip address for windows vm failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - String encodedPublicIpId = URLEncoder.encode(s_publicIpId.get(), "UTF-8"); - requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses" + "&id=" + encodedPublicIpId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&id=" + encodedPublicIpId + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("url is " + url); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - // InputStream ips = method.getResponseBodyAsStream(); - List ipAddressValues = getIPs(is, false); - // List ipAddressVals = getIPs(is, false, true); - if ((ipAddressValues != null) && !ipAddressValues.isEmpty()) { - s_windowsIpId.set(ipAddressValues.get(0)); - s_windowsIP.set(ipAddressValues.get(1)); - s_logger.info("For Windows, using non-sourceNat IP address ID: " + ipAddressValues.get(0)); - s_logger.info("For Windows, using non-sourceNat IP address: " + ipAddressValues.get(1)); - } - } else { - s_logger.error("list ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // --------------------------------- - // Use the SourceNat IP for linux - // --------------------------------- - { - requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("url is " + url); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); -// InputStream ips = method.getResponseBodyAsStream(); - List ipAddressValues = getIPs(is, true); -// is = method.getResponseBodyAsStream(); -// List ipAddressVals = getIPs(is, true, true); - if ((ipAddressValues != null) && !ipAddressValues.isEmpty()) { - s_linuxIpId.set(ipAddressValues.get(0)); - s_linuxIP.set(ipAddressValues.get(1)); - s_logger.info("For linux, using sourceNat IP address ID: " + ipAddressValues.get(0)); - s_logger.info("For linux, using sourceNat IP address: " + ipAddressValues.get(1)); - } - } else { - s_logger.error("list ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //-------------------------------------------- - // Enable Static NAT for the Source NAT Ip - //-------------------------------------------- - String encodedSourceNatPublicIpId = URLEncoder.encode(s_linuxIpId.get(), "UTF-8"); - - /* requestToSign = "apikey=" + encodedApiKey + "&command=enableStaticNat"+"&id=" + encodedSourceNatPublicIpId + "&virtualMachineId=" + encodedVmId;; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=enableStaticNat&apikey=" + encodedApiKey + "&signature=" + encodedSignature + "&id=" + encodedSourceNatPublicIpId + "&virtualMachineId=" + encodedVmId; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("url is " + url); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] { "success" }); - s_logger.info("Enable Static NAT..success? " + success.get("success")); - } else { - s_logger.error("Enable Static NAT failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - */ - // ------------------------------------------------------------- - // CREATE IP FORWARDING RULE -- Linux VM - // ------------------------------------------------------------- - String encodedVmId = URLEncoder.encode(s_linuxVmId.get(), "UTF-8"); - String encodedIpAddress = URLEncoder.encode(s_linuxIpId.get(), "UTF-8"); - requestToSign = - "apikey=" + encodedApiKey + "&command=createPortForwardingRule&ipaddressid=" + encodedIpAddress + "&privateport=22&protocol=TCP&publicport=22" + - "&virtualmachineid=" + encodedVmId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = - developerServer + "?command=createPortForwardingRule&apikey=" + encodedApiKey + "&ipaddressid=" + encodedIpAddress + - "&privateport=22&protocol=TCP&publicport=22&virtualmachineid=" + encodedVmId + "&signature=" + encodedSignature; - - s_logger.info("Created port forwarding rule with " + url); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - s_logger.info("Port forwarding rule was assigned successfully to Linux VM"); - long ipfwdid = Long.parseLong(values.get("id")); - s_logger.info("got Port Forwarding Rule's Id:" + ipfwdid); - s_linipfwdid.set(values.get("id")); - - } else { - s_logger.error("Port forwarding rule creation failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Create snapshot recurring policy if needed; otherwise create windows vm - if (snapshotTest.equals("yes")) { - - // list volumes for linux vm - { - url = server + "?command=listVolumes&virtualMachineId=" + s_linuxVmId.get() + "&type=root"; - s_logger.info("Getting rootDisk id of Centos vm"); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("List volumes response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"id"}); - if (success.get("id") == null) { - s_logger.error("Unable to get root volume for linux vm. Followin url was sent: " + url); - } - s_logger.info("Got rootVolume for linux vm with id " + success.get("id")); - s_rootVolume.set(success.get("id")); - } else { - s_logger.error("List volumes for linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - // Create recurring snapshot policy for linux vm - { - String encodedTimeZone = URLEncoder.encode("America/Los Angeles", "UTF-8"); - url = - server + "?command=createSnapshotPolicy&intervaltype=hourly&schedule=10&maxsnaps=4&volumeid=" + s_rootVolume.get() + "&timezone=" + - encodedTimeZone; - s_logger.info("Creating recurring snapshot policy for linux vm ROOT disk"); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Create recurring snapshot policy for linux vm ROOT disk: " + responseCode); - if (responseCode != 200) { - s_logger.error("Create recurring snapshot policy for linux vm ROOT disk failed with error code: " + responseCode + ". Following URL was sent: " + - url); - return responseCode; - } - } - } else { - // --------------------------------- - // DEPLOY WINDOWS VM - // --------------------------------- - String windowsVMPrivateIP = null; - { - // long templateId = 6; - long templateId = 4; - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); - String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); - encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String encodedNetworkIds = URLEncoder.encode(s_networkId.get() + ",206", "UTF-8"); - - requestToSign = - "apikey=" + encodedApiKey + "&command=deployVirtualMachine&diskofferingid=" + diskOfferingId + "&networkids=" + encodedNetworkIds + - "&serviceofferingid=" + encodedServiceOfferingId + "&templateid=" + encodedTemplateId + "&zoneid=" + encodedZoneId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = - developerServer + "?command=deployVirtualMachine" + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + encodedServiceOfferingId + - "&diskofferingid=" + diskOfferingId + "&networkids=" + encodedNetworkIds + "&templateid=" + encodedTemplateId + "&apikey=" + encodedApiKey + - "&signature=" + encodedSignature; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id", "ipaddress"}); - - if ((values.get("ipaddress") == null) || (values.get("id") == null)) { - s_logger.info("deploy windows vm response code: 401, the command was sent with url " + url); - return 401; - } else { - s_logger.info("deploy windows vm response code: " + responseCode); - windowsVMPrivateIP = values.get("ipaddress"); - long windowsVMId = Long.parseLong(values.get("id")); - s_logger.info("got windows virtual machine id: " + windowsVMId); - s_windowsVmId.set(values.get("id")); - } - } else { - s_logger.error("deploy windows vm failes with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //-------------------------------------------- - // Enable Static NAT for the Non Source NAT Ip - //-------------------------------------------- - - encodedVmId = URLEncoder.encode(s_windowsVmId.get(), "UTF-8"); - encodedPublicIpId = URLEncoder.encode(s_publicIpId.get(), "UTF-8"); - requestToSign = "apikey=" + encodedApiKey + "&command=enableStaticNat" + "&ipaddressid=" + encodedPublicIpId + "&virtualMachineId=" + encodedVmId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = - developerServer + "?command=enableStaticNat&apikey=" + encodedApiKey + "&ipaddressid=" + encodedPublicIpId + "&signature=" + encodedSignature + - "&virtualMachineId=" + encodedVmId; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("url is " + url); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"success"}); - s_logger.info("Enable Static NAT..success? " + success.get("success")); - } else { - s_logger.error("Enable Static NAT failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ------------------------------------------------------------- - // CREATE IP FORWARDING RULE -- Windows VM - // ------------------------------------------------------------- - - // create port forwarding rule for window vm - encodedIpAddress = URLEncoder.encode(s_windowsIpId.get(), "UTF-8"); - //encodedVmId = URLEncoder.encode(s_windowsVmId.get(), "UTF-8"); - - requestToSign = "apikey=" + encodedApiKey + "&command=createIpForwardingRule&endPort=22&ipaddressid=" + encodedIpAddress + "&protocol=TCP&startPort=22"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = - developerServer + "?command=createIpForwardingRule&apikey=" + encodedApiKey + "&endPort=22&ipaddressid=" + encodedIpAddress + - "&protocol=TCP&signature=" + encodedSignature + "&startPort=22"; - - s_logger.info("Created Ip forwarding rule with " + url); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - s_logger.info("Port forwarding rule was assigned successfully to Windows VM"); - long ipfwdid = Long.parseLong(values.get("id")); - s_logger.info("got Ip Forwarding Rule's Id:" + ipfwdid); - s_winipfwdid.set(values.get("id")); - } else { - s_logger.error("Port forwarding rule creation failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - } - return responseCode; - } - - private static int executeCleanup(String server, String developerServer, String username) throws HttpException, IOException { - // test steps: - // - get user - // - delete user - - // ----------------------------- - // GET USER - // ----------------------------- - String userId = s_userId.get().toString(); - String encodedUserId = URLEncoder.encode(userId, "UTF-8"); - String url = server + "?command=listUsers&id=" + encodedUserId; - s_logger.info("Cleaning up resources for user: " + userId + " with url " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userInfo = getSingleValueFromXML(is, new String[] {"username", "id", "account"}); - if (!username.equals(userInfo.get("username"))) { - s_logger.error("get user failed to retrieve requested user, aborting cleanup test" + ". Following URL was sent: " + url); - return -1; - } - - } else { - s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ----------------------------- - // UPDATE USER - // ----------------------------- - { - url = server + "?command=updateUser&id=" + userId + "&firstname=delete&lastname=me"; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("update user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"success"}); - s_logger.info("update user..success? " + success.get("success")); - } else { - s_logger.error("update user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // ----------------------------- - // Detach existin dataVolume, create a new volume, attach it to the vm - // ----------------------------- - { - url = server + "?command=listVolumes&virtualMachineId=" + s_linuxVmId.get() + "&type=dataDisk"; - s_logger.info("Getting dataDisk id of Centos vm"); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("List volumes response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"id"}); - s_logger.info("Got dataDiskVolume with id " + success.get("id")); - s_dataVolume.set(success.get("id")); - } else { - s_logger.error("List volumes failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // Detach volume - { - url = server + "?command=detachVolume&id=" + s_dataVolume.get(); - s_logger.info("Detaching volume with id " + s_dataVolume.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Detach data volume response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("The volume was detached successfully"); - } else { - s_logger.error("Detach data disk failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // Delete a volume - { - url = server + "?command=deleteVolume&id=" + s_dataVolume.get(); - s_logger.info("Deleting volume with id " + s_dataVolume.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Delete data volume response code: " + responseCode); - if (responseCode == 200) { - s_logger.info("The volume was deleted successfully"); - } else { - s_logger.error("Delete volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // Create a new volume - { - url = server + "?command=createVolume&diskofferingid=" + diskOfferingId + "&zoneid=" + zoneId + "&name=newvolume&account=" + s_account.get() + "&domainid=1"; - s_logger.info("Creating volume...."); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("create volume response code: 401"); - return 401; - } else { - s_logger.info("create volume response code: " + responseCode); - long volumeId = Long.parseLong(values.get("id")); - s_logger.info("got volume id: " + volumeId); - s_newVolume.set(values.get("id")); - } - } else { - s_logger.error("create volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // attach a new volume to the vm - { - url = server + "?command=attachVolume&id=" + s_newVolume.get() + "&virtualmachineid=" + s_linuxVmId.get(); - s_logger.info("Attaching volume with id " + s_newVolume.get() + " to the vm " + s_linuxVmId.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Attach data volume response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("The volume was attached successfully"); - } else { - s_logger.error("Attach volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // Create a snapshot - // list volumes - { - url = server + "?command=listVolumes&virtualMachineId=" + s_linuxVmId.get() + "&type=root"; - s_logger.info("Getting rootDisk id of Centos vm"); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("List volumes response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"id"}); - if (success.get("id") == null) { - s_logger.error("Unable to get root volume. Followin url was sent: " + url); - } - s_logger.info("Got rootVolume with id " + success.get("id")); - s_rootVolume.set(success.get("id")); - } else { - s_logger.error("List volumes failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // //Create snapshot from root disk volume - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=createSnapshot&volumeid=" + s_rootVolume.get(); - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=createSnapshot&volumeid=" + s_rootVolume.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Create snapshot response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("create snapshot response code: 401"); - return 401; - } else { - s_logger.info("create snapshot response code: " + responseCode + ". Got snapshot with id " + values.get("id")); - s_snapshot.set(values.get("id")); - } - } else { - s_logger.error("create snapshot failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Create volume from the snapshot created on the previous step and attach it to the running vm - /* encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - requestToSign = "apikey=" + encodedApiKey + "&command=createVolume&name=" + s_account.get() + "&snapshotid=" + s_snapshot.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=createVolume&name=" + s_account.get() + "&snapshotid=" + s_snapshot.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Create volume from snapshot response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] { "id" }); - - if (values.get("id") == null) { - s_logger.info("create volume from snapshot response code: 401"); - return 401; - } else { - s_logger.info("create volume from snapshot response code: " + responseCode + ". Got volume with id " + values.get("id") + ". The command was sent with url " + url); - s_volumeFromSnapshot.set(values.get("id")); - } - } else { - s_logger.error("create volume from snapshot failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - { - url = server + "?command=attachVolume&id=" + s_volumeFromSnapshot.get() + "&virtualmachineid=" + s_linuxVmId.get(); - s_logger.info("Attaching volume with id " + s_volumeFromSnapshot.get() + " to the vm " + s_linuxVmId.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Attach volume from snapshot to linux vm response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("The volume created from snapshot was attached successfully to linux vm"); - } else { - s_logger.error("Attach volume created from snapshot failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - */ - // ----------------------------- - // Execute reboot/stop/start commands for the VMs before deleting the account - made to exercise xen - // ----------------------------- - - // Reboot windows VM - requestToSign = "apikey=" + encodedApiKey + "&command=rebootVirtualMachine&id=" + s_windowsVmId.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=rebootVirtualMachine&id=" + s_windowsVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Reboot windows Vm response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info("Windows VM was rebooted with the status: " + success.get("success")); - } else { - s_logger.error("Reboot windows VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Stop centos VM - requestToSign = "apikey=" + encodedApiKey + "&command=stopVirtualMachine&id=" + s_linuxVmId.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=stopVirtualMachine&id=" + s_linuxVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Stop linux Vm response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info("Linux VM was stopped with the status: " + success.get("success")); - } else { - s_logger.error("Stop linux VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Create private template from root disk volume - requestToSign = - "apikey=" + encodedApiKey + "&command=createTemplate" + "&displaytext=" + s_account.get() + "&name=" + s_account.get() + "&ostypeid=11" + "&snapshotid=" + - s_snapshot.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = - developerServer + "?command=createTemplate" + "&displaytext=" + s_account.get() + "&name=" + s_account.get() + "&ostypeid=11" + "&snapshotid=" + - s_snapshot.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Create private template response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("create private template response code: 401"); - return 401; - } else { - s_logger.info("create private template response code: " + responseCode); - } - } else { - s_logger.error("create private template failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Start centos VM - requestToSign = "apikey=" + encodedApiKey + "&command=startVirtualMachine&id=" + s_windowsVmId.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=startVirtualMachine&id=" + s_windowsVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Start linux Vm response code: " + responseCode); - if (responseCode != 200) { - s_logger.error("Start linux VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // get domainRouter id - { - url = server + "?command=listRouters&zoneid=" + zoneId + "&account=" + s_account.get() + "&domainid=1"; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("List domain routers response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"id"}); - s_logger.info("Got the domR with id " + success.get("id")); - s_domainRouterId.set(success.get("id")); - } else { - s_logger.error("List domain routers failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // reboot the domain router - { - url = server + "?command=rebootRouter&id=" + s_domainRouterId.get(); - s_logger.info("Rebooting domR with id " + s_domainRouterId.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Reboot domain router response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("Domain router was rebooted successfully"); - } else { - s_logger.error("Reboot domain routers failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // ----------------------------- - // DELETE ACCOUNT - // ----------------------------- - { - url = server + "?command=deleteAccount&id=" + s_accountId.get(); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("delete account response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("Deleted account successfully"); - } else { - s_logger.error("delete account failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - return responseCode; - } - - private static int executeEventsAndBilling(String server, String developerServer) throws HttpException, IOException { - // test steps: - // - get all the events in the system for all users in the system - // - generate all the usage records in the system - // - get all the usage records in the system - - // ----------------------------- - // GET EVENTS - // ----------------------------- - String url = server + "?command=listEvents&page=1&pagesize=100&&account=" + s_account.get(); - - s_logger.info("Getting events for the account " + s_account.get()); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get events response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> eventDescriptions = getMultipleValuesFromXML(is, new String[] {"description"}); - List descriptionText = eventDescriptions.get("description"); - if (descriptionText == null) { - s_logger.info("no events retrieved..."); - } else { - for (String text : descriptionText) { - s_logger.info("event: " + text); - } - } - } else { - s_logger.error("list events failed with error code: " + responseCode + ". Following URL was sent: " + url); - - return responseCode; - } - - // ------------------------------------------------------------------------------------- - // GENERATE USAGE RECORDS (note: typically this is done infrequently) - // ------------------------------------------------------------------------------------- - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - Date currentDate = new Date(); - String endDate = dateFormat.format(currentDate); - s_logger.info("Generating usage records from September 1st till " + endDate); - url = server + "?command=generateUsageRecords&startdate=2009-09-01&enddate=" + endDate; // generate - // all usage record till today - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("generate usage records response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map successStr = getSingleValueFromXML(is, new String[] {"success"}); - s_logger.info("successfully generated usage records? " + successStr.get("success")); - } else { - s_logger.error("generate usage records failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Sleeping for a 2 minutes before getting a usage records from the database - try { - Thread.sleep(120000); - } catch (Exception ex) { - s_logger.error(ex); - } - - // -------------------------------- - // GET USAGE RECORDS - // -------------------------------- - url = server + "?command=listUsageRecords&startdate=2009-09-01&enddate=" + endDate + "&account=" + s_account.get() + "&domaindid=1"; - s_logger.info("Getting all usage records with request: " + url); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("get usage records response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> usageRecValues = getMultipleValuesFromXML(is, new String[] {"description", "usage"}); - if ((usageRecValues.containsKey("description") == true) && (usageRecValues.containsKey("usage") == true)) { - List descriptions = usageRecValues.get("description"); - List usages = usageRecValues.get("usage"); - for (int i = 0; i < descriptions.size(); i++) { - String desc = descriptions.get(i); - String usage = ""; - if (usages != null) { - if (i < usages.size()) { - usage = ", usage: " + usages.get(i); - } - } - s_logger.info("desc: " + desc + usage); - } - } - - } else { - s_logger.error("list usage records failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - return responseCode; - } - - private static boolean getNetworkStat(String server) { - try { - String url = server + "?command=listAccountStatistics&account=" + s_account.get(); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("listAccountStatistics response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map requestKeyValues = getSingleValueFromXML(is, new String[] {"receivedbytes", "sentbytes"}); - int bytesReceived = Integer.parseInt(requestKeyValues.get("receivedbytes")); - int bytesSent = Integer.parseInt(requestKeyValues.get("sentbytes")); - if ((bytesReceived > 100000000) && (bytesSent > 0)) { - s_logger.info("Network stat is correct for account" + s_account.get() + "; bytest received is " + toHumanReadableSize(bytesReceived) + " and bytes sent is " + toHumanReadableSize(bytesSent)); - return true; - } else { - s_logger.error("Incorrect value for bytes received/sent for the account " + s_account.get() + ". We got " + toHumanReadableSize(bytesReceived) + " bytes received; " + - " and " + toHumanReadableSize(bytesSent) + " bytes sent"); - return false; - } - - } else { - s_logger.error("listAccountStatistics failed with error code: " + responseCode + ". Following URL was sent: " + url); - return false; - } - } catch (Exception ex) { - s_logger.error("Exception while sending command listAccountStatistics"); - return false; - } - } - - private static int executeStop(String server, String developerServer, String username, boolean destroy) throws HttpException, IOException { - // test steps: - // - get userId for the given username - // - list virtual machines for the user - // - stop all virtual machines - // - get ip addresses for the user - // - release ip addresses - - // ----------------------------- - // GET USER - // ----------------------------- - String userId = s_userId.get().toString(); - String encodedUserId = URLEncoder.encode(userId, "UTF-8"); - - String url = server + "?command=listUsers&id=" + encodedUserId; - s_logger.info("Stopping resources for user: " + username); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userIdValues = getSingleValueFromXML(is, new String[] {"id"}); - String userIdStr = userIdValues.get("id"); - if (userIdStr != null) { - userId = userIdStr; - - } else { - s_logger.error("get user failed to retrieve a valid user id, aborting depolyment test" + ". Following URL was sent: " + url); - return -1; - } - } else { - s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - { - // ---------------------------------- - // LIST VIRTUAL MACHINES - // ---------------------------------- - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=listVirtualMachines"; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listVirtualMachines&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - - s_logger.info("Listing all virtual machines for the user with url " + url); - String[] vmIds = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list virtual machines response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> vmIdValues = getMultipleValuesFromXML(is, new String[] {"id"}); - if (vmIdValues.containsKey("id")) { - List vmIdList = vmIdValues.get("id"); - if (vmIdList != null) { - vmIds = new String[vmIdList.size()]; - vmIdList.toArray(vmIds); - String vmIdLogStr = ""; - if ((vmIds != null) && (vmIds.length > 0)) { - vmIdLogStr = vmIds[0]; - for (int i = 1; i < vmIds.length; i++) { - vmIdLogStr = vmIdLogStr + "," + vmIds[i]; - } - } - s_logger.info("got virtual machine ids: " + vmIdLogStr); - } - } - - } else { - s_logger.error("list virtual machines test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST USER IP ADDRESSES - // ---------------------------------- - - requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - String[] ipAddresses = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> ipAddressValues = getMultipleValuesFromXML(is, new String[] {"ipaddress"}); - if (ipAddressValues.containsKey("ipaddress")) { - List ipAddressList = ipAddressValues.get("ipaddress"); - if (ipAddressList != null) { - ipAddresses = new String[ipAddressList.size()]; - ipAddressList.toArray(ipAddresses); - String ipAddressLogStr = ""; - if ((ipAddresses != null) && (ipAddresses.length > 0)) { - ipAddressLogStr = ipAddresses[0]; - for (int i = 1; i < ipAddresses.length; i++) { - ipAddressLogStr = ipAddressLogStr + "," + ipAddresses[i]; - } - } - s_logger.info("got IP addresses: " + ipAddressLogStr); - } - } - - } else { - s_logger.error("list user ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST ZONES - // ---------------------------------- - - requestToSign = "apikey=" + encodedApiKey + "&command=listZones"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listZones&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - String[] zoneNames = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list zones response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> zoneNameValues = getMultipleValuesFromXML(is, new String[] {"name"}); - if (zoneNameValues.containsKey("name")) { - List zoneNameList = zoneNameValues.get("name"); - if (zoneNameList != null) { - zoneNames = new String[zoneNameList.size()]; - zoneNameList.toArray(zoneNames); - String zoneNameLogStr = "\n\n"; - if ((zoneNames != null) && (zoneNames.length > 0)) { - zoneNameLogStr += zoneNames[0]; - for (int i = 1; i < zoneNames.length; i++) { - zoneNameLogStr = zoneNameLogStr + "\n" + zoneNames[i]; - } - - } - zoneNameLogStr += "\n\n"; - s_logger.info("got zones names: " + zoneNameLogStr); - } - } - - } else { - s_logger.error("list zones failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST ACCOUNT STATISTICS - // ---------------------------------- - - requestToSign = "apikey=" + encodedApiKey + "&command=listAccounts"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listAccounts&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - String[] statNames = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("listAccountStatistics response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> statValues = getMultipleValuesFromXML(is, new String[] {"receivedbytes"}); - if (statValues.containsKey("receivedbytes")) { - List statList = statValues.get("receivedbytes"); - if (statList != null) { - statNames = new String[statList.size()]; - statList.toArray(statNames); - String statLogStr = "\n\n"; - if ((statNames != null) && (zoneNames.length > 0)) { - statLogStr += statNames[0]; - for (int i = 1; i < statNames.length; i++) { - statLogStr = statLogStr + "\n" + zoneNames[i]; - } - - } - statLogStr += "\n\n"; - s_logger.info("got accountstatistics: " + statLogStr); - } - } - - } else { - s_logger.error("listAccountStatistics failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST TEMPLATES - // ---------------------------------- - - requestToSign = "apikey=" + encodedApiKey + "&command=listTemplates@templatefilter=self"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listTemplates&apikey=" + encodedApiKey + "&templatefilter=self&signature=" + encodedSignature; - String[] templateNames = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list templates response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> templateNameValues = getMultipleValuesFromXML(is, new String[] {"name"}); - - if (templateNameValues.containsKey("name")) { - List templateNameList = templateNameValues.get("name"); - if (templateNameList != null) { - templateNames = new String[templateNameList.size()]; - templateNameList.toArray(templateNames); - String templateNameLogStr = "\n\n"; - if ((templateNames != null) && (templateNames.length > 0)) { - templateNameLogStr += templateNames[0]; - for (int i = 1; i < templateNames.length; i++) { - templateNameLogStr = templateNameLogStr + "\n" + templateNames[i]; - } - - } - templateNameLogStr += "\n\n"; - s_logger.info("got template names: " + templateNameLogStr); - } - } - - } else { - s_logger.error("list templates failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST SERVICE OFFERINGS - // ---------------------------------- - - requestToSign = "apikey=" + encodedApiKey + "&command=listServiceOfferings"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listServiceOfferings&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - String[] serviceOfferingNames = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list service offerings response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> serviceOfferingNameValues = getMultipleValuesFromXML(is, new String[] {"name"}); - - if (serviceOfferingNameValues.containsKey("name")) { - List serviceOfferingNameList = serviceOfferingNameValues.get("name"); - if (serviceOfferingNameList != null) { - serviceOfferingNames = new String[serviceOfferingNameList.size()]; - serviceOfferingNameList.toArray(serviceOfferingNames); - String serviceOfferingNameLogStr = ""; - if ((serviceOfferingNames != null) && (serviceOfferingNames.length > 0)) { - serviceOfferingNameLogStr = serviceOfferingNames[0]; - for (int i = 1; i < serviceOfferingNames.length; i++) { - serviceOfferingNameLogStr = serviceOfferingNameLogStr + ", " + serviceOfferingNames[i]; - } - } - s_logger.info("got service offering names: " + serviceOfferingNameLogStr); - } - } - - } else { - s_logger.error("list service offerings failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST EVENTS - // --------------------------------- - - url = server + "?command=listEvents&page=1&pagesize=100&&account=" + s_account.get(); - String[] eventDescriptions = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list events response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> eventNameValues = getMultipleValuesFromXML(is, new String[] {"description"}); - - if (eventNameValues.containsKey("description")) { - List eventNameList = eventNameValues.get("description"); - if (eventNameList != null) { - eventDescriptions = new String[eventNameList.size()]; - eventNameList.toArray(eventDescriptions); - String eventNameLogStr = "\n\n"; - if ((eventDescriptions != null) && (eventDescriptions.length > 0)) { - eventNameLogStr += eventDescriptions[0]; - for (int i = 1; i < eventDescriptions.length; i++) { - eventNameLogStr = eventNameLogStr + "\n" + eventDescriptions[i]; - } - } - eventNameLogStr += "\n\n"; - s_logger.info("got event descriptions: " + eventNameLogStr); - } - } - } else { - s_logger.error("list events failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // STOP/DESTROY VIRTUAL MACHINES - // ---------------------------------- - if (vmIds != null) { - String cmdName = (destroy ? "destroyVirtualMachine" : "stopVirtualMachine"); - for (String vmId : vmIds) { - requestToSign = "apikey=" + encodedApiKey + "&command=" + cmdName + "&id=" + vmId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=" + cmdName + "&id=" + vmId + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info(cmdName + " [" + vmId + "] response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info(cmdName + "..success? " + success.get("success")); - } else { - s_logger.error(cmdName + "test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - } - } - - { - String[] ipAddresses = null; - // ----------------------------------------- - // LIST NAT IP ADDRESSES - // ----------------------------------------- - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses"; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - - InputStream is = method.getResponseBodyAsStream(); - List ipAddressList = getNonSourceNatIPs(is); - ipAddresses = new String[ipAddressList.size()]; - ipAddressList.toArray(ipAddresses); - String ipAddrLogStr = ""; - if ((ipAddresses != null) && (ipAddresses.length > 0)) { - ipAddrLogStr = ipAddresses[0]; - for (int i = 1; i < ipAddresses.length; i++) { - ipAddrLogStr = ipAddrLogStr + "," + ipAddresses[i]; - } - } - s_logger.info("got ip addresses: " + ipAddrLogStr); - - } else { - s_logger.error("list nat ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ------------------------------------------------------------- - // Delete IP FORWARDING RULE -- Windows VM - // ------------------------------------------------------------- - String encodedIpFwdId = URLEncoder.encode(s_winipfwdid.get(), "UTF-8"); - - requestToSign = "apikey=" + encodedApiKey + "&command=deleteIpForwardingRule&id=" + encodedIpFwdId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=deleteIpForwardingRule&apikey=" + encodedApiKey + "&id=" + encodedIpFwdId + "&signature=" + encodedSignature; - - s_logger.info("Delete Ip forwarding rule with " + url); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("IP forwarding rule was successfully deleted"); - - } else { - s_logger.error("IP forwarding rule creation failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - //-------------------------------------------- - // Disable Static NAT for the Source NAT Ip - //-------------------------------------------- - encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String encodedPublicIpId = URLEncoder.encode(s_publicIpId.get(), "UTF-8"); - requestToSign = "apikey=" + encodedApiKey + "&command=disableStaticNat" + "&id=" + encodedPublicIpId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=disableStaticNat&apikey=" + encodedApiKey + "&id=" + encodedPublicIpId + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("url is " + url); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"success"}); - s_logger.info("Disable Static NAT..success? " + success.get("success")); - } else { - s_logger.error("Disable Static NAT failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ----------------------------------------- - // DISASSOCIATE IP ADDRESSES - // ----------------------------------------- - if (ipAddresses != null) { - for (String ipAddress : ipAddresses) { - requestToSign = "apikey=" + encodedApiKey + "&command=disassociateIpAddress&id=" + ipAddress; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=disassociateIpAddress&apikey=" + encodedApiKey + "&id=" + ipAddress + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("disassociate ip address [" + userId + "/" + ipAddress + "] response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element disassocipel = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(disassocipel, new String[] {"success"}); - // Map success = getSingleValueFromXML(input, new String[] { "success" }); - s_logger.info("disassociate ip address..success? " + success.get("success")); - } else { - s_logger.error("disassociate ip address failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - } - } - s_linuxIP.set(""); - s_linuxIpId.set(""); - s_linuxVmId.set(""); - s_linuxPassword.set(""); - s_windowsIP.set(""); - s_windowsIpId.set(""); - s_windowsVmId.set(""); - s_secretKey.set(""); - s_apiKey.set(""); - s_userId.set(Long.parseLong("0")); - s_account.set(""); - s_domainRouterId.set(""); - return responseCode; - } - - public static String signRequest(String request, String key) { - try { - Mac mac = Mac.getInstance("HmacSHA1"); - SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); - mac.init(keySpec); - mac.update(request.getBytes()); - byte[] encryptedBytes = mac.doFinal(); - return org.apache.commons.codec.binary.Base64.encodeBase64String(encryptedBytes); - } catch (Exception ex) { - s_logger.error("unable to sign request", ex); - } - return null; - } - - private static String sshWinTest(String host) { - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring win ssh test"); - return null; - } - - // We will retry 5 times before quitting - int retry = 1; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt. Account is " + s_account.get()); - Thread.sleep(300000); - } - - s_logger.info("Attempting to SSH into windows host " + host + " with retry attempt: " + retry + " for account " + s_account.get()); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User " + s_account.get() + " ssHed successfully into windows host " + host); - boolean success = false; - boolean isAuthenticated = conn.authenticateWithPassword("Administrator", "password"); - if (isAuthenticated == false) { - return "Authentication failed"; - } else { - s_logger.info("Authentication is successful"); - } - - try { - SCPClient scp = new SCPClient(conn); - scp.put("wget.exe", "wget.exe", "C:\\Users\\Administrator", "0777"); - s_logger.info("Successfully put wget.exe file"); - } catch (Exception ex) { - s_logger.error("Unable to put wget.exe " + ex); - } - - if (conn == null) { - s_logger.error("Connection is null"); - } - Session sess = conn.openSession(); - - s_logger.info("User + " + s_account.get() + " executing : wget http://" + downloadUrl); - String downloadCommand = "wget http://" + downloadUrl + " && dir dump.bin"; - sess.execCommand(downloadCommand); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - /* int len = */stderr.read(buffer); - } - } - sess.close(); - conn.close(); - - if (success) { - return null; - } else { - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail for account " + s_account.get(); - } - } - } catch (Exception e) { - s_logger.error(e); - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail with error " + e.getMessage(); - } - } - } - } - - private static String sshTest(String host, String password, String snapshotTest) { - int i = 0; - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring ssh test"); - return null; - } - - if (password == null) { - s_logger.info("Did not receive a password back from test, ignoring ssh test"); - return null; - } - - // We will retry 5 times before quitting - String result = null; - int retry = 0; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt. Account is " + s_account.get()); - Thread.sleep(120000); - } - - s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry + ". Account is " + s_account.get()); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User + " + s_account.get() + " ssHed successfully into linux host " + host); - - boolean isAuthenticated = conn.authenticateWithPassword("root", password); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password" + password); - return "Authentication failed"; - - } - - boolean success = false; - String linuxCommand = null; - - if (i % 10 == 0) - linuxCommand = "rm -rf *; wget http://" + downloadUrl + " && ls -al dump.bin"; - else - linuxCommand = "wget http://" + downloadUrl + " && ls -al dump.bin"; - - Session sess = conn.openSession(); - s_logger.info("User " + s_account.get() + " executing : " + linuxCommand); - sess.execCommand(linuxCommand); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - /* int len = */stderr.read(buffer); - } - } - - sess.close(); - conn.close(); - - if (!success) { - retry++; - if (retry == MAX_RETRY_LINUX) { - result = "SSH Linux Network test fail"; - } - } - - if (snapshotTest.equals("no")) - return result; - else { - Long sleep = 300000L; - s_logger.info("Sleeping for " + sleep / 1000 / 60 + "minutes before executing next ssh test"); - Thread.sleep(sleep); - } - } catch (Exception e) { - retry++; - s_logger.error("SSH Linux Network test fail with error"); - if ((retry == MAX_RETRY_LINUX) && (snapshotTest.equals("no"))) { - return "SSH Linux Network test fail with error " + e.getMessage(); - } - } - i++; - } - } - - public static String createMD5Password(String password) { - MessageDigest md5; - - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new CloudRuntimeException("Error", e); - } - - md5.reset(); - BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); - - // make sure our MD5 hash value is 32 digits long... - StringBuffer sb = new StringBuffer(); - String pwStr = pwInt.toString(16); - int padding = 32 - pwStr.length(); - for (int i = 0; i < padding; i++) { - sb.append('0'); - } - sb.append(pwStr); - return sb.toString(); - } - - public static Element queryAsyncJobResult(String host, InputStream inputStream) { - Element returnBody = null; - - Map values = getSingleValueFromXML(inputStream, new String[] {"jobid"}); - String jobId = values.get("jobid"); - - if (jobId == null) { - s_logger.error("Unable to get a jobId"); - return null; - } - - // s_logger.info("Job id is " + jobId); - String resultUrl = host + "?command=queryAsyncJobResult&jobid=" + jobId; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(resultUrl); - while (true) { - try { - client.executeMethod(method); - // s_logger.info("Method is executed successfully. Following url was sent " + resultUrl); - InputStream is = method.getResponseBodyAsStream(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(is); - returnBody = doc.getDocumentElement(); - doc.getDocumentElement().normalize(); - Element jobStatusTag = (Element)returnBody.getElementsByTagName("jobstatus").item(0); - String jobStatus = jobStatusTag.getTextContent(); - if (jobStatus.equals("0")) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - s_logger.debug("[ignored] interrupted while during async job result query."); - } - } else { - break; - } - - } catch (Exception ex) { - s_logger.error(ex); - } - } - return returnBody; - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/stress/WgetTest.java b/test/src-not-used/main/java/com/cloud/test/stress/WgetTest.java deleted file mode 100644 index 91885568447..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/stress/WgetTest.java +++ /dev/null @@ -1,150 +0,0 @@ -// 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.test.stress; - -import java.io.InputStream; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import org.apache.log4j.Logger; - -import com.trilead.ssh2.ChannelCondition; -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.Session; - -public class WgetTest { - - public static final int MAX_RETRY_LINUX = 1; - public static final Logger s_logger = Logger.getLogger(WgetTest.class.getName()); - public static String host = ""; - public static String password = "rs-ccb35ea5"; - - public static void main(String[] args) { - - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - // host - if (arg.equals("-h")) { - host = iter.next(); - } - //password - - if (arg.equals("-p")) { - password = iter.next(); - } - - } - - int i = 0; - if (host == null || host.equals("")) { - s_logger.info("Did not receive a host back from test, ignoring ssh test"); - System.exit(2); - } - - if (password == null) { - s_logger.info("Did not receive a password back from test, ignoring ssh test"); - System.exit(2); - } - int retry = 0; - - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt"); - Thread.sleep(120000); - } - - s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User + ssHed successfully into linux host " + host); - - boolean isAuthenticated = conn.authenticateWithPassword("root", password); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password" + password); - System.exit(2); - } - - boolean success = false; - String linuxCommand = null; - - if (i % 10 == 0) - linuxCommand = "rm -rf *; wget http://192.168.1.250/dump.bin && ls -al dump.bin"; - else - linuxCommand = "wget http://192.168.1.250/dump.bin && ls -al dump.bin"; - - Session sess = conn.openSession(); - sess.execCommand(linuxCommand); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - System.exit(2); - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - /* int len = */stderr.read(buffer); - } - } - - sess.close(); - conn.close(); - - if (!success) { - retry++; - if (retry == MAX_RETRY_LINUX) { - System.exit(2); - } - } - } catch (Exception e) { - retry++; - s_logger.error("SSH Linux Network test fail with error"); - if (retry == MAX_RETRY_LINUX) { - s_logger.error("Ssh test failed"); - System.exit(2); - } - } - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/ui/AbstractSeleniumTestCase.java b/test/src-not-used/main/java/com/cloud/test/ui/AbstractSeleniumTestCase.java deleted file mode 100644 index f9e678e2529..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/ui/AbstractSeleniumTestCase.java +++ /dev/null @@ -1,55 +0,0 @@ -// 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.test.ui; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.openqa.selenium.server.RemoteControlConfiguration; -import org.openqa.selenium.server.SeleniumServer; - -import com.thoughtworks.selenium.DefaultSelenium; - -@RunWith(JUnit4.class) -public abstract class AbstractSeleniumTestCase { - protected static DefaultSelenium selenium; - private static SeleniumServer seleniumServer; - - @BeforeClass - public static void setUp() throws Exception { - System.out.println("*** Starting selenium ... ***"); - RemoteControlConfiguration seleniumConfig = new RemoteControlConfiguration(); - seleniumConfig.setPort(4444); - seleniumServer = new SeleniumServer(seleniumConfig); - seleniumServer.start(); - - String host = System.getProperty("myParam", "localhost"); - selenium = createSeleniumClient("http://" + host + ":" + "8080/client/"); - selenium.start(); - System.out.println("*** Started selenium ***"); - } - - @AfterClass - public static void tearDown() throws Exception { - selenium.stop(); - } - - protected static DefaultSelenium createSeleniumClient(String url) throws Exception { - return new DefaultSelenium("localhost", 4444, "*firefox", url); - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteAISO.java b/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteAISO.java deleted file mode 100644 index 1998ae7c8ef..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteAISO.java +++ /dev/null @@ -1,127 +0,0 @@ -// 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.test.ui; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; - -import com.thoughtworks.selenium.SeleniumException; - -public class AddAndDeleteAISO extends AbstractSeleniumTestCase { - - @Test - public void testAddAndDeleteISO() throws Exception { - try { - selenium.open("/client/"); - selenium.type("account_username", "admin"); - selenium.type("account_password", "password"); - selenium.click("loginbutton"); - Thread.sleep(3000); - assertTrue(selenium.isTextPresent("admin")); - selenium.click("//div[@id='leftmenu_templates']/div"); - selenium.click("//div[@id='leftmenu_submenu_my_iso']/div/div[2]"); - Thread.sleep(3000); - selenium.click("label"); - - selenium.type("add_iso_name", "abc"); - selenium.type("add_iso_display_text", "abc"); - String iso_url = System.getProperty("add_iso_url", "http://10.91.28.6/ISO/Fedora-11-i386-DVD.iso"); - selenium.type("add_iso_url", iso_url); - String iso_zone = System.getProperty("add_iso_zone", "All Zones"); - selenium.select("add_iso_zone", "label=" + iso_zone); - String iso_os_type = System.getProperty("add_iso_os_type", "Fedora 11"); - selenium.select("add_iso_os_type", "label=" + iso_os_type); - selenium.click("//div[28]/div[11]/button[1]"); - Thread.sleep(3000); - int i = 1; - try { - for (;; i++) { - System.out.println("i= " + i); - selenium.click("//div[" + i + "]/div/div[2]/span/span"); - } - } catch (Exception ex) { - s_logger.info("[ignored]" - + "error during clicking test on iso: " + e.getLocalizedMessage()); - } - - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("//div[@id='after_action_info_container_on_top']")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during visibility test of iso: " + e.getLocalizedMessage()); - } - Thread.sleep(10000); - } - - assertTrue(selenium.isTextPresent("Adding succeeded")); - Thread.sleep(3000); - int status = 1; - while (!selenium.isTextPresent("Ready")) { - for (int j = 1; j <= i; j++) - - { - if (selenium.isTextPresent("Ready")) { - status = 0; - break; - } - selenium.click("//div[" + j + "]/div/div[2]/span/span"); - } - if (status == 0) { - break; - } else { - selenium.click("//div[@id='leftmenu_submenu_featured_iso']/div/div[2]"); - Thread.sleep(3000); - selenium.click("//div[@id='leftmenu_submenu_my_iso']/div/div[2]"); - Thread.sleep(3000); - } - - } - selenium.click("link=Delete ISO"); - selenium.click("//div[28]/div[11]/button[1]"); - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("after_action_info_container_on_top")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error checking visibility after test completion for iso: " + e.getLocalizedMessage()); - } - Thread.sleep(1000); - } - - assertTrue(selenium.isTextPresent("Delete ISO action succeeded")); - selenium.click("main_logout"); - selenium.waitForPageToLoad("30000"); - assertTrue(selenium.isTextPresent("Welcome to Management Console")); - - } catch (SeleniumException ex) { - - System.err.println(ex.getMessage()); - fail(ex.getMessage()); - - throw ex; - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteATemplate.java b/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteATemplate.java deleted file mode 100644 index 3a3264e9cf1..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteATemplate.java +++ /dev/null @@ -1,126 +0,0 @@ -// 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.test.ui; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; - -import com.thoughtworks.selenium.SeleniumException; - -public class AddAndDeleteATemplate extends AbstractSeleniumTestCase { - - @Test - public void testAddAndDeleteTemplate() throws Exception { - try { - selenium.open("/client/"); - selenium.type("account_username", "admin"); - selenium.type("account_password", "password"); - selenium.click("loginbutton"); - Thread.sleep(3000); - assertTrue(selenium.isTextPresent("admin")); - selenium.click("//div[@id='leftmenu_templates']/div"); - selenium.click("//div[@id='leftmenu_submenu_my_template']/div/div[2]"); - Thread.sleep(3000); - selenium.click("label"); - selenium.type("add_template_name", "abc"); - selenium.type("add_template_display_text", "abc"); - String template_url = - System.getProperty("add_template_url", "http://10.91.28.6/templates/centos53-x86_64/latest/f59f18fb-ae94-4f97-afd2-f84755767aca.vhd.bz2"); - selenium.type("add_template_url", template_url); - String template_zone = System.getProperty("add_template_zone", "All Zones"); - selenium.select("add_template_zone", "label=" + template_zone); - String template_os_type = System.getProperty("add_template_os_type", "CentOS 5.3 (32-bit)"); - selenium.select("add_template_os_type", "label=" + template_os_type); - selenium.click("//div[28]/div[11]/button[1]"); - Thread.sleep(3000); - int i = 1; - try { - for (;; i++) { - System.out.println("i= " + i); - selenium.click("//div[" + i + "]/div/div[2]/span/span"); - } - } catch (Exception ex) { - s_logger.info("[ignored]" - + "error during clicking test on template: " + ex.getLocalizedMessage()); - } - - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("//div[@id='after_action_info_container_on_top']")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during visibility test of template: " + e.getLocalizedMessage()); - } - Thread.sleep(10000); - } - - assertTrue(selenium.isTextPresent("Adding succeeded")); - Thread.sleep(3000); - int status = 1; - while (!selenium.isTextPresent("Ready")) { - for (int j = 1; j <= i; j++) - - { - if (selenium.isTextPresent("Ready")) { - status = 0; - break; - } - selenium.click("//div[" + j + "]/div/div[2]/span/span"); - } - if (status == 0) { - break; - } else { - selenium.click("//div[@id='leftmenu_submenu_featured_template']/div/div[2]"); - Thread.sleep(3000); - selenium.click("//div[@id='leftmenu_submenu_my_template']/div/div[2]"); - Thread.sleep(3000); - } - - } - selenium.click("link=Delete Template"); - selenium.click("//div[28]/div[11]/button[1]"); - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("after_action_info_container_on_top")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error checking visibility after test completion for template: " + e.getLocalizedMessage()); - } - Thread.sleep(1000); - } - - assertTrue(selenium.isTextPresent("Delete Template action succeeded")); - selenium.click("main_logout"); - selenium.waitForPageToLoad("30000"); - assertTrue(selenium.isTextPresent("Welcome to Management Console")); - } catch (SeleniumException ex) { - - System.err.println(ex.getMessage()); - fail(ex.getMessage()); - - throw ex; - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/ui/UIScenarioTest.java b/test/src-not-used/main/java/com/cloud/test/ui/UIScenarioTest.java deleted file mode 100644 index 8fde7e37ea6..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/ui/UIScenarioTest.java +++ /dev/null @@ -1,86 +0,0 @@ -// 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.test.ui; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; - -import com.thoughtworks.selenium.SeleniumException; - -public class UIScenarioTest extends AbstractSeleniumTestCase { - - @Test - public void testLoginStartStopVMScenario() throws Exception { - try { - selenium.open("/client/"); - selenium.type("account_username", "admin"); - selenium.type("account_password", "password"); - selenium.click("loginbutton"); - Thread.sleep(3000); - assertTrue(selenium.isTextPresent("admin")); - selenium.click("//div[@id='leftmenu_instances']/div"); - selenium.click("//div[@id='leftmenu_instances_stopped_instances']/div/span"); - - Thread.sleep(3000); - selenium.click("//div[@id='midmenu_startvm_link']/div/div[2]"); - selenium.click("//div[39]/div[11]/button[1]"); - - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("//div/p[@id='after_action_info']")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during visibility test after start vm: " + e.getLocalizedMessage()); - } - Thread.sleep(10000); - } - assertTrue(selenium.isTextPresent("Start Instance action succeeded")); - selenium.click("//div[@id='leftmenu_instances_running_instances']/div/span"); - - Thread.sleep(3000); - selenium.click("//div[@id='midmenu_stopvm_link']/div/div[2]"); - selenium.click("//div[39]/div[11]/button[1]"); - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("//div/p[@id='after_action_info']")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during visibility test after stop vm: " + e.getLocalizedMessage()); - } - Thread.sleep(10000); - } - - assertTrue(selenium.isTextPresent("Stop Instance action succeeded")); - selenium.click("main_logout"); - selenium.waitForPageToLoad("30000"); - assertTrue(selenium.isTextPresent("Welcome to Management Console")); - - } catch (SeleniumException ex) { - fail(ex.getMessage()); - System.err.println(ex.getMessage()); - throw ex; - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/ConsoleProxy.java b/test/src-not-used/main/java/com/cloud/test/utils/ConsoleProxy.java deleted file mode 100644 index 8c10d75a5c1..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/ConsoleProxy.java +++ /dev/null @@ -1,110 +0,0 @@ -// 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.test.utils; - -import java.io.BufferedReader; -import java.io.IOException; - -import org.apache.log4j.Logger; - -import com.cloud.utils.script.OutputInterpreter; -import com.cloud.utils.script.Script; - -public class ConsoleProxy implements Runnable { - public static String proxyIp; - private String command; - private int connectionsMade; - private long responseTime; - public static final Logger s_logger = Logger.getLogger(ConsoleProxy.class.getClass()); - - public ConsoleProxy(String port, String sid, String host) { - this.command = "https://" + proxyIp + ".realhostip.com:8000/getscreen?w=100&h=75&host=" + host + "&port=" + port + "&sid=" + sid; - s_logger.info("Command for a console proxy is " + this.command); - this.connectionsMade = 0; - this.responseTime = 0; - } - - public int getConnectionsMade() { - return this.connectionsMade; - } - - public long getResponseTime() { - return this.responseTime; - } - - @Override - public void run() { - while (true) { - - Script myScript = new Script("wget"); - myScript.add(command); - myScript.execute(); - long begin = System.currentTimeMillis(); - WgetInt process = new WgetInt(); - String response = myScript.execute(process); - long end = process.getEnd(); - if (response != null) { - s_logger.info("Content lenght is incorrect: " + response); - } - - long duration = (end - begin); - this.connectionsMade++; - this.responseTime = this.responseTime + duration; - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - s_logger.debug("[ignored] interrupted."); - } - - } - } - - public class WgetInt extends OutputInterpreter { - private long end; - - public long getEnd() { - return end; - } - - public void setEnd(long end) { - this.end = end; - } - - @Override - public String interpret(BufferedReader reader) throws IOException { - // TODO Auto-generated method stub - end = System.currentTimeMillis(); - String status = null; - String line = null; - while ((line = reader.readLine()) != null) { - int index = line.indexOf("Length:"); - if (index == -1) { - continue; - } else { - int index1 = line.indexOf("Length: 1827"); - if (index1 == -1) { - return status; - } else - status = line; - } - - } - return status; - } - - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/IpSqlGenerator.java b/test/src-not-used/main/java/com/cloud/test/utils/IpSqlGenerator.java deleted file mode 100644 index c37d08b86ff..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/IpSqlGenerator.java +++ /dev/null @@ -1,89 +0,0 @@ -// 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.test.utils; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.util.StringTokenizer; - -public class IpSqlGenerator { - public static void main(String[] args) { - try { - if (args.length != 5) { - System.out.println("Usage -- generate-ip.sh "); - System.out.println("Example -- generate-ip.sh public 192.168.1.1 192.168.1.255 1 1"); - System.out.println(" will generate ips ranging from public ips 192.168.1.1 to 192.168.1.255 for dc 1 and pod 1"); - return; - } - - String type = args[0]; - - StringTokenizer st = new StringTokenizer(args[1], "."); - int ipS1 = Integer.parseInt(st.nextToken()); - int ipS2 = Integer.parseInt(st.nextToken()); - int ipS3 = Integer.parseInt(st.nextToken()); - int ipS4 = Integer.parseInt(st.nextToken()); - - st = new StringTokenizer(args[2], "."); - int ipE1 = Integer.parseInt(st.nextToken()); - int ipE2 = Integer.parseInt(st.nextToken()); - int ipE3 = Integer.parseInt(st.nextToken()); - int ipE4 = Integer.parseInt(st.nextToken()); - - String dcId = args[3]; - String podId = args[4]; - - if (type.equals("private")) { - FileOutputStream fs = new FileOutputStream(new File("private-ips.sql")); - DataOutputStream out = new DataOutputStream(fs); - for (int i = ipS1; i <= ipE1; i++) { - for (int j = ipS2; j <= ipE2; j++) { - for (int k = ipS3; k <= ipE3; k++) { - for (int l = ipS4; l <= ipE4; l++) { - out.writeBytes("INSERT INTO `vmops`.`dc_ip_address_alloc` (ip_address, data_center_id, pod_id) VALUES ('" + i + "." + j + "." + k + "." + - l + "'," + dcId + "," + podId + ");\r\n"); - } - } - } - } - out.writeBytes("\r\n"); - out.flush(); - out.close(); - } else { - FileOutputStream fs = new FileOutputStream(new File("public-ips.sql")); - DataOutputStream out = new DataOutputStream(fs); - for (int i = ipS1; i <= ipE1; i++) { - for (int j = ipS2; j <= ipE2; j++) { - for (int k = ipS3; k <= ipE3; k++) { - for (int l = ipS4; l <= ipE4; l++) { - out.writeBytes("INSERT INTO `vmops`.`user_ip_address` (ip_address, data_center_id) VALUES ('" + i + "." + j + "." + k + "." + l + "'," + - dcId + ");\r\n"); - } - } - } - } - out.writeBytes("\r\n"); - out.flush(); - out.close(); - } - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during ip insert generator: " + e.getLocalizedMessage()); - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/ProxyLoadTemp.java b/test/src-not-used/main/java/com/cloud/test/utils/ProxyLoadTemp.java deleted file mode 100644 index f64b7d6b9e9..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/ProxyLoadTemp.java +++ /dev/null @@ -1,112 +0,0 @@ -// 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.test.utils; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.util.ArrayList; - -import org.apache.log4j.Logger; - -public class ProxyLoadTemp { - public static final Logger s_logger = Logger.getLogger(ProxyLoadTemp.class.getClass()); - public static int numThreads = 0; - public static ArrayList proxyList = new ArrayList(); - public static long begin; - public static long end; - public static long sum = 0; - - public ProxyLoadTemp() { - } - - public static void main(String[] args) { - begin = System.currentTimeMillis(); - Runtime.getRuntime().addShutdownHook(new ShutdownThread(new ProxyLoadTemp())); - ConsoleProxy.proxyIp = "172-16-1-101"; - - try { - BufferedReader consoleInput = new BufferedReader(new FileReader("console.input")); - boolean eof = false; - s_logger.info("Started reading file"); - while (!eof) { - String line = consoleInput.readLine(); - s_logger.info("Line is " + line); - if (line == null) { - s_logger.info("Line " + numThreads + " is null"); - eof = true; - } else { - String[] result = null; - try { - s_logger.info("Starting parsing line " + line); - result = parseLine(line, "[,]"); - s_logger.info("Line retrieved from the file is " + result[0] + " " + result[1] + " " + result[2]); - ConsoleProxy proxy = new ConsoleProxy(result[0], result[1], result[2]); - proxyList.add(proxy); - new Thread(proxy).start(); - numThreads++; - - } catch (Exception ex) { - s_logger.warn(ex); - } - } - - } - } catch (Exception e) { - s_logger.warn(e); - } - - } - - public static class ShutdownThread extends Thread { - ProxyLoadTemp temp; - - public ShutdownThread(ProxyLoadTemp temp) { - this.temp = temp; - } - - @Override - public void run() { - s_logger.info("Program was running in " + numThreads + " threads"); - - for (int j = 0; j < proxyList.size(); j++) { - long av = 0; - if (proxyList.get(j).getConnectionsMade() != 0) { - av = proxyList.get(j).getResponseTime() / proxyList.get(j).getConnectionsMade(); - } - s_logger.info("Information for " + j + " thread: Number of requests sent is " + proxyList.get(j).getConnectionsMade() + ". Average response time is " + - av + " milliseconds"); - sum = sum + av; - - } - ProxyLoadTemp.end = System.currentTimeMillis(); - s_logger.info("Summary for all" + numThreads + " threads: Average response time is " + sum / numThreads + " milliseconds"); - s_logger.info("Test was running for " + (ProxyLoadTemp.end - ProxyLoadTemp.begin) / 1000 + " seconds"); - } - } - - public static String[] parseLine(String line, String del) throws Exception { - String del1 = del.substring(1, del.length() - 1); - if (line.contains(del1) != true) { - throw new Exception(); - } else { - String[] token = line.split(del); - return token; - } - - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/SignEC2.java b/test/src-not-used/main/java/com/cloud/test/utils/SignEC2.java deleted file mode 100644 index 29e78c16c98..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/SignEC2.java +++ /dev/null @@ -1,143 +0,0 @@ -// 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.test.utils; - -import java.io.FileInputStream; -import java.io.IOException; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeMap; - -import org.apache.log4j.Logger; - -public class SignEC2 { - public static String url; - public static String secretkey; - public static String host; - public static String port; - public static String command; - public static String accessPoint; - public static final Logger s_logger = Logger.getLogger(SignEC2.class.getName()); - - public static void main(String[] args) { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - - if (arg.equals("-u")) { - url = iter.next(); - } - } - - Properties prop = new Properties(); - try { - prop.load(new FileInputStream("../conf/tool.properties")); - } catch (IOException ex) { - s_logger.error("Error reading from ../conf/tool.properties", ex); - System.exit(2); - } - - host = prop.getProperty("host"); - secretkey = prop.getProperty("secretkey"); - port = prop.getProperty("port"); - - if (host == null) { - s_logger.info("Please set host in tool.properties file"); - System.exit(1); - } - - if (port == null) { - s_logger.info("Please set port in tool.properties file"); - System.exit(1); - } - - if (url == null) { - s_logger.info("Please specify url with -u option"); - System.exit(1); - } - - if (secretkey == null) { - s_logger.info("Please set secretkey in tool.properties file"); - System.exit(1); - } - - if (prop.get("apikey") == null) { - s_logger.info("Please set apikey in tool.properties file"); - System.exit(1); - } - - if (prop.get("accesspoint") == null) { - s_logger.info("Please set apikey in tool.properties file"); - System.exit(1); - } - - TreeMap param = new TreeMap(); - - String req = "GET\n" + host + ":" + prop.getProperty("port") + "\n/" + prop.getProperty("accesspoint") + "\n"; - String temp = ""; - param.put("AWSAccessKeyId", prop.getProperty("apikey")); - param.put("Expires", prop.getProperty("expires")); - param.put("SignatureMethod", "HmacSHA1"); - param.put("SignatureVersion", "2"); - param.put("Version", prop.getProperty("version")); - param.put("id", "1"); - - StringTokenizer str1 = new StringTokenizer(url, "&"); - while (str1.hasMoreTokens()) { - String newEl = str1.nextToken(); - StringTokenizer str2 = new StringTokenizer(newEl, "="); - String name = str2.nextToken(); - String value = str2.nextToken(); - param.put(name, value); - } - - //sort url hash map by key - Set c = param.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + value + " for the command " + param.get("command")); - } - - } - temp = temp.substring(0, temp.length() - 1); - String requestToSign = req + temp; - String signature = UtilsForTest.signRequest(requestToSign, secretkey); - String encodedSignature = ""; - try { - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - } catch (Exception ex) { - s_logger.error(ex); - } - String url = "http://" + host + ":" + prop.getProperty("port") + "/" + prop.getProperty("accesspoint") + "?" + temp + "&Signature=" + encodedSignature; - s_logger.info("Url is " + url); - - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/SignRequest.java b/test/src-not-used/main/java/com/cloud/test/utils/SignRequest.java deleted file mode 100644 index 95fd7b29374..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/SignRequest.java +++ /dev/null @@ -1,112 +0,0 @@ -// 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.test.utils; - -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeMap; - -public class SignRequest { - public static String url; - public static String apikey; - public static String secretkey; - public static String command; - - public static void main(String[] args) { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - if (arg.equals("-a")) { - apikey = iter.next(); - - } - if (arg.equals("-u")) { - url = iter.next(); - } - - if (arg.equals("-s")) { - secretkey = iter.next(); - } - } - - if (url == null) { - System.out.println("Please specify url with -u option. Example: -u \"command=listZones&id=1\""); - System.exit(1); - } - - if (apikey == null) { - System.out.println("Please specify apikey with -a option"); - System.exit(1); - } - - if (secretkey == null) { - System.out.println("Please specify secretkey with -s option"); - System.exit(1); - } - - TreeMap param = new TreeMap(); - - String temp = ""; - param.put("apikey", apikey); - - StringTokenizer str1 = new StringTokenizer(url, "&"); - while (str1.hasMoreTokens()) { - String newEl = str1.nextToken(); - StringTokenizer str2 = new StringTokenizer(newEl, "="); - String name = str2.nextToken(); - String value = str2.nextToken(); - param.put(name, value); - } - - //sort url hash map by key - Set c = param.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; - } catch (Exception ex) { - System.out.println("Unable to set parameter " + value + " for the command " + param.get("command")); - } - - } - temp = temp.substring(0, temp.length() - 1); - String requestToSign = temp.toLowerCase(); - System.out.println("After sorting: " + requestToSign); - String signature = UtilsForTest.signRequest(requestToSign, secretkey); - System.out.println("After Base64 encoding: " + signature); - String encodedSignature = ""; - try { - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - } catch (Exception ex) { - System.out.println(ex); - } - System.out.println("After UTF8 encoding: " + encodedSignature); - String url = temp + "&signature=" + encodedSignature; - System.out.println("After sort and add signature: " + url); - - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/SqlDataGenerator.java b/test/src-not-used/main/java/com/cloud/test/utils/SqlDataGenerator.java deleted file mode 100644 index 8b42b1f1237..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/SqlDataGenerator.java +++ /dev/null @@ -1,49 +0,0 @@ -// 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.test.utils; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.util.Formatter; - -public class SqlDataGenerator { - public static void main(String[] args) { - try { - FileOutputStream fs = new FileOutputStream(new File("out.txt")); - - DataOutputStream out = new DataOutputStream(fs); - - for (int i = 20; i < 171; i++) { - out.writeBytes("INSERT INTO `vmops`.`dc_ip_address_alloc` (ip_address, data_center_id, pod_id) VALUES ('192.168.2." + i + "',1,1);\r\n"); - } - out.writeBytes("\r\n"); - for (int i = 1; i < 10000; i++) { - StringBuilder imagePath = new StringBuilder(); - Formatter formatter = new Formatter(imagePath); - formatter.format("%04x", i); - out.writeBytes("INSERT INTO `vmops`.`dc_vnet_alloc` (vnet, data_center_id) VALUES ('" + imagePath.toString() + "',1);\r\n"); - } - - out.flush(); - out.close(); - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during sql generation: " + e.getLocalizedMessage()); - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/SubmitCert.java b/test/src-not-used/main/java/com/cloud/test/utils/SubmitCert.java deleted file mode 100644 index a130d6728ec..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/SubmitCert.java +++ /dev/null @@ -1,198 +0,0 @@ -// 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.test.utils; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.IOException; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeMap; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; - -public class SubmitCert { - public static String url = "Action=SetCertificate"; - public static String secretKey; - public static String apiKey; - public static String host; - public static String port; - public static String command; - public static String accessPoint; - public static String signatureMethod; - public static String fileName = "tool.properties"; - public static String certFileName; - public static String cert; - public static final Logger s_logger = Logger.getLogger(SubmitCert.class.getName()); - - public static void main(String[] args) { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - - if (arg.equals("-c")) { - certFileName = iter.next(); - } - - if (arg.equals("-s")) { - secretKey = iter.next(); - } - - if (arg.equals("-a")) { - apiKey = iter.next(); - } - - if (arg.equals("-action")) { - url = "Action=" + iter.next(); - } - } - - Properties prop = new Properties(); - try { - prop.load(new FileInputStream("conf/tool.properties")); - } catch (IOException ex) { - s_logger.error("Error reading from conf/tool.properties", ex); - System.exit(2); - } - - host = prop.getProperty("host"); - port = prop.getProperty("port"); - - if (url.equals("Action=SetCertificate") && certFileName == null) { - s_logger.error("Please set path to certificate (including file name) with -c option"); - System.exit(1); - } - - if (secretKey == null) { - s_logger.error("Please set secretkey with -s option"); - System.exit(1); - } - - if (apiKey == null) { - s_logger.error("Please set apikey with -a option"); - System.exit(1); - } - - if (host == null) { - s_logger.error("Please set host in tool.properties file"); - System.exit(1); - } - - if (port == null) { - s_logger.error("Please set port in tool.properties file"); - System.exit(1); - } - - TreeMap param = new TreeMap(); - - String req = "GET\n" + host + ":" + prop.getProperty("port") + "\n/" + prop.getProperty("accesspoint") + "\n"; - String temp = ""; - - if (certFileName != null) { - cert = readCert(certFileName); - param.put("cert", cert); - } - - param.put("AWSAccessKeyId", apiKey); - param.put("Expires", prop.getProperty("expires")); - param.put("SignatureMethod", prop.getProperty("signaturemethod")); - param.put("SignatureVersion", "2"); - param.put("Version", prop.getProperty("version")); - - StringTokenizer str1 = new StringTokenizer(url, "&"); - while (str1.hasMoreTokens()) { - String newEl = str1.nextToken(); - StringTokenizer str2 = new StringTokenizer(newEl, "="); - String name = str2.nextToken(); - String value = str2.nextToken(); - param.put(name, value); - } - - //sort url hash map by key - Set c = param.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + value + " for the command " + param.get("command"), ex); - } - - } - temp = temp.substring(0, temp.length() - 1); - String requestToSign = req + temp; - String signature = UtilsForTest.signRequest(requestToSign, secretKey); - String encodedSignature = ""; - try { - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - } catch (Exception ex) { - ex.printStackTrace(); - } - - String url = "http://" + host + ":" + prop.getProperty("port") + "/" + prop.getProperty("accesspoint") + "?" + temp + "&Signature=" + encodedSignature; - s_logger.info("Sending request with url: " + url + "\n"); - sendRequest(url); - } - - public static String readCert(String filePath) { - try { - StringBuffer fileData = new StringBuffer(1000); - BufferedReader reader = new BufferedReader(new FileReader(filePath)); - char[] buf = new char[1024]; - int numRead = 0; - while ((numRead = reader.read(buf)) != -1) { - String readData = String.valueOf(buf, 0, numRead); - fileData.append(readData); - buf = new char[1024]; - } - reader.close(); - return fileData.toString(); - } catch (Exception ex) { - s_logger.error(ex); - return null; - } - } - - public static void sendRequest(String url) { - try { - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - String is = method.getResponseBodyAsString(); - s_logger.info("Response code " + responseCode + ": " + is); - } catch (Exception ex) { - ex.printStackTrace(); - } - - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/TestClient.java b/test/src-not-used/main/java/com/cloud/test/utils/TestClient.java deleted file mode 100644 index 20df29147e3..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/TestClient.java +++ /dev/null @@ -1,385 +0,0 @@ -// 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.test.utils; - -import java.io.InputStream; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Random; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; - -import com.trilead.ssh2.ChannelCondition; -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.SCPClient; -import com.trilead.ssh2.Session; - -public class TestClient { - private static long sleepTime = 180000L; // default 0 - private static boolean cleanUp = true; - public static final Logger s_logger = Logger.getLogger(TestClient.class.getName()); - private static boolean repeat = true; - private static int numOfUsers = 0; - private static String[] users = null; - private static boolean internet = true; - - private static final int MAX_RETRY_LINUX = 5; - private static final int MAX_RETRY_WIN = 10; - - public static void main(String[] args) { - String host = "http://localhost"; - String port = "8080"; - String testUrl = "/client/test"; - int numThreads = 1; - - try { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - // host - if (arg.equals("-h")) { - host = "http://" + iter.next(); - } - - if (arg.equals("-p")) { - port = iter.next(); - } - - if (arg.equals("-t")) { - numThreads = Integer.parseInt(iter.next()); - } - - if (arg.equals("-s")) { - sleepTime = Long.parseLong(iter.next()); - } - - if (arg.equals("-c")) { - cleanUp = Boolean.parseBoolean(iter.next()); - if (!cleanUp) - sleepTime = 0L; // no need to wait if we don't ever cleanup - } - - if (arg.equals("-r")) { - repeat = Boolean.parseBoolean(iter.next()); - } - - if (arg.equals("-u")) { - numOfUsers = Integer.parseInt(iter.next()); - } - - if (arg.equals("-i")) { - internet = Boolean.parseBoolean(iter.next()); - } - } - - final String server = host + ":" + port + testUrl; - s_logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); - if (cleanUp) - s_logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up"); - - if (numOfUsers > 0) { - s_logger.info("Pre-generating users for test of size : " + numOfUsers); - users = new String[numOfUsers]; - Random ran = new Random(); - for (int i = 0; i < numOfUsers; i++) { - users[i] = Math.abs(ran.nextInt()) + "-user"; - } - } - - for (int i = 0; i < numThreads; i++) { - new Thread(new Runnable() { - @Override - public void run() { - do { - String username = null; - try { - long now = System.currentTimeMillis(); - Random ran = new Random(); - if (users != null) { - username = users[Math.abs(ran.nextInt()) % numOfUsers]; - } else { - username = Math.abs(ran.nextInt()) + "-user"; - } - NDC.push(username); - - String url = server + "?email=" + username + "&password=" + username + "&command=deploy"; - s_logger.info("Launching test for user: " + username + " with url: " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - boolean success = false; - String reason = null; - if (responseCode == 200) { - if (internet) { - s_logger.info("Deploy successful...waiting 5 minute before SSH tests"); - Thread.sleep(300000L); // Wait 60 seconds so the linux VM can boot up. - - s_logger.info("Begin Linux SSH test"); - reason = sshTest(method.getResponseHeader("linuxIP").getValue()); - - if (reason == null) { - s_logger.info("Linux SSH test successful"); - s_logger.info("Begin Windows SSH test"); - reason = sshWinTest(method.getResponseHeader("windowsIP").getValue()); - } - } - if (reason == null) { - if (internet) { - s_logger.info("Windows SSH test successful"); - } else { - s_logger.info("deploy test successful....now cleaning up"); - if (cleanUp) { - s_logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); - Thread.sleep(sleepTime); - } else { - success = true; - } - } - if (users == null) { - s_logger.info("Sending cleanup command"); - url = server + "?email=" + username + "&password=" + username + "&command=cleanup"; - } else { - s_logger.info("Sending stop DomR / destroy VM command"); - url = server + "?email=" + username + "&password=" + username + "&command=stopDomR"; - } - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - success = true; - } else { - reason = method.getStatusText(); - } - } else { - // Just stop but don't destroy the VMs/Routers - s_logger.info("SSH test failed with reason '" + reason + "', stopping VMs"); - url = server + "?email=" + username + "&password=" + username + "&command=stop"; - responseCode = client.executeMethod(new GetMethod(url)); - } - } else { - // Just stop but don't destroy the VMs/Routers - reason = method.getStatusText(); - s_logger.info("Deploy test failed with reason '" + reason + "', stopping VMs"); - url = server + "?email=" + username + "&password=" + username + "&command=stop"; - client.executeMethod(new GetMethod(url)); - } - - if (success) { - s_logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); - } else { - s_logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + - " seconds with reason : " + reason); - } - } catch (Exception e) { - s_logger.warn("Error in thread", e); - try { - HttpClient client = new HttpClient(); - String url = server + "?email=" + username + "&password=" + username + "&command=stop"; - client.executeMethod(new GetMethod(url)); - } catch (Exception e1) { - s_logger.info("[ignored]" - + "error while executing last resort stop attempt: " + e1.getLocalizedMessage()); - } - } finally { - NDC.clear(); - } - } while (repeat); - } - }).start(); - } - } catch (Exception e) { - s_logger.error(e); - } - } - - private static String sshWinTest(String host) { - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring win ssh test"); - return null; - } - - // We will retry 5 times before quitting - int retry = 0; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt"); - Thread.sleep(300000); - } - - s_logger.info("Attempting to SSH into windows host " + host + " with retry attempt: " + retry); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("SSHed successfully into windows host " + host); - boolean success = false; - boolean isAuthenticated = conn.authenticateWithPassword("vmops", "vmops"); - if (isAuthenticated == false) { - return "Authentication failed"; - } - SCPClient scp = new SCPClient(conn); - - scp.put("wget.exe", ""); - - Session sess = conn.openSession(); - s_logger.info("Executing : wget http://172.16.0.220/dump.bin"); - sess.execCommand("wget http://172.16.0.220/dump.bin && dir dump.bin"); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - int len = stderr.read(buffer); - } - } - sess.close(); - conn.close(); - - if (success) { - return null; - } else { - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail"; - } - } - } catch (Exception e) { - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail with error " + e.getMessage(); - } - } - } - } - - private static String sshTest(String host) { - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring ssh test"); - return null; - } - - // We will retry 5 times before quitting - int retry = 0; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt"); - Thread.sleep(120000); - } - - s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("SSHed successfully into linux host " + host); - - boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); - - if (isAuthenticated == false) { - return "Authentication failed"; - } - boolean success = false; - Session sess = conn.openSession(); - s_logger.info("Executing : wget http://172.16.0.220/dump.bin"); - sess.execCommand("wget http://172.16.0.220/dump.bin && ls -al dump.bin"); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - int len = stderr.read(buffer); - } - } - - sess.close(); - conn.close(); - - if (success) { - return null; - } else { - retry++; - if (retry == MAX_RETRY_LINUX) { - return "SSH Linux Network test fail"; - } - } - } catch (Exception e) { - retry++; - if (retry == MAX_RETRY_LINUX) { - return "SSH Linux Network test fail with error " + e.getMessage(); - } - } - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/UtilsForTest.java b/test/src-not-used/main/java/com/cloud/test/utils/UtilsForTest.java deleted file mode 100644 index 78ba001bb9c..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/UtilsForTest.java +++ /dev/null @@ -1,210 +0,0 @@ -// 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.test.utils; - -import java.io.InputStream; -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.codec.binary.Base64; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.utils.exception.CloudRuntimeException; - -public class UtilsForTest { - - private static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - - public static boolean verifyTags(Map params) { - boolean result = true; - for (String value : params.keySet()) { - if (params.get(value) == null) { - result = false; - } - } - return result; - } - - public static boolean verifyTagValues(Map params, Map pattern) { - boolean result = true; - - if (pattern != null) { - for (String value : pattern.keySet()) { - if (!pattern.get(value).equals(params.get(value))) { - result = false; - System.out.println("Tag " + value + " has " + params.get(value) + " while expected value is: " + pattern.get(value)); - } - } - } - return result; - } - - public static Map parseXML(InputStream is, String[] tagNames) { - Map returnValues = new HashMap(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - System.out.println("no " + tagNames[i] + " tag in the response"); - returnValues.put(tagNames[i], null); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - System.out.println("error processing XML"); - ex.printStackTrace(); - } - return returnValues; - } - - public static ArrayList> parseMulXML(InputStream is, String[] tagNames) { - ArrayList> returnValues = new ArrayList>(); - - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - System.out.println("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - for (int j = 0; j < targetNodes.getLength(); j++) { - HashMap valueList = new HashMap(); - Node node = targetNodes.item(j); - //parse child nodes - NodeList child = node.getChildNodes(); - for (int c = 0; c < node.getChildNodes().getLength(); c++) { - child.item(c).getNodeName(); - valueList.put(child.item(c).getNodeName(), child.item(c).getTextContent()); - } - returnValues.add(valueList); - } - - } - } - } catch (Exception ex) { - System.out.println(ex); - } - - return returnValues; - } - - public static String createMD5String(String password) { - MessageDigest md5; - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new CloudRuntimeException("Error", e); - } - - md5.reset(); - BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); - - // make sure our MD5 hash value is 32 digits long... - StringBuffer sb = new StringBuffer(); - String pwStr = pwInt.toString(16); - int padding = 32 - pwStr.length(); - for (int i = 0; i < padding; i++) { - sb.append('0'); - } - sb.append(pwStr); - return sb.toString(); - } - - public static Map getSingleValueFromXML(InputStream is, String[] tagNames) { - Map returnValues = new HashMap(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - System.out.println("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - System.out.println("error processing XML"); - ex.printStackTrace(); - } - return returnValues; - } - - public static Map> getMultipleValuesFromXML(InputStream is, String[] tagNames) { - Map> returnValues = new HashMap>(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - System.out.println("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - List valueList = new ArrayList(); - for (int j = 0; j < targetNodes.getLength(); j++) { - Node node = targetNodes.item(j); - valueList.add(node.getTextContent()); - } - returnValues.put(tagNames[i], valueList); - } - } - } catch (Exception ex) { - System.out.println(ex); - } - return returnValues; - } - - public static String signRequest(String request, String key) { - try { - Mac mac = Mac.getInstance("HmacSHA1"); - SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); - mac.init(keySpec); - mac.update(request.getBytes()); - byte[] encryptedBytes = mac.doFinal(); - //System.out.println("HmacSHA1 hash: " + encryptedBytes); - return Base64.encodeBase64String(encryptedBytes); - } catch (Exception ex) { - System.out.println("unable to sign request"); - ex.printStackTrace(); - } - return null; - } - -} diff --git a/test/systemvm/test_update_config.py b/test/systemvm/test_update_config.py index 6b78bfbee42..5bdfb05dc73 100644 --- a/test/systemvm/test_update_config.py +++ b/test/systemvm/test_update_config.py @@ -280,7 +280,7 @@ class UpdateConfigTestCase(SystemVMTestCase): unique["eth%s" % ips["nic_dev_id"]] = 1 # If this is the first run, the drops will not be there yet - # this is so I can get get a true count of what is explicitly added + # this is so I can get a true count of what is explicitly added drops = len(unique) for dev in unique: drops -= ip.count_fw_rules('ACL_INBOUND_%s -j DROP' % dev) diff --git a/tools/apidoc/build-apidoc.sh b/tools/apidoc/build-apidoc.sh index 35551cda597..035a560dd29 100755 --- a/tools/apidoc/build-apidoc.sh +++ b/tools/apidoc/build-apidoc.sh @@ -6,16 +6,16 @@ # 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. - + # cloud-build-api-doc.sh -- builds api documentation. #set -x diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index bd102e9c7cc..872acc21a08 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -50,6 +50,7 @@ known_categories = { 'SystemVm': 'System VM', 'VirtualMachine': 'Virtual Machine', 'VM': 'Virtual Machine', + 'Vnf': 'Virtual Network Functions', 'Domain': 'Domain', 'Template': 'Template', 'Iso': 'ISO', @@ -133,6 +134,9 @@ known_categories = { 'removeTungstenFabricNetworkGatewayFromLogicalRouter': 'Tungsten', 'updateTungstenFabricLBHealthMonitor': 'Tungsten', 'listTungstenFabricLBHealthMonitor': 'Tungsten', + 'listNsxControllers': 'NSX', + 'addNsxController': 'NSX', + 'deleteNsxController': 'NSX', 'Vpn': 'VPN', 'Limit': 'Limit', 'ResourceCount': 'Limit', @@ -141,6 +145,7 @@ known_categories = { 'StorageMaintenance': 'Storage Pool', 'StoragePool': 'Storage Pool', 'StorageProvider': 'Storage Pool', + 'StorageScope' : 'Storage Pool', 'updateStorageCapabilities' : 'Storage Pool', 'SecurityGroup': 'Security Group', 'SSH': 'SSH', @@ -157,6 +162,11 @@ known_categories = { 'listIdps': 'Authentication', 'authorizeSamlSso': 'Authentication', 'listSamlAuthorization': 'Authentication', + 'oauthlogin': 'Authentication', + 'deleteOauthProvider': 'Oauth', + 'listOauthProvider': 'Oauth', + 'registerOauthProvider': 'Oauth', + 'updateOauthProvider': 'Oauth', 'quota': 'Quota', 'emailTemplate': 'Quota', 'Capacity': 'System Capacity', @@ -204,6 +214,7 @@ known_categories = { 'deleteSecondaryStagingStore': 'Image Store', 'listSecondaryStagingStores': 'Image Store', 'updateImageStore': 'Image Store', + 'downloadImageStoreObject': 'Image Store', 'InternalLoadBalancer': 'Internal LB', 'DeploymentPlanners': 'Configuration', 'ObjectStore': 'Image Store', @@ -249,7 +260,25 @@ known_categories = { 'importVsphereStoragePolicies' : 'vSphere storage policies', 'listVsphereStoragePolicies' : 'vSphere storage policies', 'ConsoleEndpoint': 'Console Endpoint', - 'Shutdown': 'Shutdown' + 'Shutdown': 'Shutdown', + 'importVm': 'Virtual Machine', + 'listQuarantinedIp': 'IP Quarantine', + 'updateQuarantinedIp': 'IP Quarantine', + 'removeQuarantinedIp': 'IP Quarantine', + 'Shutdown': 'Shutdown', + 'addObjectStoragePool': 'Object Store', + 'listObjectStoragePools': 'Object Store', + 'deleteObjectStoragePool': 'Object Store', + 'updateObjectStoragePool': 'Object Store', + 'createBucket': 'Object Store', + 'updateBucket': 'Object Store', + 'deleteBucket': 'Object Store', + 'listBuckets': 'Object Store', + 'listVmsForImport': 'Virtual Machine', + 'importVm': 'Virtual Machine', + 'Webhook': 'Webhook', + 'Webhooks': 'Webhook', + 'purgeExpungedResources': 'Resource' } diff --git a/tools/apidoc/pom.xml b/tools/apidoc/pom.xml index 43f4bc85ffd..c16795065f0 100644 --- a/tools/apidoc/pom.xml +++ b/tools/apidoc/pom.xml @@ -25,7 +25,7 @@ org.apache.cloudstack cloud-tools - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT ../pom.xml diff --git a/tools/appliance/README.md b/tools/appliance/README.md index e9293d6373b..bc5b2014a59 100644 --- a/tools/appliance/README.md +++ b/tools/appliance/README.md @@ -25,7 +25,8 @@ CentOS based built-in user VM template. # Setting up Tools and Environment -- Install packer and latest KVM, qemu on a Linux machine +- Install packer (v1.8.x, v1.9.x tested) and latest KVM, qemu on a Linux x86 + machine (Ubuntu 20.04 tested) - Install tools for exporting appliances: qemu-img, ovftool, faketime, sharutils - Build and install `vhd-util` as described in build.sh or use pre-built binaries at: @@ -33,10 +34,18 @@ CentOS based built-in user VM template. http://packages.shapeblue.com/systemvmtemplate/vhd-util http://packages.shapeblue.com/systemvmtemplate/libvhd.so.1.0 +- For building ARM64 systemvm template on amd64 systems, please also install: + qemu-utils qemu-system-arm qemu-efi-aarch64 + # How to build appliances Just run build.sh, it will export archived appliances for KVM, XenServer, VMWare and HyperV in `dist` directory: - bash build.sh systemvmtemplate + bash build.sh + bash build.sh systemvmtemplate 4.19.1.0 x86_64 + bash build.sh systemvmtemplate 4.19.1.0 aarch64 + +For building builtin x86_64 template run: + bash build.sh builtin diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index 1c83f9aba51..4865842d17b 100755 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -27,6 +27,8 @@ Usage: (or use command line arg, default systemvmtemplate) * Set \$version to provide version to apply to built appliance (or use command line arg, default empty) + * Set \$target_arch to provide target architecture + (or use command line arg, default to current architecture. Currently x86_64 and aarch64 are implemented) * Set \$BUILD_NUMBER to provide build number to apply to built appliance (or use command line arg, default empty) * Set \$DEBUG=1 to enable debug logging @@ -85,12 +87,18 @@ if [[ ! -z "${JENKINS_HOME}" ]]; then DEBUG=1 fi +# get current system architecture +base_arch=`arch` + # which packer definition to use appliance="${1:-${appliance:-systemvmtemplate}}" # optional version tag to put into the image filename version="${2:-${version:-}}" +# which architecture to build the template for +target_arch="${3:-${target_arch:-${base_arch}}}" + # optional (jenkins) build number tag to put into the image filename BUILD_NUMBER="${4:-${BUILD_NUMBER:-}}" @@ -105,7 +113,7 @@ elif [ ! -z "${BUILD_NUMBER}" ]; then version_tag="-${BUILD_NUMBER}" fi -appliance_build_name=${appliance}${version_tag} +appliance_build_name="${appliance}${version_tag}-${target_arch}" ### ### Generic helper functions @@ -218,7 +226,7 @@ function prepare() { function packer_build() { log INFO "building new image with packer" - cd ${appliance_build_name} && packer build template.json && cd .. + cd ${appliance_build_name} && packer build template-base_${base_arch}-target_${target_arch}.json && cd .. } function stage_vmx() { @@ -349,10 +357,12 @@ function main() { # process the disk at dist kvm_export - ovm_export - xen_server_export - vmware_export - hyperv_export + if [ "${target_arch}" == "x86_64" ]; then + ovm_export + xen_server_export + vmware_export + hyperv_export + fi rm -f "dist/${appliance}" cd dist && chmod +r * && cd .. cd dist && md5sum * > md5sum.txt && cd .. diff --git a/tools/appliance/systemvmtemplate/http/preseed_aarch64.cfg b/tools/appliance/systemvmtemplate/http/preseed_aarch64.cfg new file mode 100644 index 00000000000..5262603deaa --- /dev/null +++ b/tools/appliance/systemvmtemplate/http/preseed_aarch64.cfg @@ -0,0 +1,122 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +### Localization +# Locale sets language and country. +d-i debian-installer/locale string en_US.UTF-8 +d-i debian-installer/country string IN + +# Keyboard selection. +d-i keymap select us +d-i keyboard-configuration/xkb-keymap select us + +### Network configuration +d-i netcfg/choose_interface select auto +d-i netcfg/get_hostname string systemvm +d-i netcfg/get_domain string apache.org +d-i netcfg/wireless_wep string + +d-i hw-detect/load_firmware boolean true + +### Mirror settings +d-i mirror/country string manual +d-i mirror/http/hostname string deb.debian.org +d-i mirror/http/directory string /debian +d-i mirror/http/proxy string + +### Apt setup +d-i apt-setup/cdrom/set-first false +d-i apt-setup/security-updates boolean true +d-i apt-setup/services-select multiselect security, updates +d-i apt-setup/security_host string security.debian.org +d-i apt-setup/local0/source boolean false +d-i apt-setup/multiarch string i386 +d-i apt-setup/backports boolean true +d-i apt-setup/contrib boolean true +d-i apt-setup/multiverse boolean true +d-i apt-setup/universe boolean true + +### Clock and time zone setup +d-i clock-setup/utc boolean true +d-i time/zone string UTC +d-i clock-setup/ntp boolean true + +### Partitioning +d-i partman-auto/disk string /dev/vda +d-i partman-auto/method string regular +d-i partman-auto/expert_recipe string \ + boot-root :: \ + 538 538 1075 free \ + $iflabel{ gpt } \ + $reusemethod{ } \ + method{ efi } \ + format{ } \ + . \ + 400 60 400 ext2 \ + $primary{ } $bootable{ } \ + method{ format } format{ } \ + use_filesystem{ } filesystem{ ext2 } \ + mountpoint{ /boot } \ + . \ + 256 1000 256 linux-swap \ + method{ swap } format{ } \ + . \ + 2240 40 4000 ext4 \ + method{ format } format{ } \ + use_filesystem{ } filesystem{ ext4 } \ + mountpoint{ / } \ + . + +d-i partman-md/confirm boolean true +d-i partman-partitioning/confirm_write_new_label boolean true +d-i partman/choose_partition select finish +d-i partman/confirm boolean true +d-i partman/confirm_nooverwrite boolean true +grub-efi-arm64 grub2/force_efi_extra_removable boolean true +d-i partman-partitioning/choose_label select gpt +d-i partman-partitioning/default_label string gpt + +### Base system installation +# ... + +### Account setup +d-i passwd/root-login boolean false +d-i passwd/root-password password password +d-i passwd/root-password-again password password +d-i passwd/user-fullname string Cloud User +d-i passwd/username string cloud +d-i passwd/user-password password cloud +d-i passwd/user-password-again password cloud +d-i user-setup/encrypt-home boolean false +d-i user-setup/allow-password-weak boolean true +d-i passwd/user-default-groups string audio cdrom video admin + +### Package selection +tasksel tasksel/first multiselect ssh-server +d-i pkgsel/include string openssh-server ntp acpid sudo bzip2 openssl +# Allowed values: none, safe-upgrade, full-upgrade +d-i pkgsel/upgrade select full-upgrade +d-i pkgsel/update-policy select none + +popularity-contest popularity-contest/participate boolean false + +### Boot loader installation +d-i grub-installer/only_debian boolean true +d-i grub-installer/bootdev string default +d-i finish-install/reboot_in_progress note + +#### Advanced options diff --git a/tools/appliance/systemvmtemplate/http/preseed.cfg b/tools/appliance/systemvmtemplate/http/preseed_x86_64.cfg similarity index 98% rename from tools/appliance/systemvmtemplate/http/preseed.cfg rename to tools/appliance/systemvmtemplate/http/preseed_x86_64.cfg index ae71ed5c063..1ed0edd492f 100644 --- a/tools/appliance/systemvmtemplate/http/preseed.cfg +++ b/tools/appliance/systemvmtemplate/http/preseed_x86_64.cfg @@ -66,7 +66,7 @@ d-i partman-auto/expert_recipe string \ use_filesystem{ } filesystem{ ext2 } \ mountpoint{ /boot } \ . \ - 256 1000 256 linux-swap \ + 512 1000 512 linux-swap \ method{ swap } format{ } \ . \ 2240 40 4000 ext4 \ diff --git a/tools/appliance/systemvmtemplate/scripts/apt_upgrade.sh b/tools/appliance/systemvmtemplate/scripts/apt_upgrade.sh index bca5077dafe..91a1dd3cdab 100644 --- a/tools/appliance/systemvmtemplate/scripts/apt_upgrade.sh +++ b/tools/appliance/systemvmtemplate/scripts/apt_upgrade.sh @@ -36,8 +36,8 @@ function add_backports() { sed -i '/deb-src/d' /etc/apt/sources.list sed -i '/backports/d' /etc/apt/sources.list sed -i '/security/d' /etc/apt/sources.list - echo 'deb http://http.debian.net/debian bullseye-backports main' >> /etc/apt/sources.list - echo 'deb http://security.debian.org/debian-security bullseye-security main' >> /etc/apt/sources.list + echo 'deb http://http.debian.net/debian bookworm-backports main' >> /etc/apt/sources.list + echo 'deb http://security.debian.org/debian-security bookworm-security main' >> /etc/apt/sources.list } function apt_upgrade() { diff --git a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh index f80d62f7a1e..1a465f4999f 100644 --- a/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh +++ b/tools/appliance/systemvmtemplate/scripts/configure_systemvm_services.sh @@ -19,7 +19,7 @@ set -e set -x -CLOUDSTACK_RELEASE=4.18.1 +CLOUDSTACK_RELEASE=4.20.0 function configure_apache2() { # Enable ssl, rewrite and auth diff --git a/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh b/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh index 3b4ef653728..686661a72f9 100644 --- a/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh +++ b/tools/appliance/systemvmtemplate/scripts/install_systemvm_packages.sh @@ -22,7 +22,7 @@ set -x function install_vhd_util() { [[ -f /bin/vhd-util ]] && return - wget --no-check-certificate https://github.com/shapeblue/cloudstack-nonoss/raw/main/vhd-util -O /bin/vhd-util + wget --no-check-certificate https://download.cloudstack.org/tools/vhd-util -O /bin/vhd-util chmod a+x /bin/vhd-util } @@ -53,7 +53,7 @@ function install_packages() { ${apt_get} install grub-legacy \ rsyslog logrotate cron net-tools ifupdown tmux vim-tiny htop netbase iptables nftables \ openssh-server e2fsprogs tcpdump iftop socat wget coreutils systemd \ - python python3 python3-flask ieee-data \ + python-is-python3 python3 python3-flask python3-netaddr ieee-data \ bzip2 sed gawk diffutils grep gzip less tar telnet ftp rsync traceroute psmisc lsof procps \ inetutils-ping iputils-arping httping curl \ dnsutils zip unzip ethtool uuid file iproute2 acpid sudo \ @@ -63,10 +63,10 @@ function install_packages() { nfs-common \ samba-common cifs-utils \ xl2tpd bcrelay ppp tdb-tools \ - xenstore-utils libxenstore3.0 \ + xenstore-utils libxenstore4 \ ipvsadm conntrackd libnetfilter-conntrack3 \ keepalived irqbalance \ - openjdk-11-jre-headless \ + openjdk-17-jre-headless \ ipcalc ipset \ iptables-persistent \ libtcnative-1 libssl-dev libapr1-dev \ @@ -80,14 +80,10 @@ function install_packages() { apt-get install -y python3-json-pointer python3-jsonschema cloud-init - # python2-netaddr workaround - wget https://github.com/shapeblue/cloudstack-nonoss/raw/main/python-netaddr_0.7.19-1_all.deb - dpkg -i python-netaddr_0.7.19-1_all.deb - apt_clean # 32 bit architecture support for vhd-util - if [ "${arch}" != "i386" ]; then + if [[ "${arch}" != "i386" && "${arch}" != "arm64" ]]; then dpkg --add-architecture i386 apt-get update ${apt_get} install libuuid1:i386 libc6:i386 @@ -96,17 +92,25 @@ function install_packages() { # Install docker and containerd for CKS curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - apt-key fingerprint 0EBFCD88 - add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" + if [ "${arch}" == "arm64" ]; then + add-apt-repository "deb [arch=arm64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" + elif [ "${arch}" == "amd64" ]; then + add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" + else + add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" + fi apt-get update ${apt_get} install containerd.io apt_clean - install_vhd_util - # Install xenserver guest utilities as debian repos don't have it - wget https://mirrors.kernel.org/ubuntu/pool/main/x/xe-guest-utilities/xe-guest-utilities_7.10.0-0ubuntu1_amd64.deb - dpkg -i xe-guest-utilities_7.10.0-0ubuntu1_amd64.deb - rm -f xe-guest-utilities_7.10.0-0ubuntu1_amd64.deb + if [ "${arch}" != "arm64" ]; then + install_vhd_util + # Install xenserver guest utilities as debian repos don't have it + wget --no-check-certificate https://download.cloudstack.org/systemvm/debian/xe-guest-utilities_7.20.2-0ubuntu1_amd64.deb + dpkg -i xe-guest-utilities_7.20.2-0ubuntu1_amd64.deb + rm -f xe-guest-utilities_7.20.2-0ubuntu1_amd64.deb + fi } return 2>/dev/null || install_packages diff --git a/tools/appliance/systemvmtemplate/template-base_aarch64-target_aarch64.json b/tools/appliance/systemvmtemplate/template-base_aarch64-target_aarch64.json new file mode 100644 index 00000000000..2ceadeaf742 --- /dev/null +++ b/tools/appliance/systemvmtemplate/template-base_aarch64-target_aarch64.json @@ -0,0 +1,93 @@ +{ + "_license": "Apache License 2.0", + "builders": [ + { + "accelerator": "kvm", + "boot_command": [ + "c", + "linux /install.a64/vmlinuz ", + "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed_aarch64.cfg ", + "debian-installer=en_US.UTF-8 ", + "auto ", + "language=en locale=en_US.UTF-8 ", + "kbd-chooser/method=us ", + "keyboard-configuration/xkb-keymap=us ", + "netcfg/get_hostname=systemvm ", + "netcfg/get_domain=apache.org ", + "country=IN keymap=us ", + "fb=false ", + "debconf/frontend=noninteractive ", + "console-setup/ask_detect=false ", + "console-keymaps-at/keymap=us ", + "---", + "", + "initrd /install.a64/initrd.gz", + "", + "boot" + ], + "boot_wait": "180s", + "disk_interface": "virtio", + "cdrom_interface": "virtio-scsi", + "disk_size": "5000M", + "format": "qcow2", + "headless": true, + "http_directory": "http", + "iso_checksum": "sha512:14c2ca243ee7f6e447cc4466296d974ee36645c06d72043236c3fbea78f1948d3af88d65139105a475288f270e4b636e6885143d01bdf69462620d1825e470ae", + "iso_url": "https://cdimage.debian.org/mirror/cdimage/archive/12.5.0/arm64/iso-cd/debian-12.5.0-arm64-netinst.iso", + "net_device": "virtio-net", + "output_directory": "../dist", + "qemu_binary": "qemu-system-aarch64", + "qemuargs": [ + [ + "-m", + "500M" + ], + [ + "-machine", + "virt" + ], + [ + "-cpu", + "host" + ], + [ + "-smp", + "1" + ], + [ "-pflash", "/usr/share/AAVMF/AAVMF_CODE.fd" ], + [ "-monitor", "none" ], + [ "-enable-kvm" ], + [ "-boot", "strict=off" ] + ], + "shutdown_command": "sudo halt -p", + "ssh_password": "cloud", + "ssh_timeout": "120m", + "ssh_username": "cloud", + "type": "qemu", + "vm_name": "systemvmtemplate" + } + ], + "description": "CloudStack SystemVM template", + "provisioners": [ + { + "execute_command": "echo 'cloud' | sudo -u root -S bash {{.Path}}", + "scripts": [ + "scripts/apt_upgrade.sh", + "scripts/configure_grub.sh", + "scripts/configure_locale.sh", + "scripts/configure_networking.sh", + "scripts/configure_acpid.sh", + "scripts/install_systemvm_packages.sh", + "scripts/configure_conntrack.sh", + "scripts/authorized_keys.sh", + "scripts/configure_persistent_config.sh", + "scripts/configure_login.sh", + "../cloud_scripts_shar_archive.sh", + "scripts/configure_systemvm_services.sh", + "scripts/cleanup.sh", + "scripts/finalize.sh" + ], + "type": "shell" + } + ] +} diff --git a/tools/appliance/systemvmtemplate/template-base_x86_64-target_aarch64.json b/tools/appliance/systemvmtemplate/template-base_x86_64-target_aarch64.json new file mode 100644 index 00000000000..b49ed17104a --- /dev/null +++ b/tools/appliance/systemvmtemplate/template-base_x86_64-target_aarch64.json @@ -0,0 +1,91 @@ +{ + "_license": "Apache License 2.0", + "builders": [ + { + "boot_command": [ + "c", + "linux /install.a64/vmlinuz ", + "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed_aarch64.cfg ", + "debian-installer=en_US.UTF-8 ", + "auto ", + "language=en locale=en_US.UTF-8 ", + "kbd-chooser/method=us ", + "keyboard-configuration/xkb-keymap=us ", + "netcfg/get_hostname=systemvm ", + "netcfg/get_domain=apache.org ", + "country=IN keymap=us ", + "fb=false ", + "debconf/frontend=noninteractive ", + "console-setup/ask_detect=false ", + "console-keymaps-at/keymap=us ", + "---", + "", + "initrd /install.a64/initrd.gz", + "", + "boot" + ], + "boot_wait": "60s", + "disk_interface": "virtio", + "cdrom_interface": "virtio-scsi", + "disk_size": "5000M", + "format": "qcow2", + "headless": true, + "http_directory": "http", + "iso_checksum": "sha512:14c2ca243ee7f6e447cc4466296d974ee36645c06d72043236c3fbea78f1948d3af88d65139105a475288f270e4b636e6885143d01bdf69462620d1825e470ae", + "iso_url": "https://cdimage.debian.org/mirror/cdimage/archive/12.5.0/arm64/iso-cd/debian-12.5.0-arm64-netinst.iso", + "net_device": "virtio-net", + "output_directory": "../dist", + "qemu_binary": "qemu-system-aarch64", + "qemuargs": [ + [ + "-m", + "500M" + ], + [ + "-machine", + "virt" + ], + [ + "-cpu", + "cortex-a72" + ], + [ + "-smp", + "1" + ], + [ "-bios", "/usr/share/qemu-efi-aarch64/QEMU_EFI.fd" ], + [ "-monitor", "none" ], + [ "-boot", "strict=off" ] + ], + "shutdown_command": "sudo halt -p", + "ssh_password": "cloud", + "ssh_timeout": "120m", + "ssh_username": "cloud", + "type": "qemu", + "vm_name": "systemvmtemplate" + } + ], + "description": "CloudStack SystemVM template", + "provisioners": [ + { + "execute_command": "echo 'cloud' | sudo -u root -S bash {{.Path}}", + "scripts": [ + "scripts/apt_upgrade.sh", + "scripts/configure_grub.sh", + "scripts/configure_locale.sh", + "scripts/configure_networking.sh", + "scripts/configure_acpid.sh", + "scripts/install_systemvm_packages.sh", + "scripts/configure_conntrack.sh", + "scripts/authorized_keys.sh", + "scripts/configure_persistent_config.sh", + "scripts/configure_login.sh", + "../cloud_scripts_shar_archive.sh", + "scripts/configure_systemvm_services.sh", + "scripts/cleanup.sh", + "scripts/finalize.sh" + ], + "type": "shell" + } + ] +} diff --git a/tools/appliance/systemvmtemplate/template.json b/tools/appliance/systemvmtemplate/template-base_x86_64-target_x86_64.json similarity index 90% rename from tools/appliance/systemvmtemplate/template.json rename to tools/appliance/systemvmtemplate/template-base_x86_64-target_x86_64.json index b9d36324dce..5dc2051d127 100644 --- a/tools/appliance/systemvmtemplate/template.json +++ b/tools/appliance/systemvmtemplate/template-base_x86_64-target_x86_64.json @@ -6,7 +6,7 @@ "boot_command": [ "", "install ", - "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ", + "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed_x86_64.cfg ", "debian-installer=en_US.UTF-8 ", "auto ", "language=en locale=en_US.UTF-8 ", @@ -27,8 +27,8 @@ "format": "qcow2", "headless": true, "http_directory": "http", - "iso_checksum": "sha512:4460ef6470f6d8ae193c268e213d33a6a5a0da90c2d30c1024784faa4e4473f0c9b546a41e2d34c43fbbd43542ae4fb93cfd5cb6ac9b88a476f1a6877c478674", - "iso_url": "https://cdimage.debian.org/mirror/cdimage/archive/11.7.0/amd64/iso-cd/debian-11.7.0-amd64-netinst.iso", + "iso_checksum": "sha512:33c08e56c83d13007e4a5511b9bf2c4926c4aa12fd5dd56d493c0653aecbab380988c5bf1671dbaea75c582827797d98c4a611f7fb2b131fbde2c677d5258ec9", + "iso_url": "https://cdimage.debian.org/mirror/cdimage/archive/12.5.0/amd64/iso-cd/debian-12.5.0-amd64-netinst.iso", "net_device": "virtio-net", "output_directory": "../dist", "qemuargs": [ diff --git a/tools/build/build_asf.sh b/tools/build/build_asf.sh index 780473b9df2..a68a71c6153 100755 --- a/tools/build/build_asf.sh +++ b/tools/build/build_asf.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -104,7 +104,7 @@ perl -pi -e "s/-SNAPSHOT//" tools/docker/Dockerfile perl -pi -e "s/-SNAPSHOT//" tools/docker/Dockerfile.marvin perl -pi -e "s/-SNAPSHOT//" tools/docker/Dockerfile.centos6 -case "$currentversion" in +case "$currentversion" in *-SNAPSHOT*) perl -pi -e 's/-SNAPSHOT//' debian/rules ;; @@ -112,7 +112,7 @@ esac # set debian changelog entry tmpfilenm=$$.tmp -echo "cloudstack ($version) unstable; urgency=low" >>$tmpfilenm +echo "cloudstack ($version) unstable; urgency=low" >>$tmpfilenm echo >>$tmpfilenm echo " * Update the version to $version" >>$tmpfilenm echo >>$tmpfilenm diff --git a/tools/build/installer/debinstall_full.sh b/tools/build/installer/debinstall_full.sh index a3bf1aeec57..b125bbf7b57 100644 --- a/tools/build/installer/debinstall_full.sh +++ b/tools/build/installer/debinstall_full.sh @@ -39,13 +39,13 @@ function installed() { function doinstall() { aptitude install "$@" || return $? } - + function doupdate() { service cloud-management stop apt-get --force-yes -y -u install "cloud-*" service cloud-management restart } - + function doremove() { apt-get remove "$@" || return $? } @@ -57,13 +57,13 @@ trap "cleanup" INT TERM EXIT cd `dirname "$0"` setuprepo -installms=" M) Install the Management Server +installms=" M) Install the Management Server " installag=" A) Install the Agent " installus=" S) Install the Usage Monitor " -installdb=" D) Install the database server +installdb=" D) Install the database server " quitoptio=" Q) Quit " diff --git a/tools/build/installer/rpminstall_full.sh b/tools/build/installer/rpminstall_full.sh index 9cc78a5c7ee..1a34a035cec 100755 --- a/tools/build/installer/rpminstall_full.sh +++ b/tools/build/installer/rpminstall_full.sh @@ -43,12 +43,12 @@ function installed() { function doinstall() { yum install "$@" || return $? } - + function doupdate() { yum update --enablerepo='cloud-temp' 'cloud-*' || return $? rpm -Uvh --force cloud-scripts-*.rpm } - + function doremove() { yum remove "$@" || return $? } @@ -60,7 +60,7 @@ trap "cleanup" INT TERM EXIT cd `dirname "$0"` setuprepo -installms=" M) Install the Management Server +installms=" M) Install the Management Server " installag=" A) Install the Agent " @@ -68,7 +68,7 @@ installbm=" B) Install BareMetal Agent " installus=" S) Install the Usage Monitor " -installdb=" D) Install the database server +installdb=" D) Install the database server " quitoptio=" Q) Quit " @@ -139,7 +139,7 @@ elif [ "$installtype" == "d" -o "$installtype" == "D" ] ; then echo "Installing the MySQL server..." >&2 if doinstall mysql-server ; then - /sbin/chkconfig --add mysqld + /sbin/chkconfig --add mysqld /sbin/chkconfig --level 345 mysqld on if /sbin/service mysqld status > /dev/null 2>&1 ; then echo "Restarting the MySQL server..." >&2 diff --git a/tools/build/setnextversion.sh b/tools/build/setnextversion.sh index 47f5e39f1cb..3be6e6bb55d 100755 --- a/tools/build/setnextversion.sh +++ b/tools/build/setnextversion.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/checkstyle/pom.xml b/tools/checkstyle/pom.xml index bef394c72ae..b707cba4969 100644 --- a/tools/checkstyle/pom.xml +++ b/tools/checkstyle/pom.xml @@ -22,7 +22,7 @@ Apache CloudStack Developer Tools - Checkstyle Configuration org.apache.cloudstack checkstyle - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT UTF-8 diff --git a/tools/checkstyle/src/main/resources/cloud-pmd.xml b/tools/checkstyle/src/main/resources/cloud-pmd.xml index ec2914f68f4..66a4ec08294 100644 --- a/tools/checkstyle/src/main/resources/cloud-pmd.xml +++ b/tools/checkstyle/src/main/resources/cloud-pmd.xml @@ -24,13 +24,13 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"> - + Ruleset that brings all the rulesets we want from the pmd jar, because the maven-pmd-plugin doesn't find them otherwise. This is also the place to add our own future rulesets, if any. - + diff --git a/tools/checkstyle/src/main/resources/cloud-style.xml b/tools/checkstyle/src/main/resources/cloud-style.xml index ae68a7a5f08..0c111747eaf 100644 --- a/tools/checkstyle/src/main/resources/cloud-style.xml +++ b/tools/checkstyle/src/main/resources/cloud-style.xml @@ -1,12 +1,12 @@ - org.apache.cloudstack cloud-tools - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT ../pom.xml - mysql - mysql-connector-java + com.mysql + mysql-connector-j provided @@ -80,8 +80,8 @@ - mysql - mysql-connector-java + com.mysql + mysql-connector-j ${cs.mysql.version} diff --git a/tools/devcloud4/README.md b/tools/devcloud4/README.md index b164bb4b9b8..43e662b1a1d 100644 --- a/tools/devcloud4/README.md +++ b/tools/devcloud4/README.md @@ -35,10 +35,10 @@ The included VagrantFile will give you: ``` 1. Download and Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads) - - On Windows7, the Xenserver VM crashed immediately after booting with a General Protection Fault. + + On Windows7, the Xenserver VM crashed immediately after booting with a General Protection Fault. Installing VirtualBox version 4.3.6r91406 (https://www.virtualbox.org/wiki/Download_Old_Builds_4_3) fixed the problem, but only downgrade if the latest version does not work for you. - + 1. Download and install [Vagrant](https://www.vagrantup.com/downloads.html) 1. Ensure all Vagrant Plugins are installed: @@ -51,9 +51,9 @@ The included VagrantFile will give you: ### Configure virtualbox -1. Open virtualbox and navigate to its preferences/settings window. +1. Open virtualbox and navigate to its preferences/settings window. -1. Click onto the network tab and then onto the host only network tab. +1. Click onto the network tab and then onto the host only network tab. 1. Configure your adapters as follows: @@ -61,25 +61,25 @@ The included VagrantFile will give you: - vboxnet0: VirtualBox Host-Only Ethernet Adapter - vboxnet1: VirtualBox Host-Only Ethernet Adapter 2 - vboxnet2: VirtualBox Host-Only Ethernet Adapter 3 - + #### For Basic Networking you only need: ##### vboxnet0 - IPv4 IP address of 192.168.22.1 - Subnet of 255.255.255.0 - DHCP server disabled - + #### For Advanced Networking you will need: - - - + + + ##### vboxnet1 - IPv4 IP address of 192.168.23.1 - Subnet of 255.255.255.0 - DHCP server disabled - - - + + + ##### vboxnet2 - IPv4 IP address of 192.168.24.1 - Subnet of 255.255.255.0 @@ -98,4 +98,3 @@ The included VagrantFile will give you: - IP: 192.168.22.10 - Username: root - Password: password - diff --git a/tools/devcloud4/advanced/README.md b/tools/devcloud4/advanced/README.md index 467e4bb1d86..24082795026 100644 --- a/tools/devcloud4/advanced/README.md +++ b/tools/devcloud4/advanced/README.md @@ -1,8 +1,8 @@ ### Configure virtualbox -1. Open virtualbox and navigate to its preferences/settings window. +1. Open virtualbox and navigate to its preferences/settings window. -1. Click onto the network tab and then onto the host only network tab. +1. Click onto the network tab and then onto the host only network tab. 1. Configure your adapters as follows: @@ -10,18 +10,18 @@ - IPv4 IP address of 192.168.22.1 - Subnet of 255.255.255.0 - DHCP server disabled - + ##### vboxnet1 - IPv4 IP address of 192.168.23.1 - Subnet of 255.255.255.0 - DHCP server disabled - + ##### vboxnet2 - IPv4 IP address of 192.168.24.1 - Subnet of 255.255.255.0 - DHCP server disabled - - + + ### Start the vagrant boxes ```bash @@ -43,8 +43,8 @@ vagrant up ``` *** Note: *** - - Personally I prefer to use the 4.3 codebase rather than main. If you wish to do the same: + + Personally I prefer to use the 4.3 codebase rather than main. If you wish to do the same: ``` git reset --hard 0810029 @@ -64,7 +64,7 @@ vagrant up cd /path/to/cloudstack/repo mvn -P developer,systemvm clean install -DskipTests=true ``` - + 1. Deploy Cloudstack Database: ```bash @@ -89,5 +89,5 @@ vagrant up 1. Deploy: ``` - python -m marvin.deployDataCenter -i marvin.cfg + python -m marvin.deployDataCenter -i marvin.cfg ``` diff --git a/tools/devcloud4/basic/README.md b/tools/devcloud4/basic/README.md index e60c6ee21e0..c0ec6d89ecb 100644 --- a/tools/devcloud4/basic/README.md +++ b/tools/devcloud4/basic/README.md @@ -1,8 +1,8 @@ ### Configure virtualbox -1. Open virtualbox and navigate to its preferences/settings window. +1. Open virtualbox and navigate to its preferences/settings window. -1. Click onto the network tab and then onto the host only network tab. +1. Click onto the network tab and then onto the host only network tab. 1. Configure your adapters as follows: @@ -10,7 +10,7 @@ - IPv4 IP address of 192.168.22.1 - Subnet of 255.255.255.0 - DHCP server disabled - + ### Start the vagrant boxes @@ -33,8 +33,8 @@ vagrant up ``` *** Note: *** - - Personally I prefer to use the 4.3 codebase rather than main. If you wish to do the same: + + Personally I prefer to use the 4.3 codebase rather than main. If you wish to do the same: ``` git reset --hard 0810029 @@ -54,7 +54,7 @@ vagrant up cd /path/to/cloudstack/repo mvn -P developer,systemvm clean install -DskipTests=true ``` - + 1. Deploy Cloudstack Database: ```bash @@ -79,5 +79,5 @@ vagrant up 1. Deploying: ``` - python -m marvin.deployDataCenter -i marvin.cfg + python -m marvin.deployDataCenter -i marvin.cfg ``` diff --git a/tools/devcloud4/common/binary-installation/attributes/database_server.rb b/tools/devcloud4/common/binary-installation/attributes/database_server.rb index 35a388f6d52..200dd125497 100644 --- a/tools/devcloud4/common/binary-installation/attributes/database_server.rb +++ b/tools/devcloud4/common/binary-installation/attributes/database_server.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/binary-installation/attributes/default.rb b/tools/devcloud4/common/binary-installation/attributes/default.rb index 94662cebf53..7f836b53431 100644 --- a/tools/devcloud4/common/binary-installation/attributes/default.rb +++ b/tools/devcloud4/common/binary-installation/attributes/default.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/binary-installation/metadata.rb b/tools/devcloud4/common/binary-installation/metadata.rb index bc2f515c611..6180d50c98f 100644 --- a/tools/devcloud4/common/binary-installation/metadata.rb +++ b/tools/devcloud4/common/binary-installation/metadata.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/binary-installation/recipes/database_server.rb b/tools/devcloud4/common/binary-installation/recipes/database_server.rb index b9341a253f8..0d0c2231f0c 100644 --- a/tools/devcloud4/common/binary-installation/recipes/database_server.rb +++ b/tools/devcloud4/common/binary-installation/recipes/database_server.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/binary-installation/recipes/default.rb b/tools/devcloud4/common/binary-installation/recipes/default.rb index 600ec9891b7..d864056aea9 100644 --- a/tools/devcloud4/common/binary-installation/recipes/default.rb +++ b/tools/devcloud4/common/binary-installation/recipes/default.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/binary-installation/recipes/management_server.rb b/tools/devcloud4/common/binary-installation/recipes/management_server.rb index 742f35f272e..06a0baeb20c 100644 --- a/tools/devcloud4/common/binary-installation/recipes/management_server.rb +++ b/tools/devcloud4/common/binary-installation/recipes/management_server.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/binary-installation/recipes/nfsshares.rb b/tools/devcloud4/common/binary-installation/recipes/nfsshares.rb index 100eab9f2e7..bc12edca0c4 100644 --- a/tools/devcloud4/common/binary-installation/recipes/nfsshares.rb +++ b/tools/devcloud4/common/binary-installation/recipes/nfsshares.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/configure-network.sh b/tools/devcloud4/common/configure-network.sh index dde115dc9ab..bcab6602d92 100644 --- a/tools/devcloud4/common/configure-network.sh +++ b/tools/devcloud4/common/configure-network.sh @@ -8,9 +8,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/development-installation/attributes/database_server.rb b/tools/devcloud4/common/development-installation/attributes/database_server.rb index 314f9c1a550..8a624e9ad1e 100644 --- a/tools/devcloud4/common/development-installation/attributes/database_server.rb +++ b/tools/devcloud4/common/development-installation/attributes/database_server.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/development-installation/attributes/default.rb b/tools/devcloud4/common/development-installation/attributes/default.rb index f2c5712c75a..922bd9f7e35 100644 --- a/tools/devcloud4/common/development-installation/attributes/default.rb +++ b/tools/devcloud4/common/development-installation/attributes/default.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/development-installation/files/default/createtmplt.sh b/tools/devcloud4/common/development-installation/files/default/createtmplt.sh index 6b31232bc9e..2f8f3421350 100755 --- a/tools/devcloud4/common/development-installation/files/default/createtmplt.sh +++ b/tools/devcloud4/common/development-installation/files/default/createtmplt.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -16,7 +16,7 @@ # specific language governing permissions and limitations # under the License. - + # $Id: createtmplt.sh 9132 2010-06-04 20:17:43Z manuel $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/scripts/storage/secondary/createtmplt.sh $ # createtmplt.sh -- install a template @@ -43,7 +43,7 @@ fi verify_cksum() { echo "$1 $2" | md5sum -c --status #printf "$1\t$2" | md5sum -c --status - if [ $? -gt 0 ] + if [ $? -gt 0 ] then printf "Checksum failed, not proceeding with install\n" exit 3 @@ -53,7 +53,7 @@ verify_cksum() { untar() { local ft=$(file $1| awk -F" " '{print $2}') case $ft in - USTAR) + USTAR) printf "tar archives not supported\n" >&2 return 1 ;; @@ -99,12 +99,12 @@ uncompress() { ;; esac - if [ $? -gt 0 ] + if [ $? -gt 0 ] then printf "Failed to uncompress file (filetype=$ft), exiting " - return 1 + return 1 fi - + rm -f $1 printf $tmpfile @@ -170,7 +170,7 @@ do done isCifs() { - #TO:DO incase of multiple zone where cifs and nfs exists, + #TO:DO incase of multiple zone where cifs and nfs exists, #then check if the template file is from cifs using df -P filename #Currently only cifs is supported in hyperv zone. mount | grep "type cifs" > /dev/null @@ -185,7 +185,7 @@ fi mkdir -p $tmpltfs -if [ ! -f $tmpltimg ] +if [ ! -f $tmpltimg ] then printf "root disk file $tmpltimg doesn't exist\n" exit 3 diff --git a/tools/devcloud4/common/development-installation/metadata.rb b/tools/devcloud4/common/development-installation/metadata.rb index c2407554eb2..19255ddf378 100644 --- a/tools/devcloud4/common/development-installation/metadata.rb +++ b/tools/devcloud4/common/development-installation/metadata.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/development-installation/recipes/database_server.rb b/tools/devcloud4/common/development-installation/recipes/database_server.rb index b9341a253f8..0d0c2231f0c 100644 --- a/tools/devcloud4/common/development-installation/recipes/database_server.rb +++ b/tools/devcloud4/common/development-installation/recipes/database_server.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/development-installation/recipes/default.rb b/tools/devcloud4/common/development-installation/recipes/default.rb index 188d923854f..040e0cbd13a 100644 --- a/tools/devcloud4/common/development-installation/recipes/default.rb +++ b/tools/devcloud4/common/development-installation/recipes/default.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/development-installation/recipes/nfsshares.rb b/tools/devcloud4/common/development-installation/recipes/nfsshares.rb index 100eab9f2e7..bc12edca0c4 100644 --- a/tools/devcloud4/common/development-installation/recipes/nfsshares.rb +++ b/tools/devcloud4/common/development-installation/recipes/nfsshares.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/common/development-installation/recipes/system_templates.rb b/tools/devcloud4/common/development-installation/recipes/system_templates.rb index 9601e7bc6ca..39f584c1210 100644 --- a/tools/devcloud4/common/development-installation/recipes/system_templates.rb +++ b/tools/devcloud4/common/development-installation/recipes/system_templates.rb @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/devcloud4/pom.xml b/tools/devcloud4/pom.xml index 6e311763973..d4f2251ba81 100644 --- a/tools/devcloud4/pom.xml +++ b/tools/devcloud4/pom.xml @@ -25,13 +25,13 @@ org.apache.cloudstack cloud-tools - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT ../pom.xml - mysql - mysql-connector-java + com.mysql + mysql-connector-j provided @@ -80,8 +80,8 @@ - mysql - mysql-connector-java + com.mysql + mysql-connector-j ${cs.mysql.version} diff --git a/tools/devcloud4/prefill.sql b/tools/devcloud4/prefill.sql index 4213cd9d68b..00dc69620f8 100644 --- a/tools/devcloud4/prefill.sql +++ b/tools/devcloud4/prefill.sql @@ -5,9 +5,9 @@ -- to you under the Apache License, Version 2.0 (the -- "License"); you may not use this file except in compliance -- with the License. You may obtain a copy of the License at --- +-- -- http://www.apache.org/licenses/LICENSE-2.0 --- +-- -- Unless required by applicable law or agreed to in writing, -- software distributed under the License is distributed on an -- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 9c135b0e1ad..995eca784ce 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -20,7 +20,7 @@ FROM ubuntu:22.04 MAINTAINER "Apache CloudStack" -LABEL Vendor="Apache.org" License="ApacheV2" Version="4.19.0.0" +LABEL Vendor="Apache.org" License="ApacheV2" Version="4.20.0.0-SNAPSHOT" ARG DEBIAN_FRONTEND=noninteractive diff --git a/tools/docker/Dockerfile.marvin b/tools/docker/Dockerfile.marvin index 3faf7218e43..7ce0b629f96 100644 --- a/tools/docker/Dockerfile.marvin +++ b/tools/docker/Dockerfile.marvin @@ -20,11 +20,11 @@ FROM python:2 MAINTAINER "Apache CloudStack" -LABEL Vendor="Apache.org" License="ApacheV2" Version="4.19.0.0" +LABEL Vendor="Apache.org" License="ApacheV2" Version="4.20.0.0-SNAPSHOT" ENV WORK_DIR=/marvin -ENV PKG_URL=https://builds.cloudstack.org/job/build-master-marvin/lastSuccessfulBuild/artifact/tools/marvin/dist/Marvin-4.19.0.0-SNAPSHOT.tar.gz +ENV PKG_URL=https://builds.cloudstack.org/job/build-master-marvin/lastSuccessfulBuild/artifact/tools/marvin/dist/Marvin-4.20.0.0-SNAPSHOT.tar.gz RUN apt-get update && apt-get install -y vim RUN pip install --upgrade paramiko nose requests diff --git a/tools/docker/README.md b/tools/docker/README.md index 4384342dbf3..84cb65bd437 100644 --- a/tools/docker/README.md +++ b/tools/docker/README.md @@ -19,7 +19,7 @@ docker pull apache/cloudstack-simulator:4.17.2.0 docker run --name simulator -p 8080:5050 -d apache/cloudstack-simulator -or +or docker run --name simulator -p 8080:5050 -d apache/cloudstack-simulator:4.17.2.0 @@ -48,7 +48,7 @@ Log into the simulator: docker exec -it simulator bash ``` -### CloudStack Management-server +### CloudStack Management-server ``` docker pull mysql:5.5 diff --git a/tools/docker/systemtpl.sh b/tools/docker/systemtpl.sh index 5298799a9d1..6d8a2d55b5f 100755 --- a/tools/docker/systemtpl.sh +++ b/tools/docker/systemtpl.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/eclipse/eclipse.epf b/tools/eclipse/eclipse.epf index 6b420982cf5..562a29c366a 100644 --- a/tools/eclipse/eclipse.epf +++ b/tools/eclipse/eclipse.epf @@ -15,416 +15,416 @@ # specific language governing permissions and limitations # under the License. -/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_parentheses_in_expressions=false -/instance/org.eclipse.team.ui/org.eclipse.team.ui.first_time=false -/instance/org.eclipse.jdt.ui/cleanup.add_default_serial_version_id=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line -/instance/org.eclipse.ui.workbench/resourcetypes=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n -/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -/instance/org.eclipse.wst.sse.ui/useQuickDiffPrefPage=true -/instance/org.eclipse.jdt.ui/cleanup.always_use_this_for_non_static_method_access=false -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_private_constructors=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.continuation_indentation=2 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true -/instance/org.eclipse.wst.validation/confirmDialog=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -/instance/org.eclipse.jdt.debug/org.eclipse.jdt.debugdefault_watchpoint_suspend_policy=0 -/instance/org.eclipse.jdt.ui/cleanup.add_missing_nls_tags=false -@org.eclipse.wst.sse.core=1.1.702.v201301241617 -/instance/org.eclipse.mylyn.context.core/mylyn.attention.migrated=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false -/instance/org.eclipse.jdt.ui/useAnnotationsPrefPage=true -/instance/org.eclipse.jdt.ui/formatter_profile=_Alex -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert -/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_override_annotations=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -/instance/org.eclipse.debug.ui/preferredDetailPanes=DefaultDetailPane\:DefaultDetailPane|org.eclipse.jdt.debug.ui.DETAIL_PANE_LINE_BREAKPOINT\:org.eclipse.jdt.debug.ui.DETAIL_PANE_LINE_BREAKPOINT|org.eclipse.jdt.debug.ui.DETAIL_PANE_EXCEPTION_BREAKPOINT\:org.eclipse.jdt.debug.ui.DETAIL_PANE_EXCEPTION_BREAKPOINT| -/instance/org.eclipse.wst.validation/override=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert -/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -@org.eclipse.jdt.core=3.8.3.v20130121-145325 -/instance/org.eclipse.jdt.ui/cleanup.make_local_variable_final=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false -/instance/org.eclipse.jdt.ui/cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert -/instance/org.eclipse.jdt.ui/sp_cleanup.sort_members=false -/instance/org.eclipse.jdt.ui/cleanup.remove_unused_imports=true -/instance/org.eclipse.jdt.ui/cleanup.add_serial_version_id=false -/instance/org.eclipse.jdt.ui/cleanup.remove_unnecessary_nls_tags=true -/instance/org.eclipse.debug.ui/preferredTargets=default\:default| -/instance/org.eclipse.jdt.debug.ui/org.eclipse.jdt.debug.ui.javaDebug.alertHCRFailed=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert -/instance/org.eclipse.jdt.ui/cleanup.remove_unused_private_types=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JRE_SRC= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert -/instance/org.eclipse.jdt.ui/cleanup_profile=_Alex -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert -/instance/org.eclipse.jdt.ui/cleanup.format_source_code_changes_only=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert -/instance/org.eclipse.ui.intro/org.eclipse.epp.package.java.product_fontStyle=relative -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert -@org.eclipse.e4.ui.css.swt.theme=0.9.4.v20130123-162658 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert -/instance/org.eclipse.jdt.debug/org.eclipse.jdt.debug.default_breakpoint_suspend_policy=2 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.editor.tab.width= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert -/instance/org.eclipse.jdt.ui/sp_cleanup.make_variable_declarations_final=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert -/instance/org.eclipse.core.resources/version=1 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert -/instance/org.eclipse.jdt.ui/cleanup.add_missing_deprecated_annotations=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.javadoclocations.migrated=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_imports=true -/instance/org.eclipse.jdt.ui/content_assist_favorite_static_members= -/instance/org.eclipse.jdt.ui/sp_cleanup.make_type_abstract_if_missing_method=false -/instance/org.eclipse.jdt.ui/cleanup.remove_private_constructors=true -/instance/org.eclipse.core.runtime/line.separator=\n -/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -/instance/org.eclipse.jdt.ui/fontPropagated=true -/instance/org.eclipse.wst.validation/saveAuto=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.join_wrapped_lines=false -/instance/org.eclipse.ui.workbench/ENABLED_DECORATORS=de.tobject.findbugs.decorators.WorkingSetBugCountDecorator\:true,de.tobject.findbugs.decorators.ProjectBugCountDecorator\:true,de.tobject.findbugs.decorators.FolderBugCountDecorator\:true,de.tobject.findbugs.decorators.FileBugCountDecorator\:true,org.eclipse.m2e.core.mavenVersionDecorator\:false,org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator\:true,org.eclipse.jdt.ui.override.decorator\:true,org.eclipse.jdt.ui.interface.decorator\:false,org.eclipse.jdt.ui.buildpath.decorator\:true,org.eclipse.jubula.client.teststyle.tsGuiNodeDecorator\:true,org.eclipse.jubula.client.teststyle.tsTestresultDecorator\:true,org.eclipse.jubula.client.core.model.TestResultNode\:true,org.eclipse.jubula.client.ui.rcp.decorators.resultDurationDecorator\:true,org.eclipse.jubula.client.ui.rcp.decorators.resultParameterDecorator\:true,org.eclipse.jubula.client.ui.rcp.decorators.completenessCheckDecorator\:true,org.eclipse.jubula.client.ui.rcp.decorators.MissingReferenceDecorator\:true,org.eclipse.jubula.client.ui.rcp.decorators.excelDecorator\:true,org.eclipse.jubula.client.ui.rcp.decorators.activeElementDecorator\:true,org.eclipse.m2e.core.maven2decorator\:true,org.eclipse.mylyn.context.ui.decorator.interest\:true,org.eclipse.mylyn.tasks.ui.decorators.task\:true,org.eclipse.mylyn.team.ui.changeset.decorator\:true,org.eclipse.team.cvs.ui.decorator\:true,org.eclipse.ui.LinkedResourceDecorator\:true,org.eclipse.ui.VirtualResourceDecorator\:true,org.eclipse.ui.ContentTypeDecorator\:true,org.eclipse.ui.ResourceFilterDecorator\:false,org.python.pydev.navigator.decorator.problemsLabelDecorator\:true, -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert -@org.eclipse.ui=3.104.0.v20121024-145224 -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.ondemandthreshold=99 -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.ignorelowercasenames=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 -/instance/org.eclipse.debug.core/org.eclipse.debug.core.PREF_BREAKPOINT_MANAGER_ENABLED_STATE=true -/instance/org.eclipse.mylyn.java.ui/org.eclipse.mylyn.java.ui.run.count.3_1_0=1 -/instance/org.eclipse.ui.ide/IMPORT_FILES_AND_FOLDERS_MODE=prompt -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert -/instance/org.eclipse.jdt.ui/spelling_ignore_digits=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JUNIT_HOME=C\:/bin/Eclipse/current/plugins/org.junit_3.8.2.v3_8_2_v20100427-1100/ -/instance/org.eclipse.jdt.junit/org.eclipse.jdt.junit.show_in_all_views=false -/instance/org.eclipse.jdt.ui/sp_cleanup.make_private_fields_final=true -@org.eclipse.jdt.junit=3.7.100.v20120523-1543 -/instance/org.eclipse.jdt.ui/proposalOrderMigrated=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert -/instance/org.eclipse.wst.validation/vf.version=3 -/instance/org.eclipse.jdt.ui/spelling_ignore_single_letters=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert -/instance/org.eclipse.m2e.core/eclipse.m2.userSettingsFile=c\:\\bin\\Maven\\current\\conf\\settings.xml -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -/instance/org.eclipse.ui.ide/IMPORT_FILES_AND_FOLDERS_VIRTUAL_FOLDER_MODE=prompt -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.cleanupprofiles=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 -@org.python.pydev=2.7.5.2013052819 -/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_this_for_non_static_field_access=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert -/instance/org.eclipse.ui.intro.universal/org.eclipse.epp.package.java.product_INTRO_DATA=\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n -/instance/org.eclipse.debug.ui/pref_state_memento.org.eclipse.debug.ui.DebugVieworg.eclipse.debug.ui.DebugView=\r\n -/instance/org.eclipse.jdt.ui/spelling_ignore_non_letters=true -/instance/org.python.pydev/PYDEV_FUNDING_SHOWN=true -/instance/org.eclipse.jdt.ui/hoverModifierMasks=org.eclipse.jdt.ui.BestMatchHover;0;org.eclipse.jdt.internal.debug.ui.JavaDebugHover;0;org.eclipse.jdt.ui.ProblemHover;0;org.eclipse.jdt.ui.NLSStringHover;327680;org.eclipse.jdt.ui.JavadocHover;393216;org.eclipse.jdt.ui.AnnotationHover;0;org.eclipse.jdt.ui.JavaSourceHover;131072; -/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_override_annotations_interface_methods=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= -/instance/org.eclipse.jdt.debug/org.eclipse.jdt.debug.suspend_for_breakpoints_during_evaluation=true -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_trailing_whitespaces_all=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert -/instance/org.eclipse.jdt.ui/cleanup.always_use_blocks=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.code_templates_migrated=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.tabulation.size=4 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false -/instance/org.eclipse.jdt.ui/useQuickDiffPrefPage=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert -@org.eclipse.egit.core=2.3.1.201302201838-r -/configuration/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.exception.name=e -/instance/org.eclipse.wst.validation/USER_BUILD_PREFERENCE=enabledBuildValidatorList -/instance/org.eclipse.jdt.ui/cleanup.add_missing_methods=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert -/instance/org.eclipse.jdt.ui/sp_cleanup.never_use_blocks=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.align_type_members_on_columns=false -/instance/org.eclipse.jdt.ui/sp_cleanup.add_serial_version_id=false -/instance/org.eclipse.jdt.ui/cleanup_settings_version=2 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_field=0 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert -/instance/org.eclipse.ui.intro.universal/org.eclipse.epp.package.java.product_INTRO_ROOT_PAGES=overview,tutorials,samples,whatsnew -/instance/org.eclipse.e4.ui.css.swt.theme/themeid=org.eclipse.e4.ui.css.theme.e4_classic -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert -/instance/org.eclipse.jdt.ui/hoverModifiers=org.eclipse.jdt.ui.BestMatchHover;0;org.eclipse.jdt.internal.debug.ui.JavaDebugHover;\!0;org.eclipse.jdt.ui.ProblemHover;\!0;org.eclipse.jdt.ui.NLSStringHover;Ctrl+Alt;org.eclipse.jdt.ui.JavadocHover;Ctrl+Shift;org.eclipse.jdt.ui.AnnotationHover;\!0;org.eclipse.jdt.ui.JavaSourceHover;Shift; -/instance/org.eclipse.jdt.ui/cleanup.make_type_abstract_if_missing_method=false -@org.eclipse.wst.validation=1.2.402.v201212031633 -/instance/org.eclipse.wst.validation/USER_PREFERENCE=saveAutomaticallyfalseprojectsCanOverridetruedisableAllValidationfalseversion1.2.402.v201212031633 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indentation.size=4 -/instance/org.eclipse.jdt.ui/cleanup.sort_members_all=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert -\!/= -/instance/org.eclipse.jdt.ui/cleanup.qualify_static_member_accesses_with_declaring_class=true -/instance/org.eclipse.jdt.ui/cleanup.organize_imports=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert -/instance/org.eclipse.jdt.ui/spelling_ignore_mixed=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.join_lines_in_comments=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true -/instance/org.eclipse.jdt.ui/spelling_ignore_upper=true -/instance/org.eclipse.jdt.ui/content_assist_proposals_foreground=0,0,0 -@org.eclipse.ui.editors=3.8.0.v20120523-1540 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert -/instance/org.eclipse.jdt.ui/cleanup.add_missing_annotations=true -/instance/org.eclipse.jdt.ui/sourceHoverBackgroundColor=255,255,225 -/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_nls_tags=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -@org.eclipse.mylyn.java.ui=3.8.3.v20130107-0100 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert -/instance/org.eclipse.jdt.ui/cleanup.remove_trailing_whitespaces_ignore_empty=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert -/instance/org.eclipse.ui.ide/platformState=1364576568717 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert -@org.eclipse.team.cvs.ui=3.3.500.v20120522-1148 -/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_method_access=true -/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_this_for_non_static_method_access=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert -/instance/org.eclipse.jdt.ui/cleanup.make_private_fields_final=true -/instance/org.eclipse.ui.editors/lineNumberRuler=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= -/instance/org.eclipse.jdt.ui/sp_cleanup.format_source_code_changes_only=true -/configuration/org.eclipse.ui.ide/RECENT_WORKSPACES_PROTOCOL=3 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JRE_SRCROOT= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_line_comments=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.indent_root_tags=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.visibilityCheck=enabled -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.PREF_LAUNCH_PERSPECTIVES=\r\n\r\n -/instance/org.eclipse.m2e.editor.xml/org.eclipse.m2e.editor.xml.templates= -/instance/org.eclipse.epp.mpc.ui/CatalogDescriptor=http\://marketplace.eclipse.org -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_local_variables=false -/instance/org.eclipse.jdt.ui/cleanup.convert_to_enhanced_for_loop=false -@org.eclipse.team.core=3.6.100.v20120524-0627 -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_members=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -/instance/org.eclipse.egit.ui/resourcehistory_rev_split=700,300 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.gettersetter.use.is=true -/instance/org.eclipse.jdt.ui/sp_cleanup.format_source_code=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 -@org.eclipse.ui.intro.universal=3.2.600.v20120912-155524 -/instance/org.eclipse.jdt.ui/spelling_locale_initialized=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -/instance/org.eclipse.jdt.ui/sp_cleanup.convert_to_enhanced_for_loop=false -/instance/org.eclipse.jdt.ui/cleanup.add_missing_override_annotations=true -/instance/org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_VM_XML=\r\n\r\n\r\n\r\n\r\n\r\n -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert -/configuration/org.eclipse.ui.ide/SHOW_WORKSPACE_SELECTION_DIALOG=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert -/instance/org.eclipse.debug.ui/pref_state_memento.org.eclipse.debug.ui.ExpressionView=\r\n\r\n\r\n -/instance/org.eclipse.jdt.ui/cleanup.use_parentheses_in_expressions=false -/instance/org.python.pydev.debug/INITIAL_INTERPRETER_CMDS=import sys; print('%s %s' % (sys.executable or sys.platform, sys.version))\r\n -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_assignment=0 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert -/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_deprecated_annotations=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert -/instance/org.eclipse.jdt.ui/cleanup.use_this_for_non_static_field_access_only_if_necessary=true -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.templates_migrated=true -/instance/org.eclipse.egit.ui/merge_mode=0 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert -/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert -/instance/org.eclipse.wst.sse.ui/useAnnotationsPrefPage=true -@org.eclipse.m2e.discovery=1.3.1.20130219-1424 -@org.eclipse.wst.sse.ui=1.3.102.v201301162301 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert -/instance/org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_CONNECT_TIMEOUT=20000 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert -/instance/org.eclipse.jdt.ui/cleanup.use_this_for_non_static_method_access_only_if_necessary=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert -/instance/org.eclipse.ui.workbench/org.eclipse.ui.commands=\r\n -/instance/org.eclipse.wst.xml.core/indentationChar=space -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_methods=true -/instance/org.eclipse.wst.sse.ui/content_assist_number_of_computers=2 -/instance/org.eclipse.team.cvs.ui/pref_first_startup=false -/instance/org.eclipse.egit.ui/Blame_IgnoreWhitespace=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert -/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_field_access=true -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.custom_templates= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.timeoutForParameterNameFromAttachedJavadoc=50 -/instance/org.eclipse.jdt.ui/formatter_settings_version=12 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert -/instance/org.eclipse.jdt.ui/spelling_ignore_sentence=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 -/instance/org.eclipse.jdt.ui/sp_cleanup.never_use_parentheses_in_expressions=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert -/instance/org.eclipse.jdt.ui/cleanup.add_missing_override_annotations_interface_methods=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert -/instance/org.eclipse.jdt.ui/spelling_ignore_java_strings=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 -/instance/org.eclipse.jdt.ui/tabWidthPropagated=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.formatterprofiles=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n -/instance/org.eclipse.wst.xml.core/lineWidth=80 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 -/instance/org.eclipse.jdt.ui/cleanup.make_parameters_final=false -/instance/org.eclipse.jdt.ui/sp_cleanup.use_blocks=false -/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true -/instance/org.python.pydev/IRONPYTHON_INTERPRETER_PATH=\nC\:\\Program Files (x86)\\IronPython 2.7\\ipy64.exe\n2.7\nC\:\\Program Files (x86)\\IronPython 2.7\\ipy64.exe\nC\:\\Program Files (x86)\\IronPython 2.7\\Lib\nC\:\\Program Files (x86)\\IronPython 2.7\\DLLs\nC\:\\Program Files (x86)\\IronPython 2.7\nC\:\\Program Files (x86)\\IronPython 2.7\\lib\\site-packages\nIEHost.Execute\nMicrosoft\nMicrosoft.Aspnet.Snapin\nMicrosoft.Build.BuildEngine\nMicrosoft.Build.Conversion\nMicrosoft.Build.Framework\nMicrosoft.Build.Tasks\nMicrosoft.Build.Tasks.Deployment.Bootstrapper\nMicrosoft.Build.Tasks.Deployment.ManifestUtilities\nMicrosoft.Build.Tasks.Hosting\nMicrosoft.Build.Tasks.Windows\nMicrosoft.Build.Utilities\nMicrosoft.CLRAdmin\nMicrosoft.CSharp\nMicrosoft.Data.Entity.Build.Tasks\nMicrosoft.IE\nMicrosoft.Ink\nMicrosoft.Ink.TextInput\nMicrosoft.JScript\nMicrosoft.JScript.Vsa\nMicrosoft.ManagementConsole\nMicrosoft.ManagementConsole.Advanced\nMicrosoft.ManagementConsole.Internal\nMicrosoft.ServiceModel.Channels.Mail\nMicrosoft.ServiceModel.Channels.Mail.ExchangeWebService\nMicrosoft.ServiceModel.Channels.Mail.ExchangeWebService.Exchange2007\nMicrosoft.ServiceModel.Channels.Mail.WindowsMobile\nMicrosoft.SqlServer.Server\nMicrosoft.StylusInput\nMicrosoft.StylusInput.PluginData\nMicrosoft.VisualBasic\nMicrosoft.VisualBasic.ApplicationServices\nMicrosoft.VisualBasic.Compatibility.VB6\nMicrosoft.VisualBasic.CompilerServices\nMicrosoft.VisualBasic.Devices\nMicrosoft.VisualBasic.FileIO\nMicrosoft.VisualBasic.Logging\nMicrosoft.VisualBasic.MyServices\nMicrosoft.VisualBasic.MyServices.Internal\nMicrosoft.VisualBasic.Vsa\nMicrosoft.VisualC\nMicrosoft.VisualC.StlClr\nMicrosoft.VisualC.StlClr.Generic\nMicrosoft.Vsa\nMicrosoft.Vsa.Vb.CodeDOM\nMicrosoft.Win32\nMicrosoft.Win32.SafeHandles\nMicrosoft.Windows.Themes\nMicrosoft.WindowsCE.Forms\nMicrosoft.WindowsMobile.DirectX\nMicrosoft.WindowsMobile.DirectX.Direct3D\nMicrosoft_VsaVb\nRegCode\nSystem\nSystem.AddIn\nSystem.AddIn.Contract\nSystem.AddIn.Contract.Automation\nSystem.AddIn.Contract.Collections\nSystem.AddIn.Hosting\nSystem.AddIn.Pipeline\nSystem.CodeDom\nSystem.CodeDom.Compiler\nSystem.Collections\nSystem.Collections.Generic\nSystem.Collections.ObjectModel\nSystem.Collections.Specialized\nSystem.ComponentModel\nSystem.ComponentModel.DataAnnotations\nSystem.ComponentModel.Design\nSystem.ComponentModel.Design.Data\nSystem.ComponentModel.Design.Serialization\nSystem.Configuration\nSystem.Configuration.Assemblies\nSystem.Configuration.Install\nSystem.Configuration.Internal\nSystem.Configuration.Provider\nSystem.Data\nSystem.Data.Common\nSystem.Data.Common.CommandTrees\nSystem.Data.Design\nSystem.Data.Entity.Design\nSystem.Data.Entity.Design.AspNet\nSystem.Data.EntityClient\nSystem.Data.Linq\nSystem.Data.Linq.Mapping\nSystem.Data.Linq.SqlClient\nSystem.Data.Linq.SqlClient.Implementation\nSystem.Data.Mapping\nSystem.Data.Metadata.Edm\nSystem.Data.Objects\nSystem.Data.Objects.DataClasses\nSystem.Data.Odbc\nSystem.Data.OleDb\nSystem.Data.OracleClient\nSystem.Data.Services\nSystem.Data.Services.Client\nSystem.Data.Services.Common\nSystem.Data.Services.Design\nSystem.Data.Services.Internal\nSystem.Data.Sql\nSystem.Data.SqlClient\nSystem.Data.SqlTypes\nSystem.Deployment.Application\nSystem.Deployment.Internal\nSystem.Diagnostics\nSystem.Diagnostics.CodeAnalysis\nSystem.Diagnostics.Design\nSystem.Diagnostics.Eventing\nSystem.Diagnostics.Eventing.Reader\nSystem.Diagnostics.PerformanceData\nSystem.Diagnostics.SymbolStore\nSystem.DirectoryServices\nSystem.DirectoryServices.AccountManagement\nSystem.DirectoryServices.ActiveDirectory\nSystem.DirectoryServices.Protocols\nSystem.Drawing\nSystem.Drawing.Design\nSystem.Drawing.Drawing2D\nSystem.Drawing.Imaging\nSystem.Drawing.Printing\nSystem.Drawing.Text\nSystem.EnterpriseServices\nSystem.EnterpriseServices.CompensatingResourceManager\nSystem.EnterpriseServices.Internal\nSystem.Globalization\nSystem.IO\nSystem.IO.Compression\nSystem.IO.IsolatedStorage\nSystem.IO.Log\nSystem.IO.Packaging\nSystem.IO.Pipes\nSystem.IO.Ports\nSystem.IdentityModel.Claims\nSystem.IdentityModel.Policy\nSystem.IdentityModel.Selectors\nSystem.IdentityModel.Tokens\nSystem.Linq\nSystem.Linq.Expressions\nSystem.Management\nSystem.Management.Instrumentation\nSystem.Media\nSystem.Messaging\nSystem.Messaging.Design\nSystem.Net\nSystem.Net.Cache\nSystem.Net.Configuration\nSystem.Net.Mail\nSystem.Net.Mime\nSystem.Net.NetworkInformation\nSystem.Net.PeerToPeer\nSystem.Net.PeerToPeer.Collaboration\nSystem.Net.Security\nSystem.Net.Sockets\nSystem.Printing\nSystem.Printing.IndexedProperties\nSystem.Printing.Interop\nSystem.Reflection\nSystem.Reflection.Emit\nSystem.Resources\nSystem.Resources.Tools\nSystem.Runtime\nSystem.Runtime.CompilerServices\nSystem.Runtime.ConstrainedExecution\nSystem.Runtime.Hosting\nSystem.Runtime.InteropServices\nSystem.Runtime.InteropServices.ComTypes\nSystem.Runtime.InteropServices.CustomMarshalers\nSystem.Runtime.InteropServices.Expando\nSystem.Runtime.Remoting\nSystem.Runtime.Remoting.Activation\nSystem.Runtime.Remoting.Channels\nSystem.Runtime.Remoting.Channels.Http\nSystem.Runtime.Remoting.Channels.Ipc\nSystem.Runtime.Remoting.Channels.Tcp\nSystem.Runtime.Remoting.Contexts\nSystem.Runtime.Remoting.Lifetime\nSystem.Runtime.Remoting.Messaging\nSystem.Runtime.Remoting.Metadata\nSystem.Runtime.Remoting.MetadataServices\nSystem.Runtime.Remoting.Proxies\nSystem.Runtime.Remoting.Services\nSystem.Runtime.Serialization\nSystem.Runtime.Serialization.Configuration\nSystem.Runtime.Serialization.Formatters\nSystem.Runtime.Serialization.Formatters.Binary\nSystem.Runtime.Serialization.Formatters.Soap\nSystem.Runtime.Serialization.Json\nSystem.Runtime.Versioning\nSystem.Security\nSystem.Security.AccessControl\nSystem.Security.Authentication\nSystem.Security.Authentication.ExtendedProtection\nSystem.Security.Authentication.ExtendedProtection.Configuration\nSystem.Security.Cryptography\nSystem.Security.Cryptography.Pkcs\nSystem.Security.Cryptography.X509Certificates\nSystem.Security.Cryptography.Xml\nSystem.Security.Permissions\nSystem.Security.Policy\nSystem.Security.Principal\nSystem.Security.RightsManagement\nSystem.ServiceModel\nSystem.ServiceModel.Activation\nSystem.ServiceModel.Activation.Configuration\nSystem.ServiceModel.Channels\nSystem.ServiceModel.ComIntegration\nSystem.ServiceModel.Configuration\nSystem.ServiceModel.Description\nSystem.ServiceModel.Diagnostics\nSystem.ServiceModel.Dispatcher\nSystem.ServiceModel.Install.Configuration\nSystem.ServiceModel.Internal\nSystem.ServiceModel.MsmqIntegration\nSystem.ServiceModel.PeerResolvers\nSystem.ServiceModel.Persistence\nSystem.ServiceModel.Security\nSystem.ServiceModel.Security.Tokens\nSystem.ServiceModel.Syndication\nSystem.ServiceModel.Web\nSystem.ServiceProcess\nSystem.ServiceProcess.Design\nSystem.Speech.AudioFormat\nSystem.Speech.Recognition\nSystem.Speech.Recognition.SrgsGrammar\nSystem.Speech.Synthesis\nSystem.Speech.Synthesis.TtsEngine\nSystem.Text\nSystem.Text.RegularExpressions\nSystem.Threading\nSystem.Timers\nSystem.Transactions\nSystem.Transactions.Configuration\nSystem.Web\nSystem.Web.ApplicationServices\nSystem.Web.Caching\nSystem.Web.ClientServices\nSystem.Web.ClientServices.Providers\nSystem.Web.Compilation\nSystem.Web.Configuration\nSystem.Web.Configuration.Internal\nSystem.Web.DynamicData\nSystem.Web.DynamicData.Design\nSystem.Web.DynamicData.ModelProviders\nSystem.Web.Handlers\nSystem.Web.Hosting\nSystem.Web.Mail\nSystem.Web.Management\nSystem.Web.Mobile\nSystem.Web.Profile\nSystem.Web.Query.Dynamic\nSystem.Web.RegularExpressions\nSystem.Web.Routing\nSystem.Web.Script.Serialization\nSystem.Web.Script.Services\nSystem.Web.Security\nSystem.Web.Services\nSystem.Web.Services.Configuration\nSystem.Web.Services.Description\nSystem.Web.Services.Discovery\nSystem.Web.Services.Protocols\nSystem.Web.SessionState\nSystem.Web.UI\nSystem.Web.UI.Adapters\nSystem.Web.UI.Design\nSystem.Web.UI.Design.MobileControls\nSystem.Web.UI.Design.MobileControls.Converters\nSystem.Web.UI.Design.WebControls\nSystem.Web.UI.Design.WebControls.WebParts\nSystem.Web.UI.MobileControls\nSystem.Web.UI.MobileControls.Adapters\nSystem.Web.UI.MobileControls.Adapters.XhtmlAdapters\nSystem.Web.UI.WebControls\nSystem.Web.UI.WebControls.Adapters\nSystem.Web.UI.WebControls.WebParts\nSystem.Web.Util\nSystem.Windows\nSystem.Windows.Annotations\nSystem.Windows.Annotations.Storage\nSystem.Windows.Automation\nSystem.Windows.Automation.Peers\nSystem.Windows.Automation.Provider\nSystem.Windows.Automation.Text\nSystem.Windows.Controls\nSystem.Windows.Controls.Primitives\nSystem.Windows.Converters\nSystem.Windows.Data\nSystem.Windows.Documents\nSystem.Windows.Documents.Serialization\nSystem.Windows.Forms\nSystem.Windows.Forms.ComponentModel.Com2Interop\nSystem.Windows.Forms.Design\nSystem.Windows.Forms.Design.Behavior\nSystem.Windows.Forms.Integration\nSystem.Windows.Forms.Layout\nSystem.Windows.Forms.PropertyGridInternal\nSystem.Windows.Forms.VisualStyles\nSystem.Windows.Ink\nSystem.Windows.Ink.AnalysisCore\nSystem.Windows.Input\nSystem.Windows.Input.StylusPlugIns\nSystem.Windows.Interop\nSystem.Windows.Markup\nSystem.Windows.Markup.Localizer\nSystem.Windows.Markup.Primitives\nSystem.Windows.Media\nSystem.Windows.Media.Animation\nSystem.Windows.Media.Converters\nSystem.Windows.Media.Effects\nSystem.Windows.Media.Imaging\nSystem.Windows.Media.Media3D\nSystem.Windows.Media.Media3D.Converters\nSystem.Windows.Media.TextFormatting\nSystem.Windows.Navigation\nSystem.Windows.Resources\nSystem.Windows.Shapes\nSystem.Windows.Threading\nSystem.Windows.Xps\nSystem.Windows.Xps.Packaging\nSystem.Windows.Xps.Serialization\nSystem.Workflow.Activities\nSystem.Workflow.Activities.Configuration\nSystem.Workflow.Activities.Rules\nSystem.Workflow.Activities.Rules.Design\nSystem.Workflow.ComponentModel\nSystem.Workflow.ComponentModel.Compiler\nSystem.Workflow.ComponentModel.Design\nSystem.Workflow.ComponentModel.Serialization\nSystem.Workflow.Runtime\nSystem.Workflow.Runtime.Configuration\nSystem.Workflow.Runtime.DebugEngine\nSystem.Workflow.Runtime.Hosting\nSystem.Workflow.Runtime.Tracking\nSystem.Xml\nSystem.Xml.Linq\nSystem.Xml.Schema\nSystem.Xml.Serialization\nSystem.Xml.Serialization.Advanced\nSystem.Xml.Serialization.Configuration\nSystem.Xml.XPath\nSystem.Xml.Xsl\nSystem.Xml.Xsl.Runtime\nUIAutomationClientsideProviders\n__builtin__\n_ast\n_bisect\n_codecs\n_collections\n_csv\n_ctypes\n_ctypes_test\n_functools\n_heapq\n_io\n_locale\n_md5\n_random\n_sha\n_sha256\n_sha512\n_sqlite3\n_sre\n_ssl\n_struct\n_subprocess\n_warnings\n_weakref\n_winreg\narray\nbinascii\nbz2\ncPickle\ncStringIO\nclr\ncmath\ncopy_reg\ndatetime\nemail\nerrno\nexceptions\nfuture_builtins\ngc\nhashlib\nimp\nitertools\nmarshal\nmath\nmmap\nmsvcrt\nnt\noperator\nos\nos.path\npytest\nre\nselect\nsignal\nsocket\nsys\nthread\ntime\nunicodedata\nwinsound\nwpf\nxxsubtype\nzipimport\nzlib\n&&&&& -/instance/org.eclipse.jdt.ui/cleanup.add_generated_serial_version_id=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert -/instance/org.eclipse.wst.validation/suspend=false -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.formatterprofiles.version=12 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert -/instance/org.eclipse.compare/org.eclipse.compare.IgnoreWhitespace=true -/instance/org.eclipse.egit.ui/resourcehistory_graph_split=500,500 -@org.eclipse.mylyn.monitor.ui=3.8.3.v20130107-0100 -/instance/org.eclipse.ui.ide/PROBLEMS_FILTERS_MIGRATE=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -/instance/org.eclipse.jdt.ui/cleanup.always_use_parentheses_in_expressions=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.argumentSuffixes= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true -/instance/org.eclipse.jdt.ui/sp_cleanup.add_default_serial_version_id=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true -/instance/org.eclipse.debug.ui/pref_state_memento.org.eclipse.debug.ui.BreakpointView=\r\n\r\n\r\n\r\n\r\n -@org.eclipse.ui.workbench=3.104.0.v20130204-164612 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.importorder=java;javax;org;com;org.apache.cloudstack;com.cloud; -/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_member_accesses_with_declaring_class=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert -/instance/org.eclipse.jdt.ui/cleanup.always_use_this_for_non_static_field_access=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -/instance/org.eclipse.jdt.ui/sp_cleanup.organize_imports=true -/instance/org.eclipse.jdt.ui/cleanup.qualify_static_method_accesses_with_declaring_class=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert -@org.eclipse.egit.ui=2.3.1.201302201838-r -/instance/org.eclipse.ui.editors/quickdiff.nowarn.before.switch=always -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.line_length=120 -/instance/org.eclipse.jdt.ui/cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 -/instance/org.eclipse.jdt.debug.ui/org.eclipse.debug.ui.VariableView.org.eclipse.jdt.debug.ui.show_null_entries=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.fieldSuffixes= -/instance/org.eclipse.jdt.ui/content_assist_number_of_computers=21 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.localSuffixes= -/instance/org.eclipse.jdt.junit.core/org.eclipse.jdt.junit.enable_assertions=true -@org.eclipse.core.resources=3.8.1.v20121114-124432 -/instance/org.eclipse.jdt.ui/spelling_ignore_urls=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -/instance/org.eclipse.jdt.ui/content_assist_autoactivation_delay=50 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -@org.eclipse.search=3.8.0.v20120523-1540 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert -/instance/org.eclipse.ui.intro/org.eclipse.epp.package.java.product_INTRO_THEME=org.eclipse.ui.intro.universal.circles -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JSR305_ANNOTATIONS=C\:/bin/Eclipse/current/plugins/edu.umd.cs.findbugs.plugin.eclipse_2.0.2.20121210/lib/jsr305.jar -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JRE_LIB=C\:/bin/Java/jre7/lib/rt.jar -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.lineSplit=180 -/instance/org.eclipse.jdt.ui/content_assist_disabled_computers=org.eclipse.recommenders.completion.rcp.templates.category\u0000org.eclipse.jdt.ui.javaAllProposalCategory\u0000org.eclipse.jdt.ui.javaNoTypeProposalCategory\u0000org.eclipse.recommenders.completion.rcp.chain.category\u0000org.eclipse.jdt.ui.javaTypeProposalCategory\u0000org.eclipse.jdt.ui.textProposalCategory\u0000org.eclipse.recommenders.subwords.rcp.category\u0000 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 -@org.eclipse.ui.ide=3.8.2.v20121106-165923 -@org.eclipse.core.runtime=3.8.0.v20120912-155025 -/instance/org.eclipse.jdt.ui/editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_trailing_whitespaces_ignore_empty=true -/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_blocks=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 -/instance/org.eclipse.jdt.debug/org.eclipse.jdt.debug.PREF_HCR_WITH_COMPILATION_ERRORS=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_html=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert -/instance/org.eclipse.m2e.core/eclipse.m2.WorkspacelifecycleMappingsLocation=D\:/src/workspaces/master/.metadata/.plugins/org.eclipse.m2e.core/lifecycle-mapping-metadata.xml -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line -/instance/org.eclipse.jdt.ui/cleanup.make_variable_declarations_final=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true -/instance/org.eclipse.jdt.ui/cleanup.use_this_for_non_static_field_access=true +/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_parentheses_in_expressions=false +/instance/org.eclipse.team.ui/org.eclipse.team.ui.first_time=false +/instance/org.eclipse.jdt.ui/cleanup.add_default_serial_version_id=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +/instance/org.eclipse.ui.workbench/resourcetypes=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +/instance/org.eclipse.wst.sse.ui/useQuickDiffPrefPage=true +/instance/org.eclipse.jdt.ui/cleanup.always_use_this_for_non_static_method_access=false +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_private_constructors=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.continuation_indentation=2 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +/instance/org.eclipse.wst.validation/confirmDialog=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +/instance/org.eclipse.jdt.debug/org.eclipse.jdt.debugdefault_watchpoint_suspend_policy=0 +/instance/org.eclipse.jdt.ui/cleanup.add_missing_nls_tags=false +@org.eclipse.wst.sse.core=1.1.702.v201301241617 +/instance/org.eclipse.mylyn.context.core/mylyn.attention.migrated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +/instance/org.eclipse.jdt.ui/useAnnotationsPrefPage=true +/instance/org.eclipse.jdt.ui/formatter_profile=_Alex +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_override_annotations=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +/instance/org.eclipse.debug.ui/preferredDetailPanes=DefaultDetailPane\:DefaultDetailPane|org.eclipse.jdt.debug.ui.DETAIL_PANE_LINE_BREAKPOINT\:org.eclipse.jdt.debug.ui.DETAIL_PANE_LINE_BREAKPOINT|org.eclipse.jdt.debug.ui.DETAIL_PANE_EXCEPTION_BREAKPOINT\:org.eclipse.jdt.debug.ui.DETAIL_PANE_EXCEPTION_BREAKPOINT| +/instance/org.eclipse.wst.validation/override=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +@org.eclipse.jdt.core=3.8.3.v20130121-145325 +/instance/org.eclipse.jdt.ui/cleanup.make_local_variable_final=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +/instance/org.eclipse.jdt.ui/cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +/instance/org.eclipse.jdt.ui/sp_cleanup.sort_members=false +/instance/org.eclipse.jdt.ui/cleanup.remove_unused_imports=true +/instance/org.eclipse.jdt.ui/cleanup.add_serial_version_id=false +/instance/org.eclipse.jdt.ui/cleanup.remove_unnecessary_nls_tags=true +/instance/org.eclipse.debug.ui/preferredTargets=default\:default| +/instance/org.eclipse.jdt.debug.ui/org.eclipse.jdt.debug.ui.javaDebug.alertHCRFailed=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +/instance/org.eclipse.jdt.ui/cleanup.remove_unused_private_types=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JRE_SRC= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +/instance/org.eclipse.jdt.ui/cleanup_profile=_Alex +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +/instance/org.eclipse.jdt.ui/cleanup.format_source_code_changes_only=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +/instance/org.eclipse.ui.intro/org.eclipse.epp.package.java.product_fontStyle=relative +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +@org.eclipse.e4.ui.css.swt.theme=0.9.4.v20130123-162658 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +/instance/org.eclipse.jdt.debug/org.eclipse.jdt.debug.default_breakpoint_suspend_policy=2 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.editor.tab.width= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +/instance/org.eclipse.jdt.ui/sp_cleanup.make_variable_declarations_final=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +/instance/org.eclipse.core.resources/version=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +/instance/org.eclipse.jdt.ui/cleanup.add_missing_deprecated_annotations=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.javadoclocations.migrated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_imports=true +/instance/org.eclipse.jdt.ui/content_assist_favorite_static_members= +/instance/org.eclipse.jdt.ui/sp_cleanup.make_type_abstract_if_missing_method=false +/instance/org.eclipse.jdt.ui/cleanup.remove_private_constructors=true +/instance/org.eclipse.core.runtime/line.separator=\n +/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +/instance/org.eclipse.jdt.ui/fontPropagated=true +/instance/org.eclipse.wst.validation/saveAuto=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.join_wrapped_lines=false +/instance/org.eclipse.ui.workbench/ENABLED_DECORATORS=de.tobject.findbugs.decorators.WorkingSetBugCountDecorator\:true,de.tobject.findbugs.decorators.ProjectBugCountDecorator\:true,de.tobject.findbugs.decorators.FolderBugCountDecorator\:true,de.tobject.findbugs.decorators.FileBugCountDecorator\:true,org.eclipse.m2e.core.mavenVersionDecorator\:false,org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator\:true,org.eclipse.jdt.ui.override.decorator\:true,org.eclipse.jdt.ui.interface.decorator\:false,org.eclipse.jdt.ui.buildpath.decorator\:true,org.eclipse.jubula.client.teststyle.tsGuiNodeDecorator\:true,org.eclipse.jubula.client.teststyle.tsTestresultDecorator\:true,org.eclipse.jubula.client.core.model.TestResultNode\:true,org.eclipse.jubula.client.ui.rcp.decorators.resultDurationDecorator\:true,org.eclipse.jubula.client.ui.rcp.decorators.resultParameterDecorator\:true,org.eclipse.jubula.client.ui.rcp.decorators.completenessCheckDecorator\:true,org.eclipse.jubula.client.ui.rcp.decorators.MissingReferenceDecorator\:true,org.eclipse.jubula.client.ui.rcp.decorators.excelDecorator\:true,org.eclipse.jubula.client.ui.rcp.decorators.activeElementDecorator\:true,org.eclipse.m2e.core.maven2decorator\:true,org.eclipse.mylyn.context.ui.decorator.interest\:true,org.eclipse.mylyn.tasks.ui.decorators.task\:true,org.eclipse.mylyn.team.ui.changeset.decorator\:true,org.eclipse.team.cvs.ui.decorator\:true,org.eclipse.ui.LinkedResourceDecorator\:true,org.eclipse.ui.VirtualResourceDecorator\:true,org.eclipse.ui.ContentTypeDecorator\:true,org.eclipse.ui.ResourceFilterDecorator\:false,org.python.pydev.navigator.decorator.problemsLabelDecorator\:true, +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +@org.eclipse.ui=3.104.0.v20121024-145224 +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.ondemandthreshold=99 +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.ignorelowercasenames=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +/instance/org.eclipse.debug.core/org.eclipse.debug.core.PREF_BREAKPOINT_MANAGER_ENABLED_STATE=true +/instance/org.eclipse.mylyn.java.ui/org.eclipse.mylyn.java.ui.run.count.3_1_0=1 +/instance/org.eclipse.ui.ide/IMPORT_FILES_AND_FOLDERS_MODE=prompt +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +/instance/org.eclipse.jdt.ui/spelling_ignore_digits=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JUNIT_HOME=C\:/bin/Eclipse/current/plugins/org.junit_3.8.2.v3_8_2_v20100427-1100/ +/instance/org.eclipse.jdt.junit/org.eclipse.jdt.junit.show_in_all_views=false +/instance/org.eclipse.jdt.ui/sp_cleanup.make_private_fields_final=true +@org.eclipse.jdt.junit=3.7.100.v20120523-1543 +/instance/org.eclipse.jdt.ui/proposalOrderMigrated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +/instance/org.eclipse.wst.validation/vf.version=3 +/instance/org.eclipse.jdt.ui/spelling_ignore_single_letters=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +/instance/org.eclipse.m2e.core/eclipse.m2.userSettingsFile=c\:\\bin\\Maven\\current\\conf\\settings.xml +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +/instance/org.eclipse.ui.ide/IMPORT_FILES_AND_FOLDERS_VIRTUAL_FOLDER_MODE=prompt +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.cleanupprofiles=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +@org.python.pydev=2.7.5.2013052819 +/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_this_for_non_static_field_access=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +/instance/org.eclipse.ui.intro.universal/org.eclipse.epp.package.java.product_INTRO_DATA=\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n +/instance/org.eclipse.debug.ui/pref_state_memento.org.eclipse.debug.ui.DebugVieworg.eclipse.debug.ui.DebugView=\r\n +/instance/org.eclipse.jdt.ui/spelling_ignore_non_letters=true +/instance/org.python.pydev/PYDEV_FUNDING_SHOWN=true +/instance/org.eclipse.jdt.ui/hoverModifierMasks=org.eclipse.jdt.ui.BestMatchHover;0;org.eclipse.jdt.internal.debug.ui.JavaDebugHover;0;org.eclipse.jdt.ui.ProblemHover;0;org.eclipse.jdt.ui.NLSStringHover;327680;org.eclipse.jdt.ui.JavadocHover;393216;org.eclipse.jdt.ui.AnnotationHover;0;org.eclipse.jdt.ui.JavaSourceHover;131072; +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_override_annotations_interface_methods=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= +/instance/org.eclipse.jdt.debug/org.eclipse.jdt.debug.suspend_for_breakpoints_during_evaluation=true +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_trailing_whitespaces_all=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +/instance/org.eclipse.jdt.ui/cleanup.always_use_blocks=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.code_templates_migrated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.tabulation.size=4 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +/instance/org.eclipse.jdt.ui/useQuickDiffPrefPage=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +@org.eclipse.egit.core=2.3.1.201302201838-r +/configuration/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.exception.name=e +/instance/org.eclipse.wst.validation/USER_BUILD_PREFERENCE=enabledBuildValidatorList +/instance/org.eclipse.jdt.ui/cleanup.add_missing_methods=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +/instance/org.eclipse.jdt.ui/sp_cleanup.never_use_blocks=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +/instance/org.eclipse.jdt.ui/sp_cleanup.add_serial_version_id=false +/instance/org.eclipse.jdt.ui/cleanup_settings_version=2 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +/instance/org.eclipse.ui.intro.universal/org.eclipse.epp.package.java.product_INTRO_ROOT_PAGES=overview,tutorials,samples,whatsnew +/instance/org.eclipse.e4.ui.css.swt.theme/themeid=org.eclipse.e4.ui.css.theme.e4_classic +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +/instance/org.eclipse.jdt.ui/hoverModifiers=org.eclipse.jdt.ui.BestMatchHover;0;org.eclipse.jdt.internal.debug.ui.JavaDebugHover;\!0;org.eclipse.jdt.ui.ProblemHover;\!0;org.eclipse.jdt.ui.NLSStringHover;Ctrl+Alt;org.eclipse.jdt.ui.JavadocHover;Ctrl+Shift;org.eclipse.jdt.ui.AnnotationHover;\!0;org.eclipse.jdt.ui.JavaSourceHover;Shift; +/instance/org.eclipse.jdt.ui/cleanup.make_type_abstract_if_missing_method=false +@org.eclipse.wst.validation=1.2.402.v201212031633 +/instance/org.eclipse.wst.validation/USER_PREFERENCE=saveAutomaticallyfalseprojectsCanOverridetruedisableAllValidationfalseversion1.2.402.v201212031633 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indentation.size=4 +/instance/org.eclipse.jdt.ui/cleanup.sort_members_all=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +\!/= +/instance/org.eclipse.jdt.ui/cleanup.qualify_static_member_accesses_with_declaring_class=true +/instance/org.eclipse.jdt.ui/cleanup.organize_imports=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +/instance/org.eclipse.jdt.ui/spelling_ignore_mixed=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.join_lines_in_comments=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +/instance/org.eclipse.jdt.ui/spelling_ignore_upper=true +/instance/org.eclipse.jdt.ui/content_assist_proposals_foreground=0,0,0 +@org.eclipse.ui.editors=3.8.0.v20120523-1540 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +/instance/org.eclipse.jdt.ui/cleanup.add_missing_annotations=true +/instance/org.eclipse.jdt.ui/sourceHoverBackgroundColor=255,255,225 +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_nls_tags=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +@org.eclipse.mylyn.java.ui=3.8.3.v20130107-0100 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +/instance/org.eclipse.jdt.ui/cleanup.remove_trailing_whitespaces_ignore_empty=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +/instance/org.eclipse.ui.ide/platformState=1364576568717 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +@org.eclipse.team.cvs.ui=3.3.500.v20120522-1148 +/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_method_access=true +/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_this_for_non_static_method_access=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +/instance/org.eclipse.jdt.ui/cleanup.make_private_fields_final=true +/instance/org.eclipse.ui.editors/lineNumberRuler=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +/instance/org.eclipse.jdt.ui/sp_cleanup.format_source_code_changes_only=true +/configuration/org.eclipse.ui.ide/RECENT_WORKSPACES_PROTOCOL=3 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JRE_SRCROOT= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_line_comments=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.visibilityCheck=enabled +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.PREF_LAUNCH_PERSPECTIVES=\r\n\r\n +/instance/org.eclipse.m2e.editor.xml/org.eclipse.m2e.editor.xml.templates= +/instance/org.eclipse.epp.mpc.ui/CatalogDescriptor=http\://marketplace.eclipse.org +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_local_variables=false +/instance/org.eclipse.jdt.ui/cleanup.convert_to_enhanced_for_loop=false +@org.eclipse.team.core=3.6.100.v20120524-0627 +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_members=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +/instance/org.eclipse.egit.ui/resourcehistory_rev_split=700,300 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.gettersetter.use.is=true +/instance/org.eclipse.jdt.ui/sp_cleanup.format_source_code=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +@org.eclipse.ui.intro.universal=3.2.600.v20120912-155524 +/instance/org.eclipse.jdt.ui/spelling_locale_initialized=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.convert_to_enhanced_for_loop=false +/instance/org.eclipse.jdt.ui/cleanup.add_missing_override_annotations=true +/instance/org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_VM_XML=\r\n\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +/configuration/org.eclipse.ui.ide/SHOW_WORKSPACE_SELECTION_DIALOG=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +/instance/org.eclipse.debug.ui/pref_state_memento.org.eclipse.debug.ui.ExpressionView=\r\n\r\n\r\n +/instance/org.eclipse.jdt.ui/cleanup.use_parentheses_in_expressions=false +/instance/org.python.pydev.debug/INITIAL_INTERPRETER_CMDS=import sys; print('%s %s' % (sys.executable or sys.platform, sys.version))\r\n +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_deprecated_annotations=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +/instance/org.eclipse.jdt.ui/cleanup.use_this_for_non_static_field_access_only_if_necessary=true +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.templates_migrated=true +/instance/org.eclipse.egit.ui/merge_mode=0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +/instance/org.eclipse.wst.sse.ui/useAnnotationsPrefPage=true +@org.eclipse.m2e.discovery=1.3.1.20130219-1424 +@org.eclipse.wst.sse.ui=1.3.102.v201301162301 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +/instance/org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_CONNECT_TIMEOUT=20000 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +/instance/org.eclipse.jdt.ui/cleanup.use_this_for_non_static_method_access_only_if_necessary=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +/instance/org.eclipse.ui.workbench/org.eclipse.ui.commands=\r\n +/instance/org.eclipse.wst.xml.core/indentationChar=space +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_methods=true +/instance/org.eclipse.wst.sse.ui/content_assist_number_of_computers=2 +/instance/org.eclipse.team.cvs.ui/pref_first_startup=false +/instance/org.eclipse.egit.ui/Blame_IgnoreWhitespace=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_field_access=true +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.custom_templates= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.timeoutForParameterNameFromAttachedJavadoc=50 +/instance/org.eclipse.jdt.ui/formatter_settings_version=12 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +/instance/org.eclipse.jdt.ui/spelling_ignore_sentence=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +/instance/org.eclipse.jdt.ui/sp_cleanup.never_use_parentheses_in_expressions=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +/instance/org.eclipse.jdt.ui/cleanup.add_missing_override_annotations_interface_methods=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +/instance/org.eclipse.jdt.ui/spelling_ignore_java_strings=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +/instance/org.eclipse.jdt.ui/tabWidthPropagated=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.formatterprofiles=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.wst.xml.core/lineWidth=80 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +/instance/org.eclipse.jdt.ui/cleanup.make_parameters_final=false +/instance/org.eclipse.jdt.ui/sp_cleanup.use_blocks=false +/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +/instance/org.python.pydev/IRONPYTHON_INTERPRETER_PATH=\nC\:\\Program Files (x86)\\IronPython 2.7\\ipy64.exe\n2.7\nC\:\\Program Files (x86)\\IronPython 2.7\\ipy64.exe\nC\:\\Program Files (x86)\\IronPython 2.7\\Lib\nC\:\\Program Files (x86)\\IronPython 2.7\\DLLs\nC\:\\Program Files (x86)\\IronPython 2.7\nC\:\\Program Files (x86)\\IronPython 2.7\\lib\\site-packages\nIEHost.Execute\nMicrosoft\nMicrosoft.Aspnet.Snapin\nMicrosoft.Build.BuildEngine\nMicrosoft.Build.Conversion\nMicrosoft.Build.Framework\nMicrosoft.Build.Tasks\nMicrosoft.Build.Tasks.Deployment.Bootstrapper\nMicrosoft.Build.Tasks.Deployment.ManifestUtilities\nMicrosoft.Build.Tasks.Hosting\nMicrosoft.Build.Tasks.Windows\nMicrosoft.Build.Utilities\nMicrosoft.CLRAdmin\nMicrosoft.CSharp\nMicrosoft.Data.Entity.Build.Tasks\nMicrosoft.IE\nMicrosoft.Ink\nMicrosoft.Ink.TextInput\nMicrosoft.JScript\nMicrosoft.JScript.Vsa\nMicrosoft.ManagementConsole\nMicrosoft.ManagementConsole.Advanced\nMicrosoft.ManagementConsole.Internal\nMicrosoft.ServiceModel.Channels.Mail\nMicrosoft.ServiceModel.Channels.Mail.ExchangeWebService\nMicrosoft.ServiceModel.Channels.Mail.ExchangeWebService.Exchange2007\nMicrosoft.ServiceModel.Channels.Mail.WindowsMobile\nMicrosoft.SqlServer.Server\nMicrosoft.StylusInput\nMicrosoft.StylusInput.PluginData\nMicrosoft.VisualBasic\nMicrosoft.VisualBasic.ApplicationServices\nMicrosoft.VisualBasic.Compatibility.VB6\nMicrosoft.VisualBasic.CompilerServices\nMicrosoft.VisualBasic.Devices\nMicrosoft.VisualBasic.FileIO\nMicrosoft.VisualBasic.Logging\nMicrosoft.VisualBasic.MyServices\nMicrosoft.VisualBasic.MyServices.Internal\nMicrosoft.VisualBasic.Vsa\nMicrosoft.VisualC\nMicrosoft.VisualC.StlClr\nMicrosoft.VisualC.StlClr.Generic\nMicrosoft.Vsa\nMicrosoft.Vsa.Vb.CodeDOM\nMicrosoft.Win32\nMicrosoft.Win32.SafeHandles\nMicrosoft.Windows.Themes\nMicrosoft.WindowsCE.Forms\nMicrosoft.WindowsMobile.DirectX\nMicrosoft.WindowsMobile.DirectX.Direct3D\nMicrosoft_VsaVb\nRegCode\nSystem\nSystem.AddIn\nSystem.AddIn.Contract\nSystem.AddIn.Contract.Automation\nSystem.AddIn.Contract.Collections\nSystem.AddIn.Hosting\nSystem.AddIn.Pipeline\nSystem.CodeDom\nSystem.CodeDom.Compiler\nSystem.Collections\nSystem.Collections.Generic\nSystem.Collections.ObjectModel\nSystem.Collections.Specialized\nSystem.ComponentModel\nSystem.ComponentModel.DataAnnotations\nSystem.ComponentModel.Design\nSystem.ComponentModel.Design.Data\nSystem.ComponentModel.Design.Serialization\nSystem.Configuration\nSystem.Configuration.Assemblies\nSystem.Configuration.Install\nSystem.Configuration.Internal\nSystem.Configuration.Provider\nSystem.Data\nSystem.Data.Common\nSystem.Data.Common.CommandTrees\nSystem.Data.Design\nSystem.Data.Entity.Design\nSystem.Data.Entity.Design.AspNet\nSystem.Data.EntityClient\nSystem.Data.Linq\nSystem.Data.Linq.Mapping\nSystem.Data.Linq.SqlClient\nSystem.Data.Linq.SqlClient.Implementation\nSystem.Data.Mapping\nSystem.Data.Metadata.Edm\nSystem.Data.Objects\nSystem.Data.Objects.DataClasses\nSystem.Data.Odbc\nSystem.Data.OleDb\nSystem.Data.OracleClient\nSystem.Data.Services\nSystem.Data.Services.Client\nSystem.Data.Services.Common\nSystem.Data.Services.Design\nSystem.Data.Services.Internal\nSystem.Data.Sql\nSystem.Data.SqlClient\nSystem.Data.SqlTypes\nSystem.Deployment.Application\nSystem.Deployment.Internal\nSystem.Diagnostics\nSystem.Diagnostics.CodeAnalysis\nSystem.Diagnostics.Design\nSystem.Diagnostics.Eventing\nSystem.Diagnostics.Eventing.Reader\nSystem.Diagnostics.PerformanceData\nSystem.Diagnostics.SymbolStore\nSystem.DirectoryServices\nSystem.DirectoryServices.AccountManagement\nSystem.DirectoryServices.ActiveDirectory\nSystem.DirectoryServices.Protocols\nSystem.Drawing\nSystem.Drawing.Design\nSystem.Drawing.Drawing2D\nSystem.Drawing.Imaging\nSystem.Drawing.Printing\nSystem.Drawing.Text\nSystem.EnterpriseServices\nSystem.EnterpriseServices.CompensatingResourceManager\nSystem.EnterpriseServices.Internal\nSystem.Globalization\nSystem.IO\nSystem.IO.Compression\nSystem.IO.IsolatedStorage\nSystem.IO.Log\nSystem.IO.Packaging\nSystem.IO.Pipes\nSystem.IO.Ports\nSystem.IdentityModel.Claims\nSystem.IdentityModel.Policy\nSystem.IdentityModel.Selectors\nSystem.IdentityModel.Tokens\nSystem.Linq\nSystem.Linq.Expressions\nSystem.Management\nSystem.Management.Instrumentation\nSystem.Media\nSystem.Messaging\nSystem.Messaging.Design\nSystem.Net\nSystem.Net.Cache\nSystem.Net.Configuration\nSystem.Net.Mail\nSystem.Net.Mime\nSystem.Net.NetworkInformation\nSystem.Net.PeerToPeer\nSystem.Net.PeerToPeer.Collaboration\nSystem.Net.Security\nSystem.Net.Sockets\nSystem.Printing\nSystem.Printing.IndexedProperties\nSystem.Printing.Interop\nSystem.Reflection\nSystem.Reflection.Emit\nSystem.Resources\nSystem.Resources.Tools\nSystem.Runtime\nSystem.Runtime.CompilerServices\nSystem.Runtime.ConstrainedExecution\nSystem.Runtime.Hosting\nSystem.Runtime.InteropServices\nSystem.Runtime.InteropServices.ComTypes\nSystem.Runtime.InteropServices.CustomMarshalers\nSystem.Runtime.InteropServices.Expando\nSystem.Runtime.Remoting\nSystem.Runtime.Remoting.Activation\nSystem.Runtime.Remoting.Channels\nSystem.Runtime.Remoting.Channels.Http\nSystem.Runtime.Remoting.Channels.Ipc\nSystem.Runtime.Remoting.Channels.Tcp\nSystem.Runtime.Remoting.Contexts\nSystem.Runtime.Remoting.Lifetime\nSystem.Runtime.Remoting.Messaging\nSystem.Runtime.Remoting.Metadata\nSystem.Runtime.Remoting.MetadataServices\nSystem.Runtime.Remoting.Proxies\nSystem.Runtime.Remoting.Services\nSystem.Runtime.Serialization\nSystem.Runtime.Serialization.Configuration\nSystem.Runtime.Serialization.Formatters\nSystem.Runtime.Serialization.Formatters.Binary\nSystem.Runtime.Serialization.Formatters.Soap\nSystem.Runtime.Serialization.Json\nSystem.Runtime.Versioning\nSystem.Security\nSystem.Security.AccessControl\nSystem.Security.Authentication\nSystem.Security.Authentication.ExtendedProtection\nSystem.Security.Authentication.ExtendedProtection.Configuration\nSystem.Security.Cryptography\nSystem.Security.Cryptography.Pkcs\nSystem.Security.Cryptography.X509Certificates\nSystem.Security.Cryptography.Xml\nSystem.Security.Permissions\nSystem.Security.Policy\nSystem.Security.Principal\nSystem.Security.RightsManagement\nSystem.ServiceModel\nSystem.ServiceModel.Activation\nSystem.ServiceModel.Activation.Configuration\nSystem.ServiceModel.Channels\nSystem.ServiceModel.ComIntegration\nSystem.ServiceModel.Configuration\nSystem.ServiceModel.Description\nSystem.ServiceModel.Diagnostics\nSystem.ServiceModel.Dispatcher\nSystem.ServiceModel.Install.Configuration\nSystem.ServiceModel.Internal\nSystem.ServiceModel.MsmqIntegration\nSystem.ServiceModel.PeerResolvers\nSystem.ServiceModel.Persistence\nSystem.ServiceModel.Security\nSystem.ServiceModel.Security.Tokens\nSystem.ServiceModel.Syndication\nSystem.ServiceModel.Web\nSystem.ServiceProcess\nSystem.ServiceProcess.Design\nSystem.Speech.AudioFormat\nSystem.Speech.Recognition\nSystem.Speech.Recognition.SrgsGrammar\nSystem.Speech.Synthesis\nSystem.Speech.Synthesis.TtsEngine\nSystem.Text\nSystem.Text.RegularExpressions\nSystem.Threading\nSystem.Timers\nSystem.Transactions\nSystem.Transactions.Configuration\nSystem.Web\nSystem.Web.ApplicationServices\nSystem.Web.Caching\nSystem.Web.ClientServices\nSystem.Web.ClientServices.Providers\nSystem.Web.Compilation\nSystem.Web.Configuration\nSystem.Web.Configuration.Internal\nSystem.Web.DynamicData\nSystem.Web.DynamicData.Design\nSystem.Web.DynamicData.ModelProviders\nSystem.Web.Handlers\nSystem.Web.Hosting\nSystem.Web.Mail\nSystem.Web.Management\nSystem.Web.Mobile\nSystem.Web.Profile\nSystem.Web.Query.Dynamic\nSystem.Web.RegularExpressions\nSystem.Web.Routing\nSystem.Web.Script.Serialization\nSystem.Web.Script.Services\nSystem.Web.Security\nSystem.Web.Services\nSystem.Web.Services.Configuration\nSystem.Web.Services.Description\nSystem.Web.Services.Discovery\nSystem.Web.Services.Protocols\nSystem.Web.SessionState\nSystem.Web.UI\nSystem.Web.UI.Adapters\nSystem.Web.UI.Design\nSystem.Web.UI.Design.MobileControls\nSystem.Web.UI.Design.MobileControls.Converters\nSystem.Web.UI.Design.WebControls\nSystem.Web.UI.Design.WebControls.WebParts\nSystem.Web.UI.MobileControls\nSystem.Web.UI.MobileControls.Adapters\nSystem.Web.UI.MobileControls.Adapters.XhtmlAdapters\nSystem.Web.UI.WebControls\nSystem.Web.UI.WebControls.Adapters\nSystem.Web.UI.WebControls.WebParts\nSystem.Web.Util\nSystem.Windows\nSystem.Windows.Annotations\nSystem.Windows.Annotations.Storage\nSystem.Windows.Automation\nSystem.Windows.Automation.Peers\nSystem.Windows.Automation.Provider\nSystem.Windows.Automation.Text\nSystem.Windows.Controls\nSystem.Windows.Controls.Primitives\nSystem.Windows.Converters\nSystem.Windows.Data\nSystem.Windows.Documents\nSystem.Windows.Documents.Serialization\nSystem.Windows.Forms\nSystem.Windows.Forms.ComponentModel.Com2Interop\nSystem.Windows.Forms.Design\nSystem.Windows.Forms.Design.Behavior\nSystem.Windows.Forms.Integration\nSystem.Windows.Forms.Layout\nSystem.Windows.Forms.PropertyGridInternal\nSystem.Windows.Forms.VisualStyles\nSystem.Windows.Ink\nSystem.Windows.Ink.AnalysisCore\nSystem.Windows.Input\nSystem.Windows.Input.StylusPlugIns\nSystem.Windows.Interop\nSystem.Windows.Markup\nSystem.Windows.Markup.Localizer\nSystem.Windows.Markup.Primitives\nSystem.Windows.Media\nSystem.Windows.Media.Animation\nSystem.Windows.Media.Converters\nSystem.Windows.Media.Effects\nSystem.Windows.Media.Imaging\nSystem.Windows.Media.Media3D\nSystem.Windows.Media.Media3D.Converters\nSystem.Windows.Media.TextFormatting\nSystem.Windows.Navigation\nSystem.Windows.Resources\nSystem.Windows.Shapes\nSystem.Windows.Threading\nSystem.Windows.Xps\nSystem.Windows.Xps.Packaging\nSystem.Windows.Xps.Serialization\nSystem.Workflow.Activities\nSystem.Workflow.Activities.Configuration\nSystem.Workflow.Activities.Rules\nSystem.Workflow.Activities.Rules.Design\nSystem.Workflow.ComponentModel\nSystem.Workflow.ComponentModel.Compiler\nSystem.Workflow.ComponentModel.Design\nSystem.Workflow.ComponentModel.Serialization\nSystem.Workflow.Runtime\nSystem.Workflow.Runtime.Configuration\nSystem.Workflow.Runtime.DebugEngine\nSystem.Workflow.Runtime.Hosting\nSystem.Workflow.Runtime.Tracking\nSystem.Xml\nSystem.Xml.Linq\nSystem.Xml.Schema\nSystem.Xml.Serialization\nSystem.Xml.Serialization.Advanced\nSystem.Xml.Serialization.Configuration\nSystem.Xml.XPath\nSystem.Xml.Xsl\nSystem.Xml.Xsl.Runtime\nUIAutomationClientsideProviders\n__builtin__\n_ast\n_bisect\n_codecs\n_collections\n_csv\n_ctypes\n_ctypes_test\n_functools\n_heapq\n_io\n_locale\n_md5\n_random\n_sha\n_sha256\n_sha512\n_sqlite3\n_sre\n_ssl\n_struct\n_subprocess\n_warnings\n_weakref\n_winreg\narray\nbinascii\nbz2\ncPickle\ncStringIO\nclr\ncmath\ncopy_reg\ndatetime\nemail\nerrno\nexceptions\nfuture_builtins\ngc\nhashlib\nimp\nitertools\nmarshal\nmath\nmmap\nmsvcrt\nnt\noperator\nos\nos.path\npytest\nre\nselect\nsignal\nsocket\nsys\nthread\ntime\nunicodedata\nwinsound\nwpf\nxxsubtype\nzipimport\nzlib\n&&&&& +/instance/org.eclipse.jdt.ui/cleanup.add_generated_serial_version_id=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +/instance/org.eclipse.wst.validation/suspend=false +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.formatterprofiles.version=12 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +/instance/org.eclipse.compare/org.eclipse.compare.IgnoreWhitespace=true +/instance/org.eclipse.egit.ui/resourcehistory_graph_split=500,500 +@org.eclipse.mylyn.monitor.ui=3.8.3.v20130107-0100 +/instance/org.eclipse.ui.ide/PROBLEMS_FILTERS_MIGRATE=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +/instance/org.eclipse.jdt.ui/cleanup.always_use_parentheses_in_expressions=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.argumentSuffixes= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +/instance/org.eclipse.jdt.ui/sp_cleanup.add_default_serial_version_id=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +/instance/org.eclipse.debug.ui/pref_state_memento.org.eclipse.debug.ui.BreakpointView=\r\n\r\n\r\n\r\n\r\n +@org.eclipse.ui.workbench=3.104.0.v20130204-164612 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.importorder=java;javax;org;com;org.apache.cloudstack;com.cloud; +/instance/org.eclipse.jdt.ui/sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +/instance/org.eclipse.jdt.ui/cleanup.always_use_this_for_non_static_field_access=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.organize_imports=true +/instance/org.eclipse.jdt.ui/cleanup.qualify_static_method_accesses_with_declaring_class=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +@org.eclipse.egit.ui=2.3.1.201302201838-r +/instance/org.eclipse.ui.editors/quickdiff.nowarn.before.switch=always +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.line_length=120 +/instance/org.eclipse.jdt.ui/cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +/instance/org.eclipse.jdt.debug.ui/org.eclipse.debug.ui.VariableView.org.eclipse.jdt.debug.ui.show_null_entries=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.fieldSuffixes= +/instance/org.eclipse.jdt.ui/content_assist_number_of_computers=21 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.localSuffixes= +/instance/org.eclipse.jdt.junit.core/org.eclipse.jdt.junit.enable_assertions=true +@org.eclipse.core.resources=3.8.1.v20121114-124432 +/instance/org.eclipse.jdt.ui/spelling_ignore_urls=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +/instance/org.eclipse.jdt.ui/content_assist_autoactivation_delay=50 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +@org.eclipse.search=3.8.0.v20120523-1540 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +/instance/org.eclipse.ui.intro/org.eclipse.epp.package.java.product_INTRO_THEME=org.eclipse.ui.intro.universal.circles +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JSR305_ANNOTATIONS=C\:/bin/Eclipse/current/plugins/edu.umd.cs.findbugs.plugin.eclipse_2.0.2.20121210/lib/jsr305.jar +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.JRE_LIB=C\:/bin/Java/jre7/lib/rt.jar +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.lineSplit=180 +/instance/org.eclipse.jdt.ui/content_assist_disabled_computers=org.eclipse.recommenders.completion.rcp.templates.category\u0000org.eclipse.jdt.ui.javaAllProposalCategory\u0000org.eclipse.jdt.ui.javaNoTypeProposalCategory\u0000org.eclipse.recommenders.completion.rcp.chain.category\u0000org.eclipse.jdt.ui.javaTypeProposalCategory\u0000org.eclipse.jdt.ui.textProposalCategory\u0000org.eclipse.recommenders.subwords.rcp.category\u0000 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +@org.eclipse.ui.ide=3.8.2.v20121106-165923 +@org.eclipse.core.runtime=3.8.0.v20120912-155025 +/instance/org.eclipse.jdt.ui/editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_trailing_whitespaces_ignore_empty=true +/instance/org.eclipse.jdt.ui/sp_cleanup.always_use_blocks=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +/instance/org.eclipse.jdt.debug/org.eclipse.jdt.debug.PREF_HCR_WITH_COMPILATION_ERRORS=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_html=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +/instance/org.eclipse.m2e.core/eclipse.m2.WorkspacelifecycleMappingsLocation=D\:/src/workspaces/master/.metadata/.plugins/org.eclipse.m2e.core/lifecycle-mapping-metadata.xml +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +/instance/org.eclipse.jdt.ui/cleanup.make_variable_declarations_final=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +/instance/org.eclipse.jdt.ui/cleanup.use_this_for_non_static_field_access=true /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert @@ -432,185 +432,185 @@ /instance/org.eclipse.jdt.debug.ui/org.eclipse.debug.ui.ExpressionView.org.eclipse.jdt.debug.ui.show_null_entries=true /instance/org.eclipse.jdt.ui/sp_cleanup.correct_indentation=false /instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_source_code=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 -/instance/org.eclipse.jdt.ui/cleanup.never_use_parentheses_in_expressions=true -@org.eclipse.debug.core=3.7.100.v20120521-2012 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert -file_export_version=3.0 -@org.eclipse.jdt.debug.ui=3.6.100.v20120530-1425 -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_trailing_whitespaces=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 -/instance/org.eclipse.jdt.debug/org.eclipse.jdt.debug.PREF_REQUEST_TIMEOUT=3000 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert -/instance/org.eclipse.jdt.ui/cleanup.format_source_code=false -/configuration/org.eclipse.ui.ide/RECENT_WORKSPACES=d\:\\src\\workspaces\\vmsync\nd\:\\src\\workspaces\\master\nd\:\\src\\workspaces\\4.x -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unnecessary_casts=true -@org.eclipse.jdt.junit.core=3.7.100.v20120523-1257 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert -/instance/org.eclipse.m2e.discovery/org.eclipse.m2e.discovery.pref.projects= -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.overrideannotation=true -/instance/org.eclipse.jdt.ui/sp_cleanup.sort_members_all=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.argumentPrefixes= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true -/instance/org.eclipse.debug.ui/pref_state_memento.org.eclipse.debug.ui.VariableView=\r\n\r\n\r\n -/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.internal.ui.navigator.layout=2 -/instance/org.eclipse.jdt.ui/sp_cleanup.make_parameters_final=false -/instance/org.eclipse.jdt.ui/cleanup.remove_unnecessary_casts=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -@org.eclipse.m2e.core=1.3.1.20130219-1424 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_empty_lines=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -/instance/org.eclipse.ui/showIntro=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -/instance/org.eclipse.jdt.ui/cleanup.qualify_static_field_accesses_with_declaring_class=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.staticondemandthreshold=99 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.fieldPrefixes= -/instance/org.eclipse.mylyn.monitor.ui/org.eclipse.mylyn.monitor.activity.tracking.enabled.checked=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.localPrefixes= -/instance/org.eclipse.team.core/ignore_files=target\ntrue\n -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.cleanupprofiles.version=2 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -/instance/org.eclipse.ui.browser/internalWebBrowserHistory=file\:///D\:/src/acs/vmsync/tools/apidoc/target/xmldoc/html/root_admin/updateHypervisorCapabilities.html|*|file\:/D\:/src/acs/vmsync/tools/apidoc/target/xmldoc/html/root_admin/updateHypervisorCapabilities.html|*| -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 -/instance/org.eclipse.jdt.ui/spelling_user_dictionary_encoding= -/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_annotations=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line -/instance/org.eclipse.jdt.ui/cleanup.remove_trailing_whitespaces=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true -/instance/org.eclipse.jdt.ui/cleanup.never_use_blocks=false -/instance/org.eclipse.wst.validation/USER_MANUAL_PREFERENCE=enabledManualValidatorList -@org.eclipse.mylyn.context.core=3.8.3.v20130107-0100 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert -@org.eclipse.jdt.launching=3.6.101.v20130111-183046 -@org.eclipse.jdt.debug=3.7.101.v20120913-153601 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.compliance=1.6 -@org.eclipse.m2e.editor.xml=1.3.1.20130219-1424 -/instance/org.eclipse.jdt.ui/cleanup.remove_unused_private_fields=true -/instance/org.eclipse.jdt.ui/sp_cleanup.use_blocks_only_for_return_and_throw=false -/instance/org.eclipse.jdt.ui/cleanup.remove_unused_local_variables=false -/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.user_view_bindings=\r\n\r\n\r\n\r\n\r\n\r\n -/instance/org.eclipse.jdt.ui/cleanup.remove_unused_private_members=false -@org.python.pydev.debug=2.7.5.2013052819 -/instance/org.eclipse.jdt.ui/sp_cleanup.add_generated_serial_version_id=false -/configuration/org.eclipse.ui.ide/MAX_RECENT_WORKSPACES=5 -/instance/org.eclipse.jdt.ui/spelling_ignore_ampersand_in_properties=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.use_on_off_tags=true -@org.eclipse.ui.intro=3.4.200.v20120521-2344 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.source=1.6 -/instance/org.eclipse.wst.xml.core/indentationSize=2 -/instance/org.eclipse.jdt.ui/cleanup.use_blocks_only_for_return_and_throw=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_fields=true -/instance/org.eclipse.jdt.ui/sp_cleanup.make_local_variable_final=false -/instance/org.eclipse.m2e.core/eclipse.m2.defaultPomEditorPage=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert -/instance/org.eclipse.jdt.ui/content_assist_autoactivation_triggers_java=.( -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert -/instance/org.eclipse.jdt.ui/cleanup.use_blocks=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.FINDBUGS_ANNOTATIONS=C\:/bin/Eclipse/current/plugins/edu.umd.cs.findbugs.plugin.eclipse_2.0.2.20121210/lib/annotations.jar -/instance/org.eclipse.egit.core/GitRepositoriesView.GitDirectories=D\:\\src\\acs\\master\\.git;D\:\\src\\acs\\vmsync\\.git; -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true -/instance/org.eclipse.ui.workbench/editors=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.compact_else_if=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 -/instance/org.eclipse.jdt.ui/content_assist_proposals_background=255,255,255 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_header=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.tabulation.char=space -/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.custom_code_templates= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_block_comments=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert -/instance/org.eclipse.debug.core/prefWatchExpressions=\r\n\r\n\r\n\r\n\r\n -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert -/instance/org.eclipse.wst.validation/DELEGATES_PREFERENCE=delegateValidatorList -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert -@org.eclipse.team.ui=3.6.201.v20130125-135424 -/instance/org.eclipse.ui.editors/overviewRuler_migration=migrated_3.1 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert -@org.eclipse.wst.xml.core=1.1.702.v201301101836 -/instance/org.eclipse.jdt.ui/cleanup.remove_unused_private_methods=true -@org.eclipse.wst.xml.ui=1.1.302.v201301172222 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line -/instance/org.eclipse.ui.ide/tipsAndTricks=true -/instance/org.eclipse.search/org.eclipse.search.defaultPerspective=org.eclipse.search.defaultPerspective.none -/instance/org.eclipse.egit.ui/default_repository_dir=d\:\\src -/instance/org.eclipse.jdt.ui/sp_cleanup.on_save_use_additional_actions=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert -/instance/org.eclipse.jdt.ui/cleanup.sort_members=false -/instance/org.eclipse.jdt.ui/sp_cleanup.use_parentheses_in_expressions=false -@org.eclipse.debug.ui=3.8.2.v20130130-171415 -@org.eclipse.compare=3.5.301.v20130125-135424 -/instance/org.eclipse.jdt.ui/cleanup.use_this_for_non_static_method_access=true -/instance/org.eclipse.jdt.ui/org.eclipse.jface.textfont=1|Courier New|10.0|0|WINDOWS|1|0|0|0|0|0|0|0|0|1|0|0|0|0|Courier New; -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert -/instance/org.eclipse.ui.editors/printMargin=true -/instance/org.eclipse.jdt.ui/cleanup.remove_trailing_whitespaces_all=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert -/instance/org.eclipse.wst.validation/stateTS=0 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert -@org.eclipse.jdt.ui=3.8.2.v20130107-165834 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.M2_REPO=d\:/src/maven -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unnecessary_nls_tags=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -/instance/org.eclipse.wst.xml.ui/org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart.lastActivePage=1 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert -/instance/org.eclipse.mylyn.wikitext.ui/org.eclipse.mylyn.wikitext.ui.customtemplates= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -@org.eclipse.ui.browser=3.4.2.v20130123-162658 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 -/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_methods=false -/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.switch_perspective_on_suspend=always -/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_types=true -/instance/org.eclipse.jdt.ui/content_assist_lru_history= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert -/instance/org.eclipse.ui.editors/spacesForTabs=true -@org.eclipse.mylyn.wikitext.ui=1.7.3.v20130107-0100 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -/instance/org.python.pydev/INTERPRETER_CONFIGURATION_0=DONT_ASK -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line -@org.eclipse.epp.mpc.ui=1.1.1.I20110907-0947 -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 -/instance/org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_DEFAULT_ENVIRONMENTS_XML= -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -/instance/org.eclipse.jdt.ui/cleanup.correct_indentation=true -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert -/instance/org.eclipse.ui.ide/quickStart=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert -/instance/org.eclipse.ui.workbench/PLUGINS_NOT_ACTIVATED_ON_STARTUP=org.eclipse.m2e.discovery; -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert -/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +/instance/org.eclipse.jdt.ui/cleanup.never_use_parentheses_in_expressions=true +@org.eclipse.debug.core=3.7.100.v20120521-2012 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +file_export_version=3.0 +@org.eclipse.jdt.debug.ui=3.6.100.v20120530-1425 +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_trailing_whitespaces=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +/instance/org.eclipse.jdt.debug/org.eclipse.jdt.debug.PREF_REQUEST_TIMEOUT=3000 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +/instance/org.eclipse.jdt.ui/cleanup.format_source_code=false +/configuration/org.eclipse.ui.ide/RECENT_WORKSPACES=d\:\\src\\workspaces\\vmsync\nd\:\\src\\workspaces\\master\nd\:\\src\\workspaces\\4.x +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unnecessary_casts=true +@org.eclipse.jdt.junit.core=3.7.100.v20120523-1257 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +/instance/org.eclipse.m2e.discovery/org.eclipse.m2e.discovery.pref.projects= +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.overrideannotation=true +/instance/org.eclipse.jdt.ui/sp_cleanup.sort_members_all=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.argumentPrefixes= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +/instance/org.eclipse.debug.ui/pref_state_memento.org.eclipse.debug.ui.VariableView=\r\n\r\n\r\n +/instance/org.eclipse.jdt.ui/sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.internal.ui.navigator.layout=2 +/instance/org.eclipse.jdt.ui/sp_cleanup.make_parameters_final=false +/instance/org.eclipse.jdt.ui/cleanup.remove_unnecessary_casts=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +@org.eclipse.m2e.core=1.3.1.20130219-1424 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_empty_lines=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +/instance/org.eclipse.ui/showIntro=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +/instance/org.eclipse.jdt.ui/cleanup.qualify_static_field_accesses_with_declaring_class=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.staticondemandthreshold=99 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.fieldPrefixes= +/instance/org.eclipse.mylyn.monitor.ui/org.eclipse.mylyn.monitor.activity.tracking.enabled.checked=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.codeComplete.localPrefixes= +/instance/org.eclipse.team.core/ignore_files=target\ntrue\n +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.cleanupprofiles.version=2 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +/instance/org.eclipse.ui.browser/internalWebBrowserHistory=file\:///D\:/src/acs/vmsync/tools/apidoc/target/xmldoc/html/root_admin/updateHypervisorCapabilities.html|*|file\:/D\:/src/acs/vmsync/tools/apidoc/target/xmldoc/html/root_admin/updateHypervisorCapabilities.html|*| +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +/instance/org.eclipse.jdt.ui/spelling_user_dictionary_encoding= +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_annotations=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +/instance/org.eclipse.jdt.ui/cleanup.remove_trailing_whitespaces=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true +/instance/org.eclipse.jdt.ui/cleanup.never_use_blocks=false +/instance/org.eclipse.wst.validation/USER_MANUAL_PREFERENCE=enabledManualValidatorList +@org.eclipse.mylyn.context.core=3.8.3.v20130107-0100 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +@org.eclipse.jdt.launching=3.6.101.v20130111-183046 +@org.eclipse.jdt.debug=3.7.101.v20120913-153601 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.compliance=1.6 +@org.eclipse.m2e.editor.xml=1.3.1.20130219-1424 +/instance/org.eclipse.jdt.ui/cleanup.remove_unused_private_fields=true +/instance/org.eclipse.jdt.ui/sp_cleanup.use_blocks_only_for_return_and_throw=false +/instance/org.eclipse.jdt.ui/cleanup.remove_unused_local_variables=false +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.user_view_bindings=\r\n\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.ui/cleanup.remove_unused_private_members=false +@org.python.pydev.debug=2.7.5.2013052819 +/instance/org.eclipse.jdt.ui/sp_cleanup.add_generated_serial_version_id=false +/configuration/org.eclipse.ui.ide/MAX_RECENT_WORKSPACES=5 +/instance/org.eclipse.jdt.ui/spelling_ignore_ampersand_in_properties=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.use_on_off_tags=true +@org.eclipse.ui.intro=3.4.200.v20120521-2344 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.source=1.6 +/instance/org.eclipse.wst.xml.core/indentationSize=2 +/instance/org.eclipse.jdt.ui/cleanup.use_blocks_only_for_return_and_throw=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_fields=true +/instance/org.eclipse.jdt.ui/sp_cleanup.make_local_variable_final=false +/instance/org.eclipse.m2e.core/eclipse.m2.defaultPomEditorPage=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +/instance/org.eclipse.jdt.ui/content_assist_autoactivation_triggers_java=.( +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +/instance/org.eclipse.jdt.ui/cleanup.use_blocks=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.FINDBUGS_ANNOTATIONS=C\:/bin/Eclipse/current/plugins/edu.umd.cs.findbugs.plugin.eclipse_2.0.2.20121210/lib/annotations.jar +/instance/org.eclipse.egit.core/GitRepositoriesView.GitDirectories=D\:\\src\\acs\\master\\.git;D\:\\src\\acs\\vmsync\\.git; +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +/instance/org.eclipse.ui.workbench/editors=\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.compact_else_if=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +/instance/org.eclipse.jdt.ui/content_assist_proposals_background=255,255,255 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_header=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.tabulation.char=space +/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.custom_code_templates= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.comment.format_block_comments=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +/instance/org.eclipse.debug.core/prefWatchExpressions=\r\n\r\n\r\n\r\n\r\n +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +/instance/org.eclipse.wst.validation/DELEGATES_PREFERENCE=delegateValidatorList +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +@org.eclipse.team.ui=3.6.201.v20130125-135424 +/instance/org.eclipse.ui.editors/overviewRuler_migration=migrated_3.1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +@org.eclipse.wst.xml.core=1.1.702.v201301101836 +/instance/org.eclipse.jdt.ui/cleanup.remove_unused_private_methods=true +@org.eclipse.wst.xml.ui=1.1.302.v201301172222 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +/instance/org.eclipse.ui.ide/tipsAndTricks=true +/instance/org.eclipse.search/org.eclipse.search.defaultPerspective=org.eclipse.search.defaultPerspective.none +/instance/org.eclipse.egit.ui/default_repository_dir=d\:\\src +/instance/org.eclipse.jdt.ui/sp_cleanup.on_save_use_additional_actions=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +/instance/org.eclipse.jdt.ui/cleanup.sort_members=false +/instance/org.eclipse.jdt.ui/sp_cleanup.use_parentheses_in_expressions=false +@org.eclipse.debug.ui=3.8.2.v20130130-171415 +@org.eclipse.compare=3.5.301.v20130125-135424 +/instance/org.eclipse.jdt.ui/cleanup.use_this_for_non_static_method_access=true +/instance/org.eclipse.jdt.ui/org.eclipse.jface.textfont=1|Courier New|10.0|0|WINDOWS|1|0|0|0|0|0|0|0|0|1|0|0|0|0|Courier New; +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +/instance/org.eclipse.ui.editors/printMargin=true +/instance/org.eclipse.jdt.ui/cleanup.remove_trailing_whitespaces_all=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +/instance/org.eclipse.wst.validation/stateTS=0 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +@org.eclipse.jdt.ui=3.8.2.v20130107-165834 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.classpathVariable.M2_REPO=d\:/src/maven +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unnecessary_nls_tags=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +/instance/org.eclipse.wst.xml.ui/org.eclipse.wst.xml.ui.internal.tabletree.XMLMultiPageEditorPart.lastActivePage=1 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +/instance/org.eclipse.mylyn.wikitext.ui/org.eclipse.mylyn.wikitext.ui.customtemplates= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +@org.eclipse.ui.browser=3.4.2.v20130123-162658 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +/instance/org.eclipse.jdt.ui/sp_cleanup.add_missing_methods=false +/instance/org.eclipse.debug.ui/org.eclipse.debug.ui.switch_perspective_on_suspend=always +/instance/org.eclipse.jdt.ui/sp_cleanup.remove_unused_private_types=true +/instance/org.eclipse.jdt.ui/content_assist_lru_history= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +/instance/org.eclipse.ui.editors/spacesForTabs=true +@org.eclipse.mylyn.wikitext.ui=1.7.3.v20130107-0100 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +/instance/org.python.pydev/INTERPRETER_CONFIGURATION_0=DONT_ASK +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +@org.eclipse.epp.mpc.ui=1.1.1.I20110907-0947 +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +/instance/org.eclipse.jdt.launching/org.eclipse.jdt.launching.PREF_DEFAULT_ENVIRONMENTS_XML= +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +/instance/org.eclipse.jdt.ui/cleanup.correct_indentation=true +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +/instance/org.eclipse.ui.ide/quickStart=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +/instance/org.eclipse.ui.workbench/PLUGINS_NOT_ACTIVATED_ON_STARTUP=org.eclipse.m2e.discovery; +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +/instance/org.eclipse.jdt.core/org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert diff --git a/tools/eclipse/set-eclipse-profile.sh b/tools/eclipse/set-eclipse-profile.sh index 70dc8d41b87..48faba8ebff 100644 --- a/tools/eclipse/set-eclipse-profile.sh +++ b/tools/eclipse/set-eclipse-profile.sh @@ -1,26 +1,26 @@ -#!/bin/bash -# 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 +#!/bin/bash +# 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. -for file in `find . -name org.eclipse.m2e.core.prefs | xargs`; do - if grep -q activeProfiles=eclipse $file; then - echo Skipping $file; - else - echo Replacing $file; +for file in `find . -name org.eclipse.m2e.core.prefs | xargs`; do + if grep -q activeProfiles=eclipse $file; then + echo Skipping $file; + else + echo Replacing $file; sed -i -e s/activeProfiles=/activeProfiles=eclipse/g $file; - fi; + fi; done diff --git a/tools/marvin/CHANGES.txt b/tools/marvin/CHANGES.txt index 262c8845f72..9dd23677135 100644 --- a/tools/marvin/CHANGES.txt +++ b/tools/marvin/CHANGES.txt @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/marvin/DISCLAIMER.txt b/tools/marvin/DISCLAIMER.txt index fa1e9261a36..d3b58164b7c 100644 --- a/tools/marvin/DISCLAIMER.txt +++ b/tools/marvin/DISCLAIMER.txt @@ -1,7 +1,7 @@ -Apache CloudStack is an effort undergoing incubation at The Apache Software Foundation (ASF), -sponsored by the Apache Incubator. Incubation is required of all newly accepted -projects until a further review indicates that the infrastructure, communications, and -decision making process have stabilized in a manner consistent with other successful ASF -projects. While incubation status is not necessarily a reflection of the completeness or -stability of the code, it does indicate that the project has yet to be fully endorsed by +Apache CloudStack is an effort undergoing incubation at The Apache Software Foundation (ASF), +sponsored by the Apache Incubator. Incubation is required of all newly accepted +projects until a further review indicates that the infrastructure, communications, and +decision making process have stabilized in a manner consistent with other successful ASF +projects. While incubation status is not necessarily a reflection of the completeness or +stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF. diff --git a/tools/marvin/MANIFEST.in b/tools/marvin/MANIFEST.in index 3d373818c20..5f17a53a989 100644 --- a/tools/marvin/MANIFEST.in +++ b/tools/marvin/MANIFEST.in @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/marvin/marvin/cloudstackException.py b/tools/marvin/marvin/cloudstackException.py index 5a2f72d8c59..477a61829fb 100644 --- a/tools/marvin/marvin/cloudstackException.py +++ b/tools/marvin/marvin/cloudstackException.py @@ -88,7 +88,7 @@ class CloudstackAclException(): @staticmethod def verifyErrorCodeinException(e,errorCode): errorString = " errorCode: " + errorCode - if errorString in str(e): + if errorString in str(e): return True else: return False diff --git a/tools/marvin/marvin/cloudstackTestCase.py b/tools/marvin/marvin/cloudstackTestCase.py index d178b6ec139..297031611e9 100644 --- a/tools/marvin/marvin/cloudstackTestCase.py +++ b/tools/marvin/marvin/cloudstackTestCase.py @@ -23,7 +23,8 @@ from marvin.lib.base import ( Network, NetworkACL, NetworkOffering, - VirtualMachine + VirtualMachine, + Volume ) @@ -98,12 +99,32 @@ class cloudstackTestCase(unittest.case.TestCase): """ Delete resources (created during tests) """ + volume_list = [] for obj in resources: if isinstance(obj, VirtualMachine): obj.delete(api_client, expunge=True) + elif isinstance(obj, Volume): + obj.destroy(api_client, expunge=True) + volume_list.append(obj) else: obj.delete(api_client) + cls.wait_for_volumes_cleanup(api_client, volume_list) + + def wait_for_volumes_cleanup(cls, api_client, volume_list=[]): + """Wait for volumes to be deleted""" + for volume in volume_list: + max_retries = 24 # Max wait time will be 5 * 24 = 120 seconds + while max_retries > 0: + volumes = Volume.list( + api_client, + id=volume.id + ) + if volumes is None or len(volumes) == 0: + break + max_retries = max_retries - 1 + time.sleep(5) + def check_wget_from_vm(self, vm, public_ip, network=None, testnegative=False, isVmAccessible=True): import urllib.request, urllib.error self.debug(f"Checking if we can wget from a VM={vm.name} http server on public_ip={public_ip.ipaddress.ipaddress}, expecting failure == {testnegative} and vm is acceccible == {isVmAccessible}") @@ -162,7 +183,7 @@ class cloudstackTestCase(unittest.case.TestCase): sshClient.execute("service httpd start") time.sleep(5) ssh_response = str(sshClient.execute("service httpd status")).lower() - if not "running" in ssh_response: + if "running" not in ssh_response: raise Exception("Failed to start httpd service") self.debug("Setup webserver using apache") diff --git a/tools/marvin/marvin/config/test_data.py b/tools/marvin/marvin/config/test_data.py index c4ac6008b1f..e96dba1c4d5 100644 --- a/tools/marvin/marvin/config/test_data.py +++ b/tools/marvin/marvin/config/test_data.py @@ -177,9 +177,9 @@ test_data = { "service_offering_h2": { "name": "Tagged h2 Small Instance", "displaytext": "Tagged h2 Small Instance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, + "cpunumber": 2, + "cpuspeed": 200, + "memory": 512, "hosttags": "h2" }, "disk_offering": { @@ -1034,7 +1034,18 @@ test_data = { "requireshvm": "True", "ispublic": "True", "deployasis": "True" - } + }, + "simulator": { + "name": "tiny-simulator", + "displaytext": "tiny simulator", + "format": "vhd", + "hypervisor": "simulator", + "ostype": "Other Linux (64-bit)", + "url": "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina.vhd.bz2", + "requireshvm": "True", + "ispublic": "True", + "isextractable": "True" + }, }, "test_ovf_templates": [ { @@ -2260,11 +2271,23 @@ test_data = { "url": "http://download.cloudstack.org/cks/setup-1.26.0.iso", "mincpunumber": 2, "minmemory": 2048 + }, + "1.27.8": { + "semanticversion": "1.27.8", + "url": "http://download.cloudstack.org/cks/setup-1.27.8.iso", + "mincpunumber": 2, + "minmemory": 2048 + }, + "1.28.4": { + "semanticversion": "1.28.4", + "url": "http://download.cloudstack.org/cks/setup-1.28.4.iso", + "mincpunumber": 2, + "minmemory": 2048 } }, - "cks_kubernetes_version": "1.26.0", - "cks_kubernetes_version_upgrade_from": "1.25.0", - "cks_kubernetes_version_upgrade_to": "1.26.0", + "cks_kubernetes_version": "1.28.4", + "cks_kubernetes_version_upgrade_from": "1.27.8", + "cks_kubernetes_version_upgrade_to": "1.28.4", "cks_service_offering": { "name": "CKS-Instance", "displaytext": "CKS Instance", diff --git a/tools/marvin/marvin/dbConnection.py b/tools/marvin/marvin/dbConnection.py index 04140bab3c2..eb48e5852ed 100644 --- a/tools/marvin/marvin/dbConnection.py +++ b/tools/marvin/marvin/dbConnection.py @@ -47,7 +47,7 @@ class DbConnection(object): with contextlib.closing(conn.cursor(buffered=True)) as cursor: cursor.execute(sql, params) try: - if sql.lower().startswith('select') and cursor.rowcount > 0: + if sql.lower().startswith('select') and cursor.rowcount > 0: # we have more than just the row count/success resultRow = cursor.fetchall() except errors.InterfaceError: diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index 4e23a6a5d45..db88f762788 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -172,7 +172,7 @@ class DeployDataCenters(object): def addBaremetalRct(self, config): networktype= config.zones[0].networktype baremetalrcturl= config.zones[0].baremetalrcturl - if networktype is None or baremetalrcturl is None: + if networktype is None or baremetalrcturl is None: return if networktype.lower()=="advanced": diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py index 5906d2f1e3d..9c69d33a4ca 100755 --- a/tools/marvin/marvin/lib/base.py +++ b/tools/marvin/marvin/lib/base.py @@ -527,7 +527,7 @@ class VirtualMachine: customcpuspeed=None, custommemory=None, rootdisksize=None, rootdiskcontroller=None, vpcid=None, macaddress=None, datadisktemplate_diskoffering_list={}, properties=None, nicnetworklist=None, bootmode=None, boottype=None, dynamicscalingenabled=None, - userdataid=None, userdatadetails=None, extraconfig=None): + userdataid=None, userdatadetails=None, extraconfig=None, size=None): """Create the instance""" cmd = deployVirtualMachine.deployVirtualMachineCmd() @@ -649,7 +649,9 @@ class VirtualMachine: if rootdiskcontroller: cmd.details[0]["rootDiskController"] = rootdiskcontroller - if "size" in services: + if size: + cmd.size = size + elif "size" in services: cmd.size = services["size"] if group: @@ -774,12 +776,26 @@ class VirtualMachine: if response[0] == FAIL: raise Exception(response[1]) - def restore(self, apiclient, templateid=None): + def restore(self, apiclient, templateid=None, diskofferingid=None, rootdisksize=None, expunge=None, details=None): """Restore the instance""" cmd = restoreVirtualMachine.restoreVirtualMachineCmd() cmd.virtualmachineid = self.id if templateid: cmd.templateid = templateid + if expunge: + cmd.expunge = expunge + if diskofferingid: + cmd.diskofferingid = diskofferingid + if rootdisksize: + cmd.rootdisksize = rootdisksize + if expunge is not None: + cmd.expunge = expunge + if details: + for key, value in list(details.items()): + cmd.details.append({ + 'key': key, + 'value': value + }) return apiclient.restoreVirtualMachine(cmd) def get_ssh_client( @@ -1455,7 +1471,7 @@ class Template: @classmethod def register(cls, apiclient, services, zoneid=None, account=None, domainid=None, hypervisor=None, - projectid=None, details=None, randomize_name=True): + projectid=None, details=None, randomize_name=True, templatetag=None): """Create template from URL""" # Create template from Virtual machine and Volume ID @@ -1520,8 +1536,13 @@ class Template: if details: cmd.details = details + if templatetag: + cmd.templatetag = templatetag + if "directdownload" in services: cmd.directdownload = services["directdownload"] + if "checksum" in services: + cmd.checksum = services["checksum"] # Register Template template = apiclient.registerTemplate(cmd) @@ -1852,7 +1873,7 @@ class PublicIPAddress: if zoneid: cmd.zoneid = zoneid - elif "zoneid" in services: + elif services and "zoneid" in services: cmd.zoneid = services["zoneid"] if domainid: @@ -1877,12 +1898,19 @@ class PublicIPAddress: return PublicIPAddress(apiclient.associateIpAddress(cmd).__dict__) def delete(self, apiclient): - """Dissociate Public IP address""" + """Dissociate Public IP address using the given ID""" cmd = disassociateIpAddress.disassociateIpAddressCmd() cmd.id = self.ipaddress.id apiclient.disassociateIpAddress(cmd) return + def delete_by_ip(self, apiclient): + """Dissociate Public IP address using the given IP address""" + cmd = disassociateIpAddress.disassociateIpAddressCmd() + cmd.ipaddress = self.ipaddress.ipaddress + apiclient.disassociateIpAddress(cmd) + return + @classmethod def list(cls, apiclient, **kwargs): """List all Public IPs matching criteria""" @@ -3129,6 +3157,35 @@ class Cluster: [setattr(cmd, k, v) for k, v in list(kwargs.items())] return (apiclient.updateCluster(cmd)) + def listDrsPlans(cls, apiclient, **kwargs): + """List drs plans for cluster""" + + cmd = listClusterDrsPlan.listClusterDrsPlanCmd() + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + return apiclient.listClusterDrsPlan(cmd) + + def generateDrsPlan(cls, apiclient, migrations=None): + """Generate a drs plan for cluster""" + + cmd = generateClusterDrsPlan.generateClusterDrsPlanCmd() + cmd.id = cls.id + cmd.migrations = migrations + return apiclient.generateClusterDrsPlan(cmd) + + def executeDrsPlan(cls, apiclient, migrateto=None): + """Execute drs plan on cluster""" + + cmd = executeClusterDrsPlan.executeClusterDrsPlanCmd() + cmd.id = cls.id + if migrateto: + cmd.migrateto = [] + for vm, host in list(migrateto.items()): + cmd.migrateto.append({ + 'vm': vm, + 'host': host + }) + return apiclient.executeClusterDrsPlan(cmd) + class Host: """Manage Host life cycle""" @@ -3473,6 +3530,13 @@ class StoragePool: timeout -= 60 return returnValue + @classmethod + def listObjects(cls, apiclient, path="/"): + cmd = listStoragePoolObjects.listStoragePoolObjectsCmd() + cmd.id = cls.id + cmd.path = path + return apiclient.listStoragePoolObjects(cmd) + class Network: """Manage Network pools""" @@ -4183,6 +4247,20 @@ class ImageStore: cmd.listall = True return (apiclient.listImageStores(cmd)) + def listObjects(self, apiclient, path="/"): + cmd = listImageStoreObjects.listImageStoreObjectsCmd() + cmd.id = self.id + cmd.path = path + return apiclient.listImageStoreObjects(cmd) + + def migrateResources(self, apiclient, destStoreId, templateIdList=[], snapshotIdList=[]): + cmd = migrateResourceToAnotherSecondaryStorage.migrateResourceToAnotherSecondaryStorageCmd() + cmd.srcpool = self.id + cmd.destpool = destStoreId + cmd.templates = templateIdList + cmd.snapshots = snapshotIdList + return apiclient.migrateResourceToAnotherSecondaryStorage(cmd) + class PhysicalNetwork: """Manage physical network storage""" @@ -4816,7 +4894,7 @@ class NiciraNvp: class NetworkServiceProvider: - """Manage network serivce providers for CloudStack""" + """Manage network service providers for CloudStack""" def __init__(self, items): self.__dict__.update(items) @@ -5053,7 +5131,7 @@ class VPC: @classmethod def create(cls, apiclient, services, vpcofferingid, zoneid, networkDomain=None, account=None, - domainid=None, **kwargs): + domainid=None, start=True, **kwargs): """Creates the virtual private connection (VPC)""" cmd = createVPC.createVPCCmd() @@ -5061,6 +5139,7 @@ class VPC: cmd.displaytext = "-".join([services["displaytext"], random_gen()]) cmd.vpcofferingid = vpcofferingid cmd.zoneid = zoneid + cmd.start = start if "cidr" in services: cmd.cidr = services["cidr"] if account: @@ -5921,8 +6000,10 @@ class ResourceDetails: cmd.resourcetype = resourcetype return (apiclient.removeResourceDetail(cmd)) + # Backup and Recovery + class BackupOffering: def __init__(self, items): @@ -5987,6 +6068,7 @@ class BackupOffering: cmd.forced = forced return (apiclient.removeVirtualMachineFromBackupOffering(cmd)) + class Backup: def __init__(self, items): @@ -5998,14 +6080,16 @@ class Backup: cmd = createBackup.createBackupCmd() cmd.virtualmachineid = vmid - return (apiclient.createBackup(cmd)) + return Backup(apiclient.createBackup(cmd).__dict__) @classmethod - def delete(self, apiclient, id): + def delete(self, apiclient, id, forced=None): """Delete VM backup""" cmd = deleteBackup.deleteBackupCmd() cmd.id = id + if forced: + cmd.forced = forced return (apiclient.deleteBackup(cmd)) @classmethod @@ -6017,13 +6101,66 @@ class Backup: cmd.listall = True return (apiclient.listBackups(cmd)) - def restoreVM(self, apiclient): + @classmethod + def restoreVM(self, apiclient, backupid): """Restore VM from backup""" cmd = restoreBackup.restoreBackupCmd() - cmd.id = self.id + cmd.id = backupid return (apiclient.restoreBackup(cmd)) + @classmethod + def restoreVolumeFromBackupAndAttachToVM(self, apiclient, backupid, volumeid, virtualmachineid): + """Restore VM from backup""" + + cmd = restoreVolumeFromBackupAndAttachToVM.restoreVolumeFromBackupAndAttachToVMCmd() + cmd.backupid = backupid + cmd.volumeid = volumeid + cmd.virtualmachineid = virtualmachineid + return (apiclient.restoreVolumeFromBackupAndAttachToVM(cmd)) + + +class BackupSchedule: + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(self, apiclient, vmid, **kwargs): + """Create VM backup schedule""" + + cmd = createBackupSchedule.createBackupScheduleCmd() + cmd.virtualmachineid = vmid + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + return BackupSchedule(apiclient.createBackupSchedule(cmd).__dict__) + + @classmethod + def delete(self, apiclient, vmid): + """Delete VM backup schedule""" + + cmd = deleteBackupSchedule.deleteBackupScheduleCmd() + cmd.virtualmachineid = vmid + return (apiclient.deleteBackupSchedule(cmd)) + + @classmethod + def list(self, apiclient, vmid): + """List VM backup schedule""" + + cmd = listBackupSchedule.listBackupScheduleCmd() + cmd.virtualmachineid = vmid + cmd.listall = True + return (apiclient.listBackupSchedule(cmd)) + + @classmethod + def update(self, apiclient, vmid, **kwargs): + """Update VM backup schedule""" + + cmd = updateBackupSchedule.updateBackupScheduleCmd() + cmd.virtualmachineid = vmid + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + return (apiclient.updateBackupSchedule(cmd)) + + class ProjectRole: def __init__(self, items): @@ -6700,3 +6837,456 @@ class VMSchedule: cmd.id = self.id cmd.virtualmachineid = self.virtualmachineid return (apiclient.deleteVMSchedule(cmd)) + +class VnfTemplate: + """Manage VNF template life cycle""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def register(cls, apiclient, services, zoneid=None, + account=None, domainid=None, hypervisor=None, + projectid=None, details=None, randomize_name=True, + vnfnics=None, vnfdetails=None): + """Create VNF template from URL""" + + # Create template from Virtual machine and Volume ID + cmd = registerVnfTemplate.registerVnfTemplateCmd() + cmd.displaytext = services["displaytext"] + if randomize_name: + cmd.name = "-".join([services["name"], random_gen()]) + else: + cmd.name = services["name"] + cmd.format = services["format"] + if hypervisor: + cmd.hypervisor = hypervisor + elif "hypervisor" in services: + cmd.hypervisor = services["hypervisor"] + + if "ostypeid" in services: + cmd.ostypeid = services["ostypeid"] + elif "ostype" in services: + # Find OSTypeId from Os type + sub_cmd = listOsTypes.listOsTypesCmd() + sub_cmd.description = services["ostype"] + ostypes = apiclient.listOsTypes(sub_cmd) + + if not isinstance(ostypes, list): + raise Exception( + "Unable to find Ostype id with desc: %s" % + services["ostype"]) + cmd.ostypeid = ostypes[0].id + else: + raise Exception( + "Unable to find Ostype is required for registering template") + + cmd.url = services["url"] + + if zoneid: + cmd.zoneid = zoneid + else: + cmd.zoneid = services["zoneid"] + + cmd.isfeatured = services[ + "isfeatured"] if "isfeatured" in services else False + cmd.ispublic = services[ + "ispublic"] if "ispublic" in services else False + cmd.isextractable = services[ + "isextractable"] if "isextractable" in services else False + cmd.isdynamicallyscalable = services["isdynamicallyscalable"] if "isdynamicallyscalable" in services else False + cmd.passwordenabled = services[ + "passwordenabled"] if "passwordenabled" in services else False + cmd.deployasis = services["deployasis"] if "deployasis" in services else False + + if account: + cmd.account = account + + if domainid: + cmd.domainid = domainid + + if projectid: + cmd.projectid = projectid + elif "projectid" in services: + cmd.projectid = services["projectid"] + + if details: + cmd.details = details + + if "directdownload" in services: + cmd.directdownload = services["directdownload"] + + if vnfnics: + cmd.vnfnics = vnfnics + + if vnfdetails: + cmd.vnfdetails = vnfdetails + + # Register Template + template = apiclient.registerVnfTemplate(cmd) + + if isinstance(template, list): + return VnfTemplate(template[0].__dict__) + + def delete(self, apiclient, zoneid=None): + """Delete VNF Template""" + + cmd = deleteVnfTemplate.deleteVnfTemplateCmd() + cmd.id = self.id + if zoneid: + cmd.zoneid = zoneid + apiclient.deleteVnfTemplate(cmd) + + def update(self, apiclient, **kwargs): + """Updates the template details""" + + cmd = updateVnfTemplate.updateVnfTemplateCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + return (apiclient.updateVnfTemplate(cmd)) + + @classmethod + def list(cls, apiclient, **kwargs): + """List all templates matching criteria""" + + cmd = listVnfTemplates.listVnfTemplatesCmd() + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + if 'account' in list(kwargs.keys()) and 'domainid' in list(kwargs.keys()): + cmd.listall = True + return (apiclient.listVnfTemplates(cmd)) + +class VnfAppliance: + """Manage VNF Appliance life cycle""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services, templateid=None, accountid=None, + domainid=None, zoneid=None, networkids=None, + serviceofferingid=None, securitygroupids=None, + projectid=None, startvm=None, diskofferingid=None, + affinitygroupnames=None, affinitygroupids=None, group=None, + hostid=None, clusterid=None, keypair=None, ipaddress=None, mode='default', + method='GET', hypervisor=None, customcpunumber=None, + customcpuspeed=None, custommemory=None, rootdisksize=None, + rootdiskcontroller=None, vpcid=None, macaddress=None, datadisktemplate_diskoffering_list={}, + properties=None, nicnetworklist=None, bootmode=None, boottype=None, dynamicscalingenabled=None, + userdataid=None, userdatadetails=None, extraconfig=None, + vnfconfiguremanagement=None, vnfcidrlist=None): + """Create the VNF appliance""" + + cmd = deployVnfAppliance.deployVnfApplianceCmd() + + if serviceofferingid: + cmd.serviceofferingid = serviceofferingid + elif "serviceoffering" in services: + cmd.serviceofferingid = services["serviceoffering"] + + if zoneid: + cmd.zoneid = zoneid + elif "zoneid" in services: + cmd.zoneid = services["zoneid"] + + if hypervisor: + cmd.hypervisor = hypervisor + + if "displayname" in services: + cmd.displayname = services["displayname"] + + if "name" in services: + cmd.name = services["name"] + + if accountid: + cmd.account = accountid + elif "account" in services: + cmd.account = services["account"] + + if domainid: + cmd.domainid = domainid + elif "domainid" in services: + cmd.domainid = services["domainid"] + + if networkids: + cmd.networkids = networkids + allow_egress = False + elif "networkids" in services: + cmd.networkids = services["networkids"] + allow_egress = False + else: + # When no networkids are passed, network + # is created using the "defaultOfferingWithSourceNAT" + # which has an egress policy of DENY. But guests in tests + # need access to test network connectivity + allow_egress = True + + if templateid: + cmd.templateid = templateid + elif "template" in services: + cmd.templateid = services["template"] + + if diskofferingid: + cmd.diskofferingid = diskofferingid + elif "diskoffering" in services: + cmd.diskofferingid = services["diskoffering"] + + if keypair: + cmd.keypair = keypair + elif "keypair" in services: + cmd.keypair = services["keypair"] + + if ipaddress: + cmd.ipaddress = ipaddress + elif "ipaddress" in services: + cmd.ipaddress = services["ipaddress"] + + if securitygroupids: + cmd.securitygroupids = [str(sg_id) for sg_id in securitygroupids] + + if "affinitygroupnames" in services: + cmd.affinitygroupnames = services["affinitygroupnames"] + elif affinitygroupnames: + cmd.affinitygroupnames = affinitygroupnames + + if affinitygroupids: + cmd.affinitygroupids = affinitygroupids + + if projectid: + cmd.projectid = projectid + + if startvm is not None: + cmd.startvm = startvm + + if hostid: + cmd.hostid = hostid + + if clusterid: + cmd.clusterid = clusterid + + if "userdata" in services: + cmd.userdata = base64.urlsafe_b64encode(services["userdata"].encode()).decode() + + if userdataid is not None: + cmd.userdataid = userdataid + + if userdatadetails is not None: + cmd.userdatadetails = userdatadetails + + if "dhcpoptionsnetworklist" in services: + cmd.dhcpoptionsnetworklist = services["dhcpoptionsnetworklist"] + + if dynamicscalingenabled is not None: + cmd.dynamicscalingenabled = dynamicscalingenabled + + cmd.details = [{}] + + if customcpunumber: + cmd.details[0]["cpuNumber"] = customcpunumber + + if customcpuspeed: + cmd.details[0]["cpuSpeed"] = customcpuspeed + + if custommemory: + cmd.details[0]["memory"] = custommemory + + if not rootdisksize is None and rootdisksize >= 0: + cmd.details[0]["rootdisksize"] = rootdisksize + + if rootdiskcontroller: + cmd.details[0]["rootDiskController"] = rootdiskcontroller + + if "size" in services: + cmd.size = services["size"] + + if group: + cmd.group = group + + cmd.datadisktemplatetodiskofferinglist = [] + for datadisktemplate, diskoffering in list(datadisktemplate_diskoffering_list.items()): + cmd.datadisktemplatetodiskofferinglist.append({ + 'datadisktemplateid': datadisktemplate, + 'diskofferingid': diskoffering + }) + + # program default access to ssh + if mode.lower() == 'basic': + cls.ssh_access_group(apiclient, cmd) + + if macaddress: + cmd.macaddress = macaddress + elif macaddress in services: + cmd.macaddress = services["macaddress"] + + if properties: + cmd.properties = properties + + if nicnetworklist: + cmd.nicnetworklist = nicnetworklist + + if bootmode: + cmd.bootmode = bootmode + + if boottype: + cmd.boottype = boottype + + if extraconfig: + cmd.extraconfig = extraconfig + + if vnfconfiguremanagement: + cmd.vnfconfiguremanagement = vnfconfiguremanagement + + if vnfcidrlist: + cmd.vnfcidrlist = vnfcidrlist + + vnf_app = apiclient.deployVnfAppliance(cmd, method=method) + + return VnfAppliance(vnf_app.__dict__) + + def delete(self, apiclient, expunge=True, **kwargs): + """Destroy an VNF appliance""" + cmd = destroyVirtualMachine.destroyVirtualMachineCmd() + cmd.id = self.id + cmd.expunge = expunge + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + apiclient.destroyVirtualMachine(cmd) + +class ObjectStoragePool: + + def __init__(self, items): + self.__dict__.update(items) + + """Manage Object Stores""" + @classmethod + def create(cls, apiclient, name, url, provider, services=None): + """Add Object Store""" + cmd = addObjectStoragePool.addObjectStoragePoolCmd() + cmd.name = name + cmd.url = url + cmd.provider = provider + if services: + if "details" in services: + cmd.details = services["details"] + + return ObjectStoragePool(apiclient.addObjectStoragePool(cmd).__dict__) + + def delete(self, apiclient): + """Delete Object Store""" + cmd = deleteObjectStoragePool.deleteObjectStoragePoolCmd() + cmd.id = self.id + apiclient.deleteObjectStoragePool(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + cmd = listObjectStoragePools.listObjectStoragePoolsCmd() + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + if 'account' in list(kwargs.keys()) and 'domainid' in list(kwargs.keys()): + cmd.listall = True + return (apiclient.listObjectStoragePools(cmd)) + + def update(self, apiclient, **kwargs): + """Update the Object Store""" + + cmd = updateObjectStoragePool.updateObjectStoragePoolCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + return apiclient.updateObjectStoragePool(cmd) + +class Bucket: + """Manage Bucket Life cycle""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, name, objectstorageid, **kwargs): + """Create Bucket""" + cmd = createBucket.createBucketCmd() + cmd.name = name + cmd.objectstorageid = objectstorageid + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + + return Bucket(apiclient.createBucket(cmd).__dict__) + + def delete(self, apiclient): + """Delete Bucket""" + cmd = deleteBucket.deleteBucketCmd() + cmd.id = self.id + apiclient.deleteBucket(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + cmd = listBuckets.listBucketsCmd() + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + if 'account' in list(kwargs.keys()) and 'domainid' in list(kwargs.keys()): + cmd.listall = True + return (apiclient.listBuckets(cmd)) + + def update(self, apiclient, **kwargs): + """Update Bucket""" + + cmd = updateBucket.updateBucketCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + return apiclient.updateBucket(cmd) + +class Webhook: + """Manage Webhook Life cycle""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, name, payloadurl, **kwargs): + """Create Webhook""" + cmd = createWebhook.createWebhookCmd() + cmd.name = name + cmd.payloadurl = payloadurl + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + + return Webhook(apiclient.createWebhook(cmd).__dict__) + + @classmethod + def list(cls, apiclient, **kwargs): + cmd = listWebhooks.listWebhooksCmd() + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + if 'account' in list(kwargs.keys()) and 'domainid' in list(kwargs.keys()): + cmd.listall = True + return apiclient.listWebhooks(cmd) + + def delete(self, apiclient): + """Delete Webhook""" + cmd = deleteWebhook.deleteWebhookCmd() + cmd.id = self.id + apiclient.deleteWebhook(cmd) + + def update(self, apiclient, **kwargs): + """Update Webhook""" + + cmd = updateWebhook.updateWebhookCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + return apiclient.updateWebhook(cmd) + + def list_deliveries(self, apiclient, **kwargs): + """List Webhook Deliveries""" + + cmd = listWebhookDeliveries.listWebhookDeliveriesCmd() + cmd.webhookid = self.id + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + return apiclient.listWebhookDeliveries(cmd) + + def execute_delivery(self, apiclient, **kwargs): + """Execute Webhook Delivery""" + + cmd = executeWebhookDelivery.executeWebhookDeliveryCmd() + cmd.webhookid = self.id + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + return apiclient.executeWebhookDelivery(cmd) + + def delete_deliveries(self, apiclient, **kwargs): + """Delete Webhook Deliveries""" + + cmd = deleteWebhookDelivery.deleteWebhookDeliveryCmd() + cmd.webhookid = self.id + [setattr(cmd, k, v) for k, v in list(kwargs.items())] + return apiclient.deleteWebhookDelivery(cmd) diff --git a/tools/marvin/marvin/lib/ncc.py b/tools/marvin/marvin/lib/ncc.py index 3fbffe0ae2c..09ef26ea713 100755 --- a/tools/marvin/marvin/lib/ncc.py +++ b/tools/marvin/marvin/lib/ncc.py @@ -93,7 +93,7 @@ class NCC: elif isolation_policy.lower() == "dedicated": srv_pkg = self.createServicePackageDedicated(name, tnt_group_id, dv_group_id, isolation_policy ) else: - raise Exception("NS device must be either in shared or dedicated mode") + raise Exception("NS device must be either in shared or dedicated mode") if srv_pkg.status_code != 201: raise Exception("Error: %s" % self.__lastError) dev_add_res =self.addDevicetoServicePackage(dv_group_id, device_ip) diff --git a/tools/marvin/marvin/misc/build/CI.md b/tools/marvin/marvin/misc/build/CI.md index 3400e7ef765..89df14bbf32 100644 --- a/tools/marvin/marvin/misc/build/CI.md +++ b/tools/marvin/marvin/misc/build/CI.md @@ -28,7 +28,7 @@ components .. hypervisor kickstarts .. adding new profiles . puppet -. dnsmasq +. dnsmasq . ntpd . jenkins jnlp slave . scheduling @@ -72,7 +72,7 @@ systems - these are virtual/physical infrastructure mapped to cobbler profiles b When a new image needs to be added we create a 'distro' in cobbler and associate that with a profile's kickstart. Any new systems to be hooked-up to be serviced by the profile can then be added easily by cmd line. -b. Puppet master - Cobbler reimages machines on-demand but it is upto puppet recipes to do configuration management within them. The configuration management is required for kvm hypervisors (kvm agent for eg:) and for the cloudstack management server which needs mysql, cloudstack, etc. The puppetmasterd daemon on the driver-vm is responsible for 'kicking' nodes to initiate configuration management on themselves when they come alive. +b. Puppet master - Cobbler reimages machines on-demand but it is upto puppet recipes to do configuration management within them. The configuration management is required for kvm hypervisors (kvm agent for eg:) and for the cloudstack management server which needs mysql, cloudstack, etc. The puppetmasterd daemon on the driver-vm is responsible for 'kicking' nodes to initiate configuration management on themselves when they come alive. So the driver-vm is also the repository of all the puppet recipes for various modules that need to be configured for the test infrastructure to work. The modules are placed in /etc/puppet and bear the same structure as our GitHub repo. When we need to affect a configuration change on any of our systems we only change the GitHub repo and the systems in place are affected upon next run. @@ -90,7 +90,7 @@ h. puppet - set puppetmaster to listen on 8140 2. NFS storage - the nfs server is a single server serving as both primary and secondary storage. This is likely a limitation when compared to true production deployments but serves in good stead for a test setup. Where it becomes a limitation is in testing different storage backends. Object stores, local storage, clustered local storage etc are not addressed by this setup. -3. Hypervisor hosts - There currently are 4 hosts in this environment. These are arranged at the moment in three pods so as to be capable of being deployed in a two zone environment. One zone with two pods and and a second zone with a single pod. This covers tests that depend on +3. Hypervisor hosts - There currently are 4 hosts in this environment. These are arranged at the moment in three pods so as to be capable of being deployed in a two zone environment. One zone with two pods and a second zone with a single pod. This covers tests that depend on a. single zone/pod/cluster b. multiple cluster c. inter-zone tests @@ -107,7 +107,7 @@ Only the latest tests from git are run on the setup. This allows us to test in a control via github ================== -there are two GitHub repositories controlling the test infrastructure. +there are two GitHub repositories controlling the test infrastructure. a. The puppet recipes at gh:acs-infra-test b. The gh:cloud-autodeploy repo that has the scripts to orchestrate the overall workflow @@ -127,7 +127,7 @@ When jenkins triggers the job following sequence of actions occur on the test in 5. based on the hypervisor chosen we choose a profile for cobbler to reimage the hosts in the infrastructure. if xen is chosen we bring up the profile of the latest xen kickstart available in cobbler. currently - this is at xen 6.0.2. if kvm is chosen we can pick between ubuntu and rhel based host OS kickstarts. 6. with this knowledge we kick off the driver script with the following cmd line arguments - $ python configure.py -v $hypervisor -d $distro -p $profile -l $LOG_LVL + $ python configure.py -v $hypervisor -d $distro -p $profile -l $LOG_LVL The $distro argument chooses the hostOS of the mgmt server - this can be ubuntu / rhel. LOG_LVL can be set to INFO/DEBUG/WARN for troubleshooting and more verbose log output. @@ -137,7 +137,7 @@ The $distro argument chooses the hostOS of the mgmt server - this can be ubuntu c. starts up a new xenserver VM that will act as the mgmt server. we chose to keep things simple by launching the vm on a xenserver. one could employ jclouds via jenkins to deploy the mgmt server VM on a dogfooded cloudstack. d. in parallel the deployment config of marvin is parsed through to find the hypervisors that need to be cleaned up, pxe booted and prepared for the cloudstack deployment. e. all the hosts in the marvin config are pxe booted via ipmi and cobbler takes over to reimage them with the profile chosen by the jenkins job run. - f. while this is happening we also seed the secondary storage with the systemvm template reqd for the hypervisor. + f. while this is happening we also seed the secondary storage with the systemvm template reqd for the hypervisor. g. all the primary stores in the marvin config are then cleaned for the next run. 8. While cobbler is reimaging the hosts with the right profiles, the configure script waits until all hosts are reachable over ssh. It also checks for essential services (http, mysql) ports to come up. Cobbler once done with refreshing the machine hands over the reins to puppet. diff --git a/tools/marvin/marvin/misc/build/README.md b/tools/marvin/marvin/misc/build/README.md index 90598ed7dc3..400d21d8d64 100644 --- a/tools/marvin/marvin/misc/build/README.md +++ b/tools/marvin/marvin/misc/build/README.md @@ -48,7 +48,7 @@ run the following. ### 1a. reset the environment with the new build `$ python configure.py -b build.cfg -e environment.cfg -d deployment.cfg [[--skip-host] --install-marvin]` -OR +OR ### b. reset the environment with specific build number `$ python configure.py -n -e environment.cfg -d deployment.cfg [[--skip-host] --install-marvin]` diff --git a/tools/marvin/marvin/misc/build/kvm.properties b/tools/marvin/marvin/misc/build/kvm.properties index 1f372c6b424..28178c880cc 100644 --- a/tools/marvin/marvin/misc/build/kvm.properties +++ b/tools/marvin/marvin/misc/build/kvm.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/marvin/marvin/misc/build/redeploy.sh b/tools/marvin/marvin/misc/build/redeploy.sh index 29ddb7bda0b..854d9d9905e 100755 --- a/tools/marvin/marvin/misc/build/redeploy.sh +++ b/tools/marvin/marvin/misc/build/redeploy.sh @@ -25,7 +25,7 @@ usage() { printf "\nThe -s flag will clean the secondary path and install the specified hypervisor's system template as per -h, if -h is not given then xenserver is -assumed\n" +assumed\n" } @@ -66,7 +66,7 @@ do done if [[ -e /etc/redhat-release ]] -then +then cat /etc/redhat-release else echo "script works on rpm environments only" @@ -88,7 +88,7 @@ else fi #TODO: archive old logs -#refresh log state +#refresh log state cat /dev/null > /var/log/cloud/management/management-server.log cat /dev/null > /var/log/cloud/management/api-server.log cat /dev/null > /var/log/cloud/management/catalina.out diff --git a/tools/marvin/marvin/misc/build/xen.properties b/tools/marvin/marvin/misc/build/xen.properties index cffa28c55b9..ca76c38f53c 100644 --- a/tools/marvin/marvin/misc/build/xen.properties +++ b/tools/marvin/marvin/misc/build/xen.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/marvin/marvin/sandbox/advanced/setup.properties b/tools/marvin/marvin/sandbox/advanced/setup.properties index 73eacc938d4..89aa4616aa8 100644 --- a/tools/marvin/marvin/sandbox/advanced/setup.properties +++ b/tools/marvin/marvin/sandbox/advanced/setup.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/marvin/marvin/sandbox/advancedsg/setup.properties b/tools/marvin/marvin/sandbox/advancedsg/setup.properties index ee07ce23938..26f7e478913 100644 --- a/tools/marvin/marvin/sandbox/advancedsg/setup.properties +++ b/tools/marvin/marvin/sandbox/advancedsg/setup.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/marvin/marvin/sandbox/basic/setup.properties b/tools/marvin/marvin/sandbox/basic/setup.properties index 8833b507252..5b1aa90c8ae 100644 --- a/tools/marvin/marvin/sandbox/basic/setup.properties +++ b/tools/marvin/marvin/sandbox/basic/setup.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/marvin/marvin/sandbox/demo/simulator/simulatordemo.properties b/tools/marvin/marvin/sandbox/demo/simulator/simulatordemo.properties index 9d9f14b70a4..353ce044d12 100644 --- a/tools/marvin/marvin/sandbox/demo/simulator/simulatordemo.properties +++ b/tools/marvin/marvin/sandbox/demo/simulator/simulatordemo.properties @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/marvin/marvin/sandbox/run-marvin.sh b/tools/marvin/marvin/sandbox/run-marvin.sh index 015a43b5648..1d1dcff418e 100755 --- a/tools/marvin/marvin/sandbox/run-marvin.sh +++ b/tools/marvin/marvin/sandbox/run-marvin.sh @@ -6,9 +6,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/tools/marvin/mvn-setup.py b/tools/marvin/mvn-setup.py index 61bd2219238..cabcf0dc659 100755 --- a/tools/marvin/mvn-setup.py +++ b/tools/marvin/mvn-setup.py @@ -34,6 +34,8 @@ def replaceVersion(fname, version): with open(fname, 'r') as f: content = f.read() needle = '\nVERSION\s*=\s*[\'"][^\'"]*[\'"]' + # Ensure the version is PEP440 compliant + version = version.replace('-', '+', 1) replacement = '\nVERSION = "%s"' % version content = re.sub(needle, replacement, content, 1) with open(fname, 'w') as f: diff --git a/tools/marvin/pom.xml b/tools/marvin/pom.xml index 334d0b3e653..df1186d18b7 100644 --- a/tools/marvin/pom.xml +++ b/tools/marvin/pom.xml @@ -25,7 +25,7 @@ org.apache.cloudstack cloud-tools - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT ../pom.xml diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py index e96065f96d0..0618d84370a 100644 --- a/tools/marvin/setup.py +++ b/tools/marvin/setup.py @@ -27,7 +27,7 @@ except ImportError: raise RuntimeError("python setuptools is required to build Marvin") -VERSION = "4.19.0.0" +VERSION = "4.20.0.0-SNAPSHOT" setup(name="Marvin", version=VERSION, diff --git a/tools/ngui/static/js/lib/angular.js b/tools/ngui/static/js/lib/angular.js index e960afe36d7..74e036b6c90 100644 --- a/tools/ngui/static/js/lib/angular.js +++ b/tools/ngui/static/js/lib/angular.js @@ -6428,11 +6428,11 @@ function setter(obj, path, setValue) { } /** - * Return the value accesible from the object by path. Any undefined traversals are ignored + * Return the value accessible from the object by path. Any undefined traversals are ignored * @param {Object} obj starting object * @param {string} path path to traverse * @param {boolean=true} bindFnToScope - * @returns value as accesbile by path + * @returns value as accessible by path */ //TODO(misko): this function needs to be removed function getter(obj, path, bindFnToScope) { diff --git a/tools/pom.xml b/tools/pom.xml index a39a504d261..aa736372aff 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -25,7 +25,7 @@ org.apache.cloudstack cloudstack - 4.19.0.0-SNAPSHOT + 4.20.0.0-SNAPSHOT ../pom.xml diff --git a/tools/transifex/README-transifex.txt b/tools/transifex/README-transifex.txt index 7079331f848..ca02f88eb99 100644 --- a/tools/transifex/README-transifex.txt +++ b/tools/transifex/README-transifex.txt @@ -45,13 +45,13 @@ with the translatons from traductors. ===== The sync-transifex-ui provide too the ability to : -* Download from Transifex the source language resource files. Be carrefully, +* Download from Transifex the source language resource files. Be carrefully, with this, you can remove some transaction on Transifex if some keys has been removed inside the source language resource files. ./sync-transifex-ui.sh download-source-language CloudStack_UI.410_messagesjson -* Upload the L10N resource files on Transifex. +* Upload the L10N resource files on Transifex. ./sync-transifex-ui.sh upload-l10n-languages CloudStack_UI.410_messagesjson diff --git a/tools/transifex/sync-transifex-ui.sh b/tools/transifex/sync-transifex-ui.sh index 13d6ed6bccf..f8c7d98b161 100755 --- a/tools/transifex/sync-transifex-ui.sh +++ b/tools/transifex/sync-transifex-ui.sh @@ -51,7 +51,7 @@ doUploadL10NLangs() grep -v "^\s*//" ${DIRECTORY_RESOURCES}/${CODELANG}.js | sed -e 's/var dictionary = //' -e "\$s/;$//" > ${WORKDIR}/${CODELANG}.json tx set -r ${ARGUMENTS} -l ${CODELANG} ${WORKDIR}/${CODELANG}.json tx push -t -r ${ARGUMENTS} -l ${CODELANG} - else + else echo "Warning: the resource file for language ${CODELANG} doesn't exist." fi done @@ -64,7 +64,7 @@ doDownloadL10NLangs() if [ -f "${DIRECTORY_RESOURCES}/${CODELANG}.js" ]; then grep -v "^\s*//" ${DIRECTORY_RESOURCES}/${CODELANG}.js | sed -e 's/var dictionary = //' -e "\$s/;$//" > ${WORKDIR}/${CODELANG}.json tx set -r ${ARGUMENTS} -l ${CODELANG} ${WORKDIR}/${CODELANG}.json - else + else echo "\nWarning: the resource file for language ${CODELANG} doesn't exist." echo "Run this command to force get this language from transifex:" echo "\ntx set -r ${ARGUMENTS} -l ${CODELANG} ${WORKDIR}/${CODELANG}.json\n" @@ -83,7 +83,7 @@ doDownloadL10NLangs() -e '$s/\}$/\n\};/' \ -e "1s~^~${AL2_STRING}~" \ ${WORKDIR}/${CODELANG}.json > ${DIRECTORY_RESOURCES}/${CODELANG}.js - else + else echo "Warning: the resource file for language ${CODELANG} doesn't exist on transifex" fi done @@ -95,7 +95,7 @@ doUploadSourceLang() if [ -f ${DIRECTORY_RESOURCES}/${SRCLANG}.js ]; then grep -v "^\s*//" ${DIRECTORY_RESOURCES}/${SRCLANG}.js | sed -e 's/var dictionary = //' -e "\$s/;$//" > ${WORKDIR}/${SRCLANG}.json tx set --source -r ${ARGUMENTS} -l ${SRCLANG} ${WORKDIR}/${SRCLANG}.json - tx push -s -r ${ARGUMENTS} + tx push -s -r ${ARGUMENTS} else echo "Warning: the source language doesn't exist!" fi @@ -104,7 +104,7 @@ doUploadSourceLang() doDownloadSourceLang() { # get all resource files from transifex - tx pull -s -r ${ARGUMENTS} + tx pull -s -r ${ARGUMENTS} # Source language if [ -f "${WORKDIR}/${SRCLANG}.json" ]; then sed -e 's/":"/": "/' \ diff --git a/tools/utils/database_comparision_during_upgrade/cloud_schema_comparision.sh b/tools/utils/database_comparision_during_upgrade/cloud_schema_comparision.sh index 034b8da91b0..135e1e23d7c 100644 --- a/tools/utils/database_comparision_during_upgrade/cloud_schema_comparision.sh +++ b/tools/utils/database_comparision_during_upgrade/cloud_schema_comparision.sh @@ -52,20 +52,20 @@ do cat $path1/upgradedschema >> $tablename.diff sort $tablename.diff > $tablename.sort uniq -u $tablename.sort > $tablename.uniq - + if [ -s $tablename.uniq ] then - echo $tablename "table schema is different." + echo $tablename "table schema is different." cat $path1/upgradedschema > $tablename - rm -rf $tablename.diff $tablename.sort + rm -rf $tablename.diff $tablename.sort # do something as file has data else - rm -rf $tablename.diff $tablename.sort $tablename.uniq + rm -rf $tablename.diff $tablename.sort $tablename.uniq fi - + fi done diff --git a/tools/utils/database_comparision_during_upgrade/test_config_between_fresh_and_upgraded_setup.sh b/tools/utils/database_comparision_during_upgrade/test_config_between_fresh_and_upgraded_setup.sh index d7fe251415c..3394a240b10 100644 --- a/tools/utils/database_comparision_during_upgrade/test_config_between_fresh_and_upgraded_setup.sh +++ b/tools/utils/database_comparision_during_upgrade/test_config_between_fresh_and_upgraded_setup.sh @@ -34,7 +34,7 @@ mysql -u $dbuser -p$dbpwd -h $dbhost --skip-column-names -e "select name, desc mysql -u $dbuser -p$dbpwd -h $dbhost --skip-column-names -e "select name, scope from cloud.configuration" > $path2/scope_configuration_upgrade -IFS=$'\n' +IFS=$'\n' #to find difference between upgraded configuration and fresh install configuration @@ -58,16 +58,16 @@ do if [ ! -s t ] then echo $row >> ./only_in_upgraded - else + else fname=`awk '{print $1}' t` fvalue=`awk '{print $2}' t` fdefault=`awk '{print $3}' t` #echo $fname $fvalue $fdefault - if [ $default != $value ] + if [ $default != $value ] then if [ $default == $fdefault ] && [ $value == $fvalue ] then - echo + echo else first="$name $value" second="$fname $fvalue" @@ -78,7 +78,7 @@ do fi fi fi - + fi done @@ -103,7 +103,7 @@ do grep '^'$word'[^\.]\w*' $path2/configuration_upgrade >> ./final_diff4 count1=`wc -l <./final_diff4` count1=`expr $count1 - 1` - + if [ $count == $count1 ] then echo $row >> ./only_in_fresh diff --git a/tools/whisker/descriptor-for-packaging.xml b/tools/whisker/descriptor-for-packaging.xml index 41423332b7b..1969f68936a 100644 --- a/tools/whisker/descriptor-for-packaging.xml +++ b/tools/whisker/descriptor-for-packaging.xml @@ -865,7 +865,7 @@ EXHIBIT A -Mozilla Public License. The Original Code is ${PROJECT}. The Initial Developer of the Original Code is ${INITIAL_DEVELOPER}. - Portions created by ${INITIAL_DEVELOPER} are Copyright (C) + Portions created by ${INITIAL_DEVELOPER} are Copyright (C) ${INITIAL_DEVELOPER_COPYRIGHT}. All Rights Reserved. Contributor(s): ${CONTRIBUTORS}. @@ -888,9 +888,9 @@ EXHIBIT A -Mozilla Public License. - Please note: our license is an adaptation of the MIT X11 License and should be @@ -917,7 +917,7 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -939,9 +939,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - Eclipse Distribution License Version 1.0 @@ -973,7 +973,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - Permission is hereby granted, free of charge, to any person obtaining @@ -1066,7 +1066,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -1080,7 +1080,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE POSSIBILITY OF SUCH DAMAGE. - + + diff --git a/ui/src/components/view/TreeView.vue b/ui/src/components/view/TreeView.vue index 40cd6f0f967..4564e2bc826 100644 --- a/ui/src/components/view/TreeView.vue +++ b/ui/src/components/view/TreeView.vue @@ -204,9 +204,13 @@ export default { return } - if (Object.keys(this.resource).length > 0) { + const resourceKeys = Object.keys(this.resource) + if (resourceKeys.length > 0) { this.selectedTreeKey = this.resource.key this.$emit('change-resource', this.resource) + if (resourceKeys.filter(x => x.endsWith('limit')).length === 0) { + setTimeout(() => { this.getDetailResource(this.resource.id) }) + } // set default expand if (this.defaultSelected.length > 1) { diff --git a/ui/src/components/view/VolumesTab.vue b/ui/src/components/view/VolumesTab.vue index e9165b1b3bd..7805e5b8d87 100644 --- a/ui/src/components/view/VolumesTab.vue +++ b/ui/src/components/view/VolumesTab.vue @@ -19,7 +19,7 @@ {{ parseFloat(record.size / (1024.0 * 1024.0 * 1024.0)).toFixed(2) }} GB + @@ -64,11 +68,20 @@ export default { } }, inject: ['parentFetchData'], + computed: { + columns () { + if (this.volumes?.[0]) { + return this.allColumns.filter(col => col.dataIndex in this.volumes[0]) + } + return this.allColumns.filter(col => this.defaultColumns.includes(col.dataIndex)) + } + }, data () { return { vm: {}, volumes: [], - volumeColumns: [ + defaultColumns: ['name', 'state', 'type', 'size'], + allColumns: [ { key: 'name', title: this.$t('label.name'), @@ -87,6 +100,11 @@ export default { key: 'size', title: this.$t('label.size'), dataIndex: 'size' + }, + { + key: 'storage', + title: this.$t('label.storage'), + dataIndex: 'storage' } ] } diff --git a/ui/src/components/view/WebhookDeliveriesTab.vue b/ui/src/components/view/WebhookDeliveriesTab.vue new file mode 100644 index 00000000000..c13b0453254 --- /dev/null +++ b/ui/src/components/view/WebhookDeliveriesTab.vue @@ -0,0 +1,526 @@ +// 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. + + + + + + diff --git a/ui/src/components/widgets/ChartCard.vue b/ui/src/components/widgets/ChartCard.vue index 8d5e413c9db..a41cd69a3f1 100644 --- a/ui/src/components/widgets/ChartCard.vue +++ b/ui/src/components/widgets/ChartCard.vue @@ -93,7 +93,6 @@ export default { } &-footer { - border-top: 1px solid #e8e8e8; padding-top: 9px; margin-top: 8px; } diff --git a/ui/src/components/widgets/Console.vue b/ui/src/components/widgets/Console.vue index d73753c142e..6c16c7546a7 100644 --- a/ui/src/components/widgets/Console.vue +++ b/ui/src/components/widgets/Console.vue @@ -17,7 +17,7 @@ + + diff --git a/ui/src/components/widgets/Status.vue b/ui/src/components/widgets/Status.vue index 6575d409a3c..50340c2faa2 100644 --- a/ui/src/components/widgets/Status.vue +++ b/ui/src/components/widgets/Status.vue @@ -87,6 +87,12 @@ export default { case 'InProgress': state = this.$t('state.inprogress') break + case 'Down': + state = this.$t('state.down') + break + case 'Up': + state = this.$t('state.up') + break } return state.charAt(0).toUpperCase() + state.slice(1) } @@ -168,23 +174,24 @@ export default { if (!(state && this.displayText)) { return '' } + let result if (this.$route.path === '/vmsnapshot' || this.$route.path.includes('/vmsnapshot/')) { - return this.$t('message.vmsnapshot.state.' + state.toLowerCase()) + result = this.$t('message.vmsnapshot.state.' + state.toLowerCase()) + } else if (this.$route.path === '/vm' || this.$route.path.includes('/vm/')) { + result = this.$t('message.vm.state.' + state.toLowerCase()) + } else if (this.$route.path === '/volume' || this.$route.path.includes('/volume/')) { + result = this.$t('message.volume.state.' + state.toLowerCase()) + } else if (this.$route.path === '/guestnetwork' || this.$route.path.includes('/guestnetwork/')) { + result = this.$t('message.guestnetwork.state.' + state.toLowerCase()) + } else if (this.$route.path === '/publicip' || this.$route.path.includes('/publicip/')) { + result = this.$t('message.publicip.state.' + state.toLowerCase()) } - if (this.$route.path === '/vm' || this.$route.path.includes('/vm/')) { - return this.$t('message.vm.state.' + state.toLowerCase()) + + if (!result || (result.startsWith('message.') && result.endsWith('.state.' + state.toLowerCase()))) { + // Nothing for snapshots, vpcs, gateways, vnpnconn, vpnuser, kubectl, event, project, account, infra. They're all self explanatory + result = this.$t(state) } - if (this.$route.path === '/volume' || this.$route.path.includes('/volume/')) { - return this.$t('message.volume.state.' + state.toLowerCase()) - } - if (this.$route.path === '/guestnetwork' || this.$route.path.includes('/guestnetwork/')) { - return this.$t('message.guestnetwork.state.' + state.toLowerCase()) - } - if (this.$route.path === '/publicip' || this.$route.path.includes('/publicip/')) { - return this.$t('message.publicip.state.' + state.toLowerCase()) - } - // Nothing for snapshots, vpcs, gateways, vnpnconn, vpnuser, kubectl, event, project, account, infra. They're all self explanatory - return this.$t(state) + return result }, getStyle () { let styles = { display: 'inline-flex' } diff --git a/ui/src/components/widgets/TooltipLabel.vue b/ui/src/components/widgets/TooltipLabel.vue index 2874b1e7aa9..c596bbf35b9 100644 --- a/ui/src/components/widgets/TooltipLabel.vue +++ b/ui/src/components/widgets/TooltipLabel.vue @@ -54,5 +54,6 @@ export default { diff --git a/ui/src/config/router.js b/ui/src/config/router.js index e7e8e642877..90fae577ce4 100644 --- a/ui/src/config/router.js +++ b/ui/src/config/router.js @@ -19,8 +19,9 @@ import { UserLayout, BasicLayout, RouteView } from '@/layouts' import AutogenView from '@/views/AutogenView.vue' import IFramePlugin from '@/views/plugins/IFramePlugin.vue' +import ApiDocsPlugin from '@/views/plugins/ApiDocsPlugin.vue' -import { shallowRef, defineAsyncComponent } from 'vue' +import { shallowRef } from 'vue' import { vueProps } from '@/vue-app' import compute from '@/config/section/compute' @@ -51,14 +52,13 @@ function generateRouterMap (section) { icon: section.icon, docHelp: vueProps.$applyDocHelpMappings(section.docHelp), searchFilters: section.searchFilters, - related: section.related + related: section.related, + section: true }, component: shallowRef(RouteView) } if (section.children && section.children.length > 0) { - map.redirect = '/' + section.children[0].name - map.meta.permission = section.children[0].permission map.children = [] for (const child of section.children) { if ('show' in child && !child.show()) { @@ -75,6 +75,7 @@ function generateRouterMap (section) { icon: child.icon, docHelp: vueProps.$applyDocHelpMappings(child.docHelp), permission: child.permission, + getApiToCall: child.getApiToCall, resourceType: child.resourceType, filters: child.filters, params: child.params ? child.params : {}, @@ -201,26 +202,7 @@ export function asyncRouterMap () { name: 'dashboard', meta: { title: 'label.dashboard', - icon: 'DashboardOutlined', - tabs: [ - { - name: 'dashboard', - component: shallowRef(defineAsyncComponent(() => import('@/views/dashboard/UsageDashboardChart'))) - }, - { - name: 'accounts', - show: (record, route, user) => { return record.account === user.account || ['Admin', 'DomainAdmin'].includes(user.roletype) }, - component: shallowRef(defineAsyncComponent(() => import('@/views/project/AccountsTab'))) - }, - { - name: 'limits', - params: { - projectid: 'id' - }, - show: (record, route, user) => { return ['Admin'].includes(user.roletype) }, - component: shallowRef(defineAsyncComponent(() => import('@/components/view/ResourceLimitTab.vue'))) - } - ] + icon: 'DashboardOutlined' }, component: () => import('@/views/dashboard/Dashboard') }, @@ -242,7 +224,6 @@ export function asyncRouterMap () { generateRouterMap(tools), generateRouterMap(quota), generateRouterMap(cloudian), - { path: '/exception', name: 'exception', @@ -294,6 +275,16 @@ export function asyncRouterMap () { }) } + const apidocs = vueProps.$config.apidocs + if (apidocs !== false) { + routerMap[0].children.push({ + path: '/apidocs/', + name: 'apidocs', + component: shallowRef(ApiDocsPlugin), + meta: { title: 'label.api.docs', icon: 'read-outlined' } + }) + } + return routerMap } @@ -320,6 +311,15 @@ export const constantRouterMap = [ }, component: () => import('@/views/dashboard/VerifyTwoFa') }, + { + path: '/verifyOauth', + name: 'VerifyOauth', + meta: { + title: 'label.oauth.verification', + hidden: true + }, + component: () => import('@/views/dashboard/VerifyOauth') + }, { path: '/setup2FA', name: 'SetupTwoFaAtLogin', diff --git a/ui/src/config/section/account.js b/ui/src/config/section/account.js index 716417587c4..28c0e3f556d 100644 --- a/ui/src/config/section/account.js +++ b/ui/src/config/section/account.js @@ -24,12 +24,37 @@ export default { icon: 'team-outlined', docHelp: 'adminguide/accounts.html', permission: ['listAccounts'], + searchFilters: ['name', 'accounttype', 'domainid'], columns: ['name', 'state', 'rolename', 'roletype', 'domainpath'], details: ['name', 'id', 'rolename', 'roletype', 'domainpath', 'networkdomain', 'iptotal', 'vmtotal', 'volumetotal', 'receivedbytes', 'sentbytes', 'created'], related: [{ name: 'accountuser', title: 'label.users', param: 'account' + }, { + name: 'vm', + title: 'label.vms', + param: 'account' + }, { + name: 'volume', + title: 'label.volumes', + param: 'account' + }, { + name: 'guestnetwork', + title: 'label.networks', + param: 'account' + }, { + name: 'ssh', + title: 'label.sshkeypairs', + param: 'account' + }, { + name: 'userdata', + title: 'label.userdata', + param: 'account' + }, { + name: 'template', + title: 'label.templates', + param: 'account' }], filters: () => { const filters = ['enabled', 'disabled', 'locked'] @@ -91,7 +116,7 @@ export default { icon: 'edit-outlined', label: 'label.action.edit.account', dataView: true, - args: ['newname', 'account', 'domainid', 'networkdomain'], + args: ['newname', 'account', 'domainid', 'networkdomain', 'roleid'], mapping: { account: { value: (record) => { return record.name } diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index 6602ecb884c..4c5a61e3bdc 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -16,7 +16,6 @@ // under the License. import { shallowRef, defineAsyncComponent } from 'vue' -import kubernetes from '@/assets/icons/kubernetes.svg?inline' import store from '@/store' export default { @@ -27,15 +26,17 @@ export default { { name: 'vm', title: 'label.instances', - icon: 'desktop-outlined', + icon: 'cloud-server-outlined', docHelp: 'adminguide/virtual_machines.html', - permission: ['listVirtualMachinesMetrics'], + permission: ['listVirtualMachines', 'listVirtualMachinesMetrics'], + getApiToCall: () => store.getters.metrics ? 'listVirtualMachinesMetrics' : 'listVirtualMachines', resourceType: 'UserVm', params: () => { - var params = { details: 'servoff,tmpl,nics' } + var params = { details: 'group,nics,secgrp,tmpl,servoff,diskoff,iso,volume,affgrp,backoff' } if (store.getters.metrics) { - params = { details: 'servoff,tmpl,nics,stats' } + params = { details: 'all,stats' } } + params.isvnf = false return params }, filters: () => { @@ -61,16 +62,18 @@ export default { if (store.getters.metrics) { fields.push(...metricsFields) } - if (store.getters.userInfo.roletype === 'Admin') { fields.splice(2, 0, 'instancename') - fields.push('account') fields.push('hostname') + fields.push('account') } else if (store.getters.userInfo.roletype === 'DomainAdmin') { fields.push('account') } else { fields.push('serviceofferingname') } + if (store.getters.listAllProjects) { + fields.push('project') + } fields.push('zonename') return fields }, @@ -162,33 +165,10 @@ export default { label: 'label.reinstall.vm', message: 'message.reinstall.vm', dataView: true, - args: ['virtualmachineid', 'templateid'], - filters: (record) => { - var filters = {} - var filterParams = {} - filterParams.hypervisortype = record.hypervisor - filterParams.zoneid = record.zoneid - filters.templateid = filterParams - return filters - }, + popup: true, show: (record) => { return ['Running', 'Stopped'].includes(record.state) }, - mapping: { - virtualmachineid: { - value: (record) => { return record.id } - } - }, disabled: (record) => { return record.hostcontrolstate === 'Offline' }, - successMethod: (obj, result) => { - const vm = result.jobresult.virtualmachine || {} - if (result.jobstatus === 1 && vm.password) { - const name = vm.displayname || vm.name || vm.id - obj.$notification.success({ - message: `${obj.$t('label.reinstall.vm')}: ` + name, - description: `${obj.$t('label.password.reset.confirm')}: ` + vm.password, - duration: 0 - }) - } - } + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/ReinstallVm.vue'))) }, { api: 'createVMSnapshot', @@ -256,7 +236,7 @@ export default { { api: 'createBackupSchedule', icon: 'schedule-outlined', - label: 'Configure Backup Schedule', + label: 'label.backup.configure.schedule', docHelp: 'adminguide/virtual_machines.html#creating-vm-backups', dataView: true, popup: true, @@ -369,8 +349,15 @@ export default { label: 'label.action.reset.password', message: 'message.action.instance.reset.password', dataView: true, + args: ['password'], show: (record) => { return ['Stopped'].includes(record.state) && record.passwordenabled }, - response: (result) => { return result.virtualmachine && result.virtualmachine.password ? `The password of VM ${result.virtualmachine.displayname} is ${result.virtualmachine.password}` : null } + response: (result) => { + return { + message: result.virtualmachine && result.virtualmachine.password ? `The password of VM ${result.virtualmachine.displayname} is ${result.virtualmachine.password}` : null, + copybuttontext: result.virtualmachine.password ? 'label.copy.password' : null, + copytext: result.virtualmachine.password ? result.virtualmachine.password : null + } + } }, { api: 'resetSSHKeyForVirtualMachine', @@ -417,7 +404,7 @@ export default { label: 'label.action.unmanage.virtualmachine', message: 'message.action.unmanage.virtualmachine', dataView: true, - show: (record) => { return ['Running', 'Stopped'].includes(record.state) && record.hypervisor === 'VMware' } + show: (record) => { return ['Running', 'Stopped'].includes(record.state) && ['VMware', 'KVM'].includes(record.hypervisor) } }, { api: 'expungeVirtualMachine', @@ -447,17 +434,103 @@ export default { } ] }, + { + name: 'vmsnapshot', + title: 'label.vm.snapshots', + icon: 'camera-outlined', + docHelp: 'adminguide/storage.html#working-with-volume-snapshots', + permission: ['listVMSnapshot'], + resourceType: 'VMSnapshot', + columns: () => { + const fields = ['displayname', 'state', 'name', 'type', 'current', 'parentName', 'created'] + if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { + fields.push('account') + if (store.getters.listAllProjects) { + fields.push('project') + } + fields.push('domain') + } else if (store.getters.listAllProjects) { + fields.push('project') + } + return fields + }, + details: ['name', 'id', 'displayname', 'description', 'type', 'current', 'parentName', 'virtualmachineid', 'account', 'domain', 'created'], + searchFilters: ['name', 'domainid', 'account', 'tags'], + tabs: [ + { + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, + { + name: 'events', + resourceType: 'VmSnapshot', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + }, + { + name: 'comments', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))) + } + ], + actions: [ + { + api: 'createSnapshotFromVMSnapshot', + icon: 'camera-outlined', + label: 'label.action.create.snapshot.from.vmsnapshot', + message: 'message.action.create.snapshot.from.vmsnapshot', + dataView: true, + popup: true, + show: (record) => { return (record.state === 'Ready' && record.hypervisor === 'KVM') }, + component: shallowRef(defineAsyncComponent(() => import('@/views/storage/CreateSnapshotFromVMSnapshot.vue'))) + }, + { + api: 'revertToVMSnapshot', + icon: 'sync-outlined', + label: 'label.action.vmsnapshot.revert', + message: 'label.action.vmsnapshot.revert', + dataView: true, + show: (record) => { return record.state === 'Ready' }, + args: ['vmsnapshotid'], + mapping: { + vmsnapshotid: { + value: (record) => { return record.id } + } + } + }, + { + api: 'deleteVMSnapshot', + icon: 'delete-outlined', + label: 'label.action.vmsnapshot.delete', + message: 'message.action.vmsnapshot.delete', + dataView: true, + show: (record) => { return ['Ready', 'Expunging', 'Error'].includes(record.state) }, + args: ['vmsnapshotid'], + mapping: { + vmsnapshotid: { + value: (record) => { return record.id } + } + }, + groupAction: true, + popup: true, + groupMap: (selection) => { return selection.map(x => { return { vmsnapshotid: x } }) } + } + ] + }, { name: 'kubernetes', title: 'label.kubernetes', - icon: shallowRef(kubernetes), + icon: ['fa-solid', 'fa-dharmachakra'], docHelp: 'plugins/cloudstack-kubernetes-service.html', + searchFilters: ['name', 'domainid', 'account', 'state'], permission: ['listKubernetesClusters'], columns: (store) => { var fields = ['name', 'state', 'clustertype', 'size', 'cpunumber', 'memory', 'kubernetesversionname'] if (['Admin', 'DomainAdmin'].includes(store.userInfo.roletype)) { fields.push('account') } + if (store.listAllProjects) { + fields.push('project') + } if (store.apis.scaleKubernetesCluster.params.filter(x => x.name === 'autoscalingenabled').length > 0) { fields.splice(2, 0, 'autoscalingenabled') } @@ -469,10 +542,12 @@ export default { return filters }, details: ['name', 'description', 'zonename', 'kubernetesversionname', 'autoscalingenabled', 'minsize', 'maxsize', 'size', 'controlnodes', 'cpunumber', 'memory', 'keypair', 'associatednetworkname', 'account', 'domain', 'zonename', 'clustertype', 'created'], - tabs: [{ - name: 'k8s', - component: shallowRef(defineAsyncComponent(() => import('@/views/compute/KubernetesServiceTab.vue'))) - }], + tabs: [ + { + name: 'k8s', + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/KubernetesServiceTab.vue'))) + } + ], resourceType: 'KubernetesCluster', actions: [ { @@ -541,6 +616,9 @@ export default { groupAction: true, popup: true, args: (record, store, group) => { + if (record.clustertype === 'CloudManaged') { + return [] + } return (['Admin'].includes(store.userInfo.roletype) || store.features.allowuserexpungerecovervm) ? ['cleanup', 'expunge'] : ['cleanup'] }, @@ -551,11 +629,18 @@ export default { { name: 'autoscalevmgroup', title: 'label.autoscale.vm.groups', - icon: 'ordered-list-outlined', - docHelp: 'adminguide/autoscale_without_netscaler.html', + icon: 'fullscreen-outlined', + docHelp: 'adminguide/autoscale_with_virtual_router.html', resourceType: 'AutoScaleVmGroup', permission: ['listAutoScaleVmGroups'], - columns: ['name', 'state', 'associatednetworkname', 'publicip', 'publicport', 'privateport', 'minmembers', 'maxmembers', 'availablevirtualmachinecount', 'account'], + searchFilters: ['name', 'zoneid', 'domainid', 'account'], + columns: (store) => { + var fields = ['name', 'state', 'associatednetworkname', 'publicip', 'publicport', 'privateport', 'minmembers', 'maxmembers', 'availablevirtualmachinecount', 'account'] + if (store.listAllProjects) { + fields.push('project') + } + return fields + }, details: ['name', 'id', 'account', 'domain', 'associatednetworkname', 'associatednetworkid', 'lbruleid', 'lbprovider', 'publicip', 'publicipid', 'publicport', 'privateport', 'minmembers', 'maxmembers', 'availablevirtualmachinecount', 'interval', 'state', 'created'], related: [{ name: 'vm', @@ -659,7 +744,15 @@ export default { docHelp: 'adminguide/virtual_machines.html#changing-the-vm-name-os-or-group', resourceType: 'VMInstanceGroup', permission: ['listInstanceGroups'], - columns: ['name', 'account', 'domain'], + searchFilters: ['name', 'zoneid', 'domainid', 'account'], + columns: (store) => { + var fields = ['name', 'account'] + if (store.listAllProjects) { + fields.push('project') + } + fields.push('domain') + return fields + }, details: ['name', 'id', 'account', 'domain', 'created'], related: [{ name: 'vm', @@ -709,11 +802,17 @@ export default { icon: 'key-outlined', docHelp: 'adminguide/virtual_machines.html#using-ssh-keys-for-authentication', permission: ['listSSHKeyPairs'], + searchFilters: ['name', 'domainid', 'account', 'fingerprint'], columns: () => { var fields = ['name', 'fingerprint'] if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { fields.push('account') + if (store.getters.listAllProjects) { + fields.push('project') + } fields.push('domain') + } else if (store.getters.listAllProjects) { + fields.push('project') } return fields }, @@ -791,7 +890,12 @@ export default { var fields = ['name', 'id'] if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { fields.push('account') + if (store.getters.listAllProjects) { + fields.push('project') + } fields.push('domain') + } else if (store.getters.listAllProjects) { + fields.push('project') } return fields }, @@ -859,11 +963,17 @@ export default { icon: 'swap-outlined', docHelp: 'adminguide/virtual_machines.html#affinity-groups', permission: ['listAffinityGroups'], + searchFilters: ['name', 'zoneid', 'domainid', 'account', 'type'], columns: () => { var fields = ['name', 'type', 'description'] if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { fields.push('account') + if (store.getters.listAllProjects) { + fields.push('project') + } fields.push('domain') + } else if (store.getters.listAllProjects) { + fields.push('project') } return fields }, @@ -873,6 +983,18 @@ export default { title: 'label.instances', param: 'affinitygroupid' }], + tabs: [ + { + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, + { + name: 'events', + resourceType: 'AffinityGroup', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + } + ], actions: [ { api: 'createAffinityGroup', diff --git a/ui/src/config/section/config.js b/ui/src/config/section/config.js index 3cddc6396b0..8f792e51ac9 100644 --- a/ui/src/config/section/config.js +++ b/ui/src/config/section/config.js @@ -37,6 +37,7 @@ export default { icon: 'team-outlined', docHelp: 'adminguide/accounts.html#using-an-ldap-server-for-user-authentication', permission: ['listLdapConfigurations'], + searchFilters: ['domainid', 'hostname', 'port'], columns: ['hostname', 'port', 'domainid'], details: ['hostname', 'port', 'domainid'], actions: [ @@ -70,12 +71,73 @@ export default { } ] }, + { + name: 'oauthsetting', + title: 'label.oauth.configuration', + icon: 'login-outlined', + docHelp: 'adminguide/accounts.html#using-an-ldap-server-for-user-authentication', + permission: ['listOauthProvider'], + columns: ['provider', 'enabled', 'description', 'clientid', 'secretkey', 'redirecturi'], + details: ['provider', 'description', 'enabled', 'clientid', 'secretkey', 'redirecturi'], + actions: [ + { + api: 'registerOauthProvider', + icon: 'plus-outlined', + label: 'label.register.oauth', + listView: true, + dataView: false, + args: [ + 'provider', 'description', 'clientid', 'redirecturi', 'secretkey' + ], + mapping: { + provider: { + options: ['google', 'github'] + } + } + }, + { + api: 'updateOauthProvider', + icon: 'edit-outlined', + label: 'label.edit', + dataView: true, + popup: true, + args: ['description', 'clientid', 'redirecturi', 'secretkey'] + }, + { + api: 'updateOauthProvider', + icon: 'play-circle-outlined', + label: 'label.enable.provider', + message: 'message.confirm.enable.provider', + dataView: true, + defaultArgs: { enabled: true }, + show: (record) => { return record.enabled === false } + }, + { + api: 'updateOauthProvider', + icon: 'pause-circle-outlined', + label: 'label.disable.provider', + message: 'message.confirm.disable.provider', + dataView: true, + defaultArgs: { enabled: false }, + show: (record) => { return record.enabled === true } + }, + { + api: 'deleteOauthProvider', + icon: 'delete-outlined', + label: 'label.action.delete.oauth.provider', + message: 'message.action.delete.guest.os', + dataView: true, + popup: true + } + ] + }, { name: 'hypervisorcapability', title: 'label.hypervisor.capabilities', icon: 'database-outlined', docHelp: 'adminguide/hosts.html?highlight=Hypervisor%20capabilities#hypervisor-capabilities', permission: ['listHypervisorCapabilities'], + searchFilters: ['hypervisor'], columns: ['hypervisor', 'hypervisorversion', 'maxguestslimit', 'maxhostspercluster'], details: ['hypervisor', 'hypervisorversion', 'maxguestslimit', 'maxdatavolumeslimit', 'maxhostspercluster', 'securitygroupenabled', 'storagemotionenabled'], actions: [ diff --git a/ui/src/config/section/domain.js b/ui/src/config/section/domain.js index a8648b10f76..e6807f06278 100644 --- a/ui/src/config/section/domain.js +++ b/ui/src/config/section/domain.js @@ -32,6 +32,22 @@ export default { name: 'account', title: 'label.accounts', param: 'domainid' + }, { + name: 'vm', + title: 'label.vms', + param: 'domainid' + }, { + name: 'volume', + title: 'label.volumes', + param: 'domainid' + }, { + name: 'guestnetwork', + title: 'label.networks', + param: 'domainid' + }, { + name: 'template', + title: 'label.templates', + param: 'domainid' }], tabs: [ { diff --git a/ui/src/config/section/event.js b/ui/src/config/section/event.js index 5f4b27b88ed..5ab87e86964 100644 --- a/ui/src/config/section/event.js +++ b/ui/src/config/section/event.js @@ -15,13 +15,22 @@ // specific language governing permissions and limitations // under the License. +import store from '@/store' + export default { name: 'event', title: 'label.events', icon: 'ScheduleOutlined', docHelp: 'adminguide/events.html', permission: ['listEvents'], - columns: ['level', 'type', 'state', 'description', 'resource', 'username', 'account', 'domain', 'created'], + columns: () => { + var fields = ['level', 'type', 'state', 'description', 'resource', 'username', 'account'] + if (store.getters.listAllProjects) { + fields.push('project') + } + fields.push(...['domain', 'created']) + return fields + }, details: ['username', 'id', 'description', 'resourcetype', 'resourceid', 'state', 'level', 'type', 'account', 'domain', 'created'], searchFilters: ['level', 'domainid', 'account', 'keyword', 'resourcetype'], related: [{ diff --git a/ui/src/config/section/image.js b/ui/src/config/section/image.js index c1961fe216d..72cde6afe9c 100644 --- a/ui/src/config/section/image.js +++ b/ui/src/config/section/image.js @@ -16,7 +16,6 @@ // under the License. import { shallowRef, defineAsyncComponent } from 'vue' -import kubernetes from '@/assets/icons/kubernetes.svg?inline' import store from '@/store' export default { @@ -48,21 +47,32 @@ export default { fields.push('size') fields.push('account') } + if (store.getters.listAllProjects) { + fields.push('project') + } if (['Admin'].includes(store.getters.userInfo.roletype)) { + fields.push('templatetype') fields.push('order') } return fields }, details: () => { var fields = ['name', 'id', 'displaytext', 'checksum', 'hypervisor', 'format', 'ostypename', 'size', 'physicalsize', 'isready', 'passwordenabled', - 'crossZones', 'directdownload', 'deployasis', 'ispublic', 'isfeatured', 'isextractable', 'isdynamicallyscalable', 'crosszones', 'type', + 'crossZones', 'templatetype', 'directdownload', 'deployasis', 'ispublic', 'isfeatured', 'isextractable', 'isdynamicallyscalable', 'crosszones', 'type', 'account', 'domain', 'created', 'userdatadetails', 'userdatapolicy'] if (['Admin'].includes(store.getters.userInfo.roletype)) { - fields.push('templatetype', 'url') + fields.push('templatetag', 'templatetype', 'url') } return fields }, - searchFilters: ['name', 'zoneid', 'tags'], + searchFilters: () => { + var filters = ['name', 'zoneid', 'tags'] + if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { + filters.push('storageid') + filters.push('imagestoreid') + } + return filters + }, related: [{ name: 'vm', title: 'label.instances', @@ -77,6 +87,10 @@ export default { }, { name: 'settings', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailSettings'))) + }, { + name: 'vnf.settings', + component: shallowRef(defineAsyncComponent(() => import('@/views/image/TemplateVnfSettings.vue'))), + show: (record) => { return record.templatetype === 'VNF' && 'updateVnfTemplate' in store.getters.apis } }, { name: 'events', @@ -209,13 +223,23 @@ export default { fields.push('size') fields.push('account') } + if (store.getters.listAllProjects) { + fields.push('project') + } if (['Admin'].includes(store.getters.userInfo.roletype)) { fields.push('order') } return fields }, - details: ['name', 'id', 'displaytext', 'checksum', 'ostypename', 'size', 'bootable', 'isready', 'directdownload', 'isextractable', 'ispublic', 'isfeatured', 'crosszones', 'account', 'domain', 'created', 'userdatadetails', 'userdatapolicy', 'url'], - searchFilters: ['name', 'zoneid', 'tags'], + details: ['name', 'id', 'displaytext', 'checksum', 'ostypename', 'size', 'bootable', 'isready', 'passwordenabled', 'directdownload', 'isextractable', 'ispublic', 'isfeatured', 'isdynamicallyscalable', 'crosszones', 'account', 'domain', 'created', 'userdatadetails', 'userdatapolicy', 'url'], + searchFilters: () => { + var filters = ['name', 'zoneid', 'tags'] + if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { + filters.push('storageid') + filters.push('imagestoreid') + } + return filters + }, related: [{ name: 'vm', title: 'label.instances', @@ -340,11 +364,24 @@ export default { { name: 'kubernetesiso', title: 'label.kubernetes.isos', - icon: shallowRef(kubernetes), + icon: ['fa-solid', 'fa-dharmachakra'], docHelp: 'plugins/cloudstack-kubernetes-service.html#kubernetes-supported-versions', permission: ['listKubernetesSupportedVersions'], + searchFilters: ['zoneid', 'minimumsemanticversion'], columns: ['name', 'state', 'semanticversion', 'isostate', 'mincpunumber', 'minmemory', 'zonename'], details: ['name', 'semanticversion', 'supportsautoscaling', 'zoneid', 'zonename', 'isoid', 'isoname', 'isostate', 'mincpunumber', 'minmemory', 'supportsha', 'state', 'created'], + tabs: [ + { + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, + { + name: 'events', + resourceType: 'KubernetesSupportedVersion', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + } + ], actions: [ { api: 'addKubernetesSupportedVersion', diff --git a/ui/src/config/section/infra.js b/ui/src/config/section/infra.js index 41b08fc6f51..cb91d4d7b04 100644 --- a/ui/src/config/section/infra.js +++ b/ui/src/config/section/infra.js @@ -23,6 +23,7 @@ import clusters from '@/config/section/infra/clusters' import hosts from '@/config/section/infra/hosts' import primaryStorages from '@/config/section/infra/primaryStorages' import secondaryStorages from '@/config/section/infra/secondaryStorages' +import objectStorages from '@/config/section/infra/objectStorages' import systemVms from '@/config/section/infra/systemVms' import routers from '@/config/section/infra/routers' import ilbvms from '@/config/section/infra/ilbvms' @@ -49,6 +50,7 @@ export default { hosts, primaryStorages, secondaryStorages, + objectStorages, systemVms, routers, ilbvms, @@ -77,6 +79,7 @@ export default { permission: ['listAlerts'], columns: ['name', 'description', 'type', 'sent'], details: ['name', 'id', 'type', 'sent', 'description'], + searchFilters: ['name', 'type'], actions: [ { api: 'archiveAlerts', diff --git a/ui/src/config/section/infra/clusters.js b/ui/src/config/section/infra/clusters.js index ca6dde7ec9b..8b2f37d5b7b 100644 --- a/ui/src/config/section/infra/clusters.js +++ b/ui/src/config/section/infra/clusters.js @@ -24,9 +24,10 @@ export default { icon: 'cluster-outlined', docHelp: 'conceptsandterminology/concepts.html#about-clusters', permission: ['listClustersMetrics'], + searchFilters: ['name', 'zoneid', 'podid', 'hypervisor'], columns: () => { const fields = ['name', 'state', 'allocationstate', 'clustertype', 'hypervisortype', 'hosts'] - const metricsFields = ['cpuused', 'cpumaxdeviation', 'cpuallocated', 'cputotal', 'memoryused', 'memorymaxdeviation', 'memoryallocated', 'memorytotal'] + const metricsFields = ['cpuused', 'cpumaxdeviation', 'cpuallocated', 'cputotal', 'memoryused', 'memorymaxdeviation', 'memoryallocated', 'memorytotal', 'drsimbalance'] if (store.getters.metrics) { fields.push(...metricsFields) } @@ -34,7 +35,7 @@ export default { fields.push('zonename') return fields }, - details: ['name', 'id', 'allocationstate', 'clustertype', 'managedstate', 'hypervisortype', 'podname', 'zonename'], + details: ['name', 'id', 'allocationstate', 'clustertype', 'managedstate', 'hypervisortype', 'podname', 'zonename', 'drsimbalance'], related: [{ name: 'host', title: 'label.hosts', @@ -54,9 +55,18 @@ export default { }, { name: 'settings', component: shallowRef(defineAsyncComponent(() => import('@/components/view/SettingsTab.vue'))) + }, { + name: 'drs', + component: shallowRef(defineAsyncComponent(() => import('@/views/infra/ClusterDRSTab.vue'))) }, { name: 'comments', component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))) + }, + { + name: 'events', + resourceType: 'Cluster', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } }], actions: [ { @@ -113,6 +123,16 @@ export default { defaultArgs: { managedstate: 'Unmanaged' }, show: (record) => { return record.managedstate === 'Managed' } }, + { + api: 'executeDRS', + icon: 'gold-outlined', + label: 'label.action.drs.cluster', + message: 'message.action.drs.cluster', + dataView: true, + defaultArgs: { iterations: null }, + args: ['iterations'], + show: (record) => { return record.managedstate === 'Managed' } + }, { api: 'enableOutOfBandManagementForCluster', icon: 'plus-circle-outlined', diff --git a/ui/src/config/section/infra/hosts.js b/ui/src/config/section/infra/hosts.js index 22a9afc79cd..92688cf9280 100644 --- a/ui/src/config/section/infra/hosts.js +++ b/ui/src/config/section/infra/hosts.js @@ -21,9 +21,10 @@ import store from '@/store' export default { name: 'host', title: 'label.hosts', - icon: 'desktop-outlined', + icon: 'database-outlined', docHelp: 'conceptsandterminology/concepts.html#about-hosts', permission: ['listHostsMetrics'], + searchFilters: ['name', 'zoneid', 'podid', 'clusterid', 'hypervisor'], resourceType: 'Host', filters: () => { const filters = ['enabled', 'disabled', 'maintenance', 'up', 'down', 'alert'] @@ -31,7 +32,7 @@ export default { }, params: { type: 'routing' }, columns: () => { - const fields = ['name', 'state', 'resourcestate', 'ipaddress', 'hypervisor', 'instances', 'powerstate'] + const fields = ['name', 'state', 'resourcestate', 'ipaddress', 'hypervisor', 'instances', 'powerstate', 'version'] const metricsFields = ['cpunumber', 'cputotalghz', 'cpuusedghz', 'cpuallocatedghz', 'memorytotalgb', 'memoryusedgb', 'memoryallocatedgb', 'networkread', 'networkwrite'] if (store.getters.metrics) { fields.push(...metricsFields) @@ -44,6 +45,11 @@ export default { tabs: [{ name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, { + name: 'events', + resourceType: 'Host', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } }, { name: 'comments', component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))) @@ -68,12 +74,8 @@ export default { icon: 'edit-outlined', label: 'label.edit', dataView: true, - args: ['name', 'hosttags', 'oscategoryid'], - mapping: { - oscategoryid: { - api: 'listOsCategories' - } - } + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/infra/HostUpdate'))) }, { api: 'provisionCertificate', @@ -97,7 +99,7 @@ export default { label: 'label.action.force.reconnect', message: 'message.confirm.action.force.reconnect', dataView: true, - show: (record) => { return ['Disconnected', 'Up'].includes(record.state) } + show: (record) => { return ['Disconnected', 'Up', 'Alert'].includes(record.state) } }, { api: 'updateHost', @@ -144,6 +146,7 @@ export default { message: 'label.outofbandmanagement.configure', docHelp: 'adminguide/hosts.html#out-of-band-management', dataView: true, + post: true, args: ['hostid', 'address', 'port', 'username', 'password', 'driver'], mapping: { hostid: { @@ -280,7 +283,7 @@ export default { }, { api: 'startRollingMaintenance', - icon: 'setting-outlined', + icon: 'control-outlined', label: 'label.start.rolling.maintenance', message: 'label.start.rolling.maintenance', docHelp: 'adminguide/hosts.html#kvm-rolling-maintenance', @@ -295,6 +298,26 @@ export default { } } }, + { + api: 'declareHostAsDegraded', + icon: 'exception-outlined', + label: 'label.declare.host.as.degraded', + message: 'label.declare.host.as.degraded', + dataView: true, + show: (record) => { + return record.resourcestate !== 'Degraded' && (record.state === 'Alert' || record.state === 'Disconnected') + } + }, + { + api: 'cancelHostAsDegraded', + icon: 'file-done-outlined', + label: 'label.cancel.host.as.degraded', + message: 'label.cancel.host.as.degraded', + dataView: true, + show: (record) => { + return record.resourcestate === 'Degraded' + } + }, { api: 'deleteHost', icon: 'delete-outlined', diff --git a/ui/src/config/section/infra/ilbvms.js b/ui/src/config/section/infra/ilbvms.js index fa20d6990e9..5ab9b3edfc0 100644 --- a/ui/src/config/section/infra/ilbvms.js +++ b/ui/src/config/section/infra/ilbvms.js @@ -16,6 +16,8 @@ // under the License. import { shallowRef, defineAsyncComponent } from 'vue' +import store from '@/store' + export default { name: 'ilbvm', title: 'label.internal.lb', @@ -25,6 +27,15 @@ export default { params: { projectid: '-1' }, columns: ['name', 'state', 'publicip', 'guestnetworkname', 'vpcname', 'version', 'softwareversion', 'hostname', 'account', 'zonename', 'requiresupgrade'], details: ['name', 'id', 'version', 'softwareversion', 'requiresupgrade', 'guestnetworkname', 'vpcname', 'publicip', 'guestipaddress', 'linklocalip', 'serviceofferingname', 'networkdomain', 'isredundantrouter', 'redundantstate', 'hostname', 'account', 'zonename', 'created', 'hostcontrolstate'], + tabs: [{ + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, { + name: 'events', + resourceType: 'InternalLbVm', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + }], actions: [ { api: 'startInternalLoadBalancerVM', diff --git a/ui/src/config/section/infra/managementServers.js b/ui/src/config/section/infra/managementServers.js index d1dfa6df70d..cda19ef7cd5 100644 --- a/ui/src/config/section/infra/managementServers.js +++ b/ui/src/config/section/infra/managementServers.js @@ -26,8 +26,8 @@ export default { permission: ['listManagementServersMetrics'], resourceType: 'ManagementServer', columns: () => { - const fields = ['name', 'state', 'version'] - const metricsFields = ['collectiontime', 'availableprocessors', 'cpuload', 'heapmemoryused', 'agentcount'] + const fields = ['name', 'state', 'serviceip', 'version', 'osdistribution', 'agentcount'] + const metricsFields = ['collectiontime', 'availableprocessors', 'cpuload', 'heapmemoryused'] if (store.getters.metrics) { fields.push(...metricsFields) } diff --git a/ui/src/config/section/infra/objectStorages.js b/ui/src/config/section/infra/objectStorages.js new file mode 100644 index 00000000000..821c1b2d948 --- /dev/null +++ b/ui/src/config/section/infra/objectStorages.js @@ -0,0 +1,74 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import { shallowRef, defineAsyncComponent } from 'vue' +import store from '@/store' + +export default { + name: 'objectstore', + title: 'label.object.storage', + icon: 'gold-outlined', + docHelp: 'adminguide/storage.html#object-storage', + permission: ['listObjectStoragePools'], + columns: () => { + var fields = ['name', 'url', 'providername'] + return fields + }, + details: () => { + var fields = ['name', 'id', 'url', 'providername'] + return fields + }, + resourceType: 'ObjectStorage', + tabs: [{ + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, { + name: 'events', + resourceType: 'ObjectStore', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + }, { + name: 'comments', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))) + }], + actions: [ + { + api: 'addObjectStoragePool', + icon: 'plus-outlined', + docHelp: 'installguide/configuration.html#add-object-storage', + label: 'label.add.object.storage', + listView: true, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/infra/AddObjectStorage.vue'))) + }, + { + api: 'updateObjectStoragePool', + icon: 'edit-outlined', + label: 'label.action.update.object.storage', + args: ['name', 'url'], + dataView: true + }, + { + api: 'deleteObjectStoragePool', + icon: 'delete-outlined', + label: 'label.action.delete.object.storage', + message: 'message.action.delete.object.storage', + dataView: true, + displayName: (record) => { return record.name || record.displayName || record.id } + } + ] +} diff --git a/ui/src/config/section/infra/phynetworks.js b/ui/src/config/section/infra/phynetworks.js index 92d1e9abec8..578a12516fa 100644 --- a/ui/src/config/section/infra/phynetworks.js +++ b/ui/src/config/section/infra/phynetworks.js @@ -42,6 +42,11 @@ export default { name: 'guestnetwork', title: 'label.guest.networks', param: 'physicalnetworkid' + }, + { + name: 'publicip', + title: 'label.public.ip.addresses', + param: 'physicalnetworkid' }], actions: [ { diff --git a/ui/src/config/section/infra/pods.js b/ui/src/config/section/infra/pods.js index eff62e0a4a2..595b35f4fb9 100644 --- a/ui/src/config/section/infra/pods.js +++ b/ui/src/config/section/infra/pods.js @@ -24,6 +24,7 @@ export default { icon: 'appstore-outlined', docHelp: 'conceptsandterminology/concepts.html#about-pods', permission: ['listPods'], + searchFilters: ['name', 'zoneid'], columns: ['name', 'allocationstate', 'gateway', 'netmask', 'zonename'], details: ['name', 'id', 'allocationstate', 'netmask', 'gateway', 'zonename'], related: [{ diff --git a/ui/src/config/section/infra/primaryStorages.js b/ui/src/config/section/infra/primaryStorages.js index 4537b993a06..c4932b2daad 100644 --- a/ui/src/config/section/infra/primaryStorages.js +++ b/ui/src/config/section/infra/primaryStorages.js @@ -21,9 +21,10 @@ import store from '@/store' export default { name: 'storagepool', title: 'label.primary.storage', - icon: 'database-outlined', + icon: 'hdd-outlined', docHelp: 'adminguide/storage.html#primary-storage', permission: ['listStoragePoolsMetrics'], + searchFilters: ['name', 'zoneid', 'podid', 'clusterid', 'ipaddress', 'path', 'scope'], columns: () => { const fields = ['name', 'state', 'ipaddress', 'scope', 'type', 'path'] const metricsFields = ['disksizeusedgb', 'disksizetotalgb', 'disksizeallocatedgb', 'disksizeunallocatedgb'] @@ -34,11 +35,21 @@ export default { fields.push('zonename') return fields }, - details: ['name', 'id', 'ipaddress', 'type', 'scope', 'tags', 'path', 'provider', 'hypervisor', 'overprovisionfactor', 'disksizetotal', 'disksizeallocated', 'disksizeused', 'clustername', 'podname', 'zonename', 'created'], + details: ['name', 'id', 'ipaddress', 'type', 'nfsmountopts', 'scope', 'tags', 'path', 'provider', 'hypervisor', 'overprovisionfactor', 'disksizetotal', 'disksizeallocated', 'disksizeused', 'clustername', 'podname', 'zonename', 'created'], related: [{ name: 'volume', title: 'label.volumes', param: 'storageid' + }, + { + name: 'template', + title: 'label.templates', + param: 'storageid' + }, + { + name: 'iso', + title: 'label.isos', + param: 'storageid' }], resourceType: 'PrimaryStorage', filters: () => { @@ -51,6 +62,10 @@ export default { }, { name: 'settings', component: shallowRef(defineAsyncComponent(() => import('@/components/view/SettingsTab.vue'))) + }, { + name: 'browser', + resourceType: 'PrimaryStorage', + component: shallowRef(defineAsyncComponent(() => import('@/views/infra/StorageBrowser.vue'))) }, { name: 'events', resourceType: 'StoragePool', @@ -75,7 +90,8 @@ export default { icon: 'edit-outlined', label: 'label.edit', dataView: true, - args: ['name', 'tags', 'capacitybytes', 'capacityiops'] + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/infra/UpdatePrimaryStorage.vue'))) }, { api: 'updateStoragePool', @@ -119,6 +135,26 @@ export default { dataView: true, show: (record) => { return ['Maintenance', 'PrepareForMaintenance', 'ErrorInMaintenance'].includes(record.state) } }, + { + api: 'changeStoragePoolScope', + icon: 'swap-outlined', + label: 'label.action.change.primary.storage.scope', + dataView: true, + popup: true, + show: (record) => { + return (record.state === 'Disabled' && + (record.scope === 'CLUSTER' || + record.scope === 'ZONE') && + (record.hypervisor === 'KVM' || + record.hypervisor === 'VMware' || + record.hypervisor === 'HyperV' || + record.hypervisor === 'LXC' || + record.hypervisor === 'Any' || + record.hypervisor === 'Simulator') + ) + }, + component: shallowRef(defineAsyncComponent(() => import('@/views/infra/ChangeStoragePoolScope.vue'))) + }, { api: 'deleteStoragePool', icon: 'delete-outlined', diff --git a/ui/src/config/section/infra/secondaryStorages.js b/ui/src/config/section/infra/secondaryStorages.js index 93c54dc1d79..3fc64c5c957 100644 --- a/ui/src/config/section/infra/secondaryStorages.js +++ b/ui/src/config/section/infra/secondaryStorages.js @@ -24,6 +24,7 @@ export default { icon: 'picture-outlined', docHelp: 'adminguide/storage.html#secondary-storage', permission: ['listImageStores'], + searchFilters: ['name', 'zoneid', 'provider'], columns: () => { var fields = ['name', 'url', 'protocol', 'scope', 'zonename'] if (store.getters.apis.listImageStores.params.filter(x => x.name === 'readonly').length > 0) { @@ -42,12 +43,31 @@ export default { return fields }, resourceType: 'SecondaryStorage', + related: [{ + name: 'template', + title: 'label.templates', + param: 'imagestoreid' + }, + { + name: 'iso', + title: 'label.isos', + param: 'imagestoreid' + }, + { + name: 'snapshot', + title: 'label.snapshots', + param: 'imagestoreid' + }], tabs: [{ name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) }, { name: 'settings', component: shallowRef(defineAsyncComponent(() => import('@/components/view/SettingsTab.vue'))) + }, { + name: 'browser', + resourceType: 'ImageStore', + component: shallowRef(defineAsyncComponent(() => import('@/views/infra/StorageBrowser.vue'))) }, { name: 'events', resourceType: 'ImageStore', @@ -77,21 +97,10 @@ export default { }, { api: 'updateImageStore', - icon: 'stop-outlined', - label: 'label.action.image.store.read.only', - message: 'message.action.secondary.storage.read.only', + icon: 'edit-outlined', + label: 'label.edit', dataView: true, - defaultArgs: { readonly: true }, - show: (record) => { return record.readonly === false } - }, - { - api: 'updateImageStore', - icon: 'check-circle-outlined', - label: 'label.action.image.store.read.write', - message: 'message.action.secondary.storage.read.write', - dataView: true, - defaultArgs: { readonly: false }, - show: (record) => { return record.readonly === true } + args: ['name', 'readonly', 'capacitybytes'] }, { api: 'deleteImageStore', diff --git a/ui/src/config/section/infra/systemVms.js b/ui/src/config/section/infra/systemVms.js index e48b19cb5d4..3ecd17f95ca 100644 --- a/ui/src/config/section/infra/systemVms.js +++ b/ui/src/config/section/infra/systemVms.js @@ -24,8 +24,9 @@ export default { icon: 'thunderbolt-outlined', docHelp: 'adminguide/systemvm.html', permission: ['listSystemVms'], - columns: ['name', 'state', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'hostname', 'zonename'], - details: ['name', 'id', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'gateway', 'hostname', 'zonename', 'created', 'activeviewersessions', 'isdynamicallyscalable', 'hostcontrolstate'], + searchFilters: ['name', 'zoneid', 'podid', 'hostid', 'systemvmtype', 'storageid'], + columns: ['name', 'state', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'version', 'hostname', 'zonename'], + details: ['name', 'id', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'gateway', 'hostname', 'version', 'zonename', 'created', 'activeviewersessions', 'isdynamicallyscalable', 'hostcontrolstate'], resourceType: 'SystemVm', filters: () => { const filters = ['starting', 'running', 'stopping', 'stopped', 'destroyed', 'expunging', 'migrating', 'error', 'unknown', 'shutdown'] diff --git a/ui/src/config/section/infra/zones.js b/ui/src/config/section/infra/zones.js index b2768f77343..929add5210d 100644 --- a/ui/src/config/section/infra/zones.js +++ b/ui/src/config/section/infra/zones.js @@ -24,6 +24,7 @@ export default { icon: 'global-outlined', docHelp: 'conceptsandterminology/concepts.html#about-zones', permission: ['listZonesMetrics'], + searchFilters: ['name', 'domainid', 'tags'], columns: () => { const fields = ['name', 'allocationstate', 'type', 'networktype', 'clusters'] const metricsFields = ['cpuused', 'cpumaxdeviation', 'cpuallocated', 'cputotal', 'memoryused', 'memorymaxdeviation', 'memoryallocated', 'memorytotal'] diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js index 153e6c5df5f..8399d9769ef 100644 --- a/ui/src/config/section/network.js +++ b/ui/src/config/section/network.js @@ -34,20 +34,26 @@ export default { permission: ['listNetworks'], resourceType: 'Network', columns: () => { - var fields = ['name', 'state', 'type', 'vpcname', 'cidr', 'ip6cidr', 'broadcasturi', 'account', 'domain', 'zonename'] + var fields = ['name', 'state', 'type', 'vpcname', 'cidr', 'ip6cidr', 'broadcasturi', 'domainpath'] if (!isAdmin()) { fields = fields.filter(function (e) { return e !== 'broadcasturi' }) } + if (store.getters.listAllProjects) { + fields.push('project') + } else { + fields.push('account') + } + fields.push('zonename') return fields }, details: () => { - var fields = ['name', 'id', 'description', 'type', 'traffictype', 'vpcid', 'vlan', 'broadcasturi', 'cidr', 'ip6cidr', 'netmask', 'gateway', 'aclname', 'ispersistent', 'restartrequired', 'reservediprange', 'redundantrouter', 'networkdomain', 'egressdefaultpolicy', 'zonename', 'account', 'domain', 'associatednetwork', 'associatednetworkid', 'ip6firewall', 'ip6routing', 'ip6routes', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu', 'privatemtu'] + var fields = ['name', 'id', 'description', 'type', 'traffictype', 'vpcid', 'vlan', 'broadcasturi', 'cidr', 'ip6cidr', 'netmask', 'gateway', 'aclname', 'ispersistent', 'restartrequired', 'reservediprange', 'redundantrouter', 'networkdomain', 'egressdefaultpolicy', 'zonename', 'account', 'domainpath', 'associatednetwork', 'associatednetworkid', 'ip6firewall', 'ip6routing', 'ip6routes', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu', 'privatemtu'] if (!isAdmin()) { fields = fields.filter(function (e) { return e !== 'broadcasturi' }) } return fields }, - filters: ['all', 'account', 'domain', 'shared'], + filters: ['all', 'account', 'domainpath', 'shared'], searchFilters: ['keyword', 'zoneid', 'domainid', 'account', 'type', 'tags'], related: [{ name: 'vm', @@ -66,13 +72,17 @@ export default { component: shallowRef(defineAsyncComponent(() => import('@/views/network/Ipv6FirewallRulesTab.vue'))), show: (record, route, user) => { return record.type === 'Isolated' && ['IPv6', 'DualStack'].includes(record.internetprotocol) && !('vpcid' in record) && 'listIpv6FirewallRules' in store.getters.apis && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid) } }, { - name: 'public.ip.addresses', + name: (record) => { return record.type === 'Shared' ? 'ip.addresses' : 'public.ip.addresses' }, component: shallowRef(defineAsyncComponent(() => import('@/views/network/IpAddressesTab.vue'))), show: (record, route, user) => { return 'listPublicIpAddresses' in store.getters.apis && (record.type === 'Shared' || (record.type === 'Isolated' && !('vpcname' in record) && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid))) } }, { name: 'virtual.routers', component: shallowRef(defineAsyncComponent(() => import('@/views/network/RoutersTab.vue'))), show: (record) => { return (record.type === 'Isolated' || record.type === 'Shared') && 'listRouters' in store.getters.apis && isAdmin() } + }, { + name: 'vnf.appliances', + component: shallowRef(defineAsyncComponent(() => import('@/views/network/VnfAppliancesTab.vue'))), + show: () => { return 'listVnfAppliances' in store.getters.apis } }, { name: 'guest.ip.range', component: shallowRef(defineAsyncComponent(() => import('@/views/network/GuestIpRanges.vue'))), @@ -193,7 +203,14 @@ export default { docHelp: 'adminguide/networking_and_traffic.html#configuring-a-virtual-private-cloud', permission: ['listVPCs'], resourceType: 'Vpc', - columns: ['name', 'state', 'displaytext', 'cidr', 'account', 'domain', 'zonename'], + columns: () => { + var fields = ['name', 'state', 'displaytext', 'cidr', 'account'] + if (store.getters.listAllProjects) { + fields.push('project') + } + fields.push(...['domain', 'zonename']) + return fields + }, details: ['name', 'id', 'displaytext', 'cidr', 'networkdomain', 'ip6routes', 'ispersistent', 'redundantvpcrouter', 'restartrequired', 'zonename', 'account', 'domain', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu'], searchFilters: ['name', 'zoneid', 'domainid', 'account', 'tags'], related: [{ @@ -316,14 +333,431 @@ export default { } ] }, + { + name: 'vnfapp', + title: 'label.vnf.appliances', + icon: 'gateway-outlined', + permission: ['listVnfAppliances'], + resourceType: 'UserVm', + params: () => { + return { details: 'servoff,tmpl,nics', isvnf: true } + }, + columns: () => { + const fields = ['name', 'state', 'ipaddress'] + if (store.getters.userInfo.roletype === 'Admin') { + fields.splice(2, 0, 'instancename') + fields.push('account') + if (store.getters.listAllProjects) { + fields.push('project') + } + fields.push('domain') + fields.push('hostname') + } else if (store.getters.userInfo.roletype === 'DomainAdmin') { + fields.push('account') + if (store.getters.listAllProjects) { + fields.push('project') + } + } else { + fields.push('serviceofferingname') + } + fields.push('zonename') + return fields + }, + searchFilters: ['name', 'zoneid', 'domainid', 'account', 'groupid', 'tags'], + details: () => { + var fields = ['name', 'displayname', 'id', 'state', 'ipaddress', 'ip6address', 'templatename', 'ostypename', + 'serviceofferingname', 'isdynamicallyscalable', 'haenable', 'hypervisor', 'boottype', 'bootmode', 'account', + 'domain', 'zonename', 'userdataid', 'userdataname', 'userdataparams', 'userdatadetails', 'userdatapolicy', 'hostcontrolstate'] + const listZoneHaveSGEnabled = store.getters.zones.filter(zone => zone.securitygroupsenabled === true) + if (!listZoneHaveSGEnabled || listZoneHaveSGEnabled.length === 0) { + return fields + } + fields.push('securitygroup') + return fields + }, + tabs: [{ + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/InstanceTab.vue'))) + }], + actions: [ + { + api: 'deployVnfAppliance', + icon: 'plus-outlined', + label: 'label.vnf.appliance.add', + docHelp: 'adminguide/networking/vnf_templates_appliances.html#deploying-vnf-appliances', + listView: true, + component: () => import('@/views/compute/DeployVnfAppliance.vue') + }, + { + api: 'updateVirtualMachine', + icon: 'edit-outlined', + label: 'label.vnf.app.action.edit', + docHelp: 'adminguide/virtual_machines.html#changing-the-vm-name-os-or-group', + dataView: true, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/EditVM.vue'))) + }, + { + api: 'startVirtualMachine', + icon: 'caret-right-outlined', + label: 'label.vnf.app.action.start', + message: 'message.action.start.instance', + docHelp: 'adminguide/virtual_machines.html#stopping-and-starting-vms', + dataView: true, + groupAction: true, + popup: true, + groupMap: (selection, values) => { return selection.map(x => { return { id: x, considerlasthost: values.considerlasthost } }) }, + args: ['considerlasthost'], + show: (record) => { return ['Stopped'].includes(record.state) }, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/StartVirtualMachine.vue'))) + }, + { + api: 'stopVirtualMachine', + icon: 'poweroff-outlined', + label: 'label.vnf.app.action.stop', + message: 'message.action.stop.instance', + docHelp: 'adminguide/virtual_machines.html#stopping-and-starting-vms', + dataView: true, + groupAction: true, + groupMap: (selection, values) => { return selection.map(x => { return { id: x, forced: values.forced } }) }, + args: ['forced'], + show: (record) => { return ['Running'].includes(record.state) } + }, + { + api: 'rebootVirtualMachine', + icon: 'reload-outlined', + label: 'label.vnf.app.action.reboot', + message: 'message.action.reboot.instance', + docHelp: 'adminguide/virtual_machines.html#stopping-and-starting-vms', + dataView: true, + show: (record) => { return ['Running'].includes(record.state) }, + disabled: (record) => { return record.hostcontrolstate === 'Offline' }, + args: (record, store) => { + var fields = [] + fields.push('forced') + if (record.hypervisor === 'VMware') { + if (store.apis.rebootVirtualMachine.params.filter(x => x.name === 'bootintosetup').length > 0) { + fields.push('bootintosetup') + } + } + return fields + }, + groupAction: true, + popup: true, + groupMap: (selection, values) => { return selection.map(x => { return { id: x, forced: values.forced } }) } + }, + { + api: 'restoreVirtualMachine', + icon: 'sync-outlined', + label: 'label.vnf.app.action.reinstall', + message: 'message.reinstall.vm', + dataView: true, + args: ['virtualmachineid', 'templateid'], + filters: (record) => { + var filters = {} + var filterParams = {} + filterParams.hypervisortype = record.hypervisor + filterParams.zoneid = record.zoneid + filters.templateid = filterParams + return filters + }, + show: (record) => { return ['Running', 'Stopped'].includes(record.state) }, + mapping: { + virtualmachineid: { + value: (record) => { return record.id } + } + }, + disabled: (record) => { return record.hostcontrolstate === 'Offline' }, + successMethod: (obj, result) => { + const vm = result.jobresult.virtualmachine || {} + if (result.jobstatus === 1 && vm.password) { + const name = vm.displayname || vm.name || vm.id + obj.$notification.success({ + message: `${obj.$t('label.reinstall.vm')}: ` + name, + description: `${obj.$t('label.password.reset.confirm')}: ` + vm.password, + duration: 0 + }) + } + } + }, + { + api: 'createVMSnapshot', + icon: 'camera-outlined', + label: 'label.action.vmsnapshot.create', + docHelp: 'adminguide/virtual_machines.html#virtual-machine-snapshots', + dataView: true, + args: ['virtualmachineid', 'name', 'description', 'snapshotmemory', 'quiescevm'], + show: (record) => { + return ((['Running'].includes(record.state) && record.hypervisor !== 'LXC') || + (['Stopped'].includes(record.state) && ((record.hypervisor !== 'KVM' && record.hypervisor !== 'LXC') || + (record.hypervisor === 'KVM' && record.pooltype === 'PowerFlex')))) + }, + disabled: (record) => { return record.hostcontrolstate === 'Offline' && record.hypervisor === 'KVM' }, + mapping: { + virtualmachineid: { + value: (record, params) => { return record.id } + } + } + }, + { + api: 'createSnapshot', + icon: ['fas', 'camera-retro'], + label: 'label.action.vmstoragesnapshot.create', + docHelp: 'adminguide/virtual_machines.html#virtual-machine-snapshots', + dataView: true, + popup: true, + show: (record) => { + return ((['Running'].includes(record.state) && record.hypervisor !== 'LXC') || + (['Stopped'].includes(record.state) && !['KVM', 'LXC'].includes(record.hypervisor))) + }, + disabled: (record) => { return record.hostcontrolstate === 'Offline' && record.hypervisor === 'KVM' }, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/CreateSnapshotWizard.vue'))) + }, + { + api: 'assignVirtualMachineToBackupOffering', + icon: 'folder-add-outlined', + label: 'label.backup.offering.assign', + message: 'label.backup.offering.assign', + docHelp: 'adminguide/virtual_machines.html#backup-offerings', + dataView: true, + args: ['virtualmachineid', 'backupofferingid'], + show: (record) => { return !record.backupofferingid }, + mapping: { + virtualmachineid: { + value: (record, params) => { return record.id } + } + } + }, + { + api: 'createBackup', + icon: 'cloud-upload-outlined', + label: 'label.create.backup', + message: 'message.backup.create', + docHelp: 'adminguide/virtual_machines.html#creating-vm-backups', + dataView: true, + args: ['virtualmachineid'], + show: (record) => { return record.backupofferingid }, + mapping: { + virtualmachineid: { + value: (record, params) => { return record.id } + } + } + }, + { + api: 'createBackupSchedule', + icon: 'schedule-outlined', + label: 'label.backup.configure.schedule', + docHelp: 'adminguide/virtual_machines.html#creating-vm-backups', + dataView: true, + popup: true, + show: (record) => { return record.backupofferingid }, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/BackupScheduleWizard.vue'))), + mapping: { + virtualmachineid: { + value: (record, params) => { return record.id } + }, + intervaltype: { + options: ['HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY'] + } + } + }, + { + api: 'removeVirtualMachineFromBackupOffering', + icon: 'scissor-outlined', + label: 'label.backup.offering.remove', + message: 'label.backup.offering.remove', + docHelp: 'adminguide/virtual_machines.html#restoring-vm-backups', + dataView: true, + args: ['virtualmachineid', 'forced'], + show: (record) => { return record.backupofferingid }, + mapping: { + virtualmachineid: { + value: (record, params) => { return record.id } + } + } + }, + { + api: 'attachIso', + icon: 'paper-clip-outlined', + label: 'label.action.attach.iso', + docHelp: 'adminguide/templates.html#attaching-an-iso-to-a-vm', + dataView: true, + popup: true, + show: (record) => { return ['Running', 'Stopped'].includes(record.state) && !record.isoid }, + disabled: (record) => { return record.hostcontrolstate === 'Offline' || record.hostcontrolstate === 'Maintenance' }, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/AttachIso.vue'))) + }, + { + api: 'detachIso', + icon: 'link-outlined', + label: 'label.action.detach.iso', + message: 'message.detach.iso.confirm', + dataView: true, + args: (record, store) => { + var args = ['virtualmachineid'] + if (record && record.hypervisor && record.hypervisor === 'VMware') { + args.push('forced') + } + return args + }, + show: (record) => { return ['Running', 'Stopped'].includes(record.state) && 'isoid' in record && record.isoid }, + disabled: (record) => { return record.hostcontrolstate === 'Offline' || record.hostcontrolstate === 'Maintenance' }, + mapping: { + virtualmachineid: { + value: (record, params) => { return record.id } + } + } + }, + { + api: 'updateVMAffinityGroup', + icon: 'swap-outlined', + label: 'label.change.affinity', + docHelp: 'adminguide/virtual_machines.html#change-affinity-group-for-an-existing-vm', + dataView: true, + args: ['affinitygroupids'], + show: (record) => { return ['Stopped'].includes(record.state) }, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/ChangeAffinity'))), + popup: true + }, + { + api: 'scaleVirtualMachine', + icon: 'arrows-alt-outlined', + label: 'label.vnf.app.action.scale', + docHelp: 'adminguide/virtual_machines.html#how-to-dynamically-scale-cpu-and-ram', + dataView: true, + show: (record) => { return ['Stopped'].includes(record.state) || (['Running'].includes(record.state) && record.hypervisor !== 'LXC') }, + disabled: (record) => { return record.state === 'Running' && !record.isdynamicallyscalable }, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/ScaleVM.vue'))) + }, + { + api: 'migrateVirtualMachine', + icon: 'drag-outlined', + label: 'label.vnf.app.action.migrate.to.host', + docHelp: 'adminguide/virtual_machines.html#moving-vms-between-hosts-manual-live-migration', + dataView: true, + show: (record, store) => { return ['Running'].includes(record.state) && ['Admin'].includes(store.userInfo.roletype) }, + disabled: (record) => { return record.hostcontrolstate === 'Offline' }, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/MigrateWizard.vue'))) + }, + { + api: 'migrateVirtualMachine', + icon: 'drag-outlined', + label: 'label.vnf.app.action.migrate.to.ps', + message: 'message.migrate.instance.to.ps', + docHelp: 'adminguide/virtual_machines.html#moving-vms-between-hosts-manual-live-migration', + dataView: true, + show: (record, store) => { return ['Stopped'].includes(record.state) && ['Admin'].includes(store.userInfo.roletype) }, + disabled: (record) => { return record.hostcontrolstate === 'Offline' }, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/MigrateVMStorage'))), + popup: true + }, + { + api: 'resetPasswordForVirtualMachine', + icon: 'key-outlined', + label: 'label.action.reset.password', + message: 'message.action.instance.reset.password', + dataView: true, + show: (record) => { return ['Stopped'].includes(record.state) && record.passwordenabled }, + response: (result) => { + return { + message: result.virtualmachine && result.virtualmachine.password ? `The password of VM ${result.virtualmachine.displayname} is ${result.virtualmachine.password}` : null, + copybuttontext: result.virtualmachine.password ? 'label.copy.password' : null, + copytext: result.virtualmachine.password ? result.virtualmachine.password : null + } + } + }, + { + api: 'resetSSHKeyForVirtualMachine', + icon: 'lock-outlined', + label: 'label.reset.ssh.key.pair', + message: 'message.desc.reset.ssh.key.pair', + docHelp: 'adminguide/virtual_machines.html#resetting-ssh-keys', + dataView: true, + show: (record) => { return ['Stopped'].includes(record.state) }, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/ResetSshKeyPair'))) + }, + { + api: 'resetUserDataForVirtualMachine', + icon: 'solution-outlined', + label: 'label.reset.userdata.on.vm', + message: 'message.desc.reset.userdata', + docHelp: 'adminguide/virtual_machines.html#resetting-userdata', + dataView: true, + show: (record) => { return ['Stopped'].includes(record.state) }, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/ResetUserData'))) + }, + { + api: 'assignVirtualMachine', + icon: 'user-add-outlined', + label: 'label.assign.instance.another', + dataView: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/AssignInstance'))), + popup: true, + show: (record) => { return ['Stopped'].includes(record.state) } + }, + { + api: 'recoverVirtualMachine', + icon: 'medicine-box-outlined', + label: 'label.vnf.app.action.recover', + message: 'message.recover.vm', + dataView: true, + show: (record, store) => { return ['Destroyed'].includes(record.state) && store.features.allowuserexpungerecovervm } + }, + { + api: 'unmanageVirtualMachine', + icon: 'disconnect-outlined', + label: 'label.action.unmanage.virtualmachine', + message: 'message.action.unmanage.virtualmachine', + dataView: true, + show: (record) => { return ['Running', 'Stopped'].includes(record.state) && record.hypervisor === 'VMware' } + }, + { + api: 'expungeVirtualMachine', + icon: 'delete-outlined', + label: 'label.vnf.app.action.expunge', + message: (record) => { return record.backupofferingid ? 'message.action.expunge.instance.with.backups' : 'message.action.expunge.instance' }, + docHelp: 'adminguide/virtual_machines.html#deleting-vms', + dataView: true, + show: (record, store) => { return ['Destroyed', 'Expunging'].includes(record.state) && store.features.allowuserexpungerecovervm } + }, + { + api: 'destroyVirtualMachine', + icon: 'delete-outlined', + label: 'label.vnf.app.action.destroy', + message: 'message.action.destroy.instance', + docHelp: 'adminguide/virtual_machines.html#deleting-vms', + dataView: true, + groupAction: true, + args: (record, store, group) => { + return (['Admin'].includes(store.userInfo.roletype) || store.features.allowuserexpungerecovervm) + ? ['expunge'] : [] + }, + popup: true, + groupMap: (selection, values) => { return selection.map(x => { return { id: x, expunge: values.expunge } }) }, + show: (record) => { return ['Running', 'Stopped', 'Error'].includes(record.state) }, + component: shallowRef(defineAsyncComponent(() => import('@/views/compute/DestroyVM.vue'))) + } + ] + }, { name: 'publicip', title: 'label.public.ip.addresses', icon: 'environment-outlined', docHelp: 'adminguide/networking_and_traffic.html#reserving-public-ip-addresses-and-vlans-for-accounts', permission: ['listPublicIpAddresses'], + searchFilters: ['ipaddress', 'zoneid', 'account', 'domainid', 'vlanid', 'tags'], resourceType: 'PublicIpAddress', - columns: ['ipaddress', 'state', 'associatednetworkname', 'vpcname', 'virtualmachinename', 'allocated', 'account', 'domain', 'zonename'], + columns: () => { + var fields = ['ipaddress', 'state', 'associatednetworkname', 'vpcname', 'virtualmachinename', 'allocated', 'account'] + if (store.getters.listAllProjects) { + fields.push('project') + } + fields.push(...['domain', 'zonename']) + return fields + }, details: ['ipaddress', 'id', 'associatednetworkname', 'virtualmachinename', 'networkid', 'issourcenat', 'isstaticnat', 'virtualmachinename', 'vmipaddress', 'vlan', 'allocated', 'account', 'domain', 'zonename'], filters: ['allocated', 'reserved', 'free'], component: shallowRef(() => import('@/views/network/PublicIpResource.vue')), @@ -488,7 +922,6 @@ export default { name: 's2svpn', title: 'label.site.to.site.vpn', icon: 'lock-outlined', - hidden: true, permission: ['listVpnGateways'], columns: ['publicip', 'account', 'domain'], details: ['publicip', 'account', 'domain'], @@ -613,6 +1046,11 @@ export default { name: 'loadbalancerinstance', component: shallowRef(defineAsyncComponent(() => import('@/views/network/InternalLBAssignedVmTab.vue'))), show: () => true + }, { + name: 'events', + resourceType: 'LoadBalancerRule', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } }], actions: [ { @@ -713,7 +1151,14 @@ export default { title: 'label.vpncustomergatewayid', icon: 'lock-outlined', permission: ['listVpnCustomerGateways'], - columns: ['name', 'gateway', 'cidrlist', 'ipsecpsk', 'account', 'domain'], + columns: () => { + var fields = ['name', 'gateway', 'cidrlist', 'ipsecpsk', 'account'] + if (store.getters.listAllProjects) { + fields.push('project') + } + fields.push('domain') + return fields + }, details: ['name', 'id', 'gateway', 'cidrlist', 'ipsecpsk', 'ikepolicy', 'ikelifetime', 'ikeversion', 'esppolicy', 'esplifetime', 'dpd', 'splitconnections', 'forceencap', 'account', 'domain'], searchFilters: ['keyword', 'domainid', 'account'], resourceType: 'VPNCustomerGateway', @@ -722,6 +1167,12 @@ export default { name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) }, + { + name: 'events', + resourceType: 'VpnCustomerGateway', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + }, { name: 'comments', component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))) diff --git a/ui/src/config/section/offering.js b/ui/src/config/section/offering.js index c44de61fb79..37973344f65 100644 --- a/ui/src/config/section/offering.js +++ b/ui/src/config/section/offering.js @@ -29,6 +29,7 @@ export default { docHelp: 'adminguide/service_offerings.html#compute-and-disk-service-offerings', icon: 'cloud-outlined', permission: ['listServiceOfferings'], + searchFilters: ['name', 'zoneid', 'domainid', 'cpunumber', 'cpuspeed', 'memory'], params: () => { var params = {} if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { @@ -36,9 +37,10 @@ export default { } return params }, - columns: ['name', 'displaytext', 'cpunumber', 'cpuspeed', 'memory', 'domain', 'zone', 'order'], + filters: ['active', 'inactive'], + columns: ['name', 'displaytext', 'state', 'cpunumber', 'cpuspeed', 'memory', 'domain', 'zone', 'order'], details: () => { - var fields = ['name', 'id', 'displaytext', 'offerha', 'provisioningtype', 'storagetype', 'iscustomized', 'iscustomizediops', 'limitcpuuse', 'cpunumber', 'cpuspeed', 'memory', 'hosttags', 'tags', 'storagetags', 'domain', 'zone', 'created', 'dynamicscalingenabled', 'diskofferingstrictness', 'encryptroot'] + var fields = ['name', 'id', 'displaytext', 'offerha', 'provisioningtype', 'storagetype', 'iscustomized', 'iscustomizediops', 'limitcpuuse', 'cpunumber', 'cpuspeed', 'memory', 'hosttags', 'tags', 'storagetags', 'domain', 'zone', 'created', 'dynamicscalingenabled', 'diskofferingstrictness', 'encryptroot', 'purgeresources'] if (store.getters.apis.createServiceOffering && store.getters.apis.createServiceOffering.params.filter(x => x.name === 'storagepolicy').length > 0) { fields.splice(6, 0, 'vspherestoragepolicy') @@ -47,6 +49,13 @@ export default { store.getters.apis.createServiceOffering.params.filter(x => x.name === 'rootdisksize').length > 0) { fields.splice(12, 0, 'rootdisksize') } + const detailFields = ['minmemory', 'maxmemory', 'mincpunumber', 'maxcpunumber'] + for (const field of detailFields) { + if (store.getters.apis.createServiceOffering && + store.getters.apis.createServiceOffering.params.filter(x => field === x.name).length > 0) { + fields.push(field) + } + } return fields }, resourceType: 'ServiceOffering', @@ -55,6 +64,12 @@ export default { name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) }, + { + name: 'events', + resourceType: 'ServiceOffering', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + }, { name: 'comments', component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))), @@ -89,15 +104,33 @@ export default { dataView: true, popup: true, component: shallowRef(defineAsyncComponent(() => import('@/views/offering/UpdateOfferingAccess.vue'))) + }, + { + api: 'updateServiceOffering', + icon: 'play-circle-outlined', + label: 'label.action.enable.service.offering', + message: 'message.action.enable.service.offering', + dataView: true, + args: ['state'], + mapping: { + state: { + value: (record) => { return 'Active' } + } + }, + groupAction: true, + popup: true, + show: (record) => { return record.state !== 'Active' }, + groupMap: (selection) => { return selection.map(x => { return { id: x, state: 'Active' } }) } }, { api: 'deleteServiceOffering', - icon: 'delete-outlined', - label: 'label.action.delete.service.offering', - message: 'message.action.delete.service.offering', + icon: 'pause-circle-outlined', + label: 'label.action.disable.service.offering', + message: 'message.action.disable.service.offering', docHelp: 'adminguide/service_offerings.html#modifying-or-deleting-a-service-offering', dataView: true, groupAction: true, popup: true, + show: (record) => { return record.state === 'Active' }, groupMap: (selection) => { return selection.map(x => { return { id: x } }) } }] }, @@ -107,9 +140,29 @@ export default { icon: 'setting-outlined', docHelp: 'adminguide/service_offerings.html#system-service-offerings', permission: ['listServiceOfferings', 'listInfrastructure'], + searchFilters: ['name', 'zoneid', 'domainid', 'cpunumber', 'cpuspeed', 'memory'], params: { issystem: 'true', isrecursive: 'true' }, - columns: ['name', 'systemvmtype', 'cpunumber', 'cpuspeed', 'memory', 'storagetype', 'order'], + columns: ['name', 'state', 'systemvmtype', 'cpunumber', 'cpuspeed', 'memory', 'storagetype', 'order'], + filters: ['active', 'inactive'], details: ['name', 'id', 'displaytext', 'systemvmtype', 'provisioningtype', 'storagetype', 'iscustomized', 'limitcpuuse', 'cpunumber', 'cpuspeed', 'memory', 'storagetags', 'hosttags', 'tags', 'domain', 'zone', 'created', 'dynamicscalingenabled', 'diskofferingstrictness'], + resourceType: 'ServiceOffering', + tabs: [ + { + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, + { + name: 'events', + resourceType: 'ServiceOffering', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + }, + { + name: 'comments', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))), + show: (record, route, user) => { return ['Admin', 'DomainAdmin'].includes(user.roletype) } + } + ], actions: [{ api: 'createServiceOffering', icon: 'plus-outlined', @@ -127,16 +180,34 @@ export default { params: { issystem: 'true' }, docHelp: 'adminguide/service_offerings.html#modifying-or-deleting-a-service-offering', args: ['name', 'displaytext', 'storagetags', 'hosttags'] + }, { + api: 'updateServiceOffering', + icon: 'play-circle-outlined', + label: 'label.action.enable.system.service.offering', + message: 'message.action.enable.system.service.offering', + dataView: true, + params: { issystem: 'true' }, + args: ['state'], + mapping: { + state: { + value: (record) => { return 'Active' } + } + }, + groupAction: true, + popup: true, + show: (record) => { return record.state !== 'Active' }, + groupMap: (selection) => { return selection.map(x => { return { id: x, state: 'Active' } }) } }, { api: 'deleteServiceOffering', - icon: 'delete-outlined', - label: 'label.action.delete.system.service.offering', - message: 'message.action.delete.system.service.offering', + icon: 'pause-circle-outlined', + label: 'label.action.disable.system.service.offering', + message: 'message.action.disable.system.service.offering', docHelp: 'adminguide/service_offerings.html#modifying-or-deleting-a-service-offering', dataView: true, params: { issystem: 'true' }, groupAction: true, popup: true, + show: (record) => { return record.state === 'Active' }, groupMap: (selection) => { return selection.map(x => { return { id: x } }) } }] }, @@ -146,6 +217,7 @@ export default { icon: 'hdd-outlined', docHelp: 'adminguide/service_offerings.html#compute-and-disk-service-offerings', permission: ['listDiskOfferings'], + searchFilters: ['name', 'zoneid', 'domainid', 'storageid'], params: () => { var params = {} if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { @@ -153,9 +225,12 @@ export default { } return params }, - columns: ['name', 'displaytext', 'disksize', 'domain', 'zone', 'order'], + columns: ['name', 'displaytext', 'state', 'disksize', 'domain', 'zone', 'order'], + filters: ['active', 'inactive'], details: () => { - var fields = ['name', 'id', 'displaytext', 'disksize', 'provisioningtype', 'storagetype', 'iscustomized', 'disksizestrictness', 'iscustomizediops', 'tags', 'domain', 'zone', 'created', 'encrypt'] + var fields = ['name', 'id', 'displaytext', 'disksize', 'provisioningtype', 'storagetype', 'iscustomized', 'disksizestrictness', 'iscustomizediops', + 'diskIopsReadRate', 'diskIopsWriteRate', 'diskBytesReadRate', 'diskBytesReadRateMax', 'diskBytesWriteRate', 'diskBytesWriteRateMax', 'miniops', 'maxiops', 'tags', + 'domain', 'zone', 'created', 'encrypt'] if (store.getters.apis.createDiskOffering && store.getters.apis.createDiskOffering.params.filter(x => x.name === 'storagepolicy').length > 0) { fields.splice(6, 0, 'vspherestoragepolicy') @@ -168,6 +243,12 @@ export default { name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) }, + { + name: 'events', + resourceType: 'DiskOffering', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + }, { name: 'comments', component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))), @@ -202,15 +283,33 @@ export default { dataView: true, popup: true, component: shallowRef(defineAsyncComponent(() => import('@/views/offering/UpdateOfferingAccess.vue'))) + }, { + api: 'updateDiskOffering', + icon: 'play-circle-outlined', + label: 'label.action.enable.disk.offering', + message: 'message.action.enable.disk.offering', + dataView: true, + params: { issystem: 'true' }, + args: ['state'], + mapping: { + state: { + value: (record) => { return 'Active' } + } + }, + groupAction: true, + popup: true, + show: (record) => { return record.state !== 'Active' }, + groupMap: (selection) => { return selection.map(x => { return { id: x, state: 'Active' } }) } }, { api: 'deleteDiskOffering', - icon: 'delete-outlined', - label: 'label.action.delete.disk.offering', - message: 'message.action.delete.disk.offering', + icon: 'pause-circle-outlined', + label: 'label.action.disable.disk.offering', + message: 'message.action.disable.disk.offering', docHelp: 'adminguide/service_offerings.html#modifying-or-deleting-a-service-offering', dataView: true, groupAction: true, popup: true, + show: (record) => { return record.state === 'Active' }, groupMap: (selection) => { return selection.map(x => { return { id: x } }) } }] }, @@ -220,6 +319,7 @@ export default { icon: 'cloud-upload-outlined', docHelp: 'adminguide/virtual_machines.html#backup-offerings', permission: ['listBackupOfferings'], + searchFilters: ['zoneid'], columns: ['name', 'description', 'zonename'], details: ['name', 'id', 'description', 'externalid', 'zone', 'allowuserdrivenbackups', 'created'], related: [{ @@ -227,6 +327,18 @@ export default { title: 'label.instances', param: 'backupofferingid' }], + tabs: [ + { + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, + { + name: 'events', + resourceType: 'BackupOffering', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + } + ], actions: [{ api: 'importBackupOffering', icon: 'plus-outlined', @@ -261,14 +373,21 @@ export default { icon: 'wifi-outlined', docHelp: 'adminguide/networking.html#network-offerings', permission: ['listNetworkOfferings'], + searchFilters: ['name', 'zoneid', 'domainid', 'tags'], columns: ['name', 'state', 'guestiptype', 'traffictype', 'networkrate', 'domain', 'zone', 'order'], - details: ['name', 'id', 'displaytext', 'guestiptype', 'traffictype', 'internetprotocol', 'networkrate', 'ispersistent', 'egressdefaultpolicy', 'availability', 'conservemode', 'specifyvlan', 'specifyipranges', 'supportspublicaccess', 'supportsstrechedl2subnet', 'service', 'tags', 'domain', 'zone'], + details: ['name', 'id', 'displaytext', 'guestiptype', 'traffictype', 'internetprotocol', 'networkrate', 'ispersistent', 'egressdefaultpolicy', 'availability', 'conservemode', 'specifyvlan', 'specifyipranges', 'supportspublicaccess', 'supportsstrechedl2subnet', 'forvpc', 'fornsx', 'nsxmode', 'service', 'tags', 'domain', 'zone'], resourceType: 'NetworkOffering', tabs: [ { name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) }, + { + name: 'events', + resourceType: 'NetworkOffering', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + }, { name: 'comments', component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))), @@ -353,14 +472,27 @@ export default { icon: 'deployment-unit-outlined', docHelp: 'plugins/nuage-plugin.html?#vpc-offerings', permission: ['listVPCOfferings'], + searchFilters: ['name', 'zoneid', 'domainid'], resourceType: 'VpcOffering', columns: ['name', 'state', 'displaytext', 'domain', 'zone', 'order'], - details: ['name', 'id', 'displaytext', 'internetprotocol', 'distributedvpcrouter', 'tags', 'service', 'domain', 'zone', 'created'], + details: ['name', 'id', 'displaytext', 'internetprotocol', 'distributedvpcrouter', 'tags', 'service', 'fornsx', 'nsxmode', 'domain', 'zone', 'created'], related: [{ name: 'vpc', title: 'label.vpc', param: 'vpcofferingid' }], + tabs: [ + { + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, + { + name: 'events', + resourceType: 'VpcOffering', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + } + ], actions: [{ api: 'createVPCOffering', icon: 'plus-outlined', diff --git a/ui/src/config/section/role.js b/ui/src/config/section/role.js index a040615b9e1..c842b2f68f1 100644 --- a/ui/src/config/section/role.js +++ b/ui/src/config/section/role.js @@ -16,20 +16,28 @@ // under the License. import { shallowRef, defineAsyncComponent } from 'vue' +import store from '@/store' + export default { name: 'role', title: 'label.roles', icon: 'idcard-outlined', docHelp: 'adminguide/accounts.html#roles', permission: ['listRoles', 'listRolePermissions'], + searchFilters: ['name', 'type'], columns: ['name', 'type', 'description'], - details: ['name', 'id', 'type', 'description'], + details: ['name', 'id', 'type', 'description', 'ispublic'], tabs: [{ name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) }, { name: 'rules', component: shallowRef(defineAsyncComponent(() => import('@/views/iam/RolePermissionTab.vue'))) + }, { + name: 'events', + resourceType: 'Role', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } }], actions: [ { @@ -53,7 +61,7 @@ export default { icon: 'edit-outlined', label: 'label.edit.role', dataView: true, - args: ['name', 'description', 'type'], + args: (record) => record.isdefault ? ['ispublic'] : ['name', 'description', 'type', 'ispublic'], mapping: { type: { options: ['Admin', 'DomainAdmin', 'User'] diff --git a/ui/src/config/section/storage.js b/ui/src/config/section/storage.js index c19adc88916..28c451105a1 100644 --- a/ui/src/config/section/storage.js +++ b/ui/src/config/section/storage.js @@ -21,7 +21,7 @@ import store from '@/store' export default { name: 'storage', title: 'label.storage', - icon: 'database-outlined', + icon: 'hdd-outlined', children: [ { name: 'volume', @@ -42,24 +42,22 @@ export default { const metricsFields = ['diskkbsread', 'diskkbswrite', 'diskiopstotal'] if (store.getters.userInfo.roletype === 'Admin') { - metricsFields.push({ - physicalsize: (record) => { - return record.physicalsize ? parseFloat(record.physicalsize / (1024.0 * 1024.0 * 1024.0)).toFixed(2) + 'GB' : '' - } - }) + metricsFields.push('physicalsize') } metricsFields.push('utilization') if (store.getters.metrics) { fields.push(...metricsFields) } - if (store.getters.userInfo.roletype === 'Admin') { - fields.push('account') fields.push('storage') + fields.push('account') } else if (store.getters.userInfo.roletype === 'DomainAdmin') { fields.push('account') } + if (store.getters.listAllProjects) { + fields.push('project') + } fields.push('zonename') return fields @@ -92,7 +90,13 @@ export default { component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))) } ], - searchFilters: ['name', 'zoneid', 'domainid', 'account', 'state', 'tags'], + searchFilters: () => { + var filters = ['name', 'zoneid', 'domainid', 'account', 'state', 'tags', 'serviceofferingid', 'diskofferingid'] + if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { + filters.push('storageid') + } + return filters + }, actions: [ { api: 'createVolume', @@ -162,8 +166,8 @@ export default { dataView: true, show: (record, store) => { return record.state === 'Ready' && (record.hypervisor !== 'KVM' || - record.hypervisor === 'KVM' && record.vmstate === 'Running' && store.features.kvmsnapshotenabled || - record.hypervisor === 'KVM' && record.vmstate !== 'Running') + record.hypervisor === 'KVM' && record.vmstate === 'Running' && store.features.kvmsnapshotenabled || + record.hypervisor === 'KVM' && record.vmstate !== 'Running') }, popup: true, component: shallowRef(defineAsyncComponent(() => import('@/views/storage/TakeSnapshot.vue'))) @@ -176,8 +180,8 @@ export default { dataView: true, show: (record, store) => { return record.state === 'Ready' && (record.hypervisor !== 'KVM' || - record.hypervisor === 'KVM' && record.vmstate === 'Running' && store.features.kvmsnapshotenabled || - record.hypervisor === 'KVM' && record.vmstate !== 'Running') + record.hypervisor === 'KVM' && record.vmstate === 'Running' && store.features.kvmsnapshotenabled || + record.hypervisor === 'KVM' && record.vmstate !== 'Running') }, popup: true, component: shallowRef(defineAsyncComponent(() => import('@/views/storage/RecurringSnapshotVolume.vue'))), @@ -248,10 +252,23 @@ export default { dataView: true, show: (record) => { return !['Destroy', 'Destroyed', 'Expunging', 'Expunged', 'Migrating', 'Uploading', 'UploadError', 'Creating'].includes(record.state) && - ((record.type === 'ROOT' && record.vmstate === 'Stopped') || - (record.type !== 'ROOT' && !record.virtualmachineid && !['Allocated', 'Uploaded'].includes(record.state))) + ((record.type === 'ROOT' && record.vmstate === 'Stopped') || + (record.type !== 'ROOT' && !record.virtualmachineid && !['Allocated', 'Uploaded'].includes(record.state))) + }, + args: (record, store) => { + var fields = ['volumeid', 'name', 'displaytext', 'ostypeid', 'isdynamicallyscalable', 'requireshvm', 'passwordenabled'] + if (['Admin', 'DomainAdmin'].includes(store.userInfo.roletype)) { + fields.push('domainid') + fields.push('account') + } + if (['Admin'].includes(store.userInfo.roletype) || store.features.userpublictemplateenabled) { + fields.push('ispublic') + } + if (['Admin'].includes(store.userInfo.roletype)) { + fields.push('isfeatured') + } + return fields }, - args: ['volumeid', 'name', 'displaytext', 'ostypeid', 'ispublic', 'isfeatured', 'isdynamicallyscalable', 'requireshvm', 'passwordenabled'], mapping: { volumeid: { value: (record) => { return record.id } @@ -276,8 +293,8 @@ export default { dataView: true, show: (record, store) => { return ['Expunging', 'Expunged', 'UploadError'].includes(record.state) || - ['Allocated', 'Uploaded'].includes(record.state) && record.type !== 'ROOT' && !record.virtualmachineid || - ((['Admin', 'DomainAdmin'].includes(store.userInfo.roletype) || store.features.allowuserexpungerecovervolume) && record.state === 'Destroy') + ['Allocated', 'Uploaded'].includes(record.state) && record.type !== 'ROOT' && !record.virtualmachineid || + ((['Admin', 'DomainAdmin'].includes(store.userInfo.roletype) || store.features.allowuserexpungerecovervolume) && record.state === 'Destroy') }, groupAction: true, popup: true, @@ -311,7 +328,12 @@ export default { var fields = ['name', 'state', 'volumename', 'intervaltype', 'physicalsize', 'created'] if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { fields.push('account') + if (store.getters.listAllProjects) { + fields.push('project') + } fields.push('domain') + } else if (store.getters.listAllProjects) { + fields.push('project') } fields.push('zonename') return fields @@ -322,12 +344,29 @@ export default { name: 'details', component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) }, + { + name: 'zones', + component: shallowRef(defineAsyncComponent(() => import('@/views/storage/SnapshotZones.vue'))) + }, + { + name: 'events', + resourceType: 'Snapshot', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + }, { name: 'comments', component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))) } ], - searchFilters: ['name', 'domainid', 'account', 'tags'], + searchFilters: () => { + var filters = ['name', 'domainid', 'account', 'tags', 'zoneid'] + if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { + filters.push('storageid') + filters.push('imagestoreid') + } + return filters + }, actions: [ { api: 'createTemplate', @@ -335,12 +374,8 @@ export default { label: 'label.create.template', dataView: true, show: (record) => { return record.state === 'BackedUp' }, - args: ['snapshotid', 'name', 'displaytext', 'ostypeid', 'ispublic', 'isfeatured', 'isdynamicallyscalable', 'requireshvm', 'passwordenabled'], - mapping: { - snapshotid: { - value: (record) => { return record.id } - } - } + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/storage/CreateTemplate.vue'))) }, { api: 'createVolume', @@ -372,77 +407,6 @@ export default { } ] }, - { - name: 'vmsnapshot', - title: 'label.vm.snapshots', - icon: 'camera-outlined', - docHelp: 'adminguide/storage.html#working-with-volume-snapshots', - permission: ['listVMSnapshot'], - resourceType: 'VMSnapshot', - columns: () => { - const fields = ['displayname', 'state', 'name', 'type', 'current', 'parentName', 'created'] - if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { - fields.push('account') - fields.push('domain') - } - return fields - }, - details: ['name', 'id', 'displayname', 'description', 'type', 'current', 'parentName', 'virtualmachineid', 'account', 'domain', 'created'], - searchFilters: ['name', 'domainid', 'account', 'tags'], - tabs: [ - { - name: 'details', - component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) - }, - { - name: 'comments', - component: shallowRef(defineAsyncComponent(() => import('@/components/view/AnnotationsTab.vue'))) - } - ], - actions: [ - { - api: 'createSnapshotFromVMSnapshot', - icon: 'camera-outlined', - label: 'label.action.create.snapshot.from.vmsnapshot', - message: 'message.action.create.snapshot.from.vmsnapshot', - dataView: true, - popup: true, - show: (record) => { return (record.state === 'Ready' && record.hypervisor === 'KVM') }, - component: shallowRef(defineAsyncComponent(() => import('@/views/storage/CreateSnapshotFromVMSnapshot.vue'))) - }, - { - api: 'revertToVMSnapshot', - icon: 'sync-outlined', - label: 'label.action.vmsnapshot.revert', - message: 'label.action.vmsnapshot.revert', - dataView: true, - show: (record) => { return record.state === 'Ready' }, - args: ['vmsnapshotid'], - mapping: { - vmsnapshotid: { - value: (record) => { return record.id } - } - } - }, - { - api: 'deleteVMSnapshot', - icon: 'delete-outlined', - label: 'label.action.vmsnapshot.delete', - message: 'message.action.vmsnapshot.delete', - dataView: true, - show: (record) => { return ['Ready', 'Expunging', 'Error'].includes(record.state) }, - args: ['vmsnapshotid'], - mapping: { - vmsnapshotid: { - value: (record) => { return record.id } - } - }, - groupAction: true, - popup: true, - groupMap: (selection) => { return selection.map(x => { return { vmsnapshotid: x } }) } - } - ] - }, { name: 'backup', title: 'label.backup', @@ -493,7 +457,70 @@ export default { label: 'label.delete.backup', message: 'message.delete.backup', dataView: true, + show: (record) => { return record.state !== 'Destroyed' }, + groupAction: true, + popup: true, + groupMap: (selection, values) => { return selection.map(x => { return { id: x, forced: values.forced } }) }, + args: ['forced'] + } + ] + }, + { + name: 'buckets', + title: 'label.buckets', + icon: 'funnel-plot-outlined', + permission: ['listBuckets'], + columns: ['name', 'state', 'objectstore', 'size', 'account'], + details: ['id', 'name', 'state', 'objectstore', 'size', 'url', 'accesskey', 'usersecretkey', 'account', 'domain', 'created', 'quota', 'encryption', 'versioning', 'objectlocking', 'policy'], + tabs: [ + { + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, + { + name: 'browser', + resourceType: 'Bucket', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/ObjectStoreBrowser.vue'))), + show: (record) => { return record.provider !== 'Simulator' } + + }, + { + name: 'events', + resourceType: 'Bucket', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/EventsTab.vue'))), + show: () => { return 'listEvents' in store.getters.apis } + } + ], + actions: [ + { + api: 'createBucket', + icon: 'plus-outlined', + docHelp: 'installguide/configuration.html#create-bucket', + label: 'label.create.bucket', + listView: true, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/storage/CreateBucket.vue'))) + }, + { + api: 'updateBucket', + icon: 'edit-outlined', + docHelp: 'adminguide/object_storage.html#update-bucket', + label: 'label.bucket.update', + dataView: true, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/storage/UpdateBucket.vue'))), show: (record) => { return record.state !== 'Destroyed' } + }, + { + api: 'deleteBucket', + icon: 'delete-outlined', + label: 'label.bucket.delete', + message: 'message.bucket.delete', + dataView: true, + show: (record) => { return record.state !== 'Destroyed' }, + groupAction: true, + popup: true, + groupMap: (selection) => { return selection.map(x => { return { id: x } }) } } ] } diff --git a/ui/src/config/section/tools.js b/ui/src/config/section/tools.js index a04563c477a..a07228ca87b 100644 --- a/ui/src/config/section/tools.js +++ b/ui/src/config/section/tools.js @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. import store from '@/store' +import { shallowRef, defineAsyncComponent } from 'vue' export default { name: 'tools', @@ -60,6 +61,14 @@ export default { } ] }, + { + name: 'usage', + title: 'label.usage', + icon: 'ContainerOutlined', + permission: ['listUsageRecords'], + meta: { title: 'label.usage', icon: 'ContainerOutlined' }, + component: () => import('@/views/infra/UsageRecords.vue') + }, { name: 'manageinstances', title: 'label.action.import.export.instances', @@ -68,6 +77,163 @@ export default { resourceType: 'UserVm', permission: ['listInfrastructure', 'listUnmanagedInstances'], component: () => import('@/views/tools/ManageInstances.vue') + }, + { + name: 'managevolumes', + title: 'label.action.import.unmanage.volumes', + icon: 'interaction-outlined', + docHelp: 'adminguide/virtual_machines.html#importing-and-unmanaging-volume', + resourceType: 'UserVm', + permission: ['listInfrastructure', 'listVolumesForImport'], + component: () => import('@/views/tools/ManageVolumes.vue') + }, + { + name: 'webhook', + title: 'label.webhooks', + icon: 'node-index-outlined', + docHelp: 'adminguide/webhooks.html', + permission: ['listWebhooks'], + columns: () => { + const cols = ['name', 'payloadurl', 'state', 'created'] + if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { + cols.splice(3, 0, 'account', 'domain', 'scope') + } + if (store.getters.listAllProjects) { + cols.push('project') + } + return cols + }, + details: ['name', 'id', 'description', 'scope', 'payloadurl', 'sslverification', 'secretkey', 'state', 'account', 'domainid'], + searchFilters: () => { + var filters = ['state'] + if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { + filters.push('scope', 'domainid', 'account') + } + return filters + }, + tabs: [ + { + name: 'details', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue'))) + }, + { + name: 'recent.deliveries', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/WebhookDeliveriesTab.vue'))) + } + ], + actions: [ + { + api: 'createWebhook', + icon: 'plus-outlined', + label: 'label.create.webhook', + docHelp: 'adminguide/events.html#creating-webhooks', + listView: true, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/tools/CreateWebhook.vue'))) + }, + { + api: 'updateWebhook', + icon: 'edit-outlined', + label: 'label.update.webhook', + dataView: true, + popup: true, + args: ['name', 'description', 'payloadurl', 'sslverification', 'secretkey', 'state'], + mapping: { + state: { + options: ['Enabled', 'Disabled'] + } + } + }, + { + api: 'updateWebhook', + icon: 'play-circle-outlined', + label: 'label.enable.webhook', + message: 'message.confirm.enable.webhook', + dataView: true, + groupAction: true, + popup: true, + defaultArgs: { state: 'Enabled' }, + groupMap: (selection) => { return selection.map(x => { return { id: x } }) }, + show: (record) => { return ['Disabled'].includes(record.state) } + }, + { + api: 'updateWebhook', + icon: 'pause-circle-outlined', + label: 'label.disable.webhook', + message: 'message.confirm.disable.webhook', + dataView: true, + groupAction: true, + popup: true, + defaultArgs: { state: 'Disabled' }, + groupMap: (selection) => { return selection.map(x => { return { id: x } }) }, + show: (record) => { return ['Enabled'].includes(record.state) } + }, + { + api: 'executeWebhookDelivery', + icon: 'right-square-outlined', + label: 'label.test.webhook.delivery', + message: 'message.test.webhook.delivery', + dataView: true, + popup: true, + component: shallowRef(defineAsyncComponent(() => import('@/views/tools/TestWebhookDelivery.vue'))) + }, + { + api: 'deleteWebhook', + icon: 'delete-outlined', + label: 'label.delete.webhook', + message: 'message.delete.webhook', + dataView: true, + groupAction: true, + popup: true, + groupShow: (selectedItems, storegetters) => { + if (['Admin'].includes(storegetters.userInfo.roletype)) { + return true + } + }, + groupMap: (selection) => { return selection.map(x => { return { id: x } }) } + } + ] + }, + { + name: 'webhookdeliveries', + title: 'label.webhook.deliveries', + icon: 'gateway-outlined', + hidden: true, + permission: ['listWebhookDeliveries'], + columns: () => { + const cols = ['payload', 'eventtype', 'webhookname', 'success', 'response', 'duration'] + if (['Admin'].includes(store.getters.userInfo.roletype)) { + cols.splice(3, 0, 'managementservername') + } + return cols + }, + details: () => { + const fields = ['id', 'eventid', 'eventtype', 'headers', 'payload', 'success', 'response', 'startdate', 'enddate'] + if (['Admin'].includes(store.getters.userInfo.roletype)) { + fields.splice(1, 0, 'managementserverid', 'managementservername') + } + return fields + }, + actions: [ + { + api: 'executeWebhookDelivery', + icon: 'retweet-outlined', + label: 'label.redeliver', + message: 'message.redeliver.webhook.delivery', + dataView: true, + popup: true + }, + { + api: 'deleteWebhookDelivery', + icon: 'delete-outlined', + label: 'label.delete.webhook.delivery', + message: 'message.delete.webhook.delivery', + dataView: true, + groupAction: true, + popup: true, + groupMap: (selection) => { return selection.map(x => { return { id: x } }) } + } + ] } ] } diff --git a/ui/src/config/section/user.js b/ui/src/config/section/user.js index eef9ea3f939..d8c4ac06d0c 100644 --- a/ui/src/config/section/user.js +++ b/ui/src/config/section/user.js @@ -25,7 +25,7 @@ export default { docHelp: 'adminguide/accounts.html#users', hidden: true, permission: ['listUsers'], - columns: ['username', 'state', 'firstname', 'lastname', 'email', 'account'], + columns: ['username', 'state', 'firstname', 'lastname', 'email', 'account', 'domain'], details: ['username', 'id', 'firstname', 'lastname', 'email', 'usersource', 'timezone', 'rolename', 'roletype', 'is2faenabled', 'account', 'domain', 'created'], tabs: [ { @@ -81,7 +81,7 @@ export default { show: (record, store) => { return ['Admin', 'DomainAdmin'].includes(store.userInfo.roletype) && !record.isdefault && !(record.domain === 'ROOT' && record.account === 'admin' && record.accounttype === 1) && - record.state === 'disabled' + ['disabled', 'locked'].includes(record.state) } }, { @@ -96,6 +96,20 @@ export default { record.state === 'enabled' } }, + { + api: 'lockUser', + icon: 'LockOutlined', + label: 'label.action.lock.user', + message: (record) => ['message.lock.user', { user: record.username }], + successMessage: (record) => ['message.lock.user.success', { user: record.username }], + dataView: true, + popup: true, + show: (record, store) => { + return ['Admin', 'DomainAdmin'].includes(store.userInfo.roletype) && !record.isdefault && + !(record.domain === 'ROOT' && record.account === 'admin' && record.accounttype === 1) && + record.state === 'enabled' + } + }, { api: 'authorizeSamlSso', icon: 'form-outlined', diff --git a/ui/src/core/ext.js b/ui/src/core/ext.js index 3cea5189583..f6cfb353b13 100644 --- a/ui/src/core/ext.js +++ b/ui/src/core/ext.js @@ -22,11 +22,11 @@ import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' // import { fas } from '@fortawesome/free-solid-svg-icons' // import { far } from '@fortawesome/free-regular-svg-icons' -import { faCentos, faUbuntu, faSuse, faRedhat, faFedora, faLinux, faFreebsd, faApple, faWindows, faJava } from '@fortawesome/free-brands-svg-icons' -import { faCompactDisc, faCameraRetro } from '@fortawesome/free-solid-svg-icons' +import { faCentos, faUbuntu, faDebian, faSuse, faRedhat, faFedora, faLinux, faFreebsd, faApple, faWindows, faJava } from '@fortawesome/free-brands-svg-icons' +import { faCompactDisc, faCameraRetro, faDharmachakra } from '@fortawesome/free-solid-svg-icons' -library.add(faCentos, faUbuntu, faSuse, faRedhat, faFedora, faLinux, faFreebsd, faApple, faWindows, faJava) -library.add(faCompactDisc, faCameraRetro) +library.add(faCentos, faUbuntu, faDebian, faSuse, faRedhat, faFedora, faLinux, faFreebsd, faApple, faWindows, faJava) +library.add(faCompactDisc, faCameraRetro, faDharmachakra) export default { install: (app) => { diff --git a/ui/src/core/lazy_lib/components_use.js b/ui/src/core/lazy_lib/components_use.js index 1c2e8ee2cd8..3ee5d07a49d 100644 --- a/ui/src/core/lazy_lib/components_use.js +++ b/ui/src/core/lazy_lib/components_use.js @@ -61,9 +61,11 @@ import { Tree, Calendar, Slider, + Result, AutoComplete, Collapse, - Space + Space, + Statistic } from 'ant-design-vue' import VueClipboard from 'vue3-clipboard' import VueCropper from 'vue-cropper' @@ -131,5 +133,7 @@ export default { app.use(Collapse) app.use(Descriptions) app.use(Space) + app.use(Statistic) + app.use(Result) } } diff --git a/ui/src/core/lazy_lib/icons_use.js b/ui/src/core/lazy_lib/icons_use.js index 0a95facdd9d..d877fe8bf23 100644 --- a/ui/src/core/lazy_lib/icons_use.js +++ b/ui/src/core/lazy_lib/icons_use.js @@ -21,6 +21,7 @@ import { ApiOutlined, AppstoreOutlined, ArrowDownOutlined, + ArrowRightOutlined, ArrowUpOutlined, ArrowsAltOutlined, AuditOutlined, @@ -55,6 +56,7 @@ import { ClusterOutlined, CodeOutlined, CompassOutlined, + ContainerOutlined, ControlOutlined, CopyOutlined, CreditCardOutlined, @@ -73,10 +75,12 @@ import { DragOutlined, EditOutlined, EnvironmentOutlined, + ExceptionOutlined, ExclamationCircleOutlined, EyeInvisibleOutlined, EyeOutlined, FieldTimeOutlined, + FileDoneOutlined, FileProtectOutlined, FilterOutlined, FilterTwoTone, @@ -88,6 +92,7 @@ import { FormOutlined, ForwardOutlined, FullscreenOutlined, + FunnelPlotOutlined, GatewayOutlined, GithubOutlined, GlobalOutlined, @@ -117,6 +122,7 @@ import { MinusSquareOutlined, MobileOutlined, MoreOutlined, + NodeIndexOutlined, NotificationOutlined, NumberOutlined, LaptopOutlined, @@ -136,7 +142,9 @@ import { ReconciliationOutlined, RedoOutlined, ReloadOutlined, + RetweetOutlined, RightCircleOutlined, + RightSquareOutlined, RocketOutlined, SafetyCertificateOutlined, SafetyOutlined, @@ -164,6 +172,8 @@ import { UserOutlined, UserSwitchOutlined, UploadOutlined, + VerticalAlignBottomOutlined, + VerticalAlignTopOutlined, WarningOutlined, WifiOutlined, SolutionOutlined @@ -177,6 +187,7 @@ export default { app.component('ApiOutlined', ApiOutlined) app.component('AppstoreOutlined', AppstoreOutlined) app.component('ArrowDownOutlined', ArrowDownOutlined) + app.component('ArrowRightOutlined', ArrowRightOutlined) app.component('ArrowUpOutlined', ArrowUpOutlined) app.component('ArrowsAltOutlined', ArrowsAltOutlined) app.component('AuditOutlined', AuditOutlined) @@ -210,6 +221,7 @@ export default { app.component('CloudUploadOutlined', CloudUploadOutlined) app.component('ClusterOutlined', ClusterOutlined) app.component('CodeOutlined', CodeOutlined) + app.component('ContainerOutlined', ContainerOutlined) app.component('ControlOutlined', ControlOutlined) app.component('CompassOutlined', CompassOutlined) app.component('CopyOutlined', CopyOutlined) @@ -229,10 +241,12 @@ export default { app.component('DragOutlined', DragOutlined) app.component('EditOutlined', EditOutlined) app.component('EnvironmentOutlined', EnvironmentOutlined) + app.component('ExceptionOutlined', ExceptionOutlined) app.component('ExclamationCircleOutlined', ExclamationCircleOutlined) app.component('EyeInvisibleOutlined', EyeInvisibleOutlined) app.component('EyeOutlined', EyeOutlined) app.component('FieldTimeOutlined', FieldTimeOutlined) + app.component('FileDoneOutlined', FileDoneOutlined) app.component('FileProtectOutlined', FileProtectOutlined) app.component('FilterOutlined', FilterOutlined) app.component('FilterTwoTone', FilterTwoTone) @@ -244,6 +258,7 @@ export default { app.component('FormOutlined', FormOutlined) app.component('ForwardOutlined', ForwardOutlined) app.component('FullscreenOutlined', FullscreenOutlined) + app.component('FunnelPlotOutlined', FunnelPlotOutlined) app.component('GatewayOutlined', GatewayOutlined) app.component('GithubOutlined', GithubOutlined) app.component('GlobalOutlined', GlobalOutlined) @@ -273,6 +288,7 @@ export default { app.component('MinusSquareOutlined', MinusSquareOutlined) app.component('MobileOutlined', MobileOutlined) app.component('MoreOutlined', MoreOutlined) + app.component('NodeIndexOutlined', NodeIndexOutlined) app.component('NotificationOutlined', NotificationOutlined) app.component('NumberOutlined', NumberOutlined) app.component('LaptopOutlined', LaptopOutlined) @@ -292,7 +308,9 @@ export default { app.component('ReconciliationOutlined', ReconciliationOutlined) app.component('RedoOutlined', RedoOutlined) app.component('ReloadOutlined', ReloadOutlined) + app.component('RetweetOutlined', RetweetOutlined) app.component('RightCircleOutlined', RightCircleOutlined) + app.component('RightSquareOutlined', RightSquareOutlined) app.component('RocketOutlined', RocketOutlined) app.component('SafetyCertificateOutlined', SafetyCertificateOutlined) app.component('SafetyOutlined', SafetyOutlined) @@ -320,6 +338,8 @@ export default { app.component('UserOutlined', UserOutlined) app.component('UserSwitchOutlined', UserSwitchOutlined) app.component('UploadOutlined', UploadOutlined) + app.component('VerticalAlignBottomOutlined', VerticalAlignBottomOutlined) + app.component('VerticalAlignTopOutlined', VerticalAlignTopOutlined) app.component('WarningOutlined', WarningOutlined) app.component('WifiOutlined', WifiOutlined) app.component('renderIcon', renderIcon) diff --git a/ui/src/permission.js b/ui/src/permission.js index b780073a8ba..4380c7660d8 100644 --- a/ui/src/permission.js +++ b/ui/src/permission.js @@ -30,7 +30,7 @@ import { ACCESS_TOKEN, APIS, SERVER_MANAGER, CURRENT_PROJECT } from '@/store/mut NProgress.configure({ showSpinner: false }) // NProgress Configuration -const allowList = ['login'] // no redirect allowlist +const allowList = ['login', 'VerifyOauth'] // no redirect allowlist router.beforeEach((to, from, next) => { // start progress bar @@ -56,6 +56,14 @@ router.beforeEach((to, from, next) => { const validLogin = vueProps.$localStorage.get(ACCESS_TOKEN) || Cookies.get('userid') || Cookies.get('userid', { path: '/client' }) if (validLogin) { + var currentURL = new URL(window.location.href) + var urlParams = new URLSearchParams(currentURL.search) + var code = urlParams.get('code') + if (code != null) { + urlParams.delete('code') + } + currentURL.search = '' + window.history.replaceState(null, null, currentURL.toString()) if (to.path === '/user/login') { next({ path: '/dashboard' }) NProgress.done() @@ -104,7 +112,11 @@ router.beforeEach((to, from, next) => { } else { next({ path: redirect }) } - const project = vueProps.$localStorage.get(CURRENT_PROJECT) + var project = vueProps.$localStorage.get(CURRENT_PROJECT) + if (project == null) { + project = {} + store.commit('SET_PROJECT', project) + } store.dispatch('ToggleTheme', project.id === undefined ? 'light' : 'dark') }) }) @@ -134,7 +146,16 @@ router.beforeEach((to, from, next) => { } } } else { - if (allowList.includes(to.name)) { + if (window.location.href.includes('verifyOauth') && to.name === undefined) { + currentURL = new URL(window.location.href) + urlParams = new URLSearchParams(currentURL.search) + code = urlParams.get('code') + urlParams.delete('verifyOauth') + urlParams.delete('state') + currentURL.search = '?code=' + code + window.history.replaceState(null, null, currentURL.toString()) + next({ path: '/verifyOauth', query: { redirect: to.fullPath } }) + } else if (allowList.includes(to.name)) { next() } else { next({ path: '/user/login', query: { redirect: to.fullPath } }) diff --git a/ui/src/store/getters.js b/ui/src/store/getters.js index b0c4ecdfccd..67b168be8c2 100644 --- a/ui/src/store/getters.js +++ b/ui/src/store/getters.js @@ -50,7 +50,8 @@ const getters = { twoFaIssuer: state => state.user.twoFaIssuer, loginFlag: state => state.user.loginFlag, allProjects: (state) => state.app.allProjects, - customHypervisorName: state => state.user.customHypervisorName + customHypervisorName: state => state.user.customHypervisorName, + readyForShutdownPollingJob: state => state.user.readyForShutdownPollingJob } export default getters diff --git a/ui/src/store/modules/app.js b/ui/src/store/modules/app.js index b3130b68d61..cf2b34e4b8e 100644 --- a/ui/src/store/modules/app.js +++ b/ui/src/store/modules/app.js @@ -130,6 +130,9 @@ const app = { }, SET_SHUTDOWN_TRIGGERED: (state, shutdownTriggered) => { state.shutdownTriggered = shutdownTriggered + }, + SET_READY_FOR_SHUTDOWN_POLLING_JOB: (state, readyForShutdownPollingJob) => { + state.readyForShutdownPollingJob = readyForShutdownPollingJob } }, actions: { @@ -192,6 +195,9 @@ const app = { }, SetShutdownTriggered ({ commit }, bool) { commit('SET_SHUTDOWN_TRIGGERED', bool) + }, + SetReadyForShutdownPollingJob ({ commit }, job) { + commit('SET_READY_FOR_SHUTDOWN_POLLING_JOB', job) } } } diff --git a/ui/src/store/modules/permission.js b/ui/src/store/modules/permission.js index 3b080be5f63..ad11fe5a8d0 100644 --- a/ui/src/store/modules/permission.js +++ b/ui/src/store/modules/permission.js @@ -17,24 +17,39 @@ import { asyncRouterMap, constantRouterMap } from '@/config/router' -function hasApi (apis, route) { - if (route.meta && route.meta.permission) { - for (const permission of route.meta.permission) { - if (!apis.includes(permission)) { - return false - } - } +function hasAccessToRoute (apis, route) { + if (!route.meta || !route.meta.permission) { return true } + for (const permission of route.meta.permission) { + if (!apis.includes(permission)) { + return false + } + } + return true +} + +function hasAccessToSection (route) { + const visibleChildren = route.children.filter(child => !child.hidden) + if (visibleChildren.length === 0) { + return false + } + const redirect = '/' + visibleChildren[0].meta.name + if (redirect !== route.path) { + route.redirect = redirect + } return true } function filterAsyncRouter (routerMap, apis) { const accessedRouters = routerMap.filter(route => { - if (hasApi(apis, route)) { + if (hasAccessToRoute(apis, route)) { if (route.children && route.children.length > 0) { route.children = filterAsyncRouter(route.children, apis) } + if (route.meta && route.meta.section) { + return hasAccessToSection(route) + } return true } return false diff --git a/ui/src/store/modules/user.js b/ui/src/store/modules/user.js index 6a3ba217baf..24302a94033 100644 --- a/ui/src/store/modules/user.js +++ b/ui/src/store/modules/user.js @@ -22,7 +22,7 @@ import notification from 'ant-design-vue/es/notification' import { vueProps } from '@/vue-app' import router from '@/router' import store from '@/store' -import { login, logout, api } from '@/api' +import { oauthlogin, login, logout, api } from '@/api' import { i18n } from '@/locales' import { @@ -36,7 +36,9 @@ import { HEADER_NOTICES, DOMAIN_STORE, DARK_MODE, - CUSTOM_COLUMNS + CUSTOM_COLUMNS, + OAUTH_DOMAIN, + OAUTH_PROVIDER } from '@/store/mutation-types' const user = { @@ -65,7 +67,8 @@ const user = { twoFaEnabled: false, twoFaProvider: '', twoFaIssuer: '', - customHypervisorName: 'Custom' + customHypervisorName: 'Custom', + readyForShutdownPollingJob: '' }, mutations: { @@ -155,6 +158,15 @@ const user = { }, SET_CUSTOM_HYPERVISOR_NAME (state, name) { state.customHypervisorName = name + }, + SET_READY_FOR_SHUTDOWN_POLLING_JOB: (state, job) => { + state.readyForShutdownPollingJob = job + }, + SET_DOMAIN_USED_TO_LOGIN: (state, domain) => { + vueProps.$localStorage.set(OAUTH_DOMAIN, domain) + }, + SET_OAUTH_PROVIDER_USED_TO_LOGIN: (state, provider) => { + vueProps.$localStorage.set(OAUTH_PROVIDER, provider) } }, @@ -209,6 +221,53 @@ const user = { }) }, + OauthLogin ({ commit }, userInfo) { + return new Promise((resolve, reject) => { + oauthlogin(userInfo).then(response => { + const result = response.loginresponse || {} + Cookies.set('account', result.account, { expires: 1 }) + Cookies.set('domainid', result.domainid, { expires: 1 }) + Cookies.set('role', result.type, { expires: 1 }) + Cookies.set('timezone', result.timezone, { expires: 1 }) + Cookies.set('timezoneoffset', result.timezoneoffset, { expires: 1 }) + Cookies.set('userfullname', result.firstname + ' ' + result.lastname, { expires: 1 }) + Cookies.set('userid', result.userid, { expires: 1 }) + Cookies.set('username', result.username, { expires: 1 }) + vueProps.$localStorage.set(ACCESS_TOKEN, result.sessionkey, 24 * 60 * 60 * 1000) + commit('SET_TOKEN', result.sessionkey) + commit('SET_TIMEZONE_OFFSET', result.timezoneoffset) + + const cachedUseBrowserTimezone = vueProps.$localStorage.get(USE_BROWSER_TIMEZONE, false) + commit('SET_USE_BROWSER_TIMEZONE', cachedUseBrowserTimezone) + const darkMode = vueProps.$localStorage.get(DARK_MODE, false) + commit('SET_DARK_MODE', darkMode) + const cachedCustomColumns = vueProps.$localStorage.get(CUSTOM_COLUMNS, {}) + commit('SET_CUSTOM_COLUMNS', cachedCustomColumns) + + commit('SET_APIS', {}) + commit('SET_NAME', '') + commit('SET_AVATAR', '') + commit('SET_INFO', {}) + commit('SET_PROJECT', {}) + commit('SET_HEADER_NOTICES', []) + commit('SET_FEATURES', {}) + commit('SET_LDAP', {}) + commit('SET_CLOUDIAN', {}) + commit('SET_DOMAIN_STORE', {}) + commit('SET_LOGOUT_FLAG', false) + commit('SET_2FA_ENABLED', (result.is2faenabled === 'true')) + commit('SET_2FA_PROVIDER', result.providerfor2fa) + commit('SET_2FA_ISSUER', result.issuerfor2fa) + commit('SET_LOGIN_FLAG', false) + notification.destroy() + + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + GetInfo ({ commit }, switchDomain) { return new Promise((resolve, reject) => { const cachedApis = switchDomain ? {} : vueProps.$localStorage.get(APIS, {}) @@ -255,7 +314,10 @@ const user = { const apiName = api.name apis[apiName] = { params: api.params, - response: api.response + response: api.response, + isasync: api.isasync, + since: api.since, + description: api.description } } commit('SET_APIS', apis) diff --git a/ui/src/store/mutation-types.js b/ui/src/store/mutation-types.js index 0fe4a104958..77aeb8fb7b6 100644 --- a/ui/src/store/mutation-types.js +++ b/ui/src/store/mutation-types.js @@ -38,6 +38,8 @@ export const DARK_MODE = 'DARK_MODE' export const VUE_VERSION = 'VUE_VERSION' export const CUSTOM_COLUMNS = 'CUSTOM_COLUMNS' export const RELOAD_ALL_PROJECTS = 'RELOAD_ALL_PROJECTS' +export const OAUTH_DOMAIN = 'OAUTH_DOMAIN' +export const OAUTH_PROVIDER = 'OAUTH_PROVIDER' export const CONTENT_WIDTH_TYPE = { Fluid: 'Fluid', diff --git a/ui/src/style/dark-mode.less b/ui/src/style/dark-mode.less index 5ff6d5dd403..608e147df12 100644 --- a/ui/src/style/dark-mode.less +++ b/ui/src/style/dark-mode.less @@ -36,7 +36,7 @@ .dark-mode { background: @dark-bgColor; - h1, h2, h3, h4, h5, h6 { + h1, h2, h3, h4, h5, h6, .ant-statistic-title, .ant-statistic-content { color: @dark-text-color-3; } diff --git a/ui/src/style/vars.less b/ui/src/style/vars.less index b80e2b0914e..de2d494c878 100644 --- a/ui/src/style/vars.less +++ b/ui/src/style/vars.less @@ -471,6 +471,10 @@ a { width: auto; } +.ant-list-item.selected-item { + background-color: @primary-color-light; +} + .ant-select-arrow .anticon { vertical-align: top; } @@ -519,6 +523,11 @@ a { padding: 16px; } +.ant-tabs-left>.ant-tabs-nav .ant-tabs-tab { + padding: 8px 24px 8px 8px; + text-align: center; +} + .ant-steps { &-item-container { &:hover { diff --git a/ui/src/utils/device.js b/ui/src/utils/device.js index ce6deab7b39..86c7b1e7d84 100644 --- a/ui/src/utils/device.js +++ b/ui/src/utils/device.js @@ -43,7 +43,7 @@ export const deviceEnquire = function (callback) { } enquireJs - .register('screen and (max-width: 800px)', matchMobile) - .register('screen and (min-width: 800px) and (max-width: 1366px)', matchTablet) - .register('screen and (min-width: 1367px)', matchDesktop) + .register('screen and (max-width: 765px)', matchMobile) + .register('screen and (min-width: 766px) and (max-width: 1279px)', matchTablet) + .register('screen and (min-width: 1280px)', matchDesktop) } diff --git a/ui/src/utils/links.js b/ui/src/utils/links.js new file mode 100644 index 00000000000..fa650cdd7b8 --- /dev/null +++ b/ui/src/utils/links.js @@ -0,0 +1,36 @@ +// 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. + +export function validateLinks (router, isStatic, resource) { + const validLinks = { + volume: false + } + + if (isStatic) { + return validLinks + } + + if (resource.volumeid && router.resolve('/volume/' + resource.volumeid).matched[0].redirect !== '/exception/404') { + if (resource.volumestate) { + validLinks.volume = resource.volumestate !== 'Expunged' + } else { + validLinks.volume = true + } + } + + return validLinks +} diff --git a/ui/src/utils/plugins.js b/ui/src/utils/plugins.js index 7223f050368..d93c8796659 100644 --- a/ui/src/utils/plugins.js +++ b/ui/src/utils/plugins.js @@ -390,6 +390,10 @@ export const resourceTypePlugin = { return 'publicip' case 'NetworkAcl': return 'acllist' + case 'KubernetesCluster': + return 'kubernetes' + case 'KubernetesSupportedVersion': + return 'kubernetesiso' case 'SystemVm': case 'PhysicalNetwork': case 'Backup': @@ -417,6 +421,7 @@ export const resourceTypePlugin = { case 'AffinityGroup': case 'VpnCustomerGateway': case 'AutoScaleVmGroup': + case 'QuotaTariff': return resourceType.toLowerCase() } return '' @@ -454,33 +459,48 @@ export const localesPlugin = { } } -const KB = 1024 -const MB = 1024 * KB -const GB = 1024 * MB -const TB = 1024 * GB +const KiB = 1024 +const MiB = 1024 * KiB +const GiB = 1024 * MiB +const TiB = 1024 * GiB export const fileSizeUtilPlugin = { install (app) { + app.config.globalProperties.$bytesToGiB = function (bytes) { + if (bytes == null || bytes === 0) { + return 0 + } + return (bytes / GiB).toFixed(2) + } app.config.globalProperties.$bytesToHumanReadableSize = function (bytes) { if (bytes == null) { return '' } - if (bytes < KB && bytes >= 0) { + if (bytes < KiB && bytes >= 0) { return bytes + ' bytes' } - if (bytes < MB) { - return (bytes / KB).toFixed(2) + ' KB' - } else if (bytes < GB) { - return (bytes / MB).toFixed(2) + ' MB' - } else if (bytes < TB) { - return (bytes / GB).toFixed(2) + ' GB' + if (bytes < MiB) { + return (bytes / KiB).toFixed(2) + ' KiB' + } else if (bytes < GiB) { + return (bytes / MiB).toFixed(2) + ' MiB' + } else if (bytes < TiB) { + return (bytes / GiB).toFixed(2) + ' GiB' } else { - return (bytes / TB).toFixed(2) + ' TB' + return (bytes / TiB).toFixed(2) + ' TiB' } } } } +function isBase64 (str) { + try { + const decoded = new TextDecoder().decode(Uint8Array.from(atob(str), c => c.charCodeAt(0))) + return btoa(decoded) === str + } catch (err) { + return false + } +} + export const genericUtilPlugin = { install (app) { app.config.globalProperties.$isValidUuid = function (uuid) { @@ -489,8 +509,7 @@ export const genericUtilPlugin = { } app.config.globalProperties.$toBase64AndURIEncoded = function (text) { - const base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/ - if (base64regex.test(text)) { + if (isBase64(text)) { return text } return encodeURIComponent(btoa(unescape(encodeURIComponent(text)))) diff --git a/ui/src/utils/sort.js b/ui/src/utils/sort.js index b2f3d5451ca..5e893fb58ec 100644 --- a/ui/src/utils/sort.js +++ b/ui/src/utils/sort.js @@ -23,13 +23,19 @@ function filterNumber (value) { } function stringComparator (a, b) { - return a.toString().localeCompare(b.toString()) + return a.toString().localeCompare(b.toString(), undefined, { numeric: true }) } function numericComparator (a, b) { return filterNumber(a) < filterNumber(b) ? 1 : -1 } +function metricComparator (ma, mb) { + var a = ('' + ma).replace(/((%)|(Ghz)|(Mhz)|(MiB)|(GiB)|(GB)).*$/g, '') + var b = ('' + mb).replace(/((%)|(Ghz)|(Mhz)|(MiB)|(GiB)|(GB)).*$/g, '') + return parseFloat(a) < parseFloat(b) ? 1 : -1 +} + function ipV4AddressCIDRComparator (a, b) { a = a.split(/[./]/gm) b = b.split(/[./]/gm) @@ -76,6 +82,10 @@ function isNumeric (obj) { return !Array.isArray(obj) && !isNaN(filterNumber(obj)) } +function isMetric (value) { + return /^[0-9\\. ]*((%)|(Ghz)|(Mhz)|(MiB)|(GiB)|(GB))/.test(value) +} + /** * Compare elements, attempting to determine type of element to get the best comparison * @@ -97,6 +107,9 @@ export function genericCompare (a, b) { if (isNumeric(a) && isNumeric(b)) { comparator = numericComparator } + if (isMetric(a) && isMetric(b)) { + comparator = metricComparator + } return comparator(a, b) } diff --git a/ui/src/utils/util.js b/ui/src/utils/util.js index a55d05dbd8f..fad4d1e0f5d 100644 --- a/ui/src/utils/util.js +++ b/ui/src/utils/util.js @@ -68,3 +68,27 @@ export function sanitizeReverse (value) { .replace(/</g, '<') .replace(/>/g, '>') } + +export function toCsv ({ keys = null, data = null, columnDelimiter = ',', lineDelimiter = '\n' }) { + if (data === null || !data.length) { + return null + } + + let result = '' + result += keys.join(columnDelimiter) + result += lineDelimiter + + data.forEach(item => { + keys.forEach(key => { + if (item[key] === undefined) { + item[key] = '' + } + result += typeof item[key] === 'string' && item[key].includes(columnDelimiter) ? `"${item[key]}"` : item[key] + result += columnDelimiter + }) + result = result.slice(0, -1) + result += lineDelimiter + }) + + return result +} diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue index ba1b87042b7..36eb6d4de1d 100644 --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@ -32,20 +32,6 @@ {{ $t('label.refresh') }} - - + :style="device === 'mobile' ? { float: 'right', 'margin-top': '12px', 'margin-bottom': '-6px', display: 'table' } : { float: 'right', display: 'table', 'margin-top': '6px' }" > - +
@@ -229,7 +229,11 @@ v-if="!(currentAction.mapping && field.name in currentAction.mapping && currentAction.mapping[field.name].value)" > -
-
+
+
+ + + + diff --git a/ui/src/views/compute/EditVM.vue b/ui/src/views/compute/EditVM.vue index 3601901252b..550c4645ed6 100644 --- a/ui/src/views/compute/EditVM.vue +++ b/ui/src/views/compute/EditVM.vue @@ -177,7 +177,8 @@ export default { isdynamicallyscalable: this.resource.isdynamicallyscalable, group: this.resource.group, securitygroupids: this.resource.securitygroup.map(x => x.id), - userdata: '' + userdata: '', + haenable: this.resource.haenable }) this.rules = reactive({}) }, diff --git a/ui/src/views/compute/InstanceSchedules.vue b/ui/src/views/compute/InstanceSchedules.vue index 41694adce33..67e1f6ed749 100644 --- a/ui/src/views/compute/InstanceSchedules.vue +++ b/ui/src/views/compute/InstanceSchedules.vue @@ -22,8 +22,9 @@ style="width: 100%; margin-bottom: 10px" @click="showAddModal" :loading="loading" - :disabled="!('createVMSchedule' in $store.getters.apis)"> - {{ $t('label.schedule.add') }} + :disabled="!('createVMSchedule' in $store.getters.apis)" + > + {{ $t('label.schedule.add') }} + @refresh="this.fetchData" + /> + showQuickJumper + > @@ -60,66 +63,68 @@ :title="$t('label.schedule')" :maskClosable="false" :closable="true" - :footer="null" - @cancel="closeModal"> + @cancel="closeModal" + @ok="submitForm" + > - + v-ctrl-enter="submitForm" + > + + v-focus="true" + /> - + - + :disabled="isEdit" + > + {{ $t(action.label) }} - + - - - -
- - - - - -
-
- -
- - - + :loading="fetching" + > + {{ opt.name || opt.description }} - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - + - + - - - - - -
- - {{ $t('label.cancel') }} - - - {{ $t('label.ok') }} - -
@@ -191,7 +261,12 @@ import { mixinForm } from '@/utils/mixin' import { timeZone } from '@/utils/timezone' import debounce from 'lodash/debounce' import cronstrue from 'cronstrue/i18n' -import moment from 'moment-timezone' +import dayjs from 'dayjs' +import utc from 'dayjs/plugin/utc' +import timezone from 'dayjs/plugin/timezone' + +dayjs.extend(utc) +dayjs.extend(timezone) export default { name: 'InstanceSchedules', @@ -323,8 +398,8 @@ export default { this.isEdit = true Object.assign(this.form, schedule) // Some weird issue when we directly pass in the moment with tz object - this.form.startDate = moment(moment(schedule.startdate).tz(schedule.timezone).format(this.pattern)) - this.form.endDate = schedule.enddate ? moment(moment(schedule.enddate).tz(schedule.timezone).format(this.pattern)) : '' + this.form.startDate = dayjs(schedule.startdate).tz(schedule.timezone) + this.form.endDate = schedule.enddate ? dayjs(dayjs(schedule.enddate).tz(schedule.timezone)) : null this.showAddModal() }, showAddModal () { @@ -431,7 +506,7 @@ export default { this.updateColumns() }, generateHumanReadableSchedule (schedule) { - return cronstrue.toString(schedule, { locale: this.$i18n.locale, throwExceptionOnParseError: false }) + return cronstrue.toString(schedule, { locale: this.$i18n.locale, throwExceptionOnParseError: false, verbose: true }) }, updateColumns () { this.columns = [] diff --git a/ui/src/views/compute/InstanceTab.vue b/ui/src/views/compute/InstanceTab.vue index a69d044ea8e..5f08145a4ce 100644 --- a/ui/src/views/compute/InstanceTab.vue +++ b/ui/src/views/compute/InstanceTab.vue @@ -33,7 +33,7 @@ {{ vm.isoname }}
{{ vm.isoid }} - + + + + { x.ipaddress = x.nic[0].ipaddress }) this.instanceLoading = false }, - fetchPublicIpAddress () { + fetchNetwork () { + this.networkLoading = true + return new Promise((resolve, reject) => { + api('listNetworks', { + listAll: true, + id: this.resource.networkid + }).then(json => { + const networks = json.listnetworksresponse.network + if (this.arrayHasItems(networks)) { + this.network = networks[0] + } + resolve(this.network) + }) + this.networkLoading = false + }) + }, + async fetchPublicIpAddress () { + await this.fetchNetwork() + if (this.network && this.network.type === 'Shared') { + this.publicIpAddress = null + return + } this.networkLoading = true var params = { listAll: true, diff --git a/ui/src/views/compute/MigrateVMStorage.vue b/ui/src/views/compute/MigrateVMStorage.vue index 4d0aab4bde5..139ff856a2a 100644 --- a/ui/src/views/compute/MigrateVMStorage.vue +++ b/ui/src/views/compute/MigrateVMStorage.vue @@ -24,7 +24,7 @@ {{ $t('label.migrate.instance.single.storage') }} @@ -134,7 +134,7 @@ export default { }, submitForm () { var isUserVm = true - if (this.$route.meta.name !== 'vm') { + if (this.$route.meta.resourceType !== 'UserVm') { isUserVm = false } var migrateApi = isUserVm ? 'migrateVirtualMachine' : 'migrateSystemVm' diff --git a/ui/src/views/compute/MigrateWizard.vue b/ui/src/views/compute/MigrateWizard.vue index 8aad50d4fc0..70f40f7433a 100644 --- a/ui/src/views/compute/MigrateWizard.vue +++ b/ui/src/views/compute/MigrateWizard.vue @@ -197,7 +197,7 @@ export default { }, computed: { isUserVm () { - return this.$route.meta.name === 'vm' + return this.$route.meta.resourceType === 'UserVm' } }, watch: { diff --git a/ui/src/views/compute/RegisterUserData.vue b/ui/src/views/compute/RegisterUserData.vue index a1322a12832..8e6311fdf9a 100644 --- a/ui/src/views/compute/RegisterUserData.vue +++ b/ui/src/views/compute/RegisterUserData.vue @@ -43,6 +43,9 @@ v-model:value="form.userdata" :placeholder="apiParams.userdata.description"/> + + + + @@ -104,6 +104,10 @@ export default { autoSelectLabel: { type: String, default: '' + }, + isKVMUnmanage: { + type: Boolean, + default: false } }, data () { diff --git a/ui/src/views/compute/wizard/MultiNetworkSelection.vue b/ui/src/views/compute/wizard/MultiNetworkSelection.vue index f2397d5c48c..92d4a437599 100644 --- a/ui/src/views/compute/wizard/MultiNetworkSelection.vue +++ b/ui/src/views/compute/wizard/MultiNetworkSelection.vue @@ -36,7 +36,16 @@