Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions api/src/main/java/com/cloud/agent/api/to/NicTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class NicTO extends NetworkTO {
boolean dpdkEnabled;
Integer mtu;
Long networkId;
boolean enabled;

String networkSegmentName;

Expand Down Expand Up @@ -154,4 +155,12 @@ public String getNetworkSegmentName() {
public void setNetworkSegmentName(String networkSegmentName) {
this.networkSegmentName = networkSegmentName;
}

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
2 changes: 2 additions & 0 deletions api/src/main/java/com/cloud/vm/Nic.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,6 @@ public enum ReservationStrategy {
String getIPv6Address();

Integer getMtu();

boolean isEnabled();
}
10 changes: 10 additions & 0 deletions api/src/main/java/com/cloud/vm/NicProfile.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class NicProfile implements InternalIdentity, Serializable {
boolean defaultNic;
Integer networkRate;
boolean isSecurityGroupEnabled;
boolean enabled;

Integer orderIndex;

Expand Down Expand Up @@ -87,6 +88,7 @@ public NicProfile(Nic nic, Network network, URI broadcastUri, URI isolationUri,
broadcastType = network.getBroadcastDomainType();
trafficType = network.getTrafficType();
format = nic.getAddressFormat();
enabled = nic.isEnabled();

iPv4Address = nic.getIPv4Address();
iPv4Netmask = nic.getIPv4Netmask();
Expand Down Expand Up @@ -414,6 +416,14 @@ public void setIpv4AllocationRaceCheck(boolean ipv4AllocationRaceCheck) {
this.ipv4AllocationRaceCheck = ipv4AllocationRaceCheck;
}

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

//
// OTHER METHODS
//
Expand Down
3 changes: 3 additions & 0 deletions api/src/main/java/com/cloud/vm/UserVmService.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
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;
Expand Down Expand Up @@ -152,6 +153,8 @@ void startVirtualMachineForHA(VirtualMachine vm, Map<VirtualMachineProfile.Param
*/
UserVm updateNicIpForVirtualMachine(UpdateVmNicIpCmd cmd);

UserVm updateVirtualMachineNic(UpdateVmNicCmd cmd);

UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationException;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -416,4 +420,12 @@ public void setPublicIpId(String publicIpId) {
public void setPublicIp(String publicIp) {
this.publicIp = publicIp;
}

public Boolean getEnabled() {
return isEnabled;
}

public void setEnabled(Boolean enabled) {
isEnabled = enabled;
}
}
27 changes: 27 additions & 0 deletions core/src/main/java/com/cloud/agent/api/UpdateVmNicAnswer.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
51 changes: 51 additions & 0 deletions core/src/main/java/com/cloud/agent/api/UpdateVmNicCommand.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile request

Boolean updateDefaultNicForVM(VirtualMachine vm, Nic nic, Nic defaultNic);

boolean updateVmNic(VirtualMachine vm, Nic nic, Boolean enabled) throws ResourceUnavailableException;

/**
* @param vm
* @param network
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@
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;
Expand Down Expand Up @@ -6270,6 +6272,80 @@ private Pair<JobInfo.Status, String> orchestrateUpdateDefaultNic(final VmWorkUpd
_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;
Expand Down
Loading
Loading