mirror of https://github.com/apache/cloudstack.git
Merge branch 'main' of https://github.com/apache/cloudstack into clvm-enhancements
This commit is contained in:
commit
a29f823f13
|
|
@ -0,0 +1,20 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
[codespell]
|
||||
ignore-words = .github/linters/codespell.txt
|
||||
skip = systemvm/agent/noVNC/*,ui/package.json,ui/package-lock.json,ui/public/js/less.min.js,ui/public/locales/*.json,server/src/test/java/org/apache/cloudstack/network/ssl/CertServiceTest.java,test/integration/smoke/test_ssl_offloading.py
|
||||
|
|
@ -22,8 +22,19 @@
|
|||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "maven" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
open-pull-requests-limit: 2
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
groups:
|
||||
github-actions-dependencies:
|
||||
patterns:
|
||||
- "*"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
- package-ecosystem: "maven"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
cooldown:
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v5
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ jobs:
|
|||
smoke/test_list_volumes"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
name: codecov
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ jobs:
|
|||
language: ["actions"]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ jobs:
|
|||
- name: Set Docker repository name
|
||||
run: echo "DOCKER_REPOSITORY=apache" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set ACS version
|
||||
run: echo "ACS_VERSION=$(grep '<version>' pom.xml | head -2 | tail -1 | cut -d'>' -f2 |cut -d'<' -f1)" >> $GITHUB_ENV
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
name: Main Sonar JaCoCo Build
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check Out
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
- name: Install
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ jobs:
|
|||
name: Sonar JaCoCo Coverage
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: "refs/pull/${{ github.event.number }}/merge"
|
||||
fetch-depth: 0
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ jobs:
|
|||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v5
|
||||
|
|
|
|||
|
|
@ -162,17 +162,15 @@ repos:
|
|||
- id: forbid-submodules
|
||||
- id: mixed-line-ending
|
||||
- id: trailing-whitespace
|
||||
files: ^(LICENSE|NOTICE)$|\.(bat|cfg|cs|css|gitignore|header|in|install|java|md|properties|py|rb|rc|sh|sql|te|template|txt|ucls|vue|xml|xsl|yaml|yml)$|^cloud-cli/bindir/cloud-tool$|^debian/changelog$
|
||||
files: ^(LICENSE|NOTICE)$|README$|\.(bat|cfg|config|cs|css|erb|gitignore|header|in|install|java|md|properties|py|rb|rc|sh|sql|svg|te|template|txt|ucls|vue|xml|xsl|yaml|yml)$|^cloud-cli/bindir/cloud-tool$|^debian/changelog$
|
||||
args: [--markdown-linebreak-ext=md]
|
||||
exclude: ^services/console-proxy/rdpconsole/src/test/doc/freerdp-debug-log\.txt$
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.4.1
|
||||
rev: v2.4.2
|
||||
hooks:
|
||||
- id: codespell
|
||||
name: run codespell
|
||||
description: Check spelling with codespell
|
||||
args: [--ignore-words=.github/linters/codespell.txt]
|
||||
exclude: ^systemvm/agent/noVNC/|^ui/package\.json$|^ui/package-lock\.json$|^ui/public/js/less\.min\.js$|^ui/public/locales/.*[^n].*\.json$|^server/src/test/java/org/apache/cloudstack/network/ssl/CertServiceTest.java$|^test/integration/smoke/test_ssl_offloading.py$
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 7.0.0
|
||||
hooks:
|
||||
|
|
@ -186,7 +184,7 @@ repos:
|
|||
description: check Markdown files with markdownlint
|
||||
args: [--config=.github/linters/.markdown-lint.yml]
|
||||
types: [markdown]
|
||||
files: \.(md|mdown|markdown)$
|
||||
files: \.md$
|
||||
- repo: https://github.com/adrienverge/yamllint
|
||||
rev: v1.37.1
|
||||
hooks:
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public class NicTO extends NetworkTO {
|
|||
boolean dpdkEnabled;
|
||||
Integer mtu;
|
||||
Long networkId;
|
||||
boolean enabled;
|
||||
|
||||
String networkSegmentName;
|
||||
|
||||
|
|
@ -154,4 +155,12 @@ public class NicTO extends NetworkTO {
|
|||
public void setNetworkSegmentName(String networkSegmentName) {
|
||||
this.networkSegmentName = networkSegmentName;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,4 +162,6 @@ public interface Nic extends Identity, InternalIdentity {
|
|||
String getIPv6Address();
|
||||
|
||||
Integer getMtu();
|
||||
|
||||
boolean isEnabled();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public class NicProfile implements InternalIdentity, Serializable {
|
|||
boolean defaultNic;
|
||||
Integer networkRate;
|
||||
boolean isSecurityGroupEnabled;
|
||||
boolean enabled;
|
||||
|
||||
Integer orderIndex;
|
||||
|
||||
|
|
@ -87,6 +88,7 @@ public class NicProfile implements InternalIdentity, Serializable {
|
|||
broadcastType = network.getBroadcastDomainType();
|
||||
trafficType = network.getTrafficType();
|
||||
format = nic.getAddressFormat();
|
||||
enabled = nic.isEnabled();
|
||||
|
||||
iPv4Address = nic.getIPv4Address();
|
||||
iPv4Netmask = nic.getIPv4Netmask();
|
||||
|
|
@ -414,6 +416,14 @@ public class NicProfile implements InternalIdentity, Serializable {
|
|||
this.ipv4AllocationRaceCheck = ipv4AllocationRaceCheck;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
//
|
||||
// OTHER METHODS
|
||||
//
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd;
|
|||
import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicIpCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
|
||||
|
|
@ -152,6 +153,8 @@ public interface UserVmService {
|
|||
*/
|
||||
UserVm updateNicIpForVirtualMachine(UpdateVmNicIpCmd cmd);
|
||||
|
||||
UserVm updateVirtualMachineNic(UpdateVmNicCmd cmd);
|
||||
|
||||
UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -343,6 +343,8 @@ public interface ResponseGenerator {
|
|||
|
||||
UserVm findUserVmById(Long vmId);
|
||||
|
||||
UserVm findUserVmByNicId(Long nicId);
|
||||
|
||||
Volume findVolumeById(Long volumeId);
|
||||
|
||||
Account findAccountByNameDomain(String accountName, Long domainId);
|
||||
|
|
|
|||
|
|
@ -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.vm;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.ACL;
|
||||
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.Parameter;
|
||||
import org.apache.cloudstack.api.ResponseObject;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.NicResponse;
|
||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.uservm.UserVm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
|
||||
@APICommand(name = "updateVmNic", description = "Updates the specified VM NIC", responseObject = NicResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
authorized = { RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User })
|
||||
public class UpdateVmNicCmd extends BaseAsyncCmd {
|
||||
|
||||
@ACL
|
||||
@Parameter(name = ApiConstants.NIC_ID, type = CommandType.UUID, entityType = NicResponse.class, required = true, description = "NIC ID")
|
||||
private Long nicId;
|
||||
|
||||
@Parameter(name = ApiConstants.ENABLED, type = CommandType.BOOLEAN, description = "If true, sets the NIC state to UP; otherwise, sets the NIC state to DOWN")
|
||||
private Boolean enabled;
|
||||
|
||||
public Long getNicId() {
|
||||
return nicId;
|
||||
}
|
||||
|
||||
public Boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_NIC_UPDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
return String.format("Updating NIC %s.", getResourceUuid(ApiConstants.NIC_ID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
UserVm vm = _responseGenerator.findUserVmByNicId(nicId);
|
||||
if (vm == null) {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
return vm.getAccountId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
CallContext.current().setEventDetails(String.format("NIC ID: %s", getResourceUuid(ApiConstants.NIC_ID)));
|
||||
|
||||
UserVm result = _userVmService.updateVirtualMachineNic(this);
|
||||
|
||||
ArrayList<ApiConstants.VMDetails> dc = new ArrayList<>();
|
||||
dc.add(ApiConstants.VMDetails.valueOf("nics"));
|
||||
EnumSet<ApiConstants.VMDetails> details = EnumSet.copyOf(dc);
|
||||
|
||||
if (result != null){
|
||||
UserVmResponse response = _responseGenerator.createUserVmResponse(ResponseObject.ResponseView.Restricted, "virtualmachine", details, result).get(0);
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update NIC from VM.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -146,6 +146,10 @@ public class NicResponse extends BaseResponse {
|
|||
@Param(description = "Public IP address associated with this NIC via Static NAT rule")
|
||||
private String publicIp;
|
||||
|
||||
@SerializedName(ApiConstants.ENABLED)
|
||||
@Param(description = "whether the NIC is enabled or not")
|
||||
private Boolean isEnabled;
|
||||
|
||||
public void setVmId(String vmId) {
|
||||
this.vmId = vmId;
|
||||
}
|
||||
|
|
@ -416,4 +420,12 @@ public class NicResponse extends BaseResponse {
|
|||
public void setPublicIp(String publicIp) {
|
||||
this.publicIp = publicIp;
|
||||
}
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
isEnabled = enabled;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.agent.api;
|
||||
|
||||
public class UpdateVmNicAnswer extends Answer {
|
||||
public UpdateVmNicAnswer() {
|
||||
}
|
||||
|
||||
public UpdateVmNicAnswer(UpdateVmNicCommand cmd, boolean success, String result) {
|
||||
super(cmd, success, result);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 com.cloud.agent.api;
|
||||
|
||||
public class UpdateVmNicCommand extends Command {
|
||||
|
||||
String nicMacAddress;
|
||||
String instanceName;
|
||||
Boolean enabled;
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected UpdateVmNicCommand() {
|
||||
}
|
||||
|
||||
public UpdateVmNicCommand(String nicMacAdderss, String instanceName, Boolean enabled) {
|
||||
this.nicMacAddress = nicMacAdderss;
|
||||
this.instanceName = instanceName;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getNicMacAddress() {
|
||||
return nicMacAddress;
|
||||
}
|
||||
|
||||
public String getVmName() {
|
||||
return instanceName;
|
||||
}
|
||||
|
||||
public Boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
}
|
||||
|
|
@ -230,6 +230,8 @@ public interface VirtualMachineManager extends Manager {
|
|||
|
||||
Boolean updateDefaultNicForVM(VirtualMachine vm, Nic nic, Nic defaultNic);
|
||||
|
||||
boolean updateVmNic(VirtualMachine vm, Nic nic, Boolean enabled) throws ResourceUnavailableException;
|
||||
|
||||
/**
|
||||
* @param vm
|
||||
* @param network
|
||||
|
|
|
|||
|
|
@ -156,6 +156,8 @@ import com.cloud.agent.api.UnPlugNicAnswer;
|
|||
import com.cloud.agent.api.UnPlugNicCommand;
|
||||
import com.cloud.agent.api.UnmanageInstanceCommand;
|
||||
import com.cloud.agent.api.UnregisterVMCommand;
|
||||
import com.cloud.agent.api.UpdateVmNicAnswer;
|
||||
import com.cloud.agent.api.UpdateVmNicCommand;
|
||||
import com.cloud.agent.api.VmDiskStatsEntry;
|
||||
import com.cloud.agent.api.VmNetworkStatsEntry;
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
|
|
@ -6332,6 +6334,80 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
_jobMgr.marshallResultObject(result));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateVmNic(VirtualMachine vm, Nic nic, Boolean enabled) {
|
||||
Outcome<VirtualMachine> outcome = updateVmNicThroughJobQueue(vm, nic, enabled);
|
||||
|
||||
retrieveVmFromJobOutcome(outcome, vm.getUuid(), "updateVmNic");
|
||||
|
||||
try {
|
||||
Object jobResult = retrieveResultFromJobOutcomeAndThrowExceptionIfNeeded(outcome);
|
||||
if (jobResult instanceof Boolean) {
|
||||
return BooleanUtils.isTrue((Boolean) jobResult);
|
||||
}
|
||||
} catch (ResourceUnavailableException | InsufficientCapacityException ex) {
|
||||
throw new CloudRuntimeException(String.format("Exception while updating VM [%s] NIC. Check the logs for more information.", vm.getUuid()));
|
||||
}
|
||||
throw new CloudRuntimeException("Unexpected job execution result.");
|
||||
}
|
||||
|
||||
private boolean orchestrateUpdateVmNic(final VirtualMachine vm, final Nic nic, final Boolean enabled) throws ResourceUnavailableException {
|
||||
if (vm.getState() == State.Running) {
|
||||
try {
|
||||
UpdateVmNicCommand updateVmNicCmd = new UpdateVmNicCommand(nic.getMacAddress(), vm.getName(), enabled);
|
||||
Commands cmds = new Commands(Command.OnError.Stop);
|
||||
cmds.addCommand("updatevmnic", updateVmNicCmd);
|
||||
|
||||
_agentMgr.send(vm.getHostId(), cmds);
|
||||
|
||||
UpdateVmNicAnswer updateVmNicAnswer = cmds.getAnswer(UpdateVmNicAnswer.class);
|
||||
if (updateVmNicAnswer == null || !updateVmNicAnswer.getResult()) {
|
||||
logger.warn("Unable to update VM %s NIC [{}].", vm.getName(), nic.getUuid());
|
||||
return false;
|
||||
}
|
||||
} catch (final OperationTimedoutException e) {
|
||||
throw new AgentUnavailableException(String.format("Unable to update NIC %s for VM %s.", nic.getUuid(), vm.getUuid()), vm.getHostId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
NicVO nicVo = _nicsDao.findById(nic.getId());
|
||||
nicVo.setEnabled(enabled);
|
||||
_nicsDao.persist(nicVo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Outcome<VirtualMachine> updateVmNicThroughJobQueue(final VirtualMachine vm, final Nic nic, final Boolean isNicEnabled) {
|
||||
Long vmId = vm.getId();
|
||||
String commandName = VmWorkUpdateNic.class.getName();
|
||||
Pair<VmWorkJobVO, Long> pendingWorkJob = retrievePendingWorkJob(vmId, commandName);
|
||||
|
||||
VmWorkJobVO workJob = pendingWorkJob.first();
|
||||
|
||||
if (workJob == null) {
|
||||
Pair<VmWorkJobVO, VmWork> newVmWorkJobAndInfo = createWorkJobAndWorkInfo(commandName, vmId);
|
||||
|
||||
workJob = newVmWorkJobAndInfo.first();
|
||||
VmWorkUpdateNic workInfo = new VmWorkUpdateNic(newVmWorkJobAndInfo.second(), nic.getId(), isNicEnabled);
|
||||
|
||||
setCmdInfoAndSubmitAsyncJob(workJob, workInfo, vmId);
|
||||
}
|
||||
AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(workJob.getId());
|
||||
|
||||
return new VmJobVirtualMachineOutcome(workJob, vmId);
|
||||
}
|
||||
|
||||
@ReflectionUse
|
||||
private Pair<JobInfo.Status, String> orchestrateUpdateVmNic(final VmWorkUpdateNic work) throws Exception {
|
||||
VMInstanceVO vm = findVmById(work.getVmId());
|
||||
final NicVO nic = _entityMgr.findById(NicVO.class, work.getNicId());
|
||||
if (nic == null) {
|
||||
throw new CloudRuntimeException(String.format("Unable to find NIC with ID %s.", work.getNicId()));
|
||||
}
|
||||
final boolean result = orchestrateUpdateVmNic(vm, nic, work.isEnabled());
|
||||
return new Pair<>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(result));
|
||||
}
|
||||
|
||||
private Pair<Long, Long> findClusterAndHostIdForVmFromVolumes(long vmId) {
|
||||
Long clusterId = null;
|
||||
Long hostId = null;
|
||||
|
|
|
|||
|
|
@ -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.vm;
|
||||
|
||||
public class VmWorkUpdateNic extends VmWork {
|
||||
private static final long serialVersionUID = -8957066627929113278L;
|
||||
|
||||
Long nicId;
|
||||
Boolean enabled;
|
||||
|
||||
public VmWorkUpdateNic(VmWork vmWork, Long nicId, Boolean enabled) {
|
||||
super(vmWork);
|
||||
this.nicId = nicId;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Long getNicId() {
|
||||
return nicId;
|
||||
}
|
||||
|
||||
public Boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
}
|
||||
|
|
@ -131,6 +131,9 @@ public class NicVO implements Nic {
|
|||
@Column(name = "mtu")
|
||||
Integer mtu;
|
||||
|
||||
@Column(name = "enabled")
|
||||
boolean enabled;
|
||||
|
||||
@Transient
|
||||
transient String nsxLogicalSwitchUuid;
|
||||
|
||||
|
|
@ -143,6 +146,7 @@ public class NicVO implements Nic {
|
|||
this.networkId = configurationId;
|
||||
this.state = State.Allocated;
|
||||
this.vmType = vmType;
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -397,6 +401,14 @@ public class NicVO implements Nic {
|
|||
this.nsxLogicalSwitchPortUuid = nsxLogicalSwitchPortUuid;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 31).append(id).toHashCode();
|
||||
|
|
|
|||
|
|
@ -114,3 +114,6 @@ CALL `cloud`.`IDEMPOTENT_UPDATE_API_PERMISSION`('Resource Admin', 'deleteUserKey
|
|||
|
||||
-- Add conserve mode for VPC offerings
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','conserve_mode', 'tinyint(1) unsigned NULL DEFAULT 0 COMMENT ''True if the VPC offering is IP conserve mode enabled, allowing public IP services to be used across multiple VPC tiers'' ');
|
||||
|
||||
--- Disable/enable NICs
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.nics','enabled', 'TINYINT(1) NOT NULL DEFAULT 1 COMMENT ''Indicates whether the NIC is enabled or not'' ');
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ select
|
|||
nics.broadcast_uri broadcast_uri,
|
||||
nics.isolation_uri isolation_uri,
|
||||
nics.mtu mtu,
|
||||
nics.enabled is_nic_enabled,
|
||||
vpc.id vpc_id,
|
||||
vpc.uuid vpc_uuid,
|
||||
vpc.name vpc_name,
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ SELECT
|
|||
`nics`.`mac_address` AS `mac_address`,
|
||||
`nics`.`broadcast_uri` AS `broadcast_uri`,
|
||||
`nics`.`isolation_uri` AS `isolation_uri`,
|
||||
`nics`.`enabled` AS `is_nic_enabled`,
|
||||
`vpc`.`id` AS `vpc_id`,
|
||||
`vpc`.`uuid` AS `vpc_uuid`,
|
||||
`networks`.`uuid` AS `network_uuid`,
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ public class SequenceFetcher {
|
|||
try {
|
||||
return future.get();
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to get sequeunce for " + tg.table() + ":" + tg.pkColumnValue(), e);
|
||||
logger.warn("Unable to get sequence for " + tg.table() + ":" + tg.pkColumnValue(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
<appender-ref ref="EventLogAppender"/>
|
||||
</root>
|
||||
</log4net>
|
||||
|
||||
|
||||
<applicationSettings>
|
||||
<CloudStack.Plugin.AgentShell.AgentSettings>
|
||||
<setting name="cpus" serializeAs="String">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
<!--
|
||||
Note: Add entries to the App.config file for configuration settings
|
||||
that apply only to the Test project.
|
||||
-->
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
<!--
|
||||
Note: Add entries to the App.config file for configuration settings
|
||||
that apply only to the Test project.
|
||||
-->
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ public class BridgeVifDriver extends VifDriverBase {
|
|||
if (nic.getPxeDisable()) {
|
||||
intf.setPxeDisable(true);
|
||||
}
|
||||
intf.setLinkStateUp(nic.isEnabled());
|
||||
|
||||
return intf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4857,6 +4857,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
}
|
||||
}
|
||||
|
||||
public InterfaceDef getInterface(final Connect conn, final String vmName, final String macAddress) {
|
||||
List<InterfaceDef> interfaces = getInterfaces(conn, vmName);
|
||||
return interfaces.stream().filter(interfaceDef -> interfaceDef.getMacAddress().equals(macAddress))
|
||||
.findFirst().orElseThrow(() -> new CloudRuntimeException(String.format("Unable to find NIC with MAC address %s.", macAddress)));
|
||||
}
|
||||
|
||||
public List<DiskDef> getDisks(final Connect conn, final String vmName) {
|
||||
final LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser();
|
||||
Domain dm = null;
|
||||
|
|
|
|||
|
|
@ -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 com.cloud.hypervisor.kvm.resource.wrapper;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.UpdateVmNicAnswer;
|
||||
import com.cloud.agent.api.UpdateVmNicCommand;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
|
||||
import com.cloud.resource.CommandWrapper;
|
||||
import com.cloud.resource.ResourceWrapper;
|
||||
import org.libvirt.Connect;
|
||||
import org.libvirt.Domain;
|
||||
import org.libvirt.LibvirtException;
|
||||
|
||||
@ResourceWrapper(handles = UpdateVmNicCommand.class)
|
||||
public final class LibvirtUpdateVmNicCommandWrapper extends CommandWrapper<UpdateVmNicCommand, Answer, LibvirtComputingResource> {
|
||||
|
||||
@Override
|
||||
public Answer execute(UpdateVmNicCommand command, LibvirtComputingResource libvirtComputingResource) {
|
||||
String nicMacAddress = command.getNicMacAddress();
|
||||
String vmName = command.getVmName();
|
||||
boolean isEnabled = command.isEnabled();
|
||||
|
||||
Domain vm = null;
|
||||
try {
|
||||
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
|
||||
final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
|
||||
vm = libvirtComputingResource.getDomain(conn, vmName);
|
||||
|
||||
final InterfaceDef nic = libvirtComputingResource.getInterface(conn, vmName, nicMacAddress);
|
||||
nic.setLinkStateUp(isEnabled);
|
||||
vm.updateDeviceFlags(nic.toString(), Domain.DeviceModifyFlags.LIVE);
|
||||
|
||||
return new UpdateVmNicAnswer(command, true, "success");
|
||||
} catch (final LibvirtException e) {
|
||||
final String msg = String.format(" Update NIC failed due to %s.", e);
|
||||
logger.warn(msg, e);
|
||||
return new UpdateVmNicAnswer(command, false, msg);
|
||||
} finally {
|
||||
if (vm != null) {
|
||||
try {
|
||||
vm.free();
|
||||
} catch (final LibvirtException l) {
|
||||
logger.trace("Ignoring libvirt error.", l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7210,6 +7210,37 @@ public class LibvirtComputingResourceTest {
|
|||
Mockito.verify(diskDef).defFileBasedDisk(PHYSICAL_DISK_PATH, DEV_ID, DISK_BUS_TYPE_DATA, DiskDef.DiskFmtType.QCOW2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInterfaceTestValidMacAddressReturnInterface() {
|
||||
String macAddress = "a0:90:27:a9:9e:62";
|
||||
final String vmName = "Test";
|
||||
final InterfaceDef interfaceDef = Mockito.mock(InterfaceDef.class);
|
||||
final List<InterfaceDef> interfaces = new ArrayList<>();
|
||||
interfaces.add(interfaceDef);
|
||||
|
||||
Mockito.doReturn(macAddress).when(interfaceDef).getMacAddress();
|
||||
Mockito.doReturn(interfaces).when(libvirtComputingResourceSpy).getInterfaces(Mockito.any(), Mockito.anyString());
|
||||
|
||||
InterfaceDef result = libvirtComputingResourceSpy.getInterface(connMock, vmName, macAddress);
|
||||
|
||||
Assert.assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void getInterfaceTestInvalidMacAddressThrowCloudRuntimeException() {
|
||||
String invalidMacAddress = "ea:57:5d:f1:64:05";
|
||||
String macAddress = "a0:90:27:a9:9e:62";
|
||||
final String vmName = "Test";
|
||||
final InterfaceDef interfaceDef = Mockito.mock(InterfaceDef.class);
|
||||
final List<InterfaceDef> interfaces = new ArrayList<>();
|
||||
interfaces.add(interfaceDef);
|
||||
|
||||
Mockito.doReturn(macAddress).when(interfaceDef).getMacAddress();
|
||||
Mockito.doReturn(interfaces).when(libvirtComputingResourceSpy).getInterfaces(Mockito.any(), Mockito.anyString());
|
||||
|
||||
libvirtComputingResourceSpy.getInterface(connMock, vmName, invalidMacAddress);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractVolumeGroupFromPath_ValidPath() {
|
||||
String devicePath = "/dev/vg1/volume-123";
|
||||
|
|
|
|||
|
|
@ -465,4 +465,3 @@ public class LibvirtClvmLockTransferCommandWrapperTest {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,11 +171,20 @@ public class KubernetesClusterUtil {
|
|||
// Check if dashboard service is up running.
|
||||
while (System.currentTimeMillis() < timeoutTime) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(String.format("Checking dashboard service for the Kubernetes cluster: %s to come up", kubernetesCluster));
|
||||
LOGGER.debug(String.format("Checking dashboard service (Kubernetes Dashboard or Headlamp) for the Kubernetes cluster: %s to come up", kubernetesCluster));
|
||||
}
|
||||
// Check for Headlamp (new dashboard) in kube-system namespace
|
||||
if (isKubernetesClusterAddOnServiceRunning(kubernetesCluster, ipAddress, port, user, sshKeyFile, "kube-system", "headlamp")) {
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info(String.format("Headlamp dashboard service for the Kubernetes cluster %s is in running state", kubernetesCluster));
|
||||
}
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
// For backward compatibility, check for Kubernetes Dashboard in kubernetes-dashboard namespace
|
||||
if (isKubernetesClusterAddOnServiceRunning(kubernetesCluster, ipAddress, port, user, sshKeyFile, "kubernetes-dashboard", "kubernetes-dashboard")) {
|
||||
if (LOGGER.isInfoEnabled()) {
|
||||
LOGGER.info(String.format("Dashboard service for the Kubernetes cluster %s is in running state", kubernetesCluster));
|
||||
LOGGER.info(String.format("Kubernetes Dashboard service for the Kubernetes cluster %s is in running state", kubernetesCluster));
|
||||
}
|
||||
running = true;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -331,16 +331,29 @@ write_files:
|
|||
if [[ ${EXTERNAL_CNI_PLUGIN} == false ]]; then
|
||||
/opt/bin/kubectl apply -f ${K8S_CONFIG_SCRIPTS_COPY_DIR}/network.yaml
|
||||
fi
|
||||
/opt/bin/kubectl apply -f ${K8S_CONFIG_SCRIPTS_COPY_DIR}/dashboard.yaml
|
||||
if [ -f "${K8S_CONFIG_SCRIPTS_COPY_DIR}/headlamp.yaml" ]; then
|
||||
echo "Installing Headlamp dashboard from ISO"
|
||||
/opt/bin/kubectl apply -f ${K8S_CONFIG_SCRIPTS_COPY_DIR}/headlamp.yaml
|
||||
elif [ -f "${K8S_CONFIG_SCRIPTS_COPY_DIR}/dashboard.yaml" ]; then
|
||||
echo "Installing Kubernetes Dashboard from ISO"
|
||||
/opt/bin/kubectl apply -f ${K8S_CONFIG_SCRIPTS_COPY_DIR}/dashboard.yaml
|
||||
/opt/bin/kubectl create rolebinding admin-binding --role=admin --user=admin || true
|
||||
/opt/bin/kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=admin || true
|
||||
/opt/bin/kubectl create clusterrolebinding kubernetes-dashboard-ui --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:kubernetes-dashboard || true
|
||||
else
|
||||
echo "Warning: No dashboard YAML found in ISO (neither headlamp.yaml nor dashboard.yaml)"
|
||||
fi
|
||||
rm -rf "${K8S_CONFIG_SCRIPTS_COPY_DIR}"
|
||||
else
|
||||
### Online installation - use Headlamp by default ###
|
||||
/opt/bin/kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(/opt/bin/kubectl version | base64 | tr -d '\n')"
|
||||
/opt/bin/kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta6/aio/deploy/recommended.yaml
|
||||
/opt/bin/kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/headlamp/v0.40.1/kubernetes-headlamp.yaml
|
||||
/opt/bin/kubectl create serviceaccount headlamp-admin -n kube-system || true
|
||||
/opt/bin/kubectl create clusterrolebinding headlamp-admin --clusterrole=cluster-admin --serviceaccount=kube-system:headlamp-admin || true
|
||||
fi
|
||||
|
||||
/opt/bin/kubectl create rolebinding admin-binding --role=admin --user=admin || true
|
||||
/opt/bin/kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=admin || true
|
||||
/opt/bin/kubectl create clusterrolebinding kubernetes-dashboard-ui --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:kubernetes-dashboard || true
|
||||
|
||||
sudo touch /home/cloud/success
|
||||
echo "true" > /home/cloud/success
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
set -e
|
||||
|
||||
if [ $# -lt 6 ]; then
|
||||
echo "Invalid input. Valid usage: ./create-kubernetes-binaries-iso.sh OUTPUT_PATH KUBERNETES_VERSION CNI_VERSION CRICTL_VERSION WEAVENET_NETWORK_YAML_CONFIG DASHBOARD_YAML_CONFIG BUILD_NAME [ARCH] [ETCD_VERSION]"
|
||||
echo "eg: ./create-kubernetes-binaries-iso.sh ./ 1.11.4 0.7.1 1.11.1 https://github.com/weaveworks/weave/releases/download/latest_release/weave-daemonset-k8s-1.11.yaml https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.0/src/deploy/recommended/kubernetes-dashboard.yaml setup-v1.11.4 amd64"
|
||||
echo "Invalid input. Valid usage: ./create-kubernetes-binaries-iso.sh OUTPUT_PATH KUBERNETES_VERSION CNI_VERSION CRICTL_VERSION WEAVENET_NETWORK_YAML_CONFIG HEADLAMP_DASHBOARD_VERSION BUILD_NAME [ARCH] [ETCD_VERSION]"
|
||||
echo "eg: ./create-kubernetes-binaries-iso.sh ./ 1.11.4 0.7.1 1.11.1 https://github.com/weaveworks/weave/releases/download/latest_release/weave-daemonset-k8s-1.11.yaml 0.40.1 setup-v1.11.4 amd64"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -96,10 +96,11 @@ echo "Downloading network config ${NETWORK_CONFIG_URL}"
|
|||
network_conf_file="${working_dir}/network.yaml"
|
||||
curl -sSL ${NETWORK_CONFIG_URL} -o ${network_conf_file}
|
||||
|
||||
DASHBORAD_CONFIG_URL="${6}"
|
||||
echo "Downloading dashboard config ${DASHBORAD_CONFIG_URL}"
|
||||
dashboard_conf_file="${working_dir}/dashboard.yaml"
|
||||
curl -sSL ${DASHBORAD_CONFIG_URL} -o ${dashboard_conf_file}
|
||||
HEADLAMP_DASHBOARD_VERSION="${6}"
|
||||
HEADLAMP_DASHBOARD_URL="https://raw.githubusercontent.com/kubernetes-sigs/headlamp/v${HEADLAMP_DASHBOARD_VERSION}/kubernetes-headlamp.yaml"
|
||||
echo "Downloading Headlamp manifest from ${HEADLAMP_DASHBOARD_URL}"
|
||||
headlamp_conf_file="${working_dir}/headlamp.yaml"
|
||||
curl -sSL ${HEADLAMP_DASHBOARD_URL} -o ${headlamp_conf_file}
|
||||
|
||||
# TODO : Change the url once merged
|
||||
AUTOSCALER_URL="https://raw.githubusercontent.com/kubernetes/autoscaler/master/cluster-autoscaler/cloudprovider/cloudstack/examples/cluster-autoscaler-standard.yaml"
|
||||
|
|
@ -135,7 +136,7 @@ mkdir -p "${working_dir}/docker"
|
|||
output=`${k8s_dir}/kubeadm config images list --kubernetes-version=${RELEASE}`
|
||||
|
||||
# Don't forget about the yaml images !
|
||||
for i in ${network_conf_file} ${dashboard_conf_file}
|
||||
for i in ${network_conf_file} ${headlamp_conf_file}
|
||||
do
|
||||
images=`grep "image:" $i | cut -d ':' -f2- | tr -d ' ' | tr -d "'"`
|
||||
output=`printf "%s\n" ${output} ${images}`
|
||||
|
|
|
|||
|
|
@ -2230,6 +2230,10 @@ public class ApiDBUtils {
|
|||
return s_nicSecondaryIpDao.listByNicId(nicId);
|
||||
}
|
||||
|
||||
public static NicVO findNicById(long nicId) {
|
||||
return s_nicDao.findById(nicId);
|
||||
}
|
||||
|
||||
public static TemplateResponse newTemplateUpdateResponse(TemplateJoinVO vr) {
|
||||
return s_templateJoinDao.newUpdateResponse(vr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1929,6 +1929,12 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserVm findUserVmByNicId(Long nicId) {
|
||||
NicVO nic = ApiDBUtils.findNicById(nicId);
|
||||
return ApiDBUtils.findUserVmById(nic.getInstanceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolumeVO findVolumeById(Long volumeId) {
|
||||
return ApiDBUtils.findVolumeById(volumeId);
|
||||
|
|
@ -4844,6 +4850,8 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||
VpcVO vpc = _entityMgr.findByUuidIncludingRemoved(VpcVO.class, userVm.getVpcUuid());
|
||||
response.setVpcName(vpc.getName());
|
||||
}
|
||||
|
||||
response.setEnabled(result.isEnabled());
|
||||
return response;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO,
|
|||
nicResponse.setMtu(router.getMtu());
|
||||
}
|
||||
nicResponse.setIsDefault(router.isDefaultNic());
|
||||
nicResponse.setEnabled(router.isNicEnabled());
|
||||
nicResponse.setObjectName("nic");
|
||||
routerResponse.addNic(nicResponse);
|
||||
}
|
||||
|
|
@ -289,6 +290,7 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO,
|
|||
nicResponse.setMtu(vr.getMtu());
|
||||
}
|
||||
nicResponse.setIsDefault(vr.isDefaultNic());
|
||||
nicResponse.setEnabled(vr.isNicEnabled());
|
||||
nicResponse.setObjectName("nic");
|
||||
vrData.addNic(nicResponse);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -358,6 +358,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
nicResponse.setIp6Address(userVm.getIp6Address());
|
||||
nicResponse.setIp6Gateway(userVm.getIp6Gateway());
|
||||
nicResponse.setIp6Cidr(userVm.getIp6Cidr());
|
||||
nicResponse.setEnabled(userVm.isNicEnabled());
|
||||
if (userVm.getBroadcastUri() != null) {
|
||||
nicResponse.setBroadcastUri(userVm.getBroadcastUri().toString());
|
||||
}
|
||||
|
|
@ -625,6 +626,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
/*17: default*/
|
||||
nicResponse.setIsDefault(uvo.isDefaultNic());
|
||||
nicResponse.setDeviceId(String.valueOf(uvo.getNicDeviceId()));
|
||||
nicResponse.setEnabled(uvo.isNicEnabled());
|
||||
List<NicSecondaryIpVO> secondaryIps = ApiDBUtils.findNicSecondaryIps(uvo.getNicId());
|
||||
if (secondaryIps != null) {
|
||||
List<NicSecondaryIpResponse> ipList = new ArrayList<NicSecondaryIpResponse>();
|
||||
|
|
|
|||
|
|
@ -274,6 +274,9 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti
|
|||
@Column(name = "mtu")
|
||||
private Integer mtu;
|
||||
|
||||
@Column(name = "is_nic_enabled")
|
||||
private boolean isNicEnabled;
|
||||
|
||||
public DomainRouterJoinVO() {
|
||||
}
|
||||
|
||||
|
|
@ -577,4 +580,8 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti
|
|||
public Integer getMtu() {
|
||||
return mtu;
|
||||
}
|
||||
|
||||
public boolean isNicEnabled() {
|
||||
return isNicEnabled;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -345,6 +345,9 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
|
|||
@Column(name = "is_default_nic")
|
||||
private boolean isDefaultNic;
|
||||
|
||||
@Column(name = "is_nic_enabled")
|
||||
private boolean isNicEnabled;
|
||||
|
||||
@Column(name = "ip_address")
|
||||
private String ipAddress;
|
||||
|
||||
|
|
@ -1089,4 +1092,8 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
|
|||
public String getLeaseActionExecution() {
|
||||
return leaseActionExecution;
|
||||
}
|
||||
|
||||
public boolean isNicEnabled() {
|
||||
return isNicEnabled;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
|
|||
to.setIp6Dns1(profile.getIPv6Dns1());
|
||||
to.setIp6Dns2(profile.getIPv6Dns2());
|
||||
to.setNetworkId(profile.getNetworkId());
|
||||
to.setEnabled(profile.isEnabled());
|
||||
|
||||
NetworkVO network = networkDao.findById(profile.getNetworkId());
|
||||
to.setNetworkUuid(network.getUuid());
|
||||
|
|
|
|||
|
|
@ -567,6 +567,7 @@ import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
|
|||
import org.apache.cloudstack.api.command.user.vm.StopVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicIpCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
|
||||
|
|
@ -4165,6 +4166,7 @@ public class ManagementServerImpl extends MutualExclusiveIdsManagerBase implemen
|
|||
cmdList.add(StopVMCmd.class);
|
||||
cmdList.add(UpdateDefaultNicForVMCmd.class);
|
||||
cmdList.add(UpdateVMCmd.class);
|
||||
cmdList.add(UpdateVmNicCmd.class);
|
||||
cmdList.add(UpgradeVMCmd.class);
|
||||
cmdList.add(CreateVMGroupCmd.class);
|
||||
cmdList.add(DeleteVMGroupCmd.class);
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ import org.apache.cloudstack.api.command.user.vm.SecurityGroupAction;
|
|||
import org.apache.cloudstack.api.command.user.vm.StartVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateDefaultNicForVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicIpCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpgradeVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
|
||||
|
|
@ -1899,6 +1900,54 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return vm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserVm updateVirtualMachineNic(UpdateVmNicCmd cmd) {
|
||||
Long nicId = cmd.getNicId();
|
||||
Boolean isNicEnabled = cmd.isEnabled();
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
NicVO nic = _nicDao.findById(nicId);
|
||||
if (nic == null) {
|
||||
throw new InvalidParameterValueException("Unable to find the specified NIC.");
|
||||
}
|
||||
|
||||
UserVmVO vmInstance = _vmDao.findById(nic.getInstanceId());
|
||||
if (vmInstance == null) {
|
||||
throw new InvalidParameterValueException("Unable to find a virtual machine associated with the specified NIC.");
|
||||
}
|
||||
|
||||
if (vmInstance.getHypervisorType() != HypervisorType.KVM) {
|
||||
throw new InvalidParameterValueException("Updating the VM NIC is only supported by the KVM hypervisor.");
|
||||
}
|
||||
|
||||
NetworkVO network = _networkDao.findById(nic.getNetworkId());
|
||||
if (network == null) {
|
||||
throw new InvalidParameterValueException("Unable to find NIC's network.");
|
||||
}
|
||||
|
||||
_accountMgr.checkAccess(caller, null, true, vmInstance);
|
||||
|
||||
if (isNicEnabled == null) {
|
||||
return vmInstance;
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
success = _itMgr.updateVmNic(vmInstance, nic, isNicEnabled);
|
||||
} catch (ResourceUnavailableException e) {
|
||||
throw new CloudRuntimeException(String.format("Unable to update NIC %s of VM %s in network %s due to: %s.", nic, vmInstance, network.getUuid(), e.getMessage()));
|
||||
} catch (ConcurrentOperationException e) {
|
||||
throw new CloudRuntimeException(String.format("Concurrent operations while updating NIC %s for VM %s: %s.", nic, vmInstance, e.getMessage()));
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
throw new CloudRuntimeException(String.format("Failed to update NIC %s of VM %s in network %s.", nic, vmInstance, network.getUuid()));
|
||||
}
|
||||
|
||||
logger.debug("Successfully updated NIC {} in network {} for VM {}.", nic, network.getUuid(), vmInstance);
|
||||
return vmInstance;
|
||||
}
|
||||
|
||||
private void updatePublicIpDnatVmIp(long vmId, long networkId, String oldIp, String newIp) {
|
||||
if (!_networkModel.areServicesSupportedInNetwork(networkId, Service.StaticNat)) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ import org.apache.cloudstack.api.command.user.vm.ResetVMSSHKeyCmd;
|
|||
import org.apache.cloudstack.api.command.user.vm.ResetVMUserDataCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.UpdateVmNicCmd;
|
||||
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
|
||||
import org.apache.cloudstack.backup.BackupManager;
|
||||
import org.apache.cloudstack.backup.BackupVO;
|
||||
|
|
@ -245,6 +246,9 @@ public class UserVmManagerImplTest {
|
|||
@Mock
|
||||
private UpdateVMCmd updateVmCommand;
|
||||
|
||||
@Mock
|
||||
private UpdateVmNicCmd updateVmNicCmd;
|
||||
|
||||
@Mock
|
||||
private AccountManager accountManager;
|
||||
|
||||
|
|
@ -272,6 +276,9 @@ public class UserVmManagerImplTest {
|
|||
@Mock
|
||||
private UserVO callerUser;
|
||||
|
||||
@Mock
|
||||
private NicVO nicMock;
|
||||
|
||||
@Mock
|
||||
private VMTemplateDao templateDao;
|
||||
|
||||
|
|
@ -455,6 +462,8 @@ public class UserVmManagerImplTest {
|
|||
private static final long vmId = 1l;
|
||||
private static final long zoneId = 2L;
|
||||
private static final long accountId = 3L;
|
||||
private static final long nicId = 4L;
|
||||
private static final long networkId = 5L;
|
||||
private static final long serviceOfferingId = 10L;
|
||||
private static final long templateId = 11L;
|
||||
private static final long volumeId = 1L;
|
||||
|
|
@ -4254,6 +4263,61 @@ public class UserVmManagerImplTest {
|
|||
verify(userVmManagerImpl, never()).addExtraConfig(any(UserVmVO.class), anyString());
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void updateVirtualMachineNicTestInvalidNicThrowInvalidParameterValueException() {
|
||||
Long invalidId = -1L;
|
||||
Mockito.doReturn(invalidId).when(updateVmNicCmd).getNicId();
|
||||
|
||||
userVmManagerImpl.updateVirtualMachineNic(updateVmNicCmd);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void updateVirtualMachineNicTestInvalidNicUserVmThrowInvalidParameterValueException() {
|
||||
Mockito.doReturn(nicId).when(updateVmNicCmd).getNicId();
|
||||
Mockito.doReturn(nicMock).when(nicDao).findById(nicId);
|
||||
|
||||
userVmManagerImpl.updateVirtualMachineNic(updateVmNicCmd);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void updateVirtualMachineNicTestInvalidNicNetworkThrowInvalidParameterValueException() {
|
||||
Mockito.doReturn(nicId).when(updateVmNicCmd).getNicId();
|
||||
Mockito.doReturn(true).when(updateVmNicCmd).isEnabled();
|
||||
Mockito.doReturn(nicMock).when(nicDao).findById(nicId);
|
||||
Mockito.doReturn(vmId).when(nicMock).getInstanceId();
|
||||
Mockito.doReturn(userVmVoMock).when(userVmDao).findById(vmId);
|
||||
|
||||
userVmManagerImpl.updateVirtualMachineNic(updateVmNicCmd);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void updateVirtualMachineNicTestInvalidNicNetworkThrowCloudRuntimeException() {
|
||||
Mockito.doReturn(nicId).when(updateVmNicCmd).getNicId();
|
||||
Mockito.doReturn(true).when(updateVmNicCmd).isEnabled();
|
||||
Mockito.doReturn(nicMock).when(nicDao).findById(nicId);
|
||||
Mockito.doReturn(vmId).when(nicMock).getInstanceId();
|
||||
Mockito.doReturn(userVmVoMock).when(userVmDao).findById(vmId);
|
||||
|
||||
userVmManagerImpl.updateVirtualMachineNic(updateVmNicCmd);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateVirtualMachineNicTestValidInputReturnNicUserVm() throws ResourceUnavailableException {
|
||||
Mockito.doReturn(nicId).when(updateVmNicCmd).getNicId();
|
||||
Mockito.doReturn(true).when(updateVmNicCmd).isEnabled();
|
||||
Mockito.doReturn(nicMock).when(nicDao).findById(nicId);
|
||||
Mockito.doReturn(vmId).when(nicMock).getInstanceId();
|
||||
Mockito.doReturn(userVmVoMock).when(userVmDao).findById(vmId);
|
||||
Mockito.doReturn(Hypervisor.HypervisorType.KVM).when(userVmVoMock).getHypervisorType();
|
||||
Mockito.doReturn(networkId).when(nicMock).getNetworkId();
|
||||
Mockito.doReturn(networkMock).when(_networkDao).findById(networkId);
|
||||
Mockito.doReturn(true).when(virtualMachineManager).updateVmNic(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
||||
UserVm result = userVmManagerImpl.updateVirtualMachineNic(updateVmNicCmd);
|
||||
|
||||
Assert.assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransitionExpungingToErrorVmInExpungingState() throws Exception {
|
||||
UserVmVO vm = mock(UserVmVO.class);
|
||||
|
|
|
|||
|
|
@ -542,7 +542,7 @@ class TestRouters(cloudstackTestCase):
|
|||
|
||||
|
||||
# Validate the following
|
||||
# 1. PreReq: have rounters that are owned by other account
|
||||
# 1. PreReq: have routers that are owned by other account
|
||||
# 2. Create domain and create accounts in that domain
|
||||
# 3. Create one VM for each account
|
||||
# 4. Using Admin , run listRouters. It should return all the routers
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ known_categories = {
|
|||
'removeIpFromNic': 'Nic',
|
||||
'updateVmNicIp': 'Nic',
|
||||
'listNics':'Nic',
|
||||
'updateVmNic': 'Nic',
|
||||
'AffinityGroup': 'Affinity Group',
|
||||
'ImageStore': 'Image Store',
|
||||
'addImageStore': 'Image Store',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@ What this tool is capable to do is
|
|||
|
||||
The usage is as follows
|
||||
1. First run fresh_install_data_collection.sh file to generate data from fresh install setup .
|
||||
This will be used for comparing between fresh install and upgrade setup.
|
||||
This will be used for comparing between fresh install and upgrade setup.
|
||||
This is a onetime activity and need to be repeated only when there is some DB changes for that release .
|
||||
Output of this script will come in a base_data folder
|
||||
Output of this script will come in a base_data folder
|
||||
|
||||
2. Just before upgrade you need to run before_upgrade_data_collection.sh file to collect required data needed to compare before upgrade and after upgrade setup data
|
||||
The output of this script will come in folder data_before_upgrade
|
||||
|
||||
3. After upgrade run cloud_schema_comparision.sh to compare cloud database all tables schema between fresh and upgraded setup.
|
||||
3. After upgrade run cloud_schema_comparision.sh to compare cloud database all tables schema between fresh and upgraded setup.
|
||||
NOTE: this script requires step 1 output in current working directory
|
||||
|
||||
4. After upgrade run usage_schema_comparision.sh to compare cloud usage all tables schema between fresh and upgraded setup
|
||||
|
|
@ -41,4 +41,4 @@ The usage is as follows
|
|||
• Database user
|
||||
• Database user password
|
||||
|
||||
8. Result will be shown in the form of files .
|
||||
8. Result will be shown in the form of files .
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ The following tree shows the basic UI codebase filesystem:
|
|||
|
||||
```bash
|
||||
src
|
||||
├── assests # sprites, icons, images
|
||||
├── assets # sprites, icons, images
|
||||
├── components # Shared vue files used to render various generic / widely used components
|
||||
├── config # Contains the layout details of the various routes / sections available in the UI
|
||||
├── locales # Custom translation keys for the various supported languages
|
||||
|
|
|
|||
|
|
@ -993,6 +993,7 @@
|
|||
"label.edit.acl": "Edit ACL",
|
||||
"label.edit.acl.rule": "Edit ACL rule",
|
||||
"label.edit.autoscale.vmprofile": "Edit AutoScale Instance Profile",
|
||||
"label.edit.nic": "Edit NIC",
|
||||
"label.edit.project.details": "Edit project details",
|
||||
"label.edit.project.role": "Edit project role",
|
||||
"label.edit.role": "Edit Role",
|
||||
|
|
@ -3735,6 +3736,7 @@
|
|||
"message.network.selection": "Choose one or more Networks to attach the Instance to.",
|
||||
"message.network.selection.new.network": "A new Network can also be created here.",
|
||||
"message.network.updateip": "Please confirm that you would like to change the IP address for this NIC on the Instance.",
|
||||
"message.network.update.nic": "Please confirm that you would like to update this NIC.",
|
||||
"message.network.usage.info.data.points": "Each data point represents the difference in data traffic since the last data point.",
|
||||
"message.network.usage.info.sum.of.vnics": "The Network usage shown is made up of the sum of data traffic from all the vNICs in the Instance.",
|
||||
"message.nfs.mount.options.description": "Comma separated list of NFS mount options for KVM hosts. Supported options : vers=[3,4.0,4.1,4.2], nconnect=[1...16]",
|
||||
|
|
@ -4018,13 +4020,14 @@
|
|||
"message.success.delete.vgpu.profile": "Successfully deleted vGPU profile",
|
||||
"message.success.update.custom.action": "Successfully updated Custom Action",
|
||||
"message.success.update.extension": "Successfully updated Extension",
|
||||
"message.success.update.sharedfs": "Successfully updated Shared FileSystem",
|
||||
"message.success.update.ipaddress": "Successfully updated IP address",
|
||||
"message.success.update.iprange": "Successfully updated IP range",
|
||||
"message.success.update.ipv4.subnet": "Successfully updated IPv4 subnet",
|
||||
"message.success.update.iso": "Successfully updated ISO",
|
||||
"message.success.update.kubeversion": "Successfully updated Kubernetes supported version",
|
||||
"message.success.update.network": "Successfully updated Network",
|
||||
"message.success.update.nic": "Successfully updated NIC",
|
||||
"message.success.update.sharedfs": "Successfully updated Shared FileSystem",
|
||||
"message.success.update.template": "Successfully updated Template",
|
||||
"message.success.update.user": "Successfully updated User",
|
||||
"message.success.update.vpn.customer.gateway": "Successfully updated VPN Customer Gateway",
|
||||
|
|
@ -4074,6 +4077,7 @@
|
|||
"message.two.fa.setup.page": "Two factor authentication (2FA) is an extra layer of security to your account.<br> Once setup is done, on every login you will be prompted to enter the 2FA code.<br>",
|
||||
"message.two.fa.view.setup.key": "Click here to view the setup key",
|
||||
"message.two.fa.view.static.pin": "Click here to view the static PIN",
|
||||
"message.update.nic.processing": "Updating NIC...",
|
||||
"message.update.ipaddress.processing": "Updating IP Address...",
|
||||
"message.update.resource.count": "Please confirm that you want to update resource counts for this Account.",
|
||||
"message.update.resource.count.domain": "Please confirm that you want to update resource counts for this domain.",
|
||||
|
|
|
|||
|
|
@ -623,6 +623,7 @@
|
|||
"label.edit": "Editar",
|
||||
"label.edit.acl": "Editar lista ACL",
|
||||
"label.edit.acl.rule": "Editar regra ACL",
|
||||
"label.edit.nic": "Editar NIC",
|
||||
"label.edit.project.details": "Editar detalhes do projeto",
|
||||
"label.edit.project.role": "Editar fun\u00e7\u00e3o do projeto",
|
||||
"label.edit.role": "Editar fun\u00e7\u00e3o",
|
||||
|
|
@ -2298,6 +2299,7 @@
|
|||
"message.network.removenic": "Por favor, confirme que deseja remover esta interface de rede, esta a\u00e7\u00e3o tamb\u00e9m ir\u00e1 remover a rede associada \u00e0 VM.",
|
||||
"message.network.secondaryip": "Por favor, confirme que voc\u00ea gostaria de adquirir um novo IP secund\u00e1rio para este NIC. \n NOTA: Voc\u00ea precisa configurar manualmente o IP secund\u00e1rio rec\u00e9m-adquirido dentro da m\u00e1quina virtual.",
|
||||
"message.network.updateip": "Por favor, confirme que voc\u00ea gostaria de mudar o endere\u00e7o IP da NIC em VM.",
|
||||
"message.network.update.nic": "Por favor, confirme que voc\u00ea gostaria de atualizar esta NIC.",
|
||||
"message.network.usage.info.data.points": "Cada ponto no gr\u00e1fico representa a diferen\u00e7a de dados trafegados desde a \u00faltima coleta de estat\u00edstica realizada (o ponto anterior)",
|
||||
"message.network.usage.info.sum.of.vnics": "O uso de rede apresentado \u00e9 composto pela soma de dados trafegados por todas as vNICs da VM",
|
||||
"message.no.data.to.show.for.period": "Nenhum dado para mostrar no per\u00edodo selecionado.",
|
||||
|
|
@ -2455,6 +2457,7 @@
|
|||
"message.success.update.iprange": "Intervalo de IP atualizado com sucesso",
|
||||
"message.success.update.kubeversion": "Vers\u00e3o compat\u00edvel com Kubernetes atualizada com sucesso",
|
||||
"message.success.update.network": "Rede atualizada com sucesso",
|
||||
"message.success.update.nic": "NIC atualizada com sucesso",
|
||||
"message.success.update.user": "Usu\u00e1rio atualizado com sucesso",
|
||||
"message.success.upgrade.kubernetes": "Cluster do Kubernetes atualizado com sucesso",
|
||||
"message.success.upload": "Carregado com sucesso",
|
||||
|
|
@ -2471,6 +2474,7 @@
|
|||
"message.template.iso": "Selecione o template ou ISO para continuar",
|
||||
"message.tooltip.reserved.system.netmask": "O prefixo de rede que define a subrede deste pod. utilize a nota\u00e7\u00e3o CIDR.",
|
||||
"message.traffic.type.to.basic.zone": "Tipo de tr\u00e1fego para a zona b\u00e1sica",
|
||||
"message.update.nic.processing": "Atualizando NIC...",
|
||||
"message.update.ipaddress.processing": "Atualizando endere\u00e7o IP...",
|
||||
"message.update.resource.count": "Por favor confirme que voc\u00ea quer atualizar a contagem de recursos para esta conta.",
|
||||
"message.update.resource.count.domain": "Por favor, confirme que voc\u00ea deseja atualizar as contagens de recursos para este dom\u00ednio.",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
|
@ -66,32 +66,62 @@
|
|||
</a-timeline>
|
||||
</a-card>
|
||||
<a-card :title="$t('label.kubernetes.dashboard')">
|
||||
<p><strong>Note:</strong> CloudStack Kubernetes clusters use <strong>Headlamp</strong> dashboard (deployed in <code>kube-system</code> namespace). For backward compatibility with older clusters using Kubernetes Dashboard, please check your cluster configuration.</p>
|
||||
<a-timeline>
|
||||
<a-timeline-item>
|
||||
<p>
|
||||
{{ $t('label.run.proxy.locally') }}<br><br>
|
||||
<code><b>kubectl --kubeconfig /custom/path/kube.conf proxy</b></code>
|
||||
<strong>Access Headlamp Dashboard (new clusters)</strong><br><br>
|
||||
<strong>Step 1:</strong> Run port-forward command:<br>
|
||||
<code><b>kubectl --kubeconfig /custom/path/kube.conf port-forward -n kube-system service/headlamp 8080:80</b></code><br><br>
|
||||
<strong>Step 2:</strong> Open in your browser:<br>
|
||||
<a href="http://localhost:8080"><code>http://localhost:8080</code></a>
|
||||
</p>
|
||||
</a-timeline-item>
|
||||
<a-timeline-item>
|
||||
<p>
|
||||
{{ $t('label.open.url') }}<br><br>
|
||||
<strong>Access Kubernetes Dashboard (legacy clusters)</strong><br><br>
|
||||
<strong>Step 1:</strong> {{ $t('label.run.proxy.locally') }}<br>
|
||||
<code><b>kubectl --kubeconfig /custom/path/kube.conf proxy</b></code><br><br>
|
||||
<strong>Step 2:</strong> {{ $t('label.open.url') }}<br>
|
||||
<a href="http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/"><code>http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/</code></a>
|
||||
</p>
|
||||
</a-timeline-item>
|
||||
<a-timeline-item>
|
||||
<p>
|
||||
<strong>Create Access Token for Headlamp (new clusters)</strong>
|
||||
</p>
|
||||
<p v-html="$t('label.kubernetes.dashboard.create.token')"></p>
|
||||
<p v-html="$t('label.kubernetes.dashboard.create.token.desc')"></p>
|
||||
<a-textarea :value="'kubectl --kubeconfig /custom/path/kube.conf apply -f - <<EOF\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: kubernetes-dashboard-admin-user\n namespace: kubernetes-dashboard\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n name: kubernetes-dashboard-admin-user\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: ClusterRole\n name: cluster-admin\nsubjects:\n- kind: ServiceAccount\n name: kubernetes-dashboard-admin-user\n namespace: kubernetes-dashboard\n---\napiVersion: v1\nkind: Secret\ntype: kubernetes.io/service-account-token\nmetadata:\n name: kubernetes-dashboard-token\n namespace: kubernetes-dashboard\n annotations:\n kubernetes.io/service-account.name: kubernetes-dashboard-admin-user\nEOF'" :rows="10" readonly />
|
||||
<a-textarea :value="'kubectl --kubeconfig /custom/path/kube.conf apply -f - <<EOF\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: headlamp-admin\n namespace: kube-system\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n name: headlamp-admin\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: ClusterRole\n name: cluster-admin\nsubjects:\n- kind: ServiceAccount\n name: headlamp-admin\n namespace: kube-system\n---\napiVersion: v1\nkind: Secret\ntype: kubernetes.io/service-account-token\nmetadata:\n name: headlamp-admin-token\n namespace: kube-system\n annotations:\n kubernetes.io/service-account.name: headlamp-admin\nEOF'" :rows="12" readonly />
|
||||
<br><br>
|
||||
<p>{{ $t('label.token.for.dashboard.login') }}:</p>
|
||||
<code><b>kubectl --kubeconfig /custom/path/kube.conf describe secret headlamp-admin-token -n kube-system</b></code>
|
||||
</a-timeline-item>
|
||||
<a-timeline-item>
|
||||
<p>
|
||||
{{ $t('label.token.for.dashboard.login') }}<br><br>
|
||||
<code><b>kubectl --kubeconfig /custom/path/kube.conf describe secret $(kubectl --kubeconfig /custom/path/kube.conf get secrets -n kubernetes-dashboard | grep kubernetes-dashboard-token | awk '{print $1}') -n kubernetes-dashboard</b></code>
|
||||
<strong>Create Access Token for Kubernetes Dashboard (legacy clusters)</strong>
|
||||
</p>
|
||||
<p v-html="$t('label.kubernetes.dashboard.create.token.desc')"></p>
|
||||
<a-textarea :value="'kubectl --kubeconfig /custom/path/kube.conf apply -f - <<EOF\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: kubernetes-dashboard-admin-user\n namespace: kubernetes-dashboard\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n name: kubernetes-dashboard-admin-user\nroleRef:\n apiGroup: rbac.authorization.k8s.io\n kind: ClusterRole\n name: cluster-admin\nsubjects:\n- kind: ServiceAccount\n name: kubernetes-dashboard-admin-user\n namespace: kubernetes-dashboard\n---\napiVersion: v1\nkind: Secret\ntype: kubernetes.io/service-account-token\nmetadata:\n name: kubernetes-dashboard-token\n namespace: kubernetes-dashboard\n annotations:\n kubernetes.io/service-account.name: kubernetes-dashboard-admin-user\nEOF'" :rows="12" readonly />
|
||||
<br><br>
|
||||
<p>{{ $t('label.token.for.dashboard.login') }}:</p>
|
||||
<code><b>kubectl --kubeconfig /custom/path/kube.conf describe secret kubernetes-dashboard-token -n kubernetes-dashboard</b></code>
|
||||
</a-timeline-item>
|
||||
<a-timeline-item>
|
||||
<p>
|
||||
<strong>Important Notes:</strong><br>
|
||||
• <strong>Port-forwarding is recommended for Headlamp</strong> - simpler and more reliable than kubectl proxy<br>
|
||||
• Token is only needed if accessing Headlamp via NodePort or LoadBalancer with external access<br>
|
||||
• For Kubernetes 1.24+, service account tokens are no longer auto-generated - use the Secret resource shown above or <code>kubectl create token</code> command<br>
|
||||
• <strong>Cluster-admin role grants full control</strong> - use with caution and only for trusted administrators<br>
|
||||
• Keep the port-forward command running while using the dashboard (press Ctrl+C to stop)
|
||||
</p>
|
||||
</a-timeline-item>
|
||||
</a-timeline>
|
||||
<p>{{ $t('label.more.access.dashboard.ui') }}, <a href="https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#accessing-the-dashboard-ui">https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#accessing-the-dashboard-ui</a></p>
|
||||
<p>{{ $t('label.more.access.dashboard.ui') }}:
|
||||
<a href="https://headlamp.dev/docs/latest/">Headlamp Documentation</a> |
|
||||
<a href="https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#accessing-the-dashboard-ui">Kubernetes Dashboard (Legacy)</a>
|
||||
</p>
|
||||
</a-card>
|
||||
<a-card :title="$t('label.access.kubernetes.nodes')">
|
||||
<p v-html="$t('label.kubernetes.access.details')"></p>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,13 @@
|
|||
icon="environment-outlined"
|
||||
:disabled="(!('addIpToNic' in $store.getters.apis) && !('addIpToNic' in $store.getters.apis))"
|
||||
@onClick="onAcquireSecondaryIPAddress(record)" />
|
||||
<tooltip-button
|
||||
v-if="resource.hypervisor === 'KVM'"
|
||||
tooltipPlacement="bottom"
|
||||
:tooltip="$t('label.edit.nic')"
|
||||
icon="edit-outlined"
|
||||
:disabled="(!('updateVmNic' in $store.getters.apis))"
|
||||
@onClick="onUpdateNic(record)" />
|
||||
<a-popconfirm
|
||||
:title="$t('message.network.removenic')"
|
||||
@confirm="removeNIC(record.nic)"
|
||||
|
|
@ -195,7 +202,7 @@
|
|||
<a-divider />
|
||||
<div v-ctrl-enter="submitSecondaryIP">
|
||||
<div class="modal-form">
|
||||
<p class="modal-form__label">{{ $t('label.publicip') }}:</p>
|
||||
<p class="modal-form__label--no-margin">{{ $t('label.publicip') }}:</p>
|
||||
<a-select
|
||||
v-if="editNicResource.type==='Shared'"
|
||||
v-model:value="newSecondaryIp"
|
||||
|
|
@ -243,6 +250,31 @@
|
|||
</a-list-item>
|
||||
</a-list>
|
||||
</a-modal>
|
||||
|
||||
<a-modal
|
||||
:visible="showUpdateNicModal"
|
||||
:title="$t('label.edit.nic')"
|
||||
:maskClosable="false"
|
||||
:closable="true"
|
||||
:footer="null"
|
||||
@cancel="closeModals"
|
||||
>
|
||||
{{ $t('message.network.update.nic') }}
|
||||
|
||||
<a-form
|
||||
@finish="submitUpdateNic"
|
||||
v-ctrl-enter="submitUpdateNic">
|
||||
<a-form-item name="linkstate" ref="linkstate">
|
||||
<p class="modal-form__label">{{ $t('state.enabled') }}:</p>
|
||||
<a-switch v-model:checked="editNicStateValue" @change="val => { editNicStateValue = val }" />
|
||||
</a-form-item>
|
||||
|
||||
<div :span="24" class="action-button">
|
||||
<a-button @click="closeModals">{{ $t('label.cancel') }}</a-button>
|
||||
<a-button type="primary" ref="submit" @click="submitUpdateNic">{{ $t('label.ok') }}</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
|
|
@ -279,6 +311,7 @@ export default {
|
|||
showAddNetworkModal: false,
|
||||
showUpdateIpModal: false,
|
||||
showSecondaryIpModal: false,
|
||||
showUpdateNicModal: false,
|
||||
addNetworkData: {
|
||||
allNetworks: [],
|
||||
network: '',
|
||||
|
|
@ -289,6 +322,7 @@ export default {
|
|||
editIpAddressNic: '',
|
||||
editIpAddressValue: '',
|
||||
editNetworkId: '',
|
||||
editNicStateValue: false,
|
||||
secondaryIPs: [],
|
||||
selectedNicId: '',
|
||||
newSecondaryIp: '',
|
||||
|
|
@ -360,6 +394,7 @@ export default {
|
|||
this.showAddNetworkModal = false
|
||||
this.showUpdateIpModal = false
|
||||
this.showSecondaryIpModal = false
|
||||
this.showUpdateNicModal = false
|
||||
this.addNetworkData.network = ''
|
||||
this.addNetworkData.ipaddress = ''
|
||||
this.addNetworkData.macaddress = ''
|
||||
|
|
@ -386,6 +421,11 @@ export default {
|
|||
this.editNetworkId = record.nic.networkid
|
||||
this.fetchSecondaryIPs(record.nic.id)
|
||||
},
|
||||
onUpdateNic (record) {
|
||||
this.editNicResource = record.nic
|
||||
this.editNicStateValue = record.nic.enabled
|
||||
this.showUpdateNicModal = true
|
||||
},
|
||||
submitAddNetwork () {
|
||||
if (this.loadingNic) return
|
||||
const params = {}
|
||||
|
|
@ -609,12 +649,46 @@ export default {
|
|||
this.loadingNic = false
|
||||
this.fetchSecondaryIPs(this.selectedNicId)
|
||||
})
|
||||
},
|
||||
submitUpdateNic () {
|
||||
if (this.loadingNic) return
|
||||
this.loadingNic = true
|
||||
this.showUpdateNicModal = false
|
||||
const params = {
|
||||
nicId: this.editNicResource.id,
|
||||
enabled: this.editNicStateValue
|
||||
}
|
||||
postAPI('updateVmNic', params).then(response => {
|
||||
this.$pollJob({
|
||||
jobId: response.updatevmnicresponse.jobid,
|
||||
successMessage: this.$t('message.success.update.nic'),
|
||||
successMethod: () => {
|
||||
this.loadingNic = false
|
||||
this.closeModals()
|
||||
},
|
||||
errorMessage: this.$t('label.error'),
|
||||
errorMethod: () => {
|
||||
this.loadingNic = false
|
||||
this.closeModals()
|
||||
},
|
||||
loadingMessage: this.$t('message.update.nic.processing'),
|
||||
catchMessage: this.$t('error.fetching.async.job.result'),
|
||||
catchMethod: () => {
|
||||
this.loadingNic = false
|
||||
this.closeModals()
|
||||
this.$emit('refresh')
|
||||
}
|
||||
})
|
||||
}).catch(error => {
|
||||
this.$notifyError(error)
|
||||
this.loadingNic = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
.modal-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -626,6 +700,7 @@ export default {
|
|||
|
||||
&--no-margin {
|
||||
margin-top: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,9 @@
|
|||
{{ $t('label.default') }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'enabled'">
|
||||
<status :text="text ? 'enabled' : 'disabled'"/> {{ text ? 'Enabled' : 'Disabled' }}
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
|
|
@ -78,6 +81,7 @@
|
|||
<script>
|
||||
import { getAPI } from '@/api'
|
||||
import ResourceIcon from '@/components/view/ResourceIcon'
|
||||
import Status from '@/components/widgets/Status'
|
||||
|
||||
export default {
|
||||
name: 'NicsTable',
|
||||
|
|
@ -92,7 +96,8 @@ export default {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
ResourceIcon
|
||||
ResourceIcon,
|
||||
Status
|
||||
},
|
||||
inject: ['parentFetchData'],
|
||||
data () {
|
||||
|
|
@ -123,6 +128,11 @@ export default {
|
|||
{
|
||||
title: this.$t('label.gateway'),
|
||||
dataIndex: 'gateway'
|
||||
},
|
||||
{
|
||||
key: 'enabled',
|
||||
title: this.$t('label.state'),
|
||||
dataIndex: 'enabled'
|
||||
}
|
||||
],
|
||||
networkicon: {},
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ public class Link {
|
|||
if (caService != null) {
|
||||
return caService.createSSLEngine(sslContext, clientAddress);
|
||||
}
|
||||
LOGGER.error("CA service is not configured, by-passing CA manager to create SSL engine");
|
||||
LOGGER.error("CA service is not configured, bypassing CA manager to create SSL engine");
|
||||
char[] passphrase = KeyStoreUtils.DEFAULT_KS_PASSPHRASE;
|
||||
final KeyStore ks = loadKeyStore(NioConnection.class.getResourceAsStream("/cloud.keystore"), passphrase);
|
||||
final KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
||||
|
|
|
|||
|
|
@ -753,7 +753,7 @@ public class VmwareHelper {
|
|||
|
||||
recommendedController = guestOsDescriptor.getRecommendedDiskController();
|
||||
|
||||
// By-pass auto detected PVSCSI controller to use LsiLogic Parallel instead
|
||||
// Bypass auto detected PVSCSI controller to use LsiLogic Parallel instead
|
||||
if (DiskControllerType.getType(recommendedController) == DiskControllerType.pvscsi) {
|
||||
recommendedController = DiskControllerType.lsilogic.toString();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue